New Upstream Release - requests-aws
Ready changes
Summary
Merged new upstream version: 0.1.8 (was: 0.1.5).
Resulting package
Built on 2023-03-14T23:05 (took 1m54s)
The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:
apt install -t fresh-releases python3-awsauth
Lintian Result
Diff
diff --git a/PKG-INFO b/PKG-INFO
index 443f220..ab963a8 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: requests-aws
-Version: 0.1.5
+Version: 0.1.8
Summary: AWS authentication for Amazon S3 for the python requests module
Home-page: https://github.com/tax/python-requests-aws
Author: Paul Tax
@@ -10,7 +10,9 @@ Description: #S3 using python-requests
AWS authentication for Amazon S3 for the wonderful [pyhon requests library](http://python-requests.org)
- - Tested with python 2.6 and python 3.3.2
+ [![Build Status](https://travis-ci.org/tax/python-requests-aws.svg?branch=master)](https://travis-ci.org/tax/python-requests-aws)
+
+ - Tested with python 2.7 and python 3
- At the moment only S3 is supported
## Usage
@@ -23,17 +25,18 @@ Description: #S3 using python-requests
ACCESS_KEY = 'ACCESSKEYXXXXXXXXXXXX'
SECRET_KEY = 'AWSSECRETKEYXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
- s = 'Sam is sweet'
+ url = 'http://mybuck.s3.amazonaws.com/file.txt'
+ s = 'Lola is sweet'
# Creating a file
- r = requests.put('http://mybuck.s3.amazonaws.com/file.txt', data=s, auth=S3Auth(ACCESS_KEY, SECRET_KEY))
+ r = requests.put(url, data=s, auth=S3Auth(ACCESS_KEY, SECRET_KEY))
# Downloading a file
- r = requests.get('http://mybuck.s3.amazonaws.com/file.txt', auth=S3Auth(ACCESS_KEY, SECRET_KEY))
- if r.text == 'Sam is sweet':
+ r = requests.get(url, auth=S3Auth(ACCESS_KEY, SECRET_KEY))
+ if r.text == 'Lola is sweet':
print "It works"
# Removing a file
- r = requests.delete('http://mybuck.s3.amazonaws.com/file.txt', auth=S3Auth(ACCESS_KEY, SECRET_KEY))
+ r = requests.delete(url, auth=S3Auth(ACCESS_KEY, SECRET_KEY))
```
@@ -44,6 +47,5 @@ Description: #S3 using python-requests
$ pip install requests-aws
```
- [![Build Status](https://travis-ci.org/tax/python-requests-aws.png?branch=master)](https://travis-ci.org/tax/python-requests-aws)
Platform: UNKNOWN
diff --git a/README.md b/README.md
index 9805601..0108f3b 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,9 @@
AWS authentication for Amazon S3 for the wonderful [pyhon requests library](http://python-requests.org)
-- Tested with python 2.6 and python 3.3.2
+[![Build Status](https://travis-ci.org/tax/python-requests-aws.svg?branch=master)](https://travis-ci.org/tax/python-requests-aws)
+
+- Tested with python 2.7 and python 3
- At the moment only S3 is supported
## Usage
@@ -15,17 +17,18 @@ from awsauth import S3Auth
ACCESS_KEY = 'ACCESSKEYXXXXXXXXXXXX'
SECRET_KEY = 'AWSSECRETKEYXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
-s = 'Sam is sweet'
+url = 'http://mybuck.s3.amazonaws.com/file.txt'
+s = 'Lola is sweet'
# Creating a file
-r = requests.put('http://mybuck.s3.amazonaws.com/file.txt', data=s, auth=S3Auth(ACCESS_KEY, SECRET_KEY))
+r = requests.put(url, data=s, auth=S3Auth(ACCESS_KEY, SECRET_KEY))
# Downloading a file
-r = requests.get('http://mybuck.s3.amazonaws.com/file.txt', auth=S3Auth(ACCESS_KEY, SECRET_KEY))
-if r.text == 'Sam is sweet':
+r = requests.get(url, auth=S3Auth(ACCESS_KEY, SECRET_KEY))
+if r.text == 'Lola is sweet':
print "It works"
# Removing a file
-r = requests.delete('http://mybuck.s3.amazonaws.com/file.txt', auth=S3Auth(ACCESS_KEY, SECRET_KEY))
+r = requests.delete(url, auth=S3Auth(ACCESS_KEY, SECRET_KEY))
```
@@ -36,4 +39,3 @@ Installing requests-aws is simple with pip:
$ pip install requests-aws
```
-[![Build Status](https://travis-ci.org/tax/python-requests-aws.png?branch=master)](https://travis-ci.org/tax/python-requests-aws)
diff --git a/awsauth.py b/awsauth.py
index 85cb2a4..221e70c 100644
--- a/awsauth.py
+++ b/awsauth.py
@@ -1,16 +1,16 @@
# -*- coding: utf-8 -*-
-import base64
import hmac
from hashlib import sha1 as sha
+import urllib
+
py3k = False
try:
- from urlparse import urlparse
+ from urlparse import urlparse, unquote
from base64 import encodestring
-
except:
py3k = True
- from urllib.parse import urlparse
+ from urllib.parse import urlparse, unquote
from base64 import encodebytes as encodestring
from email.utils import formatdate
@@ -29,7 +29,8 @@ class S3Auth(AuthBase):
'torrent', 'versioning', 'versionId', 'versions', 'website', 'uploads',
'uploadId', 'response-content-type', 'response-content-language',
'response-expires', 'response-cache-control', 'delete', 'lifecycle',
- 'response-content-disposition', 'response-content-encoding'
+ 'response-content-disposition', 'response-content-encoding', 'tagging',
+ 'notification', 'cors'
]
def __init__(self, access_key, secret_key, service_url=None):
@@ -40,7 +41,7 @@ class S3Auth(AuthBase):
def __call__(self, r):
# Create date header if it is not created yet.
- if not 'date' in r.headers and not 'x-amz-date' in r.headers:
+ if 'date' not in r.headers and 'x-amz-date' not in r.headers:
r.headers['date'] = formatdate(
timeval=None,
localtime=False,
@@ -83,7 +84,8 @@ class S3Auth(AuthBase):
lk = lk.decode('utf-8')
except:
pass
- if headers[key] and (lk in interesting_headers.keys() or lk.startswith('x-amz-')):
+ if headers[key] and (lk in interesting_headers.keys()
+ or lk.startswith('x-amz-')):
interesting_headers[lk] = headers[key].strip()
# If x-amz-date is used it supersedes the date header.
@@ -115,9 +117,35 @@ class S3Auth(AuthBase):
for q in query_args:
k = q.split('=')[0]
if k in self.special_params:
- if params_found:
- buf += '&%s' % q
- else:
- buf += '?%s' % q
+ buf += '&' if params_found else '?'
params_found = True
+
+ try:
+ k, v = q.split('=', 1)
+
+ except ValueError:
+ buf += q
+
+ else:
+ # Riak CS multipart upload ids look like this, `TFDSheOgTxC2Tsh1qVK73A==`,
+ # is should be escaped to be included as part of a query string.
+ #
+ # A requests mp upload part request may look like
+ # resp = requests.put(
+ # 'https://url_here',
+ # params={
+ # 'partNumber': 1,
+ # 'uploadId': 'TFDSheOgTxC2Tsh1qVK73A=='
+ # },
+ # data='some data',
+ # auth=S3Auth('access_key', 'secret_key')
+ # )
+ #
+ # Requests automatically escapes the values in the `params` dict, so now
+ # our uploadId is `TFDSheOgTxC2Tsh1qVK73A%3D%3D`,
+ # if we sign the request with the encoded value the signature will
+ # not be valid, we'll get 403 Access Denied.
+ # So we unquote, this is no-op if the value isn't encoded.
+ buf += '{key}={value}'.format(key=k, value=unquote(v))
+
return buf
diff --git a/debian/changelog b/debian/changelog
index 85c3894..e46ef09 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+requests-aws (0.1.8-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk> Tue, 14 Mar 2023 23:04:09 -0000
+
requests-aws (0.1.5-3) unstable; urgency=medium
[ Debian Janitor ]
diff --git a/example.py b/example.py
index d37c53a..cab545a 100644
--- a/example.py
+++ b/example.py
@@ -1,42 +1,42 @@
#!/usr/bin/env python
+from __future__ import print_function
import requests
-
from awsauth import S3Auth
-import StringIO
-
-import gzip
-
-import urllib
-
ACCESS_KEY = "ACCESSKEYXXXXXXXXXXXX"
SECRET_KEY = "AWSSECRETKEYXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
-acceptableAccessCodes = (200, 204) # # https://forums.aws.amazon.com/thread.jspa?threadID=28799: http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectDELETE.html
+# https://forums.aws.amazon.com/thread.jspa?threadID=28799:
+# http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectDELETE.html
+acceptable_accesscodes = (200, 204)
if __name__ == '__main__':
- confirmIt = u'Sam is sweet' # Data needs to be in unicode, or it will fail
+ # Data needs to be in unicode, or it will fail
+ data = u'Sam is sweet'
- bucketName = 'mybucket'
- objectName = ['myfile.txt', 'my+file.txt']
+ bucket = 'mybucket'
+ object_name = ['myfile.txt', 'my+file.txt']
- for o in objectName:
+ for o in object_name:
# Creating a file
- r = requests.put(('http://%s.s3.amazonaws.com/%s' % (bucketName, o)), data=confirmIt, auth=S3Auth(ACCESS_KEY, SECRET_KEY))
- if r.status_code not in acceptableAccessCodes:
+ url = 'http://{0}.s3.amazonaws.com/{1}'.format(bucket, o)
+ r = requests.put(url, data=data, auth=S3Auth(ACCESS_KEY, SECRET_KEY))
+ if r.status_code not in acceptable_accesscodes:
r.raise_for_status()
# Downloading a file
- r = requests.get(('http://%s.s3.amazonaws.com/%s' % (bucketName, o)), auth=S3Auth(ACCESS_KEY, SECRET_KEY))
- if r.status_code not in acceptableAccessCodes:
+ url = 'http://{0}.s3.amazonaws.com/{1}'.format(bucket, o)
+ r = requests.get(url, auth=S3Auth(ACCESS_KEY, SECRET_KEY))
+ if r.status_code not in acceptable_accesscodes:
r.raise_for_status()
- if r.content == confirmIt:
- print 'Hala Madrid!'
+ if r.content == data:
+ print('Hala Madrid!')
# Removing a file
- r = requests.delete(('http://%s.s3.amazonaws.com/%s' % (bucketName, o)), auth=S3Auth(ACCESS_KEY, SECRET_KEY))
- if r.status_code not in acceptableAccessCodes:
+ url = 'http://{0}.s3.amazonaws.com/{1}'.format(bucket, o)
+ r = requests.delete(url, auth=S3Auth(ACCESS_KEY, SECRET_KEY))
+ if r.status_code not in acceptable_accesscodes:
r.raise_for_status()
diff --git a/requests_aws.egg-info/PKG-INFO b/requests_aws.egg-info/PKG-INFO
index 443f220..ab963a8 100644
--- a/requests_aws.egg-info/PKG-INFO
+++ b/requests_aws.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: requests-aws
-Version: 0.1.5
+Version: 0.1.8
Summary: AWS authentication for Amazon S3 for the python requests module
Home-page: https://github.com/tax/python-requests-aws
Author: Paul Tax
@@ -10,7 +10,9 @@ Description: #S3 using python-requests
AWS authentication for Amazon S3 for the wonderful [pyhon requests library](http://python-requests.org)
- - Tested with python 2.6 and python 3.3.2
+ [![Build Status](https://travis-ci.org/tax/python-requests-aws.svg?branch=master)](https://travis-ci.org/tax/python-requests-aws)
+
+ - Tested with python 2.7 and python 3
- At the moment only S3 is supported
## Usage
@@ -23,17 +25,18 @@ Description: #S3 using python-requests
ACCESS_KEY = 'ACCESSKEYXXXXXXXXXXXX'
SECRET_KEY = 'AWSSECRETKEYXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
- s = 'Sam is sweet'
+ url = 'http://mybuck.s3.amazonaws.com/file.txt'
+ s = 'Lola is sweet'
# Creating a file
- r = requests.put('http://mybuck.s3.amazonaws.com/file.txt', data=s, auth=S3Auth(ACCESS_KEY, SECRET_KEY))
+ r = requests.put(url, data=s, auth=S3Auth(ACCESS_KEY, SECRET_KEY))
# Downloading a file
- r = requests.get('http://mybuck.s3.amazonaws.com/file.txt', auth=S3Auth(ACCESS_KEY, SECRET_KEY))
- if r.text == 'Sam is sweet':
+ r = requests.get(url, auth=S3Auth(ACCESS_KEY, SECRET_KEY))
+ if r.text == 'Lola is sweet':
print "It works"
# Removing a file
- r = requests.delete('http://mybuck.s3.amazonaws.com/file.txt', auth=S3Auth(ACCESS_KEY, SECRET_KEY))
+ r = requests.delete(url, auth=S3Auth(ACCESS_KEY, SECRET_KEY))
```
@@ -44,6 +47,5 @@ Description: #S3 using python-requests
$ pip install requests-aws
```
- [![Build Status](https://travis-ci.org/tax/python-requests-aws.png?branch=master)](https://travis-ci.org/tax/python-requests-aws)
Platform: UNKNOWN
diff --git a/requests_aws.egg-info/requires.txt b/requests_aws.egg-info/requires.txt
index 4659180..d0fee03 100644
--- a/requests_aws.egg-info/requires.txt
+++ b/requests_aws.egg-info/requires.txt
@@ -1 +1 @@
-requests>=0.14.0
\ No newline at end of file
+requests>=0.14.0
diff --git a/setup.py b/setup.py
index 10deb9f..8f84ebf 100644
--- a/setup.py
+++ b/setup.py
@@ -15,15 +15,14 @@ if sys.argv[-1] == 'publish':
setup(
name='requests-aws',
- version='0.1.5',
+ version='0.1.8',
author='Paul Tax',
author_email='paultax@gmail.com',
include_package_data=True,
- install_requires = ['requests>=0.14.0'],
+ install_requires=['requests>=0.14.0'],
py_modules=['awsauth'],
url='https://github.com/tax/python-requests-aws',
license='BSD licence, see LICENCE.txt',
description='AWS authentication for Amazon S3 for the python requests module',
long_description=open('README.md').read(),
)
-
diff --git a/test.py b/test.py
index 1d8f6e7..3fcc5ea 100644
--- a/test.py
+++ b/test.py
@@ -1,10 +1,19 @@
import unittest
import os
import requests
+import hashlib
+import sys
from awsauth import S3Auth
+PY3 = sys.version > '3'
-TEST_BUCKET = 'testpolpol'
+if PY3:
+ from base64 import encodebytes as encodestring
+else:
+ from base64 import encodestring
+
+
+TEST_BUCKET = 'testpolpol2'
ACCESS_KEY = 'ACCESSKEYXXXXXXXXXXXX'
SECRET_KEY = 'AWSSECRETKEYXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
if 'AWS_ACCESS_KEY' in os.environ:
@@ -12,31 +21,40 @@ if 'AWS_ACCESS_KEY' in os.environ:
if 'AWS_SECRET_KEY' in os.environ:
SECRET_KEY = os.environ['AWS_SECRET_KEY']
+
class TestAWS(unittest.TestCase):
def setUp(self):
- self.auth=S3Auth(ACCESS_KEY, SECRET_KEY)
-
+ self.auth = S3Auth(ACCESS_KEY, SECRET_KEY)
+
+ def get_content_md5(self, data):
+ hashdig = hashlib.md5(data.encode('utf-8').strip()).digest()
+ signature = encodestring(hashdig)
+ if PY3:
+ return signature.decode('utf-8').strip()
+ return signature.strip()
+
def test_put_get_delete(self):
+ url = 'http://' + TEST_BUCKET + '.s3.amazonaws.com/myfile.txt'
testdata = 'Sam is sweet'
- r = requests.put('http://'+ TEST_BUCKET + '.s3.amazonaws.com/myfile.txt', data=testdata, auth=self.auth)
+ r = requests.put(url, data=testdata, auth=self.auth)
self.assertEqual(r.status_code, 200)
# Downloading a file
- r = requests.get('http://'+ TEST_BUCKET + '.s3.amazonaws.com/myfile.txt', auth=self.auth)
- self.assertEqual(r.status_code, 200)
+ r = requests.get(url, auth=self.auth)
+ self.assertEqual(r.status_code, 200)
self.assertEqual(r.text, 'Sam is sweet')
# Removing a file
- r = requests.delete('http://'+ TEST_BUCKET + '.s3.amazonaws.com/myfile.txt', auth=self.auth)
- self.assertEqual(r.status_code, 204)
-
+ r = requests.delete(url, auth=self.auth)
+ self.assertEqual(r.status_code, 204)
+
def test_put_get_delete_filnamehasplus(self):
testdata = 'Sam is sweet'
filename = 'my+file.txt'
- url = 'http://'+ TEST_BUCKET + '.s3.amazonaws.com/%s'%(filename)
+ url = 'http://' + TEST_BUCKET + '.s3.amazonaws.com/%s' % (filename)
r = requests.put(url, data=testdata, auth=self.auth)
self.assertEqual(r.status_code, 200)
# Downloading a file
r = requests.get(url, auth=self.auth)
- self.assertEqual(r.status_code, 200)
+ self.assertEqual(r.status_code, 200)
self.assertEqual(r.text, testdata)
# Removing a file
r = requests.delete(url, auth=self.auth)
@@ -45,16 +63,87 @@ class TestAWS(unittest.TestCase):
def test_put_get_delete_filname_encoded(self):
testdata = 'Sam is sweet'
filename = 'my%20file.txt'
- url = 'http://'+ TEST_BUCKET + '.s3.amazonaws.com/%s'%(filename)
+ url = 'http://' + TEST_BUCKET + '.s3.amazonaws.com/%s' % (filename)
r = requests.put(url, data=testdata, auth=self.auth)
self.assertEqual(r.status_code, 200)
# Downloading a file
r = requests.get(url, auth=self.auth)
- self.assertEqual(r.status_code, 200)
+ self.assertEqual(r.status_code, 200)
self.assertEqual(r.text, testdata)
# Removing a file
r = requests.delete(url, auth=self.auth)
self.assertEqual(r.status_code, 204)
+ def test_put_get_delete_cors(self):
+ url = 'http://' + TEST_BUCKET + '.s3.amazonaws.com/?cors'
+ testdata = '<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">\
+ <CORSRule>\
+ <AllowedOrigin>*</AllowedOrigin>\
+ <AllowedMethod>POST</AllowedMethod>\
+ <MaxAgeSeconds>3000</MaxAgeSeconds>\
+ <AllowedHeader>Authorization</AllowedHeader>\
+ </CORSRule>\
+ </CORSConfiguration>'
+ headers = {'content-md5': self.get_content_md5(testdata)}
+ r = requests.put(url, data=testdata, auth=self.auth, headers=headers)
+ self.assertEqual(r.status_code, 200)
+ # Downloading current cors configuration
+ r = requests.get(url, auth=self.auth)
+ self.assertEqual(r.status_code, 200)
+ # Removing removing cors configuration
+ r = requests.delete(url, auth=self.auth)
+ self.assertEqual(r.status_code, 204)
+
+ def test_put_get_delete_tagging(self):
+ url = 'http://' + TEST_BUCKET + '.s3.amazonaws.com/?tagging'
+ testdata = '<Tagging>\
+ <TagSet>\
+ <Tag>\
+ <Key>Project</Key>\
+ <Value>Project 1</Value>\
+ </Tag>\
+ </TagSet>\
+ </Tagging>'
+ headers = {'content-md5': self.get_content_md5(testdata)}
+ r = requests.put(url, data=testdata, auth=self.auth, headers=headers)
+ self.assertEqual(r.status_code, 204)
+ # Downloading current cors configuration
+ r = requests.get(url, auth=self.auth)
+ self.assertEqual(r.status_code, 200)
+ # Removing removing cors configuration
+ r = requests.delete(url, auth=self.auth)
+ self.assertEqual(r.status_code, 204)
+
+ def test_put_get_notification(self):
+ url = 'http://' + TEST_BUCKET + '.s3.amazonaws.com/?notification'
+ testdata = '<NotificationConfiguration></NotificationConfiguration>'
+ headers = {'content-md5': self.get_content_md5(testdata)}
+ r = requests.put(url, data=testdata, auth=self.auth, headers=headers)
+ self.assertEqual(r.status_code, 200)
+ # Downloading current cors configuration
+ r = requests.get(url, auth=self.auth)
+ self.assertEqual(r.status_code, 200)
+ # No Delete ?notification API, empty <NotificationConfiguration>
+ # tag is default
+
+ def test_canonical_string_not_using_encoded_query_params(self):
+ url = 'https://bucket.ca.tier3.io/object-name?partNumber=1&uploadId=TFDSheOgTxC2Tsh1qVK73A%3D%3D' # NOQA
+ headers = {
+ 'Content-Length': 0,
+ 'Accept-Encoding': 'gzip, deflate',
+ 'Accept': '*/*',
+ 'User-Agent': 'python-requests/2.7.0 CPython/2.7.6 Linux/3.13.0-24-generic',
+ 'Connection': 'keep-alive',
+ 'date': 'Fri, 21 Aug 2015 16:08:26 GMT',
+ }
+ method = 'PUT'
+ canonical_string = self.auth.get_canonical_string(url, headers, method)
+ self.assertTrue('TFDSheOgTxC2Tsh1qVK73A%3D%3D' not in canonical_string)
+ self.assertTrue('TFDSheOgTxC2Tsh1qVK73A==' in canonical_string)
+
+ url = 'https://bucket.ca.tier3.io/object-name?partNumber=1&uploadId=not%escaped'
+ canonical_string = self.auth.get_canonical_string(url, headers, method)
+ self.assertTrue('not%escaped' in canonical_string)
+
if __name__ == '__main__':
unittest.main()
Debdiff
[The following lists of changes regard files as different if they have different names, permissions or owners.]
Files in second set of .debs but not in first
-rw-r--r-- root/root /usr/lib/python3/dist-packages/requests_aws-0.1.8.egg-info/PKG-INFO -rw-r--r-- root/root /usr/lib/python3/dist-packages/requests_aws-0.1.8.egg-info/dependency_links.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/requests_aws-0.1.8.egg-info/requires.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/requests_aws-0.1.8.egg-info/top_level.txt
Files in first set of .debs but not in second
-rw-r--r-- root/root /usr/lib/python3/dist-packages/requests_aws-0.1.5.egg-info/PKG-INFO -rw-r--r-- root/root /usr/lib/python3/dist-packages/requests_aws-0.1.5.egg-info/dependency_links.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/requests_aws-0.1.5.egg-info/requires.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/requests_aws-0.1.5.egg-info/top_level.txt
No differences were encountered in the control files