Skip to content

sob.hooks

Hooks

Hooks(
    before_marshal: (
        typing.Callable[[sob.abc.Model], sob.abc.Model]
        | None
    ) = None,
    after_marshal: (
        typing.Callable[
            [sob.abc.JSONTypes], sob.abc.JSONTypes
        ]
        | None
    ) = None,
    before_unmarshal: (
        typing.Callable[
            [sob.abc.MarshallableTypes],
            sob.abc.MarshallableTypes,
        ]
        | None
    ) = None,
    after_unmarshal: (
        typing.Callable[[sob.abc.Model], sob.abc.Model]
        | None
    ) = None,
    before_serialize: (
        typing.Callable[
            [sob.abc.JSONTypes], sob.abc.JSONTypes
        ]
        | None
    ) = None,
    after_serialize: (
        typing.Callable[[str], str] | None
    ) = None,
    before_validate: (
        typing.Callable[[sob.abc.Model], sob.abc.Model]
        | None
    ) = None,
    after_validate: (
        typing.Callable[[sob.abc.Model], None] | None
    ) = None,
)

Bases: sob.abc.Hooks

Instances of this class hold functions ("hooks") to be executed at various points during marshalling, un-marshalling, serializing, de-serializing or validation.

Please note the following context-specific definitions:

  • marshal: To convert an instance of an sob.Model sub-class into data suitable for serializing with json.dumps. For example, marshalling an instance of sob.Dictionary, or marshalling an instance of a sub-class of sob.Object, would result in a dict object.
  • unmarshal: To convert data de-serialized using json.loads into an instance of an sob.Model sub-class. For example, un-marshalling a dict object could return in an instance of sob.Dictionary (this would be the default if no types were specified), or could return an instance of one of the sob.Model sub-classes specified in the types parameter passed to sob.unmarshal.
  • serialize: To convert a marshalled object into a JSON string.
  • deserialize: To convert a JSON string into a python-native object.
  • validate: To check that the data held by a model instance is in compliance with that model's metadata. Because data types are enforced when attributes are set, validation only entails verifying that all required attributes are present, and that no extraneous attributes are present. Validation is only initiated explicitly, by passing a model instance to the sob.validate function.

Attributes:

  • before_marshal

    A function called before marshalling a model. The before_marshal function should accept deserialized JSON data (pre-marshalling) as the first argument, and return the same type of data (or None) as the return value.

  • after_marshal

    A function to be called after marshalling a model. The after_marshal function should accept an instance of the class to which it is associated as the only argument, and must return an instance of that class as the return value.

  • before_unmarshal

    A function to be called before un-marshalling a model. The before_unmarshal function should accept an instance of the class to which it is associated as the only argument, and must return an instance of that class as the return value.

  • after_unmarshal

    A function to be called after un-marshalling a model. The after_unmarshal function should accept unmarshalled, but pre-serialized, JSON serializable data as the first argument, and return the same type of data (or None) as the return value.

  • before_serialize

    A function to be called before serializing a model. The before_serialize function should accept unmarshalled, but pre-serialized, JSON serializable data as the first argument, and return the same type of data (or None) as the return value. For most use cases, assigning a function to after_unmarshal and to before_serialize will produce the same result, however it is technically possible to unmarshal data without ever serializing it, so both hooks are provided.

  • after_serialize

    A function to be called after serializing a model. The after_serialize function should accept a JSON string as the only argument, and return a JSON string as the return value.

  • before_validate

    A function to be called before validating a model. The before_validate function should accept an instance of the class to which it is associated as the only argument, and must return an instance of that class as the return value.

  • after_validate

    A function to be called after validating a model. The after_validate function should accept an instance of the class to which it is associated as the only argument, and must return an instance of that class as the return value.

Source code in src/sob/hooks.py
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
def __init__(
    self,
    before_marshal: Callable[[abc.Model], abc.Model] | None = None,
    after_marshal: Callable[[JSONTypes], JSONTypes] | None = None,
    before_unmarshal: Callable[[MarshallableTypes], MarshallableTypes]
    | None = None,
    after_unmarshal: Callable[[abc.Model], abc.Model] | None = None,
    before_serialize: Callable[[JSONTypes], JSONTypes] | None = None,
    after_serialize: Callable[[str], str] | None = None,
    before_validate: Callable[[abc.Model], abc.Model] | None = None,
    after_validate: Callable[[abc.Model], None] | None = None,
):
    self.before_marshal = before_marshal
    self.after_marshal = after_marshal
    self.before_unmarshal = before_unmarshal
    self.after_unmarshal = after_unmarshal
    self.before_serialize = before_serialize
    self.after_serialize = after_serialize
    self.before_validate = before_validate
    self.after_validate = after_validate

ObjectHooks

ObjectHooks(
    before_marshal: (
        typing.Callable[[sob.abc.Model], sob.abc.Model]
        | None
    ) = None,
    after_marshal: (
        typing.Callable[
            [sob.abc.JSONTypes], sob.abc.JSONTypes
        ]
        | None
    ) = None,
    before_unmarshal: (
        typing.Callable[
            [sob.abc.MarshallableTypes],
            sob.abc.MarshallableTypes,
        ]
        | None
    ) = None,
    after_unmarshal: (
        typing.Callable[[sob.abc.Model], sob.abc.Model]
        | None
    ) = None,
    before_serialize: (
        typing.Callable[
            [sob.abc.JSONTypes], sob.abc.JSONTypes
        ]
        | None
    ) = None,
    after_serialize: (
        typing.Callable[[str], str] | None
    ) = None,
    before_validate: (
        typing.Callable[[sob.abc.Model], sob.abc.Model]
        | None
    ) = None,
    after_validate: (
        typing.Callable[[sob.abc.Model], None] | None
    ) = None,
    before_setattr: (
        typing.Callable[
            [
                sob.abc.Object,
                str,
                sob.abc.MarshallableTypes,
            ],
            tuple[str, sob.abc.MarshallableTypes],
        ]
        | None
    ) = None,
    after_setattr: (
        typing.Callable[
            [
                sob.abc.Object,
                str,
                sob.abc.MarshallableTypes,
            ],
            None,
        ]
        | None
    ) = None,
    before_setitem: (
        typing.Callable[
            [
                sob.abc.Object,
                str,
                sob.abc.MarshallableTypes,
            ],
            tuple[str, sob.abc.MarshallableTypes],
        ]
        | None
    ) = None,
    after_setitem: (
        typing.Callable[
            [
                sob.abc.Object,
                str,
                sob.abc.MarshallableTypes,
            ],
            None,
        ]
        | None
    ) = None,
)

Bases: sob.hooks.Hooks, sob.abc.ObjectHooks

Instances of this class hold functions ("hooks") to be executed at various points during marshalling, un-marshalling, serializing, de-serializing or validation.

Please note the following context-specific definitions:

  • marshal: To convert an instance of an sob.Model sub-class into data suitable for serializing with json.dumps. For example, marshalling an instance of sob.Dictionary, or marshalling an instance of a sub-class of sob.Object, would result in a dict object.
  • unmarshal: To convert data de-serialized using json.loads into an instance of an sob.Model sub-class. For example, un-marshalling a dict object could return in an instance of sob.Dictionary (this would be the default if no types were specified), or could return an instance of one of the sob.Model sub-classes specified in the types parameter passed to sob.unmarshal.
  • serialize: To convert a marshalled object into a JSON string.
  • deserialize: To convert a JSON string into a python-native object.
  • validate: To check that the data held by a model instance is in compliance with that model's metadata. Because data types are enforced when attributes are set, validation only entails verifying that all required attributes are present, and that no extraneous attributes are present. Validation is only initiated explicitly, by passing a model instance to the sob.validate function.

Attributes:

  • before_marshal

    A function called before marshalling a model. The before_marshal function should accept deserialized JSON data (pre-marshalling) as the first argument, and return the same type of data (or None) as the return value.

  • after_marshal

    A function to be called after marshalling a model. The after_marshal function should accept an instance of the class to which it is associated as the only argument, and must return an instance of that class as the return value.

  • before_unmarshal

    A function to be called before un-marshalling a model. The before_unmarshal function should accept an instance of the class to which it is associated as the only argument, and must return an instance of that class as the return value.

  • after_unmarshal

    A function to be called after un-marshalling a model. The after_unmarshal function should accept unmarshalled, but pre-serialized, JSON serializable data as the first argument, and return the same type of data (or None) as the return value.

  • before_serialize

    A function to be called before serializing a model. The before_serialize function should accept unmarshalled, but pre-serialized, JSON serializable data as the first argument, and return the same type of data (or None) as the return value. For most use cases, assigning a function to after_unmarshal and to before_serialize will produce the same result, however it is technically possible to unmarshal data without ever serializing it, so both hooks are provided.

  • after_serialize

    A function to be called after serializing a model. The after_serialize function should accept a JSON string as the only argument, and return a JSON string as the return value.

  • before_validate

    A function to be called before validating a model. The before_validate function should accept an instance of the class to which it is associated as the only argument, and must return an instance of that class as the return value.

  • after_validate

    A function to be called after validating a model. The after_validate function should accept an instance of the class to which it is associated as the only argument, and must return an instance of that class as the return value.

  • before_setattr

    A function to be called before setting an attribute. The before_setattr function should accept 3 positional arguments: an instance of the class to which it is associated, the attribute name, and the value to be assigned to that attribute. The function should return a tuple containing an attribute name and a value to be assigned to that attribute.

  • after_setattr

    A function to be called after setting an attribute. The after_setattr function should accept 3 positional arguments: an instance of the class to which it is associated, the attribute name, and the value assigned to that attribute. The function should return None.

  • before_setitem

    A function to be called before assigning a value to an object by key. The before_setitem function should accept 3 positional arguments: an instance of the class to which it is associated, the item key, and the value to be assigned to that key. The function should return a tuple containing a key and a value to be assigned.

  • after_setitem

    A function to be called after assigning a value to an object by key. The before_setitem function should accept 3 positional arguments: an instance of the class to which it is associated, the item key, and the value assigned to that key. The function should return None.

Source code in src/sob/hooks.py
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
def __init__(
    self,
    before_marshal: Callable[[abc.Model], abc.Model] | None = None,
    after_marshal: Callable[[JSONTypes], JSONTypes] | None = None,
    before_unmarshal: Callable[[MarshallableTypes], MarshallableTypes]
    | None = None,
    after_unmarshal: Callable[[abc.Model], abc.Model] | None = None,
    before_serialize: Callable[[JSONTypes], JSONTypes] | None = None,
    after_serialize: Callable[[str], str] | None = None,
    before_validate: Callable[[abc.Model], abc.Model] | None = None,
    after_validate: Callable[[abc.Model], None] | None = None,
    before_setattr: Callable[
        [abc.Object, str, MarshallableTypes], tuple[str, MarshallableTypes]
    ]
    | None = None,
    after_setattr: Callable[[abc.Object, str, MarshallableTypes], None]
    | None = None,
    before_setitem: Callable[
        [abc.Object, str, MarshallableTypes], tuple[str, MarshallableTypes]
    ]
    | None = None,
    after_setitem: Callable[[abc.Object, str, MarshallableTypes], None]
    | None = None,
) -> None:
    super().__init__(
        before_marshal=before_marshal,
        after_marshal=after_marshal,
        before_unmarshal=before_unmarshal,
        after_unmarshal=after_unmarshal,
        before_serialize=before_serialize,
        after_serialize=after_serialize,
        before_validate=before_validate,
        after_validate=after_validate,
    )
    self.before_setattr = before_setattr
    self.after_setattr = after_setattr
    self.before_setitem = before_setitem
    self.after_setitem = after_setitem

ArrayHooks

ArrayHooks(
    before_marshal: (
        typing.Callable[[sob.abc.Model], sob.abc.Model]
        | None
    ) = None,
    after_marshal: (
        typing.Callable[
            [sob.abc.JSONTypes], sob.abc.JSONTypes
        ]
        | None
    ) = None,
    before_unmarshal: (
        typing.Callable[
            [sob.abc.MarshallableTypes],
            sob.abc.MarshallableTypes,
        ]
        | None
    ) = None,
    after_unmarshal: (
        typing.Callable[[sob.abc.Model], sob.abc.Model]
        | None
    ) = None,
    before_serialize: (
        typing.Callable[
            [sob.abc.JSONTypes], sob.abc.JSONTypes
        ]
        | None
    ) = None,
    after_serialize: (
        typing.Callable[[str], str] | None
    ) = None,
    before_validate: (
        typing.Callable[[sob.abc.Model], sob.abc.Model]
        | None
    ) = None,
    after_validate: (
        typing.Callable[[sob.abc.Model], None] | None
    ) = None,
    before_setitem: (
        typing.Callable[
            [sob.abc.Array, int, sob.abc.MarshallableTypes],
            tuple[int, sob.abc.MarshallableTypes],
        ]
        | None
    ) = None,
    after_setitem: (
        typing.Callable[
            [sob.abc.Array, int, sob.abc.MarshallableTypes],
            None,
        ]
        | None
    ) = None,
    before_append: (
        typing.Callable[
            [sob.abc.Array, sob.abc.MarshallableTypes],
            sob.abc.MarshallableTypes,
        ]
        | None
    ) = None,
    after_append: (
        typing.Callable[
            [sob.abc.Array, sob.abc.MarshallableTypes], None
        ]
        | None
    ) = None,
)

Bases: sob.hooks.Hooks, sob.abc.ArrayHooks

Instances of this class hold functions ("hooks") to be executed at various points during marshalling, un-marshalling, serializing, de-serializing or validation.

Please note the following context-specific definitions:

  • marshal: To convert an instance of an sob.Model sub-class into data suitable for serializing with json.dumps. For example, marshalling an instance of sob.Dictionary, or marshalling an instance of a sub-class of sob.Object, would result in a dict object.
  • unmarshal: To convert data de-serialized using json.loads into an instance of an sob.Model sub-class. For example, un-marshalling a dict object could return in an instance of sob.Dictionary (this would be the default if no types were specified), or could return an instance of one of the sob.Model sub-classes specified in the types parameter passed to sob.unmarshal.
  • serialize: To convert a marshalled object into a JSON string.
  • deserialize: To convert a JSON string into a python-native object.
  • validate: To check that the data held by a model instance is in compliance with that model's metadata. Because data types are enforced when attributes are set, validation only entails verifying that all required attributes are present, and that no extraneous attributes are present. Validation is only initiated explicitly, by passing a model instance to the sob.validate function.

Attributes:

  • before_marshal

    A function called before marshalling a model. The before_marshal function should accept deserialized JSON data (pre-marshalling) as the first argument, and return the same type of data (or None) as the return value.

  • after_marshal

    A function to be called after marshalling a model. The after_marshal function should accept an instance of the class to which it is associated as the only argument, and must return an instance of that class as the return value.

  • before_unmarshal

    A function to be called before un-marshalling a model. The before_unmarshal function should accept an instance of the class to which it is associated as the only argument, and must return an instance of that class as the return value.

  • after_unmarshal

    A function to be called after un-marshalling a model. The after_unmarshal function should accept unmarshalled, but pre-serialized, JSON serializable data as the first argument, and return the same type of data (or None) as the return value.

  • before_serialize

    A function to be called before serializing a model. The before_serialize function should accept unmarshalled, but pre-serialized, JSON serializable data as the first argument, and return the same type of data (or None) as the return value. For most use cases, assigning a function to after_unmarshal and to before_serialize will produce the same result, however it is technically possible to unmarshal data without ever serializing it, so both hooks are provided.

  • after_serialize

    A function to be called after serializing a model. The after_serialize function should accept a JSON string as the only argument, and return a JSON string as the return value.

  • before_validate

    A function to be called before validating a model. The before_validate function should accept an instance of the class to which it is associated as the only argument, and must return an instance of that class as the return value.

  • after_validate

    A function to be called after validating a model. The after_validate function should accept an instance of the class to which it is associated as the only argument, and must return an instance of that class as the return value.

  • before_setitem

    A function to be called before assigning a value to an object by index. The before_setitem function should accept 3 positional arguments: an instance of the class to which it is associated, the index, and the value to be assigned to that index position. The function should return a tuple containing an index and a value to be assigned to that position.

  • after_setitem

    A function to be called after assigning a value to an object by index. The before_setitem function should accept 3 positional arguments: an instance of the class to which it is associated, the index, and the value assigned to that position. The function should return None.

  • before_append

    A function to be called before appending a value to the array. The before_append function should accept 2 positional arguments: an instance of the class to which it is associated, and the value to be appended. The function should return the value to be appended.

  • after_append

    A function to be called after appending a value to the array. The after_append function should accept 2 positional arguments: an instance of the class to which it is associated, and the value appended. The function should return None.

Source code in src/sob/hooks.py
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
def __init__(
    self,
    before_marshal: Callable[[abc.Model], abc.Model] | None = None,
    after_marshal: Callable[[JSONTypes], JSONTypes] | None = None,
    before_unmarshal: Callable[[MarshallableTypes], MarshallableTypes]
    | None = None,
    after_unmarshal: Callable[[abc.Model], abc.Model] | None = None,
    before_serialize: Callable[[JSONTypes], JSONTypes] | None = None,
    after_serialize: Callable[[str], str] | None = None,
    before_validate: Callable[[abc.Model], abc.Model] | None = None,
    after_validate: Callable[[abc.Model], None] | None = None,
    before_setitem: Callable[
        [abc.Array, int, MarshallableTypes], tuple[int, MarshallableTypes]
    ]
    | None = None,
    after_setitem: Callable[[abc.Array, int, MarshallableTypes], None]
    | None = None,
    before_append: Callable[
        [abc.Array, MarshallableTypes], MarshallableTypes
    ]
    | None = None,
    after_append: Callable[[abc.Array, MarshallableTypes], None]
    | None = None,
) -> None:
    super().__init__(
        before_marshal=before_marshal,
        after_marshal=after_marshal,
        before_unmarshal=before_unmarshal,
        after_unmarshal=after_unmarshal,
        before_serialize=before_serialize,
        after_serialize=after_serialize,
        before_validate=before_validate,
        after_validate=after_validate,
    )
    self.before_setitem = before_setitem
    self.after_setitem = after_setitem
    self.before_append = before_append
    self.after_append = after_append

DictionaryHooks

DictionaryHooks(
    before_marshal: (
        typing.Callable[[sob.abc.Model], sob.abc.Model]
        | None
    ) = None,
    after_marshal: (
        typing.Callable[
            [sob.abc.JSONTypes], sob.abc.JSONTypes
        ]
        | None
    ) = None,
    before_unmarshal: (
        typing.Callable[
            [sob.abc.MarshallableTypes],
            sob.abc.MarshallableTypes,
        ]
        | None
    ) = None,
    after_unmarshal: (
        typing.Callable[[sob.abc.Model], sob.abc.Model]
        | None
    ) = None,
    before_serialize: (
        typing.Callable[
            [sob.abc.JSONTypes], sob.abc.JSONTypes
        ]
        | None
    ) = None,
    after_serialize: (
        typing.Callable[[str], str] | None
    ) = None,
    before_validate: (
        typing.Callable[[sob.abc.Model], sob.abc.Model]
        | None
    ) = None,
    after_validate: (
        typing.Callable[[sob.abc.Model], None] | None
    ) = None,
    before_setitem: (
        typing.Callable[
            [
                sob.abc.Dictionary,
                str,
                sob.abc.MarshallableTypes,
            ],
            tuple[str, sob.abc.MarshallableTypes],
        ]
        | None
    ) = None,
    after_setitem: (
        typing.Callable[
            [
                sob.abc.Dictionary,
                str,
                sob.abc.MarshallableTypes,
            ],
            None,
        ]
        | None
    ) = None,
)

Bases: sob.hooks.Hooks, sob.abc.DictionaryHooks

Instances of this class hold functions ("hooks") to be executed at various points during marshalling, un-marshalling, serializing, de-serializing or validation.

Please note the following context-specific definitions:

  • marshal: To convert an instance of an sob.Dictionary sub-class into data suitable for serializing with json.dumps. For example, marshalling an instance of sob.Dictionary would result in a dict object.
  • unmarshal: To convert data de-serialized using json.loads into an instance of an sob.Model sub-class. For example, un-marshalling a dict object could return in an instance of sob.Dictionary (this would be the default if no types were specified), or could return an instance of one of the sob.Model sub-classes specified in the types parameter passed to sob.unmarshal.
  • serialize: To convert a marshalled object into a JSON string.
  • deserialize: To convert a JSON string into a python-native object.
  • validate: To check that the data held by a model instance is in compliance with that model's metadata. Because data types are enforced when attributes are set, validation only entails verifying that all required attributes are present, and that no extraneous attributes are present. Validation is only initiated explicitly, by passing a model instance to the sob.validate function.

Attributes:

  • before_marshal

    A function called before marshalling a model. The before_marshal function should accept deserialized JSON data (pre-marshalling) as the first argument, and return the same type of data (or None) as the return value.

  • after_marshal

    A function to be called after marshalling a model. The after_marshal function should accept an instance of the class to which it is associated as the only argument, and must return an instance of that class as the return value.

  • before_unmarshal

    A function to be called before un-marshalling a model. The before_unmarshal function should accept an instance of the class to which it is associated as the only argument, and must return an instance of that class as the return value.

  • after_unmarshal

    A function to be called after un-marshalling a model. The after_unmarshal function should accept unmarshalled, but pre-serialized, JSON serializable data as the first argument, and return the same type of data (or None) as the return value.

  • before_serialize

    A function to be called before serializing a model. The before_serialize function should accept unmarshalled, but pre-serialized, JSON serializable data as the first argument, and return the same type of data (or None) as the return value. For most use cases, assigning a function to after_unmarshal and to before_serialize will produce the same result, however it is technically possible to unmarshal data without ever serializing it, so both hooks are provided.

  • after_serialize

    A function to be called after serializing a model. The after_serialize function should accept a JSON string as the only argument, and return a JSON string as the return value.

  • before_validate

    A function to be called before validating a model. The before_validate function should accept an instance of the class to which it is associated as the only argument, and must return an instance of that class as the return value.

  • after_validate

    A function to be called after validating a model. The after_validate function should accept an instance of the class to which it is associated as the only argument, and must return an instance of that class as the return value.

  • before_setitem

    A function to be called before assigning a value to an object by key. The before_setitem function should accept 3 positional arguments: an instance of the class to which it is associated, the item key, and the value to be assigned to that key. The function should return a tuple containing a key and a value to be assigned.

  • after_setitem

    A function to be called after assigning a value to an object by key. The before_setitem function should accept 3 positional arguments: an instance of the class to which it is associated, the item key, and the value assigned to that key. The function should return None.

Source code in src/sob/hooks.py
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
def __init__(
    self,
    before_marshal: Callable[[abc.Model], abc.Model] | None = None,
    after_marshal: Callable[[JSONTypes], JSONTypes] | None = None,
    before_unmarshal: Callable[[MarshallableTypes], MarshallableTypes]
    | None = None,
    after_unmarshal: Callable[[abc.Model], abc.Model] | None = None,
    before_serialize: Callable[[JSONTypes], JSONTypes] | None = None,
    after_serialize: Callable[[str], str] | None = None,
    before_validate: Callable[[abc.Model], abc.Model] | None = None,
    after_validate: Callable[[abc.Model], None] | None = None,
    before_setitem: Callable[
        [abc.Dictionary, str, MarshallableTypes],
        tuple[str, MarshallableTypes],
    ]
    | None = None,
    after_setitem: Callable[[abc.Dictionary, str, MarshallableTypes], None]
    | None = None,
):
    super().__init__(
        before_marshal=before_marshal,
        after_marshal=after_marshal,
        before_unmarshal=before_unmarshal,
        after_unmarshal=after_unmarshal,
        before_serialize=before_serialize,
        after_serialize=after_serialize,
        before_validate=before_validate,
        after_validate=after_validate,
    )
    self.before_setitem = before_setitem
    self.after_setitem = after_setitem

read_model_hooks

read_model_hooks(
    model: type | sob.abc.Model,
) -> sob.abc.Hooks | None

Read the hooks associated with a sub-class or instance of sob.Model, or return None if no hooks are defined.

Please note that the returned hooks may be inherited, and therefore should not be modified. Use get_writable_model_hooks to retrieve an instance of these hooks suitable for modification.

Source code in src/sob/hooks.py
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
def read_model_hooks(model: type | abc.Model) -> abc.Hooks | None:
    """
    Read the hooks associated with a sub-class or instance of `sob.Model`,
    or return `None` if no hooks are defined.

    Please note that the returned hooks may be inherited,
    and therefore should not be modified. Use `get_writable_model_hooks` to
    retrieve an instance of these hooks suitable for modification.
    """
    message: str
    if isinstance(model, abc.Model):
        return getattr(model, "_instance_hooks", None) or read_model_hooks(
            type(model)
        )
    if isinstance(model, type) and issubclass(model, abc.Model):
        base: type
        try:
            return next(
                getattr(base, "_class_hooks", None)
                for base in filter(
                    lambda base: issubclass(base, abc.Model),
                    model.__mro__,
                )
            )
        except StopIteration:
            return None
    repr_model: str = repr(model)
    message = (
        "{} requires a parameter which is an instance or sub-class of "
        "`{}`, not{}".format(
            get_calling_function_qualified_name(),
            get_qualified_name(abc.Model),
            (f":\n{repr_model}" if "\n" in repr_model else f" `{repr_model}`"),
        )
    )
    raise TypeError(message)

read_object_hooks

read_object_hooks(
    model: type | sob.abc.Object,
) -> sob.abc.ObjectHooks | None

Read the hooks associated with a sub-class or instance of sob.Object, or return None if no hooks are defined.

Please note that the returned hooks may be inherited, and therefore should not be modified. Use get_writable_object_hooks to retrieve an instance of these hooks suitable for modification.

Source code in src/sob/hooks.py
567
568
569
570
571
572
573
574
575
576
def read_object_hooks(model: type | abc.Object) -> abc.ObjectHooks | None:
    """
    Read the hooks associated with a sub-class or instance of `sob.Object`,
    or return `None` if no hooks are defined.

    Please note that the returned hooks may be inherited,
    and therefore should not be modified. Use `get_writable_object_hooks` to
    retrieve an instance of these hooks suitable for modification.
    """
    return read_model_hooks(model)  # type: ignore

read_array_hooks

read_array_hooks(
    model: type | sob.abc.Array,
) -> sob.abc.ArrayHooks | None

Read the hooks associated with a sub-class or instance of sob.Array, or return None if no hooks are defined.

Please note that the returned hooks may be inherited, and therefore should not be modified. Use get_writable_array_hooks to retrieve an instance of these hooks suitable for modification.

Source code in src/sob/hooks.py
585
586
587
588
589
590
591
592
593
594
595
def read_array_hooks(model: type | abc.Array) -> abc.ArrayHooks | None:
    """
    Read the hooks associated with a sub-class or instance of `sob.Array`,
    or return `None` if no hooks are defined.

    Please note that the returned hooks may be inherited,
    and therefore should not be modified. Use
    `get_writable_array_hooks` to retrieve an instance of these hooks
    suitable for modification.
    """
    return read_model_hooks(model)  # type: ignore

read_dictionary_hooks

read_dictionary_hooks(
    model: type | sob.abc.Dictionary,
) -> sob.abc.DictionaryHooks | None

Read hooks from a sub-class or instance of sob.Dictionary.

Please note that the returned hooks may be inherited, and therefore should not be modified. Use get_writable_dictionary_hooks to retrieve an instance of these hooks suitable for modification.

Source code in src/sob/hooks.py
604
605
606
607
608
609
610
611
612
613
614
def read_dictionary_hooks(
    model: type | abc.Dictionary,
) -> abc.DictionaryHooks | None:
    """
    Read hooks from a sub-class or instance of `sob.Dictionary`.

    Please note that the returned hooks may be inherited,
    and therefore should not be modified. Use `get_writable_dictionary_hooks`
    to retrieve an instance of these hooks suitable for modification.
    """
    return read_model_hooks(model)  # type: ignore

get_writable_model_hooks

get_writable_model_hooks(
    model: type[sob.abc.Model] | sob.abc.Model,
) -> sob.abc.Hooks

Retrieve an instance of sob.Hooks which is associated directly with the model class or instance, and therefore suitable for modifying.

If model is an instance of an sob.Model sub-class, and the instance does not have any hooks associated, the class hooks will be copied to the instance and returned.

If model is a sub-class of sob.Model, but does not have any hooks associated, hooks will be copied from the first parent class which has hooks attributed, and the copy will be returned.

If neither the model class or instance, nor any parent classes, have any hooks associated—a new instance of sob.Hooks will be created, attributed to model, and returned.

Source code in src/sob/hooks.py
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
def get_writable_model_hooks(model: type[abc.Model] | abc.Model) -> abc.Hooks:
    """
    Retrieve an instance of `sob.Hooks` which is associated directly with the
    `model` class or instance, and therefore suitable for modifying.

    If `model` is an instance of an `sob.Model` sub-class, and the instance
    does not have any hooks associated, the class hooks will be
    copied to the instance and returned.

    If `model` is a sub-class of `sob.Model`, but does not have any hooks
    associated, hooks will be copied from the first parent class which
    has hooks attributed, and the copy will be returned.

    If neither the `model` class or instance, nor any parent classes,
    have any hooks associated—a new instance of `sob.Hooks` will be
    created, attributed to `model`, and returned.
    """
    if not _is_model(model):
        raise TypeError(model)
    if isinstance(model, abc.Model):
        if model._instance_hooks is None:  # noqa: SLF001
            model._instance_hooks = deepcopy(  # noqa: SLF001
                read_model_hooks(type(model))
            )
        if model._instance_hooks is None:  # noqa: SLF001
            model._instance_hooks = (  # noqa: SLF001
                ObjectHooks()
                if isinstance(model, abc.Object)
                else ArrayHooks()
                if isinstance(model, abc.Array)
                else DictionaryHooks()
            )
        return model._instance_hooks  # noqa: SLF001
    if isinstance(model, type) and issubclass(model, abc.Model):
        if model._class_hooks is None:  # noqa: SLF001
            model._class_hooks = deepcopy(  # noqa: SLF001
                read_model_hooks(model)
            )
        if model._class_hooks is None:  # noqa: SLF001
            model._class_hooks = (  # noqa: SLF001
                ObjectHooks()
                if issubclass(model, abc.Object)
                else ArrayHooks()
                if issubclass(model, abc.Array)
                else DictionaryHooks()
            )
        return model._class_hooks  # noqa: SLF001
    repr_model: str = represent(model)
    message: str = (
        "{} requires a parameter which is an instance or sub-class of "
        "`{}`, not{}".format(
            get_calling_function_qualified_name(),
            get_qualified_name(abc.Model),
            (":\n" + repr_model if "\n" in repr_model else f" `{repr_model}`"),
        )
    )
    raise TypeError(message)

get_writable_object_hooks

get_writable_object_hooks(
    model: type | sob.abc.Object,
) -> sob.abc.ObjectHooks

Retrieve an instance of sob.ObjectHooks which is associated directly with the model class or instance, and therefore suitable for modifying.

If model is an instance of an sob.Object sub-class, and the instance does not have any hooks associated, the class hooks will be copied to the instance and returned.

If model is a sub-class of sob.Object, but does not have any hooks associated, hooks will be copied from the first parent class which has hooks attributed, and the copy will be returned.

If neither the model class or instance, nor any parent classes, have any hooks associated—a new instance of sob.ObjectHooks will be created, attributed to model, and returned.

Source code in src/sob/hooks.py
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
def get_writable_object_hooks(model: type | abc.Object) -> abc.ObjectHooks:
    """
    Retrieve an instance of `sob.ObjectHooks` which is associated directly with
    the `model` class or instance, and therefore suitable for modifying.

    If `model` is an instance of an `sob.Object` sub-class, and the instance
    does not have any hooks associated, the class hooks will be
    copied to the instance and returned.

    If `model` is a sub-class of `sob.Object`, but does not have any hooks
    associated, hooks will be copied from the first parent class which
    has hooks attributed, and the copy will be returned.

    If neither the `model` class or instance, nor any parent classes,
    have any hooks associated—a new instance of `sob.ObjectHooks` will be
    created, attributed to `model`, and returned.
    """
    return get_writable_model_hooks(model)  # type: ignore

get_writable_array_hooks

get_writable_array_hooks(
    model: type | sob.abc.Array,
) -> sob.abc.ArrayHooks

Retrieve an instance of sob.ArrayHooks which is associated directly with the model class or instance, and therefore suitable for modifying.

If model is an instance of an sob.Array sub-class, and the instance does not have any hooks associated, the class hooks will be copied to the instance and returned.

If model is a sub-class of sob.Array, but does not have any hooks associated, hooks will be copied from the first parent class which has hooks attributed, and the copy will be returned.

If neither the model class or instance, nor any parent classes, have any hooks associated—a new instance of sob.ArrayHooks will be created, attributed to model, and returned.

Source code in src/sob/hooks.py
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
def get_writable_array_hooks(model: type | abc.Array) -> abc.ArrayHooks:
    """
    Retrieve an instance of `sob.ArrayHooks` which is associated directly with
    the `model` class or instance, and therefore suitable for modifying.

    If `model` is an instance of an `sob.Array` sub-class, and the instance
    does not have any hooks associated, the class hooks will be
    copied to the instance and returned.

    If `model` is a sub-class of `sob.Array`, but does not have any hooks
    associated, hooks will be copied from the first parent class which
    has hooks attributed, and the copy will be returned.

    If neither the `model` class or instance, nor any parent classes,
    have any hooks associated—a new instance of `sob.ArrayHooks` will be
    created, attributed to `model`, and returned.
    """
    return get_writable_model_hooks(model)  # type: ignore

get_writable_dictionary_hooks

get_writable_dictionary_hooks(
    model: type | sob.abc.Dictionary,
) -> sob.abc.DictionaryHooks

Retrieve an instance of sob.DictionaryHooks which is associated directly with the model class or instance, and therefore suitable for writing hooks to.

If model is an instance of an sob.Dictionary sub-class, and the instance does not have any hooks associated, the parent class'es hooks will be copied to the instance and returned.

If model is a sub-class of sob.Dictionary, but does not have any hooks associated, hooks will be copied from the first parent class which does have hooks attributed.

If neither the model class or instance, nor any parent classes, have any hooks associated—a new instance of sob.DictionaryHooks will be created, attributed to model, and returned.

Source code in src/sob/hooks.py
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
def get_writable_dictionary_hooks(
    model: type | abc.Dictionary,
) -> abc.DictionaryHooks:
    """
    Retrieve an instance of `sob.DictionaryHooks` which is associated directly
    with the `model` class or instance, and therefore suitable for writing
    hooks to.

    If `model` is an instance of an `sob.Dictionary` sub-class, and the
    instance does not have any hooks associated, the parent class'es hooks will
    be copied to the instance and returned.

    If `model` is a sub-class of `sob.Dictionary`, but does not have any hooks
    associated, hooks will be copied from the first parent class which does
    have hooks attributed.

    If neither the `model` class or instance, nor any parent classes,
    have any hooks associated—a new instance of `sob.DictionaryHooks` will be
    created, attributed to `model`, and returned.
    """
    return get_writable_model_hooks(model)  # type: ignore

get_model_hooks_type

get_model_hooks_type(model: type | sob.abc.Model) -> type

Determine the type of metadata required for the specified model class or instance.

Source code in src/sob/hooks.py
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
def get_model_hooks_type(model: type | abc.Model) -> type:
    """
    Determine the type of metadata required for the specified `model`
    class or instance.
    """
    hooks_type: type
    if not isinstance(model, (type, abc.Object, abc.Dictionary, abc.Array)):
        raise TypeError(model)
    if isinstance(model, type):
        if not issubclass(model, (abc.Object, abc.Dictionary, abc.Array)):
            raise TypeError(model)
        hooks_type = (
            ObjectHooks
            if issubclass(model, abc.Object)
            else ArrayHooks
            if issubclass(model, abc.Array)
            else DictionaryHooks
        )
    else:
        hooks_type = (
            ObjectHooks
            if isinstance(model, abc.Object)
            else ArrayHooks
            if isinstance(model, abc.Array)
            else DictionaryHooks
        )
    return hooks_type

write_model_hooks

write_model_hooks(
    model: type[sob.abc.Model] | sob.abc.Model,
    hooks: sob.abc.Hooks | None,
) -> None

Write hooks to a sub-class or instance of sob.Model.

Source code in src/sob/hooks.py
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
def write_model_hooks(
    model: type[abc.Model] | abc.Model, hooks: abc.Hooks | None
) -> None:
    """
    Write hooks to a sub-class or instance of `sob.Model`.
    """
    if hooks is not None:
        # Verify that the metadata is of the correct type
        hooks_type: type[abc.Hooks] = get_model_hooks_type(model)
        if not isinstance(hooks, hooks_type):
            message: str = (
                f"Hooks assigned to `{get_qualified_name(type(model))}` "
                f"must be of type `{get_qualified_name(hooks_type)}`"
            )
            raise ValueError(message)
    if isinstance(model, abc.Model):
        model._instance_hooks = hooks  # noqa: SLF001
    else:
        if not issubclass(model, abc.Model):
            raise TypeError(model)
        model._class_hooks = hooks  # noqa: SLF001