From 2030ca8445740118563db957ae8199b2edc83f36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Morales=20Hern=C3=A1ndez?= Date: Tue, 6 Apr 2021 08:31:05 +0100 Subject: [PATCH 1/8] Uniform logging and private repos seems to be working --- medikit/feature/python.py | 220 ++++++++++++++++++++++++++++++++------ 1 file changed, 187 insertions(+), 33 deletions(-) diff --git a/medikit/feature/python.py b/medikit/feature/python.py index 9263845..303bd23 100644 --- a/medikit/feature/python.py +++ b/medikit/feature/python.py @@ -33,14 +33,17 @@ import os import tempfile from getpass import getuser +from types import SimpleNamespace from pip._vendor.distlib.util import parse_requirement +from pip._internal.req.req_install import InstallRequirement from piptools._compat import parse_requirements from piptools.cache import DependencyCache from piptools.locations import CACHE_DIR from piptools.repositories import PyPIRepository from piptools.resolver import Resolver from piptools.utils import format_requirement +from piptools.exceptions import IncompatibleRequirements import medikit from medikit.events import subscribe @@ -52,11 +55,27 @@ def _normalize_requirement(req): - bits = req.requirement.split() + """ Overrides the original method in Medikit, now it considers the special case of private repos """ + + if req.constraints and not req.url: + bits = req.requirement.split() + else: + bits = [req.requirement, '@', req.url] + if req.extras: bits = [bits[0] + "[{}]".format(",".join(req.extras))] + bits[1:] + return " ".join(bits) +def _get_valid_link_req(req): + """ Formats the repo based dependencies, which can be dirty in case of collision between repo based and package + based declarations (for similar packages) """ + + tokens = str(req).split("@") + req_name = parse_requirement(tokens[0]) + + return req_name.name + "@ " + "@".join(tokens[1:]) + class PythonConfig(Feature.Config): """ Configuration API for the «python» feature. """ @@ -73,6 +92,8 @@ def __init__(self): self._create_packages = True self.override_requirements = False self.use_wheelhouse = False + self.use_uniform_requirements = False + self.show_comes_from_info = False @property def package_dir(self): @@ -217,6 +238,66 @@ def __add_vendors(self, reqs, extra=None): for req in reqs: self._vendors[extra].append(req) + def get_requirement_info_by_name(self, req, requirements_by_name=dict()): + """ Given a requirement, it provides its valid information to be included in the final file """ + + if self.use_uniform_requirements: + # If it is a repo and not a package, this will be True + if req.link: + requirement_name = parse_requirement(_get_valid_link_req(req.req)).name + else: + requirement_name = parse_requirement(str(req.req)).name + + # If the requirement is not in the dict, it is because it was not needed as a dependency in the original + # set containing all requirements + if requirement_name in requirements_by_name.keys(): + # In case we want to show the source for inherited dependencies + if self.show_comes_from_info and type(req.comes_from) == InstallRequirement: + return "{}\t\t\t# From: {}".format(requirements_by_name[requirement_name].requirement, + str(req.comes_from.req)) + else: + return requirements_by_name[requirement_name].requirement + + else: + return None + else: + # If not using uniform versions, we just need to provide the information based on wether it is + # a repository or a package + if self.show_comes_from_info and type(req.comes_from) == InstallRequirement: + return "{}\t\t\t# From: {}".format(format_requirement(req) if not req.link else str(req.req), + str(req.comes_from.req)) + else: + return format_requirement(req) if not req.link else str(req.req) + + def _check_duplicate_dependencies_by_extra(self, extra, requirements_by_name): + """ Checks there are not duplicate dependencies, in the case of private repositories""" + + for name, req in sorted(self._requirements[extra].items()): + requirement_str = req.requirement if not req.url else req.url.strip().replace(" ", "") + + if name not in requirements_by_name.keys(): + # This can happen if additional requirements are included from the outside, for instance with pytest + continue + + if (req.url or requirements_by_name[name].url) and requirements_by_name[name].requirement != requirement_str: + raise IncompatibleRequirements(req, requirements_by_name[name].url) + + def check_duplicate_dependencies_uniform(self, requirements_by_name): + """ Checks there are not duplicate dependencies, when use_uniform_requirements==True """ + for extra in itertools.chain((None,), self.get_extras()): + self._check_duplicate_dependencies_by_extra(extra, requirements_by_name) + + def check_duplicate_dependencies_nonuniform(self, extra, resolver): + """ Checks there are not duplicate dependencies, when use_uniform_requirements==False """ + requirements_by_name = {} + for req in resolver.resolve(max_rounds=10): + requirements_by_name[parse_requirement(str(req.req)).name] = SimpleNamespace( + requirement=format_requirement(req).strip().replace(" ", ""), + url=req.link + ) + + self._check_duplicate_dependencies_by_extra(extra, requirements_by_name) + class PythonFeature(Feature): """ @@ -414,48 +495,87 @@ def on_start(self, event): version = "0.0.0" self.render_file_inline(python_config.version_file, "__version__ = '{}'".format(version)) - setup = python_config.get_setup() - - context = { - "url": setup.pop("url", "http://example.com/"), - "download_url": setup.pop("download_url", "http://example.com/"), - } - - for k, v in context.items(): - context[k] = context[k].format(name=setup["name"], user=getuser(), version="{version}") - - context.update( - { - "entry_points": setup.pop("entry_points", {}), - "extras_require": python_config.get("extras_require"), - "install_requires": python_config.get("install_requires"), - "python": python_config, - "setup": setup, - "banner": get_override_warning_banner(), - } - ) - - # Render (with overwriting) the allmighty setup.py - self.render_file("setup.py", "python/setup.py.j2", context, override=True) + # setup = python_config.get_setup() + # + # context = { + # "url": setup.pop("url", "http://example.com/"), + # "download_url": setup.pop("download_url", "http://example.com/"), + # } + # + # for k, v in context.items(): + # context[k] = context[k].format(name=setup["name"], user=getuser(), version="{version}") + # + # context.update( + # { + # "entry_points": setup.pop("entry_points", {}), + # "extras_require": python_config.get("extras_require"), + # "install_requires": python_config.get("install_requires"), + # "python": python_config, + # "setup": setup, + # "banner": get_override_warning_banner(), + # } + # ) + # + # from pprint import pprint + # pprint(context) + # + # # Render (with overwriting) the allmighty setup.py + # self.render_file("setup.py", "python/setup.py.j2", context, override=True) @subscribe(medikit.on_end, priority=ABSOLUTE_PRIORITY) def on_end(self, event): + # Our config object python_config = event.config["python"] # Pip / PyPI repository = PyPIRepository([], cache_dir=CACHE_DIR) + # repository = PyPIRepository([], cache_dir=tempfile.mkdtemp()) + + # We just need to construct this structure if use_uniform_requirements == True + requirements_by_name = {} + if python_config.use_uniform_requirements: + tmpfile = tempfile.NamedTemporaryFile(mode="wt", delete=False) + for extra in itertools.chain((None,), python_config.get_extras()): + tmpfile.write("\n".join(python_config.get_requirements(extra=extra)) + "\n") + tmpfile.flush() + + constraints = list( + parse_requirements( + tmpfile.name, finder=repository.finder, session=repository.session, options=repository.options + ) + ) + + # This resolver is able to evaluate ALL the dependencies along the extras + resolver = Resolver( + constraints, + repository, + cache=DependencyCache(CACHE_DIR), + # cache=DependencyCache(tempfile.tempdir), + prereleases=False, + clear_caches=False, + allow_unsafe=False, + ) + + for req in resolver.resolve(max_rounds=10): + requirements_by_name[parse_requirement(str(req.req)).name] = SimpleNamespace( + requirement=format_requirement(req).strip().replace(" ", ""), + url=req.link + ) + + python_config.check_duplicate_dependencies_uniform(requirements_by_name) + + # Now it iterates along the versions in extras and looks for the requirements and its dependencies, using the + # structure created above to select the unified versions (unless the flag indicates otherwise). for extra in itertools.chain((None,), python_config.get_extras()): requirements_file = "requirements{}.txt".format("-" + extra if extra else "") if python_config.override_requirements or not os.path.exists(requirements_file): tmpfile = tempfile.NamedTemporaryFile(mode="wt", delete=False) - if extra: - tmpfile.write("\n".join(python_config.get_requirements(extra=extra))) - else: - tmpfile.write("\n".join(python_config.get_requirements())) + tmpfile.write("\n".join(python_config.get_requirements(extra=extra)) + "\n") tmpfile.flush() + constraints = list( parse_requirements( tmpfile.name, finder=repository.finder, session=repository.session, options=repository.options @@ -470,6 +590,16 @@ def on_end(self, event): allow_unsafe=False, ) + if not python_config.use_uniform_requirements: + python_config.check_duplicate_dependencies_nonuniform(extra, resolver) + + requirements_list = [] + for req in resolver.resolve(max_rounds=10): + if req.name != python_config.get("name"): + requirement = python_config.get_requirement_info_by_name(req, requirements_by_name) + if requirement: + requirements_list.append(requirement) + self.render_file_inline( requirements_file, "\n".join( @@ -477,12 +607,36 @@ def on_end(self, event): "-e .{}".format("[" + extra + "]" if extra else ""), *(("-r requirements.txt",) if extra else ()), *python_config.get_vendors(extra=extra), - *sorted( - format_requirement(req) - for req in resolver.resolve(max_rounds=10) - if req.name != python_config.get("name") - ), + *sorted(requirements_list), ) ), override=python_config.override_requirements, ) + + # Updates setup file + setup = python_config.get_setup() + + context = { + "url": setup.pop("url", ""), + "download_url": setup.pop("download_url", ""), + } + + for k, v in context.items(): + context[k] = context[k].format(name=setup["name"], user=getuser(), version="{version}") + + context.update( + { + "entry_points": setup.pop("entry_points", {}), + "extras_require": python_config.get("extras_require"), + "install_requires": python_config.get("install_requires"), + "python": python_config, + "setup": setup, + "banner": get_override_warning_banner(), + } + ) + + from pprint import pprint + pprint(context) + + # Render (with overwriting) the allmighty setup.py + self.render_file("setup.py", "python/setup.py.j2", context, override=True) From 1a9ee31aec1c48907ac9359891ffdca227638be0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Morales=20Hern=C3=A1ndez?= Date: Tue, 6 Apr 2021 09:59:33 +0100 Subject: [PATCH 2/8] Cleaning up --- medikit/feature/python.py | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/medikit/feature/python.py b/medikit/feature/python.py index 303bd23..207287b 100644 --- a/medikit/feature/python.py +++ b/medikit/feature/python.py @@ -53,6 +53,7 @@ from medikit.resources.configparser import ConfigParserResource from medikit.utils import get_override_warning_banner +from pprint import pprint def _normalize_requirement(req): """ Overrides the original method in Medikit, now it considers the special case of private repos """ @@ -92,7 +93,9 @@ def __init__(self): self._create_packages = True self.override_requirements = False self.use_wheelhouse = False + # Use the same requirement versions among all the extras, when requirements coincide. self.use_uniform_requirements = False + # Print the information of the "parent" requirement in the requirements*.txt files. self.show_comes_from_info = False @property @@ -495,33 +498,6 @@ def on_start(self, event): version = "0.0.0" self.render_file_inline(python_config.version_file, "__version__ = '{}'".format(version)) - # setup = python_config.get_setup() - # - # context = { - # "url": setup.pop("url", "http://example.com/"), - # "download_url": setup.pop("download_url", "http://example.com/"), - # } - # - # for k, v in context.items(): - # context[k] = context[k].format(name=setup["name"], user=getuser(), version="{version}") - # - # context.update( - # { - # "entry_points": setup.pop("entry_points", {}), - # "extras_require": python_config.get("extras_require"), - # "install_requires": python_config.get("install_requires"), - # "python": python_config, - # "setup": setup, - # "banner": get_override_warning_banner(), - # } - # ) - # - # from pprint import pprint - # pprint(context) - # - # # Render (with overwriting) the allmighty setup.py - # self.render_file("setup.py", "python/setup.py.j2", context, override=True) - @subscribe(medikit.on_end, priority=ABSOLUTE_PRIORITY) def on_end(self, event): From b53cc112ca2844d00bfd915262c99d44a12438c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Morales=20Hern=C3=A1ndez?= Date: Tue, 6 Apr 2021 10:00:16 +0100 Subject: [PATCH 3/8] Cleaning up --- medikit/feature/python.py | 1 - 1 file changed, 1 deletion(-) diff --git a/medikit/feature/python.py b/medikit/feature/python.py index 207287b..714aadf 100644 --- a/medikit/feature/python.py +++ b/medikit/feature/python.py @@ -53,7 +53,6 @@ from medikit.resources.configparser import ConfigParserResource from medikit.utils import get_override_warning_banner -from pprint import pprint def _normalize_requirement(req): """ Overrides the original method in Medikit, now it considers the special case of private repos """ From 8fdb81ffe6d4af44d2e04b85026d0a4e890219af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Morales=20Hern=C3=A1ndez?= Date: Tue, 6 Apr 2021 10:28:35 +0100 Subject: [PATCH 4/8] Updated comments --- medikit/feature/python.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/medikit/feature/python.py b/medikit/feature/python.py index 714aadf..44f08c4 100644 --- a/medikit/feature/python.py +++ b/medikit/feature/python.py @@ -55,7 +55,7 @@ def _normalize_requirement(req): - """ Overrides the original method in Medikit, now it considers the special case of private repos """ + """ Normalizes the requirement string. It considers the case of having or not an URL """ if req.constraints and not req.url: bits = req.requirement.split() @@ -505,7 +505,6 @@ def on_end(self, event): # Pip / PyPI repository = PyPIRepository([], cache_dir=CACHE_DIR) - # repository = PyPIRepository([], cache_dir=tempfile.mkdtemp()) # We just need to construct this structure if use_uniform_requirements == True requirements_by_name = {} From ea11cf9ddee6abb73275a795089260b17114ef44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Morales=20Hern=C3=A1ndez?= Date: Tue, 6 Apr 2021 15:08:52 +0100 Subject: [PATCH 5/8] Fix issue with reqs w/o constraints --- Makefile | 6 +-- medikit/feature/python.py | 2 +- requirements-dev.txt | 44 +++++++++--------- requirements.txt | 20 ++++---- setup.py | 97 +++++++++++++++++---------------------- 5 files changed, 77 insertions(+), 92 deletions(-) diff --git a/Makefile b/Makefile index 37825e3..9be0d28 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ -# Generated by Medikit 0.8.0 on 2020-11-25. +# Generated by Medikit 0.8.0 on 2021-04-06. # All changes will be overriden. # Edit Projectfile and run “make update” (or “medikit update”) to regenerate. PACKAGE ?= medikit -PYTHON ?= $(shell which python || echo python) +PYTHON ?= $(shell which python3 || which python || echo python3) PYTHON_BASENAME ?= $(shell basename $(PYTHON)) PYTHON_DIRNAME ?= $(shell dirname $(PYTHON)) PYTHON_REQUIREMENTS_FILE ?= requirements.txt @@ -18,7 +18,7 @@ VERSION ?= $(shell git describe 2>/dev/null || git rev-parse --short HEAD) BLACK ?= $(shell which black || echo black) BLACK_OPTIONS ?= --line-length 120 ISORT ?= $(PYTHON) -m isort -ISORT_OPTIONS ?= --recursive --apply +ISORT_OPTIONS ?= PYTEST ?= $(PYTHON_DIRNAME)/pytest PYTEST_OPTIONS ?= --capture=no --cov=$(PACKAGE) --cov-report html SPHINX_BUILD ?= $(PYTHON_DIRNAME)/sphinx-build diff --git a/medikit/feature/python.py b/medikit/feature/python.py index 44f08c4..9138ca0 100644 --- a/medikit/feature/python.py +++ b/medikit/feature/python.py @@ -57,7 +57,7 @@ def _normalize_requirement(req): """ Normalizes the requirement string. It considers the case of having or not an URL """ - if req.constraints and not req.url: + if not req.url: bits = req.requirement.split() else: bits = [req.requirement, '@', req.url] diff --git a/requirements-dev.txt b/requirements-dev.txt index f696cf1..5db23f1 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -5,48 +5,46 @@ appdirs==1.4.4 attrs==20.3.0 babel==2.9.0 black==20.8b1 -certifi==2020.11.8 +certifi==2020.12.5 cfgv==3.2.0 -chardet==3.0.4 +chardet==4.0.0 click==7.1.2 -coverage==5.3 +coverage==5.5 distlib==0.3.1 -docutils==0.16 +docutils==0.17 filelock==3.0.12 -identify==1.5.10 +identify==2.2.2 idna==2.10 imagesize==1.2.0 -importlib-metadata==3.1.0 iniconfig==1.1.1 -isort==5.6.4 -jinja2==2.11.2 +isort==5.8.0 +jinja2==2.11.3 markupsafe==1.1.1 mypy-extensions==0.4.3 nodeenv==1.5.0 -packaging==20.4 +packaging==20.9 pathspec==0.8.1 pluggy==0.13.1 -pre-commit==2.9.0 -py==1.9.0 -pygments==2.7.2 +pre-commit==2.9.3 +py==1.10.0 +pygments==2.8.1 pyparsing==2.4.7 -pytest-cov==2.10.1 -pytest==6.1.2 -pytz==2020.4 -pyyaml==5.3.1 -regex==2020.11.13 +pytest-cov==2.11.1 +pytest==6.2.3 +pytz==2021.1 +pyyaml==5.4.1 +regex==2021.4.4 releases==1.6.3 -requests==2.25.0 +requests==2.25.1 semantic-version==2.6.0 six==1.15.0 -snowballstemmer==2.0.0 +snowballstemmer==2.1.0 sphinx-sitemap==1.1.0 sphinx==1.8.5 sphinxcontrib-serializinghtml==1.1.4 sphinxcontrib-websupport==1.2.4 toml==0.10.2 -typed-ast==1.4.1 +typed-ast==1.4.2 typing-extensions==3.7.4.3 -urllib3==1.26.2 -virtualenv==20.2.1 -zipp==3.4.0 +urllib3==1.26.4 +virtualenv==20.4.3 diff --git a/requirements.txt b/requirements.txt index ec94972..ca6fa28 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,21 +1,19 @@ -e . click==7.1.2 -colorama==0.3.9 +colorama==0.4.4 git-semver==0.3.2 -gitdb==4.0.5 -gitpython==3.1.11 -importlib-metadata==3.1.0 -jinja2==2.11.2 +gitdb==4.0.7 +gitpython==3.1.14 +jinja2==2.11.3 markupsafe==1.1.1 -mondrian==0.8.0 -packaging==20.4 +mondrian==0.8.1 +packaging==20.9 pbr==5.5.1 pip-tools==4.5.1 pyparsing==2.4.7 semantic-version==2.6.0 six==1.15.0 -smmap==3.0.4 -stevedore==3.2.2 +smmap==4.0.0 +stevedore==3.3.0 whistle==1.0.1 -yapf==0.30.0 -zipp==3.4.0 +yapf==0.31.0 diff --git a/setup.py b/setup.py index 44e29c7..04e897d 100644 --- a/setup.py +++ b/setup.py @@ -1,12 +1,11 @@ -# Generated by Medikit 0.8.0 on 2020-11-25. +# Generated by Medikit 0.8.0 on 2021-04-06. # All changes will be overriden. # Edit Projectfile and run “make update” (or “medikit update”) to regenerate. +from setuptools import setup, find_packages from codecs import open from os import path -from setuptools import find_packages, setup - here = path.abspath(path.dirname(__file__)) # Py3 compatibility hacks, borrowed from IPython. @@ -21,81 +20,71 @@ def execfile(fname, globs, locs=None): # Get the long description from the README file try: - with open(path.join(here, "README.rst"), encoding="utf-8") as f: + with open(path.join(here, 'README.rst'), encoding='utf-8') as f: long_description = f.read() except: - long_description = "" + long_description = '' # Get the classifiers from the classifiers file -tolines = lambda c: list(filter(None, map(lambda s: s.strip(), c.split("\n")))) +tolines = lambda c: list(filter(None, map(lambda s: s.strip(), c.split('\n')))) try: - with open(path.join(here, "classifiers.txt"), encoding="utf-8") as f: + with open(path.join(here, 'classifiers.txt'), encoding='utf-8') as f: classifiers = tolines(f.read()) except: classifiers = [] version_ns = {} try: - execfile(path.join(here, "medikit/_version.py"), version_ns) + execfile(path.join(here, 'medikit/_version.py'), version_ns) except EnvironmentError: - version = "dev" + version = 'dev' else: - version = version_ns.get("__version__", "dev") + version = version_ns.get('__version__', 'dev') setup( - author="Romain Dorgueil", - author_email="romain@dorgueil.net", - description="Opinionated python 3.5+ project management.", - license="Apache License, Version 2.0", - name="medikit", - python_requires=">=3.5", + author='Romain Dorgueil', + author_email='romain@dorgueil.net', + description='Opinionated python 3.5+ project management.', + license='Apache License, Version 2.0', + name='medikit', + python_requires='>=3.5', version=version, long_description=long_description, classifiers=classifiers, - packages=find_packages(exclude=["ez_setup", "example", "test"]), + packages=find_packages(exclude=['ez_setup', 'example', 'test']), include_package_data=True, install_requires=[ - "git-semver ~= 0.3.2", - "jinja2 ~= 2.10", - "mondrian ~= 0.8", - "packaging ~= 20.0", - "pip-tools ~= 4.5.0", - "semantic_version < 2.7", - "stevedore ~= 3.0", - "whistle ~= 1.0", - "yapf ~= 0.20", + 'git-semver ~= 0.3.2', 'jinja2 ~= 2.10', 'mondrian ~= 0.8', + 'packaging ~= 20.0', 'pip-tools ~= 4.5.0', 'semantic_version < 2.7', + 'stevedore ~= 3.0', 'whistle ~= 1.0', 'yapf ~= 0.20' ], extras_require={ - "dev": [ - "black == 20.8b1", - "coverage ~= 5.3", - "isort", - "pre-commit ~= 2.9.0", - "pytest ~= 6.0", - "pytest-cov ~= 2.7", - "releases >= 1.6, < 1.7", - "sphinx ~= 1.7", - "sphinx-sitemap ~= 1.0", + 'dev': [ + 'black == 20.8b1', 'coverage ~= 5.3', 'isort', + 'pre-commit ~= 2.9.0', 'pytest ~= 6.0', 'pytest-cov ~= 2.7', + 'releases >= 1.6, < 1.7', 'sphinx ~= 1.7', 'sphinx-sitemap ~= 1.0' ] }, entry_points={ - "console_scripts": ["medikit=medikit.__main__:main"], - "medikit.feature": [ - "django = medikit.feature.django:DjangoFeature", - "docker = medikit.feature.docker:DockerFeature", - "format = medikit.feature.format:FormatFeature", - "git = medikit.feature.git:GitFeature", - "kube = medikit.feature.kube:KubeFeature", - "make = medikit.feature.make:MakeFeature", - "nodejs = medikit.feature.nodejs:NodeJSFeature", - "pylint = medikit.feature.pylint:PylintFeature", - "pytest = medikit.feature.pytest:PytestFeature", - "python = medikit.feature.python:PythonFeature", - "sphinx = medikit.feature.sphinx:SphinxFeature", - "webpack = medikit.feature.webpack:WebpackFeature", - "yapf = medikit.feature.yapf:YapfFeature", - ], + 'console_scripts': ['medikit=medikit.__main__:main'], + 'medikit.feature': [ + 'django = medikit.feature.django:DjangoFeature', + 'docker = medikit.feature.docker:DockerFeature', + 'format = medikit.feature.format:FormatFeature', + 'git = medikit.feature.git:GitFeature', + 'kube = medikit.feature.kube:KubeFeature', + 'make = medikit.feature.make:MakeFeature', + 'nodejs = medikit.feature.nodejs:NodeJSFeature', + 'pylint = medikit.feature.pylint:PylintFeature', + 'pytest = medikit.feature.pytest:PytestFeature', + 'python = medikit.feature.python:PythonFeature', + 'sphinx = medikit.feature.sphinx:SphinxFeature', + 'webpack = medikit.feature.webpack:WebpackFeature', + 'yapf = medikit.feature.yapf:YapfFeature' + ] }, - url="https://python-medikit.github.io/", - download_url="https://github.com/python-medikit/medikit/archive/{version}.tar.gz".format(version=version), + url='https://python-medikit.github.io/', + download_url= + 'https://github.com/python-medikit/medikit/archive/{version}.tar.gz'. + format(version=version), ) From 65777742cbc3bec030d4321bfe46de9d6f82c9d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Morales=20Hern=C3=A1ndez?= Date: Tue, 6 Apr 2021 15:16:20 +0100 Subject: [PATCH 6/8] Removed unnecessary message --- medikit/feature/python.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/medikit/feature/python.py b/medikit/feature/python.py index 9138ca0..5736c23 100644 --- a/medikit/feature/python.py +++ b/medikit/feature/python.py @@ -609,8 +609,5 @@ def on_end(self, event): } ) - from pprint import pprint - pprint(context) - # Render (with overwriting) the allmighty setup.py self.render_file("setup.py", "python/setup.py.j2", context, override=True) From f15236699fd18b3ffa60eb7ba7afee9a355934a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Morales=20Hern=C3=A1ndez?= Date: Wed, 14 Apr 2021 12:39:10 +0100 Subject: [PATCH 7/8] Added tests to increase coverage --- tests/feature/test_feature_python.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/feature/test_feature_python.py b/tests/feature/test_feature_python.py index 10540ad..1cdfb48 100644 --- a/tests/feature/test_feature_python.py +++ b/tests/feature/test_feature_python.py @@ -72,3 +72,29 @@ def test_on_start(self): assert event.setup["name"] == PACKAGE_NAME assert event.setup["python_requires"] == ">=3.5" + + def test_on_end(self): + config = self.create_config() + + feature, dispatcher = self.create_feature() + event = ProjectEvent(config=config, setup={"name": PACKAGE_NAME, "python_requires": ">=3.5"}) + feature.on_end(event) + + assert event.setup["name"] == PACKAGE_NAME + assert event.setup["python_requires"] == ">=3.5" + assert not event.config["python"].use_uniform_requirements + assert not event.config["python"].show_comes_from_info + + def test_on_end_uniform_requirements(self): + config = self.create_config() + config["python"].use_uniform_requirements = True + config["python"].show_comes_from_info = True + + feature, dispatcher = self.create_feature() + event = ProjectEvent(config=config, setup={"name": PACKAGE_NAME, "python_requires": ">=3.5"}) + feature.on_end(event) + + assert event.setup["name"] == PACKAGE_NAME + assert event.setup["python_requires"] == ">=3.5" + assert event.config["python"].use_uniform_requirements + assert event.config["python"].show_comes_from_info From 57a1e77e044488dfc77f4b3fb460e5fa4c973e47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9stor=20Morales=20Hern=C3=A1ndez?= Date: Wed, 14 Apr 2021 12:48:39 +0100 Subject: [PATCH 8/8] Added tests to increase coverage --- tests/feature/test_feature_python.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/feature/test_feature_python.py b/tests/feature/test_feature_python.py index 1cdfb48..ba8c98a 100644 --- a/tests/feature/test_feature_python.py +++ b/tests/feature/test_feature_python.py @@ -84,11 +84,13 @@ def test_on_end(self): assert event.setup["python_requires"] == ">=3.5" assert not event.config["python"].use_uniform_requirements assert not event.config["python"].show_comes_from_info + assert not event.config["python"].override_requirements def test_on_end_uniform_requirements(self): config = self.create_config() config["python"].use_uniform_requirements = True config["python"].show_comes_from_info = True + config["python"].override_requirements = True feature, dispatcher = self.create_feature() event = ProjectEvent(config=config, setup={"name": PACKAGE_NAME, "python_requires": ">=3.5"}) @@ -98,3 +100,4 @@ def test_on_end_uniform_requirements(self): assert event.setup["python_requires"] == ">=3.5" assert event.config["python"].use_uniform_requirements assert event.config["python"].show_comes_from_info + assert event.config["python"].override_requirements