Source code for prov.identifier

from __future__ import annotations  # needed for | type annotations in Python < 3.10

from typing import Any

__author__ = "Trung Dong Huynh"
__email__ = "trungdong@donggiang.com"


[docs] class Identifier: """Base class for all identifiers and also represents xsd:anyURI.""" # TODO: make Identifier an "abstract" base class and move xsd:anyURI # into a subclass def __init__(self, uri: str): """Create an identifier for the given URI. Args: uri: URI string for the identifier. Converted to ``str`` if not already one. """ self._uri: str = str(uri) # Ensure this is a unicode string @property def uri(self) -> str: """The URI associated with the current identifier.""" return self._uri def __str__(self) -> str: return self._uri def __eq__(self, other: Any) -> bool: return self.uri == other.uri if isinstance(other, Identifier) else False def __hash__(self) -> int: return hash((self.uri, self.__class__)) def __repr__(self) -> str: return f"<{self.__class__.__name__}: {self._uri}>"
[docs] def provn_representation(self) -> str: """Return the PROV-N representation of this identifier as an xsd:anyURI literal.""" return f'"{self._uri}" %% xsd:anyURI'
[docs] class QualifiedName(Identifier): """ Represents a `qualified name <https://www.w3.org/TR/prov-dm/#concept-qualifiedName>`_, which combines a namespace and a local part for use in identifying entities in a namespace-aware context. This class facilitates handling and manipulation of qualified names, which combine a namespace and a local identifier. It supports string representation, hashing, and retrieval of individual components (namespace or local part). """ def __init__(self, namespace: Namespace, localpart: str): """ Initializes a new qualified name with the provided namespace and localpart values. It combines the namespace URI and localpart to form an identifier and constructs a string representation including optional namespace prefix. Args: namespace (Namespace): The namespace object containing a URI and optional prefix associated with this qualified name. localpart (str): The local part of the qualified name. """ Identifier.__init__(self, "".join([namespace.uri, localpart])) self._namespace = namespace self._localpart = localpart self._str = ( ":".join([namespace.prefix, localpart]) if namespace.prefix else localpart ) @property def namespace(self) -> Namespace: """Namespace of qualified name.""" return self._namespace @property def localpart(self) -> str: """Local part of qualified name.""" return self._localpart def __str__(self) -> str: return self._str def __repr__(self) -> str: return f"<{self.__class__.__name__}: {self._str}>" def __hash__(self) -> int: return hash(self.uri)
[docs] def provn_representation(self) -> str: """Return the PROV-N representation of this qualified name as a quoted string.""" return f"'{self._str}'"
[docs] class Namespace: """PROV Namespace.""" def __init__(self, prefix: str, uri: str): """Create a namespace with the given prefix and URI. Args: prefix: Short-hand prefix for the namespace. uri: URI string for the namespace (cannot be blank). Raises: ValueError: If ``uri`` is empty or contains only whitespace. """ if not uri or uri.isspace(): raise ValueError("Not a valid URI to create a namespace.") self._prefix = prefix self._uri = uri self._cache: dict[str, QualifiedName] = {} @property def uri(self) -> str: """Namespace URI.""" return self._uri @property def prefix(self) -> str: """Namespace prefix.""" return self._prefix
[docs] def contains(self, identifier: Identifier) -> bool: """Check whether the given identifier's URI is contained in this namespace. Args: identifier: Identifier (or URI string) to check. Returns: ``True`` if the identifier's URI starts with this namespace's URI, ``False`` otherwise (including when the URI cannot be determined). """ uri = ( identifier if isinstance(identifier, str) else (identifier.uri if isinstance(identifier, Identifier) else None) ) return uri.startswith(self._uri) if uri else False
[docs] def qname(self, identifier: str | Identifier) -> QualifiedName | None: """Resolve an identifier to a :class:`QualifiedName` in this namespace. Args: identifier: Identifier (or URI string) to resolve. Returns: A new :class:`QualifiedName` in this namespace if ``identifier``'s URI starts with this namespace's URI, otherwise ``None``. """ uri = ( identifier if isinstance(identifier, str) else (identifier.uri if isinstance(identifier, Identifier) else None) ) if uri and uri.startswith(self._uri): return QualifiedName(self, uri[len(self._uri) :]) else: return None
def __eq__(self, other: Any) -> bool: return ( (self._uri == other.uri and self._prefix == other.prefix) if isinstance(other, Namespace) else False ) def __ne__(self, other: Any) -> bool: return ( not isinstance(other, Namespace) or self._uri != other.uri or self._prefix != other.prefix ) def __hash__(self) -> int: return hash((self._uri, self._prefix)) def __repr__(self) -> str: return f"<{self.__class__.__name__}: {self._prefix} {{{self._uri}}}>" def __getitem__(self, localpart: str) -> QualifiedName: if localpart in self._cache: return self._cache[localpart] else: qname = QualifiedName(self, localpart) self._cache[localpart] = qname return qname