Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • caosdb/src/caosdb-pylib
1 result
Show changes
Commits on Source (13)
......@@ -62,11 +62,11 @@ mypy:
allow_failure: true
# run unit tests
unittest_py3.7:
unittest_py3.8:
tags: [ docker ]
stage: test
needs: [ ]
image: python:3.7
image: python:3.8
script: &python_test_script
# Python docker has problems with tox and pip so use plain pytest here
- touch ~/.pylinkahead.ini
......@@ -74,13 +74,6 @@ unittest_py3.7:
- pip install .
- python -m pytest unittests
unittest_py3.8:
tags: [ docker ]
stage: test
needs: [ ]
image: python:3.8
script: *python_test_script
# This needs to be changed once Python 3.9 isn't the standard Python in Debian
# anymore.
unittest_py3.9:
......@@ -121,8 +114,14 @@ unittest_py3.13:
stage: test
needs: [ ]
image: python:3.13-rc
script: *python_test_script
script:
# TODO: Replace by '*python_test_script' as soon as 3.13 has been officially released.
# Python docker has problems with tox and pip so use plain pytest here
- apt update && apt install -y cargo
- touch ~/.pylinkahead.ini
- pip install pynose pytest pytest-cov jsonschema>=4.4.0 setuptools
- pip install .
- python -m pytest unittests
# Trigger building of server image and integration tests
trigger_build:
......
......@@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ###
* Support for Python 3.12
* The `linkahead` module now opts into type checking and supports mypy.
* The `linkahead` module now opts into type checking and supports mypy.
### Changed ###
......@@ -18,6 +18,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Removed ###
* Support for Python 3.7
### Fixed ###
* [#104](https://gitlab.com/linkahead/linkahead-pylib/-/issues/104) Selecting
......
......@@ -179,7 +179,7 @@ def setup_package():
"Topic :: Scientific/Engineering :: Information Analysis",
],
packages=find_packages('src'),
python_requires='>=3.7',
python_requires='>=3.8',
package_dir={'': 'src'},
install_requires=['lxml>=4.6.3',
"requests[socks]>=2.26",
......
......@@ -18,7 +18,7 @@ Or to speak it out directly in Python:
r.get_property("alpha").value = 25 # setting properties (old api)
print(r.get_property("alpha").value + 25) # getting properties (old api)
from linkahead.high_level_api import convert_to_python_entity
from linkahead.high_level_api import convert_to_python_object
obj = convert_to_python_object(r) # create a high level entity
obj.r = 25 # setting properties (new api)
print(obj.r + 25) # getting properties (new api)
......
......@@ -477,10 +477,10 @@ class Entity:
if role is None and self.permissions is not None:
# pylint: disable=unsupported-membership-test
return permission in self.permissions
else:
if self.acl is None:
raise EntityHasNoAclError("This entity does not have an ACL (yet).")
self.acl.is_permitted(role=role, permission=permission)
if self.acl is None:
raise EntityHasNoAclError("This entity does not have an ACL (yet).")
return self.acl.is_permitted(role=role, permission=permission)
def get_all_messages(self) -> Messages:
ret = Messages()
......@@ -1045,7 +1045,7 @@ out: List[Entity]
return p
else:
raise ValueError("pattern argument should be Entity, int or str")
raise ValueError("`pattern` argument should be an Entity, int or str.")
return None
......@@ -3365,7 +3365,7 @@ class Container(list):
# which is to be synced with which:
# sync_dict[local_entity]=sync_remote_enities
sync_dict: Dict[Entity, Optional[List[Entity]]] = dict()
sync_dict: Dict[Union[Container, Entity], Optional[List[Entity]]] = dict()
# list of remote entities which already have a local equivalent
used_remote_entities = []
......@@ -3966,7 +3966,7 @@ class Container(list):
else:
entity._checksum = None
# FIXME: The signature of Conatiner.insert is completely different than the superclass'
# FIXME: The signature of Container.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,
......@@ -3981,20 +3981,23 @@ class Container(list):
identified, retrieved, updated, and deleted via this ID until it has
been deleted.
If the insertion fails, a LinkAheadException will be raised. The server will have returned at
least one error-message describing the reason why it failed in that case (call
If the insertion fails, a LinkAheadException will be raised. The server will have returned
at least one error-message describing the reason why it failed in that case (call
<this_entity>.get_all_messages() in order to get these error-messages).
Some insertions might cause warning-messages on the server-side, but the entities are inserted
anyway. Set the flag 'strict' to True in order to force the server to take all warnings as errors.
This prevents the server from inserting this entity if any warning occurs.
Some insertions might cause warning-messages on the server-side, but the entities are
inserted anyway. Set the flag 'strict' to True in order to force the server to take all
warnings as errors. This prevents the server from inserting this entity if any warning
occurs.
@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.
@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.
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()
......@@ -4264,9 +4267,7 @@ class ACI():
e.set("role", self.role)
else:
if self.username is None:
raise LinkAheadException(
"An ACI must have either a role or a username."
)
raise LinkAheadException("An ACI must have either a role or a username.")
e.set("username", self.username)
if self.realm is not None:
......@@ -4654,8 +4655,8 @@ class Query():
Attributes
----------
q : str
The query string.
q : str, etree._Element
The query string, may also be a query XML snippet.
flags : dict of str
A dictionary of flags to be send with the query request.
messages : Messages()
......@@ -4686,13 +4687,11 @@ class Query():
self.etag = None
if isinstance(q, etree._Element):
string = q.get("string")
self.q = string if string is not None else ""
q.get("string")
self.q = q.get("string", "")
results = q.get("results")
if results is None:
raise LinkAheadException(
"The query result count is not available in the response."
)
raise LinkAheadException("The query result count is not available in the response.")
self.results = int(results)
cached_value = q.get("cached")
......@@ -5095,9 +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")
if counts is not None:
attrib: Union[str, etree._Attrib] = counts.attrib
return Message(type="Counts", description=None, body=attrib)
if counts is None:
raise LinkAheadException("'stats' element without a 'count' found.")
return Message(type="Counts", description=None, body=counts.attrib)
elif elem.tag == "EntityACL":
return ACL(xml=elem)
elif elem.tag == "Permissions":
......
[tox]
envlist=py37, py38, py39, py310, py311, py312, py313
envlist=py38, py39, py310, py311, py312, py313
skip_missing_interpreters = true
[testenv]
......