Skip to content

Commit

Permalink
Feature/setup param (#49)
Browse files Browse the repository at this point in the history
* refactor `batch_upload` function

* add `read_json` to upload function to read user defined params from json file

* docstrings fulfilled

* add new error messages

* add test for batch upload with custom param file per package name

* `read_json` function in `util.py`

* comment batch test to prevent namespace squatting

* fix batch upload syntax

* CHANGELOG.md updated

* remove unused parameters

* error texts updated

* remove ".json" format check

* "\n" added
  • Loading branch information
AHReccese authored Aug 7, 2024
1 parent a7e76a4 commit 113bd91
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 16 deletions.
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"
}
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

0 comments on commit 113bd91

Please sign in to comment.