Skip to content
Snippets Groups Projects

Resolve "Fix mypy errors in models.py and complete type hints"

All threads resolved!
Files
2
+ 269
119
@@ -54,6 +54,9 @@ if TYPE_CHECKING and sys.version_info > (3, 7):
from datetime import datetime
from typing import Any, Dict, Optional, Type, Union, List, TextIO, Tuple, Literal
from .datatype import DATATYPE
from tempfile import _TemporaryFileWrapper
from io import BufferedWriter
from warnings import warn
@@ -62,15 +65,26 @@ from lxml import etree
from ..configuration import get_config
from ..connection.connection import get_connection
from ..connection.encode import MultipartParam, multipart_encode
from ..exceptions import (AmbiguousEntityError, AuthorizationError,
ConsistencyError, EmptyUniqueQueryError,
EntityDoesNotExistError, EntityError,
EntityHasNoDatatypeError, HTTPURITooLongError,
LinkAheadConnectionError, LinkAheadException,
MismatchingEntitiesError, PagingConsistencyError,
QueryNotUniqueError, TransactionError,
UniqueNamesError, UnqualifiedParentsError,
UnqualifiedPropertiesError)
from ..exceptions import (
AmbiguousEntityError,
AuthorizationError,
ConsistencyError,
EmptyUniqueQueryError,
EntityDoesNotExistError,
EntityError,
EntityHasNoAclError,
EntityHasNoDatatypeError,
HTTPURITooLongError,
LinkAheadConnectionError,
LinkAheadException,
MismatchingEntitiesError,
PagingConsistencyError,
QueryNotUniqueError,
TransactionError,
UniqueNamesError,
UnqualifiedParentsError,
UnqualifiedPropertiesError,
)
from .datatype import (
BOOLEAN,
DATETIME,
@@ -95,7 +109,8 @@ FIX = "FIX"
ALL = "ALL"
NONE = "NONE"
if TYPE_CHECKING:
INHERITANCE = Literal["OBLIGATORY", "SUGGESTED", "RECOMMENDED", "FIX", "ALL", "NONE"]
INHERITANCE = Literal["OBLIGATORY", "SUGGESTED", "RECOMMENDED", "ALL", "NONE"]
IMPORTANCE = Literal["OBLIGATORY", "RECOMMENDED", "SUGGESTED", "FIX", "NONE"]
SPECIAL_ATTRIBUTES = ["name", "role", "datatype", "description",
"id", "path", "checksum", "size", "value"]
@@ -387,6 +402,10 @@ class Entity:
ACL will be revoked.
"""
# @review Florian Spreckelsen 2022-03-17
if self.acl is None:
raise EntityHasNoAclError("This entity does not have an ACL (yet).")
self.acl.grant(realm=realm, username=username, role=role,
permission=permission, priority=priority,
revoke_denial=revoke_denial)
@@ -429,6 +448,9 @@ class Entity:
ACL will be revoked.
"""
# @review Florian Spreckelsen 2022-03-17
if self.acl is None:
raise EntityHasNoAclError("This entity does not have an ACL (yet).")
self.acl.deny(realm=realm, username=username, role=role,
permission=permission, priority=priority,
revoke_grant=revoke_grant)
@@ -452,12 +474,13 @@ class Entity:
priority=priority)
def is_permitted(self, permission: Permission, role: Optional[str] = None):
if role is None:
if role is None and self.permissions is not None:
# pylint: disable=unsupported-membership-test
return permission in self.permissions
else:
self.acl.is_permitted(permission=permission)
if self.acl is None:
raise EntityHasNoAclError("This entity does not have an ACL (yet).")
self.acl.is_permitted(role=role, permission=permission)
def get_all_messages(self) -> Messages:
ret = Messages()
@@ -534,20 +557,24 @@ class Entity:
"""
if self.get_property(property_name) is None:
property = self.get_property(property_name)
if property is None:
return self
if self.get_property(property_name).value is None:
if property.value is None:
remove_if_empty_afterwards = False
empty_afterwards = False
if isinstance(self.get_property(property_name).value, list):
if value in self.get_property(property_name).value:
self.get_property(property_name).value.remove(value)
if self.get_property(property_name).value == []:
self.get_property(property_name).value = None
if isinstance(property.value, list):
if value in property.value:
property.value.remove(value)
if property.value == []:
property.value = None
empty_afterwards = True
elif self.get_property(property_name).value == value:
self.get_property(property_name).value = None
elif property.value == value:
property.value = None
empty_afterwards = True
if remove_if_empty_afterwards and empty_afterwards:
self.remove_property(property_name)
@@ -576,10 +603,10 @@ class Entity:
id: Optional[int] = None,
name: Optional[str] = None,
description: Optional[str] = None,
datatype: Optional[str] = None,
datatype: Optional[DATATYPE] = None,
unit: Optional[str] = None,
importance: Optional[str] = None,
inheritance: Union[str, INHERITANCE, None] = None,
importance: Optional[IMPORTANCE] = None,
inheritance: Optional[INHERITANCE] = None,
) -> Entity: # @ReservedAssignment
"""Add a property to this entity.
@@ -755,7 +782,7 @@ class Entity:
parent: Union[Entity, int, str, None] = None,
id: Optional[int] = None,
name: Optional[str] = None,
inheritance: Union[INHERITANCE, str, None] = None,
inheritance: INHERITANCE = "NONE",
): # @ReservedAssignment
"""Add a parent to this entity.
@@ -771,7 +798,7 @@ class Entity:
Name of the parent entity. Ignored if `parent is not
none`.
inheritance : str, INHERITANCE
One of ``obligatory``, ``recommended``, ``suggested``, or ``fix``. Specifies the
One of ``obligatory``, ``recommended``, ``suggested``, or ``all``. Specifies the
minimum importance which parent properties need to have to be inherited by this
entity. If no `inheritance` is given, no properties will be inherited by the child.
This parameter is case-insensitive.
@@ -1018,7 +1045,7 @@ out: List[Entity]
return p
else:
raise ValueError("argument should be entity, int , string")
raise ValueError("pattern argument should be Entity, int or str")
return None
@@ -1035,8 +1062,10 @@ out: List[Entity]
"""
SPECIAL_SELECTORS = ["unit", "value", "description", "id", "name"]
if not isinstance(selector, (tuple, list)):
if isinstance(selector, str):
selector = [selector]
elif isinstance(selector, tuple):
selector = list(selector)
ref = self
@@ -1051,7 +1080,7 @@ out: List[Entity]
special_selector = None
# iterating through the entity tree according to the selector
prop: Optional[Property] = None
for subselector in selector:
# selector does not match the structure, we cannot get a
# property of non-entity
@@ -1078,9 +1107,11 @@ out: List[Entity]
ref = prop
# if we saved a special selector before, apply it
if special_selector is None:
return prop.value
if prop is None:
return None
else:
return prop.value
else:
return getattr(ref, special_selector.lower())
@@ -1195,7 +1226,7 @@ out: List[Entity]
def to_xml(
self,
xml: Optional[etree._Element] = None,
add_properties: Optional[INHERITANCE] = ALL,
add_properties: INHERITANCE = "ALL",
local_serialization: bool = False,
) -> etree._Element:
"""Generate an xml representation of this entity. If the parameter xml
@@ -1207,6 +1238,10 @@ out: List[Entity]
@param xml: an xml element to which all attributes, parents,
properties, and messages
are to be added.
FIXME: Add documentation for the add_properties parameter.
FIXME: Add docuemntation for the local_serialization parameter.
@return: xml representation of this entity.
"""
@@ -1675,7 +1710,13 @@ def _log_response(body):
class QueryTemplate():
def __init__(self, id=None, name=None, query=None, description=None): # @ReservedAssignment
def __init__(
self,
id: Optional[int] = None,
name: Optional[str] = None,
query: Optional[str] = None,
description: Optional[str] = None,
): # @ReservedAssignment
self.id = (int(id) if id is not None else None)
self.role = "QueryTemplate"
@@ -1694,15 +1735,20 @@ class QueryTemplate():
self._size = None
self._upload = None
self.unit = None
self.acl = None
self.permissions = None
self.acl: Optional[ACL] = None
self.permissions: Optional[Permissions] = None
self.is_valid = lambda: False
self.is_deleted = lambda: False
self.version = None
self.state = None
def retrieve(self, raise_exception_on_error=True, unique=True, sync=True,
flags=None):
def retrieve(
self,
raise_exception_on_error: bool = True,
unique: bool = True,
sync: bool = True,
flags: Optional[Dict[str, Optional[str]]] = None,
):
return Container().append(self).retrieve(
raise_exception_on_error=raise_exception_on_error,
@@ -1710,8 +1756,14 @@ class QueryTemplate():
sync=sync,
flags=flags)[0]
def insert(self, strict=True, raise_exception_on_error=True,
unique=True, sync=True, flags=None):
def insert(
self,
strict: bool = True,
raise_exception_on_error: bool = True,
unique: bool = True,
sync: bool = True,
flags: Optional[Dict[str, Optional[str]]] = None,
):
return Container().append(self).insert(
strict=strict,
@@ -1720,8 +1772,14 @@ class QueryTemplate():
sync=sync,
flags=flags)[0]
def update(self, strict=True, raise_exception_on_error=True,
unique=True, sync=True, flags=None):
def update(
self,
strict: bool = True,
raise_exception_on_error: bool = True,
unique: bool = True,
sync: bool = True,
flags: Optional[Dict[str, Optional[str]]] = None,
):
return Container().append(self).update(
strict=strict,
@@ -1737,7 +1795,7 @@ class QueryTemplate():
def __repr__(self):
return xml2str(self.to_xml())
def to_xml(self, xml=None):
def to_xml(self, xml: Optional[etree._Element] = None):
if xml is None:
xml = etree.Element("QueryTemplate")
@@ -1767,7 +1825,7 @@ class QueryTemplate():
return xml
@staticmethod
def _from_xml(xml):
def _from_xml(xml: etree._Element):
if xml.tag.lower() == "querytemplate":
q = QueryTemplate(name=xml.get("name"),
description=xml.get("description"), query=None)
@@ -1777,16 +1835,18 @@ class QueryTemplate():
q.query = e.text
else:
child = _parse_single_xml_element(e)
if child is None:
continue
if isinstance(child, Message):
q.messages.append(child)
elif isinstance(child, ACL):
q.acl = child
elif isinstance(child, Version):
q.version = child
q.version = child # type: ignore
elif isinstance(child, Permissions):
q.permissions = child
q.id = int(xml.get("id"))
id = xml.get("id")
q.id = int(id) if id is not None else None
return q
else:
@@ -1849,7 +1909,12 @@ class Parent(Entity):
self.set_flag("inheritance", inheritance)
self.__affiliation = None
def to_xml(self, xml: Optional[etree._Element] = None, add_properties=None):
def to_xml(
self,
xml: Optional[etree._Element] = None,
add_properties: INHERITANCE = "NONE",
local_serialization: bool = False,
):
if xml is None:
xml = etree.Element("Parent")
@@ -1919,11 +1984,20 @@ class Property(Entity):
datatype=datatype, value=value, role="Property")
self.unit = unit
def to_xml(self, xml: Optional[etree._Element] = None, add_properties=ALL):
def to_xml(
self,
xml: Optional[etree._Element] = None,
add_properties: INHERITANCE = "ALL",
local_serialization: bool = False,
):
if xml is None:
xml = etree.Element("Property")
return super(Property, self).to_xml(xml, add_properties)
return super(Property, self).to_xml(
xml=xml,
add_properties=add_properties,
local_serialization=local_serialization,
)
def is_reference(self, server_retrieval=False):
"""Returns whether this Property is a reference
@@ -1974,7 +2048,7 @@ class Message(object):
type: Optional[str] = None,
code: Optional[int] = None,
description: Optional[str] = None,
body: Optional[str] = None,
body: Union[str, etree._Attrib, None] = None,
): # @ReservedAssignment
self.description = description
self.type = type if type is not None else "Info"
@@ -2028,7 +2102,7 @@ class RecordType(Entity):
parent: Union[Entity, int, str, None] = None,
id: Optional[int] = None,
name: Optional[str] = None,
inheritance: Union[INHERITANCE, str, None] = OBLIGATORY,
inheritance: INHERITANCE = "OBLIGATORY",
):
"""Add a parent to this RecordType
@@ -2048,8 +2122,8 @@ class RecordType(Entity):
name : str
Name of the parent entity. Ignored if `parent is not
none`.
inheritance : str, default OBLIGATORY
One of ``obligatory``, ``recommended``, ``suggested``, or ``fix``. Specifies the
inheritance : INHERITANCE, default OBLIGATORY
One of ``obligatory``, ``recommended``, ``suggested``, or ``all``. Specifies the
minimum importance which parent properties need to have to be inherited by this
entity. If no `inheritance` is given, no properties will be inherited by the child.
This parameter is case-insensitive.
@@ -2075,12 +2149,18 @@ class RecordType(Entity):
def to_xml(
self,
xml: Optional[etree._Element] = None,
add_properties: Optional[INHERITANCE] = ALL,
add_properties: INHERITANCE = "ALL",
local_serialization: bool = False,
) -> etree._Element:
if xml is None:
xml = etree.Element("RecordType")
return Entity.to_xml(self, xml, add_properties)
return Entity.to_xml(
self,
xml=xml,
add_properties=add_properties,
local_serialization=local_serialization,
)
class Record(Entity):
@@ -2104,11 +2184,20 @@ class Record(Entity):
Entity.__init__(self, name=name, id=id, description=description,
role="Record")
def to_xml(self, xml=None, add_properties=ALL):
def to_xml(
self,
xml: Optional[etree._Element] = None,
add_properties: INHERITANCE = "ALL",
local_serialization: bool = False,
):
if xml is None:
xml = etree.Element("Record")
return Entity.to_xml(self, xml, add_properties=ALL)
return super().to_xml(
xml=xml,
add_properties=add_properties,
local_serialization=local_serialization,
)
class File(Record):
@@ -2175,7 +2264,7 @@ class File(Record):
def to_xml(
self,
xml: Optional[etree._Element] = None,
add_properties: Optional[INHERITANCE] = ALL,
add_properties: INHERITANCE = "ALL",
local_serialization: bool = False,
):
"""Convert this file to an xml element.
@@ -2189,7 +2278,7 @@ class File(Record):
return Entity.to_xml(self, xml=xml, add_properties=add_properties,
local_serialization=local_serialization)
def download(self, target=None):
def download(self, target: Optional[str] = None):
"""Download this file-entity's actual file from the file server. It
will be stored to the target or will be hold as a temporary file.
@@ -2199,7 +2288,7 @@ class File(Record):
self.clear_server_messages()
if target:
file_ = open(target, 'wb')
file_: Union[BufferedWriter, _TemporaryFileWrapper] = open(target, "wb")
else:
file_ = NamedTemporaryFile(mode='wb', delete=False)
checksum = File.download_from_path(file_, self.path)
@@ -2211,7 +2300,9 @@ class File(Record):
return file_.name
@staticmethod
def download_from_path(target_file, path):
def download_from_path(
target_file: Union[BufferedWriter, _TemporaryFileWrapper], path: str
):
_log_request("GET (download): " + path)
response = get_connection().download_file(path)
@@ -2277,19 +2368,21 @@ class _Properties(list):
def __init__(self):
list.__init__(self)
self._importance = dict()
self._inheritance = dict()
self._element_by_name = dict()
self._element_by_id = dict()
self._importance: Dict[Property, IMPORTANCE] = dict()
self._inheritance: Dict[Property, INHERITANCE] = dict()
self._element_by_name: Dict[str, Property] = dict()
self._element_by_id: Dict[str, Property] = dict()
def get_importance(self, property): # @ReservedAssignment
def get_importance(
self, property: Union[Property, str, None]
): # @ReservedAssignment
if property is not None:
if hasattr(property, "encode"):
if isinstance(property, str):
property = self.get_by_name(property) # @ReservedAssignment
return self._importance.get(property)
def set_importance(self, property, importance): # @ReservedAssignment
def set_importance(self, property: Optional[Property], importance: IMPORTANCE): # @ReservedAssignment
if property is not None:
self._importance[property] = importance
@@ -2310,9 +2403,9 @@ class _Properties(list):
def append(
self,
property: Union[List[Entity], Entity],
importance=None,
inheritance: Union[str, INHERITANCE, None] = None,
property: Union[List[Entity], Entity, Property],
importance: Optional[IMPORTANCE] = None,
inheritance: Optional[INHERITANCE] = None,
): # @ReservedAssignment
if isinstance(property, list):
for p in property:
@@ -2340,9 +2433,7 @@ class _Properties(list):
return self
def to_xml(
self, add_to_element: etree._Element, add_properties: Union[str, INHERITANCE]
):
def to_xml(self, add_to_element: etree._Element, add_properties: INHERITANCE):
for p in self:
importance = self._importance.get(p)
@@ -3690,7 +3781,7 @@ class Container(list):
return (entities[0:hl], entities[hl:len(entities)])
def _retrieve(self, entities, flags):
def _retrieve(self, entities, flags: Dict[str, Optional[str]]):
c = get_connection()
try:
_log_request("GET: " + _ENTITY_URI_SEGMENT + str(entities) +
@@ -3744,8 +3835,14 @@ class Container(list):
return ret
def update(self, strict=False, raise_exception_on_error=True,
unique=True, sync=True, flags=None):
def update(
self,
strict: bool = False,
raise_exception_on_error: bool = True,
unique: bool = True,
sync: bool = True,
flags: Optional[Dict[str, Any]] = None,
):
"""Update these entites."""
if len(self) < 1:
@@ -3756,7 +3853,7 @@ class Container(list):
self.clear_server_messages()
insert_xml = etree.Element("Update")
http_parts = []
http_parts: List[MultipartParam] = []
if flags is None:
flags = {}
@@ -3826,7 +3923,9 @@ class Container(list):
return cresp
@staticmethod
def _process_file_if_present_and_add_to_http_parts(http_parts, entity):
def _process_file_if_present_and_add_to_http_parts(
http_parts: List[MultipartParam], entity: Union[File, Entity]
):
if isinstance(entity, File) and hasattr(
entity, 'file') and entity.file is not None:
new_checksum = File._get_checksum(entity.file)
@@ -3867,8 +3966,16 @@ class Container(list):
else:
entity._checksum = None
def insert(self, strict=False, raise_exception_on_error=True,
unique=True, sync=True, flags=None):
# FIXME: The signature of Conatiner.insert is completely different than the superclass'
# list.insert method. This may be a problem in the future, but is ignored for now.
def insert( # type: ignore
self,
strict: bool = False,
raise_exception_on_error: bool = True,
unique: bool = True,
sync: bool = True,
flags: Optional[Dict[str, Optional[str]]] = None,
):
"""Insert this file entity into LinkAhead. A successful insertion will
generate a new persistent ID for this entity. This entity can be
identified, retrieved, updated, and deleted via this ID until it has
@@ -3884,12 +3991,15 @@ class Container(list):
@param strict=False: Flag for strict mode.
@param sync=True: synchronize this container with the response from the server. Otherwise,
this method returns a new container with the inserted entities and leaves this container untouched.
this method returns a new container with the inserted entities and leaves this container untouched.
@param unique=True: Flag for unique mode. If set to True, the server will check if the name of the
entity is unique. If not, the server will return an error.
@param flags=None: Additional flags for the server.
"""
self.clear_server_messages()
insert_xml = etree.Element("Insert")
http_parts = []
http_parts: List[MultipartParam] = []
if flags is None:
flags = {}
@@ -3970,7 +4080,6 @@ class Container(list):
cresp = Container._response_to_entities(http_response)
if sync:
self._sync(cresp, unique=unique,
raise_exception_on_error=raise_exception_on_error)
@@ -3985,7 +4094,7 @@ class Container(list):
return cresp
@staticmethod
def _get_smallest_tmpid(entity):
def _get_smallest_tmpid(entity: Entity):
tmpid = 0
if entity.id is not None:
@@ -4050,7 +4159,9 @@ class Container(list):
return self
def get_property_values(self, *selectors):
def get_property_values(
self, *selectors: Union[str, Tuple[str]]
) -> List[Tuple[str]]:
""" Return a list of tuples with values of the given selectors.
I.e. a tabular representation of the container's content.
@@ -4152,11 +4263,17 @@ class ACI():
if self.role is not None:
e.set("role", self.role)
else:
if self.username is None:
raise LinkAheadException(
"An ACI must have either a role or a username."
)
e.set("username", self.username)
if self.realm is not None:
e.set("realm", self.realm)
p = etree.Element("Permission")
if self.permission is None:
raise LinkAheadException("An ACI must have a permission.")
p.set("name", self.permission)
e.append(p)
@@ -4206,7 +4323,7 @@ class ACL():
role = e.get("role")
username = e.get("username")
realm = e.get("realm")
priority = e.get("priority")
priority = self._get_boolean_priority(e.get("priority"))
for p in e:
if p.tag == "Permission":
@@ -4290,8 +4407,14 @@ class ACL():
if item in self._grants:
self._grants.remove(item)
def revoke_denial(self, username=None, realm=None,
role=None, permission=None, priority=False):
def revoke_denial(
self,
username: Optional[str] = None,
realm: Optional[str] = None,
role: Optional[str] = None,
permission: Optional[str] = None,
priority: bool = False,
):
priority = self._get_boolean_priority(priority)
item = ACI(role=role, username=username,
realm=realm, permission=permission)
@@ -4452,7 +4575,7 @@ class ACL():
return ret
def get_acl_for_user(self, username, realm=None):
def get_acl_for_user(self, username: str, realm: Optional[str] = None):
ret = ACL()
for aci in self._grants:
@@ -4545,7 +4668,7 @@ class Query():
with the resulting entities.
"""
def putFlag(self, key, value=None):
def putFlag(self, key: str, value: Optional[str] = None):
self.flags[key] = value
return self
@@ -4557,19 +4680,25 @@ class Query():
return self.flags.get(key)
def __init__(self, q: Union[str, etree._Element]):
self.flags: Dict[str, str] = dict()
self.flags: Dict[str, Optional[str]] = dict()
self.messages = Messages()
self.cached: Optional[bool] = None
self.etag = None
if isinstance(q, etree._Element):
self.q = q.get("string")
self.results = int(q.get("results"))
results = q.get("results")
if results is None:
raise LinkAheadException(
"The query result count is not available in the response."
)
self.results = int(results)
if q.get("cached") is None:
cached_value = q.get("cached")
if cached_value is None:
self.cached = False
else:
self.cached = q.get("cached").lower() == "true"
self.cached = cached_value.lower() == "true"
self.etag = q.get("etag")
for m in q:
@@ -4578,7 +4707,7 @@ class Query():
else:
self.q = q
def _query_request(self, query_dict):
def _query_request(self, query_dict: Dict[str, Optional[str]]):
"""Used internally to execute the query request..."""
_log_request("GET Entity?" + str(query_dict), None)
connection = get_connection()
@@ -4588,7 +4717,12 @@ class Query():
cresp = Container._response_to_entities(http_response)
return cresp
def _paging_generator(self, first_page, query_dict, page_length):
def _paging_generator(
self,
first_page: Container,
query_dict: Dict[str, Optional[str]],
page_length: int,
):
"""Used internally to create a generator of pages instead instead of a
container which contais all the results."""
if len(first_page) == 0:
@@ -4691,7 +4825,7 @@ class Query():
return r
self.messages = cresp.messages
if has_paging:
if has_paging and page_length is not None:
return self._paging_generator(cresp, query_dict, page_length)
else:
return cresp
@@ -4702,7 +4836,7 @@ def execute_query(
unique: bool = False,
raise_exception_on_error: bool = True,
cache: bool = True,
flags: Optional[Dict[str, str]] = None,
flags: Optional[Dict[str, Optional[str]]] = None,
page_length: Optional[int] = None,
) -> Union[Container, int]:
"""Execute a query (via a server-requests) and return the results.
@@ -4806,8 +4940,8 @@ class Info():
def __init__(self):
self.messages = Messages()
self.user_info = None
self.time_zone = None
self.user_info: Optional[UserInfo] = None
self.time_zone: Optional[TimeZone] = None
self.sync()
def sync(self):
@@ -4870,7 +5004,7 @@ class Permission():
class Permissions():
known_permissions = None
known_permissions: Optional[List[Permissions]] = None
def __init__(self, xml: etree._Element):
self.parse_xml(xml)
@@ -4883,8 +5017,12 @@ class Permissions():
for e in xml:
if e.tag == "Permission":
self._perms.add(Permission(name=e.get("name"),
description=e.get("description")))
name = e.get("name")
if name is None:
raise LinkAheadException(
"The permission element has no name attribute."
)
self._perms.add(Permission(name=name, description=e.get("description")))
def __contains__(self, p):
if isinstance(p, Permission):
@@ -4917,15 +5055,18 @@ def parse_xml(xml: Union[str, etree._Element]):
def _parse_single_xml_element(elem: etree._Element):
classmap = {
'record': Record,
'recordtype': RecordType,
'property': Property,
'file': File,
'parent': Parent,
'entity': Entity}
"record": Record,
"recordtype": RecordType,
"property": Property,
"file": File,
"parent": Parent,
"entity": Entity,
}
if elem.tag.lower() in classmap:
klass = classmap.get(elem.tag.lower())
if klass is None:
raise LinkAheadException("No class for tag '{}' found.".format(elem.tag))
entity = klass()
Entity._from_xml(entity, elem)
@@ -4953,8 +5094,9 @@ def _parse_single_xml_element(elem: etree._Element):
return Message(type='History', description=elem.get("transaction"))
elif elem.tag.lower() == 'stats':
counts = elem.find("counts")
return Message(type="Counts", description=None, body=counts.attrib)
if counts is not None:
attrib: Union[str, etree._Attrib] = counts.attrib
return Message(type="Counts", description=None, body=attrib)
elif elem.tag == "EntityACL":
return ACL(xml=elem)
elif elem.tag == "Permissions":
@@ -4962,11 +5104,19 @@ def _parse_single_xml_element(elem: etree._Element):
elif elem.tag == "UserInfo":
return UserInfo(xml=elem)
elif elem.tag == "TimeZone":
return TimeZone(zone_id=elem.get("id"), offset=elem.get("offset"),
display_name=elem.text.strip())
return TimeZone(
zone_id=elem.get("id"),
offset=elem.get("offset"),
display_name=elem.text.strip() if elem.text is not None else "",
)
else:
return Message(type=elem.tag, code=elem.get(
"code"), description=elem.get("description"), body=elem.text)
code = elem.get("code")
return Message(
type=elem.tag,
code=int(code) if code is not None else None,
description=elem.get("description"),
body=elem.text,
)
def _evaluate_and_add_error(parent_error: TransactionError, ent: Union[Entity, Container]):
@@ -5000,7 +5150,7 @@ def _evaluate_and_add_error(parent_error: TransactionError, ent: Union[Entity, C
if err.code is not None:
if int(err.code) == 101: # ent doesn't exist
new_exc = EntityDoesNotExistError(entity=ent,
new_exc: EntityError = EntityDoesNotExistError(entity=ent,
error=err)
elif int(err.code) == 110: # ent has no data type
new_exc = EntityHasNoDatatypeError(entity=ent,
@@ -5099,7 +5249,7 @@ def raise_errors(arg0: Union[Entity, QueryTemplate, Container]):
raise transaction_error
def delete(ids: Union[List[int], range], raise_exception_on_error=True):
def delete(ids: Union[List[int], range], raise_exception_on_error: bool = True):
c = Container()
if isinstance(ids, list) or isinstance(ids, range):
Loading