mirror of https://github.com/pypa/hatch.git
508 lines
19 KiB
Python
508 lines
19 KiB
Python
import json
|
|
import os
|
|
|
|
import pytest
|
|
|
|
from hatch.env.utils import get_env_var
|
|
from hatch.project.core import Project
|
|
from hatch.utils.structures import EnvVars
|
|
from hatchling.utils.constants import DEFAULT_CONFIG_FILE
|
|
|
|
|
|
@pytest.fixture(scope='module', autouse=True)
|
|
def _terminal_width():
|
|
with EnvVars({'COLUMNS': '200'}, exclude=[get_env_var(plugin_name='virtual', option='uv_path')]):
|
|
yield
|
|
|
|
|
|
def test_default(hatch, helpers, temp_dir, config_file):
|
|
config_file.model.template.plugins['default']['tests'] = False
|
|
config_file.save()
|
|
|
|
project_name = 'My.App'
|
|
|
|
with temp_dir.as_cwd():
|
|
result = hatch('new', project_name)
|
|
|
|
assert result.exit_code == 0, result.output
|
|
|
|
project_path = temp_dir / 'my-app'
|
|
data_path = temp_dir / 'data'
|
|
data_path.mkdir()
|
|
|
|
with project_path.as_cwd():
|
|
result = hatch('env', 'show', '--ascii')
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert helpers.remove_trailing_spaces(result.output) == helpers.dedent(
|
|
"""
|
|
Standalone
|
|
+---------+---------+
|
|
| Name | Type |
|
|
+=========+=========+
|
|
| default | virtual |
|
|
+---------+---------+
|
|
"""
|
|
)
|
|
|
|
|
|
def test_default_as_json(hatch, temp_dir, config_file):
|
|
config_file.model.template.plugins['default']['tests'] = False
|
|
config_file.save()
|
|
|
|
project_name = 'My.App'
|
|
|
|
with temp_dir.as_cwd():
|
|
result = hatch('new', project_name)
|
|
|
|
assert result.exit_code == 0, result.output
|
|
|
|
project_path = temp_dir / 'my-app'
|
|
data_path = temp_dir / 'data'
|
|
data_path.mkdir()
|
|
|
|
with project_path.as_cwd():
|
|
result = hatch('env', 'show', '--json')
|
|
|
|
assert result.exit_code == 0, result.output
|
|
|
|
environments = json.loads(result.output)
|
|
assert list(environments) == [
|
|
'default',
|
|
'hatch-build',
|
|
'hatch-static-analysis',
|
|
'hatch-test.py3.13',
|
|
'hatch-test.py3.12',
|
|
'hatch-test.py3.11',
|
|
'hatch-test.py3.10',
|
|
'hatch-test.py3.9',
|
|
'hatch-test.py3.8',
|
|
'hatch-uv',
|
|
]
|
|
assert environments['default'] == {'type': 'virtual'}
|
|
|
|
|
|
def test_single_only(hatch, helpers, temp_dir, config_file):
|
|
config_file.model.template.plugins['default']['tests'] = False
|
|
config_file.save()
|
|
|
|
project_name = 'My.App'
|
|
|
|
with temp_dir.as_cwd():
|
|
result = hatch('new', project_name)
|
|
|
|
assert result.exit_code == 0, result.output
|
|
|
|
project_path = temp_dir / 'my-app'
|
|
data_path = temp_dir / 'data'
|
|
data_path.mkdir()
|
|
|
|
project = Project(project_path)
|
|
helpers.update_project_environment(project, 'foo', {})
|
|
helpers.update_project_environment(project, 'bar', {})
|
|
|
|
with project_path.as_cwd():
|
|
result = hatch('env', 'show', '--ascii')
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert helpers.remove_trailing_spaces(result.output) == helpers.dedent(
|
|
"""
|
|
Standalone
|
|
+---------+---------+
|
|
| Name | Type |
|
|
+=========+=========+
|
|
| default | virtual |
|
|
+---------+---------+
|
|
| foo | virtual |
|
|
+---------+---------+
|
|
| bar | virtual |
|
|
+---------+---------+
|
|
"""
|
|
)
|
|
|
|
|
|
def test_single_and_matrix(hatch, helpers, temp_dir, config_file):
|
|
config_file.model.template.plugins['default']['tests'] = False
|
|
config_file.save()
|
|
|
|
project_name = 'My.App'
|
|
|
|
with temp_dir.as_cwd():
|
|
result = hatch('new', project_name)
|
|
|
|
assert result.exit_code == 0, result.output
|
|
|
|
project_path = temp_dir / 'my-app'
|
|
data_path = temp_dir / 'data'
|
|
data_path.mkdir()
|
|
|
|
project = Project(project_path)
|
|
helpers.update_project_environment(project, 'foo', {'matrix': [{'version': ['9000', '3.14'], 'py': ['39', '310']}]})
|
|
|
|
with project_path.as_cwd():
|
|
result = hatch('env', 'show', '--ascii')
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert helpers.remove_trailing_spaces(result.output) == helpers.dedent(
|
|
"""
|
|
Standalone
|
|
+---------+---------+
|
|
| Name | Type |
|
|
+=========+=========+
|
|
| default | virtual |
|
|
+---------+---------+
|
|
Matrices
|
|
+------+---------+----------------+
|
|
| Name | Type | Envs |
|
|
+======+=========+================+
|
|
| foo | virtual | foo.py39-9000 |
|
|
| | | foo.py39-3.14 |
|
|
| | | foo.py310-9000 |
|
|
| | | foo.py310-3.14 |
|
|
+------+---------+----------------+
|
|
"""
|
|
)
|
|
|
|
|
|
def test_default_matrix_only(hatch, helpers, temp_dir, config_file):
|
|
config_file.model.template.plugins['default']['tests'] = False
|
|
config_file.save()
|
|
|
|
project_name = 'My.App'
|
|
|
|
with temp_dir.as_cwd():
|
|
result = hatch('new', project_name)
|
|
|
|
assert result.exit_code == 0, result.output
|
|
|
|
project_path = temp_dir / 'my-app'
|
|
data_path = temp_dir / 'data'
|
|
data_path.mkdir()
|
|
|
|
project = Project(project_path)
|
|
helpers.update_project_environment(
|
|
project, 'default', {'matrix': [{'version': ['9000', '3.14'], 'py': ['39', '310']}]}
|
|
)
|
|
|
|
with project_path.as_cwd():
|
|
result = hatch('env', 'show', '--ascii')
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert helpers.remove_trailing_spaces(result.output) == helpers.dedent(
|
|
"""
|
|
Matrices
|
|
+---------+---------+------------+
|
|
| Name | Type | Envs |
|
|
+=========+=========+============+
|
|
| default | virtual | py39-9000 |
|
|
| | | py39-3.14 |
|
|
| | | py310-9000 |
|
|
| | | py310-3.14 |
|
|
+---------+---------+------------+
|
|
"""
|
|
)
|
|
|
|
|
|
def test_all_matrix_types_with_single(hatch, helpers, temp_dir, config_file):
|
|
config_file.model.template.plugins['default']['tests'] = False
|
|
config_file.save()
|
|
|
|
project_name = 'My.App'
|
|
|
|
with temp_dir.as_cwd():
|
|
result = hatch('new', project_name)
|
|
|
|
assert result.exit_code == 0, result.output
|
|
|
|
project_path = temp_dir / 'my-app'
|
|
data_path = temp_dir / 'data'
|
|
data_path.mkdir()
|
|
|
|
project = Project(project_path)
|
|
helpers.update_project_environment(
|
|
project, 'default', {'matrix': [{'version': ['9000', '3.14'], 'py': ['39', '310']}]}
|
|
)
|
|
helpers.update_project_environment(project, 'foo', {'matrix': [{'version': ['9000', '3.14'], 'py': ['39', '310']}]})
|
|
helpers.update_project_environment(project, 'bar', {})
|
|
|
|
with project_path.as_cwd():
|
|
result = hatch('env', 'show', '--ascii')
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert helpers.remove_trailing_spaces(result.output) == helpers.dedent(
|
|
"""
|
|
Standalone
|
|
+------+---------+
|
|
| Name | Type |
|
|
+======+=========+
|
|
| bar | virtual |
|
|
+------+---------+
|
|
Matrices
|
|
+---------+---------+----------------+
|
|
| Name | Type | Envs |
|
|
+=========+=========+================+
|
|
| default | virtual | py39-9000 |
|
|
| | | py39-3.14 |
|
|
| | | py310-9000 |
|
|
| | | py310-3.14 |
|
|
+---------+---------+----------------+
|
|
| foo | virtual | foo.py39-9000 |
|
|
| | | foo.py39-3.14 |
|
|
| | | foo.py310-9000 |
|
|
| | | foo.py310-3.14 |
|
|
+---------+---------+----------------+
|
|
"""
|
|
)
|
|
|
|
|
|
def test_specific(hatch, helpers, temp_dir, config_file):
|
|
config_file.model.template.plugins['default']['tests'] = False
|
|
config_file.save()
|
|
|
|
project_name = 'My.App'
|
|
|
|
with temp_dir.as_cwd():
|
|
result = hatch('new', project_name)
|
|
|
|
assert result.exit_code == 0, result.output
|
|
|
|
project_path = temp_dir / 'my-app'
|
|
data_path = temp_dir / 'data'
|
|
data_path.mkdir()
|
|
|
|
project = Project(project_path)
|
|
helpers.update_project_environment(project, 'foo', {})
|
|
helpers.update_project_environment(project, 'bar', {})
|
|
|
|
with project_path.as_cwd():
|
|
result = hatch('env', 'show', 'bar', 'foo', '--ascii')
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert helpers.remove_trailing_spaces(result.output) == helpers.dedent(
|
|
"""
|
|
Standalone
|
|
+------+---------+
|
|
| Name | Type |
|
|
+======+=========+
|
|
| foo | virtual |
|
|
+------+---------+
|
|
| bar | virtual |
|
|
+------+---------+
|
|
"""
|
|
)
|
|
|
|
|
|
def test_specific_unknown(hatch, helpers, temp_dir, config_file):
|
|
config_file.model.template.plugins['default']['tests'] = False
|
|
config_file.save()
|
|
|
|
project_name = 'My.App'
|
|
|
|
with temp_dir.as_cwd():
|
|
result = hatch('new', project_name)
|
|
|
|
assert result.exit_code == 0, result.output
|
|
|
|
project_path = temp_dir / 'my-app'
|
|
data_path = temp_dir / 'data'
|
|
data_path.mkdir()
|
|
|
|
with project_path.as_cwd():
|
|
result = hatch('env', 'show', 'foo', '--ascii')
|
|
|
|
assert result.exit_code == 1, result.output
|
|
assert helpers.remove_trailing_spaces(result.output) == helpers.dedent(
|
|
"""
|
|
Environment `foo` is not defined by project config
|
|
"""
|
|
)
|
|
|
|
|
|
def test_optional_columns(hatch, helpers, temp_dir, config_file):
|
|
config_file.model.template.plugins['default']['tests'] = False
|
|
config_file.save()
|
|
|
|
project_name = 'My.App'
|
|
|
|
with temp_dir.as_cwd():
|
|
result = hatch('new', project_name)
|
|
|
|
assert result.exit_code == 0, result.output
|
|
|
|
project_path = temp_dir / 'my-app'
|
|
data_path = temp_dir / 'data'
|
|
data_path.mkdir()
|
|
|
|
dependencies = ['python___dateutil', 'bAr.Baz[TLS] >=1.2RC5']
|
|
extra_dependencies = ['Foo;python_version<"3.8"']
|
|
env_vars = {'FOO': '1', 'BAR': '2'}
|
|
description = """
|
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna \
|
|
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \
|
|
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint \
|
|
occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
|
"""
|
|
|
|
project = Project(project_path)
|
|
config = dict(project.raw_config)
|
|
config['project']['optional-dependencies'] = {'foo_bar': [], 'baz': []}
|
|
project.save_config(config)
|
|
helpers.update_project_environment(
|
|
project,
|
|
'default',
|
|
{
|
|
'matrix': [{'version': ['9000', '3.14'], 'py': ['39', '310']}],
|
|
'description': description,
|
|
'dependencies': dependencies,
|
|
'extra-dependencies': extra_dependencies,
|
|
'env-vars': env_vars,
|
|
'features': ['Foo...Bar', 'Baz', 'baZ'],
|
|
'scripts': {'test': 'pytest', 'build': 'python -m build', '_foo': 'test'},
|
|
},
|
|
)
|
|
helpers.update_project_environment(
|
|
project,
|
|
'foo',
|
|
{
|
|
'description': description,
|
|
'dependencies': dependencies,
|
|
'extra-dependencies': extra_dependencies,
|
|
'env-vars': env_vars,
|
|
},
|
|
)
|
|
|
|
with project_path.as_cwd():
|
|
result = hatch('env', 'show', '--ascii')
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert helpers.remove_trailing_spaces(result.output) == helpers.dedent(
|
|
"""
|
|
Standalone
|
|
+------+---------+----------+-----------------------------+-----------------------+---------+----------------------------------------------------------------------------------------------------------+
|
|
| Name | Type | Features | Dependencies | Environment variables | Scripts | Description |
|
|
+======+=========+==========+=============================+=======================+=========+==========================================================================================================+
|
|
| foo | virtual | baz | bar-baz[tls]>=1.2rc5 | BAR=2 | build | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et |
|
|
| | | foo-bar | foo; python_version < '3.8' | FOO=1 | test | dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip |
|
|
| | | | python-dateutil | | | ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu |
|
|
| | | | | | | fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia |
|
|
| | | | | | | deserunt mollit anim id est laborum. |
|
|
+------+---------+----------+-----------------------------+-----------------------+---------+----------------------------------------------------------------------------------------------------------+
|
|
Matrices
|
|
+---------+---------+------------+----------+-----------------------------+-----------------------+---------+------------------------------------------------------------------------------------------+
|
|
| Name | Type | Envs | Features | Dependencies | Environment variables | Scripts | Description |
|
|
+=========+=========+============+==========+=============================+=======================+=========+==========================================================================================+
|
|
| default | virtual | py39-9000 | baz | bar-baz[tls]>=1.2rc5 | BAR=2 | build | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor |
|
|
| | | py39-3.14 | foo-bar | foo; python_version < '3.8' | FOO=1 | test | incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud |
|
|
| | | py310-9000 | | python-dateutil | | | exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure |
|
|
| | | py310-3.14 | | | | | dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. |
|
|
| | | | | | | | Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt |
|
|
| | | | | | | | mollit anim id est laborum. |
|
|
+---------+---------+------------+----------+-----------------------------+-----------------------+---------+------------------------------------------------------------------------------------------+
|
|
"""
|
|
)
|
|
|
|
|
|
def test_context_formatting(hatch, helpers, temp_dir, config_file):
|
|
config_file.model.template.plugins['default']['tests'] = False
|
|
config_file.save()
|
|
|
|
project_name = 'My.App'
|
|
|
|
with temp_dir.as_cwd():
|
|
result = hatch('new', project_name)
|
|
|
|
assert result.exit_code == 0, result.output
|
|
|
|
project_path = temp_dir / 'my-app'
|
|
data_path = temp_dir / 'data'
|
|
data_path.mkdir()
|
|
|
|
project = Project(project_path)
|
|
|
|
# Without context formatting
|
|
helpers.update_project_environment(
|
|
project,
|
|
'default',
|
|
{
|
|
'matrix': [{'version': ['9000', '3.14'], 'py': ['39', '310']}],
|
|
'dependencies': ['foo @ {root:uri}/../foo'],
|
|
},
|
|
)
|
|
|
|
# With context formatting
|
|
helpers.update_project_environment(
|
|
project,
|
|
'foo',
|
|
{
|
|
'env-vars': {'BAR': '{env:FOO_BAZ}'},
|
|
'dependencies': ['pydantic'],
|
|
},
|
|
)
|
|
|
|
with project_path.as_cwd(env_vars={'FOO_BAZ': 'FOO_BAR'}):
|
|
result = hatch('env', 'show', '--ascii')
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert helpers.remove_trailing_spaces(result.output) == helpers.dedent(
|
|
"""
|
|
Standalone
|
|
+------+---------+--------------+-----------------------+
|
|
| Name | Type | Dependencies | Environment variables |
|
|
+======+=========+==============+=======================+
|
|
| foo | virtual | pydantic | BAR=FOO_BAR |
|
|
+------+---------+--------------+-----------------------+
|
|
Matrices
|
|
+---------+---------+------------+------------------------+
|
|
| Name | Type | Envs | Dependencies |
|
|
+=========+=========+============+========================+
|
|
| default | virtual | py39-9000 | foo@ {root:uri}/../foo |
|
|
| | | py39-3.14 | |
|
|
| | | py310-9000 | |
|
|
| | | py310-3.14 | |
|
|
+---------+---------+------------+------------------------+
|
|
"""
|
|
)
|
|
|
|
|
|
def test_plugin_dependencies_unmet(hatch, helpers, temp_dir, config_file, mock_plugin_installation):
|
|
config_file.model.template.plugins['default']['tests'] = False
|
|
config_file.save()
|
|
|
|
project_name = 'My.App'
|
|
|
|
with temp_dir.as_cwd():
|
|
result = hatch('new', project_name)
|
|
|
|
assert result.exit_code == 0, result.output
|
|
|
|
project_path = temp_dir / 'my-app'
|
|
data_path = temp_dir / 'data'
|
|
data_path.mkdir()
|
|
|
|
dependency = os.urandom(16).hex()
|
|
(project_path / DEFAULT_CONFIG_FILE).write_text(
|
|
helpers.dedent(
|
|
f"""
|
|
[env]
|
|
requires = ["{dependency}"]
|
|
"""
|
|
)
|
|
)
|
|
|
|
with project_path.as_cwd():
|
|
result = hatch('env', 'show', '--ascii')
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert helpers.remove_trailing_spaces(result.output) == helpers.dedent(
|
|
"""
|
|
Syncing environment plugin requirements
|
|
Standalone
|
|
+---------+---------+
|
|
| Name | Type |
|
|
+=========+=========+
|
|
| default | virtual |
|
|
+---------+---------+
|
|
"""
|
|
)
|
|
helpers.assert_plugin_installation(mock_plugin_installation, [dependency])
|