Skip to content

Commit

Permalink
WIP: More testing likely breaking py3.6 support
Browse files Browse the repository at this point in the history
This test will break python 3.6 and I'm likely to drop support for 3.6 because of it.
The test fails because identical pathlib requirements don't compare equal in 3.6.
  • Loading branch information
MHendricks committed Dec 17, 2024
1 parent 5570f9a commit cf5cb74
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 19 deletions.
9 changes: 0 additions & 9 deletions .github/workflows/python-static-analysis-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,6 @@ jobs:
json_ver: ['json', 'json5']
os: ['ubuntu-latest', 'windows-latest']
python: ['3.7', '3.8', '3.9', '3.10', '3.11']
# Works around the depreciation of python 3.6 for ubuntu
# https://github.com/actions/setup-python/issues/544
include:
- json_ver: 'json'
os: 'ubuntu-20.04'
python: '3.6'
- json_ver: 'json5'
os: 'ubuntu-20.04'
python: '3.6'

runs-on: ${{ matrix.os }}

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ home directory on other platforms.

## Installing

Hab is installed using pip. It requires python 3.6 or above. It's recommended
Hab is installed using pip. It requires python 3.7 or above. It's recommended
that you add the path to your python's bin or Scripts folder to the `PATH`
environment variable so you can simply run the `hab` command.

Expand Down
10 changes: 5 additions & 5 deletions hab/parsers/lazy_distro_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
logger = logging.getLogger(__name__)


class DistroPaths:
class DistroPath:
__slots__ = ("distro", "hab_filename", "root", "site")

def __init__(self, distro, root, relative=NotSet, site=None):
Expand Down Expand Up @@ -83,8 +83,8 @@ def install(self, dest, replace=False, relative=NotSet):
contains this distro this error is raised and it is not installed.
Unless `replace` is set to True.
"""
if not isinstance(dest, DistroPaths):
dest = DistroPaths(self, dest, relative=relative, site=self.resolver.site)
if not isinstance(dest, DistroPath):
dest = DistroPath(self, dest, relative=relative, site=self.resolver.site)

installed = self.installed(dest, relative=relative)
if installed:
Expand All @@ -99,8 +99,8 @@ def install(self, dest, replace=False, relative=NotSet):
self.resolver.clear_caches()

def installed(self, dest, relative=NotSet):
if not isinstance(dest, DistroPaths):
dest = DistroPaths(self, dest, relative=relative, site=self.resolver.site)
if not isinstance(dest, DistroPath):
dest = DistroPath(self, dest, relative=relative, site=self.resolver.site)
return dest.hab_filename.exists()

def _ensure_loaded(self):
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ install_requires =
importlib-metadata
packaging>=20.0
setuptools-scm[toml]>=4
python_requires = >=3.6
python_requires = >=3.7
include_package_data = True
scripts =
bin/.hab-complete.bash
Expand Down
151 changes: 151 additions & 0 deletions tests/test_lazy_distro_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import pytest
from packaging.requirements import Requirement
from packaging.version import Version

from hab import DistroMode
from hab.errors import InstallDestinationExistsError
from hab.parsers.lazy_distro_version import DistroPath, LazyDistroVersion


def test_distro_path(zip_distro_sidecar, helpers, tmp_path):
resolver = helpers.render_resolver(
"site_distro_zip_sidecar.json",
tmp_path,
zip_root=zip_distro_sidecar.root.as_posix(),
)
with resolver.distro_mode_override(DistroMode.Downloaded):
distro = resolver.find_distro("dist_a==0.2")

# Passing root as a string converts it to a pathlib.Path object.
dpath = DistroPath(
distro, str(tmp_path), relative="{distro_name}-v{version}", site=resolver.site
)
# Test that the custom relative string, it used to generate root
assert dpath.root == tmp_path / "dist_a-v0.2"
assert dpath.hab_filename == tmp_path / "dist_a-v0.2" / ".hab.json"

# If site and relative are not passed the default is used
dpath = DistroPath(distro, tmp_path)
assert dpath.root == tmp_path / "dist_a" / "0.2"
assert dpath.hab_filename == tmp_path / "dist_a" / "0.2" / ".hab.json"

# Test that site settings are respected when not passing relative
resolver.site.downloads["relative_path"] = "parent/{distro_name}/child/{version}"
dpath = DistroPath(distro, tmp_path, site=resolver.site)
assert dpath.root == tmp_path / "parent" / "dist_a" / "child" / "0.2"
assert (
dpath.hab_filename
== tmp_path / "parent" / "dist_a" / "child" / "0.2" / ".hab.json"
)


def test_is_lazy(zip_distro_sidecar, helpers, tmp_path):
"""Check that a LazyDistroVersion doesn't automatically load all data."""
resolver = helpers.render_resolver(
"site_distro_zip_sidecar.json",
tmp_path,
zip_root=zip_distro_sidecar.root.as_posix(),
)
with resolver.distro_mode_override(DistroMode.Downloaded):
distro = resolver.find_distro("dist_a==0.1")

frozen_data = dict(
context=["dist_a"],
name="dist_a==0.1",
version=Version("0.1"),
)
filename = zip_distro_sidecar.root / "dist_a_v0.1.hab.json"

# The find_distro call should have called load but does not actually load data
assert isinstance(distro, LazyDistroVersion)
assert distro._loaded is False
assert distro.context == ["dist_a"]
assert distro.filename == filename
assert distro.frozen_data == frozen_data
assert distro.name == "dist_a==0.1"

# Calling _ensure_loaded actually loads the full distro from the finder's data
data = distro._ensure_loaded()
assert distro._loaded is True
assert isinstance(data, dict)
assert distro.name == "dist_a==0.1"

# If called a second time, then nothing extra is done and no data is returned.
assert distro._ensure_loaded() is None


def test_bad_kwargs():
"""Test that the proper error is raised if you attempt to init with a filename."""
match = "Passing filename to this class is not supported."
with pytest.raises(ValueError, match=match):
LazyDistroVersion(None, None, "filename")

with pytest.raises(ValueError, match=match):
LazyDistroVersion(None, None, filename="a/filename")


@pytest.mark.parametrize(
"prop,check",
(("distros", {"dist_b": Requirement("dist_b")}),),
)
def test_lazy_hab_property(prop, check, zip_distro_sidecar, helpers, tmp_path):
"""Check that a LazyDistroVersion doesn't automatically load all data."""
resolver = helpers.render_resolver(
"site_distro_zip_sidecar.json",
tmp_path,
zip_root=zip_distro_sidecar.root.as_posix(),
)
with resolver.distro_mode_override(DistroMode.Downloaded):
distro = resolver.find_distro("dist_a==0.2")

# Calling a lazy getter ensures the data is loaded
assert distro._loaded is False
value = getattr(distro, prop)
assert distro._loaded is True
assert value == check

# You can call the lazy getter repeatedly
value = getattr(distro, prop)
assert value == check


def test_install(zip_distro_sidecar, helpers, tmp_path):
"""Check that a LazyDistroVersion doesn't automatically load all data."""
resolver = helpers.render_resolver(
"site_distro_zip_sidecar.json",
tmp_path,
zip_root=zip_distro_sidecar.root.as_posix(),
)
with resolver.distro_mode_override(DistroMode.Downloaded):
distro = resolver.find_distro("dist_a==0.2")
dest_root = resolver.site.downloads["install_root"]
distro_root = dest_root / "dist_a" / "0.2"
hab_json = distro_root / ".hab.json"

# The distro is not currently installed. This also tests that it can
# auto-cast to DistroPath
assert not distro.installed(dest_root)

# Install will clear the cache, ensure its populated
assert resolver._downloadable_distros is not None
# Install the distro using LazyDistroVersion
distro.install(dest_root)
assert distro.installed(dest_root)
assert hab_json.exists()
# Check that the cache was cleared by the install function
assert resolver._downloadable_distros is None

# Test that if the distro is already installed, an error is raised
with pytest.raises(InstallDestinationExistsError) as excinfo:
distro.install(dest_root)
assert excinfo.value.filename == distro_root

# Test forced replacement of an existing distro by creating an extra file
extra_file = distro_root / "extra_file.txt"
extra_file.touch()
# This won't raise the exception, but will remove the old distro
distro.install(dest_root, replace=True)
assert hab_json.exists()
assert distro.installed(dest_root)

assert not extra_file.exists()
6 changes: 3 additions & 3 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tox]
envlist = begin,py{36,37,38,39,310,311}-{json,json5},end,black,flake8
envlist = begin,py{37,38,39,310,311}-{json,json5},end,black,flake8
skip_missing_interpreters = True
skipsdist = True

Expand Down Expand Up @@ -29,14 +29,14 @@ commands =

coverage erase

[testenv:py{36,37,38,39,310,311}-{json,json5}]
[testenv:py{37,38,39,310,311}-{json,json5}]
depends = begin

[testenv:end]
basepython = python3
depends =
begin
py{36,37,38,39,310,311}-{json,json5}
py{37,38,39,310,311}-{json,json5}
parallel_show_output = True
deps =
coverage
Expand Down

0 comments on commit cf5cb74

Please sign in to comment.