Skip to content

Commit d643e09

Browse files
refactor: migrate test infrastructure to vcs_versioning.test_api
This commit creates a unified test infrastructure that can be used by both vcs-versioning and setuptools-scm test suites. Key changes: 1. Created vcs_versioning.test_api module: - Exports WorkDir, DebugMode, and test fixtures as a pytest plugin - Contains pytest hooks (pytest_configure, fixtures, etc.) - Can be imported via pytest_plugins = ['vcs_versioning.test_api'] 2. Moved WorkDir class: - testing/wd_wrapper.py -> vcs-versioning/src/vcs_versioning/_test_utils.py - Updated imports to use vcs_versioning modules 3. Renamed test directory to avoid pytest conflict: - nextgen/vcs-versioning/testing/ -> testingB/ - Added README explaining the pytest ImportPathMismatchError issue - pytest cannot distinguish between two 'testing/conftest.py' at different locations 4. Migrated backend tests to vcs-versioning: - testing/test_git.py -> testingB/test_git.py - testing/test_mercurial.py -> testingB/test_mercurial.py - testing/test_hg_git.py -> testingB/test_hg_git.py - Updated imports to use vcs_versioning backends conditionally 5. Updated all test imports: - setuptools_scm tests now use: from vcs_versioning.test_api import WorkDir - vcs-versioning tests use the same: from vcs_versioning.test_api import WorkDir - Removed all 'from testing.wd_wrapper import WorkDir' and 'from .wd_wrapper import WorkDir' 6. Simplified conftest files: - setuptools_scm/testing/conftest.py uses pytest_plugins - vcs-versioning/testingB/conftest.py uses pytest_plugins - Both delegate to vcs_versioning.test_api for common fixtures Test results: - All 408 tests pass across both packages - Can run tests together: pytest -n12 testing/ nextgen/vcs-versioning/testingB/ - No pytest path conflicts or import errors
1 parent 8c30e5a commit d643e09

23 files changed

+488
-152
lines changed

.wip/summary.md

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
# Refactoring Complete: Summary
2+
3+
## 🎉 Migration Status: COMPLETE
4+
5+
All planned phases of the refactoring have been successfully completed. The codebase has been split into two packages with full backward compatibility maintained.
6+
7+
## Package Structure
8+
9+
### vcs-versioning (Core Package)
10+
**Location**: `nextgen/vcs-versioning/`
11+
12+
**Purpose**: VCS-agnostic versioning logic
13+
14+
**Contents**:
15+
- **Public API**:
16+
- `Configuration` - Main configuration class
17+
- `ScmVersion` - Version representation
18+
- `Version` - Version class from packaging
19+
- `DEFAULT_*` constants
20+
21+
- **Private modules** (all prefixed with `_`):
22+
- `_backends/` - VCS implementations (git, hg, hg_git, scm_workdir)
23+
- `_version_schemes.py` - Version scheme implementations
24+
- `_discover.py` - SCM discovery logic
25+
- `_fallbacks.py` - Fallback version parsing
26+
- `_cli.py` - CLI implementation
27+
- `_get_version_impl.py` - Core version logic
28+
- And more utility modules...
29+
30+
**Entry Points**:
31+
- `setuptools_scm.parse_scm` - VCS parsers
32+
- `setuptools_scm.parse_scm_fallback` - Fallback parsers
33+
- `setuptools_scm.local_scheme` - Local version schemes
34+
- `setuptools_scm.version_scheme` - Version schemes
35+
- `vcs-versioning` script
36+
37+
**Tests**: 79 passing
38+
39+
### setuptools-scm (Integration Package)
40+
**Location**: Root directory
41+
42+
**Purpose**: Setuptools integration and file finders
43+
44+
**Contents**:
45+
- **Integration modules**:
46+
- `_integration/setuptools.py` - Setuptools hooks
47+
- `_integration/dump_version.py` - Version file writing
48+
- `_integration/pyproject_reading.py` - Extended with setuptools-specific logic
49+
- `_integration/version_inference.py` - Version inference
50+
51+
- **File finders** (setuptools-specific):
52+
- `_file_finders/` - Git/Hg file finder implementations
53+
54+
- **Re-export stubs** for backward compatibility:
55+
- Most core modules re-export from vcs_versioning
56+
57+
- **Public API**: Re-exports Configuration, get_version, etc.
58+
59+
**Entry Points**:
60+
- `setuptools_scm` script
61+
- `setuptools.finalize_distribution_options` hooks
62+
- `setuptools_scm.files_command` - File finders
63+
64+
**Tests**: 329 passing, 10 skipped, 1 xfailed
65+
66+
## Test Results
67+
68+
```
69+
✅ vcs-versioning: 79 passed
70+
✅ setuptools_scm: 329 passed, 10 skipped, 1 xfailed
71+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
72+
Total: 408 tests passing
73+
```
74+
75+
**Parallel execution time**: ~15 seconds with `-n12`
76+
77+
## Key Achievements
78+
79+
### ✅ Logging Unification
80+
- Separate root loggers for each package (`vcs_versioning`, `setuptools_scm`)
81+
- Entry point configuration at CLI and setuptools hooks
82+
- Central logger registry (`LOGGER_NAMES`)
83+
- Environment variables: `VCS_VERSIONING_DEBUG` and `SETUPTOOLS_SCM_DEBUG`
84+
- Standard Python pattern: `logging.getLogger(__name__)` everywhere
85+
86+
### ✅ Backward Compatibility
87+
- All public APIs maintained in `setuptools_scm`
88+
- Legacy `get_version()` function works
89+
- Entry point names unchanged from user perspective
90+
- Tool section names: `[tool.setuptools_scm]` continues to work
91+
92+
### ✅ Clean Separation
93+
- VCS backends are private in `vcs_versioning` (`_backends/`)
94+
- Version schemes are private (only configurable via entry points)
95+
- File finders remain in `setuptools_scm` (setuptools-specific)
96+
- Clear ownership: core logic in vcs_versioning, integration in setuptools_scm
97+
98+
### ✅ Build System
99+
- uv workspace configured
100+
- Both packages build successfully
101+
- Proper dependency management
102+
- `vcs-versioning` in `build-system.requires`
103+
104+
## Important Fixes Applied
105+
106+
1. **Empty tag regex warning**: Properly emitted via delegation to vcs_versioning.get_version()
107+
2. **Test mocks**: Fixed to patch actual module locations (not re-exports)
108+
3. **Backward compatibility**: Added `__main__.py` shim, fixed imports
109+
4. **Setuptools conflict warning**: Warns when `tool.setuptools.dynamic.version` conflicts with `setuptools-scm[simple]`
110+
5. **Module privacy**: Tests import private APIs directly from vcs_versioning
111+
112+
## Next Steps (Recommended)
113+
114+
### 1. CI/CD Validation
115+
- [ ] Push to GitHub and verify Actions pass
116+
- [ ] Ensure both packages are tested in CI
117+
- [ ] Verify matrix testing (Python 3.8-3.13)
118+
119+
### 2. Documentation
120+
- [ ] Update README.md to mention vcs-versioning
121+
- [ ] Add migration guide for users who want to use vcs-versioning directly
122+
- [ ] Document the split and which package to use when
123+
124+
### 3. Release Preparation
125+
- [ ] Update CHANGELOG.md
126+
- [ ] Decide on version numbers
127+
- [ ] Consider if this warrants a major version bump
128+
- [ ] Update NEWS/release notes
129+
130+
### 4. Additional Testing
131+
- [ ] Test with real projects that use setuptools_scm
132+
- [ ] Verify editable installs work
133+
- [ ] Test build backends besides setuptools (if applicable)
134+
135+
### 5. Community Communication
136+
- [ ] Announce the refactoring
137+
- [ ] Explain benefits to users
138+
- [ ] Provide migration path for advanced users
139+
140+
## File Structure Overview
141+
142+
```
143+
setuptools_scm/
144+
├── src/setuptools_scm/ # Integration package
145+
│ ├── __init__.py # Re-exports from vcs_versioning
146+
│ ├── _integration/ # Setuptools-specific
147+
│ └── _file_finders/ # File finding (setuptools)
148+
149+
└── nextgen/vcs-versioning/ # Core package
150+
├── src/vcs_versioning/
151+
│ ├── __init__.py # Public API
152+
│ ├── config.py # Configuration (public)
153+
│ ├── _backends/ # VCS implementations (private)
154+
│ ├── _version_schemes.py # Schemes (private)
155+
│ ├── _cli.py # CLI (private)
156+
│ └── ... # Other private modules
157+
└── testing/ # Core tests (79)
158+
```
159+
160+
## Commands Reference
161+
162+
```bash
163+
# Run all tests
164+
uv run pytest -n12
165+
166+
# Run setuptools_scm tests only
167+
uv run pytest testing/ -n12
168+
169+
# Run vcs-versioning tests only
170+
uv run pytest nextgen/vcs-versioning/testing/ -n12
171+
172+
# Sync dependencies
173+
uv sync
174+
175+
# Build packages
176+
uv build
177+
178+
# Run with debug logging
179+
VCS_VERSIONING_DEBUG=1 uv run python -m setuptools_scm
180+
SETUPTOOLS_SCM_DEBUG=1 uv run python -m setuptools_scm
181+
```
182+
183+
## Migration Notes
184+
185+
The refactoring maintains full backward compatibility. Users of setuptools-scm will see no breaking changes. The new vcs-versioning package is intended for:
186+
- Projects that don't use setuptools
187+
- Direct integration into other build systems
188+
- Standalone VCS version detection
189+
190+
## Conclusion
191+
192+
**The refactoring is complete and ready for review/merge.**
193+
194+
All planned work has been completed:
195+
- Code successfully split into two packages
196+
- Full test coverage maintained (408 tests passing)
197+
- Backward compatibility preserved
198+
- Clean separation of concerns
199+
- Logging properly unified
200+
- Ready for CI/CD validation
201+

nextgen/vcs-versioning/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ exclude_lines = [
101101
]
102102

103103
[tool.pytest.ini_options]
104-
testpaths = ["testing"]
104+
testpaths = ["testingB"]
105105
python_files = ["test_*.py"]
106106
addopts = ["-ra", "--strict-markers"]
107107
markers = [

testing/wd_wrapper.py renamed to nextgen/vcs-versioning/src/vcs_versioning/_test_utils.py

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,15 @@
99

1010
import pytest
1111

12-
from setuptools_scm._run_cmd import has_command
12+
from vcs_versioning._run_cmd import has_command
1313

1414
if TYPE_CHECKING:
15-
from setuptools_scm import Configuration
16-
from setuptools_scm.version import ScmVersion
17-
from setuptools_scm.version import VersionExpectations
18-
19-
if itertools: # Make mypy happy about unused import
20-
pass
21-
2215
import sys
2316

17+
from vcs_versioning._version_schemes import ScmVersion
18+
from vcs_versioning._version_schemes import VersionExpectations
19+
from vcs_versioning.config import Configuration
20+
2421
if sys.version_info >= (3, 11):
2522
from typing import Unpack
2623
else:
@@ -47,7 +44,7 @@ def __call__(self, cmd: list[str] | str, *, timeout: int = 10, **kw: object) ->
4744
if kw:
4845
assert isinstance(cmd, str), "formatting the command requires text input"
4946
cmd = cmd.format(**kw)
50-
from setuptools_scm._run_cmd import run
47+
from vcs_versioning._run_cmd import run
5148

5249
return run(cmd, cwd=self.cwd, timeout=timeout).stdout
5350

@@ -86,7 +83,7 @@ def commit_testfile(self, reason: str | None = None, signed: bool = False) -> No
8683

8784
def get_version(self, **kw: Any) -> str:
8885
__tracebackhide__ = True
89-
from setuptools_scm import get_version
86+
from vcs_versioning._get_version_impl import get_version
9087

9188
version = get_version(root=self.cwd, fallback_root=self.cwd, **kw)
9289
print(self.cwd.name, version, sep=": ")
@@ -151,7 +148,7 @@ def create_tag(self, tag: str = "1.0.0") -> None:
151148

152149
def configure_git_commands(self) -> None:
153150
"""Configure git commands without initializing the repository."""
154-
from setuptools_scm.git import parse as git_parse
151+
from vcs_versioning._backends._git import parse as git_parse
155152

156153
self.add_command = "git add ."
157154
self.commit_command = "git commit -m test-{reason}"
@@ -160,7 +157,7 @@ def configure_git_commands(self) -> None:
160157

161158
def configure_hg_commands(self) -> None:
162159
"""Configure mercurial commands without initializing the repository."""
163-
from setuptools_scm.hg import parse as hg_parse
160+
from vcs_versioning._backends._hg import parse as hg_parse
164161

165162
self.add_command = "hg add ."
166163
self.commit_command = 'hg commit -m test-{reason} -u test -d "0 0"'
@@ -227,7 +224,7 @@ def expect_parse(
227224
Uses the same signature as ScmVersion.matches() via TypedDict Unpack.
228225
"""
229226
__tracebackhide__ = True
230-
from setuptools_scm import Configuration
227+
from vcs_versioning.config import Configuration
231228

232229
if self.parse is None:
233230
raise RuntimeError(

0 commit comments

Comments
 (0)