Skip to main content

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 a str subclass -- zero overhead after construction
  • Each ref() call appends to ref._registry and captures the caller's file/line via sys._getframe()
  • validate_refs() uses importlib.util.find_spec() to check modules. When verifying attributes, it imports the parent module via importlib.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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

symref-0.1.0.tar.gz (9.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

symref-0.1.0-py3-none-any.whl (6.0 kB view details)

Uploaded Python 3

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

Hashes for symref-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c5bacbeabd871723409216369ba1c7cf616bf87bbc519239c304fba625fc89ba
MD5 ab9828f9d08cc198badbc8ddc69b09b8
BLAKE2b-256 b4ced562cfaafd1967331766be678a70598eeb913b931d32c25c3f9a12ab5572

See more details on using hashes here.

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

Hashes for symref-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 48dcbe248427b5019f9f39b1c83b442462131a34a1390db262210528be1fc86d
MD5 b96434850d1df2185d840c17e9f8f68f
BLAKE2b-256 17e14d20a12909cc99bf307adf204d6a6a934116d8575e94c0a851180a11c813

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page