Skip to content

Commit

Permalink
fix packaging
Browse files Browse the repository at this point in the history
  • Loading branch information
gaborbernat committed Aug 22, 2019
1 parent de90910 commit 5552503
Show file tree
Hide file tree
Showing 19 changed files with 118 additions and 57 deletions.
3 changes: 0 additions & 3 deletions docs/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -967,7 +967,4 @@ Other Rules and notes
cli
===

.. autoprogram:: tox.cli:cli
:prog: tox

.. include:: links.rst
15 changes: 2 additions & 13 deletions docs/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -187,22 +187,11 @@ You can and publish it like:
Hook specifications and related API
-----------------------------------

.. automodule:: tox.hookspecs
.. automodule:: tox.plugin.spec
:members:

.. autoclass:: tox.config.Parser()
.. autoclass:: tox.config.sets.ConfigSet
:members:

.. autoclass:: tox.config.Config()
:members:

.. autoclass:: tox.config.TestenvConfig()
:members:

.. autoclass:: tox.venv.VirtualEnv()
:members:

.. autoclass:: tox.session.Session()
:members:

.. include:: links.rst
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/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .version import __version__

__all__ = ("__version__",)
3 changes: 3 additions & 0 deletions src/tox/config/cli/for_docs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .parse import _get_core_parser

parser = _get_core_parser()
12 changes: 8 additions & 4 deletions src/tox/config/cli/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,16 @@ def _get_base(args):


def _get_core(args):
tox_parser = _get_core_parser()
parsed, unknown = tox_parser.parse(args)
handlers = {k: p for k, (_, p) in tox_parser.handlers.items()}
return handlers, parsed, unknown


def _get_core_parser():
tox_parser = ToxParser.core()
# noinspection PyUnresolvedReferences
from tox.plugin.manager import MANAGER

MANAGER.tox_add_option(tox_parser)
tox_parser.fix_defaults()
parsed, unknown = tox_parser.parse(args)
handlers = {k: p for k, (_, p) in tox_parser.handlers.items()}
return handlers, parsed, unknown
return tox_parser
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
11 changes: 11 additions & 0 deletions src/tox/config/sets.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,17 @@ def add_config(
post_process=None,
overwrite=False,
):
"""
Add configuration.
:param keys:
:param of_type:
:param default:
:param desc:
:param post_process:
:param overwrite:
:return:
"""
keys_ = self._make_keys(keys)
for key in keys_:
if key in self._defined and overwrite is False:
Expand Down
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/list_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def list_env(state: State):

if not option.list_quiet and default:
print("default environments:")
max_length = max(len(env) for env in (default + extra))
max_length = max(len(env) for env in (default.envs + extra))

def report_env(name: str):
if not option.list_quiet:
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()
3 changes: 2 additions & 1 deletion src/tox/tox_env/python/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ def cached_install(self, deps, section, of_type):
if missing: # no way yet to know what to uninstall here (transitive dependencies?)
# bail out and force recreate
raise Recreate()
new_deps = [Requirement(i) for i in (set(conf_deps) - set(old))]
new_deps_str = set(conf_deps) - set(old)
new_deps = [Requirement(i) for i in new_deps_str]
self.install_python_packages(packages=new_deps)

@abstractmethod
Expand Down
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
12 changes: 8 additions & 4 deletions src/tox/tox_env/python/virtual_env/package/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ def get_package_dependencies(self, extras=None) -> List[Requirement]:
if key == "Requires-Dist":
req = Requirement(v)
markers = getattr(req.marker, "_markers", tuple()) or tuple()
for _at, (m_key, op, m_val) in enumerate(
i for i in markers if isinstance(i, tuple) and len(i) == 3
for _at, (m_key, op, m_val) in (
(j, i) for j, i in enumerate(markers) if isinstance(i, tuple) and len(i) == 3
):
if m_key.value == "extra" and op.value == "==":
extra = m_val.value
Expand All @@ -117,15 +117,19 @@ def get_package_dependencies(self, extras=None) -> List[Requirement]:
if extra is None or extra in extras:
if _at is not None:
# noinspection PyProtectedMember
del req.marker._markers[_at]
del markers[_at]
_at -= 1
if _at > 0 and markers[_at] in ("and", "or"):
del markers[_at]
# noinspection PyProtectedMember
if len(req.marker._markers) == 0:
if len(markers) == 0:
req.marker = None
result.append(req)
return result

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"
Loading

0 comments on commit 5552503

Please sign in to comment.