Skip to content
Snippets Groups Projects
Commit ce0e5e56 authored by Ladislav Lhotka's avatar Ladislav Lhotka
Browse files

Write docs for instvalue.py & consolidate code.

parent b5410349
No related branches found
No related tags found
No related merge requests found
......@@ -6,3 +6,4 @@ Basic Interaction
datamodel
instance
instvalue
****************
Instance Values
****************
***********************************
Structured Values of Instance Nodes
***********************************
.. module:: yangson.instvalue
:synopsis: Cooked instance values.
.. moduleauthor:: Ladislav Lhotka <lhotka@nic.cz>
:synopsis: Structured instance node values.
.. autodata:: Value
.. testsetup::
The standard library function :func:`json.load` parses JSON text into
convenient Python values – scalars, lists and dictionaries. For JSON-encoded
YANG data instances, we need to add a bit of extra processing and more
intelligent data structures. The reasons are as follows:
import time
from yangson.instvalue import ArrayValue, ObjectValue
This module implements the following classes:
* :class:`StructuredValue`: Abstract class for “cooked” structured
values of an instance node.
* :class:`ArrayValue`: Cooked array value of an instance node.
* :class:`ObjectValue`: Cooked object value of an instance node.
The standard Python library function :func:`json.load` parses JSON
arrays and objects into native data structures – lists and
dictionaries, respectively. In order to use them effectively in the
*Yangson* library, we need to “cook” them first, i.e. extend these
data structures with additional attributs and methods:
* In order to be able to generate entity tags for HTTP ``ETag``
headers, we need a hash value for every scalar, array or
object. Unlike scalars, though, we can't use the built-in
:func:`hash` function to compute such a value for :class:`list` and
:class:`dict` instances, so we need to *subclass* those two built-in
classes and implement the :meth:`__hash__` method in the subclasses.
headers, we need to be able to compute a hash value for arrays and
objects. Standard Python lists and dictionaries do not implement the
:meth:`__hash__` method.
* We also need each array and object to keep the time stamp of its
last modification (to be used in HTTP ``Last-Modified`` headers).
* For each array and object, we also need to record the time stamp of
its last modification (to be used in HTTP ``Last-Modified``
headers).
* All 64-bit numbers (of YANG types ``int64``, ``uint64`` and
``decimal64``) are encoded as JSON strings [RFC7951]_, so we need to
convert them to :class:`int` and :class:`decimal.decimal` values.
.. data:: Value
This module defines a type alias representing an union of possible
types of instance values.
This type alias covers all possible types of cooked values of an
instance node, both scalar and structured.
.. class:: StructuredValue
.. data:: EntryValue
This class is an abstract superclass of both :class:`ArrayValue` and
:class:`ObjectValue`. Its constructor method has one argument, *ts*
(:class:`datetime.datetime`) that is used to set the
*last_modified* attribute.
This type alias covers possible types of values of a list of
leaf-list entry.
.. attribute:: last_modified
.. class:: StructuredValue(ts: datetime.datetime = None)
This attribute contains a :class:`datetime.datetime` that
records the date and time when the :class:StructuredValue
instance was last modified.
This class is an abstract superclass for structured values of
instance nodes. The constructor argument *ts* contains the initial
value of the *timestamp* attribute. If it is ``None``, then
current time is used.
.. automethod:: time_stamp
.. rubric:: Instance Attributes
.. automethod:: __eq__
.. attribute:: timestamp
.. class:: ArrayValue
This attribute contains a :class:`datetime.datetime` that
records the date and time of the last modification.
This class is a subclass of both :class:`StructuredValue` and
:class:`list`, and corresponds to a JSON array.
.. rubric:: Public Methods
.. automethod:: __hash__
.. method:: copy() -> StructuredValue
.. class:: ObjectValue
Return a shallow copy of the receiver with :attr:`last_modified`
set to current time.
This class is a subclass of both :class:`StructuredValue` and
:class:`dict`, and corresponds to a JSON object.
.. automethod:: stamp
All member names must be identifiers of YANG data nodes. Such a
name must be qualified with the YANG module module name in which
the node is defined if and only if either
.. method:: __eq__(val: StructuredValue) -> bool
* the data node is the root of a data tree, i.e. has no parent data
nodes, or
* the data node's parent is defined in the same module.
Return ``True`` if the receiver is equal to *val*. The equality
test is based on their hash values.
.. automethod:: __hash__
.. CAUTION:: The hash values are guaranteed to be stable only
within the same Python interpreter process. This is because hash
values of Python strings change from one invocation to another.
.. autoclass:: ArrayValue(val: List[EntryValue] = [], ts: datetime.datetime = None)
:show-inheritance:
The additional constructor argument *val* contains a list that the
:class:`ArrayValue` instance will hold.
.. doctest::
>>> ary = ArrayValue([1, 2, 3])
>>> time.sleep(0.1)
>>> ac = ary.copy()
>>> ary.timestamp < ac.timestamp
True
>>> ary == ac
True
>>> ac[2] = 4
>>> ary == ac
False
.. autoclass:: ObjectValue(val: Dict[InstanceName, Value] = {}, ts: datetime.datetime = None)
:show-inheritance:
The additional constructor argument *val* contains a dictionary
that the :class:`ObjectValue` instance will hold.
.. doctest::
>>> obj = ObjectValue({'one': 1, 'two': 2})
>>> time.sleep(0.1)
>>> oc = obj.copy()
>>> obj.timestamp < oc.timestamp
True
>>> obj == oc
True
>>> oc['three'] = 3
>>> obj == oc
False
"""This module contains classes for representing instance node values."""
"""Structured values of instance nodes.
This module implements the following classes:
* StructuredValue: Abstract class for structured values of instance nodes.
* ArrayValue: Cooked array value of an instance node.
* ObjectValue: Cooked object value of an instance node.
"""
from datetime import datetime
from typing import Dict, List, Union
from .typealiases import *
#: Type alias covers all possible instance node values.
# Type aliases
Value = Union[ScalarValue, "ArrayValue", "ObjectValue"]
"""All possible types of cooked values (scalar and structured)."""
EntryValue = Union[ScalarValue, "ObjectValue"]
"""Type of the value a list ot leaf-list entry."""
class StructuredValue:
"""Abstract class for array and object values."""
......@@ -35,19 +45,23 @@ class StructuredValue:
"""
return self.__class__ == val.__class__ and hash(self) == hash(val)
def __hash__(self) -> int:
"""Return hash value for the receiver."""
raise NotImplementedError()
class ArrayValue(StructuredValue, list):
"""Array values corresponding to YANG lists and leaf-lists."""
"""This class represents cooked array values."""
def __init__(self, val: List[Value] = [], ts: datetime=None):
def __init__(self, val: List[EntryValue] = [], ts: datetime=None):
StructuredValue.__init__(self, ts)
list.__init__(self, val)
def __hash__(self) -> int:
"""Return integer hash value for the receiver."""
"""Return hash value for the receiver."""
return tuple([ x.__hash__() for x in self]).__hash__()
class ObjectValue(StructuredValue, dict):
"""Array values corresponding to YANG container."""
"""This class represents cooked object values."""
def __init__(self, val: Dict[InstanceName, Value] = {},
ts: datetime = None):
......@@ -55,6 +69,6 @@ class ObjectValue(StructuredValue, dict):
dict.__init__(self, val)
def __hash__(self) -> int:
"""Return integer hash value for the receiver."""
"""Return hash value for the receiver."""
sks = sorted(self.keys())
return tuple([ (k, self[k].__hash__()) for k in sks ]).__hash__()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment