pylibmc-1.6.3/0000755000175100001710000000000014302105267013757 5ustar runnerdocker00000000000000pylibmc-1.6.3/LICENSE0000644000175100001710000000272114302105266014765 0ustar runnerdocker00000000000000Copyright (c) 2008, Ludvig Ericson All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the author nor the names of the contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. pylibmc-1.6.3/MANIFEST.in0000644000175100001710000000050514302105266015514 0ustar runnerdocker00000000000000include README.rst LICENSE MANIFEST.in setup.py setup.cfg runtests.py include src/_pylibmcmodule.c src/_pylibmcmodule.h src/pylibmc-version.h recursive-include pylibmc *.py recursive-include tests *.py include docs/Makefile docs/make.bat docs/conf.py docs/*.svg recursive-include docs *.rst recursive-include docs/_themes * pylibmc-1.6.3/PKG-INFO0000644000175100001710000001066414302105267015063 0ustar runnerdocker00000000000000Metadata-Version: 1.1 Name: pylibmc Version: 1.6.3 Summary: Quick and small memcached client for Python Home-page: https://sendapatch.se/projects/pylibmc/ Author: Ludvig Ericson Author-email: ludvig@lericson.se License: 3-clause BSD Description: `pylibmc` is a Python client for `memcached `_ written in C. See `the documentation at sendapatch.se/projects/pylibmc/`__ for more information. __ http://sendapatch.se/projects/pylibmc/ .. image:: https://github.com/lericson/pylibmc/actions/workflows/ci.yml/badge.svg :target: https://github.com/lericson/pylibmc/actions/workflows/ci.yml New in version 1.6.0 ==================== Though no major feature overhauls have taken place, this release is partially incompatible with 1.5.0. This stems from the fact that python-memcached is now using a flag that pylibmc has been using for some years. python-memcached uses it for a different purpose, and an incompatible one. We deemed that it would be better to support this interoperability. The change also means that Unicode strings are now stored as UTF-8 rather than pickled, which may or may not result in a slight performance improvement for this type of data. We have also introduced a `pickle_protocol` behavior to enable seamless interoperability between Python 2.x and 3.x. Also, this release introduces a ManyLinux wheel, making installation a breeze on ManyLinux systems (which I suppose is many linuxes.) New in version 1.5.0 ==================== This release fixes critical memory leaks in common code paths introduced in 1.4.2. Also fixes a critical bug in a corner of the zlib inflation code, where prior memory errors would trigger a double free. Thank you to everybody involved in the making of this release, and especially `Eau de Web`__, without their contributions, this release and the bug fixes it contains wouldn't have been so expedient. __ http://www.eaudeweb.ro/ .. comment: 1.5.x should have been an extension to 1.4.x, therefore it's best to keep the 1.4.x release announcement below. New in version 1.4.0 ==================== Brace yourself, Python 3.x support has come! Thanks to everybody involved in this project; this release involves less authors but **a lot** more work per person. Thanks especially to Harvey Falcic for the work he put in, without which there wouldn't be any Python 3.x support. Also thanks to Sergey Pashinin for the initial stab at the problem. Other than that, we had miscellaneous bug fixes, testing improvements, and documentation updates. Last but not least I would like to ask for your support in this project, either by helping out with development, testing, documentation or anything at all; or simply by donating some `magic internet money`__ to the project's Bitcoin address `12dveKhqiJWCY8zXT4kaHdHELXPeGAUo9h`__. __ http://static.adzerk.net/Advertisers/5af77cf0094d4303bb308b955dd05992.jpg __ bitcoin:12dveKhqiJWCY8zXT4kaHdHELXPeGAUo9h License ======= Released under the BSD 3-clause license; see `LICENSE `_ for details. Maintainer ========== - Website: `sendapatch.se/ `_ - Github: `github.com/lericson `_ - IRC: ``lericson`` in ``#sendapatch`` on ``chat.freenode.net`` - E-mail: ``ludvig`` at ``sendapatch.se`` ------ .. image:: http://www.smbc-comics.com/comics/20110908.gif :target: http://www.smbc-comics.com/index.php?db=comics&id=2362 :align: center Platform: UNKNOWN Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3 :: Only pylibmc-1.6.3/README.rst0000644000175100001710000000616314302105266015453 0ustar runnerdocker00000000000000`pylibmc` is a Python client for `memcached `_ written in C. See `the documentation at sendapatch.se/projects/pylibmc/`__ for more information. __ http://sendapatch.se/projects/pylibmc/ .. image:: https://github.com/lericson/pylibmc/actions/workflows/ci.yml/badge.svg :target: https://github.com/lericson/pylibmc/actions/workflows/ci.yml New in version 1.6.0 ==================== Though no major feature overhauls have taken place, this release is partially incompatible with 1.5.0. This stems from the fact that python-memcached is now using a flag that pylibmc has been using for some years. python-memcached uses it for a different purpose, and an incompatible one. We deemed that it would be better to support this interoperability. The change also means that Unicode strings are now stored as UTF-8 rather than pickled, which may or may not result in a slight performance improvement for this type of data. We have also introduced a `pickle_protocol` behavior to enable seamless interoperability between Python 2.x and 3.x. Also, this release introduces a ManyLinux wheel, making installation a breeze on ManyLinux systems (which I suppose is many linuxes.) New in version 1.5.0 ==================== This release fixes critical memory leaks in common code paths introduced in 1.4.2. Also fixes a critical bug in a corner of the zlib inflation code, where prior memory errors would trigger a double free. Thank you to everybody involved in the making of this release, and especially `Eau de Web`__, without their contributions, this release and the bug fixes it contains wouldn't have been so expedient. __ http://www.eaudeweb.ro/ .. comment: 1.5.x should have been an extension to 1.4.x, therefore it's best to keep the 1.4.x release announcement below. New in version 1.4.0 ==================== Brace yourself, Python 3.x support has come! Thanks to everybody involved in this project; this release involves less authors but **a lot** more work per person. Thanks especially to Harvey Falcic for the work he put in, without which there wouldn't be any Python 3.x support. Also thanks to Sergey Pashinin for the initial stab at the problem. Other than that, we had miscellaneous bug fixes, testing improvements, and documentation updates. Last but not least I would like to ask for your support in this project, either by helping out with development, testing, documentation or anything at all; or simply by donating some `magic internet money`__ to the project's Bitcoin address `12dveKhqiJWCY8zXT4kaHdHELXPeGAUo9h`__. __ http://static.adzerk.net/Advertisers/5af77cf0094d4303bb308b955dd05992.jpg __ bitcoin:12dveKhqiJWCY8zXT4kaHdHELXPeGAUo9h License ======= Released under the BSD 3-clause license; see `LICENSE `_ for details. Maintainer ========== - Website: `sendapatch.se/ `_ - Github: `github.com/lericson `_ - IRC: ``lericson`` in ``#sendapatch`` on ``chat.freenode.net`` - E-mail: ``ludvig`` at ``sendapatch.se`` ------ .. image:: http://www.smbc-comics.com/comics/20110908.gif :target: http://www.smbc-comics.com/index.php?db=comics&id=2362 :align: center pylibmc-1.6.3/docs/0000755000175100001710000000000014302105267014707 5ustar runnerdocker00000000000000pylibmc-1.6.3/docs/Makefile0000644000175100001710000000675314302105266016361 0ustar runnerdocker00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: html clean dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pylibmc.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pylibmc.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/pylibmc" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pylibmc" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." make -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." clean: -rm -rf $(BUILDDIR)/* pylibmc-1.6.3/docs/_themes/0000755000175100001710000000000014302105267016333 5ustar runnerdocker00000000000000pylibmc-1.6.3/docs/_themes/sap/0000755000175100001710000000000014302105267017116 5ustar runnerdocker00000000000000pylibmc-1.6.3/docs/_themes/sap/layout.html0000644000175100001710000000013414302105266021316 0ustar runnerdocker00000000000000{% extends "classic/layout.html" %} {%- block relbar2 %}{% endblock %} pylibmc-1.6.3/docs/_themes/sap/static/0000755000175100001710000000000014302105267020405 5ustar runnerdocker00000000000000pylibmc-1.6.3/docs/_themes/sap/static/main.css_t0000644000175100001710000001311714302105266022370 0ustar runnerdocker00000000000000/* * default.css_t * ~~~~~~~~~~~~~ * * Sphinx stylesheet -- default theme. * * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @import url("classic.css"); /* -- page layout ----------------------------------------------------------- */ body { font-family: {{ theme_bodyfont }}; font-size: 100%; background: {{ theme_bgcolor }} url('http://sendapatch.se/bg.png'); color: #000; margin: 0; padding: 0; } div.document { margin: 1em auto; width: 45em; background-color: {{ theme_bgcolor }}; border: 1px solid {{ theme_contentboxcolor }}; } div.documentwrapper { float: left; width: 100%; } div.bodywrapper { margin: 0 0 0 230px; } div.body { background-color: {{ theme_contentbgcolor }}; color: {{ theme_textcolor }}; padding: 0 20px 30px 20px; } {%- if theme_rightsidebar|tobool %} div.bodywrapper { margin: 0 230px 0 0; } {%- endif %} div.footer { color: {{ theme_footertextcolor }}; width: 100%; padding: 9px 0 9px 0; text-align: center; font-size: 75%; } div.footer a { color: {{ theme_footertextcolor }}; text-decoration: underline; } div.related { background-color: {{ theme_relbarbgcolor }}; line-height: 30px; color: {{ theme_relbartextcolor }}; } div.related a { color: {{ theme_relbarlinkcolor }}; } div.sphinxsidebar { {%- if theme_stickysidebar|tobool %} top: 30px; bottom: 0; margin: 0; position: fixed; overflow: auto; height: auto; {%- endif %} {%- if theme_rightsidebar|tobool %} float: right; {%- if theme_stickysidebar|tobool %} right: 0; {%- endif %} {%- endif %} } {%- if theme_stickysidebar|tobool %} /* this is nice, but it it leads to hidden headings when jumping to an anchor */ /* div.related { position: fixed; } div.documentwrapper { margin-top: 30px; } */ {%- endif %} div.sphinxsidebar h3 { font-family: {{ theme_headfont }}; color: {{ theme_sidebartextcolor }}; font-size: 1.4em; font-weight: normal; margin: 0; padding: 0; } div.sphinxsidebar h3 a { color: {{ theme_sidebartextcolor }}; } div.sphinxsidebar h4 { font-family: {{ theme_headfont }}; color: {{ theme_sidebartextcolor }}; font-size: 1.3em; font-weight: normal; margin: 5px 0 0 0; padding: 0; } div.sphinxsidebar p { color: {{ theme_sidebartextcolor }}; } div.sphinxsidebar p.topless { margin: 5px 10px 10px 10px; } div.sphinxsidebar ul { margin: 10px; padding: 0; color: {{ theme_sidebartextcolor }}; } div.sphinxsidebar a { color: {{ theme_sidebarlinkcolor }}; } div.sphinxsidebar input { border: 1px solid {{ theme_sidebarlinkcolor }}; font-family: sans-serif; font-size: 1em; } {% if theme_collapsiblesidebar|tobool %} /* for collapsible sidebar */ div#sidebarbutton { background-color: {{ theme_sidebarbtncolor }}; } {% endif %} /* -- hyperlink styles ------------------------------------------------------ */ a { color: {{ theme_linkcolor }}; text-decoration: none; } a:visited { color: {{ theme_visitedlinkcolor }}; text-decoration: none; } a:hover { text-decoration: underline; } {% if theme_externalrefs|tobool %} a.external { text-decoration: none; border-bottom: 1px dashed {{ theme_linkcolor }}; } a.external:hover { text-decoration: none; border-bottom: none; } a.external:visited { text-decoration: none; border-bottom: 1px dashed {{ theme_visitedlinkcolor }}; } {% endif %} /* -- body styles ----------------------------------------------------------- */ div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 { font-family: {{ theme_headfont }}; background-color: {{ theme_headbgcolor }}; font-weight: normal; color: {{ theme_headtextcolor }}; border-bottom: 1px solid {{ theme_contentboxcolor }}; margin: 20px -20px 10px -20px; padding: 3px 0 3px 10px; } div.body h1 { margin-top: 0; font-size: 200%; } div.body h2 { font-size: 160%; } div.body h3 { font-size: 140%; } div.body h4 { font-size: 120%; } div.body h5 { font-size: 110%; } div.body h6 { font-size: 100%; } a.headerlink { color: {{ theme_headlinkcolor }}; font-size: 0.8em; padding: 0 4px 0 4px; text-decoration: none; } a.headerlink:hover { background-color: {{ theme_headlinkcolor }}; color: white; } div.body p, div.body dd, div.body li { text-align: justify; line-height: 130%; } div.admonition p.admonition-title + p { display: inline; } div.admonition p { margin-bottom: 5px; } div.admonition pre { margin-bottom: 5px; } div.admonition ul, div.admonition ol { margin-bottom: 5px; } div.note, div.seealso { background-color: transparent; border: 1px solid {{ theme_contentboxcolor }}; } div.topic { background-color: #eee; } div.warning { background-color: #ffe4e4; border: 1px solid #f66; } p.admonition-title { display: inline; } p.admonition-title:after { content: ":"; } pre { padding: 5px; background-color: {{ theme_codebgcolor }}; color: {{ theme_codetextcolor }}; line-height: 120%; border: 1px solid #ac9; border-left: none; border-right: none; } tt { background-color: #ecf0f3; padding: 0 1px 0 1px; font-size: 0.95em; } th { background-color: transparent; } .warning tt { background: #efc2c2; } .note tt { background: #d6d6d6; } .viewcode-back { font-family: {{ theme_bodyfont }}; } div.viewcode-block:target { background-color: #f4debf; border-top: 1px solid #ac9; border-bottom: 1px solid #ac9; } pylibmc-1.6.3/docs/_themes/sap/theme.conf0000644000175100001710000000137314302105266021072 0ustar runnerdocker00000000000000[theme] inherit = classic stylesheet = main.css pygments_style = sphinx [options] rightsidebar = false stickysidebar = false collapsiblesidebar = false externalrefs = false nosidebar = true bgcolor = #fefefe contentbgcolor = #efefef contentboxcolor = #c0c0c0 footertextcolor = #2e2e2e sidebarbtncolor = #3c6e83 sidebartextcolor = #ffffff sidebarlinkcolor = #98dbcc relbarbgcolor = #133f52 relbartextcolor = #ffffff relbarlinkcolor = #ffffff textcolor = #000000 headbgcolor = #f2f2f2 headtextcolor = #20435c headlinkcolor = #c60f0f linkcolor = #355f7c visitedlinkcolor = #355f7c codebgcolor = #eeffcc codetextcolor = #333333 bodyfont = 'Helvetica', Arial, sans-serif headfont = 'Helvetica', Arial, sans-serif pylibmc-1.6.3/docs/behaviors.rst0000644000175100001710000002144514302105266017430 0ustar runnerdocker00000000000000.. _behaviors: =========== Behaviors =========== libmemcached is a lot more flexible than python-memcached, and has provisions for configuring so-called *behaviors*. :mod:`pylibmc` wraps these in a Python interface. Not all of the available behaviors make sense for Python, or are hard to make use of, and as such some behaviors have been intentionally hidden or exposed in some other way (UDP and the binary protocol are examples of this.) Generally, a behavior's value should be an integer value. The exceptions are hashing and distribution, which :mod:`pylibmc` translates with the C constants' string equivalents, for readability. Other than that, the behaviors are more or less one to one mappings of libmemcached behavior constants. .. _hash: ``"hash"`` Specifies the default hashing algorithm for keys. See Hashing_ for more information and possible values. .. _distribution: ``"distribution"`` Specifies different means of distributing values to servers. See Distribution_ for more information and possible values. .. _ketama: ``"ketama"`` Setting this behavior to ``True`` is a shortcut for setting ``"hash"`` to ``"md5"`` and ``"distribution"`` to ``"consistent ketama"``. .. _ketama_weighted: ``"ketama_weighted"`` Exactly like the ``"ketama"`` behavior, but also enables the weighting support. .. _ketama_hash: ``"ketama_hash"`` Sets the hashing algorithm for host mapping on continuum. Possible values include those for the ``"hash"`` behavior. .. _buffer_requests: ``"buffer_requests"`` Enabling buffered I/O causes commands to "buffer" instead of being sent. Any action that gets data causes this buffer to be be sent to the remote connection. Quiting the connection or closing down the connection will also cause the buffered data to be pushed to the remote connection. .. _no_block: ``"no_block"`` Enables asychronous I/O. This is the fastest transport available for storage functions. .. _tcp_nodelay: ``"tcp_nodelay"`` Setting this behavior will enable the ``TCP_NODELAY`` socket option, which disables Nagle's algorithm. This obviously only makes sense for TCP connections. .. _cas: ``"cas"`` Enables support for CAS operations. .. _verify_keys: ``"verify_keys"`` Setting this behavior will test if the keys for validity before sending to memcached. .. _connect_timeout: ``"connect_timeout"`` In non-blocking mode, this specifies the timeout of socket connection in milliseconds. .. _receive_timeout: ``"receive_timeout"`` "This sets the microsecond behavior of the socket against the SO_RCVTIMEO flag. In cases where you cannot use non-blocking IO this will allow you to still have timeouts on the reading of data." .. _send_timeout: ``"send_timeout"`` "This sets the microsecond behavior of the socket against the SO_SNDTIMEO flag. In cases where you cannot use non-blocking IO this will allow you to still have timeouts on the sending of data." .. _num_replicas: ``"num_replicas"`` Poor man's high-availability solution. Specifies numbers of replicas that should be made for a given item, on different servers. "[Replication] does not dedicate certain memcached servers to store the replicas in, but instead it will store the replicas together with all of the other objects (on the 'n' next servers specified in your server list)." .. _dead_timeout: ``"dead_timeout"`` Once a server has been marked dead, wait this amount of time (in seconds) before checking to see if the server is alive again. .. _remove_failed: ``"remove_failed"`` If set, a server will be removed from the server list after this many operations on it in a row have failed. See the section on Failover_. .. _failure_limit: ``"failure_limit"`` : deprecated Use ``"remove_failed"`` if at all possible, which has the same meaning but uses newer behaviour. If set, a server will be removed from the server list after this many operations on it in a row have failed. .. _auto_eject: ``"auto_eject"`` : deprecated Use ``"remove_failed"`` if at all possible. With this behavior set, hosts which have been disabled will be removed from the list of servers after ``"failure_limit"``. Hashing ------- Basically, the hasher decides how a key is mapped to a specific memcached server. The available hashers are: * ``"default"`` - libmemcached's home-grown hasher * ``"md5"`` - MD5 * ``"crc"`` - CRC32 * ``"fnv1_64"`` - 64-bit FNV-1_ * ``"fnv1a_64"`` - 64-bit FNV-1a * ``"fnv1_32"`` - 32-bit FNV-1 * ``"fnv1a_32"`` - 32-bit FNV-1a * ``"murmur"`` - MurmurHash_ If :mod:`pylibmc` was built against a libmemcached using ``--enable-hash_hsieh``, you can also use ``"hsieh"``. .. _hashing-and-python-memcached: Hashing and python-memcached ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ python-memcached up until version 1.45 used a CRC32-based hashing algorithm not reproducible by libmemcached. You can change the hasher for python-memcached using the cmemcache_hash_ module, which will make it not only compatible with cmemcache_, but also the ``"crc"`` hasher in libmemcached. python-memcached 1.45 and later incorporated ``cmemcache_hash`` as its default hasher, and so will interoperate with libmemcached provided the libmemcached clients are told to use the CRC32-style hasher. This can be done in :mod:`pylibmc` as follows:: >>> mc.behaviors["hash"] = "crc" .. _FNV-1: http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash .. _MurmurHash: http://en.wikipedia.org/wiki/MurmurHash .. _cmemcache_hash: http://pypi.python.org/pypi/cmemcache_hash .. _cmemcache: http://gijsbert.org/cmemcache/ .. _hsieh: http://www.azillionmonkeys.com/qed/hash.html Distribution ------------ When using multiple servers, there are a few takes on how to choose a server from the set of specified servers. The default method is ``"modula"``, which is what most implementations use. You can enable consistent hashing by setting distribution to ``"consistent"``. Modula-based distribution is very simple. It works by taking the hash value, modulo the length of the server list. For example, consider the key ``"foo"`` under the ``"crc"`` hasher:: >>> servers = ["a", "b", "c"] >>> crc32_hash(key) 3187 >>> 3187 % len(servers) 1 >>> servers[1] 'b' However, if one was to add a server or remove a server, every key would be displaced by one - in effect, changing your server list would more or less reset the cache. Consistent hashing solves this at the price of a more costly key-to-server lookup function, `last.fm's RJ explains how it works`__. __ http://www.last.fm/user/RJ/journal/2007/04/10/rz_libketama_-_a_consistent_hashing_algo_for_memcache_clients Failover -------- Most people desire the classical "I don't really care" type of failover support: if a server goes down, just use another one. This case is supported, but not by default. As explained above, the default distribution mechanism is not very smart, and libmemcached doesn't support any meaningful failover for it. If a server goes down, it stays down, and all of its allotted keys will simply fail. The recommended failover behaviors is for that reason:: mc.behaviors['ketama'] = True mc.behaviors['remove_failed'] = 1 mc.behaviors['retry_timeout'] = 1 mc.behaviors['dead_timeout'] = 60 This will enable ketama hashing, and remove failed servers from rotation on their first failure, and retry them once every minute. It is the most robust configuration. To fully understand the failover state machine, peruse the following graph: .. image:: failover.svg While it might seem daunting at first, a closer examination will bring clarity to this picture. When a server connection fails, the server is marked as temporarily failed. This state is exited either by ``retry_timeout`` expiring, in which case the connection is retried, or, if ``remove_failed`` connection attempts have been made. When a server runs out of retries, it is marked dead. This removes it from rotation. However, **only** the ``ketama`` distribution actually removes servers. .. note:: There used to be two behaviors called ``failure_limit`` and ``auto_eject``; these still exist, but their interaction with the state machine is unclear, and should be avoided. ``remove_failed`` acts as a combination of the two. Non-libmemcached Behaviors -------------------------- It wouldn't make sense to have multiple avenues of configuration, and so whenever possible, pylibmc tries to co-opt the behaviors dictionary for configuration of strictly pylibmc-level things. These are described below. .. _pickle_protocol: ``"pickle_protocol"`` Specifies the default pickling protocol. This is by default set to -1, which means the pickle module will use the latest protocol it understands. This is an issue for interoperability, and so for example to work between Python 2 and 3, set this explicitly to 2 or whatever you prefer. pylibmc-1.6.3/docs/changelog.rst0000644000175100001710000001447114302105266017376 0ustar runnerdocker00000000000000Change Log ========== New in version 1.6.0 -------------------- Though no major feature overhauls have taken place, this release is partially incompatible with 1.5.0. This stems from the fact that python-memcached is now using a flag that pylibmc has been using for some years. python-memcached uses it for a different purpose, and an incompatible one. We deemed that it would be better to support this interoperability. The change also means that Unicode strings are now stored as UTF-8 rather than pickled, which may or may not result in a slight performance improvement for this type of data. We have also introduced a `pickle_protocol` behavior to enable seamless interoperability between Python 2.x and 3.x. Also, this release introduces a ManyLinux wheel, making installation a breeze on ManyLinux systems (which I suppose is many linuxes.) New in version 1.5.0 -------------------- This release fixes critical memory leaks in common code paths introduced in 1.4.2. Also fixes a critical bug in a corner of the zlib inflation code, where prior memory errors would trigger a double free. Thank you to everybody involved in the making of this release, and especially `Eau de Web`__, without their contributions, this release and the bug fixes it contains wouldn't have been so expedient. __ http://www.eaudeweb.ro/ New in version 1.4.0 -------------------- Brace yourself, Python 3.x support has come! Thanks to everybody involved in this project; this release involves less authors but **a lot** more work per person. Thanks especially to Harvey Falcic for the work he put in, without which there wouldn't be any Python 3.x support. Also thanks to Sergey Pashinin for the initial stab at the problem. Other than that, we had miscellaneous bug fixes, testing improvements, and documentation updates. Last but not least I would like to ask for your support in this project, either by helping out with development, testing, documentation or anything at all; or simply by donating some `magic internet money`__ to the project's Bitcoin address `12dveKhqiJWCY8zXT4kaHdHELXPeGAUo9h`__ __ http://static.adzerk.net/Advertisers/5af77cf0094d4303bb308b955dd05992.jpg __ bitcoin:12dveKhqiJWCY8zXT4kaHdHELXPeGAUo9h New in version 1.3.0 -------------------- Because there ain't nothing better than releasing software in the spring time. Lots of improvements have come about in just about every corner of the library, thanks to *eighteen different authors* over almost *20 pull requests*. Amazing. - Added touch support - Added compress_level - Added weighted distribution - Added automated benchmarking utility - Added Travis CI and build status - Added behavior dead_timeout - Added behaviors tcp_keepalive - Added behavior callback_prefix_key - Lots of bug tuning, fixes, tests, and documentation Lastly, thanks in particular to the authors of this release: Abramowitz, Baklanov, Bergström, Borisov, Branson, Brown, Ericson, Hansche, Hlodversson, King, Kowalak, McFague, Moura, Noguchi, Shurter, Williams and Wong. New in version 1.2.0 -------------------- This release is for the people behind `reddit.com`__, for helping push development forward. Keep doing your thing. __ http://code.reddit.com/ - `semver.org`__ versioning scheme - Fixed GIL issues - Added CAS support (ketralnis) - Added SASL authentication (Remoun) - Added more detail to errors (spladug) - Added mapping-like behavior for clients - Fixed build errors on Mac OS X - Moved to nose__ for testing - Added ``auto_eject`` behavior - Added ``num_replicas`` behavior - Added ``remove_failed`` behavior - Removed ``cache_lookups`` behavior - Improved repr of clients (noah256) - Improved IPv6 support (JshWright) - Improved pooling behavior so it doesn't cause lock-ups - Improved tests and testing foundation - Improved documentation and structure - Internalized Sphinx documentation - Bunch of other stuff __ http://semver.org/ __ http://somethingaboutorange.com/mrl/projects/nose/ New in version 1.1 ------------------ - Removed deprecated space-based behavior names. - Acquire and release the GIL properly, thanks ketralnis__ - Add support for ``libmemcached 0.40`` - Included a more useful command-line interface - Fixed handling of NUL-byte keys in ``get_multi`` in binary protocol - Fixed some valgrind-reported memory warnings - Fixed bogus usage of time argument for delete. - 1.1.1: Fixed tests under Python 2.5 __ http://www.ketralnis.com/ New in version 1.0 ------------------ - Lots of documentation fixes and other nice things like that. - Nailed what appears to be the last outstanding memory leak. - Explicitly require libmemcached 0.32 or newer. New in version 0.9 ------------------ - Added a ``get_stats`` method, which behaves exactly like `python-memcached`'s equivalent. - Gives the empty string for empty memcached values like `python-memcached` does. - Added exceptions for most `libmemcached` return codes. - Fixed an issue with ``Client.behaviors.update``. New in version 0.8 ------------------ - Pooling helpers are now available. See ``pooling.rst`` in the distribution. - The binary protocol is now properly exposed, simply pass ``binary=True`` to the constructor and there you go. - Call signatures now match `libmemcached` 0.32, but should work with older versions. Remember to run the tests! New in version 0.7 ------------------ - Restructured some of the code, which should yield better performance (if not for that, it reads better.) - Fixed some memory leaks. - Integrated changes from `amix.dk`, which should make pylibmc work under Snow Leopard. - Add support for the boolean datatype. - Improved test-runner -- now tests ``build/lib.*/_pylibmc.so`` if available, and reports some version information. - Support for x86_64 should now work completely. - Builds with Python 2.4, tests run fine, but not officially supported. - Fixed critical bugs in behavior manipulation. New in version 0.6 ------------------ - Added compatibility with `libmemcached` 0.26, WRT error return codes. - Added `flush_all` and `disconnect_all` methods. - Now using the latest pickling protocol. New in version 0.5 ------------------ - Fixed lots of memory leaks, and added support for `libmemcached` 0.23. - Also made the code tighter in terms of compiler pedantics. New in version 0.4 ------------------ - Renamed the C module to `_pylibmc`, and added lots of `libmemcached` constants to it, as well as implemented behaviors. pylibmc-1.6.3/docs/coders.rst0000644000175100001710000000320014302105266016712 0ustar runnerdocker00000000000000The List of Honored People ========================== * Marc Abramowitz * Anton Baklanov * Johan Bergström * Nikola Borisov * Rick Branson * Otto Bretz * Misha Brukman * James Brown * Adam Chainz * Mika Eloranta * Ludvig Ericson * Harvey Falcic * Michael Fladischer * Marius Gedminas * Joe Hansche * Keli Hlodversson * ketralnis * Paweł Kowalak * Hiroki Kumzaki * Patrick Lewis * Shivaram Lingamneni * Andrew McFague * Remoun Metyas * Ed Morley * Rudá Moura * Muneyuki Noguchi * Sergey Pashinin * Michael Schurter * Radek Senfeld * Noah Silas * Jari Sukanen * John Watson * John Whitlock * Neil Williams * Josh Wright * Kelly Wong Thanks to `Blogg Esse AB`__ and `Send a Patch Jonken AB`__ for their support in this open-source adventure, without these two companies this wouldn't have happened. __ http://blogg.se/ __ http://sendapatch.se/ pylibmc-1.6.3/docs/conf.py0000644000175100001710000001643514302105266016216 0ustar runnerdocker00000000000000# # pylibmc documentation build configuration file, created by # sphinx-quickstart on Mon Jun 13 13:53:22 2011. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os # Find dev-mode pylibmc pylibmc_dir = os.environ.get("PYLIBMC_DIR") if not pylibmc_dir: raise RuntimeError("please set PYLIBMC_DIR") elif not os.path.exists(pylibmc_dir): raise RuntimeError(f"PYLIBMC_DIR {pylibmc_dir!r} does not exist") elif not os.path.isdir(pylibmc_dir): raise RuntimeError(f"PYLIBMC_DIR {pylibmc_dir!r} is not a directory") else: sys.path.insert(0, pylibmc_dir) import _pylibmc # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. needs_sphinx = '1.3' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ["sphinx.ext.autodoc"] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = 'pylibmc' copyright = '2018, Ludvig Ericson' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = _pylibmc.__version__ # The full version, including alpha/beta/rc tags. release = version print(_pylibmc.__file__) print(project, release) # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'sap' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. html_theme_path = ["_themes"] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'pylibmcdoc' # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'pylibmc.tex', 'pylibmc Documentation', 'Ludvig Ericson', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'pylibmc', 'pylibmc Documentation', ['Ludvig Ericson'], 1) ] pylibmc-1.6.3/docs/failover.svg0000644000175100001710000002106314302105266017240 0ustar runnerdocker00000000000000 G init new client initconnect first connect init->initconnect on get/set connerr connection error initconnect->connerr connected connected initconnect->connected timeout server has temporarily failed connerr->timeout server_dead server is marked dead timeout->server_dead after remove_failed connection attempts new new timeout->new after retry_timeout (or dead_timeout) removed server removed from rotation server_dead->removed added server added back into rotation removed->added after dead_timeout, make a single connection attempt added->timeout new->connected on get/set connected->timeout connected->connected pylibmc-1.6.3/docs/index.rst0000644000175100001710000000631014302105266016547 0ustar runnerdocker00000000000000============================================== :mod:`pylibmc` - Python client for memcached ============================================== .. currentmodule:: pylibmc :mod:`pylibmc` is a client in Python for memcached_. It is a wrapper around TangentOrg_'s libmemcached_ library. The interface is intentionally made as close to python-memcached_ as possible, so that applications can drop-in replace it. :mod:`pylibmc` leverages among other things configurable behaviors, data pickling, data compression, battle-tested GIL retention, consistent distribution, and the binary memcached protocol. .. _TangentOrg: http://tangent.org/ .. _memcached: http://memcached.org/ .. _libmemcached: http://libmemcached.org/libMemcached.html .. _python-memcached: http://www.tummy.com/Community/software/python-memcached/ Example usage ============= Create a memcached connection and configure it:: >>> import pylibmc >>> mc = pylibmc.Client(["127.0.0.1"], binary=True, ... behaviors={"tcp_nodelay": True, ... "ketama": True}) .. hint:: In earlier versions ``behaviors`` was no keyword argument, only an attribute. To safe-guard version compatibility use ``mc.behaviors = {...}`` Basic memcached operations can be accomplished with the mapping interface:: >>> mc["some_key"] = "Some value" >>> mc["some_key"] 'Some value' >>> del mc["some_key"] >>> "some_key" in mc False "Classic" style memcached operations allow for more control and clarity:: >>> mc.set("some_key", "Some value") True >>> value = mc.get("some_key") >>> value 'Some value' >>> mc.set("another_key", 3) True >>> mc.delete("another_key") True Automatic pickling of complex Python types:: >>> mc.set("complex_plane=awesome", 4+3j) True >>> mc.get("complex_plane=awesome") (4+3j) >>> import fractions >>> mc.set("structured", {"a": ("b", "c"), ... "a2": fractions.Fraction(1, 3)}) True >>> mc.get("structured") {'a': ('b', 'c'), 'a2': Fraction(1, 3)} Atomic memcached-side increments and decrements:: >>> mc.set("key", "1") # str or int is fine True >>> mc.incr("key") 2L >>> mc.decr("key") 1L Batch operations lessen GIL contention and thus I/O is faster:: >>> mc.get_multi(["key", "another_key"]) {'key': '1'} >>> mc.set_multi({"cats": ["on acid", "furry"], "dogs": True}) [] >>> mc.get_multi(["cats", "dogs"]) {'cats': ['on acid', 'furry'], 'dogs': True} >>> mc.delete_multi(["cats", "dogs", "nonextant"]) False Further Reading =============== .. toctree:: :maxdepth: 2 changelog install reference pooling behaviors misc coders Links and resources =================== * sendapatch.se: `sendapatch.se/`__ * GitHub: `github.com/lericson/pylibmc`__ * PyPI: `pypi.python.org/pypi/pylibmc`__ * libmemcached: `tangent.org/552/libmemcached.html`__ * memcached: `memcached.org/`__ * BitCoin fund: `12dveKhqiJWCY8zXT4kaHdHELXPeGAUo9h`__ __ http://sendapatch.se/ __ http://github.com/lericson/pylibmc __ http://pypi.python.org/pypi/pylibmc __ libmemcached_ __ http://memcached.org/ __ bitcoin:12dveKhqiJWCY8zXT4kaHdHELXPeGAUo9h pylibmc-1.6.3/docs/install.rst0000644000175100001710000000203214302105266017103 0ustar runnerdocker00000000000000============ Installing ============ Requirements ============ * Python 3.6+ * libmemcached 1.0.8 or later (latest tested is 1.0.18) * zlib (required for compression support) * libsasl2 (required for authentication support) Building ======== Like any Python package, use ``setup.py``:: $ python setup.py install --with-libmemcached=/opt/local You only need to specify ``--with-libmemcached`` if libmemcached is not available on your C compiler's include and library path. This is the case if you use MacPorts or something like that. So for example, if one were to use MacPorts to install libmemcached, your libmemcached would end up in ``/opt/local``, hence ``--with-libmemcached=/opt/local``. Using ``pip`` you achieve the same thing as follows:: pip install pylibmc --install-option="--with-libmemcached=/opt/local" Note that `/usr/local` is typically on the library search path. If it is not, you'd probably want to fix that instead. Homebrew and MacOS ------------------ brew install libmemcached pip install pylibmc pylibmc-1.6.3/docs/make.bat0000644000175100001710000001064114302105266016315 0ustar runnerdocker00000000000000@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. changes to make an overview over all changed/added/deprecated items echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\pylibmc.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\pylibmc.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) :end pylibmc-1.6.3/docs/misc.rst0000644000175100001710000001135714302105266016402 0ustar runnerdocker00000000000000=========================== Miscellaneous information =========================== In 1727, pennies featured the motto "Mind your own business!" Moreso, the average giraffe's tongue is two feet, and elephants can't stand on their heads (duh). Also, the average elevator travels 10,000 miles per year and Thomas Edison was afraid of the dark. Differences from ``python-memcached`` ===================================== In general, because :mod:`pylibmc` is built on top of libmemcached, it issues exceptions for a lot of errors which ``python-memcached`` doesn't. One example is if a memcached goes down, libmemcached will report an error whereas ``python-memcached`` will simply cycle to the next memcached. On a similar note, :mod:`pylibmc` won't raise a ``ValueError`` if one uses ``Client.inc`` on a non-existent key, instead a :attr:`pylibmc.NotFound` exception is raised. Negative timeouts are treated the same way as zero timeouts are in :mod:`pylibmc`. ``python-memcached`` treats this as immediate expiry, returning success while not setting any value. This might raise exceptions in the future. The most notable difference is the hashing. See :ref:`the hashing docs ` for information and how to resolve the issue. When setting huge key values, i.e. around 1MB, will have :mod:`pylibmc` complain loudly whereas ``python-memcached`` simply ignores the error and returns. pylibmc.Client is *not* threadsafe like python-memcached's Client class (which is threadlocal). .. _exceptions: Exceptions ========== Most of all ``libmemcached`` error numbers are translated to exception classes except where it doesn't make sense. All :mod:`pylibmc` exceptions derive from :attr:`pylibmc.Error`, so to attempt a memcached operation and never fail, something like this could be used (although it should be noted soft errors are handled via return values; errors aren't always exceptional when caching things):: try: op() except pylibmc.Error as e: log_exc() Should you for some reason need the actual error code returned from ``libmemcached``, simply sneak a peak at the ``retcode`` attribute. If you're interested in exactly what maps to what, see ``_pylibmcmodule.h``. .. warning:: Never ignore exceptional states. Any programmer worth his salt knows that an except block **must** handle the error, or make the error obvious to administrators (use logs, people!) .. _compression: Compression =========== libmemcached has no built-in support for compression, and so to be compatible with python-memcached, :mod:`pylibmc` implements it by itself. Compression requires zlib to be available when building :mod:`pylibmc`, which shouldn't be an issue for any up-to-date system. Threading ========= A single connection instance is *not* thread-safe. That is to say, you'll probably wind up dissynchronizing server and client if you use the same connection in many threads simultaneously. It is encouraged to use the existing provisions for pooling so as to avoid reusing the same client in many threads. See :ref:`the docs on pooling `. Python 3 ``str`` vs. ``bytes`` keys =================================== ``memcached`` itself requires cache keys to be byte strings, but Python 3's main string type (``str``) is a sequence of Unicode code points. For convenience, :mod:`pylibmc` encodes text ``str`` keys to UTF-8 byte strings. This has a few consequences that may not be obvious: #. A ``str`` key and its UTF-8 encoding refer to the same cache value. This does *not* match the behavior of Python 3 ``dict`` and ``set`` objects:: >>> d = {'key': 'value'} >>> d[b'key'] Traceback (most recent call last): File "", line 1, in KeyError: b'key' >>> s = {'item1', 'item2'} >>> b'item1' in s False however:: >>> import pylibmc >>> c = pylibmc.Client(...) >>> c['key'] = 'value' >>> c[b'key'] 'value' #. Many of the ``_multi`` calls to :mod:`pylibmc` return keys as well as values. :mod:`pylibmc` will match the types of the keys that were provided, returning each key as ``bytes`` or ``str`` as appropriate:: >>> c.add_multi({'key1': 1, 'key2': 2}) [] >>> c.get_multi((b'key1', 'key2')) {b'key1': 1, 'key2': 2} `verify_keys` ⋁ ¬ `verify_keys` =============================== Security researchers have noted that disabling the `verify_keys` behavior is a potential threat when accepting unsanitized input. This is most troublesome as the default configuration disables this behavior. However, we have in fact **not** specified this as the default, it comes as a sort of heritage from libmemcached. For this reason, you are urged to enable `verify_keys` if you have the slightest doubt about user input getting through to your key names. pylibmc-1.6.3/docs/pooling.rst0000644000175100001710000000761714302105266017122 0ustar runnerdocker00000000000000.. currentmodule:: pylibmc.pools .. _pooling: ========= Pooling ========= :Author: Ludvig Ericson :See also: `Pooling with pylibmc`__ (this document, first revision) :See also: `Pooling with pylibmc pt. 2`__ (follow-up) __ http://lericson.blogg.se/code/2009/september/draft-sept-20-2009.html __ http://lericson.blogg.se/code/2009/september/pooling-with-pylibmc-pt-2.html .. note:: This was originally a blog post. Edited and provided here for your convenience. I was discussing how to implement pooling for :mod:`pylibmc` when I realized what `libmemcachedutil`'s pooling is - or rather, what it isn't. It's not a magical solution for concurrently doing anything at all, it's not anything like that -- it just helps you with thread-safety. In Python, however, we've got the global interpreter lock, the GIL. This lock must always be held by the thread that is dealing with anything Python. The Python interpreter itself isn't thread-safe, or rather, it is with the GIL. This means that whenever Python code is running, you'll be sure to have exclusive access to all of Python's memory (unless something is misbehaving.) In turn, this means that the usecase for using `libmemcachedutil` in a Python library is rather slim. An example with Werkzeug ======================== This is a Werkzeug-based WSGI application which would be run in multiple threads concurrently and still not have issues with races: .. code-block:: python # Configuration n_threads = 12 mc_addrs = "10.0.1.1", "10.0.1.2", "10.0.1.3" mc_pool_size = n_threads # Application import pylibmc from contextlib import contextmanager from pprint import pformat from werkzeug.wrappers import Request, Response from werkzeug.exceptions import NotFound class ClientPool(list): @contextmanager def reserve(self): mc = self.pop() try: yield mc finally: self.append(mc) mc = pylibmc.Client(mc_addrs) mc_pool = ClientPool(mc.clone() for i in xrange(mc_pool_size)) @Request.application def my_app(request): with mc_pool.reserve() as mc: key = request.path[1:].encode("ascii") val = mc.get(key) if not val: return NotFound(key) return Response(pformat(val)) if __name__ == "__main__": from werkzeug.serving import run_simple run_simple("0.0.0.0", 5050, my_app) It's fully-functional example of how one could implement pooling with :mod:`pylibmc`, and very much so in the same way that people do with `libmemcachedutil`. Paste it into a script file, it runs out of the box. FIFO-like pooling ================= The aforementioned type of pool is already implemented in :mod:`pylibmc` as :class:`pylibmc.ClientPool`, with a couple of other bells & whistles as well as tests (hint: don't implement it yourself.) Its documentation speaks for itself: .. autoclass:: pylibmc.ClientPool .. automethod:: fill .. automethod:: reserve The use is identical to what was demonstrated above, apart from initialization, that would look like this: .. code-block:: python mc = pylibmc.Client(mc_addrs) mc_pool = pylibmc.ClientPool(mc, mc_pool_size) Thread-mapped pooling ===================== Another possibility is to have a data structure that remembers the thread name (i.e. key it by thread ID or so.) Each thread would reserve its client in the dict on each request. If none exists, it would clone a master instance. Again, the documentation: .. autoclass:: pylibmc.ThreadMappedPool .. automethod:: reserve .. automethod:: relinquish A note on relinquishing ----------------------- You must be sure to call :meth:`ThreadMappedPool.relinquish` *before* exiting a thread that has used the pool, *from that thread*! Otherwise, some clients will never be reclaimed and you will have stale, useless connections. pylibmc-1.6.3/docs/reference.rst0000644000175100001710000002102714302105266017400 0ustar runnerdocker00000000000000=========== Reference =========== .. class:: pylibmc.Client(servers[, binary=False, username=None, password=None, behaviors=None]) Interface to a set of memcached servers. *servers* is a sequence of strings specifying the servers to use. *binary* specifies whether or not to use the binary protocol to talk to the memcached servers. *username* and *password* are credentials for SASL authentication. It requires support in libmemcached, and binary=True. Test for local support with pylibmc.support_sasl. *behaviors*, if given, is passed to :meth:`Client.set_behaviors` after initialization. Supported transport mechanisms are TCP, UDP and UNIX domain sockets. The default transport type is TCP. To specify UDP, the server address should be prefixed with ``"udp:"``, as in ``"udp:127.0.0.1"``. To specify UNIX domain socket, the server address must start with a slash, as in ``"/run/foo.sock"``. Mixing transport types is prohibited by :mod:`pylibmc` as this is not supported by libmemcached. .. method:: clone() -> clone Clone client, making new connections as necessary. .. Reading .. method:: get(key[, default]) -> value Get *key* if it exists, otherwise *default*. If *default* is not given, it defaults to ``None``. .. method:: get_multi(keys[, key_prefix=None]) -> values Get each of the keys in sequence *keys*. If *key_prefix* is given, specifies a string to prefix each of the values in *keys* with. Returns a mapping of each unprefixed key to its corresponding value in memcached. If a key doesn't exist, no corresponding key is set in the returned mapping. .. Writing .. method:: set(key, value[, time=0, min_compress_len=0, compress_level=-1]) -> success Set *key* to *value*. :param key: Key to use :param value: Value to set :param time: Time until expiry :param min_compress_len: Minimum length before compression is triggered If *time* is given, it specifies the number of seconds until *key* will expire. Default behavior is to never expire (equivalent of specifying ``0``). If *min_compress_len* is given, it specifies the maximum number of actual bytes stored in memcached before compression is used. Default behavior is to never compress (which is what ``0`` means). See :ref:`compression`. If *compress_level* is given, it specifies the compression level for the data. It accepts the same values as the :mod:`zlib` family, for which `zlib.Z_BEST_SPEED` and `zlib.Z_BEST_COMPRESSION` are commonly used constants. It accepts values between [0, 9] inclusively. .. method:: set_multi(mapping[, time=0, key_prefix=None, min_compress_len, compress_level]) -> failed_keys Set multiple keys as given by *mapping*. If *key_prefix* is specified, each of the keys in *mapping* is prepended with this value. Returns a list of keys which were not set for one reason or another, without their optional key prefix. .. method:: add(key, value[, time, min_compress_len, compress_level]) -> success Sets *key* if it does not exist. .. seealso:: :meth:`set`, :meth:`replace` .. method:: replace(key, value[, time, min_compress_len, compress_level]) -> success Sets *key* only if it already exists. .. seealso:: :meth:`set`, :meth:`add` .. method:: append(key, value) -> success Append *value* to *key* (i.e., ``m[k] = m[k] + v``). .. note:: Uses memcached's appending support, and therefore should never be used on keys which may be compressed or non-string values. .. method:: prepend(key, value) -> success Prepend *value* to *key* (i.e., ``m[k] = v + m[k]``). .. note:: Uses memcached's prepending support, and therefore should never be used on keys which may be compressed or non-string values. .. method:: incr(key[, delta=1]) -> value Increment value at *key* by *delta*. Returns the new value for *key*, after incrementing. Works for both strings and integer types. .. note:: There is currently no way to set a default for *key* when incrementing. .. method:: decr(key[, delta=1]) -> value Decrement value at *key* by *delta*. Returns the new value for *key*, after decrementing. Works for both strings and integer types, but will never decrement below zero. .. note:: There is currently no way to set a default for *key* when decrementing. .. Atomic operations .. method:: gets(key) -> (value, cas_id) Get *key* and its compare-and-swap ID if it exists, otherwise ``(None, None)``. The so-called CAS token or ID is used with :meth:`cas` to update a value with the guarantee that no other value was written in between. .. seealso:: :meth:`get`, :meth:`cas` .. method:: cas(key, value, cas[, time=0]) -> swapped Set *key* to *value* if *key* CAS token is *cas*. :param key: Key to use :param value: Value to set :param cas: Compare-and-swap token from :meth:`gets` :param time: Time until expiry If *time* is given, it specifies the number of seconds until *key* will expire. Default behavior is to never expire (equivalent of specifying ``0``). .. Deleting .. method:: delete(key) -> deleted Delete *key* if it exists. Returns ``True`` if the key was deleted, ``False`` otherwise (as is the case if it wasn't set in the first place.) .. method:: delete_multi(keys[, key_prefix=None]) -> deleted Delete each of key in the sequence *keys*. :param keys: Sequence of keys to delete :param key_prefix: Prefix for the keys to delete Returns ``True`` if all keys were successfully deleted, ``False`` otherwise (as is the case if it wasn't set in the first place.) .. method:: touch(key, time) -> touched Touch a given *key* and set its expiry time to *time* seconds. :param key: Key to touch :param time: Number of seconds until the key expires. Returns ``True`` if the key was successfully touched. ``False`` if the key did not exist (so touching is not possible.) .. Utilities .. method:: disconnect_all() Disconnect from all servers and reset internal state. Exposed mainly for compatibility with python-memcached, as there really is no logical reason to do this. .. method:: flush_all() -> success Flush all data from all servers. .. note:: This clears the specified memcacheds fully and entirely. .. method:: get_stats() -> [(name, stats), ...] Retrieve statistics from each of the connected memcached instances. Returns a list of two-tuples of the format ``(name, stats)``. *stats* is a mapping of statistics item names to their values. Whether or not a key exists depends on the version of libmemcached and memcached used. .. method:: serialize(value) -> bytestring, flag Serialize a Python value to bytes *bytestring* and an integer *flag* field for storage in memcached. The default implementation has special cases for bytes, ints/longs, and bools, and falls back to pickle for all other objects. Override this method to use a custom serialization format, or otherwise modify the behavior. *flag* is exposed by the memcached protocol. It adds flexibility in terms of encoding schemes: for example, objects *a* and *b* of different types may coincidentally encode to the same *bytestring*, just so long as they encode with different values of *flag*. If distinct values always encode to different byte strings (for example, when serializing all values with pickle), *flag* can simply be set to a constant. .. method:: deserialize(bytestring, flag) -> value Deserialize *bytestring*, stored with *flag*, back to a Python object. Override this method (in concert with ``serialize``) to use a custom serialization format, or otherwise modify the behavior. Raise ``CacheMiss`` in order to simulate a cache miss for the relevant key, i.e., ``get`` will return None and ``get_multi`` will omit the key from the returned mapping. This can be used to recover gracefully from version skew (e.g., retrieving a value that was pickled by a different, incompatible code version). .. data:: behaviors The behaviors used by the underlying libmemcached object. See :ref:`behaviors` for more information. pylibmc-1.6.3/setup.cfg0000644000175100001710000000013014302105266015571 0ustar runnerdocker00000000000000[nosetests] with-info=1 with-doctest=1 debug=nose.plugins.pylibmc doctest-extension=txt pylibmc-1.6.3/setup.py0000644000175100001710000000774614302105266015506 0ustar runnerdocker00000000000000import os import sys from distutils.core import setup, Extension ## Command-line argument parsing # --with-zlib: use zlib for compressing and decompressing # --without-zlib: ^ negated # --with-zlib=: path to zlib if needed # --with-libmemcached=: path to libmemcached package if needed cmd = None use_zlib = True pkgdirs = [] # incdirs and libdirs get these libs = ["memcached"] defs = [] incdirs = [] libdirs = [] def append_env(L, e): v = os.environ.get(e) if v and os.path.exists(v): L.append(v) append_env(pkgdirs, "LIBMEMCACHED") append_env(pkgdirs, "ZLIB") # Hack up sys.argv, yay unprocessed = [] for arg in sys.argv[1:]: if arg == "--with-zlib": use_zlib = True continue elif arg == "--without-zlib": use_zlib = False continue elif arg == "--with-sasl2": libs.append("sasl2") continue elif arg == "--gen-setup": cmd = arg[2:] elif "=" in arg: if arg.startswith("--with-libmemcached=") or \ arg.startswith("--with-zlib="): pkgdirs.append(arg.split("=", 1)[1]) continue unprocessed.append(arg) sys.argv[1:] = unprocessed for pkgdir in pkgdirs: incdirs.append(os.path.join(pkgdir, "include")) libdirs.append(os.path.join(pkgdir, "lib")) if use_zlib: libs.append("z") defs.append(("USE_ZLIB", None)) ## OS X non-PPC workaround # Apple OS X 10.6 with Xcode 4 have Python compiled with PPC but they removed # support for compiling with that arch, so we have to override ARCHFLAGS. if sys.platform == "darwin" and not os.environ.get("ARCHFLAGS"): compiler_dirn = "/usr/libexec/gcc/darwin" if os.path.exists(compiler_dirn): dir_items = os.listdir(compiler_dirn) if "ppc" not in dir_items: print("enabling osx-specific ARCHFLAGS/ppc hack", file=sys.stderr) os.environ["ARCHFLAGS"] = "-arch i386 -arch x86_64" # There's a bug in