{ "info": { "author": "Alex Casalboni", "author_email": "alex@alexcasalboni.com", "bugtrack_url": null, "classifiers": [], "description": "AWS System Manager Parameter Store Caching Client for Python ([![Python 2.7](https://img.shields.io/badge/python-2.7-green.svg)](https://www.python.org/downloads/release/python-270/) [![Python 3.6](https://img.shields.io/badge/python-3.6-green.svg)](https://www.python.org/downloads/release/python-360/) [![Python 3.7](https://img.shields.io/badge/python-3.7-green.svg)](https://www.python.org/downloads/release/python-370/))\n==========================================================\n\n[![Build Status](https://travis-ci.org/alexcasalboni/ssm-cache-python.svg?branch=master)](https://travis-ci.org/alexcasalboni/ssm-cache-python)\n[![Coverage Status](https://coveralls.io/repos/github/alexcasalboni/ssm-cache-python/badge.svg)](https://coveralls.io/github/alexcasalboni/ssm-cache-python)\n[![PyPI version](https://badge.fury.io/py/ssm-cache.svg)](https://badge.fury.io/py/ssm-cache)\n[![GitHub license](https://img.shields.io/github/license/alexcasalboni/ssm-cache-python.svg)](https://github.com/alexcasalboni/ssm-cache-python/blob/master/LICENSE)\n[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://GitHub.com/alexcasalboni/ssm-cache-python/graphs/commit-activity)\n[![GitHub issues](https://img.shields.io/github/issues/alexcasalboni/ssm-cache-python.svg)](https://github.com/alexcasalboni/ssm-cache-python/issues)\n[![Open Source Love svg2](https://badges.frapsoft.com/os/v2/open-source.svg?v=103)](https://github.com/ellerbrock/open-source-badges/)\n[![GitHub stars](https://img.shields.io/github/stars/alexcasalboni/ssm-cache-python.svg)](https://github.com/alexcasalboni/ssm-cache-python/stargazers)\n\n\n\n\n\nThis module wraps the AWS Parameter Store and adds a caching and grouping layer with max-age invalidation.\n\nYou can use this module with AWS Lambda to read and refresh parameters and secrets. Your IAM role will require `ssm:GetParameters` permissions (optionally, also `kms:Decrypt` if you use `SecureString` params).\n\n## How to install\n\nInstall the module with `pip`:\n\n```bash\npip install ssm-cache\n```\n\n## How to use it\n\n### Simplest use case\n\nA single parameter, configured by name.\n\n```python\nfrom ssm_cache import SSMParameter\nparam = SSMParameter('my_param_name')\nvalue = param.value\n```\n\n### With cache invalidation\n\nYou can configure the `max_age` in seconds, after which the values will be automatically refreshed.\n\n```python\nfrom ssm_cache import SSMParameter\nparam_1 = SSMParameter('param_1', max_age=300) # 5 min\nvalue_1 = param.value\n\nparam_2 = SSMParameter('param_2', max_age=3600) # 1 hour\nvalue_2 = param_2.value\n```\n### With multiple parameters\n\nYou can configure more than one parameter to be fetched/cached/decrypted as a group.\n\n```python\nfrom ssm_cache import SSMParameterGroup\ngroup = SSMParameterGroup(max_age=300)\nparam_1 = group.parameter('param_1')\nparam_2 = group.parameter('param_2')\n\nvalue_1 = param_1.value\nvalue_2 = param_2.value\n```\n\n### With hierarchical parameters\n\nYou can fetch/cache a group of parameters under a given prefix. Optionally, the group itself could have its own base path.\n\n```python\nfrom ssm_cache import SSMParameterGroup\ngroup = SSMParameterGroup(base_path=\"/Foo\")\nfoo_bar = group.parameter('/Bar') # will fetch /Foo/Bar\nbaz_params = group.parameters('/Baz') # will fetch /Foo/Baz/1 and /Foo/Baz/2\n\nassert len(group) == 3\n```\n\nNote: you can call `group.parameters(...)` multiple times. If caching is enabled, the group's cache will expire when the firstly fetched parameters expire.\n\n#### Hierarchical parameters and filters\n\nYou can filter by parameter `Type` and KMS `KeyId`, either building the filter object manually or using a class-based approach (which provides some additional checks before invoking the API).\n\n```python\nfrom ssm_cache import SSMParameterGroup\nfrom ssm_cache.filters import SSMFilterType\n\ngroup = SSMParameterGroup()\n\n# manual filter definition\nparams = group.parameters(\n path=\"/Foo/Bar\",\n filters=[{\n 'Key': 'Type',\n 'Option': 'Equals',\n 'Values': ['StringList']\n }],\n)\n\n# class-based filter\nparams = group.parameters(\n path=\"/Foo/Bar\",\n filters=[SSMFilterType().value('StringList')], # will validate allowed value(s)\n)\n```\n\n#### Hierarchical parameters and non-recursiveness\n\nYou can disable recursion when fetching parameters via prefix.\n\n```python\nfrom ssm_cache import SSMParameterGroup\ngroup = SSMParameterGroup()\n\n# will fetch /Foo/1, but not /Foo/Bar/1\nparams = group.parameters(\n path=\"/Foo\",\n recursive=False,\n)\n```\n\n### With StringList parameters\n\n`StringList` parameters ([documentation here](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-parameter.html#cfn-ssm-parameter-type)) are automatically converted to Python lists with no additional configuration.\n\n```python\nfrom ssm_cache import SSMParameter\n# \"my_twitter_api_keys\" is a StringList parameter (four comma-separated values)\ntwitter_params = SSMParameter('my_twitter_api_keys')\nkey, secret, access_token, access_token_secret = twitter_params.value\n```\n### Explicit refresh\n\nYou can manually force a refresh on a parameter or parameter group.\nNote that if a parameter is part of a group, the refresh operation will involve the entire group.\n\n```python\nfrom ssm_cache import SSMParameter\nparam = SSMParameter('my_param_name')\nvalue = param.value\nparam.refresh()\nnew_value = param.value\n```\n\n```python\nfrom ssm_cache import SSMParameterGroup\ngroup = SSMParameterGroup()\nparam_1 = group.parameter('param_1')\nparam_2 = group.parameter('param_2')\n\nvalue_1 = param_1.value\nvalue_2 = param_2.value\n\ngroup.refresh()\nnew_value_1 = param_1.value\nnew_value_2 = param_2.value\n\nparam_1.refresh()\nnew_new_value_1 = param_1.value\nnew_new_value_2 = param_2.value # one parameter refreshes the whole group\n```\n\n### Without decryption\n\nDecryption is enabled by default, but you can explicitly disable it (works for `SSMParameter` and `SSMGroup`).\n\n```python\nfrom ssm_cache import SSMParameter\nparam = SSMParameter('my_param_name', with_decryption=False)\nvalue = param.value\n```\n\n### AWS Secrets Manager Integration\n\nYou can read [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/) secrets transparently by using the `SecretsManagerParameter` class, which comes with the same interface of `SSMParameter` and performs some additional prefixing and validation.\n\n```python\nfrom ssm_cache import SecretsManagerParameter\nsecret = SecretsManagerParameter('my_secret_name')\nvalue = secret.value\n```\n\nSecrets can be added to a `SSMParameterGroup` as well, although no group prefix will be applied.\n\n\n```python\nfrom ssm_cache import SSMParameterGroup\ngroup = SSMParameterGroup()\nparam = group.parameter('my_param')\nsecret = group.secret('my_secret')\n\nparam_value = param.value\nsecret_value = secret.value\n```\n\n### Versioning support\n\nSSM Parameter Store supports version selectors ([documentation here](https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-paramstore-versions.html)).\n\nBy default, the latest version is fetched if you don't specify it.\n\nHere is how you can retrieve a specific parameter version:\n\n```python\nfrom ssm_cache import SSMParameter\nparam = SSMParameter('my_param_name:2')\nvalue = param.value\n```\n\nPlease note that invoking `param.refresh()` will not fetch newer versions. This is the intended behavior, as version selection should be used only when you need a specific parameter version.\n\nIf you don't specify any version, you can always read the current version of a parameter. In this case, invoking `param.refresh()` will invoke the new version.\n\n\n```python\nfrom ssm_cache import SSMParameter\nparam = SSMParameter('my_param_name')\nprint(param.version) # will print an int\n```\n\n\n\n## Usage with AWS Lambda\n\nYour [AWS Lambda](https://aws.amazon.com/lambda/) code will look similar to the following snippet.\n\n```python\nfrom ssm_cache import SSMParameter, SecretsManagerParameter\nparam = SSMParameter('my_param_name')\nsecret = SecretsManagerParameter('my_secret_name')\n\ndef lambda_handler(event, context):\n dbname = param.value\n password = secret.value\n return 'Hello from Lambda with dbname %s and password %s' % (dbname, password)\n\n```\n\n## Complex invalidation based on \"signals\"\n\nYou may want to explicitly refresh the parameter cache when you believe the cached value expired.\n\nIn the example below, we refresh the parameter value when an `InvalidCredentials` exception is detected (see the [decorator utility](#decorator-utility) for a simpler version!).\n\n```python\nfrom ssm_cache import SSMParameter\nfrom my_db_lib import Client, InvalidCredentials # pseudo-code\n\nparam = SSMParameter('my_db_password')\nmy_db_client = Client(password=param.value)\n\ndef read_record(is_retry=False):\n try:\n return my_db_client.read_record()\n except InvalidCredentials:\n if not is_retry: # avoid infinite recursion\n param.refresh() # force parameter refresh\n my_db_client = Client(password=param.value) # re-configure db client\n return read_record(is_retry=True) # let's try again :)\n\ndef lambda_handler(event, context):\n return {\n 'record': read_record(),\n }\n```\n\n## Decorator utility\n\nThe retry logic shown above can be simplified with the decorator method provided by each `SSMParameter` and `SSMParameterGroup` object.\n\nThe `@refresh_on_error` decorator will intercept errors (or a specific `error_class`, if given), refresh the parameters values, and attempt to re-call the decorated function. Optionally, you can provide a `callback` argument to implement your own logic (in the example below, to create a new db client with the new password).\n\n```python\nfrom ssm_cache import SSMParameter\nfrom my_db_lib import Client, InvalidCredentials # pseudo-code\n\nparam = SSMParameter('my_db_password')\nmy_db_client = Client(password=param.value)\n\ndef on_error_callback():\n my_db_client = Client(password=param.value)\n\n@param.refresh_on_error(InvalidCredentials, on_error_callback)\ndef read_record(is_retry=False):\n return my_db_client.read_record()\n\ndef lambda_handler(event, context):\n return {\n 'record': read_record(),\n }\n```\n\n\nThe `refresh_on_error` decorator supports the following arguments:\n\n* **error_class** (default: `Exception`)\n* **error_callback** (default: `None`)\n* **retry_argument** (default: `\"is_retry\"`)\n\n## Replacing the SSM client\n\nIf you want to replace the default `boto3` SSM client, `SSMParameter` allows you to call `set_ssm_client` and provide your own `boto3` client or even a custom object. Note that such custom object will need to implement two methods: `get_parameters` and `get_parameters_by_path`.\n\nFor example, here's how you could inject a Placebo client for local tests:\n\n```python\nimport placebo, boto3\nfrom ssm_cache import SSMParameter\n\n# create regular boto3 session\nsession = boto3.Session()\n# attach placebo to the session\npill = placebo.attach(session, data_path=PLACEBO_PATH)\npill.playback()\n# create special boto3 client\nclient = session.client('ssm')\n# inject special client into SSMParameter or SSMParameterGroup\nSSMParameter.set_ssm_client(client)\n```\n\n## How to contribute\n\nClone this repository, create a virtualenv and install all the dev dependencies:\n\n```bash\ngit clone https://github.com/alexcasalboni/ssm-cache-python.git\ncd ssm-cache-python\nvirtualenv env\nsource env/bin/activate\npip install -r requirements-dev.txt\n```\n\nYou can run tests with `nose`:\n\n```bash\nnosetests\n```\n\nGenerate a coverage report:\n\n```bash\nnosetests --with-coverage --cover-erase --cover-html --cover-package=ssm_cache\nopen cover/index.html\n```\n\nRun pylint:\n\n```bash\npylint ssm_cache\n```\n\nNote: when you open a new PR, GitHub will run tests on multiple Python environments and verify the new coverage for you, but we highly recommend you run these tasks locally as well before submitting new code.\n\n## What's new?\n\n* **version 2.9**: bugfix, versioning support, tests with Python 3.7\n* **version 2.8**: bugfix, new tests, fixed Travis build config\n* **version 2.7**: support for AWS Secrets Manager integration\n* **version 2.5**: hierarchical parameters, filters, and non-recursiveness support\n* **version 2.3**: StringList parameters support (auto-conversion)\n* **version 2.2**: client replacement and boto3/botocore minimum requirements\n* **version 2.1**: group refresh bugfix\n* **version 2.0**: new interface, `SSMParameterGroup` support\n* **version 1.3**: Python3 support\n* **version 1.0**: initial release\n\n## References and articles\n\n* [You should use SSM Parameter Store over Lambda env variables](https://hackernoon.com/you-should-use-ssm-parameter-store-over-lambda-env-variables-5197fc6ea45b) by Yan Cui (similar Node.js implementation)\n* [AWS System Manager Parameter Store doc](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html)\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "https://github.com/alexcasalboni/ssm-cache-python/archive/2.9.tar.gz", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/alexcasalboni/ssm-cache-python", "keywords": "aws,amazon-web-services,aws-lambda,aws-ssm,parameter-store", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "ssm-cache", "package_url": "https://pypi.org/project/ssm-cache/", "platform": "", "project_url": "https://pypi.org/project/ssm-cache/", "project_urls": { "Download": "https://github.com/alexcasalboni/ssm-cache-python/archive/2.9.tar.gz", "Homepage": "https://github.com/alexcasalboni/ssm-cache-python" }, "release_url": "https://pypi.org/project/ssm-cache/2.9/", "requires_dist": [ "boto3", "future" ], "requires_python": "", "summary": "AWS System Manager Parameter Store caching client for Python", "version": "2.9" }, "last_serial": 4974902, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "bd90eaa130bad4c349053536dfdb41fc", "sha256": "2ce12f1add903c17f39b4935a00f5ce36f0bd82b47a634b0c321fb872e62014f" }, "downloads": -1, "filename": "ssm-cache-0.1.tar.gz", "has_sig": false, "md5_digest": "bd90eaa130bad4c349053536dfdb41fc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4105, "upload_time": "2018-02-21T11:44:47", "url": "https://files.pythonhosted.org/packages/09/43/dcdadb5ecf1ebdd4da81e5c2fbf137fe5be0c11ef8d019ecb5023326c579/ssm-cache-0.1.tar.gz" } ], "1.0": [ { "comment_text": "", "digests": { "md5": "77b552c1a97d7aeab78c567a2ead05a5", "sha256": "1daa3fe85d955cceebc557beee0d3c86b9ad0718743b1afd10d4d5d2fd739f2f" }, "downloads": -1, "filename": "ssm-cache-1.0.tar.gz", "has_sig": false, "md5_digest": "77b552c1a97d7aeab78c567a2ead05a5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6298, "upload_time": "2018-02-21T13:34:22", "url": "https://files.pythonhosted.org/packages/3c/04/777dc41aea21182afa10eed0dd3a4a98b580f358d7bd0ee9db481449266f/ssm-cache-1.0.tar.gz" } ], "1.1": [ { "comment_text": "", "digests": { "md5": "ebba139a6a45fbf76ac1e3742abf332a", "sha256": "66982cdec60e7806e34f86becaa95356c2ea0d93c77fa4cae4059b717bf970d0" }, "downloads": -1, "filename": "ssm-cache-1.1.tar.gz", "has_sig": false, "md5_digest": "ebba139a6a45fbf76ac1e3742abf332a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6302, "upload_time": "2018-02-21T13:38:51", "url": "https://files.pythonhosted.org/packages/73/99/16f57ed488f77557b3bd62c60c3bc79b5a368522bb2279e8ff1fb9e985cc/ssm-cache-1.1.tar.gz" } ], "1.2": [ { "comment_text": "", "digests": { "md5": "46bcf75394e92469ea4216e8e677d5d1", "sha256": "3ae251005ed3072f810af8800ea89bc6eafa1a236028a0d7fecf7afcabadfb8d" }, "downloads": -1, "filename": "ssm-cache-1.2.tar.gz", "has_sig": false, "md5_digest": "46bcf75394e92469ea4216e8e677d5d1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6322, "upload_time": "2018-02-21T15:44:16", "url": "https://files.pythonhosted.org/packages/d1/5f/80ef14958106dac8b1b67142347325d3a90e60dd03b915f1c33d3094094d/ssm-cache-1.2.tar.gz" } ], "1.3": [ { "comment_text": "", "digests": { "md5": "40faabef32f7e24f9a42c042a8571a8c", "sha256": "0a3a2f097e01946d1377d8e3b279014c0b2af660bbe8a689cd9013b8f7fe2b8e" }, "downloads": -1, "filename": "ssm-cache-1.3.tar.gz", "has_sig": false, "md5_digest": "40faabef32f7e24f9a42c042a8571a8c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6348, "upload_time": "2018-02-21T15:46:59", "url": "https://files.pythonhosted.org/packages/15/42/a87a69af435936f14980ed82757eec75238cb0a64c76c72b586e5014e2de/ssm-cache-1.3.tar.gz" } ], "2.0": [ { "comment_text": "", "digests": { "md5": "59ec303ff34ce7c0a22932196f427b85", "sha256": "91821cddec4ac8049c5228e35d0e2db0c11e0f52523e8823819dd4c6ea0cc8c9" }, "downloads": -1, "filename": "ssm-cache-2.0.tar.gz", "has_sig": false, "md5_digest": "59ec303ff34ce7c0a22932196f427b85", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7329, "upload_time": "2018-02-22T19:39:42", "url": "https://files.pythonhosted.org/packages/64/49/f2dd247ba79ff90a43d6367e88952412098b45dae7927babdcb6ef6b4607/ssm-cache-2.0.tar.gz" } ], "2.1": [ { "comment_text": "", "digests": { "md5": "ef1d0ddbe73245bf5dd0b8f34c4978d0", "sha256": "001d14dbc90cecd4276b7d6c9565c140d3f8d112e94057f3fae0339905b3dbca" }, "downloads": -1, "filename": "ssm-cache-2.1.tar.gz", "has_sig": false, "md5_digest": "ef1d0ddbe73245bf5dd0b8f34c4978d0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8278, "upload_time": "2018-02-28T10:35:02", "url": "https://files.pythonhosted.org/packages/7e/24/c799608241738ddde3562df4e19cc803898095e1b909858128b17d34b970/ssm-cache-2.1.tar.gz" } ], "2.2": [ { "comment_text": "", "digests": { "md5": "6bddaaa5fd5a588361a915be0fa87551", "sha256": "727f8d143cfddfc60b88bac737977893faadd4e97cf8893dee13ace01d68338f" }, "downloads": -1, "filename": "ssm-cache-2.2.tar.gz", "has_sig": false, "md5_digest": "6bddaaa5fd5a588361a915be0fa87551", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10617, "upload_time": "2018-03-14T12:06:59", "url": "https://files.pythonhosted.org/packages/ac/9f/8469c19b131e72a89b1e4fda8559826c18370425e2e85fa8b37fde9e07b7/ssm-cache-2.2.tar.gz" } ], "2.3": [ { "comment_text": "", "digests": { "md5": "61eadf3d87a11bd325dfda41ee1d755a", "sha256": "0dfe4e7388434c71f913dac87b48e5819657d3d030baa5ef32ae4cfe81db1bc4" }, "downloads": -1, "filename": "ssm-cache-2.3.tar.gz", "has_sig": false, "md5_digest": "61eadf3d87a11bd325dfda41ee1d755a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11740, "upload_time": "2018-03-14T12:16:24", "url": "https://files.pythonhosted.org/packages/c1/78/930a625bd2d8c863ac3ac4d69aa38956deef13889cf30980f005b84d669b/ssm-cache-2.3.tar.gz" } ], "2.4": [ { "comment_text": "", "digests": { "md5": "dacd874b2a0259bb7eedeeb7f592d128", "sha256": "526dc589b051e37b8013f77d2bc9e483a36aa2e252a950ae0ad8d3ea861548d7" }, "downloads": -1, "filename": "ssm-cache-2.4.tar.gz", "has_sig": false, "md5_digest": "dacd874b2a0259bb7eedeeb7f592d128", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18478, "upload_time": "2018-04-27T15:49:49", "url": "https://files.pythonhosted.org/packages/0f/c8/c38c5525940ecc418ed935d23769db34f2e4502d119e3d5e59c11d0e2ba7/ssm-cache-2.4.tar.gz" } ], "2.5": [ { "comment_text": "", "digests": { "md5": "2f988261a5d61e024f014851b6ebea2b", "sha256": "075006e08d296465f364231dd868359a0ef3e7cf2f9b58950076ad30411e2370" }, "downloads": -1, "filename": "ssm-cache-2.5.tar.gz", "has_sig": false, "md5_digest": "2f988261a5d61e024f014851b6ebea2b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18493, "upload_time": "2018-04-27T16:04:30", "url": "https://files.pythonhosted.org/packages/3c/0f/d04a0d9fa29d0989365c2e8a587b48e3d1af32538f826bc97b77ccac5548/ssm-cache-2.5.tar.gz" } ], "2.6": [ { "comment_text": "", "digests": { "md5": "2aa3c63d628b70886c8a7a30d19e621d", "sha256": "337b0a1a70a5f773f99497aa995fcb70ffc25d71c6a4128a71adb7ce38e6d1b3" }, "downloads": -1, "filename": "ssm_cache-2.6-py2-none-any.whl", "has_sig": false, "md5_digest": "2aa3c63d628b70886c8a7a30d19e621d", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 19960, "upload_time": "2018-10-23T22:24:14", "url": "https://files.pythonhosted.org/packages/ee/85/fb0302becdac3f4cc7c0cbc35e53462e9f3629034cc00cb1227405bc8b97/ssm_cache-2.6-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c3b17672eed73e134dd2daac7f39471d", "sha256": "7a502ff3a0aa2fc37f7432d586da467b7f8a63a7e66db99b9f29db016d098e3f" }, "downloads": -1, "filename": "ssm-cache-2.6.tar.gz", "has_sig": false, "md5_digest": "c3b17672eed73e134dd2daac7f39471d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16881, "upload_time": "2018-10-23T22:24:17", "url": "https://files.pythonhosted.org/packages/77/19/001f550e04a2adb0106d18a55d6714b8649e7b5c46bec5efb275741bb3da/ssm-cache-2.6.tar.gz" } ], "2.6.1": [ { "comment_text": "", "digests": { "md5": "7f0d6a14d79bc6ae7102f325e6c21091", "sha256": "2fbb6751b948212308919eb0abb03e2323acb6142e5f19ab97c415d4956a4093" }, "downloads": -1, "filename": "ssm_cache-2.6.1-py2-none-any.whl", "has_sig": false, "md5_digest": "7f0d6a14d79bc6ae7102f325e6c21091", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 19981, "upload_time": "2018-10-23T22:24:13", "url": "https://files.pythonhosted.org/packages/45/e6/dc24e6468f59d4e24a7e564d2a154d4b83ba907ca9bd6248e0d4c2203eb2/ssm_cache-2.6.1-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "7a9e9615003a20ba789350004e68cc2d", "sha256": "d3ee2e174a86a00ec0ac78a75c336b62e43046cb5094aa0077fd1a7c046ded49" }, "downloads": -1, "filename": "ssm-cache-2.6.1.tar.gz", "has_sig": false, "md5_digest": "7a9e9615003a20ba789350004e68cc2d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16922, "upload_time": "2018-10-23T22:24:16", "url": "https://files.pythonhosted.org/packages/c1/4d/1f8eed049b7a4938dfcb8b8ff9ccd4689cb2e3592b31aa4478f1d7c9124a/ssm-cache-2.6.1.tar.gz" } ], "2.7": [ { "comment_text": "", "digests": { "md5": "48e0525a33fb874d32d96d72f5a2bc33", "sha256": "9e670f042dab83816dfa06602e61b586466dc2765299b76a4ff46c715e7e460f" }, "downloads": -1, "filename": "ssm_cache-2.7-py2-none-any.whl", "has_sig": false, "md5_digest": "48e0525a33fb874d32d96d72f5a2bc33", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 19963, "upload_time": "2018-10-23T22:28:49", "url": "https://files.pythonhosted.org/packages/6b/fe/14af2f270938631f9043ad91264b4d193ae3a1e386cb1c579064baf4db3f/ssm_cache-2.7-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8f0f0b58e9f57930378d5dbd5f5a4aba", "sha256": "b25a73ed197886a978d8bd5c48498459754059cb036bf671c6c98d74d87bb4e5" }, "downloads": -1, "filename": "ssm-cache-2.7.tar.gz", "has_sig": false, "md5_digest": "8f0f0b58e9f57930378d5dbd5f5a4aba", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15220, "upload_time": "2018-10-23T22:28:51", "url": "https://files.pythonhosted.org/packages/5e/ec/b5a5f70043d8c7924f72ad5247c39dd085301171483556c26ea60112c9c6/ssm-cache-2.7.tar.gz" } ], "2.8": [ { "comment_text": "", "digests": { "md5": "59ef12344f516161713a1ecad1c5743a", "sha256": "d6347f8eef559895f576976604842ddc20cd8ec0852debf377c3f552c0cf6fc0" }, "downloads": -1, "filename": "ssm_cache-2.8-py2-none-any.whl", "has_sig": false, "md5_digest": "59ef12344f516161713a1ecad1c5743a", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 19675, "upload_time": "2019-03-16T14:10:10", "url": "https://files.pythonhosted.org/packages/df/ba/5e7a1a7e2ea4853a654d6552ec52c0844fc49d9dd37033e5c351bd8f0945/ssm_cache-2.8-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8fb3071d3529af59b9f1ffcffdaa1a6a", "sha256": "324cac3366b12adca14bd0b523a900918a6efea96525bcdfdf59b25c57713a5d" }, "downloads": -1, "filename": "ssm-cache-2.8.tar.gz", "has_sig": false, "md5_digest": "8fb3071d3529af59b9f1ffcffdaa1a6a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18886, "upload_time": "2019-03-16T14:10:13", "url": "https://files.pythonhosted.org/packages/d8/4d/a0b92b2b80fcfd3646a1dda0d18e8a9c7e3595e50e475c74bc46ad3f02d5/ssm-cache-2.8.tar.gz" } ], "2.9": [ { "comment_text": "", "digests": { "md5": "24bf102ad8b368d05725be8b424e8fbd", "sha256": "47c5f4d8c5e52f9f80951f1eb5b89b72c72ac24261d4dc02576e524f2ea0195c" }, "downloads": -1, "filename": "ssm_cache-2.9-py2-none-any.whl", "has_sig": false, "md5_digest": "24bf102ad8b368d05725be8b424e8fbd", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 21475, "upload_time": "2019-03-23T02:22:58", "url": "https://files.pythonhosted.org/packages/42/e9/a7997d18c2291f1739facca4daf4c0a47c03885ee577af7c1271548e6136/ssm_cache-2.9-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "0cc71ccc5acddf59e09be6fb3fcfe62b", "sha256": "9c856f1667ecb8e6b7d6fd307efef900d784c866b56ff9c41cec553fce932250" }, "downloads": -1, "filename": "ssm-cache-2.9.tar.gz", "has_sig": false, "md5_digest": "0cc71ccc5acddf59e09be6fb3fcfe62b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20618, "upload_time": "2019-03-23T02:23:00", "url": "https://files.pythonhosted.org/packages/5a/eb/9c8a741d3fc044867a60047ffd30ab06a84d920ec007b388c6d686e3b3f5/ssm-cache-2.9.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "24bf102ad8b368d05725be8b424e8fbd", "sha256": "47c5f4d8c5e52f9f80951f1eb5b89b72c72ac24261d4dc02576e524f2ea0195c" }, "downloads": -1, "filename": "ssm_cache-2.9-py2-none-any.whl", "has_sig": false, "md5_digest": "24bf102ad8b368d05725be8b424e8fbd", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 21475, "upload_time": "2019-03-23T02:22:58", "url": "https://files.pythonhosted.org/packages/42/e9/a7997d18c2291f1739facca4daf4c0a47c03885ee577af7c1271548e6136/ssm_cache-2.9-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "0cc71ccc5acddf59e09be6fb3fcfe62b", "sha256": "9c856f1667ecb8e6b7d6fd307efef900d784c866b56ff9c41cec553fce932250" }, "downloads": -1, "filename": "ssm-cache-2.9.tar.gz", "has_sig": false, "md5_digest": "0cc71ccc5acddf59e09be6fb3fcfe62b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20618, "upload_time": "2019-03-23T02:23:00", "url": "https://files.pythonhosted.org/packages/5a/eb/9c8a741d3fc044867a60047ffd30ab06a84d920ec007b388c6d686e3b3f5/ssm-cache-2.9.tar.gz" } ] }