util.persistence.pRef module¶
- exception util.persistence.pRef.DuplicateNameError¶
Bases:
ExceptionRaised when a name lookup matches more than one PRObject.
- exception util.persistence.pRef.MalformedIDError¶
Bases:
ExceptionRaised a PReference is syntactically incorrect.
- exception util.persistence.pRef.CircularReferenceError¶
Bases:
ExceptionRaised when a PRDb document (directly or via a chain of other documents currently being read) ends up referencing its own URL while that URL’s PRDb._read() is still in progress. Without this check, such a document would otherwise send PRDb.__new__() into unbounded recursion – each nested attempt to load the same not-yet-finished URL passing every earlier guard (it’s not yet in AllDBs; the file exists; it’s not the top-level _reading call) – until the interpreter’s call stack is exhausted.
- class util.persistence.pRef.PRObject(db: DBT, **kwargs)¶
Bases:
Serializable,Dirtyable,GenericAn object with an immutable integer ID and a mutable name.
- __init__(db: DBT, **kwargs) None¶
- Parameters:
db (PRDb) – The db to which this object will belong.
kwargs (Any) – Passed on to super().__init__(). PRObject is often one link in a longer chain of cooperative __init__ calls – eg: a class combining AbstractGraph’s AGRelation with a sibling class via multiple inheritance (see sn.model.model.Relation) reaches PRObject through more than one base. Calling super().__init__(**kwargs) here (instead of simply returning) ensures whatever comes after PRObject in that particular class’s MRO – eg: AttributedObject, for a Relation or plain GraphObject – still gets initialized, exactly once, with the constructor arguments meant for it, even though PRObject itself has no use for them.
- Raises:
PermissionError – If the DB is write locked.
TypeError – If the value is not of type PRObject.
MemoryError – if the DB has been deleted.
- Note:
This used to call
Serializable.__init__(self)andDirtyable.__init__(self)directly, up here, before the super().__init__(**kwargs) call below. Serializable has no __init__ of its own so that call was a no-op, but the explicit Dirtyable call meant Dirtyable got initialized via a hardcoded direct call rather than via this class’s cooperative super() chain – and, since a class combining PRObject with something listed after Dirtyable in its own MRO (eg: sn.view.graphics.vobjects.VObject, which also mixes in ErrorReportingObject) relies on that same chain to reach the classes after Dirtyable too, this dead end silently meant ErrorReportingObject.__init__() – and anything else listed after Dirtyable – never ran at all for any such object. Removing the explicit calls and letting Dirtyable (now itself cooperative – see its own __init__) be reached exactly once via super() below fixes that for every current and future user of this class, not just this one case.
- _db: ReferenceType¶
- _id: int¶
- classmethod getInstantiationInfo() InstantiationInfo¶
- Returns:
A
InstantiationInfostructure describing the constructor parameters and how to fill them (conArgs, conKWArgs), and a further description of any additional data to be filled after immediately after the constructor (postconSetters) and more after any contained objects have been fully constructed (finalSetters), both how to write them and read them.- Return type:
- property id: int¶
- Returns:
this object’s ID in its DB.
- Return type:
int
- property db: DBT¶
- Returns:
this object’s ID.
- Return type:
:py:class:’PRDb
- Raises:
MemoryError – if the DB has been deleted.
- abstract property name: str¶
- Returns:
this object’s (usually mutable) name.
- Return type:
str
Note
This is an abstract method (property) used to resolve persistent references of the for <url>#<string-name>.
- getPRef() PReference[Self]¶
Returns a new
PReferenceobject referencing this object.- Returns:
- Return type:
PReference[Self]
- torepr(relativeTo: DBT) str¶
- Parameters:
relativeTo (DBT)
- Returns:
- Return type:
str
- __str__() str¶
- Returns:
- Return type:
str
- tostring(relativeTo: DBT | None = None) str¶
- Parameters:
relativeTo (DBT | None)
- Returns:
- Return type:
str
- _dbUrl() str¶
The URL of our DB, or the one it had when we were created if it has gone.
- Returns:
- Return type:
str
- class util.persistence.pRef.PRContainer(db: DBT, **kwargs)¶
Bases:
PRObject,GenericA PRObject that contains other objects (see getMembers()).
- class util.persistence.pRef.PRDbContainer(db: DBT, **kwargs)¶
Bases:
PRContainer,GenericThe object standing for its whole database (as object 0): its members are all the database’s objects.
- property name: str¶
- Returns:
- Return type:
str
- class util.persistence.pRef.PRDb(url: str, mode='w', memoryResident: bool = True, _reading: bool = False)¶
Bases:
Serializable,Subject,Dirtyable,GenericA dict-like object whose keys are restricted to int and values to PRObject.
- __getitem__() and related lookup methods accept either:
an int -> direct key lookup by ID
a str -> lookup by PRObject.name (raises DuplicateNameError if ambiguous)
METHODS PURPOSELY NOT IMPLEMENTED:
- __setitem__() (index assignment) is NOT implemented. Instead, the constructor
of PRObject calls PRDb._register() to obtain an id and insert itself into the PRDb.
update()
- aliases: ClassVar[dict[str, str]] = {}¶
Other URLs for DBs – eg: their old names, or where they were before they were moved – and the URLs they stand for (see resolveURL()): eg, “sn:/sn.xml” -> “sn:/sn”. One ending in “/” stands for everything under it (see _alias()).
- namedURLs: ClassVar[dict[str, Callable[[], str]]] = {}¶
Names – pseudo-URLs, eg: “sn:/baseRules” – of DBs whose actual URLs are only known when the program runs (eg: a temporary copy of a file that comes with it), and how to get each one’s URL – reading the DB, if need be (see resolveURL()). A reference to one is written as its name (see relativeURL()).
- _namesOf: ClassVar[dict[str, str]] = {}¶
The names of the namedURLs that have been resolved, by their actual URLs.
- readProgress: ClassVar[Callable[[PRDb, int], None] | None] = None¶
If set, called as a file’s objects are read – every READ_PROGRESS_STEP of them – with the DB being read and how many of its objects have been read so far (eg: to show a progress bar: its nextID is about how many there’ll be).
- READ_PROGRESS_STEP: ClassVar[int] = 250¶
How many objects are read between calls of readProgress.
- _readingURLs: ClassVar[set[str]] = {}¶
URLs for which a PRDb._read() call is currently in progress (see __new__() below). A URL is added just before its _read() starts and removed as soon as that call returns or raises. __new__() checks this set before starting a new read so that a document which (directly, or through a chain of other documents it references) ends up loading its own URL again fails fast with a CircularReferenceError instead of recursing until the stack overflows: AllDBs alone can’t catch this, since a URL is only added there after its read completes.
- classmethod _initCache()¶
Re-initializes the cache.
Warning
This should only be used for testing purposes (eg: unit testing) as it wipes the DB cache and could cause bad pointers in any interface applications.
Note
Subclasses should override to do whatever needs to be done for “blank” cache.
- classmethod getDB(url: str, mode='w') Self¶
- Parameters:
url (str) – The name of the db as a file name or a URL.
- Returns:
The DB read from disk or from the web.
- Return type:
- Raises:
FileNotFoundError – If a
file:URL points to a path that does not exist.ValueError – if the url is malformed.
urllib.error.URLError – If a remote URL cannot be reached.
Either return the DB from memory or attempt to read it from disk or from the web.
- Parameters:
mode (str)
- classmethod _read(url: str, mode='w') Self¶
- Parameters:
url (str) – The URL to fetch. May use any scheme supported by
urllib.request, plus thefile:protocol for local filesystem paths.- Returns:
Raw byte content of the resource, suitable for passing directly to an XML parser (e.g.
xml.etree.ElementTree._fromstring()orlxml.etree.XMLParser).- Return type:
bytes
- Raises:
ValueError – If url is an empty string.
FileNotFoundError – If a
file:URL points to a path that does not exist.urllib.error.URLError – If a remote URL cannot be reached.
Read the DB from disk or from the web and instantiate it. Subclasses should implement this method to actually do the read; this version merely raises the exception.
- Parameters:
mode (str)
- classmethod readFile(url: str, mode='w') Any¶
Read the object in the file (or at the URL) url – usually a PRDb, but not necessarily – and return it. Use this rather than SerializationStrategy.readx() to read a PRDb, as it takes care of files that have been copied or moved:
A copied or moved file still has its old URL in it. That’s found out first (without reading the file), so that while it’s read it’s taken as being the file it was actually read from – never confused with the original (which may be open) – and so are its references to files that were next to it, if they’ve been copied along with it (see _relocate()). Its previousURL is the URL it was copied from (written in the header the next time it’s saved).
- Parameters:
url (str)
mode (str)
- Returns:
- Return type:
Any
- _wasRead(url: str) None¶
Called once this DB has been read from url (see readFile()): for subclasses to do whatever’s needed then. (Here, nothing.)
- Parameters:
url (str) – Where it was read from.
- _bases: list[str] = []¶
The URLs of the files being read or written just now, innermost last: relative URLs in a file are relative to the file (see relativeURL(), absoluteURL()).
- classmethod basedOn(url: str | None)¶
Within this context, relative URLs are relative to url (eg: the file being read or written) – unless url is None.
- Parameters:
url (str | None)
- static isRelativeURL(url: str) bool¶
Whether url is a relative URL, eg: “pets.snm” or “shared/animals.snm” (not “file:…”, “sn:…”, “/…”, “$name”, “#12”).
- Parameters:
url (str)
- Returns:
- Return type:
bool
- classmethod absoluteURL(url: str, base: str | None = None) str¶
url, if it’s relative, made absolute against base – by default the file being read or written (see basedOn()); otherwise url as is (eg: a path typed by the user, relative to the current directory).
- Parameters:
url (str)
base (str | None)
- Returns:
- Return type:
str
- MAX_UP: int = 2¶
The most folders up (“../”) a relative URL goes (see relativeURL()): further than that, URLs stay absolute.
- classmethod relativeURL(url: str, base: str | None = None) str¶
url relative to base – by default the file being read or written (see basedOn()) – if it’s a file in the same folder, below it, or at most MAX_UP folders up from it, eg: “pets.snm”, “shared/animals.snm” or “../animals.snm”; otherwise url as is (eg: a file in an unrelated folder, or anything not a file). So a block of files copied together keeps referring to one another. (A file copied on its own still finds what it referred to: see absoluteURL().)
- Parameters:
url (str)
base (str | None)
- Returns:
- Return type:
str
- _readFrames: list[tuple[str, str]] = []¶
(stored URL, actual URL) for each copied or moved file being read just now (see _read()).
- _relocated: set[tuple[str, str]] = {}¶
(from, to) relocations already reported.
- FILE_SCHEMES: ClassVar[tuple[str, ...]] = ('', 'file', 'http', 'https')¶
The schemes of URLs of files (on this computer or elsewhere). Others – eg: “sn:” – are pseudo-URLs: names of DBs in memory (see namedURLs), taken as they are.
- classmethod resolveURL(url: str, mode: str = '') str¶
- Parameters:
url (str) – A DB’s URL, as given: perhaps relative (see absoluteURL()), an alias (see aliases), or a name (see namedURLs).
mode (str) – As for fixURL(): what to check it’s there for (“w”: writing; “”: nothing).
- Returns:
The URL it stands for: made absolute, given the default extension if it’s a file’s without one (see fixURL()), and relocated if it’s in a file that’s been copied or moved (see _relocate()). A pseudo-URL (see FILE_SCHEMES) is as it is (but for aliases and names).
- Return type:
str
- classmethod _alias(url: str) str¶
- Returns:
What url is an alias for (see aliases), if it is; else url. An alias ending in “/” stands for everything under it: eg, with “http://old.org/onto/” -> “https://new.org/ontologies/”, “http://old.org/onto/family.snm” is “https://new.org/ontologies/family.snm”.
- classmethod _relocate(url: str) str¶
While a copied or moved file is being read (see _read()): its old URL is taken to be the one it was read from; and a URL of a file that was next to it (eg: the model of a copied view) is taken to be the same file next to it now – if that file is there. Otherwise, url.
- Parameters:
url (str)
- Returns:
- Return type:
str
- serializationHeader() dict[str, str | int | float | bool | list | dict]¶
What to put in the head of its document when this is written (see SerializationStrategy.tostring()), besides its URL and super-DBs (see getInstantiationInfo()): the URL it was copied or moved from, if it was; and how many objects are in it (see objectCount()).
- Returns:
- Return type:
dict[str, HeadValue]
- objectCount() int¶
- Returns:
How many objects are written when this is (see serializationHeader()): by default, all of them (not its container).
- Return type:
int
- __init__(url: str, mode: str = 'w', memoryResident: bool = True, _reading: bool = False)¶
- Parameters:
url (str) – The URL to associate with this object. Can be a filename, interpreted in the context of the current directory.
_reading (bool) – (default False) Should not be used. Used by the persistence system to get around the existence of the URL during construction.
- Raises:
ValueError – If the URL is malformed.
DuplicateNameError – If the DB already exists in memory.
FileExistsError – If the URL already exists.
Creates a new PRDb. If the url exists already, you should be using PRDb.getDB() to retrieve it.
- Parameters:
mode (str)
memoryResident (bool)
- reading: bool¶
Can be used by contained objects to determine if a read operation is taking place.
- superDBs: list[Self]¶
List of other DBs that will be searched for indicies ([]) and get(): what this one builds on, as though their contents were its own (but not changed through it). Saved with it (see getInstantiationInfo()); change it with addSuperDB() and removeSuperDB().
- _missingSuperDBs: list[str]¶
The (saved) URLs of super-DBs that couldn’t be read when this was: kept, and saved again, so that they’re used once they’re there again.
- url: str¶
- _db: NoNoneDict[int, T]¶
- nextID: int¶
- previousURL: str | None¶
The URL this was copied or moved from, if it was (see _read()); written in the header.
- classmethod getInstantiationInfo() InstantiationInfo¶
- Returns:
A
InstantiationInfostructure describing the constructor parameters and how to fill them (conArgs, conKWArgs), and a further description of any additional data to be filled after immediately after the constructor (postconSetters) and more after any contained objects have been fully constructed (finalSetters), both how to write them and read them.- Return type:
- allSuperDBs() list[PRDb]¶
- Returns:
This one’s super-DBs, theirs, and so on (each once), nearest first.
- Return type:
list[PRDb]
- addSuperDB(db: PRDb) None¶
Make db a super-DB of this one (see superDBs), if it isn’t already.
- Parameters:
db (PRDb) – The DB.
- Raises:
ValueError – if db is this one, or builds on it (directly or not): a cycle.
- removeSuperDB(db: PRDb) None¶
Stop db being a super-DB of this one (see superDBs), if it is.
- Parameters:
db (PRDb) – The DB.
- property name¶
- Returns:
- Return type:
- save(saveas: str | None = None, overwrite=False, format: str = 'XML3') None¶
- Parameters:
saveas (Optional[str])
overwrite (bool)
format (str)
- writeLocked() bool¶
- Returns:
True iff and the DB is write-locked.
- Return type:
bool
- _register(value: T, _id: int | None = None) int¶
- Parameters:
value (PRObject) – The PRObject to be added to this DB.
_id (Optional[int]) – Normally (and defaulted to) None. But if value is an object that has previously been unregistered, this value is the the original ID (that had been returned from this method) and will be restored to this ID.
- Returns:
A new (locally) unique id for this object.
- Raises:
PermissionError – If the DB is write locked.
TypeError – If the value is not of type PRObject.
Generate a (locally) unique id for this object and add it the this DB.
The method is private, but is used in the constructor of PRObject.
- _unregister(_id: int) None¶
- Parameters:
value (PRObject) – The PRObject to be added to this DB.
_id (Optional[int]) – Normally (and defaulted to) None. But if value is an object that has previously been unregistered, this value is the the original ID (that had been returned from this method) and will be restored to this ID.
- Returns:
A new (locally) unique id for this object.
- Raises:
ValueError – if _id does not exist.
Generate a (locally) unique id for this object and add it the this DB.
The method is private, but is used in the constructor of PRObject.
- setDirty(dirty: bool = True) None¶
An object is dirty if it has been modified and should probably be saved on exit. This should be called from all methods that modify the state of this object.
If dirty is False, resets all the contained Attributes to False.
- Parameters:
dirty (bool) – (default True) The dirty to set dirty to.
- isDirty() bool¶
Returns True iff the object (or an of it’s contained Attributes) have been modified and should probably be saved on exit.
- Returns:
- Return type:
bool
- findByName(name: str) list[T]¶
- Parameters:
name (str)
- Returns:
- Return type:
list[T]
- _resolve(key: int | str) int¶
Return the integer key for key, without necessarily checking for it’s existence.
int -> returned as-is (existence check deferred to caller)
str -> scanned for a matching .name; DuplicateNameError if >1 match
- Parameters:
key (int|str) – The index or name of the object.
- Returns:
the int index of the object.
- Return type:
int
- Raises:
DuplicateNameError – if a str index is not unique.
KeyError – if the str index is not found.
TypeError – if the key is not either an int of a str.
- __getitem__(key: int | str) T¶
- Parameters:
key (int | str)
- Returns:
- Return type:
T
- _makeDBContainer() PRDbContainer[Self]¶
- Returns:
- Return type:
PRDbContainer[Self]
- getall(key: int | str, filtr: Callable[[T], bool] = <function PRDb.<lambda>>, throw: bool = False) list[T]¶
Return the integer key for key.
int -> returned as-is (existence check deferred to caller)
str -> scanned for a matching .name; DuplicateNameError if >1 match
- Parameters:
key (int | str)
filtr (Callable[[T], bool])
throw (bool)
- Returns:
- Return type:
list[T]
- get(key: int | str, default: T | None = None) T | None¶
- Parameters:
key (int | str)
default (T | None)
- Returns:
- Return type:
T | None
- keys() KeysView[int]¶
- Returns:
- Return type:
KeysView[int]
- values() ValuesView[T]¶
- Returns:
- Return type:
ValuesView[T]
- items() ItemsView[int, T]¶
- Returns:
- Return type:
ItemsView[int, T]
- torepr(relativeTo: Self | None = None) str¶
- Parameters:
relativeTo (Self | None)
- Returns:
- Return type:
str
- __str__() str¶
- Returns:
- Return type:
str
- tostring(relativeTo: Self | None = None) str¶
- Parameters:
relativeTo (Self | None)
- Returns:
- Return type:
str
- class util.persistence.pRef.PReference(text: str)¶
Bases:
GenericA reference to a persistent object implementing the __call__() method for resolving the referernce into a pointer.
- __init__(text: str)¶
- Parameters:
text (str) – A string in the form of <URL>#<id>, where <id> can be an int, a string with no spaces or a quoted string.
- Raises:
MalformedIDError – if the form of the ID is not valid.
ValueError – If it isn’t a valid URL.
FileNotFoundError – If the file or URL does not exist.
Creates a reference to a PRObject without actually trying to instantiate the PRObject or checking on it’s existence. To instantiate the object, use a call on this object.
- url: str | None¶
- name: str | None¶
- id: int¶
- __call__(relativeTo: PRDb[T] | str | None = None) T | PRDb[T]¶
- Returns:
the resolved PRObject.
- Raises:
LookupError – if the reference cannot be resolved.
- Parameters:
relativeTo (PRDb[T] | str | None)
- tostring(relativeTo: PRDb[T] | None = None) str¶
- Parameters:
relativeTo (PRDb[T] | None)
- Returns:
- Return type:
str
- __str__() str¶
- Returns:
- Return type:
str
- torepr(relativeTo: PRDb[T] | None = None) str¶
- Parameters:
relativeTo (PRDb[T] | None)
- Returns:
- Return type:
str
- classmethod formatForURL(ref: str | Self | T1, contextDB: PRDb | None = None, includeName=True) str¶
- Parameters:
ref (str|PReference|PRObject) – A string or PReference or PRObject.
contextDB (PRDb) – A db to generate a relative reference string to. To shorten the string. This with a “x?id=10: will be “http:///x?id=10” with a context and merely “?id=10” with context=x
- Returns:
The canonical for an ID. Since URL-fragment parts are not transmitted to the server in requests, they cannot be used to request fragment parts of an object, so where “#<id>” might be expected to be used, “?id=<id>” is used instead.
Format:
<url>?{id=<id_int>}{{&}name=<name>}
- Parameters:
includeName (bool)
- classmethod eval(text: str, contextDB: ~util.persistence.pRef.PRDb | None = None, filtr: ~typing.Callable[[T1], bool] = <function PReference.<lambda>>) T1 | PRDb¶
Evaluate the text expression as a PReference to an object. But be friendly in interpreting the expression by assuming a # prefix is missing if we can’t find the db in memory, file system, or web.
- Parameters:
text (str) – A valid string representing a PReference.
contextDB (Optional[PRDb]) – A PRDb in which to evaluate text.
filtr (Callable[[PRObject],bool]|None) – An optional PRObject->bool function to use to disambiguate between multiple possible return values if necessary. It should return True for a possible candidate.
- Returns:
A PRObject represented by text.
- Return type:
- classmethod _isValidID_old(text: str) tuple[str | None, int | str]¶
- Parameters:
text (str) – The text of a PReference in the form <URL>#[<int>|<str>].
- Returns:
A 2-tuble [url, id] where url is a valid URL or None, and id is either an int or a string
- Raises:
MalformedIDError – if the form of the ID is not valid.
ValueError – If it isn’t a valid URL.
FileNotFoundError – If the file or URL does not exist.
Splits the id into a URL part and an ID part. Validates the existence of the URL but makes no attempt to validate the ID. The ID may be either an int or a string name.
<validID> := <absoluteURL> | <relativeURL>
<absoluteURL> := <existing-URL>#<id>
<relativeURL> := {#}<id>
<id> := int | <str-without-whatespace> | <quoted-str>
<validID> := <absoluteURL> | <relativeURL>
<absoluteURL> := <existing-URL>{?<parameters>}#<id>
<parameters> := name=<name> | id=<int>
<relativeURL> := {#}<id>
<id> := <int> | <str-without-whatespace> | <quoted-str>
- classmethod _isValidID(s: str) tuple[str | None, int | None, str | None]¶
Split a string into path, id, and name components.
Respects single and double quoted substrings and backslash escapes. The ‘#’ and ‘?’ delimiters may appear in any order, but are expected to appear at most once each outside of quoted regions.
Query string must be of the form ‘name=<str>’ or ‘id=<int>’, where <str> may be a quoted string or an HTML percent-encoded string.
Fragment is a convenience for gracious interpretation of user input only. It must be an integer, a quoted string, or an HTML percent-encoded string. And if it’s a an integer, will be interpreted as an id; if it’s an string, will be interpreted as name. If it disagrees with the query field, a ValueError exception is thrown.
Locations are specified by standard http: https: or file: URLs, however the special notation “$<name>” looks up a DB in memory by it’s name alone as a user interface convenience.
- Parameters:
s (str) – The string to split, e.g. a URL or path with query/fragment.
- Returns:
A 3-tuple of (path, name, id). name is a str or None, id is an int or None.
- Return type:
tuple[str, str | None, int | None]
- Raises:
ValueError –
If the query or fragment cannot be parsed or one of the query fields doesn’t match the fragment field.
<validID> := <absoluteID> | <relativeID>
<absoluteID> := <existing-URL>{“?”<parameters>} | “#”<id>
<locationSpec> := <existing-URL> | “$”<dbName>
<parameters> := name=<name> | id=<int>
<relativeID> := {#}<id>
<id> := <int> | <str-without-whatespace> | <quoted-str>
- util.persistence.pRef.a: CPObject¶
- util.persistence.pRef.b: CPObject¶
- util.persistence.pRef.c: CPObject¶