diff --git a/CHANGELOG.md b/CHANGELOG.md index 73a16ce..4b01edb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Added - more testcases in conflict cases +- `batch_upload` tests +- `read_json` method in `util.py` ### Changed - `upload` method in `reserver_obj.py` +- `batch_upload` method `reserver_obj.py` ## [0.2] - 2024-06-17 ### Added - `CLI` handler diff --git a/reserver/reserver_obj.py b/reserver/reserver_obj.py index 28d93fa..ceb3669 100644 --- a/reserver/reserver_obj.py +++ b/reserver/reserver_obj.py @@ -4,11 +4,12 @@ from re import sub from sys import executable from os import environ, path, getcwd, remove -from .util import has_named_parameter, remove_dir +from .reserver_errors import ReserverBaseError from subprocess import check_output, CalledProcessError +from .reserver_param import UNEQUAL_PARAM_NAME_LENGTH_ERROR +from .util import has_named_parameter, remove_dir, read_json from .reserver_func import does_package_exist, generate_template_setup_py - class PyPIUploader: """ The Reserver PyPIUploader class reserves a package name by uploading a template repo to pypi account. @@ -31,22 +32,36 @@ def __init__(self, api_token, test_pypi=False): self.password = api_token self.test_pypi = test_pypi - def batch_upload(self, *names): + def batch_upload(self, names, user_params_path=None): """ Upload batch of package names to PyPI. :param names: packages' names - :type names: vararg + :type names: list + :param user_params_path: path to user-defined packages' parameters + :type user_params_path: None | str | list :return: Number of successfully reserved packages """ reserved_successfully = 0 - for name in names: - if isinstance(name, list): - reserved_successfully += self.batch_upload(*name) - else: - is_reserved = self.upload(name) - if is_reserved: + if user_params_path == None: + for name in names: + if self.upload(name): reserved_successfully += 1 + elif isinstance(user_params_path, str): + for name in names: + if self.upload(name, user_parameters=user_params_path): + reserved_successfully += 1 + elif isinstance(user_params_path, list): + if len(user_params_path) == 1: + for name in names: + if self.upload(name, user_parameters=user_params_path[0]): + reserved_successfully += 1 + elif len(user_params_path) == len(names): + for index, name in enumerate(names): + if self.upload(name, user_parameters=user_params_path[index]): + reserved_successfully += 1 + else: + raise ReserverBaseError(UNEQUAL_PARAM_NAME_LENGTH_ERROR) return reserved_successfully def upload(self, package_name, user_parameters=None): @@ -55,14 +70,17 @@ def upload(self, package_name, user_parameters=None): :param package_name: package name :type package_name: str - :param user_parameters: user-customized package parameters - :type user_parameters: dict + :param user_parameters: path to the .json file containing user-defined package parameters + :type user_parameters: str :return: True if the package is successfully reserved, False otherwise """ if does_package_exist(package_name, self.test_pypi): print("This package already exists in PyPI.") return False + if user_parameters != None: + user_parameters = read_json(user_parameters) + generate_template_setup_py(package_name, user_parameters) environ["TWINE_USERNAME"] = self.username diff --git a/reserver/reserver_param.py b/reserver/reserver_param.py index cc35afe..108af6e 100644 --- a/reserver/reserver_param.py +++ b/reserver/reserver_param.py @@ -21,4 +21,9 @@ "url": r'^(http|https)://[a-zA-Z0-9.-_]+\.[a-zA-Z]{2,}(/\S*)?$', } INVALID_PACKAGE_PARAMETER_NAME_ERROR = "Given parameter doesn't exist among the supported user allowed parameters." -INVALID_PACKAGE_PARAMETER_VALUE_ERROR = "Invalid value for {parameter} that should be a valid {regex}" \ No newline at end of file +INVALID_PACKAGE_PARAMETER_VALUE_ERROR = "Invalid value for {parameter} that should be a valid {regex}" +INVALID_CONFIG_FILE_NAME_ERROR = "Given file name for user-defined package params is not a string." +PARAM_FILE_DOES_NOT_EXIST_ERROR = "Given file doesn't exist." +INVALID_INPUT_USER_PARAM = "Invalid input for user params." +UNEQUAL_PARAM_NAME_LENGTH_ERROR = "You should pass either one single file path to be used for the package parameters \ +or per each package name, there should be a specific dedicated file path." diff --git a/reserver/util.py b/reserver/util.py index f84d4ff..769e1b1 100644 --- a/reserver/util.py +++ b/reserver/util.py @@ -1,9 +1,11 @@ # -*- coding: utf-8 -*- """utility module.""" -from inspect import signature import os +import json import shutil - +from inspect import signature +from .reserver_errors import ReserverBaseError +from .reserver_param import INVALID_CONFIG_FILE_NAME_ERROR, PARAM_FILE_DOES_NOT_EXIST_ERROR def has_named_parameter(func, param_name): """ @@ -32,3 +34,20 @@ def remove_dir(dirpath): """ if os.path.exists(dirpath) and os.path.isdir(dirpath): shutil.rmtree(dirpath) + + +def read_json(file_name): + """ + Read the json file and return the python obj of it. + + :param file_name: name of the .json file + :type file_name: str + :return: obj + """ + if not isinstance(file_name, str): + raise ReserverBaseError(INVALID_CONFIG_FILE_NAME_ERROR) + if os.path.isfile(file_name): + config_file = open(file_name) + return json.load(config_file) + else: + raise ReserverBaseError(PARAM_FILE_DOES_NOT_EXIST_ERROR) diff --git a/tests/config.json b/tests/config.json new file mode 100644 index 0000000..ce3036b --- /dev/null +++ b/tests/config.json @@ -0,0 +1,9 @@ +{ + "description": "[config] This name has been reserved using Reserver", + "author": "[config] Development Team", + "author_email": "configtest@test.com", + "url": "https://configurl.com", + "download_url": "https://configdownload_url.com", + "source": "https://configgithub.com/source", + "license": "[config] MIT" +} \ No newline at end of file diff --git a/tests/config2.json b/tests/config2.json new file mode 100644 index 0000000..8118716 --- /dev/null +++ b/tests/config2.json @@ -0,0 +1,9 @@ +{ + "description": "[config2] This name has been reserved using Reserver", + "author": "[config2] Development Team", + "author_email": "config2test@test.com", + "url": "https://config2url.com", + "download_url": "https://config2download_url.com", + "source": "https://config2github.com/source", + "license": "[config2] MIT" +} \ No newline at end of file diff --git a/tests/test_reserver.py b/tests/test_reserver.py index c860aee..b496773 100644 --- a/tests/test_reserver.py +++ b/tests/test_reserver.py @@ -18,7 +18,7 @@ def test_standard_module_conflict(): def test_batch_packages_names(): # test batch of package names uploader = PyPIUploader(test_pypi_token, test_pypi=True) - assert uploader.batch_upload("numpy", "scikit-learn") == 0 + assert uploader.batch_upload(["numpy", "scikit-learn"]) == 0 def test_valid_package_invalid_credentials(): # test not reserved name -> wrong credentials @@ -36,3 +36,12 @@ def test_module_conflict(): # try to reserve a name which conflicts with the module name of a previously taken package (the taken package itself has a different name, but it's module name has conflict)." uploader = PyPIUploader(pypi_token, test_pypi=False) assert uploader.upload("freeze") == False + +def test_batch_upload(): + # try to reserve two non taken package names with per package custom setup.py parameters + # uploader = PyPIUploader(test_pypi_token, True) + # assert uploader.batch_upload( + # [get_random_name(), get_random_name() + get_random_name()], + # ["config.json", "config2.json"] + # ) == 2 + assert True == True