{ "info": { "author": "Myrfy001", "author_email": "", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Operating System :: POSIX", "Programming Language :: C", "Programming Language :: Python :: 2", "Programming Language :: Python :: 3", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "## LRU Dict\n\nA fixed size dict like container which support ttl and evicts Least Recently \nUsed (LRU) items once size limit is exceeded or the ttl is exceeded. \nLRU maximum capacity can be modified at run-time.\n\nThis is a project forked from https://github.com/amitdev/lru-dict and I added \nttl feature for it which makes it more suitable to be a cache. If you want to\nknow more about the origin work, please go to the above url.\n\n\n## Install\n\n```shell\n pip install ttlru-dict\n```\nor\n```shell\n easy_install ttlru_dict\n```\n\n\n## Usage\n\nThis can be used to build a LRU cache with TTL. Usage is almost like a dict.\n\n```python\nfrom ttlru import TTLRU\nimport time\n\n# Create an TTLRU container that can hold 5 items, with default ttl = 1s\n# *NOTE* ttl is represented in nanoseconds\nl = TTLRU(5, ttl=1*1000000000)\n\n# add an item with a default ttl, in this case, it's 1000000000ns = 1 second\nl[0] = '0'\n\n# add an item with specified ttl, in this case it's 2 seconds\nl.set_with_ttl(1, '1', 2*1000000000)\n\nprint(l.items())\n# Would print [(1, '1'), (0, '0')]\n\ntime.sleep(1)\nprint(l.items())\n# Would print [(1, '1')], the first item expired.\n\ntime.sleep(1)\nprint(l.items())\n# Would print [], the second item also expired after 2 seconds.\n\n# ===================================================================\n\n# orher operations without ttl\nl = TTLRU(5) \n\nprint(l.peek_first_item(), l.peek_last_item()) #return the MRU key and LRU key\n# Would print None None\n\nfor i in range(5):\n l[i] = str(i)\nprint(l.items()) # Prints items in MRU order\n# Would print [(4, '4'), (3, '3'), (2, '2'), (1, '1'), (0, '0')]\n\nprint(l.peek_first_item(), l.peek_last_item()) #return the MRU key and LRU key\n# Would print (4, '4') (0, '0')\n\nl[5] = '5' # Inserting one more item should evict the old item\nprint(l.items())\n# Would print [(5, '5'), (4, '4'), (3, '3'), (2, '2'), (1, '1')]\n\nl[3] # Accessing an item would make it MRU\nprint(l.items())\n# Would print [(3, '3'), (5, '5'), (4, '4'), (2, '2'), (1, '1')]\n# Now 3 is in front\n\nprint(l.keys()) # Can get keys alone in MRU order\n# Would print [3, 5, 4, 2, 1]\n\ndel l[4] # Delete an item\nprint(l.items())\n# Would print [(3, '3'), (5, '5'), (2, '2'), (1, '1')]\n\nprint(l.get_size())\n# Would print 5\n\nl.set_size(3)\nprint(l.items())\n# Would print [(3, '3'), (5, '5'), (2, '2')]\nprint(l.get_size())\n# Would print 3\nprint(l.has_key(5))\n# Would print True\nprint(2 in l)\n# Would print True\n\nprint(l.get_stats())\n# Would print (1, 0)\n\n\nl.update({5: '0'}) # Update an item\nprint(l.items())\n# Would print [(5, '0'), (3, '3'), (2, '2')]\n\nl.clear()\nprint(l.items())\n# Would print []\n\ndef evicted(key, value):\n print(\"removing: %s, %s\" % (key, value))\n\nl = TTLRU(1, callback=evicted)\n\nl[1] = '1'\nl[2] = '2'\n# callback would print removing: 1, 1\n\nl[2] = '3'\n# doesn't call the evicted callback\n\nprint(l.items())\n# would print [(2, '3')]\n\ndel l[2]\n# doesn't call the evicted callback\n\nprint(l.items())\n# would print []\n```\n\n\n## Notes and Technical Details\n\n *For more detailed information, please read the source code.*\n\n### about ttl\n* ttl = -1 means won't expire forever\n* ttl is measured in nanoseconds. This is because Python's C-API `_PyTime_GetSystemClock` returns timestamp as nanoseconds, I don't want to do extra conversion.\n\n### When will ttl be checked?\n* ttl is checked everytime when you try to access it, if expired, ttlru will remove the current item, and try to return a not expired item if possible:\n * if you try to get a item like `result = l['a']`, if the item expired, `None` will returned.\n * if you try to get the first or the last item using `peek_first_item()` or `peek_last_item()`, if the first or the last item expired, it will try the next item and return the first item that is not expired. if all items is expired, then return `None`\n * `keys()`, `values()` and `items()` method will go through all the linked list and remove the expired items, then returns a list with not expired items.\n* ttl is not checkd when you access the statistics data.\n * the `len(l)` will return count includes expired items. I think go through all the list to find not exist count is too expensive, maybe I can add another method to get the count of not expired items.\n\n\n### What happened when insert an item?\n* If the dict reached it's max size, then the last one will be removed. If there is an expired item but it is not the last one, then the expired item will still stay in the dict, only the last one will be removed. The reason is if I want to remove the expired one and keep the last one which is not expired, I have to use another data structure like a skip-table to keep the ttl order, which is not implemented in this version. For the other hand, the behavier above should be a *TTL-Dict*, not a *TTL-LRU-Dict*, Maybe I will write a *TTL-Dict* in the future.\n\n### Different behavier against normal dict\n* `keys()`, `values()` and `items()` returns a list, not a view object in Python3", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/myrfy001/ttlru-dict", "keywords": "ttl,lru,dict,cache", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "ttlru-dict", "package_url": "https://pypi.org/project/ttlru-dict/", "platform": "", "project_url": "https://pypi.org/project/ttlru-dict/", "project_urls": { "Homepage": "https://github.com/myrfy001/ttlru-dict" }, "release_url": "https://pypi.org/project/ttlru-dict/1.0.1/", "requires_dist": null, "requires_python": "", "summary": "An Dict like LRU container which also has ttl feature.", "version": "1.0.1" }, "last_serial": 5664200, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "e42900f37bdd46a610f4c76749712a95", "sha256": "13a3bac889dfe7aa1143ed494b676acb61d81b5295809b98dd3ba46c25b0d784" }, "downloads": -1, "filename": "ttlru-dict-1.0.0.tar.gz", "has_sig": false, "md5_digest": "e42900f37bdd46a610f4c76749712a95", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11085, "upload_time": "2018-08-15T06:10:41", "url": "https://files.pythonhosted.org/packages/09/73/f5b68c0e254770bd0572b37fcad43b424a4e386033ee6b574f6cb5ebd304/ttlru-dict-1.0.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "215e729a15b764c25bd1f1a89c8f369c", "sha256": "911a21a3ad3f68b8b6f9bb0b6f29d9d2100734f7d5d5fcd552ca42bcd4f44504" }, "downloads": -1, "filename": "ttlru-dict-1.0.1.tar.gz", "has_sig": false, "md5_digest": "215e729a15b764c25bd1f1a89c8f369c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13339, "upload_time": "2019-08-12T06:14:06", "url": "https://files.pythonhosted.org/packages/7d/93/20001a23af1eecc4ef2b5b66207047b7370dca031afaf51bbe621ac38939/ttlru-dict-1.0.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "215e729a15b764c25bd1f1a89c8f369c", "sha256": "911a21a3ad3f68b8b6f9bb0b6f29d9d2100734f7d5d5fcd552ca42bcd4f44504" }, "downloads": -1, "filename": "ttlru-dict-1.0.1.tar.gz", "has_sig": false, "md5_digest": "215e729a15b764c25bd1f1a89c8f369c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13339, "upload_time": "2019-08-12T06:14:06", "url": "https://files.pythonhosted.org/packages/7d/93/20001a23af1eecc4ef2b5b66207047b7370dca031afaf51bbe621ac38939/ttlru-dict-1.0.1.tar.gz" } ] }