stidantic 0.1.3__py3-none-any.whl → 0.2.1__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.

Potentially problematic release.


This version of stidantic might be problematic. Click here for more details.

stidantic/types.py CHANGED
@@ -1,14 +1,19 @@
1
- from enum import Enum
2
- from re import compile
1
+ import json
2
+ import re
3
3
  from datetime import datetime
4
- from typing import Annotated, Literal, Any, Self, Type, get_args # pyright: ignore[reportDeprecated]
5
- from annotated_types import Ge, Le
6
- from typing_extensions import TypedDict
4
+ from enum import Enum
5
+ from typing import ( # noqa: UP035
6
+ Annotated,
7
+ Any,
8
+ ClassVar,
9
+ Literal,
10
+ Self,
11
+ Type, # pyright: ignore[reportDeprecated]
12
+ get_args,
13
+ )
14
+ from uuid import UUID, uuid4, uuid5
7
15
 
8
- from pydantic.functional_validators import AfterValidator, model_validator
9
- from pydantic.networks import AnyUrl, UrlConstraints
10
- from pydantic.types import Base64Bytes, StringConstraints
11
- from pydantic_core import CoreSchema, core_schema
16
+ from annotated_types import Ge, Le
12
17
  from pydantic import (
13
18
  BaseModel,
14
19
  ConfigDict,
@@ -16,28 +21,36 @@ from pydantic import (
16
21
  GetCoreSchemaHandler,
17
22
  SerializeAsAny,
18
23
  )
24
+ from pydantic.functional_serializers import PlainSerializer
25
+ from pydantic.functional_validators import AfterValidator, model_validator
26
+ from pydantic.networks import AnyUrl, UrlConstraints
27
+ from pydantic.types import Base64Bytes, StringConstraints
28
+ from pydantic_core import CoreSchema, core_schema
29
+ from typing_extensions import TypedDict
19
30
 
31
+ from stidantic.serializers import ser_datetime
32
+ from stidantic.utils import choose_one_hash
20
33
  from stidantic.validators import (
34
+ identifier_of_type,
21
35
  validate_bin_field,
22
36
  validate_hex_field,
23
37
  )
24
38
 
39
+ UUIDv5_NAMESPACE = UUID("00abedb4-aa42-466c-9c01-fed23315a9b7")
25
40
 
26
41
  # Common constraints on Stix dictionnary keys.
27
- StixKeyPattern = compile(r"^[a-zA-Z0-9\-\_]+$")
42
+ StixKeyPattern = re.compile(r"^[a-zA-Z0-9\-\_]+$")
28
43
  StixKeyConstraint = StringConstraints(max_length=250, pattern=StixKeyPattern)
29
44
  StixKey = Annotated[str, StixKeyConstraint]
30
45
 
31
46
  # Common constraints on Stix type names.
32
- StixTypePattern = compile(r"^[a-zA-Z0-9\-]+$")
47
+ StixTypePattern = re.compile(r"^[a-zA-Z0-9\-]+$")
33
48
  StixTypeConstraint = StringConstraints(pattern=StixTypePattern)
34
49
  StixType = Annotated[str, StixTypeConstraint]
35
50
 
36
51
  # Common constraints on Stix property names.
37
- StixPropPattern = compile(r"^[a-zA-Z0-9\_]+$")
38
- StixPropConstraint = StringConstraints(
39
- min_length=3, max_length=250, pattern=StixPropPattern
40
- )
52
+ StixPropPattern = re.compile(r"^[a-zA-Z0-9\_]+$")
53
+ StixPropConstraint = StringConstraints(min_length=3, max_length=250, pattern=StixPropPattern)
41
54
  StixProp = Annotated[str, StixPropConstraint]
42
55
 
43
56
  # 2.1 Binary
@@ -61,6 +74,10 @@ type StixDict = dict[
61
74
  Any, # pyright: ignore[reportExplicitAny]
62
75
  ]
63
76
 
77
+ # 2.16 Timestamp
78
+ # The timestamp type defines how dates and times are represented in STIX.
79
+ StixTimestamp = Annotated[datetime, PlainSerializer(ser_datetime)]
80
+
64
81
 
65
82
  # A URL reference to an external resource [RFC3986].
66
83
  type StixUrl = Annotated[AnyUrl, UrlConstraints(preserve_empty_path=True)]
@@ -68,10 +85,12 @@ type StixUrl = Annotated[AnyUrl, UrlConstraints(preserve_empty_path=True)]
68
85
 
69
86
  # 2.9 Identifier
70
87
  class Identifier(str):
88
+ __slots__ = () # pyright: ignore[reportUnannotatedClassAttribute]
89
+
71
90
  @classmethod
72
91
  def __get_pydantic_core_schema__(
73
92
  cls,
74
- source_type: Any, # pyright: ignore[reportExplicitAny, reportAny]
93
+ source_type: Any, # pyright: ignore[reportExplicitAny, reportAny] # noqa: ANN401
75
94
  handler: GetCoreSchemaHandler,
76
95
  ) -> CoreSchema:
77
96
  return core_schema.no_info_after_validator_function(cls, handler(str))
@@ -136,8 +155,8 @@ class Hashes(StixCore, extra="allow"):
136
155
  The value MUST be a string in the appropriate format defined by the hash type indicated in the dictionary key.
137
156
  """
138
157
  if self.__pydantic_extra__ and any(
139
- not (len(key) > 250 or len(key) < 3 or StixKeyPattern.match(key))
140
- for key in self.__pydantic_extra__.keys()
158
+ not (len(key) > 250 or len(key) < 3 or StixKeyPattern.match(key)) # noqa: PLR2004
159
+ for key in self.__pydantic_extra__
141
160
  ):
142
161
  raise ValueError("Invalid extra hash key.")
143
162
  return self
@@ -165,6 +184,7 @@ class ExternalReference(StixCore):
165
184
  external_id: str | None = None
166
185
 
167
186
  @model_validator(mode="before")
187
+ @classmethod
168
188
  def at_least_one(cls, values: dict[str, str]) -> dict[str, str]:
169
189
  """
170
190
  In addition to the source_name property, at least one of the description, url,
@@ -206,7 +226,7 @@ class GranularMarking(StixCore):
206
226
  # The marking_ref property specifies the ID of the marking-definition object that describes the marking.
207
227
  # If the lang property is not present, this property MUST be present. If the lang property is present,
208
228
  # this property MUST NOT be present.
209
- marking_ref: Identifier | None = None
229
+ marking_ref: Annotated[Identifier, AfterValidator(identifier_of_type("marking-definition"))] | None = None
210
230
  # The selectors property specifies a list of selectors for content contained within the STIX Object in which this
211
231
  # property appears. Selectors MUST conform to the syntax defined below. The marking-definition referenced in
212
232
  # the marking_ref property is applied to the content selected by the selectors in this list. The [RFC5646] language
@@ -226,9 +246,7 @@ class GranularMarking(StixCore):
226
246
  @model_validator(mode="after")
227
247
  def lang_or_marking_ref(self) -> "GranularMarking":
228
248
  if self.lang and self.marking_ref:
229
- raise ValueError(
230
- "Both lang and marking_ref properties MUST NOT be present."
231
- )
249
+ raise ValueError("Both lang and marking_ref properties MUST NOT be present.")
232
250
  if not self.lang and not self.marking_ref:
233
251
  raise ValueError("Either lang or marking_ref property MUST be present.")
234
252
  return self
@@ -247,7 +265,7 @@ class Extension(StixCore):
247
265
  extension_type: ExtensionType | None = None
248
266
 
249
267
 
250
- class ExtensionsDict(TypedDict, total=False, extra_items=SerializeAsAny[Extension]): ... # noqa: E701
268
+ class ExtensionsDict(TypedDict, total=False, extra_items=SerializeAsAny[Extension]): ...
251
269
 
252
270
 
253
271
  # 3.2 Common Properties
@@ -259,12 +277,15 @@ class StixCommon(StixCore):
259
277
  and which are not in use.
260
278
  """
261
279
 
280
+ # List of ID-contributing properties for UUIDv5 deterministic ID generation.
281
+ # Do not appear in model instances as it is a ClassVar.
282
+ id_contributing_properties: ClassVar[list[str] | None] = None
262
283
  # All STIX Objects and the STIX Bundle Object have an id property that uniquely identifies each instance
263
284
  # of the object.
264
285
  # This id MUST meet the requirements of the identifier type (see section 2.9).
265
286
  # For objects that support versioning, all objects with the same id are considered different versions
266
287
  # of the same object and the version of the object is identified by its modified property.
267
- id: Identifier
288
+ id: Identifier = Identifier("")
268
289
  # The type property identifies the type of STIX Object.
269
290
  type: str
270
291
  # The value of this property MUST be 2.1 for STIX Objects defined according to this specification.
@@ -287,7 +308,9 @@ class StixCommon(StixCore):
287
308
  external_references: list[ExternalReference] | None = None
288
309
  # The object_marking_refs property specifies a list of id properties of marking-definition objects that apply
289
310
  # to this object.
290
- object_marking_refs: list[Identifier] | None = None
311
+ object_marking_refs: (
312
+ list[Annotated[Identifier, AfterValidator(identifier_of_type("marking-definition"))]] | None
313
+ ) = None
291
314
  # The granular_markings property specifies a list of granular markings applied to this object.
292
315
  granular_markings: list[GranularMarking] | None = None
293
316
  # Specifies any extensions of the object, as a dictionary.
@@ -302,11 +325,11 @@ class StixCommon(StixCore):
302
325
  extensions: ExtensionsDict | dict[str, Extension] | None = None
303
326
 
304
327
  @classmethod
305
- def register_new_extension(
328
+ def register_property_extension(
306
329
  cls,
307
330
  definition: "StixCommon", # pyright: ignore[reportUnusedParameter]
308
- extension: Type[Extension], # pyright: ignore[reportUnusedParameter, reportDeprecated]
309
- ):
331
+ extension: Type[Extension], # pyright: ignore[reportUnusedParameter, reportDeprecated] # noqa: UP006
332
+ ) -> None:
310
333
  """
311
334
  Dynamically update the extensions property so that new classes get deserialized based on the extension key.
312
335
  """
@@ -323,19 +346,38 @@ class StixCommon(StixCore):
323
346
  cls.model_fields["extensions"].annotation = CustomExtensionsDict | None # pyright: ignore[reportAttributeAccessIssue]
324
347
  cls.model_rebuild(force=True) # pyright: ignore[reportUnusedCallResult]
325
348
 
349
+ @model_validator(mode="after")
350
+ def generate_id(self) -> Self:
351
+ if not self.id:
352
+ if self.id_contributing_properties:
353
+ id_contributing = self.model_dump(
354
+ mode="json",
355
+ by_alias=True,
356
+ exclude_none=True,
357
+ include=dict.fromkeys(self.id_contributing_properties, True),
358
+ )
359
+ if "hashes" in id_contributing:
360
+ id_contributing["hashes"] = choose_one_hash(id_contributing["hashes"]) # pyright: ignore[reportAny]
361
+ serialized = json.dumps(id_contributing, sort_keys=True, separators=(",", ":"), ensure_ascii=True)
362
+ uuid = uuid5(UUIDv5_NAMESPACE, serialized)
363
+ else:
364
+ uuid = uuid4()
365
+ self.__dict__["id"] = f"{self.type}--{uuid}"
366
+ return self
367
+
326
368
 
327
369
  class StixDomain(StixCommon):
328
370
  # The created_by_ref property specifies the id property of the identity object that describes the entity that
329
371
  # created this object.
330
- created_by_ref: Identifier | None = None
372
+ created_by_ref: Annotated[Identifier, AfterValidator(identifier_of_type("identity"))] | None = None
331
373
  # The created property represents the time at which the object was originally created.
332
374
  # The created property MUST NOT be changed when creating a new version of the object.
333
- created: datetime
375
+ created: StixTimestamp
334
376
  # The modified property is only used by STIX Objects that support versioning and represents
335
377
  # the time that this particular version of the object was last modified.
336
378
  # Object creators MUST set the modified property when creating a new
337
379
  # version of an object if the created property was set.
338
- modified: datetime
380
+ modified: StixTimestamp
339
381
 
340
382
  @model_validator(mode="after")
341
383
  def validate_modified_after_created(self) -> Self:
@@ -344,9 +386,11 @@ class StixDomain(StixCommon):
344
386
  MUST be later than or equal to the value of the created property.
345
387
  """
346
388
  if self.created > self.modified:
347
- raise ValueError(
348
- "The modified property MUST be later than or equal to the value of the created property."
349
- )
389
+ created = self.created
390
+ modified = self.modified
391
+ self.created = modified
392
+ self.modified = created
393
+ return self
350
394
  return self
351
395
 
352
396
 
@@ -356,18 +400,17 @@ class StixObservable(StixCommon):
356
400
 
357
401
 
358
402
  class StixRelationship(StixCommon):
359
- relationship_type: str
360
403
  # The created property represents the time at which the object was originally created.
361
404
  # The created property MUST NOT be changed when creating a new version of the object.
362
- created: datetime
405
+ created: StixTimestamp
363
406
  # The modified property is only used by STIX Objects that support versioning and represents
364
407
  # the time that this particular version of the object was last modified.
365
408
  # Object creators MUST set the modified property when creating a new
366
409
  # version of an object if the created property was set.
367
- modified: datetime
410
+ modified: StixTimestamp
368
411
  # The created_by_ref property specifies the id property of the identity object that describes the entity that
369
412
  # created this object.
370
- created_by_ref: Identifier | None = None
413
+ created_by_ref: Annotated[Identifier, AfterValidator(identifier_of_type("identity"))] | None = None
371
414
 
372
415
  @model_validator(mode="after")
373
416
  def validate_modified_after_created(self) -> Self:
@@ -376,9 +419,11 @@ class StixRelationship(StixCommon):
376
419
  MUST be later than or equal to the value of the created property.
377
420
  """
378
421
  if self.created > self.modified:
379
- raise ValueError(
380
- "The modified property MUST be later than or equal to the value of the created property."
381
- )
422
+ created = self.created
423
+ modified = self.modified
424
+ self.created = modified
425
+ self.modified = created
426
+ return self
382
427
  return self
383
428
 
384
429
 
@@ -386,18 +431,18 @@ class StixMeta(StixCommon):
386
431
  type: str
387
432
  # The created property represents the time at which the object was originally created.
388
433
  # The created property MUST NOT be changed when creating a new version of the object.
389
- created: datetime
434
+ created: StixTimestamp
390
435
 
391
436
 
392
437
  class StixLanguage(StixMeta):
393
438
  # The created_by_ref property specifies the id property of the identity object that describes the entity that
394
439
  # created this object.
395
- created_by_ref: Identifier | None = None
440
+ created_by_ref: Annotated[Identifier, AfterValidator(identifier_of_type("identity"))] | None = None
396
441
  # The modified property is only used by STIX Objects that support versioning and represents
397
442
  # the time that this particular version of the object was last modified.
398
443
  # Object creators MUST set the modified property when creating a new
399
444
  # version of an object if the created property was set.
400
- modified: datetime
445
+ modified: StixTimestamp
401
446
 
402
447
  @model_validator(mode="after")
403
448
  def validate_modified_after_created(self) -> Self:
@@ -406,27 +451,25 @@ class StixLanguage(StixMeta):
406
451
  MUST be later than or equal to the value of the created property.
407
452
  """
408
453
  if self.created > self.modified:
409
- raise ValueError(
410
- "The modified property MUST be later than or equal to the value of the created property."
411
- )
454
+ raise ValueError("The modified property MUST be later than or equal to the value of the created property.")
412
455
  return self
413
456
 
414
457
 
415
458
  class StixMarking(StixMeta):
416
459
  # The created_by_ref property specifies the id property of the identity object that describes the entity that
417
460
  # created this object.
418
- created_by_ref: Identifier | None = None
461
+ created_by_ref: Annotated[Identifier, AfterValidator(identifier_of_type("identity"))] | None = None
419
462
 
420
463
 
421
464
  class StixExtension(StixMeta):
422
465
  # The created_by_ref property specifies the id property of the identity object that describes the entity that
423
466
  # created this object.
424
- created_by_ref: Identifier
467
+ created_by_ref: Annotated[Identifier, AfterValidator(identifier_of_type("identity"))]
425
468
  # The modified property is only used by STIX Objects that support versioning and represents
426
469
  # the time that this particular version of the object was last modified.
427
470
  # Object creators MUST set the modified property when creating a new
428
471
  # version of an object if the created property was set.
429
- modified: datetime
472
+ modified: StixTimestamp
430
473
 
431
474
  @model_validator(mode="after")
432
475
  def validate_modified_after_created(self) -> Self:
@@ -435,7 +478,9 @@ class StixExtension(StixMeta):
435
478
  MUST be later than or equal to the value of the created property.
436
479
  """
437
480
  if self.created > self.modified:
438
- raise ValueError(
439
- "The modified property MUST be later than or equal to the value of the created property."
440
- )
481
+ created = self.created
482
+ modified = self.modified
483
+ self.created: StixTimestamp = modified
484
+ self.modified = created
485
+ return self
441
486
  return self
stidantic/utils.py ADDED
@@ -0,0 +1,15 @@
1
+ def choose_one_hash(hashes: dict[str, str]) -> dict[str, str] | None:
2
+ if "MD5" in hashes:
3
+ return {"MD5": hashes["MD5"]}
4
+ if "SHA-1" in hashes:
5
+ return {"SHA-1": hashes["SHA-1"]}
6
+ if "SHA-256" in hashes:
7
+ return {"SHA-256": hashes["SHA-256"]}
8
+ if "SHA-512" in hashes:
9
+ return {"SHA-512": hashes["SHA-512"]}
10
+
11
+ k = next(iter(hashes), None)
12
+ if k is not None:
13
+ return {k: hashes[k]}
14
+
15
+ return None
stidantic/validators.py CHANGED
@@ -1,13 +1,26 @@
1
+ from collections.abc import Callable
2
+
1
3
  from pydantic import ValidationInfo
2
4
 
3
5
 
4
- def validate_identifier(value: str) -> str:
5
- _type, _uuid = value.split("--")
6
- if not _type and not _uuid:
7
- raise ValueError("Invalid identifier format.")
6
+ def validate_identifier(value: str, types: tuple[str, ...]) -> str:
7
+ t = value.split("--")[0]
8
+ if t not in types:
9
+ raise ValueError(f"{value} is not one of {types}")
8
10
  return value
9
11
 
10
12
 
13
+ def identifier_of_type(*args: str) -> Callable[..., str]:
14
+ """
15
+ Validates that an identifier is of a certain type or types.
16
+ """
17
+
18
+ def validator(value: str) -> str:
19
+ return validate_identifier(value, args)
20
+
21
+ return validator
22
+
23
+
11
24
  def validate_bin_field(value: str, info: ValidationInfo) -> str:
12
25
  if info.field_name and not info.field_name.endswith("_bin"):
13
26
  raise ValueError("The property name MUST end with '_bin'.")
stidantic/vocab.py CHANGED
@@ -446,9 +446,7 @@ class DNSRecord(Enum):
446
446
  # by retrying the lookup with the new name.
447
447
  CSYNC = "CSYNC" # Child-to-Parent Synchronization : Specify a synchronization mechanism between a child
448
448
  # and a parent DNS zone. Typical example is declaring the same NS records in the parent and the child zone
449
- DHCID = (
450
- "DHCID" # DHCP identifier : Used in conjunction with the FQDN option to DHCP
451
- )
449
+ DHCID = "DHCID" # DHCP identifier : Used in conjunction with the FQDN option to DHCP
452
450
  DLV = "DLV" # DNSSEC Lookaside Validation record : For publishing DNSSEC trust anchors outside of the
453
451
  # DNS delegation chain. Uses the same format as the DS record. RFC 5074 describes a way of using these records.
454
452
  DNAME = "DNAME" # Delegation name record : Alias for a name and all its subnames, unlike CNAME, which is an alias
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stidantic
3
- Version: 0.1.3
3
+ Version: 0.2.1
4
4
  Summary: A Pydantic-based Python library for parsing, validating, and creating STIX 2.1 cyber threat intelligence data.
5
5
  Project-URL: Homepage, https://github.com/nicocti/stidantic
6
6
  Project-URL: Bug Tracker, https://github.com/nicocti/stidantic/issues
@@ -23,6 +23,10 @@ Requires-Python: >=3.12
23
23
  Requires-Dist: annotated-types>=0.6.0
24
24
  Requires-Dist: pydantic>=2.12
25
25
  Requires-Dist: typing-extensions>=4.14.1
26
+ Provides-Extra: dev
27
+ Requires-Dist: basedpyright; extra == 'dev'
28
+ Provides-Extra: test
29
+ Requires-Dist: deepdiff; extra == 'test'
26
30
  Description-Content-Type: text/markdown
27
31
 
28
32
  # stidantic [WIP]
@@ -80,7 +84,6 @@ from stidantic.sdo import Campaign
80
84
  from stidantic.types import Identifier
81
85
 
82
86
  campaign = Campaign(
83
- id=Identifier("campaign--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f"),
84
87
  created=datetime.now(),
85
88
  modified=datetime.now(),
86
89
  name="Operation Stealth",
@@ -99,11 +102,8 @@ print(json_output)
99
102
  from stidantic.marking import MarkingDefinition
100
103
  from stidantic.extensions.pap import PAPExtensionDefinition, PAPExtension
101
104
 
102
- MarkingDefinition.register_new_extension(PAPExtensionDefinition, PAPExtension)
105
+ MarkingDefinition.register_property_extension(PAPExtensionDefinition, PAPExtension)
103
106
  data = {
104
- "id": "marking-definition--c43594d1-4b11-4c59-93ab-1c9b14d53ce9",
105
- "type": "marking-definition",
106
- "spec_version": "2.1",
107
107
  "extensions": {
108
108
  "extension-definition--f8d78575-edfd-406e-8e84-6162a8450f5b": {
109
109
  "extension_type": "property-extension",
@@ -174,15 +174,18 @@ if isinstance(pap_green.extensions[PAPExtensionDefinition.id], PAPExtension):
174
174
  ### Bundle
175
175
  - ✅ `StixBundle` - Container for STIX objects
176
176
 
177
+ ### Extensions
178
+ - ✅ `PAP` - Permissible Actions Protocol (PAP) extension from [Oasis](https://github.com/oasis-open/cti-stix-common-objects/blob/main/extension-definition-specifications/pap-marking-definition-f8d/STIX-2.1-PAP-marking-definition.adoc)
179
+
177
180
  ## Roadmap
178
181
 
179
182
  - ~~**Full STIX 2.1 Compliance**~~
180
- - **Python packaging**
183
+ - ~~**Python packaging**~~
181
184
  - **Extensive Testing**
182
- - Mind the datetime datatype serializer to follow the specification (convert to UTC).
183
- - Implement auto deterministic UUIv5 generation for STIX Identifiers.
185
+ - ~~Mind the datetime datatype serializer to follow the specification (convert to UTC).~~
186
+ - ~~Implement auto deterministic UUIv5 generation for STIX Identifiers.~~
184
187
  - Implement a Indicator to Observable export method (and the other way round ?).
185
- - Add Generics validation for Identifier properties that must be of some type.
188
+ - ~~Add Generics validation for Identifier properties that must be of some type.~~
186
189
  - Better STIX Extension Support: Develop a robust and user-friendly mechanism for defining, parsing, and validating custom STIX extensions.
187
190
  - TAXII 2.1 Server: Build a TAXII 2.1 compliant server using FastAPI.
188
191
  - OCA Standard Extensions: Implement STIX extensions from the [Open Cybersecurity Alliance (OCA)](https://github.com/opencybersecurityalliance/stix-extensions) and [stix-common-objects](https://github.com/oasis-open/cti-stix-common-objects) repositories.
@@ -0,0 +1,19 @@
1
+ stidantic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ stidantic/bundle.py,sha256=Xkx7k-O0X853OFPDGvw_FdYO30Pt4BDsY4L6LNXV5FQ,660
3
+ stidantic/extension.py,sha256=ZOg9a6v2-DZz3xArHL4zrz0eIyuW3f3in4dOrQVWU20,7982
4
+ stidantic/language.py,sha256=laLpR1EsuYZF-e9Rp06mvKWvXO2SiavYReRmvQprhEs,2763
5
+ stidantic/marking.py,sha256=4JTMb7vXS73dWH0B1qWDqCbFUe_5tSIZKSrN5-0rz-g,5508
6
+ stidantic/sco.py,sha256=HAGWVm4m8OsKjQ-28TCJpcwLg96iVl0cGnsEMrhl4W8,76409
7
+ stidantic/sdo.py,sha256=6skCvxF1VgvzmKHi_sGL0M9vfGms4wd7WtGQxm7EfTM,56244
8
+ stidantic/serializers.py,sha256=33S6xpbiIHKCWDP-XJMXZ_AcUNuy0KetzrHYkxSj5U8,925
9
+ stidantic/sro.py,sha256=rWUpUpf5cmStekEoYUEGsOk07jLsPmGG3sO5_82RVr8,10821
10
+ stidantic/types.py,sha256=vbLocU6Y_yDBsuqqCFLnxEZVTgY9yKw2fobhB8tQ3uE,23954
11
+ stidantic/utils.py,sha256=BE7okSoZuM83jW8hlNPnjkE_l_PrMWWVkFRBM32S4Nc,451
12
+ stidantic/validators.py,sha256=oAC1rGsHX1isM2kzMvLlWIWWqPvEr_sh4aIaEKWE-tk,955
13
+ stidantic/vocab.py,sha256=m1SB0kvK_LpdWahbDWZYwm1KG0fD_u7er_-h4BWkfRo,18932
14
+ stidantic/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ stidantic/extensions/pap.py,sha256=Tc_Z2H608nfq7ZPSDh-tDjyJH2jS_IPv9Lea9Sqf-7U,2592
16
+ stidantic-0.2.1.dist-info/METADATA,sha256=cCJeExFXV46_NSANoHVAPEbx7NTrs15QUEMuJhHmZ0w,8511
17
+ stidantic-0.2.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
18
+ stidantic-0.2.1.dist-info/licenses/LICENSE,sha256=1Dm2uJzOTe6wtfCrm-OnmztCLqNrpyF8flo5fmVVpbM,1064
19
+ stidantic-0.2.1.dist-info/RECORD,,
@@ -1,15 +0,0 @@
1
- stidantic/bundle.py,sha256=Tg_62VhPfHE9LwSzC-qRy7yHnSyB1jeDRmb4ayxkj-U,768
2
- stidantic/extension.py,sha256=bGJSxyKRbZkyK1d3dhfmoaQ77w_-epCpuOrPbStyXmc,7909
3
- stidantic/language.py,sha256=ICPyx5bjOC-YP5bkpxoubJU9rEr25hbKwdFoPLq8u6s,2728
4
- stidantic/marking.py,sha256=wydmsm-HrYO-osEKmhEAQ71IMSSzllKvttIm3GZVeoU,5521
5
- stidantic/sco.py,sha256=8P1C_bVUaCnZdwErxIi8O3iQ6Pst1ObhxIKQq1CZk1k,75804
6
- stidantic/sdo.py,sha256=RbjaqcU9qb9oE-JkAuKq68S_0yE0DHXZgkb78yTzsM8,56041
7
- stidantic/sro.py,sha256=scntuescZ2Ukb5bcx7d3LCfvqys03DLU6_leT8F5p94,10617
8
- stidantic/types.py,sha256=W0_Xw-LNNKJ5phxCncO3J6XYQXPkZEfkOzKyPP2q8aQ,21772
9
- stidantic/validators.py,sha256=P_t1S8pSx1VCD9JNsB49s0p17Zj0_jtoUMc2gcGw56g,657
10
- stidantic/vocab.py,sha256=dB1vWf27A0bn167KuzcLhgYHXZOKgjb23SsOHfrHuwo,18948
11
- stidantic/extensions/pap.py,sha256=dJfwgt8HcW81gdpxXsG8EF1ucX0ZsM6C0YJ1yw9WbKw,2652
12
- stidantic-0.1.3.dist-info/METADATA,sha256=dFEGfj7KyQQe4APeIDFUHrtIg1b0KE9t9wR6iQk6nfY,8311
13
- stidantic-0.1.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
14
- stidantic-0.1.3.dist-info/licenses/LICENSE,sha256=1Dm2uJzOTe6wtfCrm-OnmztCLqNrpyF8flo5fmVVpbM,1064
15
- stidantic-0.1.3.dist-info/RECORD,,