Files
theHarvester/tests/test_runtime_dependencies.py

80 lines
2.9 KiB
Python

import subprocess
import sys
import textwrap
import tomllib
from pathlib import Path
def _dependency_names(requirements: list[str]) -> set[str]:
return {requirement.partition('==')[0] for requirement in requirements}
def test_json_extensions_are_not_installation_requirements() -> None:
project = tomllib.loads(Path('pyproject.toml').read_text(encoding='utf-8'))
assert all(not dependency.startswith('ujson') for dependency in project['project']['dependencies'])
assert all(not dependency.startswith('types-ujson') for dependency in project['dependency-groups']['dev'])
def test_unused_packages_are_not_runtime_requirements() -> None:
project = tomllib.loads(Path('pyproject.toml').read_text(encoding='utf-8'))
lock = tomllib.loads(Path('uv.lock').read_text(encoding='utf-8'))
runtime = _dependency_names(project['project']['dependencies'])
development = _dependency_names(project['dependency-groups']['dev'])
locked = {package['name'] for package in lock['package']}
assert runtime.isdisjoint({'aiofiles', 'dnspython', 'httpx', 'lxml', 'retrying'})
assert {'aiofiles', 'dnspython', 'lxml', 'retrying'}.isdisjoint(locked)
assert 'httpx' in development
def test_unused_packages_are_not_direct_development_requirements() -> None:
project = tomllib.loads(Path('pyproject.toml').read_text(encoding='utf-8'))
lock = tomllib.loads(Path('uv.lock').read_text(encoding='utf-8'))
development = _dependency_names(project['dependency-groups']['dev'])
locked = {package['name'] for package in lock['package']}
assert development.isdisjoint({'mypy-extensions', 'ty', 'types-certifi', 'types-chardet', 'wheel'})
assert {'ty', 'types-certifi', 'types-chardet', 'wheel'}.isdisjoint(locked)
assert 'exclude-newer-package' not in project['tool']['uv']
assert 'ty' not in project['tool']
def test_runtime_imports_without_optional_json_extensions() -> None:
script = textwrap.dedent(
"""
import builtins
import importlib
real_import = builtins.__import__
def import_without_ujson(name, *args, **kwargs):
if name == 'ujson':
raise ModuleNotFoundError('ujson is unavailable')
return real_import(name, *args, **kwargs)
builtins.__import__ = import_without_ujson
for module in (
'theHarvester.__main__',
'theHarvester.discovery.commoncrawl',
'theHarvester.discovery.gitlabsearch',
'theHarvester.discovery.robtex',
'theHarvester.discovery.subdomainfinderc99',
'theHarvester.discovery.windvane',
'theHarvester.lib.core',
):
importlib.import_module(module)
"""
)
result = subprocess.run(
[sys.executable, '-c', script],
check=False,
capture_output=True,
text=True,
)
assert result.returncode == 0, result.stderr