diff --git a/ethronsoft/gcspypi/__main__.py b/ethronsoft/gcspypi/__main__.py index 42c52a8..bb1bdcb 100644 --- a/ethronsoft/gcspypi/__main__.py +++ b/ethronsoft/gcspypi/__main__.py @@ -11,6 +11,8 @@ def main(): help="Specifies GCS bucket name hosting the packages. If not provided, gcspypi will try to read it from ~/.gcspypirc") parser.add_argument("--verbose", "-v", action="store_true", default=False, help="Verbose mode: exceptions stacktraces will be printed") + parser.add_argument("--python3", action="store_true", default=False, + help="Python3 mode: run in python3 mode") subparsers = parser.add_subparsers(title="commands", help="use command --help for help", dest="command") #init colorama @@ -37,7 +39,8 @@ def main(): [_, value] = reporc[0].split("=") repository = value.strip() config = { - "repository": repository + "repository": repository, + "python3": args.get("python3") } handlers[args["command"]](config, args) diff --git a/ethronsoft/gcspypi/package/package_builder.py b/ethronsoft/gcspypi/package/package_builder.py index 04cdae0..c4c5dd1 100644 --- a/ethronsoft/gcspypi/package/package_builder.py +++ b/ethronsoft/gcspypi/package/package_builder.py @@ -1,6 +1,4 @@ -from ethronsoft.gcspypi.utilities.queries import get_package_type -from ethronsoft.gcspypi.package.package import Package -from ethronsoft.gcspypi.exceptions import InvalidState +import re import json import os import shutil @@ -9,6 +7,9 @@ import zipfile +from ethronsoft.gcspypi.utilities.queries import get_package_type +from ethronsoft.gcspypi.package.package import Package +from ethronsoft.gcspypi.exceptions import InvalidState class PackageBuilder(object): @@ -78,10 +79,32 @@ def __call__(self, target): for reqs in m["run_requires"]: self.metadata["requirements"].update(reqs["requires"]) + class BackupInfoCmd(object): + def __init__(self): + self.metadata = {} + + def __call__(self, target): + m = {} + for line in target.readlines(): + if re.match(r'^[^\s]+:\s+\S+', line): + if len(line.split(":")) > 1: + k, v = line.split(":", 1) + if k.upper().strip() not in m: + m[k.upper().strip()] = [] + m[k.upper().strip()].append(v.strip()) + self.metadata["name"] = "".join(m["name".upper()]) + self.metadata["version"] = "".join(m["version".upper()]) + self.metadata["requirements"] = set([]) + for r in m.get("Requires-Dist".upper(), []): + self.metadata["requirements"].add(r) + cmd = InfoCmd() self.__seek_and_apply(zpfile, "metadata.json", cmd) if not cmd.metadata: - raise InvalidState("Could not find metadata.json") + cmd = BackupInfoCmd() + self.__seek_and_apply(zpfile, "METADATA", cmd) + if not cmd.metadata: + raise InvalidState("Could not find metadata.json") return cmd.metadata def __read_requirements(self, zpfile): diff --git a/ethronsoft/gcspypi/package/package_manager.py b/ethronsoft/gcspypi/package/package_manager.py index c6ffa06..8623aea 100644 --- a/ethronsoft/gcspypi/package/package_manager.py +++ b/ethronsoft/gcspypi/package/package_manager.py @@ -18,21 +18,34 @@ class PackageInstaller(object): # pragma: no cover + def __init__(self, is_python3): + self.__is_python3 = is_python3 + def install(self, resource, flags=[]): - subprocess.check_call(["python", "-m", "pip","install", resource] + flags) + if self.__is_python3: + subprocess.check_call(["python3", "-m", "pip","install", resource] + flags) + else: + subprocess.check_call(["python", "-m", "pip","install", resource] + flags) def uninstall(self, pkg): - subprocess.check_call(["python", "-m", "pip","uninstall", pkg.full_name.replace(":", "==")]) + if self.__is_python3: + subprocess.check_call(["python3", "-m", "pip","uninstall", pkg.full_name.replace(":", "==")]) + else: + subprocess.check_call(["python", "-m", "pip","uninstall", pkg.full_name.replace(":", "==")]) class PackageManager(object): - def __init__(self, repo, console, installer=PackageInstaller(), overwrite=False, mirroring=True, install_deps=True): + def __init__(self, repo, console, installer=None, is_python3=False, overwrite=False, mirroring=True, install_deps=True): self.__repo = repo self.__console = console - self.__installer = installer self.__overwrite = overwrite self.__mirroring = mirroring + if installer: + self.__installer = installer + else: + self.__installer = PackageInstaller(is_python3 = is_python3) self.__install_deps = install_deps + self.__is_python3 = is_python3 self.__prog = re.compile("((?:\w|-)*)(==|<=?|>=?)?((?:\d*\.?){0,3})?,?(==|<=?|>=?)?((?:\d*\.?){0,3})?") self.__repo_cache = [] self.refresh_cache() diff --git a/ethronsoft/gcspypi/parsers/backup.py b/ethronsoft/gcspypi/parsers/backup.py index 72768d6..d1c853e 100644 --- a/ethronsoft/gcspypi/parsers/backup.py +++ b/ethronsoft/gcspypi/parsers/backup.py @@ -1,17 +1,18 @@ -from ethronsoft.gcspypi.package.package_manager import PackageManager +from ethronsoft.gcspypi.package.package_manager import PackageManager,PackageInstaller from ethronsoft.gcspypi.utilities.console import Console from ethronsoft.gcspypi.parsers.commons import init_repository def handle_pull(config, data): with Console(verbose=config.get("verbose", False), exit_on_error=True) as c: repo = init_repository(c, config["repository"]) - pkg_mgr = PackageManager(repo, console=c) + is_python3 = config.get("python3", False) + pkg_mgr = PackageManager(repo, console=c, installer=None, is_python3=config.get("python3", False)) pkg_mgr.clone(data["destination"]) def handle_push(config, data): with Console(verbose=config.get("verbose", False), exit_on_error=True) as c: repo = init_repository(c, config["repository"]) - pkg_mgr = PackageManager(repo, console=c) + pkg_mgr = PackageManager(repo, console=c, installer=None, is_python3=config.get("python3", False)) pkg_mgr.restore(data["zipped_repo"]) class BackupParser(object): diff --git a/ethronsoft/gcspypi/parsers/download.py b/ethronsoft/gcspypi/parsers/download.py index dcf57fa..494a7d0 100644 --- a/ethronsoft/gcspypi/parsers/download.py +++ b/ethronsoft/gcspypi/parsers/download.py @@ -5,7 +5,7 @@ def handle_(config, data): with Console(verbose=config.get("verbose", False), exit_on_error=True) as c: repo = init_repository(c, config["repository"]) - pkg_mgr = PackageManager(repo, console=c) + pkg_mgr = PackageManager(repo, console=c, installer=None, is_python3 = config.get("python3", False)) downloaded = pkg_mgr.download_by_name(data["obj"], data["dir"]) c.info("Downloaded: {0}".format(downloaded)) diff --git a/ethronsoft/gcspypi/parsers/install.py b/ethronsoft/gcspypi/parsers/install.py index f865d21..ab1315a 100644 --- a/ethronsoft/gcspypi/parsers/install.py +++ b/ethronsoft/gcspypi/parsers/install.py @@ -5,7 +5,12 @@ def handle_(config, data): with Console(verbose=config.get("verbose", False), exit_on_error=True) as c: repo = init_repository(c, config["repository"]) - pkg_mgr = PackageManager(repo, console=c, mirroring=data["mirror"], install_deps=not data["no_dependencies"]) + pkg_mgr = PackageManager(repo, + console=c, + installer=None, + is_python3=config.get("python3", False), + mirroring=data["mirror"], + install_deps=not data["no_dependencies"]) if data["requirements"]: c.info("installing from requirements file...") for syntax in open(data["requirements"], "r").readlines(): diff --git a/ethronsoft/gcspypi/parsers/list.py b/ethronsoft/gcspypi/parsers/list.py index 479a799..7fd3a16 100644 --- a/ethronsoft/gcspypi/parsers/list.py +++ b/ethronsoft/gcspypi/parsers/list.py @@ -5,7 +5,7 @@ def handle_(config, data): with Console(verbose=config.get("verbose", False), exit_on_error=True) as c: repo = init_repository(c, config["repository"]) - pkg_mgr = PackageManager(repo, console=c) + pkg_mgr = PackageManager(repo, console=c, installer=None, is_python3 = config.get("python3", False)) for path in sorted(pkg_mgr.list_items(data["package"], from_cache=True)): c.output(path.split("/")[-1]) diff --git a/ethronsoft/gcspypi/parsers/remove.py b/ethronsoft/gcspypi/parsers/remove.py index 33e30d3..d9de265 100644 --- a/ethronsoft/gcspypi/parsers/remove.py +++ b/ethronsoft/gcspypi/parsers/remove.py @@ -5,7 +5,7 @@ def handle_(config, data): with Console(verbose=config.get("verbose", False), exit_on_error=True) as c: repo = init_repository(c, config["repository"]) - pkg_mgr = PackageManager(repo, console=c) + pkg_mgr = PackageManager(repo, console=c, installer=None, is_python3 = config.get("python3", False)) for syntax in data["packages"]: pkg = pkg_mgr.search(syntax) ok = pkg is not None diff --git a/ethronsoft/gcspypi/parsers/search.py b/ethronsoft/gcspypi/parsers/search.py index e2ac4ea..cb6d58b 100644 --- a/ethronsoft/gcspypi/parsers/search.py +++ b/ethronsoft/gcspypi/parsers/search.py @@ -5,7 +5,7 @@ def handle_(config, data): with Console(verbose=config.get("verbose", False), exit_on_error=True) as c: repo = init_repository(c, config["repository"]) - pkg_mgr = PackageManager(repo, console=c) + pkg_mgr = PackageManager(repo, console=c, installer=None, is_python3 = config.get("python3", False)) for syntax in data["syntax"]: pkg = pkg_mgr.search(syntax) if pkg: diff --git a/ethronsoft/gcspypi/parsers/uninstall.py b/ethronsoft/gcspypi/parsers/uninstall.py index fe46ece..1f4c59d 100644 --- a/ethronsoft/gcspypi/parsers/uninstall.py +++ b/ethronsoft/gcspypi/parsers/uninstall.py @@ -5,7 +5,7 @@ def handle_(config, data): with Console(verbose=config.get("verbose", False), exit_on_error=True) as c: repo = init_repository(c, config["repository"]) - pkg_mgr = PackageManager(repo, console=c) + pkg_mgr = PackageManager(repo, console=c, installer=None, is_python3 = config.get("python3", False)) for syntax in data["packages"]: pkg_mgr.uninstall(Package.from_text(syntax)) diff --git a/ethronsoft/gcspypi/parsers/upload.py b/ethronsoft/gcspypi/parsers/upload.py index f3ca44d..e8ba7cd 100644 --- a/ethronsoft/gcspypi/parsers/upload.py +++ b/ethronsoft/gcspypi/parsers/upload.py @@ -6,7 +6,7 @@ def handle_(config, data): with Console(verbose=config.get("verbose", False), exit_on_error=True) as c: repo = init_repository(c, config["repository"]) - pkg_mgr = PackageManager(repo, console=c, overwrite=data["overwrite"]) + pkg_mgr = PackageManager(repo, console=c, installer=None, is_python3 = config.get("python3", False), overwrite=data["overwrite"]) pkg = PackageBuilder(os.path.abspath(data["file"])).build() c.info("uploading {}...".format(str(pkg))) pkg_mgr.upload(pkg, os.path.abspath(data["file"])) diff --git a/setup.py b/setup.py index f5d6f49..5b4ff59 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name='gcspypi', - version='1.0.7', + version='1.0.8', author='Ethronsoft', author_email='dev@ethronsoft.com', license=open("LICENSE").read(), @@ -13,10 +13,10 @@ packages=find_packages(), zip_safe=False, install_requires=[ - "tqdm", - "colorama", - "six==1.11.0", - "google-cloud-storage==1.5.0", + "tqdm>=4.32.0", + "colorama>=0.4.1", + "six>=1.12.0", + "google-cloud-storage>=1.23.0", ], tests_require=[ "pytest", diff --git a/test/data/gcspypi-1.0.8+dev1-py3-none-any.whl b/test/data/gcspypi-1.0.8+dev1-py3-none-any.whl new file mode 100644 index 0000000..5c4bd39 Binary files /dev/null and b/test/data/gcspypi-1.0.8+dev1-py3-none-any.whl differ diff --git a/test/package_builder_test.py b/test/package_builder_test.py index e38e9ba..4fef85a 100644 --- a/test/package_builder_test.py +++ b/test/package_builder_test.py @@ -18,11 +18,6 @@ def test_src_wrong(): with pytest.raises(InvalidState): PackageBuilder(pkg_path).build() -def test_wheel_wrong(): - pkg_path = resource_filename(__name__, "data/WRONG-test_package-1.0.0-py2-none-any.whl") - with pytest.raises(InvalidState): - PackageBuilder(pkg_path).build() - def test_src_zip(): pkg_path = resource_filename(__name__, "data/test_package-1.0.0.zip") pkg = PackageBuilder(pkg_path).build() @@ -38,3 +33,14 @@ def test_wheel(): assert pkg.version == "1.0.0" assert pkg.requirements == set(["test-dep1", "test-dep2"]) assert pkg.type == "WHEEL" + +def test_wheel_py3(): + pkg_path = resource_filename(__name__, "data/gcspypi-1.0.8+dev1-py3-none-any.whl") + pkg = PackageBuilder(pkg_path).build() + assert pkg.name == "gcspypi" + assert pkg.version == "1.0.8+dev1" + assert pkg.type == "WHEEL" + assert pkg.requirements == set(["colorama (>=0.4.1)", + "google-cloud-storage (>=1.23.0)", + "six (>=1.12.0)", + "tqdm (>=4.32.0)", ])