summaryrefslogtreecommitdiffstats
path: root/third_party/python/cbor2/docs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/python/cbor2/docs')
-rw-r--r--third_party/python/cbor2/docs/conf.py33
-rw-r--r--third_party/python/cbor2/docs/customizing.rst132
-rw-r--r--third_party/python/cbor2/docs/index.rst15
-rw-r--r--third_party/python/cbor2/docs/modules/decoder.rst5
-rw-r--r--third_party/python/cbor2/docs/modules/encoder.rst5
-rw-r--r--third_party/python/cbor2/docs/modules/types.rst5
-rw-r--r--third_party/python/cbor2/docs/usage.rst80
-rw-r--r--third_party/python/cbor2/docs/versionhistory.rst73
8 files changed, 348 insertions, 0 deletions
diff --git a/third_party/python/cbor2/docs/conf.py b/third_party/python/cbor2/docs/conf.py
new file mode 100644
index 0000000000..0ddeb0719e
--- /dev/null
+++ b/third_party/python/cbor2/docs/conf.py
@@ -0,0 +1,33 @@
+# coding: utf-8
+#!/usr/bin/env python
+import pkg_resources
+
+
+extensions = [
+ 'sphinx.ext.autodoc',
+ 'sphinx.ext.intersphinx'
+]
+
+templates_path = ['_templates']
+source_suffix = '.rst'
+master_doc = 'index'
+project = 'cbor2'
+author = u'Alex Grönholm'
+copyright = u'2016, ' + author
+
+v = pkg_resources.get_distribution(project).parsed_version
+version = v.base_version
+release = v.public
+
+language = None
+
+exclude_patterns = ['_build']
+pygments_style = 'sphinx'
+highlight_language = 'python'
+todo_include_todos = False
+
+html_theme = 'sphinx_rtd_theme'
+html_static_path = ['_static']
+htmlhelp_basename = project.replace('-', '') + 'doc'
+
+intersphinx_mapping = {'python': ('http://docs.python.org/', None)}
diff --git a/third_party/python/cbor2/docs/customizing.rst b/third_party/python/cbor2/docs/customizing.rst
new file mode 100644
index 0000000000..bf9b1b4540
--- /dev/null
+++ b/third_party/python/cbor2/docs/customizing.rst
@@ -0,0 +1,132 @@
+Customizing encoding and decoding
+=================================
+
+Both the encoder and decoder can be customized to support a wider range of types.
+
+On the encoder side, this is accomplished by passing a callback as the ``default`` constructor
+argument. This callback will receive an object that the encoder could not serialize on its own.
+The callback should then return a value that the encoder can serialize on its own, although the
+return value is allowed to contain objects that also require the encoder to use the callback, as
+long as it won't result in an infinite loop.
+
+On the decoder side, you have two options: ``tag_hook`` and ``object_hook``. The former is called
+by the decoder to process any semantic tags that have no predefined decoders. The latter is called
+for any newly decoded ``dict`` objects, and is mostly useful for implementing a JSON compatible
+custom type serialization scheme. Unless your requirements restrict you to JSON compatible types
+only, it is recommended to use ``tag_hook`` for this purpose.
+
+JSON compatibility
+------------------
+
+In certain applications, it may be desirable to limit the supported types to the same ones
+serializable as JSON: (unicode) string, integer, float, boolean, null, array and object (dict).
+This can be done by passing the ``json_compatible`` option to the encoder. When incompatible types
+are encountered, a :class:`~cbor2.encoder.CBOREncodeError` is then raised.
+
+For the decoder, there is no support for detecting incoming incompatible types yet.
+
+Using the CBOR tags for custom types
+------------------------------------
+
+The most common way to use ``default`` is to call :meth:`~cbor2.encoder.CBOREncoder.encode`
+to add a custom tag in the data stream, with the payload as the value::
+
+ class Point(object):
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def default_encoder(encoder, value):
+ # Tag number 4000 was chosen arbitrarily
+ encoder.encode(CBORTag(4000, [value.x, value.y]))
+
+The corresponding ``tag_hook`` would be::
+
+ def tag_hook(decoder, tag, shareable_index=None):
+ if tag.tag != 4000:
+ return tag
+
+ # tag.value is now the [x, y] list we serialized before
+ return Point(*tag.value)
+
+Using dicts to carry custom types
+---------------------------------
+
+The same could be done with ``object_hook``, except less efficiently::
+
+ def default_encoder(encoder, value):
+ encoder.encode(dict(typename='Point', x=value.x, y=value.y))
+
+ def object_hook(decoder, value):
+ if value.get('typename') != 'Point':
+ return value
+
+ return Point(value['x'], value['y'])
+
+You should make sure that whatever way you decide to use for telling apart your "specially marked"
+dicts from arbitrary data dicts won't mistake on for the other.
+
+Value sharing with custom types
+-------------------------------
+
+In order to properly encode and decode cyclic references with custom types, some special care has
+to be taken. Suppose you have a custom type as below, where every child object contains a reference
+to its parent and the parent contains a list of children::
+
+ from cbor2 import dumps, loads, shareable_encoder, CBORTag
+
+
+ class MyType(object):
+ def __init__(self, parent=None):
+ self.parent = parent
+ self.children = []
+ if parent:
+ self.parent.children.append(self)
+
+This would not normally be serializable, as it would lead to an endless loop (in the worst case)
+and raise some exception (in the best case). Now, enter CBOR's extension tags 28 and 29. These tags
+make it possible to add special markers into the data stream which can be later referenced and
+substituted with the object marked earlier.
+
+To do this, in ``default`` hooks used with the encoder you will need to use the
+:meth:`~cbor2.encoder.shareable_encoder` decorator on your ``default`` hook function. It will
+automatically automatically add the object to the shared values registry on the encoder and prevent
+it from being serialized twice (instead writing a reference to the data stream)::
+
+ @shareable_encoder
+ def default_encoder(encoder, value):
+ # The state has to be serialized separately so that the decoder would have a chance to
+ # create an empty instance before the shared value references are decoded
+ serialized_state = encoder.encode_to_bytes(value.__dict__)
+ encoder.encode(CBORTag(3000, serialized_state))
+
+On the decoder side, you will need to initialize an empty instance for shared value lookup before
+the object's state (which may contain references to it) is decoded.
+This is done with the :meth:`~cbor2.encoder.CBORDecoder.set_shareable` method::
+
+ def tag_hook(decoder, tag, shareable_index=None):
+ # Return all other tags as-is
+ if tag.tag != 3000:
+ return tag
+
+ # Create a raw instance before initializing its state to make it possible for cyclic
+ # references to work
+ instance = MyType.__new__(MyType)
+ decoder.set_shareable(shareable_index, instance)
+
+ # Separately decode the state of the new object and then apply it
+ state = decoder.decode_from_bytes(tag.value)
+ instance.__dict__.update(state)
+ return instance
+
+You could then verify that the cyclic references have been restored after deserialization::
+
+ parent = MyType()
+ child1 = MyType(parent)
+ child2 = MyType(parent)
+ serialized = dumps(parent, default=default_encoder, value_sharing=True)
+
+ new_parent = loads(serialized, tag_hook=tag_hook)
+ assert new_parent.children[0].parent is new_parent
+ assert new_parent.children[1].parent is new_parent
+
diff --git a/third_party/python/cbor2/docs/index.rst b/third_party/python/cbor2/docs/index.rst
new file mode 100644
index 0000000000..443c245d86
--- /dev/null
+++ b/third_party/python/cbor2/docs/index.rst
@@ -0,0 +1,15 @@
+.. include:: ../README.rst
+ :start-line: 7
+ :end-before: Project links
+
+Table of contents
+-----------------
+
+.. toctree::
+ :maxdepth: 2
+
+ usage
+ customizing
+ versionhistory
+
+* :ref:`API reference <modindex>`
diff --git a/third_party/python/cbor2/docs/modules/decoder.rst b/third_party/python/cbor2/docs/modules/decoder.rst
new file mode 100644
index 0000000000..c2c58fe9db
--- /dev/null
+++ b/third_party/python/cbor2/docs/modules/decoder.rst
@@ -0,0 +1,5 @@
+:mod:`cbor2.decoder`
+====================
+
+.. automodule:: cbor2.decoder
+ :members:
diff --git a/third_party/python/cbor2/docs/modules/encoder.rst b/third_party/python/cbor2/docs/modules/encoder.rst
new file mode 100644
index 0000000000..c4240eeaad
--- /dev/null
+++ b/third_party/python/cbor2/docs/modules/encoder.rst
@@ -0,0 +1,5 @@
+:mod:`cbor2.encoder`
+====================
+
+.. automodule:: cbor2.encoder
+ :members:
diff --git a/third_party/python/cbor2/docs/modules/types.rst b/third_party/python/cbor2/docs/modules/types.rst
new file mode 100644
index 0000000000..a6dedaa3e4
--- /dev/null
+++ b/third_party/python/cbor2/docs/modules/types.rst
@@ -0,0 +1,5 @@
+:mod:`cbor2.types`
+==================
+
+.. automodule:: cbor2.types
+ :members:
diff --git a/third_party/python/cbor2/docs/usage.rst b/third_party/python/cbor2/docs/usage.rst
new file mode 100644
index 0000000000..54b028ee53
--- /dev/null
+++ b/third_party/python/cbor2/docs/usage.rst
@@ -0,0 +1,80 @@
+Basic usage
+===========
+
+Serializing and deserializing with cbor2 is pretty straightforward::
+
+ from cbor2 import dumps, loads
+
+ # Serialize an object as a bytestring
+ data = dumps(['hello', 'world'])
+
+ # Deserialize a bytestring
+ obj = loads(data)
+
+ # Efficiently deserialize from a file
+ with open('input.cbor', 'rb') as fp:
+ obj = load(fp)
+
+ # Efficiently serialize an object to a file
+ with open('output.cbor', 'wb') as fp:
+ dump(obj, fp)
+
+Some data types, however, require extra considerations, as detailed below.
+
+String/bytes handling on Python 2
+---------------------------------
+
+The ``str`` type is encoded as binary on Python 2. If you want to encode strings as text on
+Python 2, use unicode strings instead.
+
+Date/time handling
+------------------
+
+The CBOR specification does not support naïve datetimes (that is, datetimes where ``tzinfo`` is
+missing). When the encoder encounters such a datetime, it needs to know which timezone it belongs
+to. To this end, you can specify a default timezone by passing a :class:`~datetime.tzinfo` instance
+to :func:`~cbor2.encoder.dump`/:func:`~cbor2.encoder.dumps` call as the ``timezone`` argument.
+Decoded datetimes are always timezone aware.
+
+By default, datetimes are serialized in a manner that retains their timezone offsets. You can
+optimize the data stream size by passing ``datetime_as_timestamp=False`` to
+:func:`~cbor2.encoder.dump`/:func:`~cbor2.encoder.dumps`, but this causes the timezone offset
+information to be lost.
+
+Cyclic (recursive) data structures
+----------------------------------
+
+If the encoder encounters a shareable object (ie. list or dict) that it has been before, it will
+by default raise :exc:`~cbor2.encoder.CBOREncodeError` indicating that a cyclic reference has been
+detected and value sharing was not enabled. CBOR has, however, an extension specification that
+allows the encoder to reference a previously encoded value without processing it again. This makes
+it possible to serialize such cyclic references, but value sharing has to be enabled by passing
+``value_sharing=True`` to :func:`~cbor2.encoder.dump`/:func:`~cbor2.encoder.dumps`.
+
+.. warning:: Support for value sharing is rare in other CBOR implementations, so think carefully
+ whether you want to enable it. It also causes some line overhead, as all potentially shareable
+ values must be tagged as such.
+
+Tag support
+-----------
+
+In addition to all standard CBOR tags, this library supports many extended tags:
+
+=== ======================================== ====================================================
+Tag Semantics Python type(s)
+=== ======================================== ====================================================
+0 Standard date/time string datetime.date / datetime.datetime
+1 Epoch-based date/time datetime.date / datetime.datetime
+2 Positive bignum int / long
+3 Negative bignum int / long
+4 Decimal fraction decimal.Decimal
+5 Bigfloat decimal.Decimal
+28 Mark shared value N/A
+29 Reference shared value N/A
+30 Rational number fractions.Fraction
+35 Regular expression ``_sre.SRE_Pattern`` (result of ``re.compile(...)``)
+36 MIME message email.message.Message
+37 Binary UUID uuid.UUID
+=== ======================================== ====================================================
+
+Arbitary tags can be represented with the :class:`~cbor2.types.CBORTag` class.
diff --git a/third_party/python/cbor2/docs/versionhistory.rst b/third_party/python/cbor2/docs/versionhistory.rst
new file mode 100644
index 0000000000..246e43bb83
--- /dev/null
+++ b/third_party/python/cbor2/docs/versionhistory.rst
@@ -0,0 +1,73 @@
+Version history
+===============
+
+This library adheres to `Semantic Versioning <http://semver.org/>`_.
+
+**4.0.1.** (2017-08-21)
+
+- Fixed silent truncation of decoded data if there are not enough bytes in the stream for an exact
+ read (``CBORDecodeError`` is now raised instead)
+
+**4.0.0** (2017-04-24)
+
+- **BACKWARD INCOMPATIBLE** Value sharing has been disabled by default, for better compatibility
+ with other implementations and better performance (since it is rarely needed)
+- **BACKWARD INCOMPATIBLE** Replaced the ``semantic_decoders`` decoder option with the ``tag_hook``
+ option
+- **BACKWARD INCOMPATIBLE** Replaced the ``encoders`` encoder option with the ``default`` option
+- **BACKWARD INCOMPATIBLE** Factored out the file object argument (``fp``) from all callbacks
+- **BACKWARD INCOMPATIBLE** The encoder no longer supports every imaginable type implementing the
+ ``Sequence`` or ``Map`` interface, as they turned out to be too broad
+- Added the ``object_hook`` option for decoding dicts into complex objects
+ (intended for situations where JSON compatibility is required and semantic tags cannot be used)
+- Added encoding and decoding of simple values (``CBORSimpleValue``)
+ (contributed by Jerry Lundström)
+- Replaced the decoder for bignums with a simpler and faster version (contributed by orent)
+- Made all relevant classes and functions available directly in the ``cbor2`` namespace
+- Added proper documentation
+
+**3.0.4** (2016-09-24)
+
+- Fixed TypeError when trying to encode extension types (regression introduced in 3.0.3)
+
+**3.0.3** (2016-09-23)
+
+- No changes, just re-releasing due to git tagging screw-up
+
+**3.0.2** (2016-09-23)
+
+- Fixed decoding failure for datetimes with microseconds (tag 0)
+
+**3.0.1** (2016-08-08)
+
+- Fixed error in the cyclic structure detection code that could mistake one container for
+ another, sometimes causing a bogus error about cyclic data structures where there was none
+
+**3.0.0** (2016-07-03)
+
+- **BACKWARD INCOMPATIBLE** Encoder callbacks now receive three arguments: the encoder instance,
+ the value to encode and a file-like object. The callback must must now either write directly to
+ the file-like object or call another encoder callback instead of returning an iterable.
+- **BACKWARD INCOMPATIBLE** Semantic decoder callbacks now receive four arguments: the decoder
+ instance, the primitive value, a file-like object and the shareable index for the decoded value.
+ Decoders that support value sharing must now set the raw value at the given index in
+ ``decoder.shareables``.
+- **BACKWARD INCOMPATIBLE** Removed support for iterative encoding (``CBOREncoder.encode()`` is no
+ longer a generator function and always returns ``None``)
+- Significantly improved performance (encoder ~30 % faster, decoder ~60 % faster)
+- Fixed serialization round-trip for ``undefined`` (simple type #23)
+- Added proper support for value sharing in callbacks
+
+**2.0.0** (2016-06-11)
+
+- **BACKWARD INCOMPATIBLE** Deserialize unknown tags as ``CBORTag`` objects so as not to lose
+ information
+- Fixed error messages coming from nested structures
+
+**1.1.0** (2016-06-10)
+
+- Fixed deserialization of cyclic structures
+
+**1.0.0** (2016-06-08)
+
+- Initial release