New Option for Dynamic Versioning (#1)

* added new option for dynamic versioning

* added quotes for dynamic options

Co-authored-by: Siyang <teo_siyang@imda.gov.sg>
This commit is contained in:
Jake Teo 2021-03-25 17:37:00 +08:00 committed by GitHub
parent 060f52f597
commit 4eae4794a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 85 additions and 15 deletions

View File

@ -10,4 +10,5 @@ Development Lead
Contributors
------------
None yet. Why not be the first?
* Jake Teo <mapattacker@gmail.com>
* Jerome Chan <cjerome94@gmail.com>

View File

@ -49,7 +49,7 @@ Usage
--force Overwrite existing requirements.txt
--diff <file> Compare modules in requirements.txt to project imports.
--clean <file> Clean up requirements.txt by removing modules that are not imported in project.
--no-pin Omit version of output packages.
--dynamic <scheme> Enables dynamic version updates by 'minor', 'micro' or 'all' schemes.
Example
-------

34
pipreqs/pipreqs.py Executable file → Normal file
View File

@ -31,7 +31,8 @@ Options:
imports.
--clean <file> Clean up requirements.txt by removing modules
that are not imported in project.
--no-pin Omit version of output packages.
--dynamic <scheme> Enables dynamic version updates by 'minor',
'micro' or 'all' schemes.
"""
from __future__ import print_function, absolute_import
from contextlib import contextmanager
@ -392,6 +393,28 @@ def clean(file_, imports):
logging.info("Successfully cleaned up requirements in " + file_)
def dynamic_versioning(scheme, imports):
"""Enables dynamic versioning by minor, micro or all scheme."""
if scheme == "all":
imports = [{"name": item["name"], "version": ""} for item in imports]
else:
for item in imports:
version = item["version"]
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):
encoding = args.get('--encoding')
extra_ignore_dirs = args.get('--ignore')
@ -450,8 +473,13 @@ def init(args):
"use --force to overwrite it")
return
if args.get('--no-pin'):
imports = [{'name': item["name"], 'version': ''} for item in imports]
if args["--dynamic"]:
scheme = args.get("--dynamic")
if scheme in ["minor", "micro", "all"]:
imports = dynamic_versioning(scheme, imports)
else:
raise ValueError("Invalid argument for dynamic scheme, "
"use 'minor', 'micro' or 'all' instead")
if args["--print"]:
output_requirements(imports)

61
tests/test_pipreqs.py Executable file → Normal file
View File

@ -93,7 +93,7 @@ class TestPipreqs(unittest.TestCase):
"""
pipreqs.init({'<path>': self.project, '--savepath': None, '--print': False,
'--use-local': None, '--force': True, '--proxy':None, '--pypi-server':None,
'--diff': None, '--clean': None})
'--diff': None, '--clean': None, '--dynamic': None})
assert os.path.exists(self.requirements_path) == 1
with open(self.requirements_path, "r") as f:
data = f.read().lower()
@ -106,7 +106,7 @@ class TestPipreqs(unittest.TestCase):
"""
pipreqs.init({'<path>': self.project, '--savepath': None, '--print': False,
'--use-local': True, '--force': True, '--proxy':None, '--pypi-server':None,
'--diff': None, '--clean': None})
'--diff': None, '--clean': None, '--dynamic': None})
assert os.path.exists(self.requirements_path) == 1
with open(self.requirements_path, "r") as f:
data = f.readlines()
@ -120,7 +120,7 @@ class TestPipreqs(unittest.TestCase):
"""
pipreqs.init({'<path>': self.project, '--savepath':
self.alt_requirement_path, '--use-local': None, '--proxy':None, '--pypi-server':None, '--print': False,
"--diff": None, "--clean": None})
"--diff": None, "--clean": None, '--dynamic': None})
assert os.path.exists(self.alt_requirement_path) == 1
with open(self.alt_requirement_path, "r") as f:
data = f.read().lower()
@ -137,7 +137,7 @@ class TestPipreqs(unittest.TestCase):
f.write("should_not_be_overwritten")
pipreqs.init({'<path>': self.project, '--savepath': None,
'--use-local': None, '--force': None, '--proxy':None, '--pypi-server':None, '--print': False,
"--diff": None, "--clean": None})
"--diff": None, "--clean": None, '--dynamic': None})
assert os.path.exists(self.requirements_path) == 1
with open(self.requirements_path, "r") as f:
data = f.read().lower()
@ -173,7 +173,8 @@ class TestPipreqs(unittest.TestCase):
'--pypi-server':None,
'--ignore':'.ignored_dir,.ignore_second',
'--diff': None,
'--clean': None
'--clean': None,
'--dynamic': None
}
)
with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f:
@ -181,9 +182,9 @@ class TestPipreqs(unittest.TestCase):
for item in ['click', 'getpass']:
self.assertFalse(item.lower() in data)
def test_omit_version(self):
def test_dynamic_version_all_scheme(self):
"""
Test --no-pin parameter
Test --dynamic=all
"""
pipreqs.init(
{'<path>': self.project_with_ignore_directory, '--savepath': None, '--print': False,
@ -192,13 +193,53 @@ class TestPipreqs(unittest.TestCase):
'--pypi-server': None,
'--diff': None,
'--clean': None,
'--no-pin': True
'--dynamic': 'all'
}
)
with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f:
data = f.read().lower()
for item in ['beautifulsoup4==4.8.1', 'boto==2.49.0']:
self.assertFalse(item.lower() in data)
for item in ['beautifulsoup4', 'boto']:
self.assertTrue(item.lower() in data)
def test_dynamic_version_micro_scheme(self):
"""
Test --dynamic=micro
"""
pipreqs.init(
{'<path>': self.project_with_ignore_directory, '--savepath': None, '--print': False,
'--use-local': None, '--force': True,
'--proxy': None,
'--pypi-server': None,
'--diff': None,
'--clean': None,
'--dynamic': 'micro'
}
)
with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f:
data = f.readlines()
for item in data:
asterisk = item.strip().split(".")[2]
self.assertEqual(asterisk, "*",)
def test_dynamic_version_minor_scheme(self):
"""
Test --dynamic=minor
"""
pipreqs.init(
{'<path>': self.project_with_ignore_directory, '--savepath': None, '--print': False,
'--use-local': None, '--force': True,
'--proxy': None,
'--pypi-server': None,
'--diff': None,
'--clean': None,
'--dynamic': 'minor'
}
)
with open(os.path.join(self.project_with_ignore_directory, "requirements.txt"), "r") as f:
data = f.readlines()
for item in data:
asterisk = item.strip().split(".")[1]
self.assertEqual(asterisk, "*",)
def tearDown(self):
"""