diff --git a/.github/workflows/check-same-version.yml b/.github/workflows/check-same-version.yml
index c3cb65c..5e732b5 100644
--- a/.github/workflows/check-same-version.yml
+++ b/.github/workflows/check-same-version.yml
@@ -26,7 +26,7 @@ jobs:
cache: 'pip' # optional and only works for Python projects
- name: Run same-version
- uses: willynilly/same-version@v5.1.0
+ uses: willynilly/same-version@v6.0.0
with:
fail_for_missing_file: false
check_github_event: true
diff --git a/CITATION.cff b/CITATION.cff
index 8d5cf03..d1e862d 100644
--- a/CITATION.cff
+++ b/CITATION.cff
@@ -34,7 +34,7 @@ keywords:
- metadata
- harmonization
license: Apache-2.0
-version: "5.1.0"
+version: "6.0.0"
date-released: "2025-06-10"
references:
- title: Citation File Format
diff --git a/README.md b/README.md
index 3c0e44b..188c091 100644
--- a/README.md
+++ b/README.md
@@ -56,9 +56,9 @@ This workflow runs after the tag or release exists and can report problems, but
- GitHub tag/release
- `CITATION.cff`
- `pyproject.toml` (Python)
-- `setup.py` (Python)
+- `setup.py` (Python, via static analysis only — no execution)
- `setup.cfg` (Python)
-- Python files with `__version__` assignment
+- Python files with `__version__` assignment (static parsing only — must be assigned directly to a string literal)
- `codemeta.json` (General)
- `.zenodo.json` (General)
- `package.json` (JS/TypeScript)
@@ -259,7 +259,7 @@ jobs:
python-version: ">=3.10"
- name: Run same-version
- uses: willynilly/same-version@v5.1.0
+ uses: willynilly/same-version@v6.0.0
with:
fail_for_missing_file: false
check_github_event: true
@@ -309,7 +309,7 @@ jobs:
python-version: ">=3.10"
- name: Run same-version
- uses: willynilly/same-version@v5.1.0
+ uses: willynilly/same-version@v6.0.0
with:
fail_for_missing_file: false
check_github_event: true
@@ -347,7 +347,7 @@ Add to your `.pre-commit-config.yaml`:
```yaml
repos:
- repo: https://github.com/willynilly/same-version
- rev: v5.1.0 # Use latest tag
+ rev: v6.0.0 # Use latest tag
hooks:
- id: same-version
stages: [pre-commit, pre-push]
diff --git a/example.pre-commit-config.yaml b/example.pre-commit-config.yaml
index eb340b0..6698d6c 100644
--- a/example.pre-commit-config.yaml
+++ b/example.pre-commit-config.yaml
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/willynilly/same-version
- rev: v5.1.0 # Use latest tag
+ rev: v6.0.0 # Use latest tag
hooks:
- id: same-version
stages: [pre-commit, pre-push]
diff --git a/pyproject.toml b/pyproject.toml
index 590c014..6dfafeb 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "same-version"
-version = "5.1.0"
+version = "6.0.0"
description = "Automatically ensures your software version metadata is consistent across key project files."
readme = "README.md"
requires-python = ">=3.10"
diff --git a/src/same_version/extractors/py_ast_extractor.py b/src/same_version/extractors/py_ast_extractor.py
index dfeb714..b05977c 100644
--- a/src/same_version/extractors/py_ast_extractor.py
+++ b/src/same_version/extractors/py_ast_extractor.py
@@ -7,7 +7,8 @@ class PyAstExtractor(FileExtractor):
def _get_data(self) -> dict:
data = {}
+ data['tree'] = None
if self.target_file_path and self.target_exists:
with open(self.target_file_path, 'r', encoding='utf-8') as f:
- data['tree'] = ast.parse(f.read(), filename=self.target_file_path.resolve())
+ data['tree'] = ast.parse(f.read(), filename=str(self.target_file_path.resolve()))
return data
\ No newline at end of file
diff --git a/src/same_version/extractors/py_version_assignment_extractor.py b/src/same_version/extractors/py_version_assignment_extractor.py
index 74e129a..f91ecec 100644
--- a/src/same_version/extractors/py_version_assignment_extractor.py
+++ b/src/same_version/extractors/py_version_assignment_extractor.py
@@ -10,7 +10,7 @@ class PyVersionAssignmentExtractor(PyAstExtractor):
def __init__(self, cli_args: Namespace):
target_cli_parameter_name: str = '--py-version-assignment-path'
- default_target_name: str = "Python file with __version__ assignment"
+ default_target_name: str = "Python file with __version__ assignment to a literal string"
super().__init__(
target_file_path=self._create_target_file_path_from_cli_arg(cli_args=cli_args, cli_arg_parameter=target_cli_parameter_name),
default_target_name=default_target_name,
diff --git a/src/same_version/extractors/ro_crate_metadata_json_extractor.py b/src/same_version/extractors/ro_crate_metadata_json_extractor.py
index 76954ab..aecf59a 100644
--- a/src/same_version/extractors/ro_crate_metadata_json_extractor.py
+++ b/src/same_version/extractors/ro_crate_metadata_json_extractor.py
@@ -19,7 +19,7 @@ def _get_version_from_data(self, data: dict) -> str | None:
version = None
graph: list | None = data.get('@graph', None)
if isinstance(graph, list) and graph is not None:
- id = self.cli_args.get('ro_crate_metadata_json_id', None)
+ id = vars(self.cli_args).get('ro_crate_metadata_json_id', None)
if id is not None:
for resource in graph:
resource_id = resource.get('@id', None)
diff --git a/src/same_version/extractors/setup_cfg_extractor.py b/src/same_version/extractors/setup_cfg_extractor.py
index 3ca9ffe..9fc7503 100644
--- a/src/same_version/extractors/setup_cfg_extractor.py
+++ b/src/same_version/extractors/setup_cfg_extractor.py
@@ -1,3 +1,4 @@
+import configparser
from argparse import Namespace
from same_version.extractors.ini_extractor import IniExtractor
@@ -15,13 +16,18 @@ def __init__(self, cli_args: Namespace):
)
def _get_version_from_data(self, data: dict) -> str | None:
- config = data.get('config', None)
+ config: configparser.ConfigParser | None = data.get('config', None)
if config is None:
return None
- metadata = config.get('metadata', None)
- if metadata is None:
+
+ if not config.has_section('metadata'):
return None
- version = config.get('version', None)
+
+ if not config.has_option('metadata', 'version'):
+ return None
+
+ version = config.get('metadata', 'version')
+
if isinstance(version, str):
version = version.strip()
diff --git a/src/same_version/extractors/setup_py_extractor.py b/src/same_version/extractors/setup_py_extractor.py
index b5da133..5b4f4a8 100644
--- a/src/same_version/extractors/setup_py_extractor.py
+++ b/src/same_version/extractors/setup_py_extractor.py
@@ -1,12 +1,12 @@
+import ast
import logging
-import subprocess
from argparse import Namespace
-from same_version.extractors.file_extractor import FileExtractor
+from same_version.extractors.py_ast_extractor import PyAstExtractor
logger = logging.getLogger(__name__)
-class SetupPyExtractor(FileExtractor):
+class SetupPyExtractor(PyAstExtractor):
def __init__(self, cli_args: Namespace):
target_cli_parameter_name: str = '--setup-py-path'
@@ -17,21 +17,62 @@ def __init__(self, cli_args: Namespace):
target_cli_parameter_name=target_cli_parameter_name
)
- def _get_data(self) -> dict:
- data = {}
-
- if not self.target_exists:
- data['version'] = None
- else:
- try:
- output = subprocess.check_output(['python', str(self.target_file_path), '--version'], stderr=subprocess.STDOUT)
- data['version'] = output.decode('utf-8').strip()
- except subprocess.CalledProcessError as e:
- logger.error(f"❌ Error running {self.target_name} --version:\n{e.output.decode('utf-8')}")
- data['version'] = None
-
- return data
-
def _get_version_from_data(self, data: dict) -> str | None:
- version = data.get('version', None)
- return version
\ No newline at end of file
+ tree = data.get('tree', None)
+ if tree is None:
+ return None
+
+ visitor = SetupPyVisitor()
+ visitor.visit(tree)
+
+ version: str | None = visitor.version
+ if not isinstance(version, str) and version is not None:
+ version = None
+
+ return version
+
+
+class SetupPyVisitor(ast.NodeVisitor):
+ def __init__(self):
+ self.version = None
+ self.assignments = {}
+
+ def visit_Assign(self, node):
+ # Capture simple assignments: version = "1.2.3"
+ if len(node.targets) == 1 and isinstance(node.targets[0], ast.Name):
+ var_name = node.targets[0].id
+ value = self._get_constant_value(node.value)
+ if value is not None:
+ self.assignments[var_name] = value
+
+ def visit_Call(self, node):
+ # Look for any call to 'setup' function
+ if self._is_setup_call(node):
+ for kw in node.keywords:
+ if kw.arg == "version":
+ value = self._get_constant_value(kw.value)
+ if value is None and isinstance(kw.value, ast.Name):
+ # Handle: version=version_var
+ value = self.assignments.get(kw.value.id)
+ if value is not None:
+ self.version = value
+
+ def _get_constant_value(self, node):
+ if isinstance(node, ast.Constant): # Python 3.8+
+ if isinstance(node.value, str):
+ return node.value
+ elif isinstance(node, ast.Str): # Python <3.8
+ return node.s
+ return None
+
+ def _is_setup_call(self, node):
+ # Accept setup() or setuptools.setup()
+ if isinstance(node.func, ast.Name):
+ return node.func.id == "setup"
+ if isinstance(node.func, ast.Attribute):
+ return (
+ node.func.attr == "setup" and
+ isinstance(node.func.value, ast.Name) and
+ node.func.value.id == "setuptools"
+ )
+ return False
diff --git a/src/same_version/main.py b/src/same_version/main.py
index 8ef2660..b817bd7 100644
--- a/src/same_version/main.py
+++ b/src/same_version/main.py
@@ -51,7 +51,7 @@
logger = logging.getLogger(__name__)
def parse_args() -> argparse.Namespace:
- parser = argparse.ArgumentParser(description="Check metadata files for consistent software versions using canonical PEP 440 and SemVer")
+ parser = argparse.ArgumentParser(description="Check whether your software version metadata is consistent across key project files.")
parser.add_argument('--base-version', required=False, help='A base version from which to check')
parser.add_argument('--fail-for-missing-file', default=False, required=False, help='Fail for any checked file that is missing')
parser.add_argument('--check-citation-cff', default=True, required=False, help='Check CITATION.cff? (true/false)')
diff --git a/tests/extractors/conftest.py b/tests/extractors/conftest.py
index 628e697..75f3081 100644
--- a/tests/extractors/conftest.py
+++ b/tests/extractors/conftest.py
@@ -15,4 +15,72 @@ def cli_args_with_base_version():
@pytest.fixture
def cli_args_with_valid_package_json_path():
package_json_path: Path = Path(__file__).resolve().parent.parent / 'test_data' / 'package.json'
- return Namespace(package_json_path=package_json_path)
\ No newline at end of file
+ return Namespace(package_json_path=package_json_path)
+
+@pytest.fixture
+def cli_args_with_valid_pom_xml_path():
+ pom_xml_path: Path = Path(__file__).resolve().parent.parent / 'test_data' / 'pom.xml'
+ return Namespace(pom_xml_path=pom_xml_path)
+
+@pytest.fixture
+def cli_args_with_valid_pyproject_toml_path():
+ pyproject_toml_path: Path = Path(__file__).resolve().parent.parent / 'test_data' / 'pyproject.toml'
+ return Namespace(pyproject_toml_path=pyproject_toml_path)
+
+@pytest.fixture
+def cli_args_with_valid_cargo_toml_path():
+ cargo_toml_path: Path = Path(__file__).resolve().parent.parent / 'test_data' / 'Cargo.toml'
+ return Namespace(cargo_toml_path=cargo_toml_path)
+
+@pytest.fixture
+def cli_args_with_valid_composer_json_path():
+ composer_json_path: Path = Path(__file__).resolve().parent.parent / 'test_data' / 'composer.json'
+ return Namespace(composer_json_path=composer_json_path)
+
+@pytest.fixture
+def cli_args_with_valid_codemeta_json_path():
+ codemeta_json_path: Path = Path(__file__).resolve().parent.parent / 'test_data' / 'codemeta.json'
+ return Namespace(codemeta_json_path=codemeta_json_path)
+
+@pytest.fixture
+def cli_args_with_valid_ro_crate_metadata_json_path_and_id():
+ ro_crate_metadata_json_path: Path = Path(__file__).resolve().parent.parent / 'test_data' / 'ro-crate-metadata.json'
+ ro_crate_metadata_json_id: str = 'software/'
+ return Namespace(ro_crate_metadata_json_path=ro_crate_metadata_json_path, ro_crate_metadata_json_id=ro_crate_metadata_json_id)
+
+@pytest.fixture
+def cli_args_with_valid_zenodo_json_path():
+ zenodo_json_path: Path = Path(__file__).resolve().parent.parent / 'test_data' / '.zenodo.json'
+ return Namespace(zenodo_json_path=zenodo_json_path)
+
+@pytest.fixture
+def cli_args_with_valid_nuspec_path():
+ nuspec_path: Path = Path(__file__).resolve().parent.parent / 'test_data' / '.nuspec'
+ return Namespace(nuspec_path=nuspec_path)
+
+@pytest.fixture
+def cli_args_with_valid_r_description_path():
+ r_description_path: Path = Path(__file__).resolve().parent.parent / 'test_data' / 'DESCRIPTION'
+ return Namespace(r_description_path=r_description_path)
+
+@pytest.fixture
+def cli_args_with_valid_setup_cfg_path():
+ setup_cfg_path: Path = Path(__file__).resolve().parent.parent / 'test_data' / 'setup.cfg'
+ return Namespace(setup_cfg_path=setup_cfg_path)
+
+@pytest.fixture
+def cli_args_with_valid_setup_py_path():
+ setup_py_path: Path = Path(__file__).resolve().parent.parent / 'test_data' / 'setup.py'
+ return Namespace(setup_py_path=setup_py_path)
+
+@pytest.fixture
+def cli_args_with_valid_citation_cff_path():
+ citation_cff_path: Path = Path(__file__).resolve().parent.parent / 'test_data' / 'CITATION.cff'
+ return Namespace(citation_cff_path=citation_cff_path)
+
+@pytest.fixture
+def cli_args_with_valid_py_version_assignment_path():
+ py_version_assignment_path: Path = Path(__file__).resolve().parent.parent / 'test_data' / 'main_with_literal_version_assignment.py'
+ return Namespace(py_version_assignment_path=py_version_assignment_path)
+
+
diff --git a/tests/extractors/test_cargo_toml_extractor.py b/tests/extractors/test_cargo_toml_extractor.py
new file mode 100644
index 0000000..ee9e896
--- /dev/null
+++ b/tests/extractors/test_cargo_toml_extractor.py
@@ -0,0 +1,37 @@
+from argparse import Namespace
+from pathlib import Path
+
+from same_version.extractors.cargo_toml_extractor import CargoTomlExtractor
+
+
+def test_cargo_toml_extractor_extract_version_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:CargoTomlExtractor = CargoTomlExtractor(cli_args=empty_cli_args)
+ assert extractor.extract_version() is None
+
+def test_cargo_toml_extractor_target_parameter_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:CargoTomlExtractor = CargoTomlExtractor(cli_args=empty_cli_args)
+ assert extractor.target_name == 'Cargo.toml'
+
+def test_cargo_toml_extractor_target_exists_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:CargoTomlExtractor = CargoTomlExtractor(cli_args=empty_cli_args)
+ assert extractor.target_exists is False
+
+def test_cargo_toml_extractor_target_cli_parameter_name_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:CargoTomlExtractor = CargoTomlExtractor(cli_args=empty_cli_args)
+ assert extractor.target_cli_parameter_name == '--cargo-toml-path'
+
+def test_cargo_toml_extractor_extract_version_with_cli_args_with_valid_cargo_toml_path(cli_args_with_valid_cargo_toml_path: Namespace):
+ extractor:CargoTomlExtractor = CargoTomlExtractor(cli_args=cli_args_with_valid_cargo_toml_path)
+ assert extractor.extract_version() == '10.0.8'
+
+def test_cargo_toml_extractor_target_parameter_with_cli_args_with_valid_cargo_toml_path(cli_args_with_valid_cargo_toml_path: Namespace):
+ extractor:CargoTomlExtractor = CargoTomlExtractor(cli_args=cli_args_with_valid_cargo_toml_path)
+ assert extractor.target_name is not None and Path(extractor.target_name).name == 'Cargo.toml'
+
+def test_cargo_toml_extractor_target_exists_with_cli_args_with_valid_cargo_toml_path(cli_args_with_valid_cargo_toml_path: Namespace):
+ extractor:CargoTomlExtractor = CargoTomlExtractor(cli_args=cli_args_with_valid_cargo_toml_path)
+ assert extractor.target_exists is True
+
+def test_cargo_toml_extractor_target_cli_parameter_name_with_cli_args_with_valid_cargo_toml_path(cli_args_with_valid_cargo_toml_path: Namespace):
+ extractor:CargoTomlExtractor = CargoTomlExtractor(cli_args=cli_args_with_valid_cargo_toml_path)
+ assert extractor.target_cli_parameter_name == '--cargo-toml-path'
\ No newline at end of file
diff --git a/tests/extractors/test_citation_cff_extractor.py b/tests/extractors/test_citation_cff_extractor.py
new file mode 100644
index 0000000..692da53
--- /dev/null
+++ b/tests/extractors/test_citation_cff_extractor.py
@@ -0,0 +1,37 @@
+from argparse import Namespace
+from pathlib import Path
+
+from same_version.extractors.citation_cff_extractor import CitationCffExtractor
+
+
+def test_citation_cff_extractor_extract_version_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:CitationCffExtractor = CitationCffExtractor(cli_args=empty_cli_args)
+ assert extractor.extract_version() is None
+
+def test_citation_cff_extractor_target_parameter_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:CitationCffExtractor = CitationCffExtractor(cli_args=empty_cli_args)
+ assert extractor.target_name == 'CITATION.cff'
+
+def test_citation_cff_extractor_target_exists_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:CitationCffExtractor = CitationCffExtractor(cli_args=empty_cli_args)
+ assert extractor.target_exists is False
+
+def test_citation_cff_extractor_target_cli_parameter_name_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:CitationCffExtractor = CitationCffExtractor(cli_args=empty_cli_args)
+ assert extractor.target_cli_parameter_name == '--citation-cff-path'
+
+def test_citation_cff_extractor_extract_version_with_cli_args_with_valid_citation_cff_path(cli_args_with_valid_citation_cff_path: Namespace):
+ extractor:CitationCffExtractor = CitationCffExtractor(cli_args=cli_args_with_valid_citation_cff_path)
+ assert extractor.extract_version() == '0.0.8000'
+
+def test_citation_cff_extractor_target_parameter_with_cli_args_with_valid_citation_cff_path(cli_args_with_valid_citation_cff_path: Namespace):
+ extractor:CitationCffExtractor = CitationCffExtractor(cli_args=cli_args_with_valid_citation_cff_path)
+ assert extractor.target_name is not None and Path(extractor.target_name).name == 'CITATION.cff'
+
+def test_citation_cff_extractor_target_exists_with_cli_args_with_valid_citation_cff_path(cli_args_with_valid_citation_cff_path: Namespace):
+ extractor:CitationCffExtractor = CitationCffExtractor(cli_args=cli_args_with_valid_citation_cff_path)
+ assert extractor.target_exists is True
+
+def test_citation_cff_extractor_target_cli_parameter_name_with_cli_args_with_valid_citation_cff_path(cli_args_with_valid_citation_cff_path: Namespace):
+ extractor:CitationCffExtractor = CitationCffExtractor(cli_args=cli_args_with_valid_citation_cff_path)
+ assert extractor.target_cli_parameter_name == '--citation-cff-path'
\ No newline at end of file
diff --git a/tests/extractors/test_codemeta_json_extractor.py b/tests/extractors/test_codemeta_json_extractor.py
new file mode 100644
index 0000000..319c21d
--- /dev/null
+++ b/tests/extractors/test_codemeta_json_extractor.py
@@ -0,0 +1,37 @@
+from argparse import Namespace
+from pathlib import Path
+
+from same_version.extractors.codemeta_json_extractor import CodeMetaJsonExtractor
+
+
+def test_codemeta_json_extractor_extract_version_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:CodeMetaJsonExtractor = CodeMetaJsonExtractor(cli_args=empty_cli_args)
+ assert extractor.extract_version() is None
+
+def test_codemeta_json_extractor_target_parameter_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:CodeMetaJsonExtractor = CodeMetaJsonExtractor(cli_args=empty_cli_args)
+ assert extractor.target_name == 'codemeta.json'
+
+def test_codemeta_json_extractor_target_exists_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:CodeMetaJsonExtractor = CodeMetaJsonExtractor(cli_args=empty_cli_args)
+ assert extractor.target_exists is False
+
+def test_codemeta_json_extractor_target_cli_parameter_name_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:CodeMetaJsonExtractor = CodeMetaJsonExtractor(cli_args=empty_cli_args)
+ assert extractor.target_cli_parameter_name == '--codemeta-json-path'
+
+def test_codemeta_json_extractor_extract_version_with_cli_args_with_valid_codemeta_json_path(cli_args_with_valid_codemeta_json_path: Namespace):
+ extractor:CodeMetaJsonExtractor = CodeMetaJsonExtractor(cli_args=cli_args_with_valid_codemeta_json_path)
+ assert extractor.extract_version() == '13.9.4'
+
+def test_codemeta_json_extractor_target_parameter_with_cli_args_with_valid_codemeta_json_path(cli_args_with_valid_codemeta_json_path: Namespace):
+ extractor:CodeMetaJsonExtractor = CodeMetaJsonExtractor(cli_args=cli_args_with_valid_codemeta_json_path)
+ assert extractor.target_name is not None and Path(extractor.target_name).name == 'codemeta.json'
+
+def test_codemeta_json_extractor_target_exists_with_cli_args_with_valid_codemeta_json_path(cli_args_with_valid_codemeta_json_path: Namespace):
+ extractor:CodeMetaJsonExtractor = CodeMetaJsonExtractor(cli_args=cli_args_with_valid_codemeta_json_path)
+ assert extractor.target_exists is True
+
+def test_codemeta_json_extractor_target_cli_parameter_name_with_cli_args_with_valid_codemeta_json_path(cli_args_with_valid_codemeta_json_path: Namespace):
+ extractor:CodeMetaJsonExtractor = CodeMetaJsonExtractor(cli_args=cli_args_with_valid_codemeta_json_path)
+ assert extractor.target_cli_parameter_name == '--codemeta-json-path'
\ No newline at end of file
diff --git a/tests/extractors/test_composer_json_extractor.py b/tests/extractors/test_composer_json_extractor.py
new file mode 100644
index 0000000..babfad1
--- /dev/null
+++ b/tests/extractors/test_composer_json_extractor.py
@@ -0,0 +1,37 @@
+from argparse import Namespace
+from pathlib import Path
+
+from same_version.extractors.composer_json_extractor import ComposerJsonExtractor
+
+
+def test_composer_json_extractor_extract_version_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:ComposerJsonExtractor = ComposerJsonExtractor(cli_args=empty_cli_args)
+ assert extractor.extract_version() is None
+
+def test_composer_json_extractor_target_parameter_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:ComposerJsonExtractor = ComposerJsonExtractor(cli_args=empty_cli_args)
+ assert extractor.target_name == 'composer.json'
+
+def test_composer_json_extractor_target_exists_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:ComposerJsonExtractor = ComposerJsonExtractor(cli_args=empty_cli_args)
+ assert extractor.target_exists is False
+
+def test_composer_json_extractor_target_cli_parameter_name_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:ComposerJsonExtractor = ComposerJsonExtractor(cli_args=empty_cli_args)
+ assert extractor.target_cli_parameter_name == '--composer-json-path'
+
+def test_composer_json_extractor_extract_version_with_cli_args_with_valid_composer_json_path(cli_args_with_valid_composer_json_path: Namespace):
+ extractor:ComposerJsonExtractor = ComposerJsonExtractor(cli_args=cli_args_with_valid_composer_json_path)
+ assert extractor.extract_version() == '6.0.8'
+
+def test_composer_json_extractor_target_parameter_with_cli_args_with_valid_composer_json_path(cli_args_with_valid_composer_json_path: Namespace):
+ extractor:ComposerJsonExtractor = ComposerJsonExtractor(cli_args=cli_args_with_valid_composer_json_path)
+ assert extractor.target_name is not None and Path(extractor.target_name).name == 'composer.json'
+
+def test_composer_json_extractor_target_exists_with_cli_args_with_valid_composer_json_path(cli_args_with_valid_composer_json_path: Namespace):
+ extractor:ComposerJsonExtractor = ComposerJsonExtractor(cli_args=cli_args_with_valid_composer_json_path)
+ assert extractor.target_exists is True
+
+def test_composer_json_extractor_target_cli_parameter_name_with_cli_args_with_valid_composer_json_path(cli_args_with_valid_composer_json_path: Namespace):
+ extractor:ComposerJsonExtractor = ComposerJsonExtractor(cli_args=cli_args_with_valid_composer_json_path)
+ assert extractor.target_cli_parameter_name == '--composer-json-path'
\ No newline at end of file
diff --git a/tests/extractors/test_nuspec_extractor.py b/tests/extractors/test_nuspec_extractor.py
new file mode 100644
index 0000000..72f181f
--- /dev/null
+++ b/tests/extractors/test_nuspec_extractor.py
@@ -0,0 +1,37 @@
+from argparse import Namespace
+from pathlib import Path
+
+from same_version.extractors.nuspec_extractor import NuspecExtractor
+
+
+def test_nuspec_extractor_extract_version_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:NuspecExtractor = NuspecExtractor(cli_args=empty_cli_args)
+ assert extractor.extract_version() is None
+
+def test_nuspec_extractor_target_parameter_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:NuspecExtractor = NuspecExtractor(cli_args=empty_cli_args)
+ assert extractor.target_name == '.nuspec'
+
+def test_nuspec_extractor_target_exists_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:NuspecExtractor = NuspecExtractor(cli_args=empty_cli_args)
+ assert extractor.target_exists is False
+
+def test_nuspec_extractor_target_cli_parameter_name_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:NuspecExtractor = NuspecExtractor(cli_args=empty_cli_args)
+ assert extractor.target_cli_parameter_name == '--nuspec-path'
+
+def test_nuspec_extractor_extract_version_with_cli_args_with_valid_nuspec_path(cli_args_with_valid_nuspec_path: Namespace):
+ extractor:NuspecExtractor = NuspecExtractor(cli_args=cli_args_with_valid_nuspec_path)
+ assert extractor.extract_version() == '4.8.12'
+
+def test_nuspec_extractor_target_parameter_with_cli_args_with_valid_nuspec_path(cli_args_with_valid_nuspec_path: Namespace):
+ extractor:NuspecExtractor = NuspecExtractor(cli_args=cli_args_with_valid_nuspec_path)
+ assert extractor.target_name is not None and Path(extractor.target_name).name == '.nuspec'
+
+def test_nuspec_extractor_target_exists_with_cli_args_with_valid_nuspec_path(cli_args_with_valid_nuspec_path: Namespace):
+ extractor:NuspecExtractor = NuspecExtractor(cli_args=cli_args_with_valid_nuspec_path)
+ assert extractor.target_exists is True
+
+def test_nuspec_extractor_target_cli_parameter_name_with_cli_args_with_valid_nuspec_path(cli_args_with_valid_nuspec_path: Namespace):
+ extractor:NuspecExtractor = NuspecExtractor(cli_args=cli_args_with_valid_nuspec_path)
+ assert extractor.target_cli_parameter_name == '--nuspec-path'
\ No newline at end of file
diff --git a/tests/extractors/test_pom_xml_extractor.py b/tests/extractors/test_pom_xml_extractor.py
new file mode 100644
index 0000000..523808b
--- /dev/null
+++ b/tests/extractors/test_pom_xml_extractor.py
@@ -0,0 +1,37 @@
+from argparse import Namespace
+from pathlib import Path
+
+from same_version.extractors.pom_xml_extractor import PomXmlExtractor
+
+
+def test_pom_xml_extractor_extract_version_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:PomXmlExtractor = PomXmlExtractor(cli_args=empty_cli_args)
+ assert extractor.extract_version() is None
+
+def test_pom_xml_extractor_target_parameter_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:PomXmlExtractor = PomXmlExtractor(cli_args=empty_cli_args)
+ assert extractor.target_name == 'pom.xml'
+
+def test_pom_xml_extractor_target_exists_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:PomXmlExtractor = PomXmlExtractor(cli_args=empty_cli_args)
+ assert extractor.target_exists is False
+
+def test_pom_xml_extractor_target_cli_parameter_name_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:PomXmlExtractor = PomXmlExtractor(cli_args=empty_cli_args)
+ assert extractor.target_cli_parameter_name == '--pom-xml-path'
+
+def test_pom_xml_extractor_extract_version_with_cli_args_with_valid_pom_xml_path(cli_args_with_valid_pom_xml_path: Namespace):
+ extractor:PomXmlExtractor = PomXmlExtractor(cli_args=cli_args_with_valid_pom_xml_path)
+ assert extractor.extract_version() == '1.2.3'
+
+def test_pom_xml_extractor_target_parameter_with_cli_args_with_valid_pom_xml_path(cli_args_with_valid_pom_xml_path: Namespace):
+ extractor:PomXmlExtractor = PomXmlExtractor(cli_args=cli_args_with_valid_pom_xml_path)
+ assert extractor.target_name is not None and Path(extractor.target_name).name == 'pom.xml'
+
+def test_pom_xml_extractor_target_exists_with_cli_args_with_valid_pom_xml_path(cli_args_with_valid_pom_xml_path: Namespace):
+ extractor:PomXmlExtractor = PomXmlExtractor(cli_args=cli_args_with_valid_pom_xml_path)
+ assert extractor.target_exists is True
+
+def test_pom_xml_extractor_target_cli_parameter_name_with_cli_args_with_valid_pom_xml_path(cli_args_with_valid_pom_xml_path: Namespace):
+ extractor:PomXmlExtractor = PomXmlExtractor(cli_args=cli_args_with_valid_pom_xml_path)
+ assert extractor.target_cli_parameter_name == '--pom-xml-path'
\ No newline at end of file
diff --git a/tests/extractors/test_py_version_assignment_extractor.py b/tests/extractors/test_py_version_assignment_extractor.py
new file mode 100644
index 0000000..b70274e
--- /dev/null
+++ b/tests/extractors/test_py_version_assignment_extractor.py
@@ -0,0 +1,39 @@
+from argparse import Namespace
+from pathlib import Path
+
+from same_version.extractors.py_version_assignment_extractor import (
+ PyVersionAssignmentExtractor,
+)
+
+
+def test_py_version_assignment_extractor_extract_version_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:PyVersionAssignmentExtractor = PyVersionAssignmentExtractor(cli_args=empty_cli_args)
+ assert extractor.extract_version() is None
+
+def test_py_version_assignment_extractor_target_parameter_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:PyVersionAssignmentExtractor = PyVersionAssignmentExtractor(cli_args=empty_cli_args)
+ assert extractor.target_name == "Python file with __version__ assignment to a literal string"
+
+def test_py_version_assignment_extractor_target_exists_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:PyVersionAssignmentExtractor = PyVersionAssignmentExtractor(cli_args=empty_cli_args)
+ assert extractor.target_exists is False
+
+def test_py_version_assignment_extractor_target_cli_parameter_name_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:PyVersionAssignmentExtractor = PyVersionAssignmentExtractor(cli_args=empty_cli_args)
+ assert extractor.target_cli_parameter_name == '--py-version-assignment-path'
+
+def test_py_version_assignment_extractor_extract_version_with_cli_args_with_valid_py_version_assignment_path(cli_args_with_valid_py_version_assignment_path: Namespace):
+ extractor:PyVersionAssignmentExtractor = PyVersionAssignmentExtractor(cli_args=cli_args_with_valid_py_version_assignment_path)
+ assert extractor.extract_version() == '15.2.4'
+
+def test_py_version_assignment_extractor_target_parameter_with_cli_args_with_valid_py_version_assignment_path(cli_args_with_valid_py_version_assignment_path: Namespace):
+ extractor:PyVersionAssignmentExtractor = PyVersionAssignmentExtractor(cli_args=cli_args_with_valid_py_version_assignment_path)
+ assert extractor.target_name is not None and Path(extractor.target_name).name == 'main_with_literal_version_assignment.py'
+
+def test_py_version_assignment_extractor_target_exists_with_cli_args_with_valid_py_version_assignment_path(cli_args_with_valid_py_version_assignment_path: Namespace):
+ extractor:PyVersionAssignmentExtractor = PyVersionAssignmentExtractor(cli_args=cli_args_with_valid_py_version_assignment_path)
+ assert extractor.target_exists is True
+
+def test_py_version_assignment_extractor_target_cli_parameter_name_with_cli_args_with_valid_py_version_assignment_path(cli_args_with_valid_py_version_assignment_path: Namespace):
+ extractor:PyVersionAssignmentExtractor = PyVersionAssignmentExtractor(cli_args=cli_args_with_valid_py_version_assignment_path)
+ assert extractor.target_cli_parameter_name == '--py-version-assignment-path'
\ No newline at end of file
diff --git a/tests/extractors/test_pyproject_toml_extractor.py b/tests/extractors/test_pyproject_toml_extractor.py
new file mode 100644
index 0000000..b3d6180
--- /dev/null
+++ b/tests/extractors/test_pyproject_toml_extractor.py
@@ -0,0 +1,37 @@
+from argparse import Namespace
+from pathlib import Path
+
+from same_version.extractors.pyproject_toml_extractor import PyprojectTomlExtractor
+
+
+def test_pyproject_toml_extractor_extract_version_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:PyprojectTomlExtractor = PyprojectTomlExtractor(cli_args=empty_cli_args)
+ assert extractor.extract_version() is None
+
+def test_pyproject_toml_extractor_target_parameter_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:PyprojectTomlExtractor = PyprojectTomlExtractor(cli_args=empty_cli_args)
+ assert extractor.target_name == 'pyproject.toml'
+
+def test_pyproject_toml_extractor_target_exists_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:PyprojectTomlExtractor = PyprojectTomlExtractor(cli_args=empty_cli_args)
+ assert extractor.target_exists is False
+
+def test_pyproject_toml_extractor_target_cli_parameter_name_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:PyprojectTomlExtractor = PyprojectTomlExtractor(cli_args=empty_cli_args)
+ assert extractor.target_cli_parameter_name == '--pyproject-toml-path'
+
+def test_pyproject_toml_extractor_extract_version_with_cli_args_with_valid_pyproject_toml_path(cli_args_with_valid_pyproject_toml_path: Namespace):
+ extractor:PyprojectTomlExtractor = PyprojectTomlExtractor(cli_args=cli_args_with_valid_pyproject_toml_path)
+ assert extractor.extract_version() == '8.7.6'
+
+def test_pyproject_toml_extractor_target_parameter_with_cli_args_with_valid_pyproject_toml_path(cli_args_with_valid_pyproject_toml_path: Namespace):
+ extractor:PyprojectTomlExtractor = PyprojectTomlExtractor(cli_args=cli_args_with_valid_pyproject_toml_path)
+ assert extractor.target_name is not None and Path(extractor.target_name).name == 'pyproject.toml'
+
+def test_pyproject_toml_extractor_target_exists_with_cli_args_with_valid_pyproject_toml_path(cli_args_with_valid_pyproject_toml_path: Namespace):
+ extractor:PyprojectTomlExtractor = PyprojectTomlExtractor(cli_args=cli_args_with_valid_pyproject_toml_path)
+ assert extractor.target_exists is True
+
+def test_pyproject_toml_extractor_target_cli_parameter_name_with_cli_args_with_valid_pyproject_toml_path(cli_args_with_valid_pyproject_toml_path: Namespace):
+ extractor:PyprojectTomlExtractor = PyprojectTomlExtractor(cli_args=cli_args_with_valid_pyproject_toml_path)
+ assert extractor.target_cli_parameter_name == '--pyproject-toml-path'
\ No newline at end of file
diff --git a/tests/extractors/test_r_description_extractor.py b/tests/extractors/test_r_description_extractor.py
new file mode 100644
index 0000000..99c9a8d
--- /dev/null
+++ b/tests/extractors/test_r_description_extractor.py
@@ -0,0 +1,37 @@
+from argparse import Namespace
+from pathlib import Path
+
+from same_version.extractors.r_description_extractor import RDescriptionExtractor
+
+
+def test_r_description_extractor_extract_version_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:RDescriptionExtractor = RDescriptionExtractor(cli_args=empty_cli_args)
+ assert extractor.extract_version() is None
+
+def test_r_description_extractor_target_parameter_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:RDescriptionExtractor = RDescriptionExtractor(cli_args=empty_cli_args)
+ assert extractor.target_name == 'DESCRIPTION'
+
+def test_r_description_extractor_target_exists_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:RDescriptionExtractor = RDescriptionExtractor(cli_args=empty_cli_args)
+ assert extractor.target_exists is False
+
+def test_r_description_extractor_target_cli_parameter_name_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:RDescriptionExtractor = RDescriptionExtractor(cli_args=empty_cli_args)
+ assert extractor.target_cli_parameter_name == '--r-description-path'
+
+def test_r_description_extractor_extract_version_with_cli_args_with_valid_r_description_path(cli_args_with_valid_r_description_path: Namespace):
+ extractor:RDescriptionExtractor = RDescriptionExtractor(cli_args=cli_args_with_valid_r_description_path)
+ assert extractor.extract_version() == '3.1.4'
+
+def test_r_description_extractor_target_parameter_with_cli_args_with_valid_r_description_path(cli_args_with_valid_r_description_path: Namespace):
+ extractor:RDescriptionExtractor = RDescriptionExtractor(cli_args=cli_args_with_valid_r_description_path)
+ assert extractor.target_name is not None and Path(extractor.target_name).name == 'DESCRIPTION'
+
+def test_r_description_extractor_target_exists_with_cli_args_with_valid_r_description_path(cli_args_with_valid_r_description_path: Namespace):
+ extractor:RDescriptionExtractor = RDescriptionExtractor(cli_args=cli_args_with_valid_r_description_path)
+ assert extractor.target_exists is True
+
+def test_r_description_extractor_target_cli_parameter_name_with_cli_args_with_valid_r_description_path(cli_args_with_valid_r_description_path: Namespace):
+ extractor:RDescriptionExtractor = RDescriptionExtractor(cli_args=cli_args_with_valid_r_description_path)
+ assert extractor.target_cli_parameter_name == '--r-description-path'
\ No newline at end of file
diff --git a/tests/extractors/test_ro_crate_metadata_json_extractor.py b/tests/extractors/test_ro_crate_metadata_json_extractor.py
new file mode 100644
index 0000000..c54d936
--- /dev/null
+++ b/tests/extractors/test_ro_crate_metadata_json_extractor.py
@@ -0,0 +1,39 @@
+from argparse import Namespace
+from pathlib import Path
+
+from same_version.extractors.ro_crate_metadata_json_extractor import (
+ RoCrateMetadataJsonExtractor,
+)
+
+
+def test_ro_crate_metadata_json_extractor_extract_version_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:RoCrateMetadataJsonExtractor = RoCrateMetadataJsonExtractor(cli_args=empty_cli_args)
+ assert extractor.extract_version() is None
+
+def test_ro_crate_metadata_json_extractor_target_parameter_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:RoCrateMetadataJsonExtractor = RoCrateMetadataJsonExtractor(cli_args=empty_cli_args)
+ assert extractor.target_name == 'ro-crate-metadata.json'
+
+def test_ro_crate_metadata_json_extractor_target_exists_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:RoCrateMetadataJsonExtractor = RoCrateMetadataJsonExtractor(cli_args=empty_cli_args)
+ assert extractor.target_exists is False
+
+def test_ro_crate_metadata_json_extractor_target_cli_parameter_name_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:RoCrateMetadataJsonExtractor = RoCrateMetadataJsonExtractor(cli_args=empty_cli_args)
+ assert extractor.target_cli_parameter_name == '--ro-crate-metadata-json-path'
+
+def test_ro_crate_metadata_json_extractor_extract_version_with_cli_args_with_valid_ro_crate_metadata_json_path_and_id(cli_args_with_valid_ro_crate_metadata_json_path_and_id: Namespace):
+ extractor:RoCrateMetadataJsonExtractor = RoCrateMetadataJsonExtractor(cli_args=cli_args_with_valid_ro_crate_metadata_json_path_and_id)
+ assert extractor.extract_version() == '7.2.5'
+
+def test_ro_crate_metadata_json_extractor_target_parameter_with_cli_args_with_valid_ro_crate_metadata_json_path_and_id(cli_args_with_valid_ro_crate_metadata_json_path_and_id: Namespace):
+ extractor:RoCrateMetadataJsonExtractor = RoCrateMetadataJsonExtractor(cli_args=cli_args_with_valid_ro_crate_metadata_json_path_and_id)
+ assert extractor.target_name is not None and Path(extractor.target_name).name == 'ro-crate-metadata.json'
+
+def test_ro_crate_metadata_json_extractor_target_exists_with_cli_args_with_valid_ro_crate_metadata_json_path_and_id(cli_args_with_valid_ro_crate_metadata_json_path_and_id: Namespace):
+ extractor:RoCrateMetadataJsonExtractor = RoCrateMetadataJsonExtractor(cli_args=cli_args_with_valid_ro_crate_metadata_json_path_and_id)
+ assert extractor.target_exists is True
+
+def test_ro_crate_metadata_json_extractor_target_cli_parameter_name_with_cli_args_with_valid_ro_crate_metadata_json_path_and_id(cli_args_with_valid_ro_crate_metadata_json_path_and_id: Namespace):
+ extractor:RoCrateMetadataJsonExtractor = RoCrateMetadataJsonExtractor(cli_args=cli_args_with_valid_ro_crate_metadata_json_path_and_id)
+ assert extractor.target_cli_parameter_name == '--ro-crate-metadata-json-path'
\ No newline at end of file
diff --git a/tests/extractors/test_setup_cfg_extractor.py b/tests/extractors/test_setup_cfg_extractor.py
new file mode 100644
index 0000000..631f050
--- /dev/null
+++ b/tests/extractors/test_setup_cfg_extractor.py
@@ -0,0 +1,37 @@
+from argparse import Namespace
+from pathlib import Path
+
+from same_version.extractors.setup_cfg_extractor import SetupCfgExtractor
+
+
+def test_setup_cfg_extractor_extract_version_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:SetupCfgExtractor = SetupCfgExtractor(cli_args=empty_cli_args)
+ assert extractor.extract_version() is None
+
+def test_setup_cfg_extractor_target_parameter_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:SetupCfgExtractor = SetupCfgExtractor(cli_args=empty_cli_args)
+ assert extractor.target_name == 'setup.cfg'
+
+def test_setup_cfg_extractor_target_exists_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:SetupCfgExtractor = SetupCfgExtractor(cli_args=empty_cli_args)
+ assert extractor.target_exists is False
+
+def test_setup_cfg_extractor_target_cli_parameter_name_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:SetupCfgExtractor = SetupCfgExtractor(cli_args=empty_cli_args)
+ assert extractor.target_cli_parameter_name == '--setup-cfg-path'
+
+def test_setup_cfg_extractor_extract_version_with_cli_args_with_valid_setup_cfg_path(cli_args_with_valid_setup_cfg_path: Namespace):
+ extractor:SetupCfgExtractor = SetupCfgExtractor(cli_args=cli_args_with_valid_setup_cfg_path)
+ assert extractor.extract_version() == '9.0.3'
+
+def test_setup_cfg_extractor_target_parameter_with_cli_args_with_valid_setup_cfg_path(cli_args_with_valid_setup_cfg_path: Namespace):
+ extractor:SetupCfgExtractor = SetupCfgExtractor(cli_args=cli_args_with_valid_setup_cfg_path)
+ assert extractor.target_name is not None and Path(extractor.target_name).name == 'setup.cfg'
+
+def test_setup_cfg_extractor_target_exists_with_cli_args_with_valid_setup_cfg_path(cli_args_with_valid_setup_cfg_path: Namespace):
+ extractor:SetupCfgExtractor = SetupCfgExtractor(cli_args=cli_args_with_valid_setup_cfg_path)
+ assert extractor.target_exists is True
+
+def test_setup_cfg_extractor_target_cli_parameter_name_with_cli_args_with_valid_setup_cfg_path(cli_args_with_valid_setup_cfg_path: Namespace):
+ extractor:SetupCfgExtractor = SetupCfgExtractor(cli_args=cli_args_with_valid_setup_cfg_path)
+ assert extractor.target_cli_parameter_name == '--setup-cfg-path'
\ No newline at end of file
diff --git a/tests/extractors/test_setup_py_extractor.py b/tests/extractors/test_setup_py_extractor.py
new file mode 100644
index 0000000..ee9abba
--- /dev/null
+++ b/tests/extractors/test_setup_py_extractor.py
@@ -0,0 +1,37 @@
+from argparse import Namespace
+from pathlib import Path
+
+from same_version.extractors.setup_py_extractor import SetupPyExtractor
+
+
+def test_setup_py_extractor_extract_version_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:SetupPyExtractor = SetupPyExtractor(cli_args=empty_cli_args)
+ assert extractor.extract_version() is None
+
+def test_setup_py_extractor_target_parameter_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:SetupPyExtractor = SetupPyExtractor(cli_args=empty_cli_args)
+ assert extractor.target_name == 'setup.py'
+
+def test_setup_py_extractor_target_exists_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:SetupPyExtractor = SetupPyExtractor(cli_args=empty_cli_args)
+ assert extractor.target_exists is False
+
+def test_setup_py_extractor_target_cli_parameter_name_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:SetupPyExtractor = SetupPyExtractor(cli_args=empty_cli_args)
+ assert extractor.target_cli_parameter_name == '--setup-py-path'
+
+def test_setup_py_extractor_extract_version_with_cli_args_with_valid_setup_py_path(cli_args_with_valid_setup_py_path: Namespace):
+ extractor:SetupPyExtractor = SetupPyExtractor(cli_args=cli_args_with_valid_setup_py_path)
+ assert extractor.extract_version() == '8.3.7'
+
+def test_setup_py_extractor_target_parameter_with_cli_args_with_valid_setup_py_path(cli_args_with_valid_setup_py_path: Namespace):
+ extractor:SetupPyExtractor = SetupPyExtractor(cli_args=cli_args_with_valid_setup_py_path)
+ assert extractor.target_name is not None and Path(extractor.target_name).name == 'setup.py'
+
+def test_setup_py_extractor_target_exists_with_cli_args_with_valid_setup_py_path(cli_args_with_valid_setup_py_path: Namespace):
+ extractor:SetupPyExtractor = SetupPyExtractor(cli_args=cli_args_with_valid_setup_py_path)
+ assert extractor.target_exists is True
+
+def test_setup_py_extractor_target_cli_parameter_name_with_cli_args_with_valid_setup_py_path(cli_args_with_valid_setup_py_path: Namespace):
+ extractor:SetupPyExtractor = SetupPyExtractor(cli_args=cli_args_with_valid_setup_py_path)
+ assert extractor.target_cli_parameter_name == '--setup-py-path'
\ No newline at end of file
diff --git a/tests/extractors/test_zenodo_json_extractor.py b/tests/extractors/test_zenodo_json_extractor.py
new file mode 100644
index 0000000..01fcc7c
--- /dev/null
+++ b/tests/extractors/test_zenodo_json_extractor.py
@@ -0,0 +1,37 @@
+from argparse import Namespace
+from pathlib import Path
+
+from same_version.extractors.zenodo_json_extractor import ZenodoJsonExtractor
+
+
+def test_zenodo_json_extractor_extract_version_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:ZenodoJsonExtractor = ZenodoJsonExtractor(cli_args=empty_cli_args)
+ assert extractor.extract_version() is None
+
+def test_zenodo_json_extractor_target_parameter_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:ZenodoJsonExtractor = ZenodoJsonExtractor(cli_args=empty_cli_args)
+ assert extractor.target_name == '.zenodo.json'
+
+def test_zenodo_json_extractor_target_exists_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:ZenodoJsonExtractor = ZenodoJsonExtractor(cli_args=empty_cli_args)
+ assert extractor.target_exists is False
+
+def test_zenodo_json_extractor_target_cli_parameter_name_with_empty_cli_args(empty_cli_args: Namespace):
+ extractor:ZenodoJsonExtractor = ZenodoJsonExtractor(cli_args=empty_cli_args)
+ assert extractor.target_cli_parameter_name == '--zenodo-json-path'
+
+def test_zenodo_json_extractor_extract_version_with_cli_args_with_valid_zenodo_json_path(cli_args_with_valid_zenodo_json_path: Namespace):
+ extractor:ZenodoJsonExtractor = ZenodoJsonExtractor(cli_args=cli_args_with_valid_zenodo_json_path)
+ assert extractor.extract_version() == '4.2.6'
+
+def test_zenodo_json_extractor_target_parameter_with_cli_args_with_valid_zenodo_json_path(cli_args_with_valid_zenodo_json_path: Namespace):
+ extractor:ZenodoJsonExtractor = ZenodoJsonExtractor(cli_args=cli_args_with_valid_zenodo_json_path)
+ assert extractor.target_name is not None and Path(extractor.target_name).name == '.zenodo.json'
+
+def test_zenodo_json_extractor_target_exists_with_cli_args_with_valid_zenodo_json_path(cli_args_with_valid_zenodo_json_path: Namespace):
+ extractor:ZenodoJsonExtractor = ZenodoJsonExtractor(cli_args=cli_args_with_valid_zenodo_json_path)
+ assert extractor.target_exists is True
+
+def test_zenodo_json_extractor_target_cli_parameter_name_with_cli_args_with_valid_zenodo_json_path(cli_args_with_valid_zenodo_json_path: Namespace):
+ extractor:ZenodoJsonExtractor = ZenodoJsonExtractor(cli_args=cli_args_with_valid_zenodo_json_path)
+ assert extractor.target_cli_parameter_name == '--zenodo-json-path'
\ No newline at end of file
diff --git a/tests/test_data/.nuspec b/tests/test_data/.nuspec
new file mode 100644
index 0000000..e78267f
--- /dev/null
+++ b/tests/test_data/.nuspec
@@ -0,0 +1,15 @@
+
+
+
+ My.Dummy.App
+ 4.8.12
+ My Dummy App
+ Test Author
+ Test Author
+ false
+ A dummy NuGet package for unit testing.
+ Initial dummy release.
+ Copyright 2025
+ dummy test unit-test
+
+
diff --git a/tests/test_data/.zenodo.json b/tests/test_data/.zenodo.json
new file mode 100644
index 0000000..a2224a8
--- /dev/null
+++ b/tests/test_data/.zenodo.json
@@ -0,0 +1,21 @@
+{
+ "title": "My Dummy App",
+ "version": "4.2.6",
+ "description": "A dummy app for unit testing.",
+ "creators": [
+ {
+ "name": "Test Author",
+ "affiliation": "Example Institute",
+ "orcid": "0000-0000-0000-0000"
+ }
+ ],
+ "license": "MIT",
+ "upload_type": "software",
+ "publication_date": "2024-06-14",
+ "keywords": [
+ "dummy",
+ "test",
+ "unit test"
+ ],
+ "access_right": "open"
+}
\ No newline at end of file
diff --git a/tests/test_data/CITATION.cff b/tests/test_data/CITATION.cff
new file mode 100644
index 0000000..58e9ee1
--- /dev/null
+++ b/tests/test_data/CITATION.cff
@@ -0,0 +1,14 @@
+cff-version: 1.2.0
+message: "If you use this software, please cite it as below."
+title: "My Dummy App"
+version: "0.0.8000"
+doi: 10.5281/zenodo.1234567
+authors:
+ - family-names: Author
+ given-names: Test
+ affiliation: Example Institute
+ orcid: https://orcid.org/0000-0000-0000-0000
+date-released: 2025-06-14
+license: MIT
+repository-code: https://github.com/example/my-dummy-app
+url: https://github.com/example/my-dummy-app
diff --git a/tests/test_data/Cargo.toml b/tests/test_data/Cargo.toml
new file mode 100644
index 0000000..a7592e3
--- /dev/null
+++ b/tests/test_data/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "my-dummy-app"
+version = "10.0.8"
+authors = ["Test Author "]
+edition = "2021"
+description = "A dummy Rust app for unit testing."
+license = "MIT"
+
+[dependencies]
+serde = { version = "1.0", features = ["derive"] }
diff --git a/tests/test_data/DESCRIPTION b/tests/test_data/DESCRIPTION
new file mode 100644
index 0000000..e029388
--- /dev/null
+++ b/tests/test_data/DESCRIPTION
@@ -0,0 +1,11 @@
+Package: mydummyapp
+Type: Package
+Title: A Dummy App for Unit Testing
+Version: 3.1.4
+Author: Test Author [aut]
+Maintainer: Test Author
+Description: A dummy R package to use for unit testing of metadata parsers.
+License: MIT
+Encoding: UTF-8
+LazyData: true
+RoxygenNote: 7.1.1
diff --git a/tests/test_data/codemeta.json b/tests/test_data/codemeta.json
new file mode 100644
index 0000000..50c0ea4
--- /dev/null
+++ b/tests/test_data/codemeta.json
@@ -0,0 +1,15 @@
+{
+ "@context": "https://doi.org/10.5063/schema/codemeta-2.0",
+ "@type": "SoftwareSourceCode",
+ "name": "my-dummy-app",
+ "version": "13.9.4",
+ "description": "A dummy app for unit testing.",
+ "author": {
+ "@type": "Person",
+ "name": "Test Author",
+ "email": "author@example.com"
+ },
+ "license": "MIT",
+ "programmingLanguage": "Python",
+ "identifier": "https://github.com/example/my-dummy-app"
+}
\ No newline at end of file
diff --git a/tests/test_data/composer.json b/tests/test_data/composer.json
new file mode 100644
index 0000000..3c7dff3
--- /dev/null
+++ b/tests/test_data/composer.json
@@ -0,0 +1,22 @@
+{
+ "name": "example/my-dummy-app",
+ "description": "A dummy PHP app for unit testing.",
+ "version": "6.0.8",
+ "type": "project",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Test Author",
+ "email": "author@example.com"
+ }
+ ],
+ "require": {
+ "php": ">=7.4",
+ "monolog/monolog": "^2.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "MyDummyApp\\": "src/"
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/test_data/main_with_literal_version_assignment.py b/tests/test_data/main_with_literal_version_assignment.py
new file mode 100644
index 0000000..30fe614
--- /dev/null
+++ b/tests/test_data/main_with_literal_version_assignment.py
@@ -0,0 +1,12 @@
+# version_metadata.py
+
+"""
+My Dummy App
+"""
+
+__author__ = "Test Author"
+__email__ = "author@example.com"
+__version__ = "15.2.4"
+
+def main():
+ print("Hello world")
diff --git a/tests/test_data/pom.xml b/tests/test_data/pom.xml
new file mode 100644
index 0000000..ef2eedd
--- /dev/null
+++ b/tests/test_data/pom.xml
@@ -0,0 +1,13 @@
+
+ 4.0.0
+
+ com.example
+ my-app
+ 1.2.3
+
+ My Dummy App
+ A dummy pom for unit testing.
+
diff --git a/tests/test_data/pyproject.toml b/tests/test_data/pyproject.toml
new file mode 100644
index 0000000..3673759
--- /dev/null
+++ b/tests/test_data/pyproject.toml
@@ -0,0 +1,14 @@
+[project]
+name = "my-dummy-app"
+version = "8.7.6"
+description = "A dummy app for unit testing."
+authors = [
+ { name = "Test Author", email = "author@example.com" }
+]
+dependencies = [
+ "requests >=2.0.0"
+]
+
+[build-system]
+requires = ["setuptools>=61.0"]
+build-backend = "setuptools.build_meta"
diff --git a/tests/test_data/ro-crate-metadata.json b/tests/test_data/ro-crate-metadata.json
new file mode 100644
index 0000000..0a2c507
--- /dev/null
+++ b/tests/test_data/ro-crate-metadata.json
@@ -0,0 +1,53 @@
+{
+ "@context": [
+ "https://w3id.org/ro/crate/1.1/context",
+ {
+ "@vocab": "https://schema.org/",
+ "ro": "https://w3id.org/ro/terms/"
+ }
+ ],
+ "@graph": [
+ {
+ "@id": "ro-crate-metadata.json",
+ "@type": "CreativeWork",
+ "about": {
+ "@id": "./"
+ }
+ },
+ {
+ "@id": "./",
+ "@type": "Dataset",
+ "name": "My Dummy RO-Crate for Unit Testing",
+ "description": "A dummy RO-Crate used for metadata unit testing.",
+ "license": {
+ "@id": "https://opensource.org/licenses/MIT"
+ },
+ "author": {
+ "@type": "Person",
+ "name": "Test Author",
+ "affiliation": {
+ "@type": "Organization",
+ "name": "Example Institute"
+ }
+ },
+ "datePublished": "2025-06-14",
+ "hasPart": {
+ "@id": "software/"
+ }
+ },
+ {
+ "@id": "software/",
+ "@type": "SoftwareSourceCode",
+ "name": "My Dummy App",
+ "version": "7.2.5",
+ "programmingLanguage": {
+ "@type": "ComputerLanguage",
+ "name": "Python"
+ },
+ "license": {
+ "@id": "https://opensource.org/licenses/MIT"
+ },
+ "codeRepository": "https://github.com/example/my-dummy-app"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/tests/test_data/setup.cfg b/tests/test_data/setup.cfg
new file mode 100644
index 0000000..922722c
--- /dev/null
+++ b/tests/test_data/setup.cfg
@@ -0,0 +1,23 @@
+[metadata]
+name = my-dummy-app
+version = 9.0.3
+description = A dummy app for unit testing.
+author = Test Author
+author_email = author@example.com
+license = MIT
+url = https://github.com/example/my-dummy-app
+classifiers =
+ Programming Language :: Python :: 3
+ License :: OSI Approved :: MIT License
+ Development Status :: 4 - Beta
+
+[options]
+packages = find:
+python_requires = >=3.7
+install_requires =
+ requests >=2.0.0
+
+[options.extras_require]
+dev =
+ pytest
+ flake8
diff --git a/tests/test_data/setup.py b/tests/test_data/setup.py
new file mode 100644
index 0000000..cfccbd9
--- /dev/null
+++ b/tests/test_data/setup.py
@@ -0,0 +1,27 @@
+from setuptools import find_packages, setup
+
+setup(
+ name="my-dummy-app",
+ version="8.3.7",
+ description="A dummy app for unit testing.",
+ author="Test Author",
+ author_email="author@example.com",
+ url="https://github.com/example/my-dummy-app",
+ license="MIT",
+ packages=find_packages(),
+ python_requires=">=3.7",
+ install_requires=[
+ "requests>=2.0.0"
+ ],
+ extras_require={
+ "dev": [
+ "pytest",
+ "flake8"
+ ]
+ },
+ classifiers=[
+ "Programming Language :: Python :: 3",
+ "License :: OSI Approved :: MIT License",
+ "Development Status :: 4 - Beta"
+ ]
+)