diff --git a/src/api/json/catalog.json b/src/api/json/catalog.json index ebcffee18d3..5ae6e5ef25c 100644 --- a/src/api/json/catalog.json +++ b/src/api/json/catalog.json @@ -6351,6 +6351,12 @@ "fileMatch": ["tombi.toml", "**/tombi/config.toml"], "url": "https://www.schemastore.org/tombi.json" }, + { + "name": "tox", + "description": "tox configuration for automating Python testing and task management", + "fileMatch": ["tox.toml"], + "url": "https://raw.githubusercontent.com/tox-dev/tox/main/src/tox/tox.schema.json" + }, { "name": "TextMate Grammar", "description": "Language grammar description files for TextMate and compatible editors", diff --git a/src/negative_test/tox/tox-invalid-type.toml b/src/negative_test/tox/tox-invalid-type.toml new file mode 100644 index 00000000000..ffe9558c590 --- /dev/null +++ b/src/negative_test/tox/tox-invalid-type.toml @@ -0,0 +1,2 @@ +#:schema ../../schemas/json/tox.json +env_list = 42 diff --git a/src/schema-validation.jsonc b/src/schema-validation.jsonc index 003dfae688f..76f83095ccb 100644 --- a/src/schema-validation.jsonc +++ b/src/schema-validation.jsonc @@ -328,6 +328,7 @@ "partial-poetry.json", // pyproject.json[tool.poetry] "partial-repo-review.json", // pyproject.json[tool.repo-review] "partial-tox.json", // pyproject.json[tool.tox] + "tox.json", "partial-eslint-plugins.json", // eslintrc.json[rules.*] "partial-fusion-pack-metadata.json", // minecraft-pack-mcmeta.json[fusion] "partial-fusion-texture-metadata.json", // minecraft-texture-mcmeta.json[fusion] @@ -1096,6 +1097,9 @@ "partial-pdm.json": { "externalSchema": ["partial-pdm-dockerize.json"] }, + "partial-tox.json": { + "externalSchema": ["tox.json"] + }, "partial-poetry.json": { "externalSchema": ["base.json"] }, @@ -1182,6 +1186,7 @@ "partial-setuptools-scm.json", "partial-taskipy.json", "partial-tox.json", + "tox.json", "poetry.json", "ruff.json", "tombi.json", diff --git a/src/schemas/json/partial-tox.json b/src/schemas/json/partial-tox.json index f2fb0db0d13..77526f1f046 100644 --- a/src/schemas/json/partial-tox.json +++ b/src/schemas/json/partial-tox.json @@ -4,7 +4,11 @@ "title": "Tox configuration in pyproject.toml", "description": "Schema for the [tool.tox] section in pyproject.toml", "type": "object", - "additionalProperties": true, + "allOf": [ + { + "$ref": "https://json.schemastore.org/tox.json" + } + ], "properties": { "legacy_tox_ini": { "type": "string", diff --git a/src/schemas/json/tox.json b/src/schemas/json/tox.json new file mode 100644 index 00000000000..ceaed5ee529 --- /dev/null +++ b/src/schemas/json/tox.json @@ -0,0 +1,706 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://json.schemastore.org/tox.json", + "title": "tox configuration", + "description": "tox configuration file (tox.toml or [tool.tox] in pyproject.toml)", + "x-taplo": { + "links": { + "key": "https://tox.wiki/en/stable/config.html" + } + }, + "type": "object", + "properties": { + "tox_root": { + "type": "string", + "description": "the root directory (where the configuration file is found)" + }, + "toxinidir": { + "$ref": "#/properties/tox_root", + "description": "Deprecated: use 'tox_root' instead", + "deprecated": true + }, + "work_dir": { + "type": "string", + "description": "working directory" + }, + "toxworkdir": { + "$ref": "#/properties/work_dir", + "description": "Deprecated: use 'work_dir' instead", + "deprecated": true + }, + "temp_dir": { + "type": "string", + "description": "a folder for temporary files (is not cleaned at start)" + }, + "env_list": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/definitions/subs" + }, + { + "type": "object", + "required": ["product"], + "properties": { + "product": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "object", + "required": ["prefix"], + "properties": { + "prefix": { + "type": "string" + }, + "start": { + "type": "integer" + }, + "stop": { + "type": "integer" + } + }, + "additionalProperties": false + } + ] + }, + "description": "factor groups for cartesian product expansion" + }, + "exclude": { + "type": "array", + "items": { + "type": "string" + }, + "description": "environment names to exclude from product" + } + }, + "additionalProperties": false + } + ] + }, + "description": "define environments to automatically run" + }, + "envlist": { + "$ref": "#/properties/env_list", + "description": "Deprecated: use 'env_list' instead", + "deprecated": true + }, + "base": { + "type": "array", + "items": { + "$ref": "#/definitions/subs" + }, + "description": "inherit missing keys from these sections" + }, + "min_version": { + "type": "string", + "description": "Define the minimal tox version required to run" + }, + "minversion": { + "$ref": "#/properties/min_version", + "description": "Deprecated: use 'min_version' instead", + "deprecated": true + }, + "provision_tox_env": { + "type": "string", + "description": "Name of the virtual environment used to provision a tox." + }, + "requires": { + "type": "array", + "items": { + "$ref": "#/definitions/subs" + }, + "description": "Name of the virtual environment used to provision a tox." + }, + "labels": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/definitions/subs" + }, + { + "type": "object", + "required": ["product"], + "properties": { + "product": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "object", + "required": ["prefix"], + "properties": { + "prefix": { + "type": "string" + }, + "start": { + "type": "integer" + }, + "stop": { + "type": "integer" + } + }, + "additionalProperties": false + } + ] + }, + "description": "factor groups for cartesian product expansion" + }, + "exclude": { + "type": "array", + "items": { + "type": "string" + }, + "description": "environment names to exclude from product" + } + }, + "additionalProperties": false + } + ] + } + }, + "description": "core labels" + }, + "ignore_base_python_conflict": { + "type": "boolean", + "description": "do not raise error if the environment name conflicts with base python" + }, + "ignore_basepython_conflict": { + "$ref": "#/properties/ignore_base_python_conflict", + "description": "Deprecated: use 'ignore_base_python_conflict' instead", + "deprecated": true + }, + "skip_missing_interpreters": { + "type": "boolean", + "description": "skip running missing interpreters" + }, + "no_package": { + "type": "boolean", + "description": "is there any packaging involved in this project" + }, + "skipsdist": { + "$ref": "#/properties/no_package", + "description": "Deprecated: use 'no_package' instead", + "deprecated": true + }, + "package_env": { + "type": "string", + "description": "tox environment used to package" + }, + "isolated_build_env": { + "$ref": "#/properties/package_env", + "description": "Deprecated: use 'package_env' instead", + "deprecated": true + }, + "package_root": { + "type": "string", + "description": "indicates where the packaging root file exists (historically setup.py file or pyproject.toml now)" + }, + "setupdir": { + "$ref": "#/properties/package_root", + "description": "Deprecated: use 'package_root' instead", + "deprecated": true + }, + "env_run_base": { + "type": "object", + "description": "base configuration for run environments", + "x-taplo": { + "links": { + "key": "https://tox.wiki/en/stable/config.html#run-environment" + } + }, + "properties": { + "set_env": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/subs" + }, + "description": "environment variables to set when running commands in the tox environment" + }, + "setenv": { + "$ref": "#/properties/env_run_base/properties/set_env", + "description": "Deprecated: use 'set_env' instead", + "deprecated": true + }, + "base": { + "type": "array", + "items": { + "$ref": "#/definitions/subs" + }, + "description": "inherit missing keys from these sections" + }, + "runner": { + "type": "string", + "description": "the tox execute used to evaluate this environment" + }, + "description": { + "type": "string", + "description": "description attached to the tox environment" + }, + "depends": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/definitions/subs" + }, + { + "type": "object", + "required": ["product"], + "properties": { + "product": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "object", + "required": ["prefix"], + "properties": { + "prefix": { + "type": "string" + }, + "start": { + "type": "integer" + }, + "stop": { + "type": "integer" + } + }, + "additionalProperties": false + } + ] + }, + "description": "factor groups for cartesian product expansion" + }, + "exclude": { + "type": "array", + "items": { + "type": "string" + }, + "description": "environment names to exclude from product" + } + }, + "additionalProperties": false + } + ] + }, + "description": "tox environments that this environment depends on (must be run after those)" + }, + "labels": { + "type": "array", + "items": { + "$ref": "#/definitions/subs" + }, + "description": "labels attached to the tox environment" + }, + "env_dir": { + "type": "string", + "description": "directory assigned to the tox environment" + }, + "envdir": { + "$ref": "#/properties/env_run_base/properties/env_dir", + "description": "Deprecated: use 'env_dir' instead", + "deprecated": true + }, + "env_tmp_dir": { + "type": "string", + "description": "a folder that is always reset at the start of the run" + }, + "envtmpdir": { + "$ref": "#/properties/env_run_base/properties/env_tmp_dir", + "description": "Deprecated: use 'env_tmp_dir' instead", + "deprecated": true + }, + "env_log_dir": { + "type": "string", + "description": "a folder for logging where tox will put logs of tool invocation" + }, + "envlogdir": { + "$ref": "#/properties/env_run_base/properties/env_log_dir", + "description": "Deprecated: use 'env_log_dir' instead", + "deprecated": true + }, + "suicide_timeout": { + "type": "number", + "description": "timeout to allow process to exit before sending SIGINT" + }, + "interrupt_timeout": { + "type": "number", + "description": "timeout before sending SIGTERM after SIGINT" + }, + "terminate_timeout": { + "type": "number", + "description": "timeout before sending SIGKILL after SIGTERM" + }, + "platform": { + "type": "string", + "description": "run on platforms that match this regular expression (empty means any platform)" + }, + "pass_env": { + "type": "array", + "items": { + "$ref": "#/definitions/subs" + }, + "description": "environment variables to pass on to the tox environment" + }, + "passenv": { + "$ref": "#/properties/env_run_base/properties/pass_env", + "description": "Deprecated: use 'pass_env' instead", + "deprecated": true + }, + "disallow_pass_env": { + "type": "array", + "items": { + "$ref": "#/definitions/subs" + }, + "description": "environment variable patterns to exclude after pass_env glob expansion" + }, + "parallel_show_output": { + "type": "boolean", + "description": "if set to True the content of the output will always be shown when running in parallel mode" + }, + "recreate": { + "type": "boolean", + "description": "always recreate virtual environment if this option is true, otherwise leave it up to tox" + }, + "allowlist_externals": { + "type": "array", + "items": { + "$ref": "#/definitions/subs" + }, + "description": "external command glob to allow calling" + }, + "list_dependencies_command": { + "type": "array", + "items": { + "$ref": "#/definitions/subs" + }, + "description": "command used to list installed packages" + }, + "pip_pre": { + "type": "boolean", + "description": "install the latest available pre-release (alpha/beta/rc) of dependencies without a specified version" + }, + "install_command": { + "type": "array", + "items": { + "$ref": "#/definitions/subs" + }, + "description": "command used to install packages" + }, + "constraints": { + "type": "string", + "description": "constraints to apply to installed python dependencies" + }, + "constrain_package_deps": { + "type": "boolean", + "description": "If true, apply constraints during install_package_deps." + }, + "use_frozen_constraints": { + "type": "boolean", + "description": "Use the exact versions of installed deps as constraints, otherwise use the listed deps." + }, + "commands_pre": { + "type": "array", + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/subs" + } + }, + "description": "the commands to be called before testing" + }, + "commands": { + "type": "array", + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/subs" + } + }, + "description": "the commands to be called for testing" + }, + "commands_post": { + "type": "array", + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/subs" + } + }, + "description": "the commands to be called after testing" + }, + "recreate_commands": { + "type": "array", + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/subs" + } + }, + "description": "commands to run before the environment is removed during recreation (e.g. cache cleanup)" + }, + "change_dir": { + "type": "string", + "description": "change to this working directory when executing the test command" + }, + "changedir": { + "$ref": "#/properties/env_run_base/properties/change_dir", + "description": "Deprecated: use 'change_dir' instead", + "deprecated": true + }, + "args_are_paths": { + "type": "boolean", + "description": "if True rewrite relative posargs paths from cwd to change_dir" + }, + "ignore_errors": { + "type": "boolean", + "description": "when executing the commands keep going even if a sub-command exits with non-zero exit code" + }, + "commands_retry": { + "type": "integer", + "minimum": 0, + "description": "number of times to retry a failed command (0 means no retries)" + }, + "ignore_outcome": { + "type": "boolean", + "description": "if set to true a failing result of this testenv will not make tox fail (instead just warn)" + }, + "fail_fast": { + "type": "boolean", + "description": "if set to true, tox will stop executing remaining environments when this environment fails" + }, + "default_base_python": { + "type": "array", + "items": { + "$ref": "#/definitions/subs" + }, + "description": "fallback python interpreter used when no factor or explicit base_python is defined" + }, + "base_python": { + "type": "array", + "items": { + "$ref": "#/definitions/subs" + }, + "description": "environment identifier for python, first one found wins" + }, + "basepython": { + "$ref": "#/properties/env_run_base/properties/base_python", + "description": "Deprecated: use 'base_python' instead", + "deprecated": true + }, + "deps": { + "type": "string", + "description": "python dependencies with optional version specifiers, as specified by PEP-440" + }, + "dependency_groups": { + "type": "array", + "items": { + "$ref": "#/definitions/subs" + }, + "description": "dependency groups to install of the target package" + }, + "extras": { + "type": "array", + "items": { + "$ref": "#/definitions/subs" + }, + "description": "extras to install of the target package" + }, + "pylock": { + "type": "string", + "description": "PEP 751 pylock.toml lock file path to install locked dependencies from" + }, + "extra_setup_commands": { + "type": "array", + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/subs" + } + }, + "description": "commands to execute after setup (deps and package install) but before test commands" + }, + "skip_missing_interpreters": { + "type": "boolean", + "description": "override core skip_missing_interpreters for this environment" + }, + "system_site_packages": { + "type": "boolean", + "description": "create virtual environments that also have access to globally installed packages." + }, + "sitepackages": { + "$ref": "#/properties/env_run_base/properties/system_site_packages", + "description": "Deprecated: use 'system_site_packages' instead", + "deprecated": true + }, + "always_copy": { + "type": "boolean", + "description": "force virtualenv to always copy rather than symlink" + }, + "alwayscopy": { + "$ref": "#/properties/env_run_base/properties/always_copy", + "description": "Deprecated: use 'always_copy' instead", + "deprecated": true + }, + "download": { + "type": "boolean", + "description": "true if you want virtualenv to upgrade pip/wheel/setuptools to the latest version" + }, + "virtualenv_spec": { + "type": "string", + "description": "PEP 440 version spec for virtualenv (e.g. virtualenv<20.22.0). When set, tox bootstraps this version in an isolated environment and runs it via subprocess, enabling Python versions incompatible with the installed virtualenv." + }, + "skip_install": { + "type": "boolean", + "description": "skip installation" + }, + "use_develop": { + "type": "boolean", + "description": "use develop mode" + }, + "usedevelop": { + "$ref": "#/properties/env_run_base/properties/use_develop", + "description": "Deprecated: use 'use_develop' instead", + "deprecated": true + }, + "package": { + "type": "string", + "description": "package installation mode - wheel | sdist | sdist-wheel | editable | editable-legacy | deps-only | skip | external " + }, + "package_env": { + "type": "string", + "description": "tox environment used to package" + } + }, + "additionalProperties": true + }, + "env_pkg_base": { + "$ref": "#/properties/env_run_base", + "type": "object", + "description": "base configuration for packaging environments", + "x-taplo": { + "links": { + "key": "https://tox.wiki/en/stable/config.html#packaging-environment" + } + }, + "additionalProperties": true + }, + "env": { + "type": "object", + "description": "per-environment overrides (keyed by environment name)", + "x-taplo": { + "links": { + "key": "https://tox.wiki/en/stable/config.html#run-environment" + } + }, + "patternProperties": { + "^.*$": { + "$ref": "#/properties/env_run_base" + } + } + }, + "legacy_tox_ini": { + "type": "string", + "description": "tox configuration in INI format embedded in a TOML file", + "x-taplo": { + "links": { + "key": "https://tox.wiki/en/stable/config.html#pyproject-toml-ini" + } + } + } + }, + "additionalProperties": true, + "definitions": { + "subs": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "replace": { + "type": "string" + }, + "name": { + "type": "string" + }, + "default": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "$ref": "#/definitions/subs" + } + } + ] + }, + "extend": { + "type": "boolean" + } + }, + "required": ["replace"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "replace": { + "type": "string" + }, + "of": { + "type": "array", + "items": { + "type": "string" + } + }, + "default": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "$ref": "#/definitions/subs" + } + } + ] + }, + "extend": { + "type": "boolean" + } + }, + "required": ["replace", "of"], + "additionalProperties": false + } + ] + } + } +} diff --git a/src/test/pyproject/tox-toml-config.toml b/src/test/pyproject/tox-toml-config.toml new file mode 100644 index 00000000000..9d08b9e64c3 --- /dev/null +++ b/src/test/pyproject/tox-toml-config.toml @@ -0,0 +1,9 @@ +#:schema ../../schemas/json/pyproject.json +[tool.tox] +env_list = ["py"] +no_package = true + +[tool.tox.env_run_base] +description = "run tests" +deps = "pytest" +commands = [["python", "-m", "pytest"]] diff --git a/src/test/tox/tox-full.toml b/src/test/tox/tox-full.toml new file mode 100644 index 00000000000..e4a8bf128dd --- /dev/null +++ b/src/test/tox/tox-full.toml @@ -0,0 +1,15 @@ +#:schema ../../schemas/json/tox.json +env_list = ["py", "lint"] +min_version = "4.0" +no_package = true + +[env_run_base] +description = "run tests" +deps = "pytest" +commands = [["python", "-m", "pytest"]] +pass_env = ["HOME", "CI"] +set_env = { PYTHONDONTWRITEBYTECODE = "1" } + +[env.lint] +description = "run linters" +commands = [["python", "-m", "flake8"]] diff --git a/src/test/tox/tox-minimal.toml b/src/test/tox/tox-minimal.toml new file mode 100644 index 00000000000..bd50849b3e2 --- /dev/null +++ b/src/test/tox/tox-minimal.toml @@ -0,0 +1,2 @@ +#:schema ../../schemas/json/tox.json +env_list = ["py"] diff --git a/src/test/tox/tox-product.toml b/src/test/tox/tox-product.toml new file mode 100644 index 00000000000..b1b8639e63d --- /dev/null +++ b/src/test/tox/tox-product.toml @@ -0,0 +1,8 @@ +#:schema ../../schemas/json/tox.json +env_list = [ + { product = [["py39", "py310"], ["django42", "django50"]], exclude = ["py39-django50"] } +] +no_package = true + +[env_run_base] +commands = [["python", "-m", "pytest"]]