Forward-referencing Python objects by dotted import path with refactor safety
Project description
symref
Refactor-safe forward references for Python dotted import paths.
Many frameworks (Celery, Django, etc.) accept dotted string paths as configuration. These strings are invisible to refactoring tools and IDEs -- renaming a module silently breaks them. symref wraps these paths in a str subclass that registers them for later validation, catching broken references in tests instead of production.
Installation
pip install symref
Requires Python 3.12+. No runtime dependencies.
Usage
from symref import ref
app.conf.task_routes = {
ref("myapp.tasks.send_email", kind="celery_task"): {"queue": "email"},
ref("myapp.tasks.process_order", kind="celery_task"): {"queue": "orders"},
}
ref() returns a plain str -- frameworks see no difference. But each call is recorded in a global registry with its source location.
Validate in tests
from symref import validate_refs
def test_all_refs_resolve():
validate_refs()
def test_celery_task_refs():
validate_refs(kind="celery_task")
If any path can't be resolved, validate_refs() raises SymrefError with all broken references and their source locations:
symref.SymrefError: 2 broken reference(s):
- "myapp.tasks.send_email" (defined in config/celery.py:8)
- "myapp.tasks.process_order" (defined in config/celery.py:9)
API
ref(path, *, kind=None)
Creates a forward reference. Returns a str subclass instance.
path-- fully qualified dotted import path (module or attribute)kind(optional) -- arbitrary label for filtering validation (e.g."celery_task","django_app")
validate_refs(kind=None)
Checks that every registered ref resolves to a real module or attribute. Raises SymrefError if any are broken. Pass kind to validate only refs with that label.
SymrefError
Raised when one or more refs can't be resolved. The .broken attribute contains the list of broken ref instances.
How it works
ref()is astrsubclass -- zero overhead after construction- Each
ref()call appends toref._registryand captures the caller's file/line viasys._getframe() validate_refs()usesimportlib.util.find_spec()to check modules. When verifying attributes, it imports the parent module viaimportlib.import_module()-- this may execute module-level code as a side effect- No imports happen at
ref()construction time -- validation is fully deferred
Documentation
Build and preview the docs locally:
uv run mkdocs serve
Then open http://127.0.0.1:8000.
Contributing
See CONTRIBUTING.md for development setup, testing, and PR guidelines.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file symref-0.1.0.tar.gz.
File metadata
- Download URL: symref-0.1.0.tar.gz
- Upload date:
- Size: 9.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c5bacbeabd871723409216369ba1c7cf616bf87bbc519239c304fba625fc89ba
|
|
| MD5 |
ab9828f9d08cc198badbc8ddc69b09b8
|
|
| BLAKE2b-256 |
b4ced562cfaafd1967331766be678a70598eeb913b931d32c25c3f9a12ab5572
|
File details
Details for the file symref-0.1.0-py3-none-any.whl.
File metadata
- Download URL: symref-0.1.0-py3-none-any.whl
- Upload date:
- Size: 6.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
48dcbe248427b5019f9f39b1c83b442462131a34a1390db262210528be1fc86d
|
|
| MD5 |
b96434850d1df2185d840c17e9f8f68f
|
|
| BLAKE2b-256 |
17e14d20a12909cc99bf307adf204d6a6a934116d8575e94c0a851180a11c813
|