Project

General

Profile

Download (4.32 KB) Statistics
| Branch: | Tag: | Revision:
#!/usr/bin/env python3

import argparse
import json

import semver

# We need a blacklist of packages that are devDependencies but not needed to build
NPM_BLACKLIST = [
'axios-mock-adapter',
'babel-eslint',
'babel-jest',
'coveralls',
'jest',
'jest-cli',
'prettier',
'react-addons-test-utils',
'react-test-renderer',
'redux-mock-store',
'webpack-dev-server',
]

NPM_BLACKLIST_PREFIXES = [
'@storybook/',
'enzyme',
'eslint',
'stylelint',
]

def is_blacklisted(package):
return (package in NPM_BLACKLIST
or any(package.startswith(prefix) for prefix in NPM_BLACKLIST_PREFIXES))


def get_requirement(version):
if not version:
raise ValueError('Empty version received')

if version[0].isdigit():
return ['= {}'.format(version)]

if version.startswith('^') or version.startswith('~'):
modifier = version[0]
parsed = semver.parse_version_info(version[1:])

min_version = '{}.{}.{}'.format(parsed.major, parsed.minor, parsed.patch)
if modifier == '^':
max_version = semver.bump_major(min_version)
elif modifier == '~':
max_version = semver.bump_minor(min_version)

return ['>= {}'.format(min_version), '< {}'.format(max_version)]

raise ValueError('Unable to handle version {}'.format(version))


def get_requirements(dependencies, fmt):
for package, version in sorted(dependencies.items()):
for requirement in get_requirement(version):
if is_blacklisted(package):
yield '#' + fmt.format(package, requirement)
else:
yield fmt.format(package, requirement)


def get_npm_sections(packages):
for section in ('devDependencies', 'dependencies'):
for requires in ('BuildRequires', 'Requires'):
trigger = '{} {}\n'.format(section, requires)
requirements = list(get_requirements(packages[section], requires + ': npm({}) {}\n'))
yield trigger, requirements


def get_specfile_sections(prefix, fp):
trigger = prefix.replace('start', 'end', 1)
key = None
section = []

for line in fp:
if line.startswith(prefix):
if key:
raise Exception('Unclosed section {}'.format(key))

key = strip_prefix(line, prefix)
section = []
elif key:
if line.startswith(trigger):
yield (key, section)
key = None
else:
section.append(line.rstrip() + '\n')


def get_new_content(prefix, current_content, requires):
key = None

for line in current_content:
if key:
if line == key:
yield line
key = None
else:
yield line

if line.startswith(prefix):
key = strip_prefix(line, prefix)
try:
for require in requires[key]:
yield require
except KeyError:
raise SystemExit('Unrecognized section found: ' + line)
key = prefix.replace('start', 'end') + key


def strip_prefix(line, prefix):
return line[len(prefix):]


def main():
parser = argparse.ArgumentParser(description='Update the dependencies within sections')
parser.add_argument('requirementstype', help='the type of conversion',
choices=('npm', 'specfile', 'direct'))
parser.add_argument('requirementsfile', help='Path to the requirements file',
type=argparse.FileType('r'))
parser.add_argument('specfile', help='path to the specfile', type=argparse.FileType('r'))
args = parser.parse_args()

if args.requirementstype == 'npm':
prefix = '# start package.json '
requires = dict(get_npm_sections(json.load(args.requirementsfile)))
elif args.requirementstype == 'specfile':
prefix = '# start specfile '
requires = dict(get_specfile_sections(prefix, args.requirementsfile))
else:
prefix = '# start '
requires = json.load(args.requirementsfile)

current_content = args.specfile.readlines()
args.specfile.close()

new_content = list(get_new_content(prefix, current_content, requires))

with open(args.specfile.name, 'w') as fp:
fp.writelines(new_content)


if __name__ == '__main__':
main()
(14-14/14)