From: Shane Jaroch Date: Sun, 4 Jan 2026 09:32:33 +0000 (-0500) Subject: add installtion test; fix failing install X-Git-Url: https://git.nutra.tk/v2?a=commitdiff_plain;h=d4a650079c1ea1713fe5a1d4fbc0d99dfd55faf1;p=gamesguru%2Fgetmyancestors.git add installtion test; fix failing install --- diff --git a/.continueignore b/.continueignore new file mode 100644 index 0000000..390e8b3 --- /dev/null +++ b/.continueignore @@ -0,0 +1,3 @@ +.venv/ +build +*.egg-info diff --git a/getmyancestors/tests/test_installation.py b/getmyancestors/tests/test_installation.py new file mode 100644 index 0000000..478e57a --- /dev/null +++ b/getmyancestors/tests/test_installation.py @@ -0,0 +1,147 @@ +"""Test package installation and basic functionality.""" +import os +import sys +import subprocess +import tempfile +import venv +import unittest +import shutil +from pathlib import Path + + +class TestInstallation(unittest.TestCase): + """Test that the package can be installed and basic commands work.""" + + @classmethod + def setUpClass(cls): + """Get the project root directory.""" + # Go up 3 levels from tests directory: getmyancestors/tests -> getmyancestors -> . + cls.project_root = Path(__file__).parent.parent.parent.absolute() + print(f"Project root: {cls.project_root}") + + def test_clean_installation(self): + """Test installing the package in a clean virtual environment.""" + # Skip on CI if it takes too long + if os.environ.get('CI') == 'true' and os.environ.get('SKIP_LONG_TESTS'): + self.skipTest("Skipping long-running installation test in CI") + + with tempfile.TemporaryDirectory() as tmpdir: + tmpdir_path = Path(tmpdir) + + # Create a clean virtual environment + venv_dir = tmpdir_path / "venv" + print(f"Creating virtual environment at: {venv_dir}") + venv.create(venv_dir, with_pip=True, clear=True) + + # Get paths to pip and python in the virtual environment + if sys.platform == "win32": + pip_path = venv_dir / "Scripts" / "pip.exe" + python_path = venv_dir / "Scripts" / "python.exe" + else: + pip_path = venv_dir / "bin" / "pip" + python_path = venv_dir / "bin" / "python" + + # Install the package from the project directory + print(f"Installing package from: {self.project_root}") + result = subprocess.run( + [str(pip_path), "install", str(self.project_root)], + capture_output=True, + text=True, + cwd=self.project_root + ) + + if result.returncode != 0: + print(f"Installation failed. STDOUT: {result.stdout}") + print(f"Installation failed. STDERR: {result.stderr}") + + self.assertEqual( + result.returncode, 0, + f"Package installation failed:\nSTDOUT: {result.stdout}\nSTDERR: {result.stderr}" + ) + + # Test that the package can be imported + print("Testing package import...") + result = subprocess.run( + [str(python_path), "-c", "import getmyancestors; print('Import successful')"], + capture_output=True, + text=True + ) + + self.assertEqual( + result.returncode, 0, + f"Package import failed:\nSTDOUT: {result.stdout}\nSTDERR: {result.stderr}" + ) + self.assertIn("Import successful", result.stdout) + + # Test that CLI commands can be imported (check entry points) + print("Testing CLI command imports...") + for module in ["getmyancestors.getmyanc", "getmyancestors.mergemyanc", "getmyancestors.fstogedcom"]: + result = subprocess.run( + [str(python_path), "-c", f"from {module} import main; print('{module} import successful')"], + capture_output=True, + text=True + ) + self.assertEqual( + result.returncode, 0, + f"Failed to import {module}:\nSTDOUT: {result.stdout}\nSTDERR: {result.stderr}" + ) + + def test_dependencies_match(self): + """Test that all imports have corresponding dependencies in pyproject.toml.""" + import tomllib + + # Read pyproject.toml + pyproject_path = self.project_root / "pyproject.toml" + self.assertTrue(pyproject_path.exists(), f"pyproject.toml not found at {pyproject_path}") + + with open(pyproject_path, 'rb') as f: + pyproject = tomllib.load(f) + + # Get dependencies from pyproject.toml + dependencies = pyproject.get('project', {}).get('dependencies', []) + dependency_names = [] + for dep in dependencies: + # Extract package name (remove version specifiers) + name = dep.split('==')[0].split('>=')[0].split('<=')[0].split('~=')[0].strip() + dependency_names.append(name) + + print(f"Dependencies in pyproject.toml: {dependency_names}") + + # Check critical dependencies that we know are needed + critical_deps = [ + 'requests', + 'requests-cache', # Note: package name uses hyphen, import uses underscore + 'requests-ratelimiter', + 'diskcache', + 'babelfish', + 'geocoder', + 'fake-useragent', + ] + + for dep in critical_deps: + # Handle requests-cache vs requests_cache naming difference + if dep == 'requests-cache': + check_name = 'requests_cache' + else: + check_name = dep.replace('-', '_') # Convert hyphen to underscore for import check + + # Try to import the dependency + try: + __import__(check_name) + print(f"✓ Can import {check_name}") + except ImportError as e: + # Check if it's in dependencies (allowing for naming differences) + found = False + for pyproject_dep in dependency_names: + if dep in pyproject_dep or pyproject_dep in dep: + found = True + break + + if not found: + self.fail(f"Dependency '{dep}' is imported but not declared in pyproject.toml") + else: + print(f"✓ Dependency '{dep}' is declared (as '{pyproject_dep}')") + + +if __name__ == "__main__": + unittest.main(verbosity=2) \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 6975ba2..7112eb4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,7 @@ +[build-system] +requires = ["setuptools>=61.0", "wheel"] +build-backend = "setuptools.build_meta" + [project] name = "getmyancestors" description = "Retrieve GEDCOM data from FamilySearch Tree" @@ -21,25 +25,30 @@ dependencies = [ "requests==2.32.3", "fake-useragent==2.0.3", "geocoder==1.38.1", - "requests-ratelimiter==0.7.0" + "requests-ratelimiter==0.7.0", + "requests-cache" # Added missing dependency ] dynamic = ["version", "readme"] +[project.urls] +HomePage = "https://github.com/Linekio/getmyancestors" + +[project.scripts] +getmyancestors = "getmyancestors.getmyanc:main" +mergemyancestors = "getmyancestors.mergemyanc:main" +fstogedcom = "getmyancestors.fstogedcom:main" + +[tool.setuptools] +# Use find packages with exclude pattern +packages.find = {exclude = ["http_cache", "http_cache.*"]} + [tool.setuptools.dynamic] version = {attr = "getmyancestors.__version__"} readme = {file = ["README.md"]} -[project.urls] -HomePage = "https://github.com/Linekio/getmyancestors" - [tool.setuptools.package-data] getmyancestors = ["fstogedcom.png"] -[project.scripts] -getmyancestors = "getmyancestors.getmyancestors:main" -mergemyancestors = "getmyancestors.mergemyancestors:main" -fstogedcom = "getmyancestors.fstogedcom:main" - # Linting configs [tool.isort] @@ -97,4 +106,4 @@ omit = [ "**/tests/**" # do NOT show coverage tests... redundant ] -exclude_lines = ["pragma: no cover"] +exclude_lines = ["pragma: no cover"] \ No newline at end of file