Skip to content

Commit

Permalink
fix packaging
Browse files Browse the repository at this point in the history
  • Loading branch information
gaborbernat committed Aug 21, 2019
1 parent b9b0140 commit caf86f7
Show file tree
Hide file tree
Showing 11 changed files with 79 additions and 29 deletions.
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ classifiers =

[options]
packages = find:
python_requires = >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
python_requires = >=3.5
install_requires =
importlib-metadata >= 0.12, <1;python_version<"3.8"
packaging >= 14
Expand Down
3 changes: 3 additions & 0 deletions src/tox/config/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,6 @@ def __iter__(self):

def __repr__(self):
return "{}(config_source={!r})".format(type(self).__name__, self._src)

def __contains__(self, item):
return item in self._envs
28 changes: 21 additions & 7 deletions src/tox/config/source/ini/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@
from ..api import EnvList, Loader, Source
from .convert import StrConvert
from .factor import filter_for_env, find_envs
from .replace import replace
from .replace import BASE_TEST_ENV, replace

BASE_TEST_ENV = "testenv"
TEST_ENV_PREFIX = "{}:".format(BASE_TEST_ENV)


Expand All @@ -28,6 +27,7 @@ def __init__(self, path: Path) -> None:
src=self,
name=None,
default_base=EnvList([]),
section_loader=self._get_section,
)
super().__init__(core)
self._envs = {} # type: Dict[str, IniLoader]
Expand Down Expand Up @@ -70,7 +70,9 @@ def get_section(self, item, name):
try:
return self._envs[item]
except KeyError:
loader = IniLoader(self._get_section(item), self, name, self.BASE_ENV_LIST)
loader = IniLoader(
self._get_section(item), self, name, self.BASE_ENV_LIST, self._get_section
)
self._envs[item] = loader
return loader

Expand Down Expand Up @@ -104,13 +106,19 @@ class IniLoader(Loader, StrConvert):
"""Load from a ini section"""

def __init__(
self, section: Optional[SectionProxy], src: Ini, name: Optional[str], default_base: EnvList
self,
section: Optional[SectionProxy],
src: Ini,
name: Optional[str],
default_base: EnvList,
section_loader,
) -> None:
super().__init__(name)
self._section = section # type:Optional[SectionProxy]
self._src = src # type: Ini
self._default_base = default_base # type:EnvList
self._base = [] # type:List[IniLoader]
self._section_loader = section_loader

def __deepcopy__(self, memo):
# python < 3.7 cannot copy config parser
Expand All @@ -127,10 +135,11 @@ def __deepcopy__(self, memo):
def setup_with_conf(self, conf: ConfigSet):
# noinspection PyUnusedLocal
def load_bases(values, conf_):
result = []
result = [] # type: List[IniLoader]
for value in values:
name = value.lstrip(TEST_ENV_PREFIX)
result.append(self._src.get_section(value, name))
ini_loader = self._src.get_section(value, name) # type: IniLoader
result.append(ini_loader)
return result

conf.add_config(
Expand Down Expand Up @@ -169,11 +178,16 @@ def _load_raw_from(self, as_name, conf, key):
raise KeyError(key)
value = self._section[key]
collapsed_newlines = value.replace("\\\n", "") # collapse explicit line splits
replace_executed = replace(collapsed_newlines, conf, as_name) # do replacements
replace_executed = replace(
collapsed_newlines, conf, as_name, self._section_loader
) # do replacements
factor_selected = filter_for_env(replace_executed, as_name) # select matching factors
# extend factors
return factor_selected

def get_value(self, section, key):
return self._section_loader(section)[key]

@property
def loaders(self):
yield self
Expand Down
19 changes: 13 additions & 6 deletions src/tox/config/source/ini/replace.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,24 @@
""",
re.VERBOSE,
)
BASE_TEST_ENV = "testenv"


def substitute_once(val, conf, name):
def substitute_once(val, conf, name, section_loader):
# noinspection PyTypeChecker
return RE_ITEM_REF.sub(partial(_replace_match, conf, name), val)
return RE_ITEM_REF.sub(partial(_replace_match, conf, name, section_loader), val)


def replace(value, conf, name):
def replace(value, conf, name, section_loader):
while True: # substitution found
expanded = substitute_once(value, conf, name)
expanded = substitute_once(value, conf, name, section_loader)
if expanded == value:
break
value = expanded
return expanded


def _replace_match(conf: Config, name, match):
def _replace_match(conf: Config, name, section_loader, match):
groups = match.groupdict()
sub_type = groups["sub_type"]
value = groups["substitution_value"]
Expand All @@ -50,10 +51,16 @@ def _replace_match(conf: Config, name, match):
if sub_type is not None:
key_missing_value = value
value = sub_type
else:
value = groups["key"]
section = groups["section"] or name
# noinspection PyBroadException
if section not in conf:
env_conf = section_loader(section)
else:
env_conf = conf[section]
try:
replace_value = conf[section][value]
replace_value = env_conf[value]
except Exception:
# noinspection PyBroadException
try:
Expand Down
2 changes: 1 addition & 1 deletion src/tox/session/cmd/run/single.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def run_one(tox_env: RunToxEnv, recreate: bool, no_test: bool) -> int:
try:
tox_env.setup()
except Recreate:
tox_env.clean(package_env=recreate)
tox_env.clean(package_env=False) # restart creation once, no package please
tox_env.setup()

code = run_commands(tox_env, no_test)
Expand Down
23 changes: 23 additions & 0 deletions src/tox/tox_env/package.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
from abc import ABC, abstractmethod
from typing import Any, List

from tox.config.sets import ConfigSet
from tox.execute.api import Execute
from tox.tox_env.errors import Recreate

from .api import ToxEnv


class PackageToxEnv(ToxEnv, ABC):
def __init__(self, conf: ConfigSet, core: ConfigSet, options, executor: Execute):
super().__init__(conf, core, options, executor)
self._cleaned = False
self._setup_done = False

def register_config(self):
super().register_config()

Expand All @@ -15,3 +24,17 @@ def get_package_dependencies(self, extras=None) -> List[Any]:
@abstractmethod
def perform_packaging(self) -> List[Any]:
raise NotImplementedError

def clean(self):
# package environments may be shared clean only once
if self._cleaned is False:
self._cleaned = True
super().clean()

def ensure_setup(self):
if self._setup_done is False:
try:
self.setup()
except Recreate:
self.clean()
self.setup()
8 changes: 1 addition & 7 deletions src/tox/tox_env/python/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from packaging.requirements import Requirement

from tox.tox_env.errors import Recreate, Skip
from tox.tox_env.errors import Skip

from ..runner import RunToxEnv
from .api import NoInterpreter, Python
Expand Down Expand Up @@ -49,12 +49,6 @@ def setup(self) -> None:
self.cached_install(self.conf["deps"], PythonRun.__name__, "deps")

if self.package_env is not None:
try:
self.package_env.setup()
except Recreate:
self.package_env.clean()
self.package_env.setup()

package_deps = self.package_env.get_package_dependencies(self.conf["extras"])
self.cached_install(package_deps, PythonRun.__name__, "package_deps")
self.install_package()
Expand Down
1 change: 1 addition & 0 deletions src/tox/tox_env/python/virtual_env/package/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ def get_package_dependencies(self, extras=None) -> List[Requirement]:

def _ensure_meta_present(self):
if self._distribution_meta is None:
self.ensure_setup()
self.meta_folder.mkdir(exist_ok=True)
cmd = [
"python",
Expand Down
1 change: 1 addition & 0 deletions src/tox/tox_env/python/virtual_env/package/artifact/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,6 @@ def _build_artifact(self) -> List[Path]:
def perform_packaging(self) -> List[Path]:
"""build_wheel/build_sdist"""
if self._package is None:
self.ensure_setup()
self._package = self._build_artifact()
return self._package
8 changes: 8 additions & 0 deletions tests/unit/config/ini/replace/test_replace_tox_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,11 @@ def test_replace_within_tox_env_missing_default_env_only(example):
env_config.add_config(keys="o", of_type=str, default="o", desc="o")
result = env_config["o"]
assert result == "one"


def test_replace_within_tox_env_from_base(example):
env_config = example("p = one\n[testenv:a]\no = {[testenv]p}")
env_config.add_config(keys="p", of_type=str, default="p", desc="p")
env_config.add_config(keys="o", of_type=str, default="o", desc="o")
result = env_config["o"]
assert result == "one"
13 changes: 6 additions & 7 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
[tox]
envlist =
py38
py37
py35
py37
py36
pypy3
coverage
fix_lint
docs
Expand Down Expand Up @@ -49,7 +48,7 @@ deps = twine >= 1.12.1
# TODO installing readme-renderer[md] should not be necessary
readme-renderer[md] >= 24.0
pip >= 18.0.0
skip_install = true
package = skip
extras =
commands = pip wheel -w {envtmpdir}/build --no-deps .
twine check {envtmpdir}/build/*
Expand All @@ -64,7 +63,7 @@ passenv = {[testenv]passenv}
extras = lint
deps =
pre-commit >= 1.14.4, < 2
skip_install = True
package = skip
commands = pre-commit run --all-files --show-diff-on-failure {posargs}
python -c 'import pathlib; print("hint: run {} install to add checks as pre-commit hook".format(pathlib.Path(r"{envdir}") / "bin" / "pre-commit"))'

Expand All @@ -75,7 +74,7 @@ description = [run locally after tests]: combine coverage data and create report
deps = {[testenv]deps}
coverage >= 4.4.1, < 5
diff_cover
skip_install = True
package = skip
passenv = {[testenv]passenv}
DIFF_AGAINST
setenv = COVERAGE_FILE={toxworkdir}/.coverage
Expand All @@ -92,7 +91,7 @@ parallel_show_output = True
# PYTHONPATH=.:$PYTHONPATH python3 -m tox -e exit_code
basepython = python3.7
description = commands with several exit codes
skip_install = True
package = skip
commands = python3.7 -c "import sys; sys.exit(139)"

[testenv:X]
Expand Down Expand Up @@ -160,7 +159,7 @@ commands = python {toxinidir}/tasks/release.py --version {posargs}
[testenv:notify]
description = notify people about the release of the library
basepython = python3.7
skip_install = true
package = skip
passenv = *
deps = gitpython >= 2.1.10
packaging >= 17.1
Expand Down

0 comments on commit caf86f7

Please sign in to comment.