{ "info": { "author": "Emin Martinian", "author_email": "emin.martinian@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "Programming Language :: Python :: 3" ], "description": "Introduction\n============\n\nThe ``ox_cache`` package is a collection of tools for fast, thread-safe,\nand flexible caching or memoizing of results. In particular,\n``ox_cache`` is designed to make it easy to implement the quirks of your\nparticular caching needs.\n\nFor example, if you want to repopulate the entire cache when you get a\nsingle cache miss, you can include the ``RefreshDictMixin``. Or if you\nwant to include least-recently-used semantics, you can include the\n``LRUReplacementMixin``. Or if you want a timed expiration, you can use\nthe ``TimedExpiryMixin``.\n\nThe basic structure is that you create a sub-class of ``OxCacheBase``,\ninclude appropriate mixins, and then define a way to get a new value on\na cache miss.\n\nFeatures\n--------\n\nSome of the interesting features of ``ox_cache`` include:\n\n1. Flexible: You can mix and match mixins and overrides to easily get\n desired caching behavior.\n2. Memoization: Built-in decorators for function memoization.\n3. Dict-like: Dictionary methods such as ``__setitem__``,\n ``__getitem__``, ``__delitem__``, ``__contains__``, ``__iter__``, and\n ``items`` are provided.\n4. Thread-safe: All of the basic operations use threading.Lock().\n5. Thread-smart: Hooks and overridable methods are structured so that\n you can ignore threads in your customization but stay thread safe.\n6. Docs: Python docstrings are provided for every class and method.\n7. Unit tests: Source code comes with unit tests with very high code\n coverage.\n\nQuick Start\n===========\n\nInstallation\n------------\n\nInstall with the usual\n\n.. code:: sh\n\n $ pip install ox_cache\n\nCaching\n-------\n\nThe simplest way to use the cache is to create an instance of\nOxCacheBase and use it like a dict as shown below but to really get the\npower of ``ox_cache``, you will want to use mixins or overrides as shown\nlater.\n\n.. code:: python\n\n >>> from ox_cache import OxCacheBase\n >>> c = OxCacheBase() # trivial example of a cache\n >>> c['foo'] = 5 # alternative: c.store('foo', 5, **options)\n >>> c['foo']\n 5\n\nOf course, with the usage above you don't really get any benefits beyond\na standard dict. One convenient feature of ``ox_cache`` is that you can\noverride the ``make_value`` method to get a \"smart cache\". With\n``make_value``, when there is no value for a key, your cache will no how\nto make that value.\n\nTo get a \"smart cache\" you simply sub-class ``OxCacheBase`` and then\noverride desired methods. The only required method you must override is\nthe ``make_value`` method to make the value when a key is not in the\ncache. The following illustrates the simplest use case:\n\n.. code:: python\n\n >>> from ox_cache import OxCacheBase\n >>> class BasicCache(OxCacheBase):\n ... def make_value(self, key, **opts):\n ... 'Simple function to create value for requested key.'\n ... print('Calling refresh for key=\"%s\"' % key)\n ... return 'x' * key # create a bunch of x's\n ...\n >>> cache = BasicCache()\n >>> cache.get(5) # Will call make_value to generate 1st value.\n Calling refresh for key=\"5\"\n 'xxxxx'\n >>> cache.get(5) # Will get value from cache without calling make_value\n 'xxxxx'\n\nYou can get more interesting cache features by including mixins. The\nfollowing illustrate a simple example where we include the\n``TimedExpiryMixin`` so that cache entries expire after a set amount of\ntime.\n\n.. code:: python\n\n\n >>> from ox_cache import OxCacheBase, TimedExpiryMixin\n >>> class TimedCache(TimedExpiryMixin, OxCacheBase):\n ... 'Cache which expires items after after self.expiry_seconds.'\n ... def make_value(self, key, **opts):\n ... 'Simple function to create value for requested key.'\n ... print('Calling refresh for key=\"%s\"' % key)\n ... return 'key=\"%s\" is fun!' % key\n ...\n >>> cache = TimedCache(expiry_seconds=100) # expires after 100 seconds\n >>> cache.get('test') # Will call make_value to generate value.\n Calling refresh for key=\"test\"\n 'key=\"test\" is fun!'\n >>> cache.ttl('test') > 60 # Check time to live is pretty long\n True\n >>> cache.get('test') # If called immediately, will use cached item\n 'key=\"test\" is fun!'\n >>> cache.expiry_seconds = 1 # Change expiration time to be much faster\n >>> import time; time.sleep(1.1) # Wait a few seconds for cache item to expire\n >>> cache.get('test') # Will generate a new value since time limit expired\n Calling refresh for key=\"test\"\n 'key=\"test\" is fun!'\n\nIn addition to the ``get`` method illustrated above, a few other methods\nyou may find useful include:\n\n1. ``ttl``: Return the time-to-live for a key.\n2. ``expired``: Return whether the cache entry for a key has expired.\n3. ``delete``: Remove an entry from the cache.\n4. ``clean``: Go through the entire cache and remove expired elements.\n5. ``exists``: Check if an element is in the cache (possibly expired).\n\nFor more sophisticated caching you can use more mix-ins or override the\ndesired functions. See the docs for the ``OxCacheBase`` class in the\nsource code or in the following documentation sections.\n\nNote that if you want to keep things as simple as possible, you don't\nhave to override ``make_value`` if using the ``TimedExpiryMixin`` but\ncan just use the ``store`` method as shown below:\n\nKeeping it Simple\n~~~~~~~~~~~~~~~~~\n\n.. code:: python\n\n >>> import time\n >>> from ox_cache import OxCacheBase, TimedExpiryMixin\n >>> class MyCache(TimedExpiryMixin, OxCacheBase):\n ... 'Cache with timed expiry'\n ... \n >>> cache = MyCache() # Create an instance\n >>> cache.expiry_seconds = 1 # make refresh time very short\n >>> cache.store('foo', 'blah')\n >>> cache.get('foo')\n 'blah'\n >>> time.sleep(1.5) # sleep so that cache becomes stale\n >>> try: # Attempt to get stale item 'foo'\n ... cache.get('foo') # will cause an exception\n ... except: # since make_value not defined\n ... print(\"unable to get 'foo'\")\n ...\n unable to get 'foo'\n\nMemoization\n-----------\n\nTo memoize (cache) function calls you can use something like the\n``OxMemoizer`` as a function decorator as shown in the example below:\n\n.. code:: python\n\n\n >>> from ox_cache import OxMemoizer\n >>> @OxMemoizer\n ... def my_func(x, y):\n ... 'Add two inputs'\n ... z = x + y\n ... print('called my_func(%s, %s) = %s' % (x, y, z))\n ... return z\n ...\n >>> my_func(1, 2) # This will actually call the function.\n called my_func(1, 2) = 3\n 3\n >>> my_func(1, 2) # This will use a cached value.\n 3\n\nSince ``OxMemoizer`` is just a sub-class of ``OxCacheBase`` you can use\none of the provided mixins to control expiration or just use something\nlike the ``LRUReplacementMemoizer``. As shown below, setting the\n``max_size`` property of an instance of ``LRUReplacementMemoizer`` will\nautomatically kick out least recently used cache entries when the cache\ngets too large.\n\n.. code:: python\n\n\n >>> from ox_cache import LRUReplacementMemoizer\n >>> @LRUReplacementMemoizer\n ... def my_func(x, y):\n ... 'Add two inputs'\n ... z = x + y\n ... print('called my_func(%s, %s) = %s' % (x, y, z))\n ... return z\n ...\n >>> my_func(1, 2)\n called my_func(1, 2) = 3\n 3\n >>> my_func.max_size = 3\n >>> data = [my_func(1, i) for i in range(4)]\n called my_func(1, 0) = 1\n called my_func(1, 1) = 2\n called my_func(1, 3) = 4\n >>> len(my_func), my_func.exists(1, 0) # Verify least recent item kicked out\n (3, False)\n\nIf you wanted time based expiration, you could use ``TimedMemoizer`` or\nsimply subclass ``OxMemoizer`` and include mixins like\n``LRUReplacementMixin`` and/or ``TimedExpiryMixin``.\n\nNote that since our memoizers are sub-classes of ``OxCacheBase``, you\ncan use any of the methods from ``OxCacheBase`` as shown below:\n\n.. code:: python\n\n\n >>> my_func.exists(1, 3)\n True\n >>> my_func.delete(1, 3)\n >>> my_func.exists(1, 3)\n False\n\nDiscussion\n==========\n\nThe ox\\_cache package provides tools to build your own simple caching\nsystem. The core class is ``OxCacheBase`` which everything inherits\nfrom. The only function which you must provide when you sub-class\n``OxCacheBase`` is ``make_value`` which defines how to create a value\nwhich is not in the cache.\n\nYou can further customize how the cache works either by overriding\nappropriate methods or by using one of the many mixins provided. For\nexample, the following illustrates how you can use the\n``TimedExpiryMixin`` and the ``RefreshDictMixin`` to create a\n``BatchCache`` which updates the whole cache any time there is a cache\nmiss:\n\n.. code:: python\n\n\n >>> from ox_cache import OxCacheBase, TimedExpiryMixin, RefreshDictMixin\n >>> class BatchCache(TimedExpiryMixin, RefreshDictMixin, OxCacheBase):\n ... 'Simple cache with time-based refresh via a function that gives dict'\n ... def make_dict(self, key):\n ... \"Function to make dict to use to refresh cache.\"\n ... return {k: str(k)+self.info for k in ([key] + list(range(10)))}\n ...\n >>> cache = BatchCache()\n >>> cache.info = '5'\n >>> cache.get(2) # will auto-refresh using make_dict\n '25'\n >>> cache.ttl(2) > 0\n True\n >>> cache.info = '6'\n >>> cache.get(2) # cache has not been marked as stale so no refresh\n '25'\n >>> cache.expiry_seconds = 1 # make refresh time very short\n >>> time.sleep(1.5) # sleep so that cache becomes stale\n >>> cache.ttl(2)\n 0\n >>> cache.get(2) # check cache to see that we auto-refresh\n '26'\n >>> cache.expiry_seconds = 1000 # slow down auto refresh for other examples\n >>> cache.store(800, 5)\n >>> cache.get(800)\n 5\n >>> cache.store('800', 'a string')\n >>> cache.get('800')\n 'a string'\n >>> cache.delete(800)\n >>> cache.get(800, allow_refresh=False) is None\n True\n\nAdditional Information\n======================\n\nYou can find the project page at https://github.com/emin63/ox\\_cache\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/emin63/ox_cache", "keywords": "cache caching memoization", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "ox_cache", "package_url": "https://pypi.org/project/ox_cache/", "platform": "", "project_url": "https://pypi.org/project/ox_cache/", "project_urls": { "Homepage": "http://github.com/emin63/ox_cache" }, "release_url": "https://pypi.org/project/ox_cache/1.3.2/", "requires_dist": null, "requires_python": "", "summary": "Tools for caching and memoization in python.", "version": "1.3.2" }, "last_serial": 5200411, "releases": { "1.0": [ { "comment_text": "", "digests": { "md5": "20ede607f83498a713d4c388fa4e6932", "sha256": "70c2262fd34d40078fba6a2f5d66d216812c82a15834f95035cf4b0996ff3614" }, "downloads": -1, "filename": "ox_cache-1.0.tar.gz", "has_sig": false, "md5_digest": "20ede607f83498a713d4c388fa4e6932", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18692, "upload_time": "2018-12-13T22:27:55", "url": "https://files.pythonhosted.org/packages/e5/d5/f8a1a9654fe5cc9a9d655c36fbce99abd84329cf1a8825b62a04711ee3a1/ox_cache-1.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "338852a06d5fc3a180e1901b47710383", "sha256": "7fc9271a4cb9de0d37dfc7b12f6c3e3d8770f61a50ab104eb9a52777a0d11a5b" }, "downloads": -1, "filename": "ox_cache-1.0.1.tar.gz", "has_sig": false, "md5_digest": "338852a06d5fc3a180e1901b47710383", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19395, "upload_time": "2018-12-13T22:36:51", "url": "https://files.pythonhosted.org/packages/5b/88/8a8d53f8a30502b3d433f1de1aa95cdc75bfa7cc95511270b6fdb3ec9931/ox_cache-1.0.1.tar.gz" } ], "1.1": [ { "comment_text": "", "digests": { "md5": "dc285195631f7430385e7f8b3b2102b0", "sha256": "16ff1f8a190f1df91178e9c6fe0013fad25c3d2869407d9f87050a915aa6e22d" }, "downloads": -1, "filename": "ox_cache-1.1.tar.gz", "has_sig": false, "md5_digest": "dc285195631f7430385e7f8b3b2102b0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19635, "upload_time": "2018-12-13T23:06:34", "url": "https://files.pythonhosted.org/packages/56/35/1028f35e752d2715cfe722497810bd86c2154bf33d0d04b67df20db253ea/ox_cache-1.1.tar.gz" } ], "1.1.1": [ { "comment_text": "", "digests": { "md5": "b6d81b65e831339a770b1365d4a56b3c", "sha256": "d5d670eb0e6dcd481d4b3e1eef34328b4897259da3c620b956944204af445109" }, "downloads": -1, "filename": "ox_cache-1.1.1.tar.gz", "has_sig": false, "md5_digest": "b6d81b65e831339a770b1365d4a56b3c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19690, "upload_time": "2018-12-13T23:08:31", "url": "https://files.pythonhosted.org/packages/84/3d/d4be9d429a60b7ca208e59f91af6bcd2f6579937be75f9a78eb8e90c6fcd/ox_cache-1.1.1.tar.gz" } ], "1.2.1": [ { "comment_text": "", "digests": { "md5": "a9b404a6a33426156937074b02e63092", "sha256": "35b3583b1681d5aa2e46dae1f87bbb241208adabfce5c610f84a1981012fd017" }, "downloads": -1, "filename": "ox_cache-1.2.1.tar.gz", "has_sig": false, "md5_digest": "a9b404a6a33426156937074b02e63092", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20195, "upload_time": "2018-12-14T17:49:48", "url": "https://files.pythonhosted.org/packages/b9/c2/cb862b3a4bf261c789563308db5870b28af6aba0f0373a54e188e409d375/ox_cache-1.2.1.tar.gz" } ], "1.3.1": [ { "comment_text": "", "digests": { "md5": "d57a7da65ad5ab066193c0d6a47affbe", "sha256": "df6587316d3fbe4a033c8e231c4e75b71119e9694e443524ec5e8d4a5cd87f8f" }, "downloads": -1, "filename": "ox_cache-1.3.1.tar.gz", "has_sig": false, "md5_digest": "d57a7da65ad5ab066193c0d6a47affbe", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20564, "upload_time": "2018-12-17T18:57:12", "url": "https://files.pythonhosted.org/packages/4c/88/bd3df19d9297793a738165d0a8276bb7ecd088402e11602aa4e64e8ee21d/ox_cache-1.3.1.tar.gz" } ], "1.3.2": [ { "comment_text": "", "digests": { "md5": "0212da4b72c166be98cb6be558635238", "sha256": "474e4ce378adaf165b867181ea0f26b57dc9080d7c1baa498938cb864155d1af" }, "downloads": -1, "filename": "ox_cache-1.3.2.tar.gz", "has_sig": false, "md5_digest": "0212da4b72c166be98cb6be558635238", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21593, "upload_time": "2019-04-28T19:01:35", "url": "https://files.pythonhosted.org/packages/2f/19/a24d1aed98e7c814e6242c8d1e9ca0aa5cdda7530658b7a0cdc391d23713/ox_cache-1.3.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "0212da4b72c166be98cb6be558635238", "sha256": "474e4ce378adaf165b867181ea0f26b57dc9080d7c1baa498938cb864155d1af" }, "downloads": -1, "filename": "ox_cache-1.3.2.tar.gz", "has_sig": false, "md5_digest": "0212da4b72c166be98cb6be558635238", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21593, "upload_time": "2019-04-28T19:01:35", "url": "https://files.pythonhosted.org/packages/2f/19/a24d1aed98e7c814e6242c8d1e9ca0aa5cdda7530658b7a0cdc391d23713/ox_cache-1.3.2.tar.gz" } ] }