Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/setup param #49

Merged
merged 13 commits into from
Aug 7, 2024
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
42 changes: 30 additions & 12 deletions reserver/reserver_obj.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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):
Expand All @@ -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
Expand Down
7 changes: 6 additions & 1 deletion reserver/reserver_param.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
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."
23 changes: 21 additions & 2 deletions reserver/util.py
Original file line number Diff line number Diff line change
@@ -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):
"""
Expand Down Expand Up @@ -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)
9 changes: 9 additions & 0 deletions tests/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"description": "[config] This name has been reserved using Reserver",
"author": "[config] Development Team",
"author_email": "[email protected]",
"url": "https://configurl.com",
"download_url": "https://configdownload_url.com",
"source": "https://configgithub.com/source",
"license": "[config] MIT"
}
Comment on lines +1 to +9
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, add an example of this to README.md.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

after this PR, I will handle CLI in which we can handle custom batch uploads
then I will update README.md

9 changes: 9 additions & 0 deletions tests/config2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"description": "[config2] This name has been reserved using Reserver",
"author": "[config2] Development Team",
"author_email": "[email protected]",
"url": "https://config2url.com",
"download_url": "https://config2download_url.com",
"source": "https://config2github.com/source",
"license": "[config2] MIT"
}
11 changes: 10 additions & 1 deletion tests/test_reserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Loading