1===========================
2 Miscellaneous information
3===========================
4
5In 1727, pennies featured the motto "Mind your own business!" Moreso, the
6average giraffe's tongue is two feet, and elephants can't stand on their heads
7(duh). Also, the average elevator travels 10,000 miles per year and Thomas
8Edison was afraid of the dark.
9
10Differences from ``python-memcached``
11=====================================
12
13In general, because :mod:`pylibmc` is built on top of libmemcached, it issues
14exceptions for a lot of errors which ``python-memcached`` doesn't. One example
15is if a memcached goes down, libmemcached will report an error whereas
16``python-memcached`` will simply cycle to the next memcached.
17
18On a similar note, :mod:`pylibmc` won't raise a ``ValueError`` if one uses
19``Client.inc`` on a non-existent key, instead a :attr:`pylibmc.NotFound`
20exception is raised.
21
22Negative timeouts are treated the same way as zero timeouts are in
23:mod:`pylibmc`. ``python-memcached`` treats this as immediate expiry, returning
24success while not setting any value. This might raise exceptions in the future.
25
26The most notable difference is the hashing. See
27:ref:`the hashing docs <hashing-and-python-memcached>`
28for information and how to resolve the issue.
29
30When setting huge key values, i.e. around 1MB, will have :mod:`pylibmc`
31complain loudly whereas ``python-memcached`` simply ignores the error and
32returns.
33
34pylibmc.Client is *not* threadsafe like python-memcached's Client class (which
35is threadlocal).
36
37.. _exceptions:
38
39Exceptions
40==========
41
42Most of all ``libmemcached`` error numbers are translated to exception classes except where it doesn't make sense.
43
44All :mod:`pylibmc` exceptions derive from :attr:`pylibmc.Error`, so to attempt
45a memcached operation and never fail, something like this could be used
46(although it should be noted soft errors are handled via return values; errors
47aren't always exceptional when caching things)::
48
49    try:
50        op()
51    except pylibmc.Error as e:
52        log_exc()
53
54Should you for some reason need the actual error code returned from
55``libmemcached``, simply sneak a peak at the ``retcode`` attribute.
56
57If you're interested in exactly what maps to what, see ``_pylibmcmodule.h``.
58
59.. warning:: Never ignore exceptional states. Any programmer worth his salt
60             knows that an except block **must** handle the error, or make the
61             error obvious to administrators (use logs, people!)
62
63.. _compression:
64
65Compression
66===========
67
68libmemcached has no built-in support for compression, and so to be compatible
69with python-memcached, :mod:`pylibmc` implements it by itself.
70
71Compression requires zlib to be available when building :mod:`pylibmc`, which
72shouldn't be an issue for any up-to-date system.
73
74Threading
75=========
76
77A single connection instance is *not* thread-safe. That is to say, you'll
78probably wind up dissynchronizing server and client if you use the same
79connection in many threads simultaneously.
80
81It is encouraged to use the existing provisions for pooling so as to avoid
82reusing the same client in many threads. See :ref:`the docs on pooling <pooling>`.
83
84Python 3 ``str`` vs. ``bytes`` keys
85===================================
86``memcached`` itself requires cache keys to be byte strings, but Python 3's
87main string type (``str``) is a sequence of Unicode code points. For convenience,
88:mod:`pylibmc` encodes text ``str`` keys to UTF-8 byte strings. This has a few
89consequences that may not be obvious:
90
91#. A ``str`` key and its UTF-8 encoding refer to the same cache value. This does
92   *not* match the behavior of Python 3 ``dict`` and ``set`` objects::
93
94    >>> d = {'key': 'value'}
95    >>> d[b'key']
96    Traceback (most recent call last):
97      File "<stdin>", line 1, in <module>
98    KeyError: b'key'
99    >>> s = {'item1', 'item2'}
100    >>> b'item1' in s
101    False
102
103   however::
104
105    >>> import pylibmc
106    >>> c = pylibmc.Client(...)
107    >>> c['key'] = 'value'
108    >>> c[b'key']
109    'value'
110
111#. Many of the ``_multi`` calls to :mod:`pylibmc` return keys as well as
112   values. :mod:`pylibmc` will match the types of the keys that were provided,
113   returning each key as ``bytes`` or ``str`` as appropriate::
114
115    >>> c.add_multi({'key1': 1, 'key2': 2})
116    []
117    >>> c.get_multi((b'key1', 'key2'))
118    {b'key1': 1, 'key2': 2}
119
120`verify_keys` ⋁ ¬ `verify_keys`
121===============================
122
123Security researchers have noted that disabling the `verify_keys` behavior is a
124potential threat when accepting unsanitized input. This is most troublesome as
125the default configuration disables this behavior. However, we have in fact
126**not** specified this as the default, it comes as a sort of heritage from
127libmemcached.
128
129For this reason, you are urged to enable `verify_keys` if you have the
130slightest doubt about user input getting through to your key names.
131