{ "info": { "author": "Runzhou Li (Leo)", "author_email": "runzhou.li@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Natural Language :: English", "Programming Language :: Python", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3" ], "description": "techies\n=======\n\nOpinionated Python toolbox\n\nMaster branch: |Build Status|\n\nPrerequisites\n-------------\n\n- Redis server for Counters and Python ``Queue`` implementations.\n\nInstallation\n------------\n\n::\n\n $ pip install techies\n $ pip install techies --upgrade\n\nIn The Box\n----------\n\nCounters (backed by Redis)\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n*New in 0.2.0* ``techies.MultiCounter`` is a stateless multi-event\ncounter, based on Redis ``Hash``.\n\n.. code:: python\n\n from techies import MultiCounter\n\n counter = MultiCounter(key='demo_counter')\n\n counter.incr('event_1')\n counter.incr('event_1')\n counter.incr('event_2')\n counter.incr('event_3')\n counter.incr('event_2')\n\n print(counter.get_count('event_1')) # 2\n print(counter.get_count('event_2')) # 2\n print(counter.get_count('event_3')) # 1\n print(counter.get_count('event_null')) # 0\n\n print(counter.json()) # {u'event_2': u'4', u'event_3': u'2', u'event_1': u'4'}\n print(unicode(counter)) # {\"event_2\": \"2\", \"event_3\": \"1\", \"event_1\": \"2\"}\n print(str(counter)) # same as above\n\n # clears the counts\n counter.clear()\n\n*New in 0.2.0* ``techies.TsCounter`` is a stateless multi-key,\nsingle-event timestamp counter, based on Redis ``Hash``.\n\n.. code:: python\n\n from techies import TsCounter\n import time\n\n # initialize with chunk_size and ttl defined\n counter = TsCounter(\n key='demo_event',\n chunk_size=24 * 60 * 60,\n ttl=48 * 60 * 60\n )\n # or call initialize() method later to customize chunk_size and/or ttl\n counter.initialize(chunk_size=24 * 60 * 60, ttl=48 * 60 * 60)\n\n t = time.time()\n\n counter.incr(timestamp=t - 86400)\n counter.incr(timestamp=t - 86400)\n counter.incr(timestamp=t)\n counter.incr(timestamp=t - 86400)\n counter.incr(timestamp=t + 86400)\n counter.incr(timestamp=t + 86400)\n\n print(counter.get_count(timestamp=t - 86400)) # 3\n print(counter.get_count(timestamp=t)) # 1\n print(counter.get_count(timestamp=t + 86400)) # 2\n\n print(counter.json()) # {u'demo_event:1429142400': {u'1429162301': u'3'}, u'demo_event:1429228800': {u'1429248701': u'1'}, u'demo_event:1429315200': {u'1429335101': u'2'}}\n print(unicode(counter)) # {\"demo_event:1429142400\": {\"1429162301\": \"3\"}, \"demo_event:1429228800\": {\"1429248701\": \"1\"}, \"demo_event:1429315200\": {\"1429335101\": \"2\"}}\n print(str(counter)) # same as above\n\n # clears the counts\n counter.clear()\n\n``techies.StateCounter`` is a single event state counter, based on Redis\n``Hash``. Project\n```tidehunter`` `__ is built\naround the concept and APIs of this counter, you can find some extended\nusage example on its `project\npage `__. **Breaking API\nChanges from 0.1.4 to 0.2.0**: ``StateCounter`` now has a new behavior\nwhen its objects are casted by ``str`` and ``unicode``. ``get_all()`` is\nnow ``json()``, and ``started`` and ``stopped`` are now properties\ninstead of methods.\n\nPython ``Queue`` Implementations (backed by Redis)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n``techies.Queue``, based on Redis ``List``. Interfaces are almost\nstandard queue compatible.\n\n.. code:: python\n\n from techies import Queue\n\n q = Queue(key='demo_q', host='localhost', port=6379, db=0)\n\n # put, or enqueue\n q.put('lol')\n q.put('dota')\n q.put('skyrim')\n q.put('dota')\n\n # Check size of the queue, two ways\n print(q.qsize()) # 4\n print(len(q)) # 4\n\n # get, or dequeue\n print(q.get()) # 'lol'\n print(q.get()) # 'dota'\n print(q.get()) # 'skyrim'\n print(q.get()) # 'dota'\n print(q.get()) # ''\n\n # clear the queue\n q.clear()\n\n``techies.UniQueue``, based on Redis ``Sorted Set``. Inherits\n``techies.Queue`` but ignores repetitive items, keeps items unique.\nScore of the sorted set member is epoch timestamp from ``time.time()``.\n\n.. code:: python\n\n from techies import UniQueue\n\n q = UniQueue(key='demo_q', host='localhost', port=6379, db=0)\n\n # put, or enqueue\n q.put('lol')\n q.put('dota')\n q.put('skyrim')\n q.put('dota') # this one is ignored\n\n # Check size of the unique queue, two ways\n print(q.qsize()) # 3\n print(len(q)) # 3\n\n # get, or dequeue\n print(q.get()) # 'lol'\n print(q.get()) # 'dota'\n print(q.get()) # 'skyrim'\n print(q.get()) # '' # only 3 unique items\n\n # clear the queue\n q.clear()\n\n``techies.CountQueue``, based on Redis ``Sorted Set``. Inherits\n``techies.UniQueue`` but score is used as a count of item appearance,\nthat the item has the highest count gets placed in front to be ``get``\nfirst.\n\n.. code:: python\n\n from techies import CountQueue\n\n q = CountQueue(key='demo_q', host='localhost', port=6379, db=0)\n\n # put, or enqueue\n q.put('lol')\n q.put('dota')\n q.put('skyrim')\n q.put('dota') # increment the count of the existing 'dota'\n\n # Check size of the unique queue, two ways\n print(q.qsize()) # 3\n print(len(q)) # 3\n\n # get, or dequeue\n print(q.get()) # ('dota', 2) # the one with the most count is returned first\n print(q.get()) # ('lol', 1)\n print(q.get()) # ('skyrim', 1)\n print(q.get()) # () # only 3 unique items still\n\n # clear the queue\n q.clear()\n\nPython ``logging.Handler`` Implementation\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n``techies.QueueHandler``, inherits standard ``logging.Handler`` that\n``emit`` to any standard ``Queue`` compatible implementations, including\nall the ``Queue`` implementations in this library.\n\n.. code:: python\n\n import logging\n from techies import (\n Queue, UniQueue, CountQueue, QueueHandler, REF_LOG_FORMAT\n )\n from techies.compat import xrange\n\n if __name__ == '__main__':\n key = 'test_q'\n q = Queue(key=key, host='localhost', port=6379, db=0)\n uq = UniQueue(key=key, host='localhost', port=6379, db=1)\n cq = CountQueue(key=key, host='localhost', port=6379, db=2)\n\n logger = logging.getLogger(__name__)\n\n for i in [q, uq, cq]:\n handler = QueueHandler(i)\n handler.setFormatter(logging.Formatter(REF_LOG_FORMAT))\n logger.addHandler(handler)\n\n # Enqueue multiple times of the same error\n for i in xrange(3):\n try:\n 1 / 0\n except ZeroDivisionError as e:\n logger.error(e)\n\n # simple queue, should print error log 3 times\n while len(q):\n print(q.get())\n\n # unique queue, should just have 1 item in this case\n print(len(uq) == 1)\n print(uq.get())\n\n # count queue, should just have 1 item as unique queue\n print(len(cq) == 1)\n print(cq.get()[1]) # 3, the count of the same item\n\n for i in [q, uq, cq]:\n i.clear()\n\nTest (Unit Tests)\n-----------------\n\nTo run unit tests locally, make sure that you have Redis server\ninstalled and running locally, where DB 0 is not occupied by any data\nthat you cannot afford to lose.\n\n::\n\n $ pip install -r requirements.txt\n $ pip install -r test_requirements.txt\n $ nosetests --with-coverage --cover-package=techies\n\nLicense\n-------\n\nThe MIT License (MIT). See the full\n`LICENSE `__.\n\n.. |Build Status| image:: https://travis-ci.org/woozyking/techies.png?branch=master\n :target: https://travis-ci.org/woozyking/techies\n\nContributors\n------------\n\n- `Runzhou Li (Leo) `__\n- `Frank Yin `__ - Initial ``Queue``\n and ``UniQueue`` implementations\n\nChangelog\n---------\n\n0.2.0 (2015-04-17)\n~~~~~~~~~~~~~~~~~~\n\n- Removed ``hiredis`` from requirements.txt since it is not a hard\n requirement. Users who wish to take advantage of ``hiredis`` can\n always install it themselves, following the concept of ``redis-py``.\n- Added ``MultiCounter``, a stateless multi-event counter, based on\n Redis ``Hash``.\n- Added ``TsCounter``, a stateless timestamp counter based on Redis\n ``Hash``, and making use of multiple keys to group timestamps, with\n auto expiration based on Redis key TTL mechanism.\n- **Breaking Change**: ``StateCounter`` now has a new behavior when its\n objects are casted by ``str`` and ``unicode``. ``get_all()`` is now\n ``json()``. This change directly reflects the underlying change\n described in the next point. Also, ``started`` and ``stopped`` are\n now properties instead of methods.\n- Simplified ``techies.landmines.RedisBase`` by factoring out its new\n child class ``techies.landmines.RedisHashBase``. All Redis Hash based\n implementations now extends from this class to get unicode ``dict``\n by calling ``json()`` method (previously ``get_all()``), and unicode\n string serialization of the ``dict`` by casting the objects using\n ``str`` or ``unicode`` (both behave exactly the same).\n\n0.1.4 (2014-01-22)\n~~~~~~~~~~~~~~~~~~\n\n- Added ``StateCounter``, a state counter based on Redis ``Hash``. To\n see an example of its usage, see\n `tidehunter `__.\n- Included ``hiredis`` in requirements.txt for added performance gain.\n\n0.1.3 (2014-01-20)\n~~~~~~~~~~~~~~~~~~\n\n- Added ``QueueHandler``, inherits standard ``logging.Handler`` that\n ``emit`` to any standard ``Queue`` compatible implementations,\n including all the ``Queue`` implementations in this library\n- Exposed direct accessibility of all intended APIs, for example,\n ``from techies import Queue``; or if you will,\n ``from techies import *``\n- Behavior of ``CountQueue.get`` has changed from just returning the\n item value to a ``tuple`` of item value and its number of appearances\n in the queue, eg: ``('dota', 2)``; an empty ``tuple`` is returned\n when the ``CountQueue`` is empty\n\n0.1.2 (2014-01-17)\n~~~~~~~~~~~~~~~~~~\n\n- Added ``CountQueue``, inherits ``UniQueue`` but the score is used as\n a count of item appearance, that the item has the highest count gets\n placed in front to be ``get`` first\n- Behavior of all ``Queue`` and its subclasses' ``put`` and\n ``put_nowait`` methods changed from return certain value to not\n return anything (more Python standard Queue like)\n\n0.1.1 (2014-01-16)\n~~~~~~~~~~~~~~~~~~\n\n- Python 3.2 and 3.3 supported now\n- Behavior of both ``Queue`` and ``UniQueue``'s ``get`` method changed\n from returning ``None`` to empty \"native string\" (unicode for Python\n 2.x, str for Python 3.x) when attempting to dequeue from an empty\n queue\n\n0.1.0 (2014-01-16)\n~~~~~~~~~~~~~~~~~~\n\n- Initial release with Redis backed ``Queue`` and ``UniQueue``", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/woozyking/techies", "keywords": null, "license": "Copyright (c) 2014 Runzhou Li\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.", "maintainer": null, "maintainer_email": null, "name": "techies", "package_url": "https://pypi.org/project/techies/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/techies/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/woozyking/techies" }, "release_url": "https://pypi.org/project/techies/0.2.0/", "requires_dist": null, "requires_python": null, "summary": "Opinionated Python toolbox", "version": "0.2.0" }, "last_serial": 1508890, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "5a63e9d7b808c076663c9320674a6f15", "sha256": "839fdd8c3b9c7806272d5556dad4e03c0958103fd9c2d674c3d49403abab8244" }, "downloads": -1, "filename": "techies-0.1.0.tar.gz", "has_sig": false, "md5_digest": "5a63e9d7b808c076663c9320674a6f15", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4120, "upload_time": "2014-01-16T06:57:50", "url": "https://files.pythonhosted.org/packages/a5/68/d906c640e4bbac03ef9c5a7528104ad4a2682679d553a0c3a8e13b5018aa/techies-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "a032933feb65d75e9af928e1b3dcf3e4", "sha256": "e945ec2b0629de2962cdff9582942528ffbd0778f16ffca0eeb1a1aaba81891c" }, "downloads": -1, "filename": "techies-0.1.1.tar.gz", "has_sig": false, "md5_digest": "a032933feb65d75e9af928e1b3dcf3e4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5192, "upload_time": "2014-01-16T20:59:31", "url": "https://files.pythonhosted.org/packages/a8/4f/52f13cf042fc9a2782db4edc55f4284923c5a8bcdbccc375b18feed40cc5/techies-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "f0721bbfa5100f614383c0ce6cbdd6ba", "sha256": "5529747727800dc1b69206d09f7ed9dd87c33bf54945497f9f1608a5c8415567" }, "downloads": -1, "filename": "techies-0.1.2.tar.gz", "has_sig": false, "md5_digest": "f0721bbfa5100f614383c0ce6cbdd6ba", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5701, "upload_time": "2014-01-17T21:43:05", "url": "https://files.pythonhosted.org/packages/09/49/b27559e64269d2660f18c353b9b590deaa1ffe948a12b3de482bdbe7f774/techies-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "2b7d2ad8a70d06ca35afa48a1ff3d414", "sha256": "8cbb4399cb2db9a046e50b8804ac31807375c31f215afe8838e37a8d986efa83" }, "downloads": -1, "filename": "techies-0.1.3.tar.gz", "has_sig": false, "md5_digest": "2b7d2ad8a70d06ca35afa48a1ff3d414", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6917, "upload_time": "2014-01-21T01:16:52", "url": "https://files.pythonhosted.org/packages/f2/87/bc96bfcc5ba675b60bd16f56b2ae68cb5053bada926b8a8696f4f23ed003/techies-0.1.3.tar.gz" } ], "0.1.4": [ { "comment_text": "", "digests": { "md5": "2cc035c1d05ce55a9c88f1c2e622ef32", "sha256": "c713e721670cf71ebe963366bb1183b9f57b28511537048a240edefba793295e" }, "downloads": -1, "filename": "techies-0.1.4.tar.gz", "has_sig": false, "md5_digest": "2cc035c1d05ce55a9c88f1c2e622ef32", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7590, "upload_time": "2014-01-22T21:53:58", "url": "https://files.pythonhosted.org/packages/9c/53/16aa7c59c9468204777465f219d1451bd6ff2318786317dcc8dfd1000943/techies-0.1.4.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "d0d49cd7638d2c086829eccb3c3f8a2a", "sha256": "7614a280108f91a43a4ced8192443414e932d6e3db13b9b8a087064f7c88e604" }, "downloads": -1, "filename": "techies-0.2.0.tar.gz", "has_sig": false, "md5_digest": "d0d49cd7638d2c086829eccb3c3f8a2a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13312, "upload_time": "2015-04-17T06:18:41", "url": "https://files.pythonhosted.org/packages/e0/85/de84e629bb5528c6e936b130049557f6ae7af9f7462f0ebe0a8af6d3913d/techies-0.2.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "d0d49cd7638d2c086829eccb3c3f8a2a", "sha256": "7614a280108f91a43a4ced8192443414e932d6e3db13b9b8a087064f7c88e604" }, "downloads": -1, "filename": "techies-0.2.0.tar.gz", "has_sig": false, "md5_digest": "d0d49cd7638d2c086829eccb3c3f8a2a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13312, "upload_time": "2015-04-17T06:18:41", "url": "https://files.pythonhosted.org/packages/e0/85/de84e629bb5528c6e936b130049557f6ae7af9f7462f0ebe0a8af6d3913d/techies-0.2.0.tar.gz" } ] }