referencing is currently in beta so long as version numbers begin with a 0, meaning its public interface may change if issues are uncovered, though not typically without reason. Once it seems clear that the interfaces look correct (likely after referencing is in use for some period of time) versioning will move to CalVer and interfaces will not change in backwards-incompatible ways without deprecation periods.


Backwards compatibility is always defined relative to the specifications we implement. Changing a behavior which is incorrect according to the relevant referencing specifications is not considered a backwards-incompatible change – on the contrary, it’s considered a bug fix.

In the spirit of having some explicit detail on referencing's public interfaces, here is a non-exhaustive list of things which are not part of the referencing public interface, and therefore which may change without warning, even once no longer in beta:

  • All commonly understood indicators of privacy in Python – in particular, (sub)packages, modules and identifiers beginning with a single underscore. In the case of modules or packages, this includes all of their contents recursively, regardless of their naming.

  • All contents in the referencing.tests package unless explicitly indicated otherwise

  • The precise contents and wording of exception messages raised by any callable, private or public.

  • The precise contents of the __repr__ of any type defined in the package.

  • The ability to instantiate exceptions defined in referencing.exceptions, with the sole exception of those explicitly indicating they are publicly instantiable (notably referencing.exceptions.NoSuchResource).

  • The instantiation of any type with no public identifier, even if instances of it are returned by other public API. E.g., referencing._core.Resolver is not publicly exposed, and it is not public API to instantiate it in ways other than by calling referencing.Registry.resolver or an equivalent. All of its public attributes are of course public, however.

  • The concrete types within the signature of a callable whenever they differ from their documented types. In other words, if a function documents that it returns an argument of type Mapping[int, Sequence[str]], this is the promised return type, not whatever concrete type is returned which may be richer or have additional attributes and methods. Changes to the signature will continue to guarantee this return type (or a broader one) but indeed are free to change the concrete type.

  • Any identifiers in any modules which are imported from other modules. In other words, if imports bar from referencing.quux, it is not public API to use; only is public API. This does not apply to any objects exposed directly on the referencing package (e.g. referencing.Resource), which are indeed public.

  • Subclassing of any class defined throughout the package. Doing so is not supported for any object, and in general most types will raise exceptions to remind downstream users not to do so.

If any API usage may be questionable, feel free to open a discussion (or issue if appropriate) to clarify.