spdx-python-model 0.0.2__py3-none-any.whl → 0.0.3__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.
@@ -6,6 +6,9 @@
6
6
  #
7
7
  # SPDX-License-Identifier: Apache-2.0
8
8
 
9
+ from __future__ import annotations
10
+
11
+ import decimal
9
12
  import functools
10
13
  import hashlib
11
14
  import json
@@ -14,19 +17,36 @@ import sys
14
17
  import threading
15
18
  import time
16
19
  import warnings
20
+ from abc import ABC, abstractmethod
17
21
  from contextlib import contextmanager
18
- from datetime import datetime, timezone, timedelta
22
+ from datetime import datetime, timedelta, timezone
19
23
  from enum import Enum
20
- from abc import ABC, abstractmethod
21
-
22
-
23
- def check_type(obj, types):
24
+ from typing import (
25
+ Any,
26
+ Callable,
27
+ Collection,
28
+ Dict,
29
+ Iterable,
30
+ Iterator,
31
+ List,
32
+ Optional,
33
+ Set,
34
+ Tuple,
35
+ Type,
36
+ Union,
37
+ cast,
38
+ )
39
+
40
+
41
+ def check_type(obj: Any, types: Union[Type[Any], Tuple[Type[Any], ...]]) -> None:
24
42
  if not isinstance(obj, types):
25
43
  if isinstance(types, (list, tuple)):
26
44
  raise TypeError(
27
- f"Value must be one of type: {', '.join(t.__name__ for t in types)}. Got {type(obj)}"
45
+ f"Value must be one of type: {', '.join(t.__name__ for t in types)}. Got {type(obj).__name__}"
28
46
  )
29
- raise TypeError(f"Value must be of type {types.__name__}. Got {type(obj)}")
47
+ raise TypeError(
48
+ f"Value must be of type {types.__name__}. Got {type(obj).__name__}"
49
+ )
30
50
 
31
51
 
32
52
  class Property(ABC):
@@ -35,13 +55,15 @@ class Property(ABC):
35
55
  class
36
56
  """
37
57
 
38
- def __init__(self, *, pattern=None):
58
+ VALID_TYPES: Union[Tuple, Type] = ()
59
+
60
+ def __init__(self, *, pattern: Optional[str] = None):
39
61
  self.pattern = pattern
40
62
 
41
- def init(self):
63
+ def init(self) -> Any:
42
64
  return None
43
65
 
44
- def validate(self, value):
66
+ def validate(self, value) -> None:
45
67
  check_type(value, self.VALID_TYPES)
46
68
  if self.pattern is not None and not re.search(
47
69
  self.pattern, self.to_string(value)
@@ -50,37 +72,41 @@ class Property(ABC):
50
72
  f"Value is not correctly formatted. Got '{self.to_string(value)}'"
51
73
  )
52
74
 
53
- def set(self, value):
75
+ def set(self, value: Any) -> Any:
54
76
  return value
55
77
 
56
- def check_min_count(self, value, min_count):
78
+ def check_min_count(self, value, min_count: int) -> bool:
57
79
  return min_count == 1
58
80
 
59
- def check_max_count(self, value, max_count):
81
+ def check_max_count(self, value, max_count: int) -> bool:
60
82
  return max_count == 1
61
83
 
62
- def elide(self, value):
84
+ def elide(self, value) -> bool:
63
85
  return value is None
64
86
 
65
- def walk(self, value, callback, path):
87
+ def walk(self, value, callback: Callable, path: List[str]) -> None:
66
88
  callback(value, path)
67
89
 
68
- def iter_objects(self, value, recursive, visited):
90
+ def iter_objects(
91
+ self, value, recursive: bool, visited: Set[SHACLObject]
92
+ ) -> Iterable[Any]:
69
93
  return []
70
94
 
71
- def link_prop(self, value, objectset, missing, visited):
95
+ def link_prop(
96
+ self, value, objectset, missing: Optional[Set[str]], visited: Set[SHACLObject]
97
+ ):
72
98
  return value
73
99
 
74
- def to_string(self, value):
100
+ def to_string(self, value) -> str:
75
101
  return str(value)
76
102
 
77
103
  @abstractmethod
78
- def encode(self, encoder, value, state):
79
- pass
104
+ def encode(self, encoder, value, state) -> None:
105
+ raise NotImplementedError("Subclasses must implement encode method")
80
106
 
81
107
  @abstractmethod
82
- def decode(self, decoder, *, objectset=None):
83
- pass
108
+ def decode(self, decoder, *, objectset: Optional[SHACLObjectSet] = None) -> Any:
109
+ raise NotImplementedError("Subclasses must implement decode method")
84
110
 
85
111
 
86
112
  class StringProp(Property):
@@ -90,21 +116,25 @@ class StringProp(Property):
90
116
 
91
117
  VALID_TYPES = str
92
118
 
93
- def set(self, value):
119
+ def set(self, value) -> str:
94
120
  return str(value)
95
121
 
96
- def encode(self, encoder, value, state):
122
+ def encode(self, encoder, value, state) -> None:
97
123
  encoder.write_string(value)
98
124
 
99
- def decode(self, decoder, *, objectset=None):
125
+ def decode(
126
+ self, decoder, *, objectset: Optional[SHACLObjectSet] = None
127
+ ) -> Optional[str]:
100
128
  return decoder.read_string()
101
129
 
102
130
 
103
131
  class AnyURIProp(StringProp):
104
- def encode(self, encoder, value, state):
132
+ def encode(self, encoder, value, state) -> None:
105
133
  encoder.write_iri(value)
106
134
 
107
- def decode(self, decoder, *, objectset=None):
135
+ def decode(
136
+ self, decoder, *, objectset: Optional[SHACLObjectSet] = None
137
+ ) -> Optional[str]:
108
138
  return decoder.read_iri()
109
139
 
110
140
 
@@ -117,37 +147,52 @@ class DateTimeProp(Property):
117
147
  UTC_FORMAT_STR = "%Y-%m-%dT%H:%M:%SZ"
118
148
  REGEX = r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(Z|[+-]\d{2}:\d{2})?$"
119
149
 
120
- def set(self, value):
150
+ def set(self, value) -> datetime:
121
151
  return self._normalize(value)
122
152
 
123
- def encode(self, encoder, value, state):
153
+ def encode(self, encoder, value, state) -> None:
124
154
  encoder.write_datetime(self.to_string(value))
125
155
 
126
- def decode(self, decoder, *, objectset=None):
156
+ def decode(
157
+ self, decoder, *, objectset: Optional[SHACLObjectSet] = None
158
+ ) -> Optional[datetime]:
127
159
  s = decoder.read_datetime()
128
160
  if s is None:
129
161
  return None
162
+ if isinstance(s, datetime):
163
+ return self._normalize(s)
130
164
  v = self.from_string(s)
131
165
  return self._normalize(v)
132
166
 
133
- def _normalize(self, value):
167
+ def _normalize(self, value: datetime) -> datetime:
134
168
  if value.utcoffset() is None:
135
169
  value = value.astimezone()
170
+
171
+ # Remove seconds from timezone offset
136
172
  offset = value.utcoffset()
137
- seconds = offset % timedelta(minutes=-1 if offset.total_seconds() < 0 else 1)
138
- if seconds:
139
- offset = offset - seconds
140
- value = value.replace(tzinfo=timezone(offset))
173
+ if offset is not None:
174
+ seconds = offset % timedelta(
175
+ minutes=-1 if offset.total_seconds() < 0 else 1
176
+ )
177
+ if seconds:
178
+ offset = offset - seconds
179
+ value = value.replace(tzinfo=timezone(offset))
180
+
181
+ # Convert 00:00 timezone offset to UTC
182
+ offset = value.utcoffset()
183
+ if offset is not None and offset.seconds == 0:
184
+ value = value.astimezone(timezone.utc)
185
+
141
186
  value = value.replace(microsecond=0)
142
187
  return value
143
188
 
144
- def to_string(self, value):
189
+ def to_string(self, value: datetime) -> str:
145
190
  value = self._normalize(value)
146
191
  if value.tzinfo == timezone.utc:
147
192
  return value.strftime(self.UTC_FORMAT_STR)
148
193
  return value.isoformat()
149
194
 
150
- def from_string(self, value):
195
+ def from_string(self, value: str) -> datetime:
151
196
  if not re.match(self.REGEX, value):
152
197
  raise ValueError(f"'{value}' is not a correctly formatted datetime")
153
198
  if "Z" in value:
@@ -172,25 +217,27 @@ class DateTimeStampProp(DateTimeProp):
172
217
  class IntegerProp(Property):
173
218
  VALID_TYPES = int
174
219
 
175
- def set(self, value):
220
+ def set(self, value) -> int:
176
221
  return int(value)
177
222
 
178
- def encode(self, encoder, value, state):
223
+ def encode(self, encoder, value, state) -> None:
179
224
  encoder.write_integer(value)
180
225
 
181
- def decode(self, decoder, *, objectset=None):
226
+ def decode(
227
+ self, decoder, *, objectset: Optional[SHACLObjectSet] = None
228
+ ) -> Optional[int]:
182
229
  return decoder.read_integer()
183
230
 
184
231
 
185
232
  class PositiveIntegerProp(IntegerProp):
186
- def validate(self, value):
233
+ def validate(self, value) -> None:
187
234
  super().validate(value)
188
235
  if value < 1:
189
236
  raise ValueError(f"Value must be >=1. Got {value}")
190
237
 
191
238
 
192
239
  class NonNegativeIntegerProp(IntegerProp):
193
- def validate(self, value):
240
+ def validate(self, value) -> None:
194
241
  super().validate(value)
195
242
  if value < 0:
196
243
  raise ValueError(f"Value must be >= 0. Got {value}")
@@ -199,41 +246,52 @@ class NonNegativeIntegerProp(IntegerProp):
199
246
  class BooleanProp(Property):
200
247
  VALID_TYPES = bool
201
248
 
202
- def set(self, value):
249
+ def set(self, value) -> bool:
203
250
  return bool(value)
204
251
 
205
- def encode(self, encoder, value, state):
252
+ def encode(self, encoder, value, state) -> None:
206
253
  encoder.write_bool(value)
207
254
 
208
- def decode(self, decoder, *, objectset=None):
255
+ def decode(
256
+ self, decoder, *, objectset: Optional[SHACLObjectSet] = None
257
+ ) -> Optional[bool]:
209
258
  return decoder.read_bool()
210
259
 
211
260
 
212
261
  class FloatProp(Property):
213
262
  VALID_TYPES = (float, int)
214
263
 
215
- def set(self, value):
264
+ def set(self, value) -> float:
216
265
  return float(value)
217
266
 
218
- def encode(self, encoder, value, state):
267
+ def encode(self, encoder, value, state) -> None:
219
268
  encoder.write_float(value)
220
269
 
221
- def decode(self, decoder, *, objectset=None):
270
+ def decode(
271
+ self, decoder, *, objectset: Optional[SHACLObjectSet] = None
272
+ ) -> Optional[float]:
222
273
  return decoder.read_float()
223
274
 
224
275
 
225
276
  class IRIProp(Property):
226
- def __init__(self, context=[], *, pattern=None):
277
+ def __init__(
278
+ self,
279
+ context: Optional[List[Tuple[str, str]]] = None,
280
+ *,
281
+ pattern: Optional[str] = None,
282
+ ):
283
+ if context is None:
284
+ context = []
227
285
  super().__init__(pattern=pattern)
228
286
  self.context = context
229
287
 
230
- def compact(self, value):
288
+ def compact(self, value) -> Optional[str]:
231
289
  for iri, compact in self.context:
232
290
  if value == iri:
233
291
  return compact
234
292
  return None
235
293
 
236
- def expand(self, value):
294
+ def expand(self, value) -> Optional[str]:
237
295
  for iri, compact in self.context:
238
296
  if value == compact:
239
297
  return iri
@@ -248,15 +306,19 @@ class ObjectProp(IRIProp):
248
306
  A scalar SHACL object property of a SHACL object
249
307
  """
250
308
 
251
- def __init__(self, cls, required, context=[]):
309
+ def __init__(
310
+ self, cls, required: bool, context: Optional[List[Tuple[str, str]]] = None
311
+ ):
312
+ if context is None:
313
+ context = []
252
314
  super().__init__(context)
253
315
  self.cls = cls
254
316
  self.required = required
255
317
 
256
- def validate(self, value):
318
+ def validate(self, value) -> None:
257
319
  check_type(value, (self.cls, str))
258
320
 
259
- def walk(self, value, callback, path):
321
+ def walk(self, value, callback: Callable, path: List[str]) -> None:
260
322
  if value is None:
261
323
  return
262
324
 
@@ -265,7 +327,7 @@ class ObjectProp(IRIProp):
265
327
  else:
266
328
  callback(value, path)
267
329
 
268
- def iter_objects(self, value, recursive, visited):
330
+ def iter_objects(self, value, recursive: bool, visited):
269
331
  if value is None or isinstance(value, str):
270
332
  return
271
333
 
@@ -277,7 +339,7 @@ class ObjectProp(IRIProp):
277
339
  for c in value.iter_objects(recursive=True, visited=visited):
278
340
  yield c
279
341
 
280
- def encode(self, encoder, value, state):
342
+ def encode(self, encoder, value, state) -> None:
281
343
  if value is None:
282
344
  raise ValueError("Object cannot be None")
283
345
 
@@ -287,11 +349,12 @@ class ObjectProp(IRIProp):
287
349
 
288
350
  return value.encode(encoder, state)
289
351
 
290
- def decode(self, decoder, *, objectset=None):
291
- iri = decoder.read_iri()
292
- if iri is None:
352
+ def decode(self, decoder, *, objectset: Optional[SHACLObjectSet] = None):
353
+ if decoder.is_object():
293
354
  return self.cls.decode(decoder, objectset=objectset)
294
355
 
356
+ iri = decoder.read_iri()
357
+
295
358
  iri = self.expand(iri) or iri
296
359
 
297
360
  if objectset is None:
@@ -329,41 +392,45 @@ class ObjectProp(IRIProp):
329
392
 
330
393
 
331
394
  class ListProxy(object):
332
- def __init__(self, prop, data=None):
395
+ def __init__(self, prop: Property, data: Optional[List[Any]] = None):
333
396
  if data is None:
334
- self.__data = []
397
+ self.__data: List[Any] = []
335
398
  else:
336
399
  self.__data = data
337
400
  self.__prop = prop
338
401
 
339
- def append(self, value):
402
+ def append(self, value) -> None:
340
403
  self.__prop.validate(value)
341
404
  self.__data.append(self.__prop.set(value))
342
405
 
343
- def insert(self, idx, value):
406
+ def insert(self, idx: int, value) -> None:
344
407
  self.__prop.validate(value)
345
408
  self.__data.insert(idx, self.__prop.set(value))
346
409
 
347
- def extend(self, items):
410
+ def extend(self, items: Iterable[Any]) -> None:
348
411
  for i in items:
349
412
  self.append(i)
350
413
 
351
- def sort(self, *args, **kwargs):
414
+ def sort(self, *args, **kwargs) -> None:
352
415
  self.__data.sort(*args, **kwargs)
353
416
 
354
417
  def __getitem__(self, key):
355
418
  return self.__data[key]
356
419
 
357
- def __setitem__(self, key, value):
420
+ def __setitem__(self, key, value) -> None:
358
421
  if isinstance(key, slice):
359
422
  for v in value:
360
423
  self.__prop.validate(v)
361
424
  self.__data[key] = [self.__prop.set(v) for v in value]
362
- else:
425
+ elif isinstance(key, int):
363
426
  self.__prop.validate(value)
364
427
  self.__data[key] = self.__prop.set(value)
428
+ else:
429
+ raise TypeError(
430
+ f"ListProxy indices must be integers or slices. Got {type(key).__name__}"
431
+ )
365
432
 
366
- def __delitem__(self, key):
433
+ def __delitem__(self, key) -> None:
367
434
  del self.__data[key]
368
435
 
369
436
  def __contains__(self, item):
@@ -372,10 +439,10 @@ class ListProxy(object):
372
439
  def __iter__(self):
373
440
  return iter(self.__data)
374
441
 
375
- def __len__(self):
442
+ def __len__(self) -> int:
376
443
  return len(self.__data)
377
444
 
378
- def __str__(self):
445
+ def __str__(self) -> str:
379
446
  return str(self.__data)
380
447
 
381
448
  def __repr__(self):
@@ -395,43 +462,43 @@ class ListProp(Property):
395
462
 
396
463
  VALID_TYPES = (list, ListProxy)
397
464
 
398
- def __init__(self, prop):
465
+ def __init__(self, prop: Property):
399
466
  super().__init__()
400
467
  self.prop = prop
401
468
 
402
- def init(self):
469
+ def init(self) -> ListProxy:
403
470
  return ListProxy(self.prop)
404
471
 
405
- def validate(self, value):
472
+ def validate(self, value) -> None:
406
473
  super().validate(value)
407
474
 
408
475
  for i in value:
409
476
  self.prop.validate(i)
410
477
 
411
- def set(self, value):
478
+ def set(self, value) -> ListProxy:
412
479
  if isinstance(value, ListProxy):
413
480
  return value
414
481
 
415
482
  return ListProxy(self.prop, [self.prop.set(d) for d in value])
416
483
 
417
- def check_min_count(self, value, min_count):
484
+ def check_min_count(self, value, min_count: int) -> bool:
418
485
  check_type(value, ListProxy)
419
486
  return len(value) >= min_count
420
487
 
421
- def check_max_count(self, value, max_count):
488
+ def check_max_count(self, value, max_count: int) -> bool:
422
489
  check_type(value, ListProxy)
423
490
  return len(value) <= max_count
424
491
 
425
- def elide(self, value):
492
+ def elide(self, value) -> bool:
426
493
  check_type(value, ListProxy)
427
494
  return len(value) == 0
428
495
 
429
- def walk(self, value, callback, path):
496
+ def walk(self, value, callback: Callable, path: List[str]) -> None:
430
497
  callback(value, path)
431
498
  for idx, v in enumerate(value):
432
499
  self.prop.walk(v, callback, path + [f"[{idx}]"])
433
500
 
434
- def iter_objects(self, value, recursive, visited):
501
+ def iter_objects(self, value, recursive: bool, visited):
435
502
  for v in value:
436
503
  for c in self.prop.iter_objects(v, recursive, visited):
437
504
  yield c
@@ -444,7 +511,7 @@ class ListProp(Property):
444
511
 
445
512
  return ListProxy(self.prop, data=data)
446
513
 
447
- def encode(self, encoder, value, state):
514
+ def encode(self, encoder, value, state) -> None:
448
515
  check_type(value, ListProxy)
449
516
 
450
517
  with encoder.write_list() as list_s:
@@ -452,7 +519,9 @@ class ListProp(Property):
452
519
  with list_s.write_list_item() as item_s:
453
520
  self.prop.encode(item_s, v, state)
454
521
 
455
- def decode(self, decoder, *, objectset=None):
522
+ def decode(
523
+ self, decoder, *, objectset: Optional[SHACLObjectSet] = None
524
+ ) -> ListProxy:
456
525
  data = []
457
526
  for val_d in decoder.read_list():
458
527
  v = self.prop.decode(val_d, objectset=objectset)
@@ -465,10 +534,10 @@ class ListProp(Property):
465
534
  class EnumProp(IRIProp):
466
535
  VALID_TYPES = str
467
536
 
468
- def __init__(self, values, *, pattern=None):
537
+ def __init__(self, values, *, pattern: Optional[str] = None):
469
538
  super().__init__(values, pattern=pattern)
470
539
 
471
- def validate(self, value):
540
+ def validate(self, value) -> None:
472
541
  super().validate(value)
473
542
 
474
543
  valid_values = self.iri_values()
@@ -477,10 +546,10 @@ class EnumProp(IRIProp):
477
546
  f"'{value}' is not a valid value. Choose one of {' '.join(valid_values)}"
478
547
  )
479
548
 
480
- def encode(self, encoder, value, state):
549
+ def encode(self, encoder, value, state) -> None:
481
550
  encoder.write_enum(value, self, self.compact(value))
482
551
 
483
- def decode(self, decoder, *, objectset=None):
552
+ def decode(self, decoder, *, objectset: Optional[SHACLObjectSet] = None) -> str:
484
553
  v = decoder.read_enum(self)
485
554
  return self.expand(v) or v
486
555
 
@@ -491,7 +560,7 @@ class NodeKind(Enum):
491
560
  BlankNodeOrIRI = 3
492
561
 
493
562
 
494
- def is_IRI(s):
563
+ def is_IRI(s: Any) -> bool:
495
564
  if not isinstance(s, str):
496
565
  return False
497
566
  if s.startswith("_:"):
@@ -501,7 +570,7 @@ def is_IRI(s):
501
570
  return True
502
571
 
503
572
 
504
- def is_blank_node(s):
573
+ def is_blank_node(s: Any) -> bool:
505
574
  if not isinstance(s, str):
506
575
  return False
507
576
  if not s.startswith("_:"):
@@ -509,19 +578,23 @@ def is_blank_node(s):
509
578
  return True
510
579
 
511
580
 
512
- def register(type_iri, *, compact_type=None, abstract=False):
513
- def add_class(key, c):
581
+ def register(
582
+ type_iri: str, *, compact_type: Optional[str] = None, abstract: bool = False
583
+ ):
584
+ def add_class(key: str, c: Type[SHACLObject]) -> None:
514
585
  assert (
515
586
  key not in SHACLObject.CLASSES
516
587
  ), f"{key} already registered to {SHACLObject.CLASSES[key].__name__}"
517
588
  SHACLObject.CLASSES[key] = c
518
589
 
519
- def decorator(c):
590
+ def decorator(c: Type[SHACLObject]) -> Type[SHACLObject]:
591
+ """
592
+ Decorator to register a class as a SHACL object type.
593
+ The class must derive from SHACLObject.
594
+ """
520
595
  global NAMED_INDIVIDUALS
521
596
 
522
- assert issubclass(
523
- c, SHACLObject
524
- ), f"{c.__name__} is not derived from SHACLObject"
597
+ assert issubclass(c, SHACLObject), f"{c} is not derived from SHACLObject"
525
598
 
526
599
  c._OBJ_TYPE = type_iri
527
600
  c.IS_ABSTRACT = abstract
@@ -542,16 +615,31 @@ def register(type_iri, *, compact_type=None, abstract=False):
542
615
 
543
616
 
544
617
  register_lock = threading.Lock()
545
- NAMED_INDIVIDUALS = set()
618
+ NAMED_INDIVIDUALS: Set[str] = set()
546
619
 
547
620
 
548
621
  @functools.total_ordering
549
622
  class SHACLObject(object):
550
- CLASSES = {}
623
+ CLASSES: Dict[str, Type] = {}
624
+ NAMED_INDIVIDUALS: Dict[str, str] = {}
551
625
  NODE_KIND = NodeKind.BlankNodeOrIRI
552
- ID_ALIAS = None
553
- IS_ABSTRACT = True
554
- IS_DEPRECATED = False
626
+ ID_ALIAS: Optional[str] = None
627
+ IS_ABSTRACT: bool = True
628
+ IS_DEPRECATED: bool = False
629
+
630
+ # These will be reinitialized during registration with @register decorator,
631
+ # defined here first to allow visibility at class level
632
+ _OBJ_TYPE: str = ""
633
+ _OBJ_COMPACT_TYPE: Optional[str] = None
634
+ _OBJ_PROPERTIES: Dict[str, Tuple] = {}
635
+ _OBJ_IRIS: Dict[str, str] = {}
636
+ _OBJ_DEPRECATED: Set[str] = set()
637
+ _NEEDS_REG: bool = True
638
+
639
+ # Instance variables
640
+ _id: Optional[str]
641
+ _obj_data: Dict[str, Any]
642
+ _obj_metadata: Dict[str, Any]
555
643
 
556
644
  def __init__(self, **kwargs):
557
645
  if self._is_abstract():
@@ -560,7 +648,9 @@ class SHACLObject(object):
560
648
  )
561
649
 
562
650
  if self.__class__.IS_DEPRECATED:
563
- warnings.warn(f"{self.__class__.__name__} is deprecated", DeprecationWarning)
651
+ warnings.warn(
652
+ f"{self.__class__.__name__} is deprecated", DeprecationWarning
653
+ )
564
654
 
565
655
  with register_lock:
566
656
  cls = self.__class__
@@ -580,24 +670,24 @@ class SHACLObject(object):
580
670
  for k, v in kwargs.items():
581
671
  setattr(self, k, v)
582
672
 
583
- def _is_abstract(self):
673
+ def _is_abstract(self) -> bool:
584
674
  return self.__class__.IS_ABSTRACT
585
675
 
586
676
  @classmethod
587
- def _register_props(cls):
677
+ def _register_props(cls: Type[SHACLObject]) -> None:
588
678
  cls._add_property("_id", StringProp(), iri="@id")
589
679
 
590
680
  @classmethod
591
681
  def _add_property(
592
- cls,
593
- pyname,
594
- prop,
595
- iri,
596
- min_count=None,
597
- max_count=None,
598
- compact=None,
599
- deprecated=False,
600
- ):
682
+ cls: Type[SHACLObject],
683
+ pyname: str,
684
+ prop: Property,
685
+ iri: str,
686
+ min_count: Optional[int] = None,
687
+ max_count: Optional[int] = None,
688
+ compact: Optional[str] = None,
689
+ deprecated: bool = False,
690
+ ) -> None:
601
691
  if pyname in cls._OBJ_IRIS:
602
692
  raise KeyError(f"'{pyname}' is already defined for '{cls.__name__}'")
603
693
  if iri in cls._OBJ_PROPERTIES:
@@ -614,7 +704,7 @@ class SHACLObject(object):
614
704
  if deprecated:
615
705
  cls._OBJ_DEPRECATED.add(iri)
616
706
 
617
- def __setattr__(self, name, value):
707
+ def __setattr__(self, name: str, value) -> None:
618
708
  if name == self.ID_ALIAS:
619
709
  self["@id"] = value
620
710
  return
@@ -627,7 +717,7 @@ class SHACLObject(object):
627
717
  f"'{name}' is not a valid property of {self.__class__.__name__}"
628
718
  )
629
719
 
630
- def __getattr__(self, name):
720
+ def __getattr__(self, name: str):
631
721
  if name in self._OBJ_IRIS:
632
722
  return self.__dict__["_obj_data"][self._OBJ_IRIS[name]]
633
723
 
@@ -650,7 +740,7 @@ class SHACLObject(object):
650
740
  f"'{name}' is not a valid property of {self.__class__.__name__}"
651
741
  )
652
742
 
653
- def __delattr__(self, name):
743
+ def __delattr__(self, name: str) -> None:
654
744
  if name == self.ID_ALIAS:
655
745
  del self["@id"]
656
746
  return
@@ -663,7 +753,9 @@ class SHACLObject(object):
663
753
  f"'{name}' is not a valid property of {self.__class__.__name__}"
664
754
  )
665
755
 
666
- def __get_prop(self, iri):
756
+ def __get_prop(
757
+ self, iri: str
758
+ ) -> Tuple[Property, Optional[int], Optional[int], str, Optional[str]]:
667
759
  if iri not in self._OBJ_PROPERTIES:
668
760
  raise KeyError(
669
761
  f"'{iri}' is not a valid property of {self.__class__.__name__}"
@@ -671,45 +763,51 @@ class SHACLObject(object):
671
763
 
672
764
  return self._OBJ_PROPERTIES[iri]
673
765
 
674
- def __iter_props(self):
766
+ def __iter_props(
767
+ self,
768
+ ) -> Iterator[
769
+ Tuple[str, Property, Optional[int], Optional[int], str, Optional[str]]
770
+ ]:
675
771
  for iri, v in self._OBJ_PROPERTIES.items():
676
772
  yield iri, *v
677
773
 
678
- def __getitem__(self, iri):
774
+ def __getitem__(self, iri: str) -> Any:
679
775
  return self.__dict__["_obj_data"][iri]
680
776
 
681
- def __setitem__(self, iri, value):
777
+ def __setitem__(self, iri: str, value) -> None:
682
778
  if iri == "@id":
683
779
  if self.NODE_KIND == NodeKind.BlankNode:
684
780
  if not is_blank_node(value):
685
781
  raise ValueError(
686
- f"{self.__class__.__name__} ({id(self)}) can only have local reference. Property '{iri}' cannot be set to '{value}' and must start with '_:'"
782
+ f"{self.__class__.__name__} ({id(self)}) can only have local reference. Property '{iri}' cannot be set to {value!r} and must start with '_:'"
687
783
  )
688
784
  elif self.NODE_KIND == NodeKind.IRI:
689
785
  if not is_IRI(value):
690
786
  raise ValueError(
691
- f"{self.__class__.__name__} ({id(self)}) can only have an IRI value. Property '{iri}' cannot be set to '{value}'"
787
+ f"{self.__class__.__name__} ({id(self)}) can only have an IRI value. Property '{iri}' cannot be set to {value!r}"
692
788
  )
693
789
  else:
694
790
  if not is_blank_node(value) and not is_IRI(value):
695
791
  raise ValueError(
696
- f"{self.__class__.__name__} ({id(self)}) Has invalid Property '{iri}' '{value}'. Must be a blank node or IRI"
792
+ f"{self.__class__.__name__} ({id(self)}) Has invalid Property '{iri}' {value!r}. Must be a blank node or IRI"
697
793
  )
698
794
 
699
795
  prop, _, _, pyname, _ = self.__get_prop(iri)
700
796
  prop.validate(value)
701
797
  if iri in self._OBJ_DEPRECATED:
702
- warnings.warn(f"{self.__class__.__name__}.{pyname} is deprecated", DeprecationWarning)
798
+ warnings.warn(
799
+ f"{self.__class__.__name__}.{pyname} is deprecated", DeprecationWarning
800
+ )
703
801
  self.__dict__["_obj_data"][iri] = prop.set(value)
704
802
 
705
- def __delitem__(self, iri):
803
+ def __delitem__(self, iri: str) -> None:
706
804
  prop, _, _, _, _ = self.__get_prop(iri)
707
805
  self.__dict__["_obj_data"][iri] = prop.init()
708
806
 
709
- def __iter__(self):
710
- return self._OBJ_PROPERTIES.keys()
807
+ def __iter__(self) -> Iterator[str]:
808
+ return iter(self._OBJ_PROPERTIES.keys())
711
809
 
712
- def walk(self, callback, path=None):
810
+ def walk(self, callback: Callable, path: Optional[List[str]] = None) -> None:
713
811
  """
714
812
  Walk object tree, invoking the callback for each item
715
813
 
@@ -724,13 +822,13 @@ class SHACLObject(object):
724
822
  for iri, prop, _, _, _, _ in self.__iter_props():
725
823
  prop.walk(self.__dict__["_obj_data"][iri], callback, path + [f".{iri}"])
726
824
 
727
- def property_keys(self):
825
+ def property_keys(self) -> Iterator[Tuple[Optional[str], str, Optional[str]]]:
728
826
  for iri, _, _, _, pyname, compact in self.__iter_props():
729
827
  if iri == "@id":
730
828
  compact = self.ID_ALIAS
731
829
  yield pyname, iri, compact
732
830
 
733
- def iter_objects(self, *, recursive=False, visited=None):
831
+ def iter_objects(self, *, recursive: bool = False, visited=None):
734
832
  """
735
833
  Iterate of all objects that are a child of this one
736
834
  """
@@ -743,7 +841,7 @@ class SHACLObject(object):
743
841
  ):
744
842
  yield c
745
843
 
746
- def encode(self, encoder, state):
844
+ def encode(self, encoder, state) -> None:
747
845
  idname = self.ID_ALIAS or self._OBJ_IRIS["_id"]
748
846
  if not self._id and self.NODE_KIND == NodeKind.IRI:
749
847
  raise ValueError(
@@ -792,52 +890,43 @@ class SHACLObject(object):
792
890
  prop.encode(prop_s, value, state)
793
891
 
794
892
  @classmethod
795
- def _make_object(cls, typ):
893
+ def _make_object(cls: Type["SHACLObject"], typ: str) -> "SHACLObject":
796
894
  if typ not in cls.CLASSES:
797
895
  raise TypeError(f"Unknown type {typ}")
798
896
 
799
897
  return cls.CLASSES[typ]()
800
898
 
801
899
  @classmethod
802
- def decode(cls, decoder, *, objectset=None):
900
+ def decode(cls, decoder, *, objectset: Optional[SHACLObjectSet] = None):
803
901
  typ, obj_d = decoder.read_object()
804
902
  if typ is None:
805
903
  raise TypeError("Unable to determine type for object")
806
904
 
807
905
  obj = cls._make_object(typ)
808
- for key in (obj.ID_ALIAS, obj._OBJ_IRIS["_id"]):
809
- with obj_d.read_property(key) as prop_d:
810
- if prop_d is None:
811
- continue
812
-
813
- _id = prop_d.read_iri()
814
- if _id is None:
815
- raise TypeError(f"Object key '{key}' is the wrong type")
816
-
817
- obj._id = _id
818
- break
906
+ _id = obj_d.read_object_id(obj.ID_ALIAS)
907
+ if _id is not None:
908
+ obj._id = _id
819
909
 
820
910
  if obj.NODE_KIND == NodeKind.IRI and not obj._id:
821
911
  raise ValueError("Object is missing required IRI")
822
912
 
823
913
  if objectset is not None:
824
914
  if obj._id:
825
- v = objectset.find_by_id(_id)
915
+ v = objectset.find_by_id(obj._id)
826
916
  if v is not None:
827
917
  return v
918
+ objectset.add_index(obj)
828
919
 
829
920
  obj._decode_properties(obj_d, objectset=objectset)
830
921
 
831
- if objectset is not None:
832
- objectset.add_index(obj)
833
922
  return obj
834
923
 
835
- def _decode_properties(self, decoder, objectset=None):
924
+ def _decode_properties(self, decoder, objectset: Optional[SHACLObjectSet] = None):
836
925
  for key in decoder.object_keys():
837
926
  if not self._decode_prop(decoder, key, objectset=objectset):
838
927
  raise KeyError(f"Unknown property '{key}'")
839
928
 
840
- def _decode_prop(self, decoder, key, objectset=None):
929
+ def _decode_prop(self, decoder, key, objectset: Optional[SHACLObjectSet] = None):
841
930
  if key in (self._OBJ_IRIS["_id"], self.ID_ALIAS):
842
931
  return True
843
932
 
@@ -857,7 +946,9 @@ class SHACLObject(object):
857
946
 
858
947
  return False
859
948
 
860
- def link_helper(self, objectset, missing, visited):
949
+ def link_helper(
950
+ self, objectset: Optional[SHACLObjectSet], missing, visited
951
+ ) -> None:
861
952
  if self in visited:
862
953
  return
863
954
 
@@ -900,7 +991,7 @@ class SHACLObject(object):
900
991
  return sort_key(self) < sort_key(other)
901
992
 
902
993
 
903
- class SHACLExtensibleObject(object):
994
+ class SHACLExtensibleObject(SHACLObject):
904
995
  CLOSED = False
905
996
 
906
997
  def __init__(self, typ=None, **kwargs):
@@ -910,7 +1001,7 @@ class SHACLExtensibleObject(object):
910
1001
  self.__dict__["_obj_TYPE"] = (self._OBJ_TYPE, self._OBJ_COMPACT_TYPE)
911
1002
  super().__init__(**kwargs)
912
1003
 
913
- def _is_abstract(self):
1004
+ def _is_abstract(self) -> bool:
914
1005
  # Unknown classes are assumed to not be abstract so that they can be
915
1006
  # deserialized
916
1007
  typ = self.__dict__["_obj_TYPE"][0]
@@ -928,7 +1019,7 @@ class SHACLExtensibleObject(object):
928
1019
  obj = cls(typ)
929
1020
  return obj
930
1021
 
931
- def _decode_properties(self, decoder, objectset=None):
1022
+ def _decode_properties(self, decoder, objectset: Optional[SHACLObjectSet] = None):
932
1023
  def decode_value(d):
933
1024
  if not d.is_list():
934
1025
  return d.read_value()
@@ -952,25 +1043,6 @@ class SHACLExtensibleObject(object):
952
1043
  self.__dict__["_obj_data"][key] = decode_value(prop_d)
953
1044
 
954
1045
  def _encode_properties(self, encoder, state):
955
- def encode_value(encoder, v):
956
- if isinstance(v, bool):
957
- encoder.write_bool(v)
958
- elif isinstance(v, str):
959
- encoder.write_string(v)
960
- elif isinstance(v, int):
961
- encoder.write_integer(v)
962
- elif isinstance(v, float):
963
- encoder.write_float(v)
964
- elif isinstance(v, list):
965
- with encoder.write_list() as list_s:
966
- for i in v:
967
- with list_s.write_list_item() as item_s:
968
- encode_value(item_s, i)
969
- else:
970
- raise TypeError(
971
- f"Unsupported serialized type {type(v)} with value '{v}'"
972
- )
973
-
974
1046
  super()._encode_properties(encoder, state)
975
1047
  if self.CLOSED:
976
1048
  return
@@ -980,9 +1052,27 @@ class SHACLExtensibleObject(object):
980
1052
  continue
981
1053
 
982
1054
  with encoder.write_property(iri) as prop_s:
983
- encode_value(prop_s, value)
984
-
985
- def __setitem__(self, iri, value):
1055
+ if isinstance(value, list):
1056
+ v = value
1057
+ else:
1058
+ v = [value]
1059
+ with prop_s.write_list() as list_s:
1060
+ for i in v:
1061
+ with list_s.write_list_item() as item_s:
1062
+ if isinstance(i, bool):
1063
+ item_s.write_bool(i)
1064
+ elif isinstance(i, str):
1065
+ item_s.write_string(i)
1066
+ elif isinstance(i, int):
1067
+ item_s.write_integer(i)
1068
+ elif isinstance(i, float):
1069
+ item_s.write_float(i)
1070
+ else:
1071
+ raise TypeError(
1072
+ f"Unsupported serialized type {type(i)} with value {i!r}"
1073
+ )
1074
+
1075
+ def __setitem__(self, iri: str, value) -> None:
986
1076
  try:
987
1077
  super().__setitem__(iri, value)
988
1078
  except KeyError:
@@ -991,9 +1081,10 @@ class SHACLExtensibleObject(object):
991
1081
 
992
1082
  if not is_IRI(iri):
993
1083
  raise KeyError(f"Key '{iri}' must be an IRI")
1084
+ obj_data = self.__dict__["_obj_data"]
994
1085
  self.__dict__["_obj_data"][iri] = value
995
1086
 
996
- def __delitem__(self, iri):
1087
+ def __delitem__(self, iri: str) -> None:
997
1088
  try:
998
1089
  super().__delitem__(iri)
999
1090
  except KeyError:
@@ -1011,8 +1102,8 @@ class SHACLExtensibleObject(object):
1011
1102
  return self.__dict__["_obj_TYPE"][1]
1012
1103
  return super().__getattr__(name)
1013
1104
 
1014
- def property_keys(self):
1015
- iris = set()
1105
+ def property_keys(self) -> Iterator[Tuple[Optional[str], str, Optional[str]]]:
1106
+ iris: Set[str] = set()
1016
1107
  for pyname, iri, compact in super().property_keys():
1017
1108
  iris.add(iri)
1018
1109
  yield pyname, iri, compact
@@ -1026,16 +1117,16 @@ class SHACLExtensibleObject(object):
1026
1117
 
1027
1118
 
1028
1119
  class SHACLObjectSet(object):
1029
- def __init__(self, objects=[], *, link=False):
1030
- self.objects = set()
1031
- self.missing_ids = set()
1032
- for o in objects:
1033
- self.objects.add(o)
1120
+ def __init__(self, objects: Collection[SHACLObject] = [], *, link: bool = False):
1121
+ self.objects: Set[SHACLObject] = set(objects)
1122
+ self.missing_ids: Set[str] = set()
1123
+ self.obj_by_id: Dict[str, SHACLObject] = {}
1124
+ self.obj_by_type: Dict[str, Set[Tuple[bool, SHACLObject]]] = {}
1034
1125
  self.create_index()
1035
1126
  if link:
1036
1127
  self._link()
1037
1128
 
1038
- def create_index(self):
1129
+ def create_index(self) -> None:
1039
1130
  """
1040
1131
  (re)Create object index
1041
1132
 
@@ -1047,7 +1138,7 @@ class SHACLObjectSet(object):
1047
1138
  for o in self.foreach():
1048
1139
  self.add_index(o)
1049
1140
 
1050
- def add_index(self, obj):
1141
+ def add_index(self, obj: SHACLObject) -> None:
1051
1142
  """
1052
1143
  Add object to index
1053
1144
 
@@ -1081,7 +1172,7 @@ class SHACLObjectSet(object):
1081
1172
 
1082
1173
  self.obj_by_id[obj._id] = obj
1083
1174
 
1084
- def add(self, obj):
1175
+ def add(self, obj: SHACLObject) -> SHACLObject:
1085
1176
  """
1086
1177
  Add object to object set
1087
1178
 
@@ -1097,7 +1188,7 @@ class SHACLObjectSet(object):
1097
1188
  self.add_index(obj)
1098
1189
  return obj
1099
1190
 
1100
- def update(self, *others):
1191
+ def update(self, *others) -> None:
1101
1192
  """
1102
1193
  Update object set adding all objects in each other iterable
1103
1194
  """
@@ -1105,13 +1196,13 @@ class SHACLObjectSet(object):
1105
1196
  for obj in o:
1106
1197
  self.add(obj)
1107
1198
 
1108
- def __contains__(self, item):
1199
+ def __contains__(self, item: SHACLObject) -> bool:
1109
1200
  """
1110
1201
  Returns True if the item is in the object set
1111
1202
  """
1112
1203
  return item in self.objects
1113
1204
 
1114
- def link(self):
1205
+ def link(self) -> Set[str]:
1115
1206
  """
1116
1207
  Link object set
1117
1208
 
@@ -1127,24 +1218,24 @@ class SHACLObjectSet(object):
1127
1218
  self.create_index()
1128
1219
  return self._link()
1129
1220
 
1130
- def _link(self):
1221
+ def _link(self) -> Set[str]:
1131
1222
  global NAMED_INDIVIDUALS
1132
1223
 
1133
1224
  self.missing_ids = set()
1134
- visited = set()
1225
+ visited: Set[SHACLObject] = set()
1135
1226
 
1136
- new_objects = set()
1227
+ new_objects: Set[SHACLObject] = set()
1137
1228
 
1138
1229
  for o in self.objects:
1139
1230
  if o._id:
1140
- o = self.find_by_id(o._id, o)
1231
+ o = cast(SHACLObject, self.find_by_id(o._id, o))
1141
1232
  o.link_helper(self, self.missing_ids, visited)
1142
1233
  new_objects.add(o)
1143
1234
 
1144
1235
  self.objects = new_objects
1145
1236
 
1146
1237
  # Remove blank nodes
1147
- obj_by_id = {}
1238
+ obj_by_id: Dict[str, SHACLObject] = {}
1148
1239
  for _id, obj in self.obj_by_id.items():
1149
1240
  if _id.startswith("_:"):
1150
1241
  del obj._id
@@ -1157,7 +1248,9 @@ class SHACLObjectSet(object):
1157
1248
 
1158
1249
  return self.missing_ids
1159
1250
 
1160
- def find_by_id(self, _id, default=None):
1251
+ def find_by_id(
1252
+ self, _id: str, default: Optional[SHACLObject] = None
1253
+ ) -> Optional[SHACLObject]:
1161
1254
  """
1162
1255
  Find object by ID
1163
1256
 
@@ -1168,7 +1261,7 @@ class SHACLObjectSet(object):
1168
1261
  return default
1169
1262
  return self.obj_by_id[_id]
1170
1263
 
1171
- def foreach(self):
1264
+ def foreach(self) -> Iterable[SHACLObject]:
1172
1265
  """
1173
1266
  Iterate over every object in the object set, and all child objects
1174
1267
  """
@@ -1181,7 +1274,9 @@ class SHACLObjectSet(object):
1181
1274
  for child in o.iter_objects(recursive=True, visited=visited):
1182
1275
  yield child
1183
1276
 
1184
- def foreach_type(self, typ, *, match_subclass=True):
1277
+ def foreach_type(
1278
+ self, typ: Union[str, SHACLObject], *, match_subclass: bool = True
1279
+ ) -> Iterable[SHACLObject]:
1185
1280
  """
1186
1281
  Iterate over each object of a specified type (or subclass there of)
1187
1282
 
@@ -1190,8 +1285,9 @@ class SHACLObjectSet(object):
1190
1285
  returned
1191
1286
  """
1192
1287
  if not isinstance(typ, str):
1193
- if not issubclass(typ, SHACLObject):
1288
+ if not isinstance(typ, type) or not issubclass(typ, SHACLObject):
1194
1289
  raise TypeError(f"Type must be derived from SHACLObject, got {typ}")
1290
+ typ = cast(SHACLObject, typ)
1195
1291
  typ = typ._OBJ_TYPE
1196
1292
 
1197
1293
  if typ not in self.obj_by_type:
@@ -1201,7 +1297,7 @@ class SHACLObjectSet(object):
1201
1297
  if match_subclass or exact:
1202
1298
  yield o
1203
1299
 
1204
- def merge(self, *objectsets):
1300
+ def merge(self, *objectsets) -> "SHACLObjectSet":
1205
1301
  """
1206
1302
  Merge object sets
1207
1303
 
@@ -1215,16 +1311,59 @@ class SHACLObjectSet(object):
1215
1311
 
1216
1312
  return SHACLObjectSet(new_objects, link=True)
1217
1313
 
1218
- def encode(self, encoder, force_list=False, *, key=None):
1314
+ def inline_blank_nodes(self) -> None:
1315
+ """
1316
+ Removes (inlines) blank node objects from the root object set if they
1317
+ are referenced in only one other location besides the root.
1318
+
1319
+ Deserializers that do not preserve the tree-like structure of the
1320
+ objects (e.g. RDF) should call this to ensure that blank nodes are
1321
+ inline correctly
1322
+ """
1323
+ ref_counts: Dict[SHACLObject, int] = {}
1324
+
1325
+ def walk_callback(value: SHACLObject, path: List[str]) -> bool:
1326
+ nonlocal ref_counts
1327
+
1328
+ if not isinstance(value, SHACLObject):
1329
+ return True
1330
+
1331
+ ref_counts.setdefault(value, 0)
1332
+ ref_counts[value] += 1
1333
+ if ref_counts[value] > 1:
1334
+ return False
1335
+
1336
+ return True
1337
+
1338
+ for o in self.objects:
1339
+ # Note that every object in the root object set gets at least one
1340
+ # reference
1341
+ o.walk(walk_callback)
1342
+
1343
+ new_objects = set()
1344
+ for o in self.objects:
1345
+ if is_IRI(o._id):
1346
+ new_objects.add(o)
1347
+ # If the object is a blank node and is only referenced by this
1348
+ # root list and one other location, remove it from the root list
1349
+ #
1350
+ # A count of 1 means the object is only referenced by the root, and
1351
+ # therefore must be kept
1352
+ elif ref_counts[o] != 2:
1353
+ new_objects.add(o)
1354
+
1355
+ self.objects = new_objects
1356
+
1357
+ def encode(self, encoder, force_list: bool = False, *, key=None) -> None:
1219
1358
  """
1220
1359
  Serialize a list of objects to a serialization encoder
1221
1360
 
1222
1361
  If force_list is true, a list will always be written using the encoder.
1223
1362
  """
1224
- ref_counts = {}
1363
+ ref_counts: Dict[SHACLObject, int] = {}
1225
1364
  state = EncodeState()
1226
1365
 
1227
- def walk_callback(value, path):
1366
+ def walk_callback(value: SHACLObject, path: List[str]) -> bool:
1228
1367
  nonlocal state
1229
1368
  nonlocal ref_counts
1230
1369
 
@@ -1232,7 +1371,7 @@ class SHACLObjectSet(object):
1232
1371
  return True
1233
1372
 
1234
1373
  # Remove blank node ID for re-assignment
1235
- if value._id and value._id.startswith("_:"):
1374
+ if is_blank_node(value._id):
1236
1375
  del value._id
1237
1376
 
1238
1377
  if value._id:
@@ -1290,7 +1429,7 @@ class SHACLObjectSet(object):
1290
1429
  self.create_index()
1291
1430
 
1292
1431
  for obj_d in decoder.read_list():
1293
- o = SHACLObject.decode(obj_d, objectset=self)
1432
+ o = SHACLExtensibleObject.decode(obj_d, objectset=self)
1294
1433
  self.objects.add(o)
1295
1434
 
1296
1435
  self._link()
@@ -1312,13 +1451,13 @@ class EncodeState(object):
1312
1451
 
1313
1452
  return self.blank_objects[o]
1314
1453
 
1315
- def is_refed(self, o):
1454
+ def is_refed(self, o) -> bool:
1316
1455
  return o in self.ref_objects
1317
1456
 
1318
- def add_refed(self, o):
1457
+ def add_refed(self, o) -> None:
1319
1458
  self.ref_objects.add(o)
1320
1459
 
1321
- def is_written(self, o):
1460
+ def is_written(self, o) -> bool:
1322
1461
  return o in self.written_objects
1323
1462
 
1324
1463
  def add_written(self, o):
@@ -1327,26 +1466,26 @@ class EncodeState(object):
1327
1466
 
1328
1467
  class Decoder(ABC):
1329
1468
  @abstractmethod
1330
- def read_value(self):
1469
+ def read_value(self) -> Optional[Any]:
1331
1470
  """
1332
1471
  Consume next item
1333
1472
 
1334
1473
  Consumes the next item of any type
1335
1474
  """
1336
- pass
1475
+ raise NotImplementedError("Subclasses must implement read_value method")
1337
1476
 
1338
1477
  @abstractmethod
1339
- def read_string(self):
1478
+ def read_string(self) -> Optional[str]:
1340
1479
  """
1341
1480
  Consume the next item as a string.
1342
1481
 
1343
1482
  Returns the string value of the next item, or `None` if the next item
1344
1483
  is not a string
1345
1484
  """
1346
- pass
1485
+ raise NotImplementedError("Subclasses must implement read_string method")
1347
1486
 
1348
1487
  @abstractmethod
1349
- def read_datetime(self):
1488
+ def read_datetime(self) -> Optional[str]:
1350
1489
  """
1351
1490
  Consumes the next item as a date & time string
1352
1491
 
@@ -1357,20 +1496,20 @@ class Decoder(ABC):
1357
1496
  implementation can just check if the next item is a string without
1358
1497
  worrying about the format
1359
1498
  """
1360
- pass
1499
+ raise NotImplementedError("Subclasses must implement read_datetime method")
1361
1500
 
1362
1501
  @abstractmethod
1363
- def read_integer(self):
1502
+ def read_integer(self) -> Optional[int]:
1364
1503
  """
1365
1504
  Consumes the next item as an integer
1366
1505
 
1367
1506
  Returns the integer value of the next item, or `None` if the next item
1368
1507
  is not an integer
1369
1508
  """
1370
- pass
1509
+ raise NotImplementedError("Subclasses must implement read_integer method")
1371
1510
 
1372
1511
  @abstractmethod
1373
- def read_iri(self):
1512
+ def read_iri(self) -> Optional[str]:
1374
1513
  """
1375
1514
  Consumes the next item as an IRI string
1376
1515
 
@@ -1380,10 +1519,10 @@ class Decoder(ABC):
1380
1519
  The returned string should be either a fully-qualified IRI, or a blank
1381
1520
  node ID
1382
1521
  """
1383
- pass
1522
+ raise NotImplementedError("Subclasses must implement read_iri method")
1384
1523
 
1385
1524
  @abstractmethod
1386
- def read_enum(self, e):
1525
+ def read_enum(self, e) -> Optional[str]:
1387
1526
  """
1388
1527
  Consumes the next item as an Enum value string
1389
1528
 
@@ -1394,30 +1533,30 @@ class Decoder(ABC):
1394
1533
  actually a member of the specified Enum, so the `Decoder` does not need
1395
1534
  to check that, but can if it wishes
1396
1535
  """
1397
- pass
1536
+ raise NotImplementedError("Subclasses must implement read_enum method")
1398
1537
 
1399
1538
  @abstractmethod
1400
- def read_bool(self):
1539
+ def read_bool(self) -> Optional[bool]:
1401
1540
  """
1402
1541
  Consume the next item as a boolean value
1403
1542
 
1404
1543
  Returns the boolean value of the next item, or `None` if the next item
1405
1544
  is not a boolean
1406
1545
  """
1407
- pass
1546
+ raise NotImplementedError("Subclasses must implement read_bool method")
1408
1547
 
1409
1548
  @abstractmethod
1410
- def read_float(self):
1549
+ def read_float(self) -> Optional[float]:
1411
1550
  """
1412
1551
  Consume the next item as a float value
1413
1552
 
1414
1553
  Returns the float value of the next item, or `None` if the next item is
1415
1554
  not a float
1416
1555
  """
1417
- pass
1556
+ raise NotImplementedError("Subclasses must implement read_float method")
1418
1557
 
1419
1558
  @abstractmethod
1420
- def read_list(self):
1559
+ def read_list(self) -> Iterator["Decoder"]:
1421
1560
  """
1422
1561
  Consume the next item as a list generator
1423
1562
 
@@ -1425,19 +1564,19 @@ class Decoder(ABC):
1425
1564
  generated `Decoder` can be used to read the corresponding item from the
1426
1565
  list
1427
1566
  """
1428
- pass
1567
+ raise NotImplementedError("Subclasses must implement read_list method")
1429
1568
 
1430
1569
  @abstractmethod
1431
- def is_list(self):
1570
+ def is_list(self) -> bool:
1432
1571
  """
1433
1572
  Checks if the next item is a list
1434
1573
 
1435
1574
  Returns True if the next item is a list, or False if it is a scalar
1436
1575
  """
1437
- pass
1576
+ raise NotImplementedError("Subclasses must implement is_list method")
1438
1577
 
1439
1578
  @abstractmethod
1440
- def read_object(self):
1579
+ def read_object(self) -> Tuple[Any, "Decoder"]:
1441
1580
  """
1442
1581
  Consume next item as an object
1443
1582
 
@@ -1448,11 +1587,11 @@ class Decoder(ABC):
1448
1587
  Properties will be read out of the object using `read_property` and
1449
1588
  `read_object_id`
1450
1589
  """
1451
- pass
1590
+ raise NotImplementedError("Subclasses must implement read_object method")
1452
1591
 
1453
1592
  @abstractmethod
1454
1593
  @contextmanager
1455
- def read_property(self, key):
1594
+ def read_property(self, key) -> Iterator[Optional["Decoder"]]:
1456
1595
  """
1457
1596
  Read property from object
1458
1597
 
@@ -1460,19 +1599,28 @@ class Decoder(ABC):
1460
1599
  value of the property with the given key in current object, or `None`
1461
1600
  if the property does not exist in the current object.
1462
1601
  """
1463
- pass
1602
+ raise NotImplementedError("Subclasses must implement read_property method")
1603
+
1604
+ @abstractmethod
1605
+ def is_object(self) -> bool:
1606
+ """
1607
+ Checks if the item is an object
1608
+
1609
+ Returns True if the item is an object, or False if is not
1610
+ """
1611
+ raise NotImplementedError("Subclasses must implement is_object method")
1464
1612
 
1465
1613
  @abstractmethod
1466
- def object_keys(self):
1614
+ def object_keys(self) -> Iterator[str]:
1467
1615
  """
1468
1616
  Read property keys from an object
1469
1617
 
1470
1618
  Iterates over all the serialized keys for the current object
1471
1619
  """
1472
- pass
1620
+ raise NotImplementedError("Subclasses must implement object_keys method")
1473
1621
 
1474
1622
  @abstractmethod
1475
- def read_object_id(self, alias=None):
1623
+ def read_object_id(self, alias=None) -> Optional[Any]:
1476
1624
  """
1477
1625
  Read current object ID property
1478
1626
 
@@ -1484,15 +1632,15 @@ class Decoder(ABC):
1484
1632
  If `alias` is provided, is is a hint as to another name by which the ID
1485
1633
  might be found, if the `Decoder` supports aliases for an ID
1486
1634
  """
1487
- pass
1635
+ raise NotImplementedError("Subclasses must implement read_object_id method")
1488
1636
 
1489
1637
 
1490
1638
  class JSONLDDecoder(Decoder):
1491
- def __init__(self, data, root=False):
1639
+ def __init__(self, data, root: bool = False):
1492
1640
  self.data = data
1493
1641
  self.root = root
1494
1642
 
1495
- def read_value(self):
1643
+ def read_value(self) -> Optional[Any]:
1496
1644
  if isinstance(self.data, str):
1497
1645
  try:
1498
1646
  return float(self.data)
@@ -1500,47 +1648,47 @@ class JSONLDDecoder(Decoder):
1500
1648
  pass
1501
1649
  return self.data
1502
1650
 
1503
- def read_string(self):
1651
+ def read_string(self) -> Optional[str]:
1504
1652
  if isinstance(self.data, str):
1505
1653
  return self.data
1506
1654
  return None
1507
1655
 
1508
- def read_datetime(self):
1656
+ def read_datetime(self) -> Optional[str]:
1509
1657
  return self.read_string()
1510
1658
 
1511
- def read_integer(self):
1659
+ def read_integer(self) -> Optional[int]:
1512
1660
  if isinstance(self.data, int):
1513
1661
  return self.data
1514
1662
  return None
1515
1663
 
1516
- def read_bool(self):
1664
+ def read_bool(self) -> Optional[bool]:
1517
1665
  if isinstance(self.data, bool):
1518
1666
  return self.data
1519
1667
  return None
1520
1668
 
1521
- def read_float(self):
1669
+ def read_float(self) -> Optional[float]:
1522
1670
  if isinstance(self.data, (int, float, str)):
1523
1671
  return float(self.data)
1524
1672
  return None
1525
1673
 
1526
- def read_iri(self):
1674
+ def read_iri(self) -> Optional[str]:
1527
1675
  if isinstance(self.data, str):
1528
1676
  return self.data
1529
1677
  return None
1530
1678
 
1531
- def read_enum(self, e):
1679
+ def read_enum(self, e) -> Optional[str]:
1532
1680
  if isinstance(self.data, str):
1533
1681
  return self.data
1534
1682
  return None
1535
1683
 
1536
- def read_list(self):
1684
+ def read_list(self) -> Iterator["JSONLDDecoder"]:
1537
1685
  if self.is_list():
1538
1686
  for v in self.data:
1539
1687
  yield self.__class__(v)
1540
1688
  else:
1541
1689
  yield self
1542
1690
 
1543
- def is_list(self):
1691
+ def is_list(self) -> bool:
1544
1692
  return isinstance(self.data, (list, tuple, set))
1545
1693
 
1546
1694
  def __get_value(self, *keys):
@@ -1550,14 +1698,17 @@ class JSONLDDecoder(Decoder):
1550
1698
  return None
1551
1699
 
1552
1700
  @contextmanager
1553
- def read_property(self, key):
1701
+ def read_property(self, key) -> Iterator[Optional["JSONLDDecoder"]]:
1554
1702
  v = self.__get_value(key)
1555
1703
  if v is not None:
1556
1704
  yield self.__class__(v)
1557
1705
  else:
1558
1706
  yield None
1559
1707
 
1560
- def object_keys(self):
1708
+ def is_object(self) -> bool:
1709
+ return isinstance(self.data, dict)
1710
+
1711
+ def object_keys(self) -> Iterator[str]:
1561
1712
  for key in self.data.keys():
1562
1713
  if key in ("@type", "type"):
1563
1714
  continue
@@ -1565,19 +1716,19 @@ class JSONLDDecoder(Decoder):
1565
1716
  continue
1566
1717
  yield key
1567
1718
 
1568
- def read_object(self):
1719
+ def read_object(self) -> Tuple[Any, "JSONLDDecoder"]:
1569
1720
  typ = self.__get_value("@type", "type")
1570
1721
  if typ is not None:
1571
1722
  return typ, self
1572
1723
 
1573
1724
  return None, self
1574
1725
 
1575
- def read_object_id(self, alias=None):
1726
+ def read_object_id(self, alias=None) -> Optional[Any]:
1576
1727
  return self.__get_value(alias, "@id")
1577
1728
 
1578
1729
 
1579
1730
  class JSONLDDeserializer(object):
1580
- def deserialize_data(self, data, objectset: SHACLObjectSet):
1731
+ def deserialize_data(self, data, objectset: SHACLObjectSet) -> None:
1581
1732
  if "@graph" in data:
1582
1733
  h = JSONLDDecoder(data["@graph"], True)
1583
1734
  else:
@@ -1585,23 +1736,23 @@ class JSONLDDeserializer(object):
1585
1736
 
1586
1737
  objectset.decode(h)
1587
1738
 
1588
- def read(self, f, objectset: SHACLObjectSet):
1739
+ def read(self, f, objectset: SHACLObjectSet) -> None:
1589
1740
  data = json.load(f)
1590
1741
  self.deserialize_data(data, objectset)
1591
1742
 
1592
1743
 
1593
1744
  class Encoder(ABC):
1594
1745
  @abstractmethod
1595
- def write_string(self, v):
1746
+ def write_string(self, v) -> None:
1596
1747
  """
1597
1748
  Write a string value
1598
1749
 
1599
1750
  Encodes the value as a string in the output
1600
1751
  """
1601
- pass
1752
+ raise NotImplementedError("Subclasses must implement write_string method")
1602
1753
 
1603
1754
  @abstractmethod
1604
- def write_datetime(self, v):
1755
+ def write_datetime(self, v) -> None:
1605
1756
  """
1606
1757
  Write a date & time string
1607
1758
 
@@ -1609,19 +1760,19 @@ class Encoder(ABC):
1609
1760
 
1610
1761
  Note: The provided string is already correctly encoded as an ISO datetime
1611
1762
  """
1612
- pass
1763
+ raise NotImplementedError("Subclasses must implement write_datetime method")
1613
1764
 
1614
1765
  @abstractmethod
1615
- def write_integer(self, v):
1766
+ def write_integer(self, v) -> None:
1616
1767
  """
1617
1768
  Write an integer value
1618
1769
 
1619
1770
  Encodes the value as an integer in the output
1620
1771
  """
1621
- pass
1772
+ raise NotImplementedError("Subclasses must implement write_integer method")
1622
1773
 
1623
1774
  @abstractmethod
1624
- def write_iri(self, v, compact=None):
1775
+ def write_iri(self, v, compact=None) -> None:
1625
1776
  """
1626
1777
  Write IRI
1627
1778
 
@@ -1630,10 +1781,10 @@ class Encoder(ABC):
1630
1781
  the serialization supports compacted IRIs, it should be preferred to
1631
1782
  the full IRI
1632
1783
  """
1633
- pass
1784
+ raise NotImplementedError("Subclasses must implement write_iri method")
1634
1785
 
1635
1786
  @abstractmethod
1636
- def write_enum(self, v, e, compact=None):
1787
+ def write_enum(self, v, e, compact=None) -> None:
1637
1788
  """
1638
1789
  Write enum value IRI
1639
1790
 
@@ -1641,29 +1792,29 @@ class Encoder(ABC):
1641
1792
  qualified IRI. If `compact` is provided and the serialization supports
1642
1793
  compacted IRIs, it should be preferred to the full IRI.
1643
1794
  """
1644
- pass
1795
+ raise NotImplementedError("Subclasses must implement write_enum method")
1645
1796
 
1646
1797
  @abstractmethod
1647
- def write_bool(self, v):
1798
+ def write_bool(self, v) -> None:
1648
1799
  """
1649
1800
  Write boolean
1650
1801
 
1651
1802
  Encodes the value as a boolean in the output
1652
1803
  """
1653
- pass
1804
+ raise NotImplementedError("Subclasses must implement write_bool method")
1654
1805
 
1655
1806
  @abstractmethod
1656
- def write_float(self, v):
1807
+ def write_float(self, v) -> None:
1657
1808
  """
1658
1809
  Write float
1659
1810
 
1660
1811
  Encodes the value as a floating point number in the output
1661
1812
  """
1662
- pass
1813
+ raise NotImplementedError("Subclasses must implement write_float method")
1663
1814
 
1664
1815
  @abstractmethod
1665
1816
  @contextmanager
1666
- def write_object(self, o, _id, needs_id):
1817
+ def write_object(self, o: SHACLObject, _id: str, needs_id: bool):
1667
1818
  """
1668
1819
  Write object
1669
1820
 
@@ -1681,11 +1832,11 @@ class Encoder(ABC):
1681
1832
 
1682
1833
  Properties will be written the object using `write_property`
1683
1834
  """
1684
- pass
1835
+ raise NotImplementedError("Subclasses must implement write_object method")
1685
1836
 
1686
1837
  @abstractmethod
1687
1838
  @contextmanager
1688
- def write_property(self, iri, compact=None):
1839
+ def write_property(self, iri: str, compact: Optional[str] = None):
1689
1840
  """
1690
1841
  Write object property
1691
1842
 
@@ -1696,7 +1847,7 @@ class Encoder(ABC):
1696
1847
  the serialization supports compacted IRIs, it should be preferred to
1697
1848
  the full IRI.
1698
1849
  """
1699
- pass
1850
+ raise NotImplementedError("Subclasses must implement write_property method")
1700
1851
 
1701
1852
  @abstractmethod
1702
1853
  @contextmanager
@@ -1709,7 +1860,7 @@ class Encoder(ABC):
1709
1860
 
1710
1861
  Each item of the list will be added using `write_list_item`
1711
1862
  """
1712
- pass
1863
+ raise NotImplementedError("Subclasses must implement write_list method")
1713
1864
 
1714
1865
  @abstractmethod
1715
1866
  @contextmanager
@@ -1720,7 +1871,7 @@ class Encoder(ABC):
1720
1871
  A context manager that yields an `Encoder` that can be used to encode
1721
1872
  the value for a list item
1722
1873
  """
1723
- pass
1874
+ raise NotImplementedError("Subclasses must implement write_list_item method")
1724
1875
 
1725
1876
 
1726
1877
  class JSONLDEncoder(Encoder):
@@ -1749,14 +1900,14 @@ class JSONLDEncoder(Encoder):
1749
1900
  self.data = str(v)
1750
1901
 
1751
1902
  @contextmanager
1752
- def write_property(self, iri, compact=None):
1903
+ def write_property(self, iri: str, compact: Optional[str] = None):
1753
1904
  s = self.__class__(None)
1754
1905
  yield s
1755
1906
  if s.data is not None:
1756
- self.data[compact or iri] = s.data
1907
+ self.data[compact or iri] = s.data # type: ignore # within write_object() context, self.data is always dict or None
1757
1908
 
1758
1909
  @contextmanager
1759
- def write_object(self, o, _id, needs_id):
1910
+ def write_object(self, o: SHACLObject, _id: str, needs_id: bool):
1760
1911
  self.data = {
1761
1912
  "type": o.COMPACT_TYPE or o.TYPE,
1762
1913
  }
@@ -1776,7 +1927,7 @@ class JSONLDEncoder(Encoder):
1776
1927
  s = self.__class__(None)
1777
1928
  yield s
1778
1929
  if s.data is not None:
1779
- self.data.append(s.data)
1930
+ self.data.append(s.data) # type: ignore # within write_list() context, self.data is always list or None
1780
1931
 
1781
1932
 
1782
1933
  class JSONLDSerializer(object):
@@ -1786,11 +1937,11 @@ class JSONLDSerializer(object):
1786
1937
  def serialize_data(
1787
1938
  self,
1788
1939
  objectset: SHACLObjectSet,
1789
- force_at_graph=False,
1940
+ force_at_graph: bool = False,
1790
1941
  ):
1791
1942
  h = JSONLDEncoder()
1792
1943
  objectset.encode(h, force_at_graph)
1793
- data = {}
1944
+ data: Dict[str, Any] = {}
1794
1945
  if len(CONTEXT_URLS) == 1:
1795
1946
  data["@context"] = CONTEXT_URLS[0]
1796
1947
  elif CONTEXT_URLS:
@@ -1798,9 +1949,11 @@ class JSONLDSerializer(object):
1798
1949
 
1799
1950
  if isinstance(h.data, list):
1800
1951
  data["@graph"] = h.data
1801
- else:
1952
+ elif isinstance(h.data, dict):
1802
1953
  for k, v in h.data.items():
1803
1954
  data[k] = v
1955
+ # elif h.data is not None: # str, int, float, bool
1956
+ # data["value"] = h.data
1804
1957
 
1805
1958
  return data
1806
1959
 
@@ -1808,13 +1961,16 @@ class JSONLDSerializer(object):
1808
1961
  self,
1809
1962
  objectset: SHACLObjectSet,
1810
1963
  f,
1811
- force_at_graph=False,
1964
+ force_at_graph: bool = False,
1812
1965
  **kwargs,
1813
1966
  ):
1814
1967
  """
1815
1968
  Write a SHACLObjectSet to a JSON LD file
1816
1969
 
1817
1970
  If force_at_graph is True, a @graph node will always be written
1971
+
1972
+ Note that f should be a file-like object that supports the `write`
1973
+ method, and that opens in binary mode (e.g. `open("file.json", "wb")`).
1818
1974
  """
1819
1975
  data = self.serialize_data(objectset, force_at_graph)
1820
1976
 
@@ -1822,9 +1978,9 @@ class JSONLDSerializer(object):
1822
1978
 
1823
1979
  sha1 = hashlib.sha1()
1824
1980
  for chunk in json.JSONEncoder(**args).iterencode(data):
1825
- chunk = chunk.encode("utf-8")
1826
- f.write(chunk)
1827
- sha1.update(chunk)
1981
+ chunk_bytes = chunk.encode("utf-8")
1982
+ f.write(chunk_bytes)
1983
+ sha1.update(chunk_bytes)
1828
1984
 
1829
1985
  return sha1.hexdigest()
1830
1986
 
@@ -1870,7 +2026,7 @@ class JSONLDInlineEncoder(Encoder):
1870
2026
  self.write(json.dumps(str(v)))
1871
2027
 
1872
2028
  @contextmanager
1873
- def write_property(self, iri, compact=None):
2029
+ def write_property(self, iri: str, compact: Optional[str] = None):
1874
2030
  self._write_comma()
1875
2031
  self.write_string(compact or iri)
1876
2032
  self.write(":")
@@ -1878,7 +2034,7 @@ class JSONLDInlineEncoder(Encoder):
1878
2034
  self.comma = True
1879
2035
 
1880
2036
  @contextmanager
1881
- def write_object(self, o, _id, needs_id):
2037
+ def write_object(self, o: SHACLObject, _id: str, needs_id: bool):
1882
2038
  self._write_comma()
1883
2039
 
1884
2040
  self.write("{")
@@ -1920,7 +2076,7 @@ class JSONLDInlineSerializer(object):
1920
2076
  self,
1921
2077
  objectset: SHACLObjectSet,
1922
2078
  f,
1923
- force_at_graph=False,
2079
+ force_at_graph: bool = False,
1924
2080
  ):
1925
2081
  """
1926
2082
  Write a SHACLObjectSet to a JSON LD file
@@ -1946,13 +2102,256 @@ class JSONLDInlineSerializer(object):
1946
2102
  return sha1.hexdigest()
1947
2103
 
1948
2104
 
1949
- def print_tree(objects, all_fields=False):
2105
+ try:
2106
+ import rdflib
2107
+ import rdflib.term
2108
+ from rdflib.namespace import RDF
2109
+
2110
+ class RDFDecoder(Decoder):
2111
+ def __init__(
2112
+ self,
2113
+ graph: rdflib.Graph,
2114
+ subject: Optional[rdflib.term.Node] = None,
2115
+ predicate: Optional[rdflib.term.Node] = None,
2116
+ value: Optional[rdflib.term.Node] = None,
2117
+ ):
2118
+ self.graph = graph
2119
+ self.subject = subject
2120
+ self.predicate = predicate
2121
+ self.value = value
2122
+
2123
+ def __read_node(self):
2124
+ if self.value is not None:
2125
+ return self.value
2126
+ if self.predicate is None:
2127
+ return None
2128
+ return self.graph.value(self.subject, self.predicate)
2129
+
2130
+ def read_value(self) -> Optional[Any]:
2131
+ v = self.__read_node()
2132
+ if isinstance(v, rdflib.term.Literal):
2133
+ return v.toPython()
2134
+ return None
2135
+
2136
+ def read_string(self) -> Optional[str]:
2137
+ v = self.read_value()
2138
+ if isinstance(v, str):
2139
+ return v
2140
+ return None
2141
+
2142
+ def read_datetime(self) -> Optional[str]:
2143
+ return self.read_value()
2144
+
2145
+ def read_integer(self) -> Optional[int]:
2146
+ v = self.read_value()
2147
+ if isinstance(v, (int, decimal.Decimal)):
2148
+ return int(v)
2149
+ return None
2150
+
2151
+ def read_bool(self) -> Optional[bool]:
2152
+ v = self.read_value()
2153
+ if isinstance(v, bool):
2154
+ return v
2155
+ return None
2156
+
2157
+ def read_float(self) -> Optional[float]:
2158
+ v = self.read_value()
2159
+ if isinstance(v, (int, float, str, decimal.Decimal)):
2160
+ return float(v)
2161
+ return None
2162
+
2163
+ def read_iri(self) -> Optional[str]:
2164
+ v = self.__read_node()
2165
+ if isinstance(v, rdflib.term.URIRef):
2166
+ return v.toPython()
2167
+ elif isinstance(v, rdflib.term.Literal):
2168
+ v = v.toPython()
2169
+ if isinstance(v, str):
2170
+ return v
2171
+ elif isinstance(v, rdflib.term.BNode):
2172
+ return v.n3()
2173
+ return None
2174
+
2175
+ def read_enum(self, e) -> Optional[str]:
2176
+ v = self.__read_node()
2177
+ if isinstance(v, rdflib.term.URIRef):
2178
+ return v.toPython()
2179
+ return None
2180
+
2181
+ def read_list(self) -> Iterator["RDFDecoder"]:
2182
+ if not self.subject:
2183
+ blank_nodes = set()
2184
+ for s in self.graph.subjects(unique=True):
2185
+ # type: ignore # RDF.type is dynamic
2186
+ if (s, RDF.type, None) not in self.graph:
2187
+ continue
2188
+
2189
+ if isinstance(s, rdflib.term.BNode):
2190
+ blank_nodes.add(s)
2191
+ continue
2192
+ yield self.__class__(self.graph, s)
2193
+
2194
+ for s in blank_nodes:
2195
+ yield self.__class__(self.graph, s)
2196
+ else:
2197
+ for o in self.graph.objects(self.subject, self.predicate):
2198
+ # type: ignore # RDF.type is dynamic
2199
+ if (o, RDF.type, None) in self.graph:
2200
+ yield self.__class__(self.graph, o)
2201
+ else:
2202
+ yield self.__class__(
2203
+ self.graph,
2204
+ self.subject,
2205
+ self.predicate,
2206
+ o,
2207
+ )
2208
+
2209
+ def is_list(self) -> bool:
2210
+ if not self.subject:
2211
+ return True
2212
+ if self.value is not None:
2213
+ return False
2214
+ return len(list(self.graph.objects(self.subject, self.predicate))) > 1
2215
+
2216
+ @contextmanager
2217
+ def read_property(self, key) -> Iterator[Optional["RDFDecoder"]]:
2218
+ if key == "@id":
2219
+ yield self.__class__(self.graph, value=self.subject)
2220
+ else:
2221
+ yield self.__class__(self.graph, self.subject, rdflib.term.URIRef(key))
2222
+
2223
+ def is_object(self) -> bool:
2224
+ n = self.__read_node() or self.subject
2225
+ # type: ignore # RDF.type is dynamic
2226
+ return (n, RDF.type, None) in self.graph
2227
+
2228
+ def object_keys(self) -> Iterator[str]:
2229
+ for p in self.graph.predicates(self.subject, unique=True):
2230
+ # type: ignore # RDF.type is dynamic
2231
+ if p == RDF.type:
2232
+ continue
2233
+
2234
+ if not isinstance(p, rdflib.term.IdentifiedNode):
2235
+ raise TypeError(f"Predicate is of unknown type {type(p)}")
2236
+
2237
+ yield p.toPython()
2238
+
2239
+ def read_object(self) -> Tuple[Any, "RDFDecoder"]:
2240
+ s = self.__read_node()
2241
+ if s is None:
2242
+ s = self.subject
2243
+
2244
+ # type: ignore # RDF.type is dynamic
2245
+ typ = self.graph.value(s, RDF.type)
2246
+ if typ is None:
2247
+ return None, self
2248
+
2249
+ if not isinstance(typ, rdflib.term.IdentifiedNode):
2250
+ raise TypeError(f"Type value is of unknown type {type(typ)}")
2251
+
2252
+ return typ.toPython(), self.__class__(self.graph, s)
2253
+
2254
+ def read_object_id(self, alias=None) -> Optional[Any]:
2255
+ if isinstance(self.subject, rdflib.term.BNode):
2256
+ return self.subject.n3()
2257
+ if not isinstance(self.subject, rdflib.term.IdentifiedNode):
2258
+ raise TypeError(f"Subject is of unknown type {type(self.subject)}")
2259
+ return self.subject.toPython()
2260
+
2261
+ class RDFDeserializer(object):
2262
+ def read(self, graph: rdflib.Graph, objset: SHACLObjectSet) -> None:
2263
+ d = RDFDecoder(graph)
2264
+ objset.decode(d)
2265
+ objset.inline_blank_nodes()
2266
+
2267
+ class RDFEncoder(Encoder):
2268
+ def __init__(
2269
+ self,
2270
+ graph: rdflib.Graph,
2271
+ subject: Optional[rdflib.term.Node] = None,
2272
+ predicate: Optional[rdflib.term.Node] = None,
2273
+ ):
2274
+ self.graph = graph
2275
+ self.subject = subject
2276
+ self.predicate = predicate
2277
+
2278
+ def __add_literal(self, v):
2279
+ if self.subject is None or self.predicate is None:
2280
+ raise TypeError()
2281
+ self.graph.add((self.subject, self.predicate, rdflib.Literal(v)))
2282
+
2283
+ def __add_uriref(self, v):
2284
+ if self.subject is None or self.predicate is None:
2285
+ raise TypeError()
2286
+ self.graph.add((self.subject, self.predicate, rdflib.URIRef(v)))
2287
+
2288
+ def write_string(self, v):
2289
+ self.__add_literal(v)
2290
+
2291
+ def write_datetime(self, v):
2292
+ self.__add_literal(v)
2293
+
2294
+ def write_integer(self, v):
2295
+ self.__add_literal(v)
2296
+
2297
+ def write_iri(self, v, compact=None):
2298
+ self.__add_uriref(v)
2299
+
2300
+ def write_enum(self, v, e, compact=None):
2301
+ self.__add_uriref(v)
2302
+
2303
+ def write_bool(self, v):
2304
+ self.__add_literal(v)
2305
+
2306
+ def write_float(self, v):
2307
+ self.__add_literal(v)
2308
+
2309
+ @contextmanager
2310
+ def write_property(self, iri: str, compact: Optional[str] = None):
2311
+ yield self.__class__(self.graph, self.subject, rdflib.URIRef(iri))
2312
+
2313
+ @contextmanager
2314
+ def write_object(self, o, _id, needs_id: bool):
2315
+ obj: rdflib.term.Node
2316
+ if _id.startswith("_:"):
2317
+ obj = rdflib.BNode(_id[2:])
2318
+ else:
2319
+ obj = rdflib.URIRef(_id)
2320
+
2321
+ if self.subject is not None:
2322
+ if self.predicate is None:
2323
+ raise TypeError()
2324
+ self.graph.add((self.subject, self.predicate, obj))
2325
+ self.graph.add((obj, RDF.type, rdflib.URIRef(o.TYPE))) # type: ignore # RDF.type is dynamic
2326
+ yield self.__class__(self.graph, obj)
2327
+
2328
+ @contextmanager
2329
+ def write_list(self):
2330
+ yield self
2331
+
2332
+ @contextmanager
2333
+ def write_list_item(self):
2334
+ yield self
2335
+
2336
+ class RDFSerializer(object):
2337
+ def write(self, objset: SHACLObjectSet, g: rdflib.Graph):
2338
+ """
2339
+ Write a SHACLObjectSet to an RDF graph
2340
+ """
2341
+ e = RDFEncoder(g)
2342
+ objset.encode(e)
2343
+
2344
+ except ImportError:
2345
+ pass
2346
+
2347
+
2348
+ def print_tree(objects, all_fields: bool = False) -> None:
1950
2349
  """
1951
2350
  Print object tree
1952
2351
  """
1953
2352
  seen = set()
1954
2353
 
1955
- def callback(value, path):
2354
+ def callback(value, path: List[str]):
1956
2355
  nonlocal seen
1957
2356
 
1958
2357
  s = (" " * (len(path) - 1)) + f"{path[-1]}"
@@ -1986,7 +2385,7 @@ def print_tree(objects, all_fields=False):
1986
2385
  """Format Guard"""
1987
2386
 
1988
2387
 
1989
- CONTEXT_URLS = [
2388
+ CONTEXT_URLS: List[str] = [
1990
2389
  "https://spdx.org/rdf/3.0.1/spdx-context.jsonld",
1991
2390
  ]
1992
2391
 
@@ -1998,7 +2397,7 @@ CONTEXT_URLS = [
1998
2397
  class ai_EnergyConsumption(SHACLObject):
1999
2398
  NODE_KIND = NodeKind.BlankNodeOrIRI
2000
2399
  IS_DEPRECATED = False
2001
- NAMED_INDIVIDUALS = {
2400
+ NAMED_INDIVIDUALS: Dict[str, str] = {
2002
2401
  }
2003
2402
 
2004
2403
  @classmethod
@@ -2039,7 +2438,7 @@ class ai_EnergyConsumption(SHACLObject):
2039
2438
  class ai_EnergyConsumptionDescription(SHACLObject):
2040
2439
  NODE_KIND = NodeKind.BlankNodeOrIRI
2041
2440
  IS_DEPRECATED = False
2042
- NAMED_INDIVIDUALS = {
2441
+ NAMED_INDIVIDUALS: Dict[str, str] = {
2043
2442
  }
2044
2443
 
2045
2444
  @classmethod
@@ -2074,7 +2473,7 @@ class ai_EnergyConsumptionDescription(SHACLObject):
2074
2473
  class ai_EnergyUnitType(SHACLObject):
2075
2474
  NODE_KIND = NodeKind.BlankNodeOrIRI
2076
2475
  IS_DEPRECATED = False
2077
- NAMED_INDIVIDUALS = {
2476
+ NAMED_INDIVIDUALS: Dict[str, str] = {
2078
2477
  "kilowattHour": "https://spdx.org/rdf/3.0.1/terms/AI/EnergyUnitType/kilowattHour",
2079
2478
  "megajoule": "https://spdx.org/rdf/3.0.1/terms/AI/EnergyUnitType/megajoule",
2080
2479
  "other": "https://spdx.org/rdf/3.0.1/terms/AI/EnergyUnitType/other",
@@ -2092,7 +2491,7 @@ class ai_EnergyUnitType(SHACLObject):
2092
2491
  class ai_SafetyRiskAssessmentType(SHACLObject):
2093
2492
  NODE_KIND = NodeKind.BlankNodeOrIRI
2094
2493
  IS_DEPRECATED = False
2095
- NAMED_INDIVIDUALS = {
2494
+ NAMED_INDIVIDUALS: Dict[str, str] = {
2096
2495
  "high": "https://spdx.org/rdf/3.0.1/terms/AI/SafetyRiskAssessmentType/high",
2097
2496
  "low": "https://spdx.org/rdf/3.0.1/terms/AI/SafetyRiskAssessmentType/low",
2098
2497
  "medium": "https://spdx.org/rdf/3.0.1/terms/AI/SafetyRiskAssessmentType/medium",
@@ -2113,7 +2512,7 @@ class ai_SafetyRiskAssessmentType(SHACLObject):
2113
2512
  class AnnotationType(SHACLObject):
2114
2513
  NODE_KIND = NodeKind.BlankNodeOrIRI
2115
2514
  IS_DEPRECATED = False
2116
- NAMED_INDIVIDUALS = {
2515
+ NAMED_INDIVIDUALS: Dict[str, str] = {
2117
2516
  "other": "https://spdx.org/rdf/3.0.1/terms/Core/AnnotationType/other",
2118
2517
  "review": "https://spdx.org/rdf/3.0.1/terms/Core/AnnotationType/review",
2119
2518
  }
@@ -2128,7 +2527,7 @@ class AnnotationType(SHACLObject):
2128
2527
  class CreationInfo(SHACLObject):
2129
2528
  NODE_KIND = NodeKind.BlankNodeOrIRI
2130
2529
  IS_DEPRECATED = False
2131
- NAMED_INDIVIDUALS = {
2530
+ NAMED_INDIVIDUALS: Dict[str, str] = {
2132
2531
  }
2133
2532
 
2134
2533
  @classmethod
@@ -2188,7 +2587,7 @@ class CreationInfo(SHACLObject):
2188
2587
  class DictionaryEntry(SHACLObject):
2189
2588
  NODE_KIND = NodeKind.BlankNodeOrIRI
2190
2589
  IS_DEPRECATED = False
2191
- NAMED_INDIVIDUALS = {
2590
+ NAMED_INDIVIDUALS: Dict[str, str] = {
2192
2591
  }
2193
2592
 
2194
2593
  @classmethod
@@ -2219,7 +2618,7 @@ class Element(SHACLObject):
2219
2618
  NODE_KIND = NodeKind.IRI
2220
2619
  ID_ALIAS = "spdxId"
2221
2620
  IS_DEPRECATED = False
2222
- NAMED_INDIVIDUALS = {
2621
+ NAMED_INDIVIDUALS: Dict[str, str] = {
2223
2622
  }
2224
2623
 
2225
2624
  @classmethod
@@ -2310,7 +2709,7 @@ class ElementCollection(Element):
2310
2709
  NODE_KIND = NodeKind.IRI
2311
2710
  ID_ALIAS = "spdxId"
2312
2711
  IS_DEPRECATED = False
2313
- NAMED_INDIVIDUALS = {
2712
+ NAMED_INDIVIDUALS: Dict[str, str] = {
2314
2713
  }
2315
2714
 
2316
2715
  @classmethod
@@ -2371,7 +2770,7 @@ class ElementCollection(Element):
2371
2770
  class ExternalIdentifier(SHACLObject):
2372
2771
  NODE_KIND = NodeKind.BlankNodeOrIRI
2373
2772
  IS_DEPRECATED = False
2374
- NAMED_INDIVIDUALS = {
2773
+ NAMED_INDIVIDUALS: Dict[str, str] = {
2375
2774
  }
2376
2775
 
2377
2776
  @classmethod
@@ -2439,7 +2838,7 @@ class ExternalIdentifier(SHACLObject):
2439
2838
  class ExternalIdentifierType(SHACLObject):
2440
2839
  NODE_KIND = NodeKind.BlankNodeOrIRI
2441
2840
  IS_DEPRECATED = False
2442
- NAMED_INDIVIDUALS = {
2841
+ NAMED_INDIVIDUALS: Dict[str, str] = {
2443
2842
  "cpe22": "https://spdx.org/rdf/3.0.1/terms/Core/ExternalIdentifierType/cpe22",
2444
2843
  "cpe23": "https://spdx.org/rdf/3.0.1/terms/Core/ExternalIdentifierType/cpe23",
2445
2844
  "cve": "https://spdx.org/rdf/3.0.1/terms/Core/ExternalIdentifierType/cve",
@@ -2482,7 +2881,7 @@ class ExternalIdentifierType(SHACLObject):
2482
2881
  class ExternalMap(SHACLObject):
2483
2882
  NODE_KIND = NodeKind.BlankNodeOrIRI
2484
2883
  IS_DEPRECATED = False
2485
- NAMED_INDIVIDUALS = {
2884
+ NAMED_INDIVIDUALS: Dict[str, str] = {
2486
2885
  }
2487
2886
 
2488
2887
  @classmethod
@@ -2531,7 +2930,7 @@ class ExternalMap(SHACLObject):
2531
2930
  class ExternalRef(SHACLObject):
2532
2931
  NODE_KIND = NodeKind.BlankNodeOrIRI
2533
2932
  IS_DEPRECATED = False
2534
- NAMED_INDIVIDUALS = {
2933
+ NAMED_INDIVIDUALS: Dict[str, str] = {
2535
2934
  }
2536
2935
 
2537
2936
  @classmethod
@@ -2624,7 +3023,7 @@ class ExternalRef(SHACLObject):
2624
3023
  class ExternalRefType(SHACLObject):
2625
3024
  NODE_KIND = NodeKind.BlankNodeOrIRI
2626
3025
  IS_DEPRECATED = False
2627
- NAMED_INDIVIDUALS = {
3026
+ NAMED_INDIVIDUALS: Dict[str, str] = {
2628
3027
  "altDownloadLocation": "https://spdx.org/rdf/3.0.1/terms/Core/ExternalRefType/altDownloadLocation",
2629
3028
  "altWebPage": "https://spdx.org/rdf/3.0.1/terms/Core/ExternalRefType/altWebPage",
2630
3029
  "binaryArtifact": "https://spdx.org/rdf/3.0.1/terms/Core/ExternalRefType/binaryArtifact",
@@ -2771,7 +3170,7 @@ class ExternalRefType(SHACLObject):
2771
3170
  class HashAlgorithm(SHACLObject):
2772
3171
  NODE_KIND = NodeKind.BlankNodeOrIRI
2773
3172
  IS_DEPRECATED = False
2774
- NAMED_INDIVIDUALS = {
3173
+ NAMED_INDIVIDUALS: Dict[str, str] = {
2775
3174
  "adler32": "https://spdx.org/rdf/3.0.1/terms/Core/HashAlgorithm/adler32",
2776
3175
  "blake2b256": "https://spdx.org/rdf/3.0.1/terms/Core/HashAlgorithm/blake2b256",
2777
3176
  "blake2b384": "https://spdx.org/rdf/3.0.1/terms/Core/HashAlgorithm/blake2b384",
@@ -2848,7 +3247,7 @@ class IndividualElement(Element):
2848
3247
  NODE_KIND = NodeKind.IRI
2849
3248
  ID_ALIAS = "spdxId"
2850
3249
  IS_DEPRECATED = False
2851
- NAMED_INDIVIDUALS = {
3250
+ NAMED_INDIVIDUALS: Dict[str, str] = {
2852
3251
  "NoAssertionElement": "https://spdx.org/rdf/3.0.1/terms/Core/NoAssertionElement",
2853
3252
  "NoneElement": "https://spdx.org/rdf/3.0.1/terms/Core/NoneElement",
2854
3253
  }
@@ -2865,7 +3264,7 @@ class IndividualElement(Element):
2865
3264
  class IntegrityMethod(SHACLObject):
2866
3265
  NODE_KIND = NodeKind.BlankNodeOrIRI
2867
3266
  IS_DEPRECATED = False
2868
- NAMED_INDIVIDUALS = {
3267
+ NAMED_INDIVIDUALS: Dict[str, str] = {
2869
3268
  }
2870
3269
 
2871
3270
  @classmethod
@@ -2887,7 +3286,7 @@ class IntegrityMethod(SHACLObject):
2887
3286
  class LifecycleScopeType(SHACLObject):
2888
3287
  NODE_KIND = NodeKind.BlankNodeOrIRI
2889
3288
  IS_DEPRECATED = False
2890
- NAMED_INDIVIDUALS = {
3289
+ NAMED_INDIVIDUALS: Dict[str, str] = {
2891
3290
  "build": "https://spdx.org/rdf/3.0.1/terms/Core/LifecycleScopeType/build",
2892
3291
  "design": "https://spdx.org/rdf/3.0.1/terms/Core/LifecycleScopeType/design",
2893
3292
  "development": "https://spdx.org/rdf/3.0.1/terms/Core/LifecycleScopeType/development",
@@ -2914,7 +3313,7 @@ class LifecycleScopeType(SHACLObject):
2914
3313
  class NamespaceMap(SHACLObject):
2915
3314
  NODE_KIND = NodeKind.BlankNodeOrIRI
2916
3315
  IS_DEPRECATED = False
2917
- NAMED_INDIVIDUALS = {
3316
+ NAMED_INDIVIDUALS: Dict[str, str] = {
2918
3317
  }
2919
3318
 
2920
3319
  @classmethod
@@ -2946,7 +3345,7 @@ class NamespaceMap(SHACLObject):
2946
3345
  class PackageVerificationCode(IntegrityMethod):
2947
3346
  NODE_KIND = NodeKind.BlankNodeOrIRI
2948
3347
  IS_DEPRECATED = False
2949
- NAMED_INDIVIDUALS = {
3348
+ NAMED_INDIVIDUALS: Dict[str, str] = {
2950
3349
  }
2951
3350
 
2952
3351
  @classmethod
@@ -3009,7 +3408,7 @@ class PackageVerificationCode(IntegrityMethod):
3009
3408
  class PositiveIntegerRange(SHACLObject):
3010
3409
  NODE_KIND = NodeKind.BlankNodeOrIRI
3011
3410
  IS_DEPRECATED = False
3012
- NAMED_INDIVIDUALS = {
3411
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3013
3412
  }
3014
3413
 
3015
3414
  @classmethod
@@ -3040,7 +3439,7 @@ class PositiveIntegerRange(SHACLObject):
3040
3439
  class PresenceType(SHACLObject):
3041
3440
  NODE_KIND = NodeKind.BlankNodeOrIRI
3042
3441
  IS_DEPRECATED = False
3043
- NAMED_INDIVIDUALS = {
3442
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3044
3443
  "no": "https://spdx.org/rdf/3.0.1/terms/Core/PresenceType/no",
3045
3444
  "noAssertion": "https://spdx.org/rdf/3.0.1/terms/Core/PresenceType/noAssertion",
3046
3445
  "yes": "https://spdx.org/rdf/3.0.1/terms/Core/PresenceType/yes",
@@ -3058,7 +3457,7 @@ class PresenceType(SHACLObject):
3058
3457
  class ProfileIdentifierType(SHACLObject):
3059
3458
  NODE_KIND = NodeKind.BlankNodeOrIRI
3060
3459
  IS_DEPRECATED = False
3061
- NAMED_INDIVIDUALS = {
3460
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3062
3461
  "ai": "https://spdx.org/rdf/3.0.1/terms/Core/ProfileIdentifierType/ai",
3063
3462
  "build": "https://spdx.org/rdf/3.0.1/terms/Core/ProfileIdentifierType/build",
3064
3463
  "core": "https://spdx.org/rdf/3.0.1/terms/Core/ProfileIdentifierType/core",
@@ -3098,7 +3497,7 @@ class Relationship(Element):
3098
3497
  NODE_KIND = NodeKind.IRI
3099
3498
  ID_ALIAS = "spdxId"
3100
3499
  IS_DEPRECATED = False
3101
- NAMED_INDIVIDUALS = {
3500
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3102
3501
  }
3103
3502
 
3104
3503
  @classmethod
@@ -3238,7 +3637,7 @@ class Relationship(Element):
3238
3637
  class RelationshipCompleteness(SHACLObject):
3239
3638
  NODE_KIND = NodeKind.BlankNodeOrIRI
3240
3639
  IS_DEPRECATED = False
3241
- NAMED_INDIVIDUALS = {
3640
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3242
3641
  "complete": "https://spdx.org/rdf/3.0.1/terms/Core/RelationshipCompleteness/complete",
3243
3642
  "incomplete": "https://spdx.org/rdf/3.0.1/terms/Core/RelationshipCompleteness/incomplete",
3244
3643
  "noAssertion": "https://spdx.org/rdf/3.0.1/terms/Core/RelationshipCompleteness/noAssertion",
@@ -3256,7 +3655,7 @@ class RelationshipCompleteness(SHACLObject):
3256
3655
  class RelationshipType(SHACLObject):
3257
3656
  NODE_KIND = NodeKind.BlankNodeOrIRI
3258
3657
  IS_DEPRECATED = False
3259
- NAMED_INDIVIDUALS = {
3658
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3260
3659
  "affects": "https://spdx.org/rdf/3.0.1/terms/Core/RelationshipType/affects",
3261
3660
  "amendedBy": "https://spdx.org/rdf/3.0.1/terms/Core/RelationshipType/amendedBy",
3262
3661
  "ancestorOf": "https://spdx.org/rdf/3.0.1/terms/Core/RelationshipType/ancestorOf",
@@ -3443,7 +3842,7 @@ class SpdxDocument(ElementCollection):
3443
3842
  NODE_KIND = NodeKind.IRI
3444
3843
  ID_ALIAS = "spdxId"
3445
3844
  IS_DEPRECATED = False
3446
- NAMED_INDIVIDUALS = {
3845
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3447
3846
  }
3448
3847
 
3449
3848
  @classmethod
@@ -3484,7 +3883,7 @@ class SpdxDocument(ElementCollection):
3484
3883
  class SupportType(SHACLObject):
3485
3884
  NODE_KIND = NodeKind.BlankNodeOrIRI
3486
3885
  IS_DEPRECATED = False
3487
- NAMED_INDIVIDUALS = {
3886
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3488
3887
  "deployed": "https://spdx.org/rdf/3.0.1/terms/Core/SupportType/deployed",
3489
3888
  "development": "https://spdx.org/rdf/3.0.1/terms/Core/SupportType/development",
3490
3889
  "endOfSupport": "https://spdx.org/rdf/3.0.1/terms/Core/SupportType/endOfSupport",
@@ -3515,7 +3914,7 @@ class Tool(Element):
3515
3914
  NODE_KIND = NodeKind.IRI
3516
3915
  ID_ALIAS = "spdxId"
3517
3916
  IS_DEPRECATED = False
3518
- NAMED_INDIVIDUALS = {
3917
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3519
3918
  }
3520
3919
 
3521
3920
 
@@ -3524,7 +3923,7 @@ class Tool(Element):
3524
3923
  class dataset_ConfidentialityLevelType(SHACLObject):
3525
3924
  NODE_KIND = NodeKind.BlankNodeOrIRI
3526
3925
  IS_DEPRECATED = False
3527
- NAMED_INDIVIDUALS = {
3926
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3528
3927
  "amber": "https://spdx.org/rdf/3.0.1/terms/Dataset/ConfidentialityLevelType/amber",
3529
3928
  "clear": "https://spdx.org/rdf/3.0.1/terms/Dataset/ConfidentialityLevelType/clear",
3530
3929
  "green": "https://spdx.org/rdf/3.0.1/terms/Dataset/ConfidentialityLevelType/green",
@@ -3545,7 +3944,7 @@ class dataset_ConfidentialityLevelType(SHACLObject):
3545
3944
  class dataset_DatasetAvailabilityType(SHACLObject):
3546
3945
  NODE_KIND = NodeKind.BlankNodeOrIRI
3547
3946
  IS_DEPRECATED = False
3548
- NAMED_INDIVIDUALS = {
3947
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3549
3948
  "clickthrough": "https://spdx.org/rdf/3.0.1/terms/Dataset/DatasetAvailabilityType/clickthrough",
3550
3949
  "directDownload": "https://spdx.org/rdf/3.0.1/terms/Dataset/DatasetAvailabilityType/directDownload",
3551
3950
  "query": "https://spdx.org/rdf/3.0.1/terms/Dataset/DatasetAvailabilityType/query",
@@ -3569,7 +3968,7 @@ class dataset_DatasetAvailabilityType(SHACLObject):
3569
3968
  class dataset_DatasetType(SHACLObject):
3570
3969
  NODE_KIND = NodeKind.BlankNodeOrIRI
3571
3970
  IS_DEPRECATED = False
3572
- NAMED_INDIVIDUALS = {
3971
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3573
3972
  "audio": "https://spdx.org/rdf/3.0.1/terms/Dataset/DatasetType/audio",
3574
3973
  "categorical": "https://spdx.org/rdf/3.0.1/terms/Dataset/DatasetType/categorical",
3575
3974
  "graph": "https://spdx.org/rdf/3.0.1/terms/Dataset/DatasetType/graph",
@@ -3622,7 +4021,7 @@ class expandedlicensing_LicenseAddition(Element):
3622
4021
  NODE_KIND = NodeKind.IRI
3623
4022
  ID_ALIAS = "spdxId"
3624
4023
  IS_DEPRECATED = False
3625
- NAMED_INDIVIDUALS = {
4024
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3626
4025
  }
3627
4026
 
3628
4027
  @classmethod
@@ -3687,7 +4086,7 @@ class expandedlicensing_ListedLicenseException(expandedlicensing_LicenseAddition
3687
4086
  NODE_KIND = NodeKind.IRI
3688
4087
  ID_ALIAS = "spdxId"
3689
4088
  IS_DEPRECATED = False
3690
- NAMED_INDIVIDUALS = {
4089
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3691
4090
  }
3692
4091
 
3693
4092
  @classmethod
@@ -3718,7 +4117,7 @@ class expandedlicensing_ListedLicenseException(expandedlicensing_LicenseAddition
3718
4117
  class extension_CdxPropertyEntry(SHACLObject):
3719
4118
  NODE_KIND = NodeKind.BlankNodeOrIRI
3720
4119
  IS_DEPRECATED = False
3721
- NAMED_INDIVIDUALS = {
4120
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3722
4121
  }
3723
4122
 
3724
4123
  @classmethod
@@ -3748,7 +4147,7 @@ class extension_CdxPropertyEntry(SHACLObject):
3748
4147
  class extension_Extension(SHACLExtensibleObject, SHACLObject):
3749
4148
  NODE_KIND = NodeKind.BlankNodeOrIRI
3750
4149
  IS_DEPRECATED = False
3751
- NAMED_INDIVIDUALS = {
4150
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3752
4151
  }
3753
4152
 
3754
4153
 
@@ -3757,7 +4156,7 @@ class extension_Extension(SHACLExtensibleObject, SHACLObject):
3757
4156
  class security_CvssSeverityType(SHACLObject):
3758
4157
  NODE_KIND = NodeKind.BlankNodeOrIRI
3759
4158
  IS_DEPRECATED = False
3760
- NAMED_INDIVIDUALS = {
4159
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3761
4160
  "critical": "https://spdx.org/rdf/3.0.1/terms/Security/CvssSeverityType/critical",
3762
4161
  "high": "https://spdx.org/rdf/3.0.1/terms/Security/CvssSeverityType/high",
3763
4162
  "low": "https://spdx.org/rdf/3.0.1/terms/Security/CvssSeverityType/low",
@@ -3781,7 +4180,7 @@ class security_CvssSeverityType(SHACLObject):
3781
4180
  class security_ExploitCatalogType(SHACLObject):
3782
4181
  NODE_KIND = NodeKind.BlankNodeOrIRI
3783
4182
  IS_DEPRECATED = False
3784
- NAMED_INDIVIDUALS = {
4183
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3785
4184
  "kev": "https://spdx.org/rdf/3.0.1/terms/Security/ExploitCatalogType/kev",
3786
4185
  "other": "https://spdx.org/rdf/3.0.1/terms/Security/ExploitCatalogType/other",
3787
4186
  }
@@ -3796,7 +4195,7 @@ class security_ExploitCatalogType(SHACLObject):
3796
4195
  class security_SsvcDecisionType(SHACLObject):
3797
4196
  NODE_KIND = NodeKind.BlankNodeOrIRI
3798
4197
  IS_DEPRECATED = False
3799
- NAMED_INDIVIDUALS = {
4198
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3800
4199
  "act": "https://spdx.org/rdf/3.0.1/terms/Security/SsvcDecisionType/act",
3801
4200
  "attend": "https://spdx.org/rdf/3.0.1/terms/Security/SsvcDecisionType/attend",
3802
4201
  "track": "https://spdx.org/rdf/3.0.1/terms/Security/SsvcDecisionType/track",
@@ -3817,7 +4216,7 @@ class security_SsvcDecisionType(SHACLObject):
3817
4216
  class security_VexJustificationType(SHACLObject):
3818
4217
  NODE_KIND = NodeKind.BlankNodeOrIRI
3819
4218
  IS_DEPRECATED = False
3820
- NAMED_INDIVIDUALS = {
4219
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3821
4220
  "componentNotPresent": "https://spdx.org/rdf/3.0.1/terms/Security/VexJustificationType/componentNotPresent",
3822
4221
  "inlineMitigationsAlreadyExist": "https://spdx.org/rdf/3.0.1/terms/Security/VexJustificationType/inlineMitigationsAlreadyExist",
3823
4222
  "vulnerableCodeCannotBeControlledByAdversary": "https://spdx.org/rdf/3.0.1/terms/Security/VexJustificationType/vulnerableCodeCannotBeControlledByAdversary",
@@ -3842,7 +4241,7 @@ class security_VulnAssessmentRelationship(Relationship):
3842
4241
  NODE_KIND = NodeKind.IRI
3843
4242
  ID_ALIAS = "spdxId"
3844
4243
  IS_DEPRECATED = False
3845
- NAMED_INDIVIDUALS = {
4244
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3846
4245
  }
3847
4246
 
3848
4247
  @classmethod
@@ -3900,7 +4299,7 @@ class simplelicensing_AnyLicenseInfo(Element):
3900
4299
  NODE_KIND = NodeKind.IRI
3901
4300
  ID_ALIAS = "spdxId"
3902
4301
  IS_DEPRECATED = False
3903
- NAMED_INDIVIDUALS = {
4302
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3904
4303
  }
3905
4304
 
3906
4305
 
@@ -3910,7 +4309,7 @@ class simplelicensing_LicenseExpression(simplelicensing_AnyLicenseInfo):
3910
4309
  NODE_KIND = NodeKind.IRI
3911
4310
  ID_ALIAS = "spdxId"
3912
4311
  IS_DEPRECATED = False
3913
- NAMED_INDIVIDUALS = {
4312
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3914
4313
  }
3915
4314
 
3916
4315
  @classmethod
@@ -3950,7 +4349,7 @@ class simplelicensing_SimpleLicensingText(Element):
3950
4349
  NODE_KIND = NodeKind.IRI
3951
4350
  ID_ALIAS = "spdxId"
3952
4351
  IS_DEPRECATED = False
3953
- NAMED_INDIVIDUALS = {
4352
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3954
4353
  }
3955
4354
 
3956
4355
  @classmethod
@@ -3972,7 +4371,7 @@ class simplelicensing_SimpleLicensingText(Element):
3972
4371
  class software_ContentIdentifier(IntegrityMethod):
3973
4372
  NODE_KIND = NodeKind.BlankNodeOrIRI
3974
4373
  IS_DEPRECATED = False
3975
- NAMED_INDIVIDUALS = {
4374
+ NAMED_INDIVIDUALS: Dict[str, str] = {
3976
4375
  }
3977
4376
 
3978
4377
  @classmethod
@@ -4006,7 +4405,7 @@ class software_ContentIdentifier(IntegrityMethod):
4006
4405
  class software_ContentIdentifierType(SHACLObject):
4007
4406
  NODE_KIND = NodeKind.BlankNodeOrIRI
4008
4407
  IS_DEPRECATED = False
4009
- NAMED_INDIVIDUALS = {
4408
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4010
4409
  "gitoid": "https://spdx.org/rdf/3.0.1/terms/Software/ContentIdentifierType/gitoid",
4011
4410
  "swhid": "https://spdx.org/rdf/3.0.1/terms/Software/ContentIdentifierType/swhid",
4012
4411
  }
@@ -4021,7 +4420,7 @@ class software_ContentIdentifierType(SHACLObject):
4021
4420
  class software_FileKindType(SHACLObject):
4022
4421
  NODE_KIND = NodeKind.BlankNodeOrIRI
4023
4422
  IS_DEPRECATED = False
4024
- NAMED_INDIVIDUALS = {
4423
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4025
4424
  "directory": "https://spdx.org/rdf/3.0.1/terms/Software/FileKindType/directory",
4026
4425
  "file": "https://spdx.org/rdf/3.0.1/terms/Software/FileKindType/file",
4027
4426
  }
@@ -4037,7 +4436,7 @@ class software_FileKindType(SHACLObject):
4037
4436
  class software_SbomType(SHACLObject):
4038
4437
  NODE_KIND = NodeKind.BlankNodeOrIRI
4039
4438
  IS_DEPRECATED = False
4040
- NAMED_INDIVIDUALS = {
4439
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4041
4440
  "analyzed": "https://spdx.org/rdf/3.0.1/terms/Software/SbomType/analyzed",
4042
4441
  "build": "https://spdx.org/rdf/3.0.1/terms/Software/SbomType/build",
4043
4442
  "deployed": "https://spdx.org/rdf/3.0.1/terms/Software/SbomType/deployed",
@@ -4064,7 +4463,7 @@ class software_SbomType(SHACLObject):
4064
4463
  class software_SoftwarePurpose(SHACLObject):
4065
4464
  NODE_KIND = NodeKind.BlankNodeOrIRI
4066
4465
  IS_DEPRECATED = False
4067
- NAMED_INDIVIDUALS = {
4466
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4068
4467
  "application": "https://spdx.org/rdf/3.0.1/terms/Software/SoftwarePurpose/application",
4069
4468
  "archive": "https://spdx.org/rdf/3.0.1/terms/Software/SoftwarePurpose/archive",
4070
4469
  "bom": "https://spdx.org/rdf/3.0.1/terms/Software/SoftwarePurpose/bom",
@@ -4161,7 +4560,7 @@ class build_Build(Element):
4161
4560
  NODE_KIND = NodeKind.IRI
4162
4561
  ID_ALIAS = "spdxId"
4163
4562
  IS_DEPRECATED = False
4164
- NAMED_INDIVIDUALS = {
4563
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4165
4564
  }
4166
4565
 
4167
4566
  @classmethod
@@ -4251,7 +4650,7 @@ class Agent(Element):
4251
4650
  NODE_KIND = NodeKind.IRI
4252
4651
  ID_ALIAS = "spdxId"
4253
4652
  IS_DEPRECATED = False
4254
- NAMED_INDIVIDUALS = {
4653
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4255
4654
  }
4256
4655
 
4257
4656
 
@@ -4261,7 +4660,7 @@ class Annotation(Element):
4261
4660
  NODE_KIND = NodeKind.IRI
4262
4661
  ID_ALIAS = "spdxId"
4263
4662
  IS_DEPRECATED = False
4264
- NAMED_INDIVIDUALS = {
4663
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4265
4664
  }
4266
4665
 
4267
4666
  @classmethod
@@ -4318,7 +4717,7 @@ class Artifact(Element):
4318
4717
  NODE_KIND = NodeKind.IRI
4319
4718
  ID_ALIAS = "spdxId"
4320
4719
  IS_DEPRECATED = False
4321
- NAMED_INDIVIDUALS = {
4720
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4322
4721
  }
4323
4722
 
4324
4723
  @classmethod
@@ -4402,7 +4801,7 @@ class Bundle(ElementCollection):
4402
4801
  NODE_KIND = NodeKind.IRI
4403
4802
  ID_ALIAS = "spdxId"
4404
4803
  IS_DEPRECATED = False
4405
- NAMED_INDIVIDUALS = {
4804
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4406
4805
  }
4407
4806
 
4408
4807
  @classmethod
@@ -4424,7 +4823,7 @@ class Bundle(ElementCollection):
4424
4823
  class Hash(IntegrityMethod):
4425
4824
  NODE_KIND = NodeKind.BlankNodeOrIRI
4426
4825
  IS_DEPRECATED = False
4427
- NAMED_INDIVIDUALS = {
4826
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4428
4827
  }
4429
4828
 
4430
4829
  @classmethod
@@ -4479,7 +4878,7 @@ class LifecycleScopedRelationship(Relationship):
4479
4878
  NODE_KIND = NodeKind.IRI
4480
4879
  ID_ALIAS = "spdxId"
4481
4880
  IS_DEPRECATED = False
4482
- NAMED_INDIVIDUALS = {
4881
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4483
4882
  }
4484
4883
 
4485
4884
  @classmethod
@@ -4508,7 +4907,7 @@ class Organization(Agent):
4508
4907
  NODE_KIND = NodeKind.IRI
4509
4908
  ID_ALIAS = "spdxId"
4510
4909
  IS_DEPRECATED = False
4511
- NAMED_INDIVIDUALS = {
4910
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4512
4911
  "SpdxOrganization": "https://spdx.org/rdf/3.0.1/terms/Core/SpdxOrganization",
4513
4912
  }
4514
4913
  # An Organization representing the SPDX Project.
@@ -4521,7 +4920,7 @@ class Person(Agent):
4521
4920
  NODE_KIND = NodeKind.IRI
4522
4921
  ID_ALIAS = "spdxId"
4523
4922
  IS_DEPRECATED = False
4524
- NAMED_INDIVIDUALS = {
4923
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4525
4924
  }
4526
4925
 
4527
4926
 
@@ -4531,7 +4930,7 @@ class SoftwareAgent(Agent):
4531
4930
  NODE_KIND = NodeKind.IRI
4532
4931
  ID_ALIAS = "spdxId"
4533
4932
  IS_DEPRECATED = False
4534
- NAMED_INDIVIDUALS = {
4933
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4535
4934
  }
4536
4935
 
4537
4936
 
@@ -4542,7 +4941,7 @@ class expandedlicensing_ConjunctiveLicenseSet(simplelicensing_AnyLicenseInfo):
4542
4941
  NODE_KIND = NodeKind.IRI
4543
4942
  ID_ALIAS = "spdxId"
4544
4943
  IS_DEPRECATED = False
4545
- NAMED_INDIVIDUALS = {
4944
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4546
4945
  }
4547
4946
 
4548
4947
  @classmethod
@@ -4568,7 +4967,7 @@ class expandedlicensing_CustomLicenseAddition(expandedlicensing_LicenseAddition)
4568
4967
  NODE_KIND = NodeKind.IRI
4569
4968
  ID_ALIAS = "spdxId"
4570
4969
  IS_DEPRECATED = False
4571
- NAMED_INDIVIDUALS = {
4970
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4572
4971
  }
4573
4972
 
4574
4973
 
@@ -4579,7 +4978,7 @@ class expandedlicensing_DisjunctiveLicenseSet(simplelicensing_AnyLicenseInfo):
4579
4978
  NODE_KIND = NodeKind.IRI
4580
4979
  ID_ALIAS = "spdxId"
4581
4980
  IS_DEPRECATED = False
4582
- NAMED_INDIVIDUALS = {
4981
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4583
4982
  }
4584
4983
 
4585
4984
  @classmethod
@@ -4605,7 +5004,7 @@ class expandedlicensing_ExtendableLicense(simplelicensing_AnyLicenseInfo):
4605
5004
  NODE_KIND = NodeKind.IRI
4606
5005
  ID_ALIAS = "spdxId"
4607
5006
  IS_DEPRECATED = False
4608
- NAMED_INDIVIDUALS = {
5007
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4609
5008
  }
4610
5009
 
4611
5010
 
@@ -4616,7 +5015,7 @@ class expandedlicensing_IndividualLicensingInfo(simplelicensing_AnyLicenseInfo):
4616
5015
  NODE_KIND = NodeKind.IRI
4617
5016
  ID_ALIAS = "spdxId"
4618
5017
  IS_DEPRECATED = False
4619
- NAMED_INDIVIDUALS = {
5018
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4620
5019
  "NoAssertionLicense": "https://spdx.org/rdf/3.0.1/terms/ExpandedLicensing/NoAssertionLicense",
4621
5020
  "NoneLicense": "https://spdx.org/rdf/3.0.1/terms/ExpandedLicensing/NoneLicense",
4622
5021
  }
@@ -4634,7 +5033,7 @@ class expandedlicensing_License(expandedlicensing_ExtendableLicense):
4634
5033
  NODE_KIND = NodeKind.IRI
4635
5034
  ID_ALIAS = "spdxId"
4636
5035
  IS_DEPRECATED = False
4637
- NAMED_INDIVIDUALS = {
5036
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4638
5037
  }
4639
5038
 
4640
5039
  @classmethod
@@ -4727,7 +5126,7 @@ class expandedlicensing_ListedLicense(expandedlicensing_License):
4727
5126
  NODE_KIND = NodeKind.IRI
4728
5127
  ID_ALIAS = "spdxId"
4729
5128
  IS_DEPRECATED = False
4730
- NAMED_INDIVIDUALS = {
5129
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4731
5130
  }
4732
5131
 
4733
5132
  @classmethod
@@ -4760,7 +5159,7 @@ class expandedlicensing_OrLaterOperator(expandedlicensing_ExtendableLicense):
4760
5159
  NODE_KIND = NodeKind.IRI
4761
5160
  ID_ALIAS = "spdxId"
4762
5161
  IS_DEPRECATED = False
4763
- NAMED_INDIVIDUALS = {
5162
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4764
5163
  }
4765
5164
 
4766
5165
  @classmethod
@@ -4784,7 +5183,7 @@ class expandedlicensing_WithAdditionOperator(simplelicensing_AnyLicenseInfo):
4784
5183
  NODE_KIND = NodeKind.IRI
4785
5184
  ID_ALIAS = "spdxId"
4786
5185
  IS_DEPRECATED = False
4787
- NAMED_INDIVIDUALS = {
5186
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4788
5187
  }
4789
5188
 
4790
5189
  @classmethod
@@ -4815,7 +5214,7 @@ class expandedlicensing_WithAdditionOperator(simplelicensing_AnyLicenseInfo):
4815
5214
  class extension_CdxPropertiesExtension(extension_Extension):
4816
5215
  NODE_KIND = NodeKind.BlankNodeOrIRI
4817
5216
  IS_DEPRECATED = False
4818
- NAMED_INDIVIDUALS = {
5217
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4819
5218
  }
4820
5219
 
4821
5220
  @classmethod
@@ -4838,7 +5237,7 @@ class security_CvssV2VulnAssessmentRelationship(security_VulnAssessmentRelations
4838
5237
  NODE_KIND = NodeKind.IRI
4839
5238
  ID_ALIAS = "spdxId"
4840
5239
  IS_DEPRECATED = False
4841
- NAMED_INDIVIDUALS = {
5240
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4842
5241
  }
4843
5242
 
4844
5243
  @classmethod
@@ -4870,7 +5269,7 @@ class security_CvssV3VulnAssessmentRelationship(security_VulnAssessmentRelations
4870
5269
  NODE_KIND = NodeKind.IRI
4871
5270
  ID_ALIAS = "spdxId"
4872
5271
  IS_DEPRECATED = False
4873
- NAMED_INDIVIDUALS = {
5272
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4874
5273
  }
4875
5274
 
4876
5275
  @classmethod
@@ -4917,7 +5316,7 @@ class security_CvssV4VulnAssessmentRelationship(security_VulnAssessmentRelations
4917
5316
  NODE_KIND = NodeKind.IRI
4918
5317
  ID_ALIAS = "spdxId"
4919
5318
  IS_DEPRECATED = False
4920
- NAMED_INDIVIDUALS = {
5319
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4921
5320
  }
4922
5321
 
4923
5322
  @classmethod
@@ -4964,7 +5363,7 @@ class security_EpssVulnAssessmentRelationship(security_VulnAssessmentRelationshi
4964
5363
  NODE_KIND = NodeKind.IRI
4965
5364
  ID_ALIAS = "spdxId"
4966
5365
  IS_DEPRECATED = False
4967
- NAMED_INDIVIDUALS = {
5366
+ NAMED_INDIVIDUALS: Dict[str, str] = {
4968
5367
  }
4969
5368
 
4970
5369
  @classmethod
@@ -4996,7 +5395,7 @@ class security_ExploitCatalogVulnAssessmentRelationship(security_VulnAssessmentR
4996
5395
  NODE_KIND = NodeKind.IRI
4997
5396
  ID_ALIAS = "spdxId"
4998
5397
  IS_DEPRECATED = False
4999
- NAMED_INDIVIDUALS = {
5398
+ NAMED_INDIVIDUALS: Dict[str, str] = {
5000
5399
  }
5001
5400
 
5002
5401
  @classmethod
@@ -5040,7 +5439,7 @@ class security_SsvcVulnAssessmentRelationship(security_VulnAssessmentRelationshi
5040
5439
  NODE_KIND = NodeKind.IRI
5041
5440
  ID_ALIAS = "spdxId"
5042
5441
  IS_DEPRECATED = False
5043
- NAMED_INDIVIDUALS = {
5442
+ NAMED_INDIVIDUALS: Dict[str, str] = {
5044
5443
  }
5045
5444
 
5046
5445
  @classmethod
@@ -5069,7 +5468,7 @@ class security_VexVulnAssessmentRelationship(security_VulnAssessmentRelationship
5069
5468
  NODE_KIND = NodeKind.IRI
5070
5469
  ID_ALIAS = "spdxId"
5071
5470
  IS_DEPRECATED = False
5072
- NAMED_INDIVIDUALS = {
5471
+ NAMED_INDIVIDUALS: Dict[str, str] = {
5073
5472
  }
5074
5473
 
5075
5474
  @classmethod
@@ -5099,7 +5498,7 @@ class security_Vulnerability(Artifact):
5099
5498
  NODE_KIND = NodeKind.IRI
5100
5499
  ID_ALIAS = "spdxId"
5101
5500
  IS_DEPRECATED = False
5102
- NAMED_INDIVIDUALS = {
5501
+ NAMED_INDIVIDUALS: Dict[str, str] = {
5103
5502
  }
5104
5503
 
5105
5504
  @classmethod
@@ -5137,7 +5536,7 @@ class software_SoftwareArtifact(Artifact):
5137
5536
  NODE_KIND = NodeKind.IRI
5138
5537
  ID_ALIAS = "spdxId"
5139
5538
  IS_DEPRECATED = False
5140
- NAMED_INDIVIDUALS = {
5539
+ NAMED_INDIVIDUALS: Dict[str, str] = {
5141
5540
  }
5142
5541
 
5143
5542
  @classmethod
@@ -5255,7 +5654,7 @@ class Bom(Bundle):
5255
5654
  NODE_KIND = NodeKind.IRI
5256
5655
  ID_ALIAS = "spdxId"
5257
5656
  IS_DEPRECATED = False
5258
- NAMED_INDIVIDUALS = {
5657
+ NAMED_INDIVIDUALS: Dict[str, str] = {
5259
5658
  }
5260
5659
 
5261
5660
 
@@ -5265,7 +5664,7 @@ class expandedlicensing_CustomLicense(expandedlicensing_License):
5265
5664
  NODE_KIND = NodeKind.IRI
5266
5665
  ID_ALIAS = "spdxId"
5267
5666
  IS_DEPRECATED = False
5268
- NAMED_INDIVIDUALS = {
5667
+ NAMED_INDIVIDUALS: Dict[str, str] = {
5269
5668
  }
5270
5669
 
5271
5670
 
@@ -5276,7 +5675,7 @@ class security_VexAffectedVulnAssessmentRelationship(security_VexVulnAssessmentR
5276
5675
  NODE_KIND = NodeKind.IRI
5277
5676
  ID_ALIAS = "spdxId"
5278
5677
  IS_DEPRECATED = False
5279
- NAMED_INDIVIDUALS = {
5678
+ NAMED_INDIVIDUALS: Dict[str, str] = {
5280
5679
  }
5281
5680
 
5282
5681
  @classmethod
@@ -5310,7 +5709,7 @@ class security_VexFixedVulnAssessmentRelationship(security_VexVulnAssessmentRela
5310
5709
  NODE_KIND = NodeKind.IRI
5311
5710
  ID_ALIAS = "spdxId"
5312
5711
  IS_DEPRECATED = False
5313
- NAMED_INDIVIDUALS = {
5712
+ NAMED_INDIVIDUALS: Dict[str, str] = {
5314
5713
  }
5315
5714
 
5316
5715
 
@@ -5321,7 +5720,7 @@ class security_VexNotAffectedVulnAssessmentRelationship(security_VexVulnAssessme
5321
5720
  NODE_KIND = NodeKind.IRI
5322
5721
  ID_ALIAS = "spdxId"
5323
5722
  IS_DEPRECATED = False
5324
- NAMED_INDIVIDUALS = {
5723
+ NAMED_INDIVIDUALS: Dict[str, str] = {
5325
5724
  }
5326
5725
 
5327
5726
  @classmethod
@@ -5370,7 +5769,7 @@ class security_VexUnderInvestigationVulnAssessmentRelationship(security_VexVulnA
5370
5769
  NODE_KIND = NodeKind.IRI
5371
5770
  ID_ALIAS = "spdxId"
5372
5771
  IS_DEPRECATED = False
5373
- NAMED_INDIVIDUALS = {
5772
+ NAMED_INDIVIDUALS: Dict[str, str] = {
5374
5773
  }
5375
5774
 
5376
5775
 
@@ -5380,7 +5779,7 @@ class software_File(software_SoftwareArtifact):
5380
5779
  NODE_KIND = NodeKind.IRI
5381
5780
  ID_ALIAS = "spdxId"
5382
5781
  IS_DEPRECATED = False
5383
- NAMED_INDIVIDUALS = {
5782
+ NAMED_INDIVIDUALS: Dict[str, str] = {
5384
5783
  }
5385
5784
 
5386
5785
  @classmethod
@@ -5414,7 +5813,7 @@ class software_Package(software_SoftwareArtifact):
5414
5813
  NODE_KIND = NodeKind.IRI
5415
5814
  ID_ALIAS = "spdxId"
5416
5815
  IS_DEPRECATED = False
5417
- NAMED_INDIVIDUALS = {
5816
+ NAMED_INDIVIDUALS: Dict[str, str] = {
5418
5817
  }
5419
5818
 
5420
5819
  @classmethod
@@ -5472,7 +5871,7 @@ class software_Sbom(Bom):
5472
5871
  NODE_KIND = NodeKind.IRI
5473
5872
  ID_ALIAS = "spdxId"
5474
5873
  IS_DEPRECATED = False
5475
- NAMED_INDIVIDUALS = {
5874
+ NAMED_INDIVIDUALS: Dict[str, str] = {
5476
5875
  }
5477
5876
 
5478
5877
  @classmethod
@@ -5501,7 +5900,7 @@ class software_Snippet(software_SoftwareArtifact):
5501
5900
  NODE_KIND = NodeKind.IRI
5502
5901
  ID_ALIAS = "spdxId"
5503
5902
  IS_DEPRECATED = False
5504
- NAMED_INDIVIDUALS = {
5903
+ NAMED_INDIVIDUALS: Dict[str, str] = {
5505
5904
  }
5506
5905
 
5507
5906
  @classmethod
@@ -5542,7 +5941,7 @@ class ai_AIPackage(software_Package):
5542
5941
  NODE_KIND = NodeKind.IRI
5543
5942
  ID_ALIAS = "spdxId"
5544
5943
  IS_DEPRECATED = False
5545
- NAMED_INDIVIDUALS = {
5944
+ NAMED_INDIVIDUALS: Dict[str, str] = {
5546
5945
  }
5547
5946
 
5548
5947
  @classmethod
@@ -5695,7 +6094,7 @@ class dataset_DatasetPackage(software_Package):
5695
6094
  NODE_KIND = NodeKind.IRI
5696
6095
  ID_ALIAS = "spdxId"
5697
6096
  IS_DEPRECATED = False
5698
- NAMED_INDIVIDUALS = {
6097
+ NAMED_INDIVIDUALS: Dict[str, str] = {
5699
6098
  }
5700
6099
 
5701
6100
  @classmethod