oldaplib 0.3.4__py3-none-any.whl → 0.3.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,13 @@
1
- from enum import Enum
2
- from typing import Type, Self
1
+ from enum import Enum, Flag, auto
2
+ from typing import Type, Self, Any
3
3
 
4
4
  from oldaplib.src.xsd.xsd_qname import Xsd_QName
5
5
 
6
+ class Target(Flag):
7
+ SHACL = auto()
8
+ OWL = auto()
9
+ BOTH = SHACL | OWL # convenience alias
10
+
6
11
 
7
12
  class AttributeClass(Enum):
8
13
  """
@@ -10,7 +15,12 @@ class AttributeClass(Enum):
10
15
  Project, PropertyClass, ResourceClass, User etc.,
11
16
  """
12
17
 
13
- def __new__(cls, value: Xsd_QName | str, mandatory: bool, immutable: bool, datatype: Type):
18
+ def __new__(cls,
19
+ value: Xsd_QName | str,
20
+ mandatory: bool,
21
+ immutable: bool,
22
+ datatype: Type,
23
+ target: Target = Target.BOTH):
14
24
  """
15
25
  :param value: The value of the attribute-enum item. Must have the form of a QName!
16
26
  :param mandatory: True, if this attribute is mandatory, False otherwise.
@@ -23,6 +33,7 @@ class AttributeClass(Enum):
23
33
  member._mandatory = mandatory
24
34
  member._immutable = immutable
25
35
  member._datatype = datatype
36
+ member._target = target
26
37
  return member
27
38
 
28
39
  def __str__(self) -> str:
@@ -48,6 +59,23 @@ class AttributeClass(Enum):
48
59
  def immutable(self) -> bool:
49
60
  return self._immutable
50
61
 
62
+ @property
63
+ def target(self) -> Target:
64
+ """Where this attribute should be emitted/used (SHACL, OWL, BOTH)."""
65
+ return self._target
66
+
67
+ @property
68
+ def in_shacl(self) -> bool:
69
+ return bool(self._target & Target.SHACL)
70
+
71
+ @property
72
+ def in_owl(self) -> bool:
73
+ return bool(self._target & Target.OWL)
74
+
75
+ @property
76
+ def to_rdf(self) -> str:
77
+ return self._value.toRdf
78
+
51
79
  @classmethod
52
80
  def from_value(cls, value: Xsd_QName | str) -> Self:
53
81
  """
@@ -73,6 +101,3 @@ class AttributeClass(Enum):
73
101
  return member
74
102
  raise ValueError(f"No member with name {name} found")
75
103
 
76
- @property
77
- def to_rdf(self) -> str:
78
- return self._value.toRdf
@@ -19,8 +19,8 @@ class OwlPropertyType(Enum):
19
19
  IrreflexiveProperty = 'owl:IrreflexiveProperty'
20
20
  FunctionalProperty = 'owl:FunctionalProperty'
21
21
  InverseFunctionalProperty = 'owl:InverseFunctionalProperty'
22
- # InverseOfProperty = 'owl:InverseOfProperty'
23
- # EquivalentProperty = 'owl:EquivalentProperty'
22
+ # InverseOfProperty = 'owl:inverseOf'
23
+ # EquivalentProperty = 'owl:equivalentProperty'
24
24
  # _owl_inverseOf: Xsd_QName # :hasParent owl:inverseOf :hasChild .
25
25
  # _owl_equivalent: Xsd_QName # :hasSpouse owl:equivalentProperty :marriedTo .
26
26
 
@@ -3,7 +3,7 @@ from typing import Self
3
3
 
4
4
  from oldaplib.src.dtypes.languagein import LanguageIn
5
5
  from oldaplib.src.dtypes.xsdset import XsdSet
6
- from oldaplib.src.enums.attributeclass import AttributeClass
6
+ from oldaplib.src.enums.attributeclass import AttributeClass, Target
7
7
  from oldaplib.src.enums.xsd_datatypes import XsdDatatypes
8
8
  from oldaplib.src.helpers.langstring import LangString
9
9
  from oldaplib.src.helpers.numeric import Numeric
@@ -12,6 +12,7 @@ from oldaplib.src.helpers.observable_set import ObservableSet
12
12
  from oldaplib.src.xsd.iri import Iri
13
13
  from oldaplib.src.xsd.xsd_boolean import Xsd_boolean
14
14
  from oldaplib.src.xsd.xsd_integer import Xsd_integer
15
+ from oldaplib.src.xsd.xsd_qname import Xsd_QName
15
16
  from oldaplib.src.xsd.xsd_string import Xsd_string
16
17
 
17
18
 
@@ -35,26 +36,28 @@ class PropClassAttr(AttributeClass):
35
36
  - `PropertyClassAttribute.DESCRIPTION`: Description of the property. The literal is a string that may
36
37
  have attached a language id.
37
38
  """
38
- # order: (QName, mandatory, immutable, datatype)
39
+ # order: (QName, mandatory, immutable, datatype, target)
39
40
  SUBPROPERTY_OF = ('rdfs:subPropertyOf', False, False, Iri)
40
- TYPE = ('rdf:type', False, False, ObservableSet)
41
- CLASS = ('sh:class', False, False, Iri)
42
- NODEKIND = ('sh:nodeKind', False, False, Iri)
43
- DATATYPE = ('sh:datatype', False, False, XsdDatatypes)
44
- NAME = ('sh:name', False, False, LangString) # needs notifier
45
- DESCRIPTION = ('sh:description', False, False, LangString) # needs notifier
46
- LANGUAGE_IN = ('sh:languageIn', False, False, LanguageIn) # needs notifier
47
- UNIQUE_LANG = ('sh:uniqueLang', False, False, Xsd_boolean)
48
- IN = ('sh:in', False, False, XsdSet) # needs notifier
49
- MIN_LENGTH = ('sh:minLength', False, False, Xsd_integer)
50
- MAX_LENGTH = ('sh:maxLength', False, False, Xsd_integer)
51
- PATTERN = ('sh:pattern', False, False, Xsd_string)
52
- MIN_EXCLUSIVE = ('sh:minExclusive', False, False, Numeric)
53
- MIN_INCLUSIVE = ('sh:minInclusive', False, False, Numeric)
54
- MAX_EXCLUSIVE = ('sh:maxExclusive', False, False, Numeric)
55
- MAX_INCLUSIVE = ('sh:maxInclusive', False, False, Numeric)
56
- LESS_THAN = ('sh:lessThan', False, False, Iri)
57
- LESS_THAN_OR_EQUALS = ('sh:lessThanOrEquals', False, False, Iri)
41
+ TYPE = ('rdf:type', False, False, ObservableSet, Target.OWL)
42
+ CLASS = ('sh:class', False, False, Iri, Target.SHACL)
43
+ NODEKIND = ('sh:nodeKind', False, False, Iri, Target.SHACL)
44
+ DATATYPE = ('sh:datatype', False, False, XsdDatatypes, Target.SHACL)
45
+ NAME = ('sh:name', False, False, LangString, Target.SHACL) # needs notifier
46
+ DESCRIPTION = ('sh:description', False, False, LangString, Target.SHACL) # needs notifier
47
+ LANGUAGE_IN = ('sh:languageIn', False, False, LanguageIn, Target.SHACL) # needs notifier
48
+ UNIQUE_LANG = ('sh:uniqueLang', False, False, Xsd_boolean, Target.SHACL)
49
+ IN = ('sh:in', False, False, XsdSet, Target.SHACL) # needs notifier
50
+ MIN_LENGTH = ('sh:minLength', False, False, Xsd_integer, Target.SHACL)
51
+ MAX_LENGTH = ('sh:maxLength', False, False, Xsd_integer, Target.SHACL)
52
+ PATTERN = ('sh:pattern', False, False, Xsd_string, Target.SHACL)
53
+ MIN_EXCLUSIVE = ('sh:minExclusive', False, False, Numeric, Target.SHACL)
54
+ MIN_INCLUSIVE = ('sh:minInclusive', False, False, Numeric, Target.SHACL)
55
+ MAX_EXCLUSIVE = ('sh:maxExclusive', False, False, Numeric, Target.SHACL)
56
+ MAX_INCLUSIVE = ('sh:maxInclusive', False, False, Numeric, Target.SHACL)
57
+ LESS_THAN = ('sh:lessThan', False, False, Iri, Target.SHACL)
58
+ LESS_THAN_OR_EQUALS = ('sh:lessThanOrEquals', False, False, Iri, Target.SHACL)
59
+ INVERSE_OF = ('owl:inverseOf', False, False, Xsd_QName, Target.OWL)
60
+ EQUIVALEND_PROPERTY = ('owl:equivalentProperty', False, False, Xsd_QName, Target.OWL)
58
61
 
59
62
 
60
63
  @classmethod
@@ -823,6 +823,8 @@ class PropertyClass(Model, Notify):
823
823
  group = val
824
824
  elif key in propkeys:
825
825
  attr = PropClassAttr.from_value(key)
826
+ if not attr.in_shacl:
827
+ continue
826
828
  if attr.datatype == Numeric:
827
829
  if not isinstance(val, (Xsd_integer, Xsd_float)):
828
830
  raise OldapErrorInconsistency(f'SHACL inconsistency: "{attr.value}" expects a "Xsd:integer" or "Xsd:float", but got "{type(val).__name__}".')
@@ -858,6 +860,7 @@ class PropertyClass(Model, Notify):
858
860
  def read_owl(self) -> None:
859
861
  if self._externalOntology:
860
862
  return
863
+ propkeys = {Xsd_QName(x.value) for x in PropClassAttr}
861
864
  context = Context(name=self._con.context_name)
862
865
  query1 = context.sparql_context
863
866
  query1 += f"""
@@ -878,24 +881,12 @@ class PropertyClass(Model, Notify):
878
881
  obj = r['o']
879
882
  match attr:
880
883
  case 'rdf:type':
881
- if obj == 'owl:DatatypeProperty':
882
- self._attributes[PropClassAttr.TYPE].add(OwlPropertyType.OwlDataProperty)
883
- elif obj == 'owl:ObjectProperty':
884
- self._attributes[PropClassAttr.TYPE].add(OwlPropertyType.OwlObjectProperty)
885
- elif obj == 'rdf:Property':
886
- self._attributes[PropClassAttr.TYPE].add(OwlPropertyType.StatementProperty)
887
- elif obj == 'owl:TransitiveProperty':
888
- self._attributes[PropClassAttr.TYPE].add(OwlPropertyType.TransitiveProperty)
889
- elif obj == 'owl:SymmetricProperty':
890
- self._attributes[PropClassAttr.TYPE].add(OwlPropertyType.SymmetricProperty)
891
- elif obj == 'owl:ReflexiveProperty':
892
- self._attributes[PropClassAttr.TYPE].add(OwlPropertyType.ReflexiveProperty)
893
- elif obj == 'owl:IrreflexiveProperty':
894
- self._attributes[PropClassAttr.TYPE].add(OwlPropertyType.IrreflexiveProperty)
895
- elif obj == 'owl:InverseFunctionalProperty':
896
- self._attributes[PropClassAttr.TYPE].add(OwlPropertyType.InverseFunctionalProperty)
897
- else:
898
- raise OldapErrorNotFound(f'Unknown owl:Property type "{obj}"')
884
+ try:
885
+ # If obj is already a member, keep it; otherwise look it up by value
886
+ prop_type = obj if isinstance(obj, OwlPropertyType) else OwlPropertyType(obj)
887
+ except ValueError as e:
888
+ raise OldapErrorNotFound(f'Unknown owl:Property type "{obj}"') from e
889
+ self._attributes[PropClassAttr.TYPE].add(prop_type)
899
890
  case 'owl:subPropertyOf':
900
891
  self._attributes[PropClassAttr.SUBPROPERTY_OF] = obj
901
892
  case 'rdfs:range':
@@ -919,6 +910,11 @@ class PropertyClass(Model, Notify):
919
910
  dt = obj
920
911
  if self._modified != dt:
921
912
  raise OldapError(f'Inconsistency between SHACL and OWL: created "{self._modified}" vs "{dt}" for property "{self._property_class_iri}".')
913
+ case _:
914
+ if attr in propkeys:
915
+ pcattr = PropClassAttr.from_value(attr)
916
+ if pcattr.in_owl:
917
+ self._attributes[pcattr] = pcattr.datatype(obj)
922
918
  #
923
919
  # Consistency checks
924
920
  #
@@ -1052,7 +1048,7 @@ class PropertyClass(Model, Notify):
1052
1048
  sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}oldap:statementProperty {self._statementProperty.toRdf}'
1053
1049
  sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}oldap:externalOntology {self._externalOntology.toRdf}'
1054
1050
  for prop, value in self._attributes.items():
1055
- if prop == PropClassAttr.TYPE:
1051
+ if not prop.in_shacl:
1056
1052
  continue
1057
1053
  if not value and not isinstance(value, bool):
1058
1054
  #if value is None:
@@ -1085,24 +1081,47 @@ class PropertyClass(Model, Notify):
1085
1081
 
1086
1082
  def create_owl_part1(self, timestamp: Xsd_dateTime, indent: int = 0, indent_inc: int = 4) -> str:
1087
1083
  blank = ''
1088
- sparql = f'{blank:{indent * indent_inc}}{self._property_class_iri.toRdf} rdf:type {self._attributes[PropClassAttr.TYPE].toRdf}'
1089
- if self._attributes.get(PropClassAttr.SUBPROPERTY_OF):
1090
- sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}rdfs:subPropertyOf {self._attributes[PropClassAttr.SUBPROPERTY_OF].toRdf}'
1084
+ sparql = f'{blank:{indent * indent_inc}}{self._property_class_iri.toRdf} {PropClassAttr.TYPE.toRdf} {self._attributes[PropClassAttr.TYPE].toRdf}'
1091
1085
  if self._internal:
1092
1086
  sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}rdfs:domain {self._internal.toRdf}'
1093
1087
  if self._attributes.get(PropClassAttr.TYPE) and OwlPropertyType.OwlDataProperty in self._attributes[PropClassAttr.TYPE]:
1094
1088
  sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}rdfs:range {self._attributes[PropClassAttr.DATATYPE].value}'
1095
1089
  elif self._attributes.get(PropClassAttr.TYPE) and OwlPropertyType.OwlObjectProperty in self._attributes[PropClassAttr.TYPE]:
1096
1090
  sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}rdfs:range {self._attributes[PropClassAttr.CLASS].toRdf}'
1091
+ for attr, val in self._attributes.items():
1092
+ #attr = PropClassAttr.from_value(key)
1093
+ if not attr.in_owl or attr == PropClassAttr.TYPE or val is None:
1094
+ continue
1095
+ if attr == PropClassAttr.NAME:
1096
+ sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}rdfs:label {val.toRdf}'
1097
+ elif attr == PropClassAttr.DESCRIPTION:
1098
+ sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}rdfs:comment {val.toRdf}'
1099
+ else:
1100
+ sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}{attr.toRdf} {val.toRdf}'
1097
1101
  sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}dcterms:creator {self._con.userIri.toRdf}'
1098
1102
  sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}dcterms:created {timestamp.toRdf}'
1099
1103
  sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}dcterms:contributor {self._con.userIri.toRdf}'
1100
1104
  sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}dcterms:modified {timestamp.toRdf}'
1101
- if self.name:
1102
- sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}rdfs:label {self.name.toRdf}'
1103
- if self.description:
1104
- sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}rdfs:comment {self.description.toRdf}'
1105
1105
  sparql += ' .\n'
1106
+
1107
+ # sparql = f'{blank:{indent * indent_inc}}{self._property_class_iri.toRdf} rdf:type {self._attributes[PropClassAttr.TYPE].toRdf}'
1108
+ # if self._attributes.get(PropClassAttr.SUBPROPERTY_OF):
1109
+ # sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}rdfs:subPropertyOf {self._attributes[PropClassAttr.SUBPROPERTY_OF].toRdf}'
1110
+ # if self._internal:
1111
+ # sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}rdfs:domain {self._internal.toRdf}'
1112
+ # if self._attributes.get(PropClassAttr.TYPE) and OwlPropertyType.OwlDataProperty in self._attributes[PropClassAttr.TYPE]:
1113
+ # sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}rdfs:range {self._attributes[PropClassAttr.DATATYPE].value}'
1114
+ # elif self._attributes.get(PropClassAttr.TYPE) and OwlPropertyType.OwlObjectProperty in self._attributes[PropClassAttr.TYPE]:
1115
+ # sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}rdfs:range {self._attributes[PropClassAttr.CLASS].toRdf}'
1116
+ # sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}dcterms:creator {self._con.userIri.toRdf}'
1117
+ # sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}dcterms:created {timestamp.toRdf}'
1118
+ # sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}dcterms:contributor {self._con.userIri.toRdf}'
1119
+ # sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}dcterms:modified {timestamp.toRdf}'
1120
+ # if self.name:
1121
+ # sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}rdfs:label {self.name.toRdf}'
1122
+ # if self.description:
1123
+ # sparql += f' ;\n{blank:{(indent + 1) * indent_inc}}rdfs:comment {self.description.toRdf}'
1124
+ # sparql += ' .\n'
1106
1125
  return sparql
1107
1126
 
1108
1127
  def create_owl_part2(self, *,
@@ -1218,6 +1237,7 @@ class PropertyClass(Model, Notify):
1218
1237
  try:
1219
1238
  self._con.transaction_update(sparql)
1220
1239
  except OldapError as err:
1240
+ print(sparql)
1221
1241
  self._con.transaction_abort()
1222
1242
  raise
1223
1243
  if not self._externalOntology: # it's a project specific property -> OWL has been written -> check consistency!
@@ -1362,12 +1382,14 @@ class PropertyClass(Model, Notify):
1362
1382
  owlclass_iri: Xsd_QName | None = None,
1363
1383
  timestamp: Xsd_dateTime,
1364
1384
  indent: int = 0, indent_inc: int = 4) -> str:
1385
+ tmp = {x for x in PropClassAttr if x.in_owl and x != PropClassAttr.TYPE}
1365
1386
  owl_propclass_attributes = {PropClassAttr.SUBPROPERTY_OF, # should be in OWL ontology
1366
1387
  PropClassAttr.DATATYPE, # used for rdfs:range in OWL ontology
1367
- PropClassAttr.CLASS} # used for rdfs:range in OWL ontology
1388
+ PropClassAttr.CLASS} | tmp # used for rdfs:range in OWL ontology
1389
+ tmp = {x: x.value.toRdf for x in PropClassAttr if x.in_owl and x != PropClassAttr.TYPE}
1368
1390
  owl_prop = {PropClassAttr.SUBPROPERTY_OF: PropClassAttr.SUBPROPERTY_OF.value,
1369
1391
  PropClassAttr.DATATYPE: "rdfs:range",
1370
- PropClassAttr.CLASS: "rdfs:range"}
1392
+ PropClassAttr.CLASS: "rdfs:range"} | tmp
1371
1393
  blank = ''
1372
1394
  sparql_list = []
1373
1395
  for prop, change in self._changeset.items():
oldaplib/src/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.3.4"
1
+ __version__ = "0.3.5"
@@ -55,7 +55,7 @@ class Xsd_QName(Xsd):
55
55
  raise OldapErrorValue(f'Invalid string "{value}" for QName. Error: {err}')
56
56
  self._value = f'{prefix}:{fragment}'
57
57
  else:
58
- raise OldapErrorValue(f'Invalid value for QName "{value}"')
58
+ raise OldapErrorValue(f'Invalid value for QName "{value}" (type: {type(value).__name__})')
59
59
  else:
60
60
  prefix = Xsd_NCName(value, validate=validate)
61
61
  if fragment:
@@ -110,6 +110,22 @@ class TestPropertyClass(unittest.TestCase):
110
110
  self.assertEqual(p.get(PropClassAttr.DESCRIPTION), LangString("A property for testing...@en", "Property für Tests@de"))
111
111
  self.assertEqual(p[PropClassAttr.TYPE], {OwlPropertyType.StatementProperty, OwlPropertyType.OwlDataProperty})
112
112
 
113
+ def test_propertyclass_constructor_owlprop(self):
114
+ p = PropertyClass(con=self._connection,
115
+ project=self._project,
116
+ property_class_iri=Xsd_QName('test:isParent'),
117
+ toClass=Iri('test:Human'),
118
+ name=LangString(["Parent"]),
119
+ description={"Parent of the human"})
120
+ i = PropertyClass(con=self._connection,
121
+ project=self._project,
122
+ property_class_iri=Xsd_QName('test:isChild'),
123
+ toClass=Iri('test:Human'),
124
+ inverseOf=Xsd_QName('test:isParent'),
125
+ name=LangString(["Child"]),
126
+ description={"Child of the human"})
127
+ self.assertEqual(i.inverseOf, Xsd_QName('test:isParent'))
128
+
113
129
  def test_propertyclass_inset_datatypes(self):
114
130
  p = PropertyClass(con=self._connection,
115
131
  project=self._project,
@@ -416,6 +432,30 @@ class TestPropertyClass(unittest.TestCase):
416
432
  ignore_cache=True)
417
433
  self.assertEqual(p4.get(PropClassAttr.TYPE), {OwlPropertyType.SymmetricProperty, OwlPropertyType.OwlDataProperty})
418
434
 
435
+ def test_propertyclass_create_G(self):
436
+ p = PropertyClass(con=self._connection,
437
+ project=self._project,
438
+ property_class_iri=Xsd_QName('test:isParentG'),
439
+ toClass=Iri('test:Human'),
440
+ name=LangString(["Parent"]),
441
+ description={"Parent of the human"})
442
+ p.create()
443
+ i = PropertyClass(con=self._connection,
444
+ project=self._project,
445
+ property_class_iri=Xsd_QName('test:isChildG'),
446
+ toClass=Iri('test:Human'),
447
+ inverseOf=Xsd_QName('test:isParentG'),
448
+ name=LangString(["Child"]),
449
+ description={"Child of the human"})
450
+ self.assertEqual(i.inverseOf, Xsd_QName('test:isParentG'))
451
+ i.create()
452
+ i2 = PropertyClass.read(con=self._connection,
453
+ project=self._project,
454
+ property_class_iri=Xsd_QName('test:isChildG'),
455
+ ignore_cache=True)
456
+ self.assertEqual(i2.get(PropClassAttr.INVERSE_OF), Xsd_QName('test:isParentG'))
457
+
458
+
419
459
  def test_propertyclass_create_nopermission(self):
420
460
  p1 = PropertyClass(
421
461
  con=self._unpriv,
@@ -850,6 +890,24 @@ class TestPropertyClass(unittest.TestCase):
850
890
  ignore_cache=True)
851
891
  self.assertEqual(p8.get(PropClassAttr.TYPE), {OwlPropertyType.SymmetricProperty, OwlPropertyType.OwlDataProperty})
852
892
 
893
+ def test_propertyclass_update9(self):
894
+ i = PropertyClass(con=self._connection,
895
+ project=self._project,
896
+ property_class_iri=Xsd_QName('test:isChild9'),
897
+ toClass=Iri('test:Human'),
898
+ inverseOf=Xsd_QName('test:isParent9'),
899
+ name=LangString(["Child"]),
900
+ description={"Child of the human"})
901
+ self.assertEqual(i.inverseOf, Xsd_QName('test:isParent9'))
902
+ i.create()
903
+ i.inverseOf = Xsd_QName('test:anotherParent')
904
+ i.update()
905
+ i2 = PropertyClass.read(con=self._connection,
906
+ project=self._project,
907
+ property_class_iri=Xsd_QName('test:isChild9'),
908
+ ignore_cache=True)
909
+ self.assertEqual(i2.get(PropClassAttr.INVERSE_OF), Xsd_QName('test:anotherParent'))
910
+
853
911
  # @unittest.skip('Work in progress')
854
912
  def test_propertyclass_delete_attrs(self):
855
913
  p1 = PropertyClass(
@@ -894,6 +952,23 @@ class TestPropertyClass(unittest.TestCase):
894
952
  res = QueryProcessor(self._context, jsonres)
895
953
  self.assertEqual(len(res), 0)
896
954
 
955
+ def test_propertyclass_delete_owlattr(self):
956
+ i = PropertyClass(con=self._connection,
957
+ project=self._project,
958
+ property_class_iri=Xsd_QName('test:isChildDel'),
959
+ toClass=Iri('test:Human'),
960
+ inverseOf=Xsd_QName('test:isParentDel'),
961
+ name=LangString(["Child"]),
962
+ description={"Child of the human"})
963
+ i.create()
964
+ i.inverseOf = None
965
+ i.update()
966
+ i2 = PropertyClass.read(con=self._connection,
967
+ project=self._project,
968
+ property_class_iri=Xsd_QName('test:isChildDel'),
969
+ ignore_cache=True)
970
+ self.assertIsNone(i2.get(PropClassAttr.INVERSE_OF))
971
+
897
972
  # @unittest.skip('Work in progress')
898
973
  def test_propertyclass_delete(self):
899
974
  p1 = PropertyClass(
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: oldaplib
3
- Version: 0.3.4
3
+ Version: 0.3.5
4
4
  Summary: Open Media Access Server Library (Linked Open Data middleware/RESTApi)
5
5
  License: GNU Affero General Public License version 3
6
6
  Author: Lukas Rosenthaler
@@ -9,6 +9,7 @@ Requires-Python: >=3.12,<4.0
9
9
  Classifier: License :: Other/Proprietary License
10
10
  Classifier: Programming Language :: Python :: 3
11
11
  Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
12
13
  Requires-Dist: bcrypt (==5.0.0)
13
14
  Requires-Dist: bump2version (>=1.0.1,<2.0.0)
14
15
  Requires-Dist: cloudpickle (>=3.1.1,<4.0.0)
@@ -20,17 +20,17 @@ oldaplib/src/dtypes/xsdset.py,sha256=oMFSY7JGBf0CYneoHL3OtnFIeEPaULN3FdUW7u15_I4
20
20
  oldaplib/src/enums/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  oldaplib/src/enums/action.py,sha256=aL7XXmoZ63_L2TTR37vqHpPPf5H_kYiPunNyiSDN28U,828
22
22
  oldaplib/src/enums/adminpermissions.py,sha256=v8Rc83NPSG_s7830-I7CbmKIhOioN2YkSH1xhWMKXdU,1998
23
- oldaplib/src/enums/attributeclass.py,sha256=Nm8gaNvs3vT-bjvj8QZDPev1ncjxzOng9R7auP6yV_g,2402
23
+ oldaplib/src/enums/attributeclass.py,sha256=Lc7OnMMl9vjXj0SuL0l30iEjwC3oWDv_C8PFeTavDGc,3006
24
24
  oldaplib/src/enums/datapermissions.py,sha256=0KiDjrPeSpGDAui8Z74sFBdDm64stzcMJx_dVEa2-bo,3437
25
25
  oldaplib/src/enums/externalontologyattr.py,sha256=U5vlEQwOkf80mHbztBXicpsWSOCNcHzhoRFJlPnwj-E,808
26
26
  oldaplib/src/enums/haspropertyattr.py,sha256=ZncedtYDNAP0kaPE_nsbzb7EdAt32wMXTPxWBBwwvy4,748
27
27
  oldaplib/src/enums/language.py,sha256=OfQsFpIBj8lGBbZEqVCR_1F-bimPM48vqBl4EKBgggY,4623
28
28
  oldaplib/src/enums/oldaplistattr.py,sha256=xuOU3oP35-PFFmlI-jlN28yqdk5lp_OzScKCC1O4IDI,620
29
29
  oldaplib/src/enums/oldaplistnodeattr.py,sha256=qokSxE-0FLyWNipjjY3gZJC2bBEt1qS1Z2SFg-gb0kc,722
30
- oldaplib/src/enums/owlpropertytype.py,sha256=GvOFTMRNid1W0IdmWfG1vDTYaA945FOpTBP9k7QRpes,997
30
+ oldaplib/src/enums/owlpropertytype.py,sha256=R7DaCV4vtkGeuDhslN3q7719J1sLKUL-x0o91Te7Qk8,989
31
31
  oldaplib/src/enums/permissionsetattr.py,sha256=og4jPvbY86ABr_I9qIvhvg4iIiQCFMcv9-_0D2gfzz8,839
32
32
  oldaplib/src/enums/projectattr.py,sha256=A_iayrT3Sd1L_guhHtCKSlUaVf9JqikRXqML-GHkJ3o,1173
33
- oldaplib/src/enums/propertyclassattr.py,sha256=TrfJwHrvjpYBqF1_fTNFQJKwIrK7AFMzSyV-1vsQfTg,3786
33
+ oldaplib/src/enums/propertyclassattr.py,sha256=92R_rVdG-xAWLsRqFknuyKIwLXI-g8gTszL_x9cGNVk,4263
34
34
  oldaplib/src/enums/resourceclassattr.py,sha256=g8tc5JDr4wLCteBNnhHMVE4cRZOhlSQqs-qFnRB3_N0,709
35
35
  oldaplib/src/enums/sparql_result_format.py,sha256=MLBHKY25o96mswSWioR-rS__zP6kPzYGNIWLZCr9784,636
36
36
  oldaplib/src/enums/userattr.py,sha256=ZRBGGLP5NMvyAER893TzRjfkhZk4jOtS9RsSkYsQM-c,1628
@@ -66,11 +66,11 @@ oldaplib/src/oldaplistnode.py,sha256=NnC2juEGTtEkDO6OlB9PjSw_zTF-wSsRUgEk-6VV9DA
66
66
  oldaplib/src/oldaplogging.py,sha256=IDSOylms9OSTInYPC4Y2QrTTEzRL0T5I2QssCevOhTU,1242
67
67
  oldaplib/src/permissionset.py,sha256=bzzVuZ7O_yVMujziwo32GEJIZYGG3g5gTds4HjLmGtU,31874
68
68
  oldaplib/src/project.py,sha256=DNwViRg19zkE1F0zuWqQFK008uTVehVAu7xNbyessig,34207
69
- oldaplib/src/propertyclass.py,sha256=T2lRyqB7KnHGqpUhlb0Rv6_4xrl7L6Ck4Gnr9C9vcC8,91984
69
+ oldaplib/src/propertyclass.py,sha256=pnaDsmyGKQnJaaOHXA0XyLcp4zn1b1vC9sLbjXls4lM,93462
70
70
  oldaplib/src/resourceclass.py,sha256=EIxyd7Z_w59wDxWLXCaLvhhvh5SjLEUWb8gqmZz8LLM,102046
71
71
  oldaplib/src/user.py,sha256=Z4GXPRkaHXx3glUpPXQdFqYMxQPOuqayDwkTAE5RGjU,48820
72
72
  oldaplib/src/userdataclass.py,sha256=FbZkcRt0pKbOeqsZ7HbpwoKE-XPWH2AqpHG1GcsrBPo,12364
73
- oldaplib/src/version.py,sha256=UwIhDBoqqZjYW7sIs3nj3FDOHCGSvF-VwNKHwkA_fmI,21
73
+ oldaplib/src/version.py,sha256=7Mpk_ZUorFUStSKEAk4F5dnB7uCLNFviloAVMVv5V-8,21
74
74
  oldaplib/src/xsd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
75
  oldaplib/src/xsd/floatingpoint.py,sha256=rDReKqh0mXyc4F5wslgTUxbeGf3-PGERyughj5_62YI,8852
76
76
  oldaplib/src/xsd/iri.py,sha256=w1Dr0z-REi7yPe3GPGnyzGrLVMvLY03kEeK-AmZ9sxw,8383
@@ -106,7 +106,7 @@ oldaplib/src/xsd/xsd_nonnegativeinteger.py,sha256=pj9xa5YslZV6gSlnyIk4aXESQVgtsE
106
106
  oldaplib/src/xsd/xsd_nonpositiveinteger.py,sha256=7cAFDIcewzeDZscQi3cbDZdqcbUMAvYR7DHrPvFw_fM,965
107
107
  oldaplib/src/xsd/xsd_normalizedstring.py,sha256=NLLzH2Memdlrp4Ogvu94YOOOQzEMjvQeEZ8J-tOV40M,3965
108
108
  oldaplib/src/xsd/xsd_positiveinteger.py,sha256=gAuqOpcOo0RHXtONXc2l-NSfcvSLDiSboUl963OAh1I,946
109
- oldaplib/src/xsd/xsd_qname.py,sha256=vHSkV-9LE5JubdlUmBtvLp-_QQDZBxAC6FagSbgfHZw,7358
109
+ oldaplib/src/xsd/xsd_qname.py,sha256=A5W5Xoth8PYG_zVgLaOonhP0Zplb2vXOgmDakY_5c1o,7389
110
110
  oldaplib/src/xsd/xsd_short.py,sha256=Yg1ltCIay2y-NObW4ZN-UvYfAF2sOOi_ZFLdyiUP6hQ,990
111
111
  oldaplib/src/xsd/xsd_string.py,sha256=y_tw17IrI1xr1lLDSGlPPp1U22N8Oea787kTJz7QO1I,9780
112
112
  oldaplib/src/xsd/xsd_time.py,sha256=aZLXu2a-nyA1_FuloW-foL6UWnXwO7pMqhiPmAexL2Y,3671
@@ -134,7 +134,7 @@ oldaplib/test/test_oldaplist_helpers.py,sha256=vJkA_Txhdk4oIwo2YK566yOte2Z6MQksh
134
134
  oldaplib/test/test_oldaplistnode.py,sha256=bWoCmDmHvOnNNviSCvhWo7LA2CskA_5IRDxNUufTKj4,149434
135
135
  oldaplib/test/test_permissionset.py,sha256=YOCirqm_oFE1Emz9fYsnDeawwI6zHN9xBv9vOZnKst0,23368
136
136
  oldaplib/test/test_project.py,sha256=fwkfaCxEskd27xinxDDr74dMWs7S0YcGr84mUOw20x4,25290
137
- oldaplib/test/test_propertyclass.py,sha256=eJd5xz_zpGNagan0zac_wwxLVoU8ci8dLFFU-sxlnSc,49445
137
+ oldaplib/test/test_propertyclass.py,sha256=67Kw5cDlPzRNm20bqz1QB-8PXFpV5iQy8Jza1epLXxk,53293
138
138
  oldaplib/test/test_resourceclass.py,sha256=WQGyns2S8O6vDH8oXBQjcww_VcjIONovuNdKm0coO-c,96621
139
139
  oldaplib/test/test_semantic_version.py,sha256=OSJYHWDpKBqk-HsxJ2nFpSr14a4OEZTFCogzEni8mcE,3392
140
140
  oldaplib/test/test_user.py,sha256=gLTcQ0ymi9pYPPpq9BOY_3YS07EJXtnJKFCHe4Rj0mQ,72133
@@ -157,6 +157,6 @@ oldaplib/testdata/source_type.yaml,sha256=dSihKikw3O-IlGf6anj5KWMoBYLaweLVF1Zojm
157
157
  oldaplib/testdata/test_move_left_of_toL.yaml,sha256=2m1OSQrQFlsCQxeJrjzBAO74LMprNDo_HuyrYGsOeXI,787
158
158
  oldaplib/testdata/testlist.yaml,sha256=AT11nXEG81Sfyb-tr1gQV0H_dZBrOCcFuHf7YtL8P2g,1994
159
159
  oldaplib/testit.http,sha256=qW7mnr6aNLXFG6lQdLgyhXILOPN6qc5iFVZclLyVvkY,303
160
- oldaplib-0.3.4.dist-info/METADATA,sha256=BPQxTrS2_5kauWCqBpmRbeD5p6VZFjRZ1dWLPw58oMs,2803
161
- oldaplib-0.3.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
162
- oldaplib-0.3.4.dist-info/RECORD,,
160
+ oldaplib-0.3.5.dist-info/METADATA,sha256=YpXOxS-1xvQQpvMl_REtdkSbsizXGNcE3zhylyTrj2s,2854
161
+ oldaplib-0.3.5.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
162
+ oldaplib-0.3.5.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.0
2
+ Generator: poetry-core 2.1.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any