Skip to content

Commit

Permalink
test that generated pycs are valid after a fresh install
Browse files Browse the repository at this point in the history
  • Loading branch information
scauligi committed Jun 6, 2022
1 parent 7a2a70b commit 4b1b130
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 2 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ jobs:
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python }}
- run: pip install . && rm -r hy
- run: pip install . && mv hy _hy_src
# We want to be sure we're testing the installed version,
# instead of running from the source tree.
# instead of running from the source tree,
# but we still need to keep it around for a few tests.
- run: pip install pytest
- run: pytest
7 changes: 7 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@
os.environ.pop("HYSTARTUP", None)


def pytest_configure(config):
config.addinivalue_line(
"markers",
"online: mark the test as possibly needing an internet connection (deselect with '-m \"not online\"')",
)


def pytest_ignore_collect(path, config):
versions = [
(sys.version_info < (3, 8), "sub_py3_7_only"),
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class install(install):
def run(self):
super().run()
import py_compile
import sys
from glob import glob

import hy # for compile hooks
Expand Down
123 changes: 123 additions & 0 deletions tests/test_install.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#!/usr/bin/env python

import contextlib
import importlib._bootstrap_external
import importlib.util
import os
import shutil
import site
import subprocess
import tempfile
import venv
from pathlib import Path

import _imp
import pytest

python_exe = "python.exe" if os.name == "nt" else "python"
envBuilder = venv.EnvBuilder(clear=True, with_pip=True, symlinks=(os.name == "nt"))
hy_source = Path(__file__).parent.parent


@pytest.fixture(scope="module", autouse=True)
def _restore_hy():
running_in_ci = False
if not (hy_source / "hy").exists() and (hy_source / "_hy_src").exists():
running_in_ci = True
shutil.move(hy_source / "_hy_src", hy_source / "hy")
yield
if running_in_ci:
shutil.move(hy_source / "hy", hy_source / "_hy_src")


def check_pyc(source_or_pyc_fname):
try:
source_fname = importlib.util.source_from_cache(source_or_pyc_fname)
pycname = source_or_pyc_fname
except ValueError:
pycname = importlib.util.cache_from_source(source_or_pyc_fname)
source_fname = source_or_pyc_fname

stat = os.stat(source_fname)
basename = os.path.basename(source_fname)
with open(pycname, "rb") as fp:
pyc = fp.read()

exc_details = {"name": source_fname, "path": pycname}

flags = importlib._bootstrap_external._classify_pyc(pyc, basename, exc_details)

if flags & 0b1:
# hash-based
with open(source_fname, "rb") as fp:
source_bytes = fp.read()
source_hash = _imp.source_hash(
importlib.util._RAW_MAGIC_NUMBER,
source_bytes,
)
importlib._bootstrap_external._validate_hash_pyc(
pyc, source_hash, basename, exc_details
)
else:
# timestamp-based
mtime = int(stat.st_mtime)
importlib._bootstrap_external._validate_timestamp_pyc(
pyc, mtime, stat.st_size, basename, exc_details
)


@contextlib.contextmanager
def fresh_env(*extra_packages):
with tempfile.TemporaryDirectory() as name:
envBuilder.create(name)
base = Path(name)
if extra_packages:
pip = base / "bin" / "pip"
subprocess.run([pip, "install", *extra_packages], check=True)
yield base


def with_and_without_wheel(f):
def _wrapped():
with fresh_env() as base:
pip = base / "bin" / "pip"
sitepackages = Path(site.getsitepackages([base])[0])
f(pip, sitepackages)
with fresh_env("wheel") as base:
pip = base / "bin" / "pip"
sitepackages = Path(site.getsitepackages([base])[0])
f(pip, sitepackages)

return _wrapped


@pytest.mark.online
@with_and_without_wheel
def test_install_dot(pip, sitepackages):
subprocess.run([pip, "install", hy_source], check=True)
for path in (sitepackages / "hy").glob("**/*.hy"):
check_pyc(path)


@pytest.mark.online
def test_install_sdist():
with fresh_env() as base:
root = base / "build"
python = base / "bin" / python_exe
shutil.copytree(
hy_source, root, ignore=shutil.ignore_patterns(".git", "build", "dist")
)
subprocess.run(
[python, root / "setup.py", "sdist"],
env={**os.environ, "HY_VERSION": "unknown"},
check=True,
)
tarball = root / "dist" / "hy-unknown.tar.gz"

@with_and_without_wheel
def _test_install_sdist(pip, sitepackages):
subprocess.run([pip, "install", tarball], check=True)
for path in (sitepackages / "hy").glob("**/*.hy"):
check_pyc(path)

_test_install_sdist()

0 comments on commit 4b1b130

Please sign in to comment.