{ "info": { "author": "Paul Wexler", "author_email": "paul@prometheusresearch.com", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Developers", "Programming Language :: Python" ], "description": "=========\ns3\n=========\n\n.. contents::\n\nOverview\n========\n\ns3 is a connector to S3, Amazon's Simple Storage System REST API.\n\nUse it to upload, download, delete, copy, test files for existence in S3, or \nupdate their metadata.\n\nS3 files may have metadata in addition to their content. \nMetadata is a set of key/value pairs. \nMetadata may be set when the file is uploaded \nor it can be updated subsequently.\n\nS3 files are stored in S3 buckets. Buckets can be created, listed, \nconfigured, and deleted. The bucket configuration can be read and the \nbucket contents can be listed.\n\nIn addition to the s3 Python module, \nthis package contains a command line tool also named s3. \nThe tool imports the module and offers a command line\ninterface to some of the module's capability.\n\nInstallation\n============\n\nFrom PyPi\n::\n\n $ pip install s3 \n\nFrom source\n::\n\n $ hg clone ssh://hg@bitbucket.org/prometheus/s3\n $ pip install -e s3 \n\nThe installation is successful if you can import s3 \nand run the command line tool. The following commands \nmust produce no errors:\n::\n\n $ python -c 'import s3'\n $ s3 --help\n\nAPI to remote storage\n=====================\n\nS3 Buckets\n----------\n\nBuckets store files. Buckets may be created and deleted. They may be\nlisted, configured, and loaded with files. The configuration can be read,\nand the files in the bucket can be listed.\n\nBucket names must be unique across S3 so it is best to use a unique prefix on\nall bucket names. S3 forbids underscores in bucket names, and although\nit allows periods, these confound DNS and should be avoided.\nFor example, at Prometheus Research \nwe prefix all of our bucket names with: **com-prometheus-**\n\nAll the bucket configuration options work the same way - the caller\nprovides XML or JSON data and perhaps headers or params as well.\n\ns3 accepts a python object for the data argument instead of a string.\nThe object will be converted to XML or JSON as required.\n\nLikewise, s3 returns a python dict instead of the XML or JSON string\nreturned by S3. However, that string is readily available if need be,\nbecause the response returned by requests.request() is exposed to the\ncaller.\n\nS3 Filenames\n------------\n\nAn S3 file name consists of a bucket and a key. This pair of\nstrings uniquely identifies the file within S3.\n\nThe S3Name class is instantiated with a key and a bucket; the key\nis required and the bucket defaults to None.\n\nThe Storage class methods take a **remote_name** argument which\ncan be either a string which is the key, or an instance of the\nS3Name class. When no bucket is given (or the bucket is None) then\nthe default_bucket established when the connection is instantiated\nis used. If no bucket is given (or the bucket is None) and there\nis no default bucket then a ValueError is raised.\n\nIn other words, the S3Name class provides a means of using a bucket\nother than the default_bucket.\n\nS3 Directories\n--------------\n\nAlthough S3 storage is flat: buckets contain keys, S3 lets you impose\na directory tree structure on your bucket by using a delimiter in your\nkeys.\n\nFor example, if you name a key 'a/b/f', and use '/' as the delimiter,\nthen S3 will consider that 'a' is a directory, 'b' is a sub-directory\nof 'a', and 'f' is a file in 'b'.\n\n\nHeaders and Metadata\n--------------------\n\nAdditional http headers may be sent using the methods which write\ndata. These methods accept an optional **headers** argument which\nis a python dict. The headers control various aspects of how the\nfile may be handled. S3 supports a variety of headers. These are\nnot discussed here. See Amazon's S3 documentation for more info\non S3 headers.\n\nThose headers whose key begins with the special prefix:\n**x-amz-meta-** are considered to be metadata headers and are\nused to set the metadata attributes of the file.\n\nThe methods which read files also return the metadata which\nconsists of only those response headers which begin with\n**x-amz-meta-**.\n\nPython classes for S3 data\n--------------------------\n\nTo facilitate the transfer of data between S3 and applications various\nclasses were defined which correspond to data returned by S3.\n\nAll attributes of these classes are strings.\n\n* S3Bucket\n * creation_date\n * name\n\n* S3Key\n * e_tag\n * key\n * last_modified\n * owner\n * size\n * storage_class\n\n* S3Owner\n * display_name\n * id\n\nXML strings and Python objects\n------------------------------\n\nAn XML string consists of a series of nested tags. An XML tag can be\nrepresented in python as an entry in a dict. An OrderedDict from the\ncollections module should be used when the order of the keys is\nimportant.\n\nThe opening tag (everything between the '<' and the '>') is the key and\neverything between the opening tag and the closing tag is the value of\nthe key.\n\nSince every value must be enclosed in a tag, not every python object can\nrepresent XML in this way. In particular, lists may only contain dicts\nwhich have a single key.\n\nFor example this XML::\n\n \n \n 1 \n \n \n 2 \n \n \n\nis equivalent to this object::\n\n {'a xmlns=\"foo\"': [{'b1': {'c1': 1}}, {'b2': {'c2': 2}}] }\n\nStorage Methods\n---------------\n\nThe arguments **remote_source**, **remote_destination**, and\n**remote_name** may be either a string, or an S3Name instance.\n\n**local_name** is a string and is the name of the file on the\nlocal system. This string is passed directly to open().\n\n**bucket** is a string and is the name of the bucket.\n\n**headers** is a python dict used to encode additional request headers.\n\n**params** is either a python dict used to encode the request\nparameters, or a string containing all the text of the url query string\nafter the '?'.\n\n**data** is a string or an object and is the body of the message. The\nobject will be converted to an XML or JSON string as appropriate.\n\nAll methods return on success or raise StorageError on failure.\n\nUpon return **storage.response** contains the raw response object which\nwas returned by the requests module. So for example,\nstorage.response.headers contains the response headers returned by S3.\nSee\nhttp://docs.python-requests.org/en/latest/api/ for a description of the\nresponse object.\n\nSee http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketOps.html\nfor a description of the available bucket operations and their arguments.\n\n**storage.bucket_create(bucket, headers={}, data=None)**\n Create a bucket named **bucket**. **headers** may be used to set\n either ACL or explicit access permissions. **data** may be used to\n override the default region. If data is None, data is set as\n follows::\n\n data = {\n 'CreateBucketConfiguration'\n ' xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"': {\n 'LocationConstraint': self.connection.region}}\n\n**storage.bucket_delete(bucket)**\n Delete a bucket named **bucket**.\n\n**storage.bucket_delete_cors(bucket)**\n Delete cors configuration of bucket named **bucket**.\n\n**storage.bucket_delete_lifecycle(bucket)**\n Delete lifecycle configuration of bucket named **bucket**.\n\n**storage.bucket_delete_policy(bucket)**\n Delete policy of bucket named **bucket**.\n\n**storage.bucket_delete_tagging(bucket)**\n Delete tagging configuration of bucket named **bucket**.\n\n**storage.bucket_delete_website(bucket)**\n Delete website configuration of bucket named **bucket**.\n\n**exists = storage.bucket_exists(bucket)**\n Test if **bucket** exists in storage.\n\n exists - boolean.\n\n**storage.bucket_get(self, bucket, params={})**\n Gets the next block of keys from the bucket based on params.\n\n**d = storage.bucket_get_acl(bucket)**\n Returns bucket acl configuration as a dict.\n\n**d = storage.bucket_get_cors(bucket)**\n Returns bucket cors configuration as a dict.\n\n**d = storage.bucket_get_lifecycle(bucket)**\n Returns bucket lifecycle as a dict.\n\n**d = storage.bucket_get_location(bucket)**\n Returns bucket location configuration as a dict.\n\n**d = storage.bucket_get_logging(bucket)**\n Returns bucket logging configuration as a dict.\n\n**d = storage.bucket_get_notification(bucket)**\n Returns bucket notification configuration as a dict.\n\n**d = storage.bucket_get_policy(bucket)**\n Returns bucket policy as a dict.\n\n**d = storage.bucket_get_request_payment(bucket)**\n Returns bucket requestPayment configuration as a dict.\n\n**d = storage.bucket_get_tagging(bucket)**\n Returns bucket tagging configuration as a dict.\n\n**d = storage.bucket_get_versioning(bucket)**\n Returns bucket versioning configuration as a dict.\n\n**d = storage.bucket_get_versions(bucket, params={})**\n Returns bucket versions as a dict.\n\n**d = storage.bucket_get_website(bucket)**\n Returns bucket website configuration as a dict.\n\n**for bucket in storage.bucket_list():**\n Returns a Generator object which returns all the buckets for the\n authenticated user's account. \n\n Each bucket is returned as an S3Bucket instance.\n\n**for key in storage.bucket_list_keys(bucket, delimiter=None, prefix=None, params={}):**\n Returns a Generator object which returns all the keys in the bucket.\n \n Each key is returned as an S3Key instance.\n\n * bucket - the name of the bucket to list\n * delimiter - used to request common prefixes\n * prefix - used to filter the listing\n * params - additional parameters.\n\n When delimiter is used, the keys (i.e. file names) are returned\n first, followed by the common prefixes (i.e. directory names).\n Each key is returned as an S3Key instance. Each common prefix\n is returned as a string.\n\n As a convenience, the delimiter and prefix may be\n provided as either keyword arguments or as keys in params. If the\n arguments are provided, they are used to update params. In any case,\n params are passed to S3.\n\n See http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html\n for a description of delimiter, prefix, and the other parameters.\n\n**bucket_set_acl(bucket, headers={}, data='')**\n Configure bucket acl using xml data, or request headers.\n\n**bucket_set_cors(bucket, data='')**\n Configure bucket cors with xml data.\n\n**bucket_set_lifecycle(bucket, data='')**\n Configure bucket lifecycle with xml data.\n\n**bucket_set_logging(bucket, data='')**\n Configure bucket logging with xml data.\n\n**bucket_set_notification(bucket, data='')**\n Configure bucket notification with xml data.\n\n**bucket_set_policy(bucket, data='')**\n Configure bucket policy using json data.\n\n**bucket_set_request_payment(bucket, data='')**\n Configure bucket requestPayment with xml data.\n\n**bucket_set_tagging(bucket, data='')**\n Configure bucket tagging with xml data.\n\n**bucket_set_versioning(bucket, headers={}, data='')**\n Configure bucket versioning using xml data and request headers.\n\n**bucket_set_website(bucket, data='')**\n Configure bucket website with xml data.\n\n**storage.copy(remote_source, remote_destination, headers={})**\n Copy **remote_source** to **remote_destination**.\n\n The destination metadata is copied from **headers** when it\n contains metadata; otherwise it is copied from the source\n metadata.\n\n**storage.delete(remote_name)**\n Delete **remote_name** from storage.\n\n**exists, metadata = storage.exists(remote_name)**\n Test if **remote_name** exists in storage, retrieve its\n metadata if it does.\n\n exists - boolean, metadata - dict.\n\n**metadata = storage.read(remote_name, local_name)**\n Download **remote_name** from storage, save it locally as\n **local_name** and retrieve its metadata.\n\n metadata - dict.\n\n**storage.update_metadata(remote_name, headers)**\n Update (replace) the metadata associated with **remote_name**\n with the metadata headers in **headers**.\n\n**storage.write(local_name, remote_name, headers={})**\n Upload **local_name** to storage as **remote_name**, and set\n its metadata if any metadata headers are in **headers**.\n\nStorageError\n------------\n\nThere are two forms of exceptions. \n\nThe first form is when a request to S3 completes but fails. For example a \nread request may fail because the user does not have read permission. \nIn this case a StorageError is raised with:\n\n* msg - The name of the method that was called (e.g. 'read', 'exists', etc.)\n \n* exception - A detailed error message\n\n* response - The raw response object returned by requests.\n\nThe second form is when any other exception happens. For example a disk or \nnetwork error. In this case StorageError is raised with:\n\n* msg - A detailed error message.\n\n* exception - The exception object\n\n* response - None\n\nUsage\n=====\n\nConfiguration\n-------------\n\nFirst configure your yaml file.\n\n- **access_key_id** and **secret_access_key** are generated by the S3 \n account manager. They are effectively the username and password for the \n account.\n\n- **default_bucket** is the name of the default bucket to use when referencing\n S3 files. bucket names must be unique (on earth) so by convention we use a\n prefix on all our bucket names: com-prometheus- (NOTE: amazon forbids\n underscores in bucket names, and although they allow periods, periods will \n confound DNS - so it is best not to use periods in bucket names.\n \n- **endpoint** and **region** are the Amazon server url to connect to and\n its associated region. See \n http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region for a list\n of the available endpoints and their associated regions.\n\n- **tls** True => use https://, False => use http://. Default is True.\n\n- **retry** contains values used to retry requests.request().\n If a request fails with an error listed in `status_codes`,\n and the `limit` of tries has not been reached, \n then a retry message is logged,\n the program sleeps for `interval` seconds, \n and the request is sent again. \n Default is::\n\n retry:\n limit: 5\n interval: 2.5\n status_codes: \n - 104\n\n **limit** is the number of times to try to send the request.\n 0 means unlimited retries.\n\n **interval** is the number of seconds to wait between retries.\n\n **status_codes** is a list of request status codes (errors) to retry.\n \nHere is an example s3.yaml\n::\n\n ---\n s3: \n access_key_id: \"XXXXX\"\n secret_access_key: \"YYYYYYY\"\n default_bucket: \"ZZZZZZZ\"\n endpoint: \"s3-us-west-2.amazonaws.com\"\n region: \"us-west-2\"\n\nNext configure your S3 bucket permissions. You can use s3 to create, \nconfigure, and manage your buckets (see the examples below) or you can \nuse Amazon's web interface:\n\n- Log onto your Amazon account.\n- Create a bucket or click on an existing bucket.\n- Click on Properties.\n- Click on Permissions.\n- Click on Edit Bucket Policy.\n\nHere is a example policy with the required permissions:\n::\n\n {\n\t \"Version\": \"2008-10-17\",\n\t \"Id\": \"Policyxxxxxxxxxxxxx\",\n\t \"Statement\": [\n\t\t {\n\t\t\t \"Sid\": \"Stmtxxxxxxxxxxxxx\",\n\t\t\t \"Effect\": \"Allow\",\n\t\t\t \"Principal\": {\n\t\t\t\t \"AWS\": \"arn:aws:iam::xxxxxxxxxxxx:user/XXXXXXX\"\n\t\t\t },\n\t\t\t \"Action\": [\n\t\t\t\t \"s3:AbortMultipartUpload\",\n\t\t\t\t \"s3:GetObjectAcl\",\n\t\t\t\t \"s3:GetObjectVersion\",\n\t\t\t\t \"s3:DeleteObject\",\n\t\t\t\t \"s3:DeleteObjectVersion\",\n\t\t\t\t \"s3:GetObject\",\n\t\t\t\t \"s3:PutObjectAcl\",\n\t\t\t\t \"s3:PutObjectVersionAcl\",\n\t\t\t\t \"s3:ListMultipartUploadParts\",\n\t\t\t\t \"s3:PutObject\",\n\t\t\t\t \"s3:GetObjectVersionAcl\"\n\t\t\t ],\n\t\t\t \"Resource\": [\n\t\t\t\t \"arn:aws:s3:::com.prometheus.cgtest-1/*\",\n\t\t\t\t \"arn:aws:s3:::com.prometheus.cgtest-1\"\n\t\t\t ]\n\t\t }\n\t ]\n }\n\nExamples\n--------\n\nOnce the yaml file is configured you can instantiate a S3Connection and \nyou use that connection to instantiate a Storage instance.\n::\n\n import s3\n import yaml\n \n with open('s3.yaml', 'r') as fi:\n config = yaml.load(fi)\n\n connection = s3.S3Connection(**config['s3']) \n storage = s3.Storage(connection)\n\nThen you call methods on the Storage instance. \n\nThe following code creates a bucket called \"com-prometheus-my-bucket\" and \nasserts the bucket exists. Then it deletes the bucket, and asserts the \nbucket does not exist.\n::\n\n my_bucket_name = 'com-prometheus-my-bucket'\n storage.bucket_create(my_bucket_name)\n assert storage.bucket_exists(my_bucket_name)\n storage.bucket_delete(my_bucket_name)\n assert not storage.bucket_exists(my_bucket_name)\n\nThe following code lists all the buckets and all the keys in each bucket.\n::\n\n for bucket in storage.bucket_list():\n print bucket.name, bucket.creation_date\n for key in storage.bucket_list_keys(bucket.name):\n print '\\t', key.key, key.size, key.last_modified, key.owner.display_name\n \nThe following code uses the default bucket and uploads a file named \"example\" \nfrom the local filesystem as \"example-in-s3\" in s3. It then checks that \n\"example-in-s3\" exists in storage, downloads the file as \"example-from-s3\", \ncompares the original with the downloaded copy to ensure they are the same, \ndeletes \"example-in-s3\", and finally checks that it is no longer in storage.\n::\n\n import subprocess\n try:\n storage.write(\"example\", \"example-in-s3\")\n exists, metadata = storage.exists(\"example-in-s3\")\n assert exists\n metadata = storage.read(\"example-in-s3\", \"example-from-s3\")\n assert 0 == subprocess.call(['diff', \"example\", \"example-from-s3\"])\n storage.delete(\"example-in-s3\")\n exists, metadata = storage.exists(\"example-in-s3\")\n assert not exists\n except StorageError, e:\n print 'failed:', e\n \nThe following code again uploads \"example\" as \"example-in-s3\". This time it \nuses the bucket \"my-other-bucket\" explicitly, and it sets some metadata and \nchecks that the metadata is set correctly. Then it changes the metadata \nand checks that as well.\n::\n\n headers = {\n 'x-amz-meta-state': 'unprocessed',\n }\n remote_name = s3.S3Name(\"example-in-s3\", bucket=\"my-other-bucket\")\n try:\n storage.write(\"example\", remote_name, headers=headers)\n exists, metadata = storage.exists(remote_name)\n assert exists\n assert metadata == headers\n headers['x-amz-meta-state'] = 'processed'\n storage.update_metadata(remote_name, headers)\n metadata = storage.read(remote_name, \"example-from-s3\")\n assert metadata == headers\n except StorageError, e:\n print 'failed:', e\n\nThe following code configures \"com-prometheus-my-bucket\" with a policy \nthat restricts \"myuser\" to write-only. myuser can write files but \ncannot read them back, delete them, or even list them.\n::\n\n storage.bucket_set_policy(\"com-prometheus-my-bucket\", data={\n \"Version\": \"2008-10-17\",\n \"Id\": \"BucketUploadNoDelete\",\n \"Statement\": [\n {\n \"Sid\": \"Stmt01\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"AWS\": \"arn:aws:iam::123456789012:user/myuser\"\n },\n \"Action\": [\n \"s3:AbortMultipartUpload\",\n \"s3:ListMultipartUploadParts\",\n \"s3:PutObject\",\n ],\n \"Resource\": [\n \"arn:aws:s3:::com-prometheus-my-bucket/*\",\n \"arn:aws:s3:::com-prometheus-my-bucket\"\n ]\n }\n ]\n })\n\n\ns3 Command Line Tool\n====================\n\nThis package installs both the s3 Python module \nand the s3 command line tool.\n\nThe command line tool provides a convenient way to upload and download \nfiles to and from S3 without writing python code.\n\nAs of now the tool supports the put, get, delete, and list commands; \nbut it does not support all the features of the module API.\n\ns3 expects to find ``s3.yaml`` in the current directory.\nIf it is not there you must tell s3 where it is using the --config option.\nFor example::\n\n $ s3 --config /path/to/s3.yaml command [command arguments]\n\nYou must provide a command. Some commands have required arguments \nand/or optional arguments - it depends upon the command.\n\nUse the --help option to see \na list of supported commands and their arguments::\n\n $ s3 --help\n usage: s3 [-h] [-c CONFIG] [-v] [-b BUCKET]\n {get,put,delete,list,create-bucket,delete-bucket,list-buckets} ...\n\n Commands operate on the default bucket unless the --bucket option is used.\n\n Create a bucket\n create-bucket [bucket_name]\n The default bucket_name is the default bucket.\n \n Delete a file from S3\n delete delete_file\n\n Delete a bucket\n delete-bucket [bucket_name]\n The default bucket_name is the default bucket.\n\n Get a file from S3\n get remote_src [local_dst]\n\n List all files or list a single file and its metadata.\n list [list_file]\n\n List all buckets or list a single bucket. \n list-buckets [bucket_name]\n If bucket_name is given but does not exist, this is printed::\n \n '%s NOT FOUND' % bucket_name\n\n Put a file to S3\n put local_src [remote_dst]\n\n arguments:\n bucket_name\n The name of the bucket to use. \n delete_file\n The remote file to delete.\n list_file\n If present, the file to list (with its metadata),\n otherwise list all files.\n local_dst\n The name of the local file to create (or overwrite).\n The default is the basename of the remote_src.\n local_src\n The name of the local file to put.\n remote_dst\n The name of the s3 file to create (or overwrite).\n The default is the basename of the local_src.\n remote_src\n The name of the file in S3 to get.\n\n positional arguments:\n {get,put,delete,list,create-bucket,delete-bucket,list-buckets}\n\n optional arguments:\n -h, --help show this help message and exit\n -c CONFIG, --config CONFIG\n CONFIG is the configuration file to use.\n Default is s3.yaml\n -v, --verbose Show results of commands.\n -b BUCKET, --bucket BUCKET\n Use BUCKET instead of the default bucket.\n\nSee `s3 Command Line Tool`_ in the API Reference. \n\n.. _`s3 Command Line Tool`: reference.html#module-bin_s3", "description_content_type": null, "docs_url": "https://pythonhosted.org/s3/", "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://bitbucket.org/prometheus/s3/", "keywords": "amazon,aws,s3,upload,download", "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "s3", "package_url": "https://pypi.org/project/s3/", "platform": "Any", "project_url": "https://pypi.org/project/s3/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://bitbucket.org/prometheus/s3/" }, "release_url": "https://pypi.org/project/s3/3.0.0/", "requires_dist": null, "requires_python": null, "summary": "Python module which connects to Amazon's S3 REST API", "version": "3.0.0" }, "last_serial": 1565318, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "fd83170d33841bcfd3f9dbb7aebce439", "sha256": "2b704b1505ad6de795fc9c30f1ab0e46e0f39b49b3909c85594df3f88194c023" }, "downloads": -1, "filename": "s3-0.0.1.tar.gz", "has_sig": false, "md5_digest": "fd83170d33841bcfd3f9dbb7aebce439", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13934, "upload_time": "2014-05-20T16:55:28", "url": "https://files.pythonhosted.org/packages/04/0a/5e53a92519cf4c2414b34e59331e7843b035db4273e2fb583d36f82f1808/s3-0.0.1.tar.gz" } ], "0.0.2": [ { "comment_text": "", "digests": { "md5": "24d9c1d3708c615327cb32d4274e9c34", "sha256": "d052a3ca5f73978ccdac01767b9ac8a0eeebebc9acfcd2716f4ab38a81495c4b" }, "downloads": -1, "filename": "s3-0.0.2.tar.gz", "has_sig": false, "md5_digest": "24d9c1d3708c615327cb32d4274e9c34", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16694, "upload_time": "2014-05-28T22:02:10", "url": "https://files.pythonhosted.org/packages/af/b1/d8f2b020b579c12c37d6416b0922c5352a842e2b68604ff532bb2fee3dcf/s3-0.0.2.tar.gz" } ], "0.1.0": [ { "comment_text": "", "digests": { "md5": "6d0c0947e1f94d18332f260103509098", "sha256": "c1233ed1a5170941349bc20b3ec218aa43f213a13330ecdad10b2f5645a1bcdb" }, "downloads": -1, "filename": "s3-0.1.0.tar.gz", "has_sig": false, "md5_digest": "6d0c0947e1f94d18332f260103509098", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16294, "upload_time": "2014-06-03T21:01:51", "url": "https://files.pythonhosted.org/packages/16/8b/ed80cfc9fb8cbad42a76ad517c65ed5f9df9ded447a7cd824b8eab7d2aa5/s3-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "dbd9429a7dfc86cba34addaa6caeb05d", "sha256": "37f79cc58c173282b6d76df63f5f0271f18251efb9d2c7333a90ad85699ede93" }, "downloads": -1, "filename": "s3-0.1.1.tar.gz", "has_sig": false, "md5_digest": "dbd9429a7dfc86cba34addaa6caeb05d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16288, "upload_time": "2014-06-03T21:15:48", "url": "https://files.pythonhosted.org/packages/f8/dc/b7112f4eec7d5030481e37faa7bb2b7b4ccdb139420f7e4568e7ae733709/s3-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "28fcc7f91b33cbd507d9efa93016b5ea", "sha256": "a2fd2c6b2abf7fc3c533d180e3b4dc097b5ea64131dac9c4f685cc0b71f6749d" }, "downloads": -1, "filename": "s3-0.1.2.tar.gz", "has_sig": false, "md5_digest": "28fcc7f91b33cbd507d9efa93016b5ea", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16344, "upload_time": "2014-06-04T13:57:44", "url": "https://files.pythonhosted.org/packages/4c/ac/ec6fe82fba3c288afd0b845f77c0f852631f39ebfbeaf135a63eb1081084/s3-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "a5e1f2fa6c501140b2b947cde3717e05", "sha256": "e9e7fe0449d11bc1c45775c592a50d8d9132704bc665465d5d3a143eddbc9260" }, "downloads": -1, "filename": "s3-0.1.3.tar.gz", "has_sig": false, "md5_digest": "a5e1f2fa6c501140b2b947cde3717e05", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13921, "upload_time": "2014-06-11T22:25:53", "url": "https://files.pythonhosted.org/packages/8a/3e/92df6641cce27b107828ff52058830e2bc9ebd984185a25e8a0321f0b5de/s3-0.1.3.tar.gz" } ], "1.0.0": [ { "comment_text": "", "digests": { "md5": "5d45d2236d139998f88d8e5921593a6d", "sha256": "acc8c1a9b6b7ce349f640b0b0213616b9e4e05514c25b024be7829d682519700" }, "downloads": -1, "filename": "s3-1.0.0.tar.gz", "has_sig": false, "md5_digest": "5d45d2236d139998f88d8e5921593a6d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 31414, "upload_time": "2015-05-12T18:31:43", "url": "https://files.pythonhosted.org/packages/e5/18/fe9be997970235f3edd4098faf95bc7bc8352583be1a2faaa8e5e1dd900f/s3-1.0.0.tar.gz" } ], "2.0.0": [ { "comment_text": "", "digests": { "md5": "0609317463b177036a4a60fe029393a4", "sha256": "58dfa0b102713af2e7dc16dd442c056a3617c14e02230fac993690aafe66446b" }, "downloads": -1, "filename": "s3-2.0.0.tar.gz", "has_sig": false, "md5_digest": "0609317463b177036a4a60fe029393a4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32492, "upload_time": "2015-05-18T18:10:11", "url": "https://files.pythonhosted.org/packages/d2/6c/5b7a7e3d1c73bcdb2c59fdc9de4039e6b973437608ccfd7d8af7cf4eed5f/s3-2.0.0.tar.gz" } ], "3.0.0": [ { "comment_text": "", "digests": { "md5": "d6d73694eff10407cc92429a27121faf", "sha256": "d664698ecac6a08e71400a4d7f8ef8f3c672a1b85fe9a4449c0236ac5b80d2c8" }, "downloads": -1, "filename": "s3-3.0.0.tar.gz", "has_sig": false, "md5_digest": "d6d73694eff10407cc92429a27121faf", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 34812, "upload_time": "2015-05-27T21:04:01", "url": "https://files.pythonhosted.org/packages/a6/b5/7b135294de619e59aaf4e5a8005cab17348cf017635891777e09a8858d64/s3-3.0.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "d6d73694eff10407cc92429a27121faf", "sha256": "d664698ecac6a08e71400a4d7f8ef8f3c672a1b85fe9a4449c0236ac5b80d2c8" }, "downloads": -1, "filename": "s3-3.0.0.tar.gz", "has_sig": false, "md5_digest": "d6d73694eff10407cc92429a27121faf", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 34812, "upload_time": "2015-05-27T21:04:01", "url": "https://files.pythonhosted.org/packages/a6/b5/7b135294de619e59aaf4e5a8005cab17348cf017635891777e09a8858d64/s3-3.0.0.tar.gz" } ] }