changes based on discussions w maintainer

This commit is contained in:
Siyang 2021-03-29 21:35:34 +08:00
parent 4eae4794a0
commit 69a884a4c4
2 changed files with 48 additions and 49 deletions

View File

@ -31,8 +31,11 @@ Options:
imports. imports.
--clean <file> Clean up requirements.txt by removing modules --clean <file> Clean up requirements.txt by removing modules
that are not imported in project. that are not imported in project.
--dynamic <scheme> Enables dynamic version updates by 'minor', --mode <scheme> Enables dynamic versioning with <compat>,
'micro' or 'all' schemes. <gt> or <non-pin> schemes.
<compat> | e.g. Flask~=1.1.2
<gt> | e.g. Flask>=1.1.2
<no-pin> | e.g. Flask
""" """
from __future__ import print_function, absolute_import from __future__ import print_function, absolute_import
from contextlib import contextmanager from contextlib import contextmanager
@ -162,21 +165,21 @@ def filter_line(line):
return len(line) > 0 and line[0] != "#" return len(line) > 0 and line[0] != "#"
def generate_requirements_file(path, imports): def generate_requirements_file(path, imports, symbol):
with _open(path, "w") as out_file: with _open(path, "w") as out_file:
logging.debug('Writing {num} requirements: {imports} to {file}'.format( logging.debug('Writing {num} requirements: {imports} to {file}'.format(
num=len(imports), num=len(imports),
file=path, file=path,
imports=", ".join([x['name'] for x in imports]) imports=", ".join([x['name'] for x in imports])
)) ))
fmt = '{name}=={version}' fmt = '{name}' + symbol + '{version}'
out_file.write('\n'.join( out_file.write('\n'.join(
fmt.format(**item) if item['version'] else '{name}'.format(**item) fmt.format(**item) if item['version'] else '{name}'.format(**item)
for item in imports) + '\n') for item in imports) + '\n')
def output_requirements(imports): def output_requirements(imports, symbol):
generate_requirements_file('-', imports) generate_requirements_file('-', imports, symbol)
def get_imports_info( def get_imports_info(
@ -394,25 +397,17 @@ def clean(file_, imports):
def dynamic_versioning(scheme, imports): def dynamic_versioning(scheme, imports):
"""Enables dynamic versioning by minor, micro or all scheme.""" """Enables dynamic versioning with <compat>, <gt> or <non-pin> schemes."""
if scheme == "all": if scheme == "no-pin":
imports = [{"name": item["name"], "version": ""} for item in imports] imports = [{"name": item["name"], "version": ""} for item in imports]
symbol = ""
elif scheme == "gt":
symbol = ">="
elif scheme == "compat":
symbol = "~="
else: else:
for item in imports: symbol = "=="
version = item["version"] return imports, symbol
arr = version.split(".")
length = len(arr)
if length != 1:
if scheme == "minor":
arr = arr[0]
elif scheme == "micro" and length >= 2:
arr = arr[:2]
arr = ".".join(arr)
arr = arr + ".*"
item["version"] = arr
return imports
def init(args): def init(args):
@ -473,19 +468,21 @@ def init(args):
"use --force to overwrite it") "use --force to overwrite it")
return return
if args["--dynamic"]: if args["--mode"]:
scheme = args.get("--dynamic") scheme = args.get("--mode")
if scheme in ["minor", "micro", "all"]: if scheme in ["compat", "gt", "no-pin"]:
imports = dynamic_versioning(scheme, imports) imports, symbol = dynamic_versioning(scheme, imports)
else: else:
raise ValueError("Invalid argument for dynamic scheme, " raise ValueError("Invalid argument for mode flag, "
"use 'minor', 'micro' or 'all' instead") "use 'compat', 'gt' or 'no-pin' instead")
else:
symbol = "=="
if args["--print"]: if args["--print"]:
output_requirements(imports) output_requirements(imports, symbol)
logging.info("Successfully output requirements") logging.info("Successfully output requirements")
else: else:
generate_requirements_file(path, imports) generate_requirements_file(path, imports, symbol)
logging.info("Successfully saved requirements file in " + path) logging.info("Successfully saved requirements file in " + path)

View File

@ -93,7 +93,7 @@ class TestPipreqs(unittest.TestCase):
""" """
pipreqs.init({'<path>': self.project, '--savepath': None, '--print': False, pipreqs.init({'<path>': self.project, '--savepath': None, '--print': False,
'--use-local': None, '--force': True, '--proxy':None, '--pypi-server':None, '--use-local': None, '--force': True, '--proxy':None, '--pypi-server':None,
'--diff': None, '--clean': None, '--dynamic': None}) '--diff': None, '--clean': None, '--mode': None})
assert os.path.exists(self.requirements_path) == 1 assert os.path.exists(self.requirements_path) == 1
with open(self.requirements_path, "r") as f: with open(self.requirements_path, "r") as f:
data = f.read().lower() data = f.read().lower()
@ -106,7 +106,7 @@ class TestPipreqs(unittest.TestCase):
""" """
pipreqs.init({'<path>': self.project, '--savepath': None, '--print': False, pipreqs.init({'<path>': self.project, '--savepath': None, '--print': False,
'--use-local': True, '--force': True, '--proxy':None, '--pypi-server':None, '--use-local': True, '--force': True, '--proxy':None, '--pypi-server':None,
'--diff': None, '--clean': None, '--dynamic': None}) '--diff': None, '--clean': None, '--mode': None})
assert os.path.exists(self.requirements_path) == 1 assert os.path.exists(self.requirements_path) == 1
with open(self.requirements_path, "r") as f: with open(self.requirements_path, "r") as f:
data = f.readlines() data = f.readlines()
@ -120,7 +120,7 @@ class TestPipreqs(unittest.TestCase):
""" """
pipreqs.init({'<path>': self.project, '--savepath': pipreqs.init({'<path>': self.project, '--savepath':
self.alt_requirement_path, '--use-local': None, '--proxy':None, '--pypi-server':None, '--print': False, self.alt_requirement_path, '--use-local': None, '--proxy':None, '--pypi-server':None, '--print': False,
"--diff": None, "--clean": None, '--dynamic': None}) "--diff": None, "--clean": None, '--mode': None})
assert os.path.exists(self.alt_requirement_path) == 1 assert os.path.exists(self.alt_requirement_path) == 1
with open(self.alt_requirement_path, "r") as f: with open(self.alt_requirement_path, "r") as f:
data = f.read().lower() data = f.read().lower()
@ -137,7 +137,7 @@ class TestPipreqs(unittest.TestCase):
f.write("should_not_be_overwritten") f.write("should_not_be_overwritten")
pipreqs.init({'<path>': self.project, '--savepath': None, pipreqs.init({'<path>': self.project, '--savepath': None,
'--use-local': None, '--force': None, '--proxy':None, '--pypi-server':None, '--print': False, '--use-local': None, '--force': None, '--proxy':None, '--pypi-server':None, '--print': False,
"--diff": None, "--clean": None, '--dynamic': None}) "--diff": None, "--clean": None, '--mode': None})
assert os.path.exists(self.requirements_path) == 1 assert os.path.exists(self.requirements_path) == 1
with open(self.requirements_path, "r") as f: with open(self.requirements_path, "r") as f:
data = f.read().lower() data = f.read().lower()
@ -174,7 +174,7 @@ class TestPipreqs(unittest.TestCase):
'--ignore':'.ignored_dir,.ignore_second', '--ignore':'.ignored_dir,.ignore_second',
'--diff': None, '--diff': None,
'--clean': None, '--clean': None,
'--dynamic': None '--mode': None
} }
) )
with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f:
@ -182,9 +182,9 @@ class TestPipreqs(unittest.TestCase):
for item in ['click', 'getpass']: for item in ['click', 'getpass']:
self.assertFalse(item.lower() in data) self.assertFalse(item.lower() in data)
def test_dynamic_version_all_scheme(self): def test_dynamic_version_no_pin_scheme(self):
""" """
Test --dynamic=all Test --mode=no-pin
""" """
pipreqs.init( pipreqs.init(
{'<path>': self.project_with_ignore_directory, '--savepath': None, '--print': False, {'<path>': self.project_with_ignore_directory, '--savepath': None, '--print': False,
@ -193,7 +193,7 @@ class TestPipreqs(unittest.TestCase):
'--pypi-server': None, '--pypi-server': None,
'--diff': None, '--diff': None,
'--clean': None, '--clean': None,
'--dynamic': 'all' '--mode': 'no-pin'
} }
) )
with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f:
@ -201,9 +201,9 @@ class TestPipreqs(unittest.TestCase):
for item in ['beautifulsoup4', 'boto']: for item in ['beautifulsoup4', 'boto']:
self.assertTrue(item.lower() in data) self.assertTrue(item.lower() in data)
def test_dynamic_version_micro_scheme(self): def test_dynamic_version_gt_scheme(self):
""" """
Test --dynamic=micro Test --mode=gt
""" """
pipreqs.init( pipreqs.init(
{'<path>': self.project_with_ignore_directory, '--savepath': None, '--print': False, {'<path>': self.project_with_ignore_directory, '--savepath': None, '--print': False,
@ -212,18 +212,19 @@ class TestPipreqs(unittest.TestCase):
'--pypi-server': None, '--pypi-server': None,
'--diff': None, '--diff': None,
'--clean': None, '--clean': None,
'--dynamic': 'micro' '--mode': 'gt'
} }
) )
with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f:
data = f.readlines() data = f.readlines()
for item in data: for item in data:
asterisk = item.strip().split(".")[2] symbol = '>='
self.assertEqual(asterisk, "*",) message = 'symbol is not in item'
self.assertIn(symbol, item, message)
def test_dynamic_version_minor_scheme(self): def test_dynamic_version_compat_scheme(self):
""" """
Test --dynamic=minor Test --mode=compat
""" """
pipreqs.init( pipreqs.init(
{'<path>': self.project_with_ignore_directory, '--savepath': None, '--print': False, {'<path>': self.project_with_ignore_directory, '--savepath': None, '--print': False,
@ -232,14 +233,15 @@ class TestPipreqs(unittest.TestCase):
'--pypi-server': None, '--pypi-server': None,
'--diff': None, '--diff': None,
'--clean': None, '--clean': None,
'--dynamic': 'minor' '--mode': 'compat'
} }
) )
with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f: with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f:
data = f.readlines() data = f.readlines()
for item in data: for item in data:
asterisk = item.strip().split(".")[1] symbol = '~='
self.assertEqual(asterisk, "*",) message = 'symbol is not in item'
self.assertIn(symbol, item, message)
def tearDown(self): def tearDown(self):
""" """