Skip to content

Commit

Permalink
First implementation of tox_to_nox for tox 4
Browse files Browse the repository at this point in the history
  • Loading branch information
frenzymadness committed Jan 24, 2023
1 parent 1fe4414 commit d2d1ce2
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 8 deletions.
34 changes: 34 additions & 0 deletions nox/tox4_to_nox.jinja2
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import nox

{% for envname, envconfig in config.items()|sort: %}
@nox.session({%- if envconfig.base_python %}python='{{envconfig.base_python}}'{%- endif %})
def {{fixname(envname)}}(session):
{%- if envconfig.description != '' %}
"""{{envconfig.description}}"""
{%- endif %}
{%- set envs = envconfig.get('set_env', {}) -%}
{%- for key, value in envs.items()|sort: %}
session.env['{{key}}'] = '{{value}}'
{%- endfor %}

{%- if envconfig.deps %}
session.install({{wrapjoin(envconfig.deps)}})
{%- endif %}

{%- if not envconfig.skip_install %}
{%- if envconfig.use_develop %}
session.install('-e', '.')
{%- else %}
session.install('.')
{%- endif -%}
{%- endif %}

{#- TODO: implement session.chdir -#}
{%- if envconfig.changedir and config.toxinidir.bestrelpath(envconfig.changedir) != '.' %}
session.chdir('{{config.toxinidir.bestrelpath(envconfig.changedir)}}')
{%- endif %}

{%- for command in envconfig.commands %}
session.run('{{command}}')
{%- endfor %}
{% endfor %}
55 changes: 48 additions & 7 deletions nox/tox_to_nox.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,31 @@
from typing import Any, Iterator

import jinja2
import tox.config
from tox import __version__ as TOX_VERSION

_TEMPLATE = jinja2.Template(
pkgutil.get_data(__name__, "tox_to_nox.jinja2").decode("utf-8"), # type: ignore[union-attr]
extensions=["jinja2.ext.do"],
)
TOX3 = TOX_VERSION[0] == "3"

if TOX3:
import tox.config
_TEMPLATE = jinja2.Template(
pkgutil.get_data(__name__, "tox_to_nox.jinja2").decode("utf-8"), # type: ignore[union-attr]
extensions=["jinja2.ext.do"],
)
else:
from subprocess import check_output
from configparser import ConfigParser
_TEMPLATE = jinja2.Template(
pkgutil.get_data(__name__, "tox4_to_nox.jinja2").decode("utf-8"), # type: ignore[union-attr]
extensions=["jinja2.ext.do"],
)


def wrapjoin(seq: Iterator[Any]) -> str:
return ", ".join([f"'{item}'" for item in seq])


def fixname(envname: str) -> str:
envname = envname.replace("-", "_")
envname = envname.replace("-", "_").replace(":", "_")
if not envname.isidentifier():
print(
f"Environment {envname!r} is not a valid nox session name.\n"
Expand All @@ -49,7 +60,37 @@ def main() -> None:

args = parser.parse_args()

config = tox.config.parseconfig([])
if TOX3:
config = tox.config.parseconfig([])
else:
output = check_output(["tox", "config"], text=True)
original_config = ConfigParser()
original_config.read_string(output)
config = {}

for name, section in original_config.items():
config[name] = dict(section)
# Convert set_env from string to dict
set_env = {}
for var in section.get("set_env", "").strip().splitlines():
k, v = var.split("=")
if k not in ("PYTHONHASHSEED", "TOX_ENV_DIR", "TOX_ENV_NAME"):
set_env[k] = v

if set_env:
config[name]["set_env"] = set_env

for option in "deps", "commands":
if isinstance(config[name].get(option), str):
config[name][option] = config[name][option].strip().splitlines()

for option in "skip_install", "use_develop":
if config[name].get(option):
if config[name][option] == "False":
config[name][option] = False
else:
config[name][option] = True

output = _TEMPLATE.render(config=config, wrapjoin=wrapjoin, fixname=fixname)

with open(args.output, "w") as outfile:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ classifiers = [
[project.optional-dependencies]
tox_to_nox = [
"jinja2",
"tox<4",
"tox",
]

[project.urls]
Expand Down

0 comments on commit d2d1ce2

Please sign in to comment.