]> Nutra Git (v2) - gamesguru/getmyancestors.git/commitdiff
add installtion test; fix failing install
authorShane Jaroch <chown_tee@proton.me>
Sun, 4 Jan 2026 09:32:33 +0000 (04:32 -0500)
committerShane Jaroch <chown_tee@proton.me>
Sun, 4 Jan 2026 09:32:33 +0000 (04:32 -0500)
.continueignore [new file with mode: 0644]
getmyancestors/tests/test_installation.py [new file with mode: 0644]
pyproject.toml

diff --git a/.continueignore b/.continueignore
new file mode 100644 (file)
index 0000000..390e8b3
--- /dev/null
@@ -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 (file)
index 0000000..478e57a
--- /dev/null
@@ -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
index 6975ba2b246c4cb6222af663c8730a8b45af42f9..7112eb4c6d641343682dc814f4e4027c0cd01909 100644 (file)
@@ -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