diff -Nru python-boto-2.40.0/boto/auth.py python-boto-2.44.0/boto/auth.py --- python-boto-2.40.0/boto/auth.py 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/boto/auth.py 2016-12-08 23:54:36.000000000 +0000 @@ -59,7 +59,13 @@ '.eu-central', '-eu-central', '.ap-northeast-2', - '-ap-northeast-2' + '-ap-northeast-2', + '.ap-south-1', + '-ap-south-1', + '.us-east-2', + '-us-east-2', + '-ca-central', + '.ca-central' ] @@ -771,8 +777,8 @@ # Add signature to params now that we have it req.params['X-Amz-Signature'] = signature - return 'https://%s%s?%s' % (req.host, req.path, - urllib.parse.urlencode(req.params)) + return '%s://%s%s?%s' % (req.protocol, req.host, req.path, + urllib.parse.urlencode(req.params)) class STSAnonHandler(AuthHandler): diff -Nru python-boto-2.40.0/boto/dynamodb2/table.py python-boto-2.44.0/boto/dynamodb2/table.py --- python-boto-2.40.0/boto/dynamodb2/table.py 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/boto/dynamodb2/table.py 2016-12-08 23:54:36.000000000 +0000 @@ -669,7 +669,7 @@ should be fetched) Returns an ``Item`` instance containing all the data for that record. - + Raises an ``ItemNotFound`` exception if the item is not found. Example:: @@ -1581,9 +1581,9 @@ }) results.append(item) - raw_unproccessed = raw_results.get('UnprocessedKeys', {}) + raw_unprocessed = raw_results.get('UnprocessedKeys', {}).get(self.table_name, {}) - for raw_key in raw_unproccessed.get('Keys', []): + for raw_key in raw_unprocessed.get('Keys', []): py_key = {} for key, value in raw_key.items(): diff -Nru python-boto-2.40.0/boto/ec2/connection.py python-boto-2.44.0/boto/ec2/connection.py --- python-boto-2.40.0/boto/ec2/connection.py 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/boto/ec2/connection.py 2016-12-08 23:54:36.000000000 +0000 @@ -2650,7 +2650,7 @@ # get all the snapshots, sort them by date and time, and # organize them into one array for each volume: all_snapshots = self.get_all_snapshots(owner = 'self') - all_snapshots.sort(cmp = lambda x, y: cmp(x.start_time, y.start_time)) + all_snapshots.sort(key=lambda x: x.start_time) snaps_for_each_volume = {} for snap in all_snapshots: # the snapshot name and the volume name are the same. diff -Nru python-boto-2.40.0/boto/endpoints.json python-boto-2.44.0/boto/endpoints.json --- python-boto-2.40.0/boto/endpoints.json 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/boto/endpoints.json 2016-12-08 23:54:36.000000000 +0000 @@ -2,33 +2,45 @@ "autoscaling": { "ap-northeast-1": "autoscaling.ap-northeast-1.amazonaws.com", "ap-northeast-2": "autoscaling.ap-northeast-2.amazonaws.com", + "ap-south-1": "autoscaling.ap-south-1.amazonaws.com", "ap-southeast-1": "autoscaling.ap-southeast-1.amazonaws.com", "ap-southeast-2": "autoscaling.ap-southeast-2.amazonaws.com", + "ca-central-1": "autoscaling.ca-central-1.amazonaws.com", "cn-north-1": "autoscaling.cn-north-1.amazonaws.com.cn", "eu-central-1": "autoscaling.eu-central-1.amazonaws.com", "eu-west-1": "autoscaling.eu-west-1.amazonaws.com", "sa-east-1": "autoscaling.sa-east-1.amazonaws.com", "us-east-1": "autoscaling.us-east-1.amazonaws.com", + "us-east-2": "autoscaling.us-east-2.amazonaws.com", "us-gov-west-1": "autoscaling.us-gov-west-1.amazonaws.com", "us-west-1": "autoscaling.us-west-1.amazonaws.com", "us-west-2": "autoscaling.us-west-2.amazonaws.com" }, "awslambda": { "ap-northeast-1": "lambda.ap-northeast-1.amazonaws.com", + "ap-northeast-2": "lambda.ap-northeast-2.amazonaws.com", + "ap-southeast-1": "lambda.ap-southeast-1.amazonaws.com", + "ap-southeast-2": "lambda.ap-southeast-2.amazonaws.com", + "eu-central-1": "lambda.eu-central-1.amazonaws.com", "eu-west-1": "lambda.eu-west-1.amazonaws.com", "us-east-1": "lambda.us-east-1.amazonaws.com", + "us-east-2": "lambda.us-east-2.amazonaws.com", + "us-west-1": "lambda.us-west-1.amazonaws.com", "us-west-2": "lambda.us-west-2.amazonaws.com" }, "cloudformation": { "ap-northeast-1": "cloudformation.ap-northeast-1.amazonaws.com", "ap-northeast-2": "cloudformation.ap-northeast-2.amazonaws.com", + "ap-south-1": "cloudformation.ap-south-1.amazonaws.com", "ap-southeast-1": "cloudformation.ap-southeast-1.amazonaws.com", "ap-southeast-2": "cloudformation.ap-southeast-2.amazonaws.com", + "ca-central-1": "cloudformation.ca-central-1.amazonaws.com", "cn-north-1": "cloudformation.cn-north-1.amazonaws.com.cn", "eu-central-1": "cloudformation.eu-central-1.amazonaws.com", "eu-west-1": "cloudformation.eu-west-1.amazonaws.com", "sa-east-1": "cloudformation.sa-east-1.amazonaws.com", "us-east-1": "cloudformation.us-east-1.amazonaws.com", + "us-east-2": "cloudformation.us-east-2.amazonaws.com", "us-gov-west-1": "cloudformation.us-gov-west-1.amazonaws.com", "us-west-1": "cloudformation.us-west-1.amazonaws.com", "us-west-2": "cloudformation.us-west-2.amazonaws.com" @@ -36,12 +48,15 @@ "cloudfront": { "ap-northeast-1": "cloudfront.amazonaws.com", "ap-northeast-2": "cloudfront.amazonaws.com", + "ap-south-1": "cloudfront.amazonaws.com", "ap-southeast-1": "cloudfront.amazonaws.com", "ap-southeast-2": "cloudfront.amazonaws.com", + "ca-central-1": "cloudfront.amazonaws.com", "eu-central-1": "cloudfront.amazonaws.com", "eu-west-1": "cloudfront.amazonaws.com", "sa-east-1": "cloudfront.amazonaws.com", "us-east-1": "cloudfront.amazonaws.com", + "us-east-2": "cloudfront.amazonaws.com", "us-west-1": "cloudfront.amazonaws.com", "us-west-2": "cloudfront.amazonaws.com" }, @@ -49,14 +64,18 @@ "ap-northeast-1": "cloudhsm.ap-northeast-1.amazonaws.com", "ap-southeast-1": "cloudhsm.ap-southeast-1.amazonaws.com", "ap-southeast-2": "cloudhsm.ap-southeast-2.amazonaws.com", + "ca-central-1": "cloudhsm.ca-central-1.amazonaws.com", "eu-central-1": "cloudhsm.eu-central-1.amazonaws.com", "eu-west-1": "cloudhsm.eu-west-1.amazonaws.com", "us-east-1": "cloudhsm.us-east-1.amazonaws.com", + "us-east-2": "cloudhsm.us-east-2.amazonaws.com", "us-gov-west-1": "cloudhsm.us-gov-west-1.amazonaws.com", + "us-west-1": "cloudhsm.us-west-1.amazonaws.com", "us-west-2": "cloudhsm.us-west-2.amazonaws.com" }, "cloudsearch": { "ap-northeast-1": "cloudsearch.ap-northeast-1.amazonaws.com", + "ap-northeast-2": "cloudsearch.ap-northeast-2.amazonaws.com", "ap-southeast-1": "cloudsearch.ap-southeast-1.amazonaws.com", "ap-southeast-2": "cloudsearch.ap-southeast-2.amazonaws.com", "eu-central-1": "cloudsearch.eu-central-1.amazonaws.com", @@ -68,6 +87,7 @@ }, "cloudsearchdomain": { "ap-northeast-1": "cloudsearch.ap-northeast-1.amazonaws.com", + "ap-northeast-2": "cloudsearch.ap-northeast-2.amazonaws.com", "ap-southeast-1": "cloudsearch.ap-southeast-1.amazonaws.com", "ap-southeast-2": "cloudsearch.ap-southeast-2.amazonaws.com", "eu-central-1": "cloudsearch.eu-central-1.amazonaws.com", @@ -80,13 +100,16 @@ "cloudtrail": { "ap-northeast-1": "cloudtrail.ap-northeast-1.amazonaws.com", "ap-northeast-2": "cloudtrail.ap-northeast-2.amazonaws.com", + "ap-south-1": "cloudtrail.ap-south-1.amazonaws.com", "ap-southeast-1": "cloudtrail.ap-southeast-1.amazonaws.com", "ap-southeast-2": "cloudtrail.ap-southeast-2.amazonaws.com", + "ca-central-1": "cloudtrail.ca-central-1.amazonaws.com", "cn-north-1": "cloudtrail.cn-north-1.amazonaws.com.cn", "eu-central-1": "cloudtrail.eu-central-1.amazonaws.com", "eu-west-1": "cloudtrail.eu-west-1.amazonaws.com", "sa-east-1": "cloudtrail.sa-east-1.amazonaws.com", "us-east-1": "cloudtrail.us-east-1.amazonaws.com", + "us-east-2": "cloudtrail.us-east-2.amazonaws.com", "us-gov-west-1": "cloudtrail.us-gov-west-1.amazonaws.com", "us-west-1": "cloudtrail.us-west-1.amazonaws.com", "us-west-2": "cloudtrail.us-west-2.amazonaws.com" @@ -94,13 +117,16 @@ "cloudwatch": { "ap-northeast-1": "monitoring.ap-northeast-1.amazonaws.com", "ap-northeast-2": "monitoring.ap-northeast-2.amazonaws.com", + "ap-south-1": "monitoring.ap-south-1.amazonaws.com", "ap-southeast-1": "monitoring.ap-southeast-1.amazonaws.com", "ap-southeast-2": "monitoring.ap-southeast-2.amazonaws.com", + "ca-central-1": "monitoring.ca-central-1.amazonaws.com", "cn-north-1": "monitoring.cn-north-1.amazonaws.com.cn", "eu-central-1": "monitoring.eu-central-1.amazonaws.com", "eu-west-1": "monitoring.eu-west-1.amazonaws.com", "sa-east-1": "monitoring.sa-east-1.amazonaws.com", "us-east-1": "monitoring.us-east-1.amazonaws.com", + "us-east-2": "monitoring.us-east-2.amazonaws.com", "us-gov-west-1": "monitoring.us-gov-west-1.amazonaws.com", "us-west-1": "monitoring.us-west-1.amazonaws.com", "us-west-2": "monitoring.us-west-2.amazonaws.com" @@ -108,32 +134,48 @@ "codedeploy": { "ap-northeast-1": "codedeploy.ap-northeast-1.amazonaws.com", "ap-northeast-2": "codedeploy.ap-northeast-2.amazonaws.com", + "ap-south-1": "codedeploy.ap-south-1.amazonaws.com", "ap-southeast-1": "codedeploy.ap-southeast-1.amazonaws.com", "ap-southeast-2": "codedeploy.ap-southeast-2.amazonaws.com", + "ca-central-1": "codedeploy.ca-central-1.amazonaws.com", "eu-central-1": "codedeploy.eu-central-1.amazonaws.com", "eu-west-1": "codedeploy.eu-west-1.amazonaws.com", + "sa-east-1": "codedeploy.sa-east-1.amazonaws.com", "us-east-1": "codedeploy.us-east-1.amazonaws.com", + "us-east-2": "codedeploy.us-east-2.amazonaws.com", "us-west-1": "codedeploy.us-west-1.amazonaws.com", "us-west-2": "codedeploy.us-west-2.amazonaws.com" }, "cognito-identity": { "ap-northeast-1": "cognito-identity.ap-northeast-1.amazonaws.com", + "ap-northeast-2": "cognito-identity.ap-northeast-2.amazonaws.com", + "eu-central-1": "cognito-identity.eu-central-1.amazonaws.com", "eu-west-1": "cognito-identity.eu-west-1.amazonaws.com", - "us-east-1": "cognito-identity.us-east-1.amazonaws.com" + "us-east-1": "cognito-identity.us-east-1.amazonaws.com", + "us-west-2": "cognito-identity.us-west-2.amazonaws.com" }, "cognito-sync": { "ap-northeast-1": "cognito-sync.ap-northeast-1.amazonaws.com", + "ap-northeast-2": "cognito-sync.ap-northeast-2.amazonaws.com", + "eu-central-1": "cognito-sync.eu-central-1.amazonaws.com", "eu-west-1": "cognito-sync.eu-west-1.amazonaws.com", - "us-east-1": "cognito-sync.us-east-1.amazonaws.com" + "us-east-1": "cognito-sync.us-east-1.amazonaws.com", + "us-west-2": "cognito-sync.us-west-2.amazonaws.com" }, "configservice": { "ap-northeast-1": "config.ap-northeast-1.amazonaws.com", + "ap-northeast-2": "config.ap-northeast-2.amazonaws.com", + "ap-south-1": "config.ap-south-1.amazonaws.com", "ap-southeast-1": "config.ap-southeast-1.amazonaws.com", "ap-southeast-2": "config.ap-southeast-2.amazonaws.com", + "ca-central-1": "config.ca-central-1.amazonaws.com", + "cn-north-1": "config.cn-north-1.amazonaws.com.cn", "eu-central-1": "config.eu-central-1.amazonaws.com", "eu-west-1": "config.eu-west-1.amazonaws.com", "sa-east-1": "config.sa-east-1.amazonaws.com", "us-east-1": "config.us-east-1.amazonaws.com", + "us-east-2": "config.us-east-2.amazonaws.com", + "us-gov-west-1": "config.us-gov-west-1.amazonaws.com", "us-west-1": "config.us-west-1.amazonaws.com", "us-west-2": "config.us-west-2.amazonaws.com" }, @@ -147,26 +189,33 @@ "directconnect": { "ap-northeast-1": "directconnect.ap-northeast-1.amazonaws.com", "ap-northeast-2": "directconnect.ap-northeast-2.amazonaws.com", + "ap-south-1": "directconnect.ap-south-1.amazonaws.com", "ap-southeast-1": "directconnect.ap-southeast-1.amazonaws.com", "ap-southeast-2": "directconnect.ap-southeast-2.amazonaws.com", + "ca-central-1": "directconnect.ca-central-1.amazonaws.com", "cn-north-1": "directconnect.cn-north-1.amazonaws.com.cn", "eu-central-1": "directconnect.eu-central-1.amazonaws.com", "eu-west-1": "directconnect.eu-west-1.amazonaws.com", "sa-east-1": "directconnect.sa-east-1.amazonaws.com", "us-east-1": "directconnect.us-east-1.amazonaws.com", + "us-east-2": "directconnect.us-east-2.amazonaws.com", + "us-gov-west-1": "directconnect.us-gov-west-1.amazonaws.com", "us-west-1": "directconnect.us-west-1.amazonaws.com", "us-west-2": "directconnect.us-west-2.amazonaws.com" }, "dynamodb": { "ap-northeast-1": "dynamodb.ap-northeast-1.amazonaws.com", "ap-northeast-2": "dynamodb.ap-northeast-2.amazonaws.com", + "ap-south-1": "dynamodb.ap-south-1.amazonaws.com", "ap-southeast-1": "dynamodb.ap-southeast-1.amazonaws.com", "ap-southeast-2": "dynamodb.ap-southeast-2.amazonaws.com", + "ca-central-1": "dynamodb.ca-central-1.amazonaws.com", "cn-north-1": "dynamodb.cn-north-1.amazonaws.com.cn", "eu-central-1": "dynamodb.eu-central-1.amazonaws.com", "eu-west-1": "dynamodb.eu-west-1.amazonaws.com", "sa-east-1": "dynamodb.sa-east-1.amazonaws.com", "us-east-1": "dynamodb.us-east-1.amazonaws.com", + "us-east-2": "dynamodb.us-east-2.amazonaws.com", "us-gov-west-1": "dynamodb.us-gov-west-1.amazonaws.com", "us-west-1": "dynamodb.us-west-1.amazonaws.com", "us-west-2": "dynamodb.us-west-2.amazonaws.com" @@ -174,35 +223,45 @@ "ec2": { "ap-northeast-1": "ec2.ap-northeast-1.amazonaws.com", "ap-northeast-2": "ec2.ap-northeast-2.amazonaws.com", + "ap-south-1": "ec2.ap-south-1.amazonaws.com", "ap-southeast-1": "ec2.ap-southeast-1.amazonaws.com", "ap-southeast-2": "ec2.ap-southeast-2.amazonaws.com", + "ca-central-1": "ec2.ca-central-1.amazonaws.com", "cn-north-1": "ec2.cn-north-1.amazonaws.com.cn", "eu-central-1": "ec2.eu-central-1.amazonaws.com", "eu-west-1": "ec2.eu-west-1.amazonaws.com", "sa-east-1": "ec2.sa-east-1.amazonaws.com", "us-east-1": "ec2.us-east-1.amazonaws.com", + "us-east-2": "ec2.us-east-2.amazonaws.com", "us-gov-west-1": "ec2.us-gov-west-1.amazonaws.com", "us-west-1": "ec2.us-west-1.amazonaws.com", "us-west-2": "ec2.us-west-2.amazonaws.com" }, "ec2containerservice": { "ap-northeast-1": "ecs.ap-northeast-1.amazonaws.com", + "ap-southeast-1": "ecs.ap-southeast-1.amazonaws.com", "ap-southeast-2": "ecs.ap-southeast-2.amazonaws.com", + "ca-central-1": "ecs.ca-central-1.amazonaws.com", + "eu-central-1": "ecs.eu-central-1.amazonaws.com", "eu-west-1": "ecs.eu-west-1.amazonaws.com", "us-east-1": "ecs.us-east-1.amazonaws.com", + "us-east-2": "ecs.us-east-2.amazonaws.com", "us-west-1": "ecs.us-west-1.amazonaws.com", "us-west-2": "ecs.us-west-2.amazonaws.com" }, "elasticache": { "ap-northeast-1": "elasticache.ap-northeast-1.amazonaws.com", "ap-northeast-2": "elasticache.ap-northeast-2.amazonaws.com", + "ap-south-1": "elasticache.ap-south-1.amazonaws.com", "ap-southeast-1": "elasticache.ap-southeast-1.amazonaws.com", "ap-southeast-2": "elasticache.ap-southeast-2.amazonaws.com", + "ca-central-1": "elasticache.ca-central-1.amazonaws.com", "cn-north-1": "elasticache.cn-north-1.amazonaws.com.cn", "eu-central-1": "elasticache.eu-central-1.amazonaws.com", "eu-west-1": "elasticache.eu-west-1.amazonaws.com", "sa-east-1": "elasticache.sa-east-1.amazonaws.com", "us-east-1": "elasticache.us-east-1.amazonaws.com", + "us-east-2": "elasticache.us-east-2.amazonaws.com", "us-gov-west-1": "elasticache.us-gov-west-1.amazonaws.com", "us-west-1": "elasticache.us-west-1.amazonaws.com", "us-west-2": "elasticache.us-west-2.amazonaws.com" @@ -210,26 +269,32 @@ "elasticbeanstalk": { "ap-northeast-1": "elasticbeanstalk.ap-northeast-1.amazonaws.com", "ap-northeast-2": "elasticbeanstalk.ap-northeast-2.amazonaws.com", + "ap-south-1": "elasticbeanstalk.ap-south-1.amazonaws.com", "ap-southeast-1": "elasticbeanstalk.ap-southeast-1.amazonaws.com", "ap-southeast-2": "elasticbeanstalk.ap-southeast-2.amazonaws.com", + "ca-central-1": "elasticbeanstalk.ca-central-1.amazonaws.com", "cn-north-1": "elasticbeanstalk.cn-north-1.amazonaws.com.cn", "eu-central-1": "elasticbeanstalk.eu-central-1.amazonaws.com", "eu-west-1": "elasticbeanstalk.eu-west-1.amazonaws.com", "sa-east-1": "elasticbeanstalk.sa-east-1.amazonaws.com", "us-east-1": "elasticbeanstalk.us-east-1.amazonaws.com", + "us-east-2": "elasticbeanstalk.us-east-2.amazonaws.com", "us-west-1": "elasticbeanstalk.us-west-1.amazonaws.com", "us-west-2": "elasticbeanstalk.us-west-2.amazonaws.com" }, "elasticloadbalancing": { "ap-northeast-1": "elasticloadbalancing.ap-northeast-1.amazonaws.com", "ap-northeast-2": "elasticloadbalancing.ap-northeast-2.amazonaws.com", + "ap-south-1": "elasticloadbalancing.ap-south-1.amazonaws.com", "ap-southeast-1": "elasticloadbalancing.ap-southeast-1.amazonaws.com", "ap-southeast-2": "elasticloadbalancing.ap-southeast-2.amazonaws.com", + "ca-central-1": "elasticloadbalancing.ca-central-1.amazonaws.com", "cn-north-1": "elasticloadbalancing.cn-north-1.amazonaws.com.cn", "eu-central-1": "elasticloadbalancing.eu-central-1.amazonaws.com", "eu-west-1": "elasticloadbalancing.eu-west-1.amazonaws.com", "sa-east-1": "elasticloadbalancing.sa-east-1.amazonaws.com", "us-east-1": "elasticloadbalancing.us-east-1.amazonaws.com", + "us-east-2": "elasticloadbalancing.us-east-2.amazonaws.com", "us-gov-west-1": "elasticloadbalancing.us-gov-west-1.amazonaws.com", "us-west-1": "elasticloadbalancing.us-west-1.amazonaws.com", "us-west-2": "elasticloadbalancing.us-west-2.amazonaws.com" @@ -237,20 +302,25 @@ "elasticmapreduce": { "ap-northeast-1": "ap-northeast-1.elasticmapreduce.amazonaws.com", "ap-northeast-2": "ap-northeast-2.elasticmapreduce.amazonaws.com", + "ap-south-1": "ap-south-1.elasticmapreduce.amazonaws.com", "ap-southeast-1": "ap-southeast-1.elasticmapreduce.amazonaws.com", "ap-southeast-2": "ap-southeast-2.elasticmapreduce.amazonaws.com", + "ca-central-1": "ca-central-1.elasticmapreduce.amazonaws.com", "cn-north-1": "elasticmapreduce.cn-north-1.amazonaws.com.cn", "eu-central-1": "elasticmapreduce.eu-central-1.amazonaws.com", "eu-west-1": "eu-west-1.elasticmapreduce.amazonaws.com", "sa-east-1": "sa-east-1.elasticmapreduce.amazonaws.com", "us-east-1": "elasticmapreduce.us-east-1.amazonaws.com", + "us-east-2": "us-east-2.elasticmapreduce.amazonaws.com", "us-gov-west-1": "elasticmapreduce.us-gov-west-1.amazonaws.com", "us-west-1": "us-west-1.elasticmapreduce.amazonaws.com", "us-west-2": "us-west-2.elasticmapreduce.amazonaws.com" }, "elastictranscoder": { "ap-northeast-1": "elastictranscoder.ap-northeast-1.amazonaws.com", + "ap-south-1": "elastictranscoder.ap-south-1.amazonaws.com", "ap-southeast-1": "elastictranscoder.ap-southeast-1.amazonaws.com", + "ap-southeast-2": "elastictranscoder.ap-southeast-2.amazonaws.com", "eu-west-1": "elastictranscoder.eu-west-1.amazonaws.com", "us-east-1": "elastictranscoder.us-east-1.amazonaws.com", "us-west-1": "elastictranscoder.us-west-1.amazonaws.com", @@ -259,11 +329,14 @@ "glacier": { "ap-northeast-1": "glacier.ap-northeast-1.amazonaws.com", "ap-northeast-2": "glacier.ap-northeast-2.amazonaws.com", + "ap-south-1": "glacier.ap-south-1.amazonaws.com", "ap-southeast-2": "glacier.ap-southeast-2.amazonaws.com", + "ca-central-1": "glacier.ca-central-1.amazonaws.com", "cn-north-1": "glacier.cn-north-1.amazonaws.com.cn", "eu-central-1": "glacier.eu-central-1.amazonaws.com", "eu-west-1": "glacier.eu-west-1.amazonaws.com", "us-east-1": "glacier.us-east-1.amazonaws.com", + "us-east-2": "glacier.us-east-2.amazonaws.com", "us-gov-west-1": "glacier.us-gov-west-1.amazonaws.com", "us-west-1": "glacier.us-west-1.amazonaws.com", "us-west-2": "glacier.us-west-2.amazonaws.com" @@ -271,13 +344,16 @@ "iam": { "ap-northeast-1": "iam.amazonaws.com", "ap-northeast-2": "iam.amazonaws.com", + "ap-south-1": "iam.amazonaws.com", "ap-southeast-1": "iam.amazonaws.com", "ap-southeast-2": "iam.amazonaws.com", + "ca-central-1": "iam.amazonaws.com", "cn-north-1": "iam.cn-north-1.amazonaws.com.cn", "eu-central-1": "iam.amazonaws.com", "eu-west-1": "iam.amazonaws.com", "sa-east-1": "iam.amazonaws.com", "us-east-1": "iam.amazonaws.com", + "us-east-2": "iam.amazonaws.com", "us-gov-west-1": "iam.us-gov.amazonaws.com", "us-west-1": "iam.amazonaws.com", "us-west-2": "iam.amazonaws.com" @@ -285,37 +361,46 @@ "importexport": { "ap-northeast-1": "importexport.amazonaws.com", "ap-northeast-2": "importexport.amazonaws.com", + "ap-south-1": "importexport.amazonaws.com", "ap-southeast-1": "importexport.amazonaws.com", "ap-southeast-2": "importexport.amazonaws.com", + "ca-central-1": "importexport.amazonaws.com", "eu-central-1": "importexport.amazonaws.com", "eu-west-1": "importexport.amazonaws.com", "sa-east-1": "importexport.amazonaws.com", "us-east-1": "importexport.amazonaws.com", + "us-east-2": "importexport.amazonaws.com", "us-west-1": "importexport.amazonaws.com", "us-west-2": "importexport.amazonaws.com" }, "kinesis": { "ap-northeast-1": "kinesis.ap-northeast-1.amazonaws.com", "ap-northeast-2": "kinesis.ap-northeast-2.amazonaws.com", + "ap-south-1": "kinesis.ap-south-1.amazonaws.com", "ap-southeast-1": "kinesis.ap-southeast-1.amazonaws.com", "ap-southeast-2": "kinesis.ap-southeast-2.amazonaws.com", + "ca-central-1": "kinesis.ca-central-1.amazonaws.com", "cn-north-1": "kinesis.cn-north-1.amazonaws.com.cn", "eu-central-1": "kinesis.eu-central-1.amazonaws.com", - "sa-east-1": "kinesis.sa-east-1.amazonaws.com", "eu-west-1": "kinesis.eu-west-1.amazonaws.com", + "sa-east-1": "kinesis.sa-east-1.amazonaws.com", "us-east-1": "kinesis.us-east-1.amazonaws.com", + "us-east-2": "kinesis.us-east-2.amazonaws.com", "us-west-1": "kinesis.us-west-1.amazonaws.com", "us-west-2": "kinesis.us-west-2.amazonaws.com" }, "kms": { "ap-northeast-1": "kms.ap-northeast-1.amazonaws.com", "ap-northeast-2": "kms.ap-northeast-2.amazonaws.com", + "ap-south-1": "kms.ap-south-1.amazonaws.com", "ap-southeast-1": "kms.ap-southeast-1.amazonaws.com", "ap-southeast-2": "kms.ap-southeast-2.amazonaws.com", + "ca-central-1": "kms.ca-central-1.amazonaws.com", "eu-central-1": "kms.eu-central-1.amazonaws.com", "eu-west-1": "kms.eu-west-1.amazonaws.com", "sa-east-1": "kms.sa-east-1.amazonaws.com", "us-east-1": "kms.us-east-1.amazonaws.com", + "us-east-2": "kms.us-east-2.amazonaws.com", "us-gov-west-1": "kms.us-gov-west-1.amazonaws.com", "us-west-1": "kms.us-west-1.amazonaws.com", "us-west-2": "kms.us-west-2.amazonaws.com" @@ -323,11 +408,17 @@ "logs": { "ap-northeast-1": "logs.ap-northeast-1.amazonaws.com", "ap-northeast-2": "logs.ap-northeast-2.amazonaws.com", + "ap-south-1": "logs.ap-south-1.amazonaws.com", "ap-southeast-1": "logs.ap-southeast-1.amazonaws.com", "ap-southeast-2": "logs.ap-southeast-2.amazonaws.com", + "ca-central-1": "logs.ca-central-1.amazonaws.com", + "cn-north-1": "logs.cn-north-1.amazonaws.com.cn", "eu-central-1": "logs.eu-central-1.amazonaws.com", "eu-west-1": "logs.eu-west-1.amazonaws.com", + "sa-east-1": "logs.sa-east-1.amazonaws.com", "us-east-1": "logs.us-east-1.amazonaws.com", + "us-east-2": "logs.us-east-2.amazonaws.com", + "us-gov-west-1": "logs.us-gov-west-1.amazonaws.com", "us-west-1": "logs.us-west-1.amazonaws.com", "us-west-2": "logs.us-west-2.amazonaws.com" }, @@ -336,18 +427,32 @@ "us-east-1": "machinelearning.us-east-1.amazonaws.com" }, "opsworks": { - "us-east-1": "opsworks.us-east-1.amazonaws.com" + "ap-northeast-1": "opsworks.ap-northeast-1.amazonaws.com", + "ap-northeast-2": "opsworks.ap-northeast-2.amazonaws.com", + "ap-south-1": "opsworks.ap-south-1.amazonaws.com", + "ap-southeast-1": "opsworks.ap-southeast-1.amazonaws.com", + "ap-southeast-2": "opsworks.ap-southeast-2.amazonaws.com", + "eu-central-1": "opsworks.eu-central-1.amazonaws.com", + "eu-west-1": "opsworks.eu-west-1.amazonaws.com", + "sa-east-1": "opsworks.sa-east-1.amazonaws.com", + "us-east-1": "opsworks.us-east-1.amazonaws.com", + "us-east-2": "opsworks.us-east-2.amazonaws.com", + "us-west-1": "opsworks.us-west-1.amazonaws.com", + "us-west-2": "opsworks.us-west-2.amazonaws.com" }, "rds": { "ap-northeast-1": "rds.ap-northeast-1.amazonaws.com", "ap-northeast-2": "rds.ap-northeast-2.amazonaws.com", + "ap-south-1": "rds.ap-south-1.amazonaws.com", "ap-southeast-1": "rds.ap-southeast-1.amazonaws.com", "ap-southeast-2": "rds.ap-southeast-2.amazonaws.com", + "ca-central-1": "rds.ca-central-1.amazonaws.com", "cn-north-1": "rds.cn-north-1.amazonaws.com.cn", "eu-central-1": "rds.eu-central-1.amazonaws.com", "eu-west-1": "rds.eu-west-1.amazonaws.com", "sa-east-1": "rds.sa-east-1.amazonaws.com", "us-east-1": "rds.amazonaws.com", + "us-east-2": "rds.us-east-2.amazonaws.com", "us-gov-west-1": "rds.us-gov-west-1.amazonaws.com", "us-west-1": "rds.us-west-1.amazonaws.com", "us-west-2": "rds.us-west-2.amazonaws.com" @@ -355,23 +460,32 @@ "redshift": { "ap-northeast-1": "redshift.ap-northeast-1.amazonaws.com", "ap-northeast-2": "redshift.ap-northeast-2.amazonaws.com", + "ap-south-1": "redshift.ap-south-1.amazonaws.com", "ap-southeast-1": "redshift.ap-southeast-1.amazonaws.com", "ap-southeast-2": "redshift.ap-southeast-2.amazonaws.com", + "ca-central-1": "redshift.ca-central-1.amazonaws.com", + "cn-north-1": "redshift.cn-north-1.amazonaws.com.cn", "eu-central-1": "redshift.eu-central-1.amazonaws.com", "eu-west-1": "redshift.eu-west-1.amazonaws.com", + "sa-east-1": "redshift.sa-east-1.amazonaws.com", "us-east-1": "redshift.us-east-1.amazonaws.com", + "us-east-2": "redshift.us-east-2.amazonaws.com", "us-gov-west-1": "redshift.us-gov-west-1.amazonaws.com", + "us-west-1": "redshift.us-west-1.amazonaws.com", "us-west-2": "redshift.us-west-2.amazonaws.com" }, "route53": { "ap-northeast-1": "route53.amazonaws.com", "ap-northeast-2": "route53.amazonaws.com", + "ap-south-1": "route53.amazonaws.com", "ap-southeast-1": "route53.amazonaws.com", "ap-southeast-2": "route53.amazonaws.com", + "ca-central-1": "route53.amazonaws.com", "eu-central-1": "route53.amazonaws.com", "eu-west-1": "route53.amazonaws.com", "sa-east-1": "route53.amazonaws.com", "us-east-1": "route53.amazonaws.com", + "us-east-2": "route53.amazonaws.com", "us-west-1": "route53.amazonaws.com", "us-west-2": "route53.amazonaws.com" }, @@ -381,13 +495,16 @@ "s3": { "ap-northeast-1": "s3-ap-northeast-1.amazonaws.com", "ap-northeast-2": "s3.ap-northeast-2.amazonaws.com", + "ap-south-1": "s3.ap-south-1.amazonaws.com", "ap-southeast-1": "s3-ap-southeast-1.amazonaws.com", "ap-southeast-2": "s3-ap-southeast-2.amazonaws.com", + "ca-central-1": "s3.ca-central-1.amazonaws.com", "cn-north-1": "s3.cn-north-1.amazonaws.com.cn", "eu-central-1": "s3.eu-central-1.amazonaws.com", "eu-west-1": "s3-eu-west-1.amazonaws.com", "sa-east-1": "s3-sa-east-1.amazonaws.com", "us-east-1": "s3.amazonaws.com", + "us-east-2": "s3.us-east-2.amazonaws.com", "us-gov-west-1": "s3-us-gov-west-1.amazonaws.com", "us-west-1": "s3-us-west-1.amazonaws.com", "us-west-2": "s3-us-west-2.amazonaws.com" @@ -410,13 +527,16 @@ "sns": { "ap-northeast-1": "sns.ap-northeast-1.amazonaws.com", "ap-northeast-2": "sns.ap-northeast-2.amazonaws.com", + "ap-south-1": "sns.ap-south-1.amazonaws.com", "ap-southeast-1": "sns.ap-southeast-1.amazonaws.com", "ap-southeast-2": "sns.ap-southeast-2.amazonaws.com", + "ca-central-1": "sns.ca-central-1.amazonaws.com", "cn-north-1": "sns.cn-north-1.amazonaws.com.cn", "eu-central-1": "sns.eu-central-1.amazonaws.com", "eu-west-1": "sns.eu-west-1.amazonaws.com", "sa-east-1": "sns.sa-east-1.amazonaws.com", "us-east-1": "sns.us-east-1.amazonaws.com", + "us-east-2": "sns.us-east-2.amazonaws.com", "us-gov-west-1": "sns.us-gov-west-1.amazonaws.com", "us-west-1": "sns.us-west-1.amazonaws.com", "us-west-2": "sns.us-west-2.amazonaws.com" @@ -424,39 +544,48 @@ "sqs": { "ap-northeast-1": "ap-northeast-1.queue.amazonaws.com", "ap-northeast-2": "ap-northeast-2.queue.amazonaws.com", + "ap-south-1": "ap-south-1.queue.amazonaws.com", "ap-southeast-1": "ap-southeast-1.queue.amazonaws.com", "ap-southeast-2": "ap-southeast-2.queue.amazonaws.com", + "ca-central-1": "ca-central-1.queue.amazonaws.com", "cn-north-1": "cn-north-1.queue.amazonaws.com.cn", "eu-central-1": "eu-central-1.queue.amazonaws.com", "eu-west-1": "eu-west-1.queue.amazonaws.com", "sa-east-1": "sa-east-1.queue.amazonaws.com", "us-east-1": "queue.amazonaws.com", + "us-east-2": "us-east-2.queue.amazonaws.com", "us-gov-west-1": "us-gov-west-1.queue.amazonaws.com", "us-west-1": "us-west-1.queue.amazonaws.com", "us-west-2": "us-west-2.queue.amazonaws.com" }, "storagegateway": { "ap-northeast-1": "storagegateway.ap-northeast-1.amazonaws.com", + "ap-northeast-2": "storagegateway.ap-northeast-2.amazonaws.com", "ap-southeast-1": "storagegateway.ap-southeast-1.amazonaws.com", "ap-southeast-2": "storagegateway.ap-southeast-2.amazonaws.com", + "ca-central-1": "storagegateway.ca-central-1.amazonaws.com", "cn-north-1": "storagegateway.cn-north-1.amazonaws.com.cn", "eu-central-1": "storagegateway.eu-central-1.amazonaws.com", "eu-west-1": "storagegateway.eu-west-1.amazonaws.com", "sa-east-1": "storagegateway.sa-east-1.amazonaws.com", "us-east-1": "storagegateway.us-east-1.amazonaws.com", + "us-east-2": "storagegateway.us-east-2.amazonaws.com", "us-west-1": "storagegateway.us-west-1.amazonaws.com", "us-west-2": "storagegateway.us-west-2.amazonaws.com" }, "sts": { "ap-northeast-1": "sts.amazonaws.com", - "ap-northeast-2": "sts.amazonaws.com", + "ap-northeast-2": "sts.ap-northeast-2.amazonaws.com", + "ap-south-1": "sts.amazonaws.com", "ap-southeast-1": "sts.amazonaws.com", "ap-southeast-2": "sts.amazonaws.com", + "ca-central-1": "sts.amazonaws.com", "cn-north-1": "sts.cn-north-1.amazonaws.com.cn", "eu-central-1": "sts.amazonaws.com", "eu-west-1": "sts.amazonaws.com", "sa-east-1": "sts.amazonaws.com", "us-east-1": "sts.amazonaws.com", + "us-east-2": "sts.amazonaws.com", "us-gov-west-1": "sts.us-gov-west-1.amazonaws.com", "us-west-1": "sts.amazonaws.com", "us-west-2": "sts.amazonaws.com" @@ -467,13 +596,16 @@ "swf": { "ap-northeast-1": "swf.ap-northeast-1.amazonaws.com", "ap-northeast-2": "swf.ap-northeast-2.amazonaws.com", + "ap-south-1": "swf.ap-south-1.amazonaws.com", "ap-southeast-1": "swf.ap-southeast-1.amazonaws.com", "ap-southeast-2": "swf.ap-southeast-2.amazonaws.com", + "ca-central-1": "swf.ca-central-1.amazonaws.com", "cn-north-1": "swf.cn-north-1.amazonaws.com.cn", "eu-central-1": "swf.eu-central-1.amazonaws.com", "eu-west-1": "swf.eu-west-1.amazonaws.com", "sa-east-1": "swf.sa-east-1.amazonaws.com", "us-east-1": "swf.us-east-1.amazonaws.com", + "us-east-2": "swf.us-east-2.amazonaws.com", "us-gov-west-1": "swf.us-gov-west-1.amazonaws.com", "us-west-1": "swf.us-west-1.amazonaws.com", "us-west-2": "swf.us-west-2.amazonaws.com" diff -Nru python-boto-2.40.0/boto/gs/bucket.py python-boto-2.44.0/boto/gs/bucket.py --- python-boto-2.40.0/boto/gs/bucket.py 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/boto/gs/bucket.py 2016-12-08 23:54:36.000000000 +0000 @@ -44,11 +44,14 @@ STANDARD_ACL = 'acl' CORS_ARG = 'cors' LIFECYCLE_ARG = 'lifecycle' +STORAGE_CLASS_ARG='storageClass' ERROR_DETAILS_REGEX = re.compile(r'
(?P
.*)
') class Bucket(S3Bucket): """Represents a Google Cloud Storage bucket.""" + StorageClassBody = ('\n' + '%s') VersioningBody = ('\n' '%s' '') @@ -599,7 +602,7 @@ :return: The StorageClass for the bucket. """ response = self.connection.make_request('GET', self.name, - query_args='storageClass') + query_args=STORAGE_CLASS_ARG) body = response.read() if response.status == 200: rs = ResultSet(self) @@ -610,6 +613,15 @@ raise self.connection.provider.storage_response_error( response.status, response.reason, body) + def set_storage_class(self, storage_class, headers=None): + """ + Sets a bucket's storage class. + + :param str storage_class: A string containing the storage class. + :param dict headers: Additional headers to send with the request. + """ + req_body = self.StorageClassBody % (get_utf8_value(storage_class)) + self.set_subresource(STORAGE_CLASS_ARG, req_body, headers=headers) # Method with same signature as boto.s3.bucket.Bucket.add_email_grant(), # to allow polymorphic treatment at application layer. diff -Nru python-boto-2.40.0/boto/gs/key.py python-boto-2.44.0/boto/gs/key.py --- python-boto-2.40.0/boto/gs/key.py 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/boto/gs/key.py 2016-12-08 23:54:36.000000000 +0000 @@ -131,6 +131,8 @@ self.content_encoding = value elif key == 'x-goog-stored-content-length': self.size = int(value) + elif key == 'x-goog-storage-class': + self.storage_class = value def open_read(self, headers=None, query_args='', override_num_retries=None, response_headers=None): diff -Nru python-boto-2.40.0/boto/gs/lifecycle.py python-boto-2.44.0/boto/gs/lifecycle.py --- python-boto-2.40.0/boto/gs/lifecycle.py 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/boto/gs/lifecycle.py 2016-12-08 23:54:36.000000000 +0000 @@ -22,26 +22,25 @@ from boto.exception import InvalidLifecycleConfigError # Relevant tags for the lifecycle configuration XML document. -LIFECYCLE_CONFIG = 'LifecycleConfiguration' -RULE = 'Rule' -ACTION = 'Action' -DELETE = 'Delete' -CONDITION = 'Condition' -AGE = 'Age' -CREATED_BEFORE = 'CreatedBefore' -NUM_NEWER_VERSIONS = 'NumberOfNewerVersions' -IS_LIVE = 'IsLive' +LIFECYCLE_CONFIG = 'LifecycleConfiguration' +RULE = 'Rule' +ACTION = 'Action' +DELETE = 'Delete' +SET_STORAGE_CLASS = 'SetStorageClass' +CONDITION = 'Condition' +AGE = 'Age' +CREATED_BEFORE = 'CreatedBefore' +NUM_NEWER_VERSIONS = 'NumberOfNewerVersions' +IS_LIVE = 'IsLive' +MATCHES_STORAGE_CLASS = 'MatchesStorageClass' # List of all action elements. -LEGAL_ACTIONS = [DELETE] -# List of all action parameter elements. -LEGAL_ACTION_PARAMS = [] +LEGAL_ACTIONS = [DELETE, SET_STORAGE_CLASS] # List of all condition elements. -LEGAL_CONDITIONS = [AGE, CREATED_BEFORE, NUM_NEWER_VERSIONS, IS_LIVE] -# Dictionary mapping actions to supported action parameters for each action. -LEGAL_ACTION_ACTION_PARAMS = { - DELETE: [], -} +LEGAL_CONDITIONS = [AGE, CREATED_BEFORE, NUM_NEWER_VERSIONS, IS_LIVE, + MATCHES_STORAGE_CLASS] +# List of conditions elements that may be repeated. +LEGAL_REPEATABLE_CONDITIONS = [MATCHES_STORAGE_CLASS] class Rule(object): """ @@ -49,17 +48,16 @@ :ivar action: Action to be taken. - :ivar action_params: A dictionary of action specific parameters. Each item - in the dictionary represents the name and value of an action parameter. + :ivar action_text: The text value for the specified action, if any. :ivar conditions: A dictionary of conditions that specify when the action - should be taken. Each item in the dictionary represents the name and value - of a condition. + should be taken. Each item in the dictionary represents the name and + value (or a list of multiple values, if applicable) of a condition. """ - def __init__(self, action=None, action_params=None, conditions=None): + def __init__(self, action=None, action_text=None, conditions=None): self.action = action - self.action_params = action_params or {} + self.action_text = action_text self.conditions = conditions or {} # Name of the current enclosing tag (used to validate the schema). @@ -88,23 +86,15 @@ raise InvalidLifecycleConfigError( 'Only one action tag is allowed in each rule') self.action = name - elif name in LEGAL_ACTION_PARAMS: - # Make sure this tag is found in an action tag. - if self.current_tag not in LEGAL_ACTIONS: - raise InvalidLifecycleConfigError( - 'Tag %s found outside of action' % name) - # Make sure this tag is allowed for the current action tag. - if name not in LEGAL_ACTION_ACTION_PARAMS[self.action]: - raise InvalidLifecycleConfigError( - 'Tag %s not allowed in action %s' % (name, self.action)) elif name == CONDITION: self.validateStartTag(name, RULE) elif name in LEGAL_CONDITIONS: self.validateStartTag(name, CONDITION) # Verify there is no duplicate conditions. - if name in self.conditions: + if (name in self.conditions and + name not in LEGAL_REPEATABLE_CONDITIONS): raise InvalidLifecycleConfigError( - 'Found duplicate conditions %s' % name) + 'Found duplicate non-repeatable conditions %s' % name) else: raise InvalidLifecycleConfigError('Unsupported tag ' + name) self.current_tag = name @@ -118,17 +108,20 @@ elif name == ACTION: self.current_tag = RULE elif name in LEGAL_ACTIONS: + if name == SET_STORAGE_CLASS and value is not None: + self.action_text = value.strip() self.current_tag = ACTION - elif name in LEGAL_ACTION_PARAMS: - self.current_tag = self.action - # Add the action parameter name and value to the dictionary. - self.action_params[name] = value.strip() elif name == CONDITION: self.current_tag = RULE elif name in LEGAL_CONDITIONS: self.current_tag = CONDITION - # Add the condition name and value to the dictionary. - self.conditions[name] = value.strip() + # Some conditions specify a list of values. + if name in LEGAL_REPEATABLE_CONDITIONS: + if name not in self.conditions: + self.conditions[name] = [] + self.conditions[name].append(value.strip()) + else: + self.conditions[name] = value.strip() else: raise InvalidLifecycleConfigError('Unsupported end tag ' + name) @@ -143,26 +136,32 @@ def to_xml(self): """Convert the rule into XML string representation.""" - s = '<' + RULE + '>' - s += '<' + ACTION + '>' - if self.action_params: - s += '<' + self.action + '>' - for param in LEGAL_ACTION_PARAMS: - if param in self.action_params: - s += ('<' + param + '>' + self.action_params[param] + '') - s += '' + s = ['<' + RULE + '>'] + s.append('<' + ACTION + '>') + if self.action_text: + s.extend(['<' + self.action + '>', + self.action_text, + '']) else: - s += '<' + self.action + '/>' - s += '' - s += '<' + CONDITION + '>' - for condition in LEGAL_CONDITIONS: - if condition in self.conditions: - s += ('<' + condition + '>' + self.conditions[condition] + '') - s += '' - s += '' - return s + s.append('<' + self.action + '/>') + s.append('') + s.append('<' + CONDITION + '>') + for condition_name in self.conditions: + if condition_name not in LEGAL_CONDITIONS: + continue + if condition_name in LEGAL_REPEATABLE_CONDITIONS: + condition_values = self.conditions[condition_name] + else: + # Wrap condition value in a list, allowing us to iterate over + # all condition values using the same logic. + condition_values = [self.conditions[condition_name]] + for condition_value in condition_values: + s.extend(['<' + condition_name + '>', + condition_value, + '']) + s.append('') + s.append('') + return ''.join(s) class LifecycleConfig(list): """ @@ -196,14 +195,14 @@ def to_xml(self): """Convert LifecycleConfig object into XML string representation.""" - s = '' - s += '<' + LIFECYCLE_CONFIG + '>' + s = [''] + s.append('<' + LIFECYCLE_CONFIG + '>') for rule in self: - s += rule.to_xml() - s += '' - return s + s.append(rule.to_xml()) + s.append('') + return ''.join(s) - def add_rule(self, action, action_params, conditions): + def add_rule(self, action, action_text, conditions): """ Add a rule to this Lifecycle configuration. This only adds the rule to the local copy. To install the new rule(s) on the bucket, you need to @@ -213,15 +212,13 @@ :type action: str :param action: Action to be taken. - :type action_params: dict - :param action_params: A dictionary of action specific parameters. Each - item in the dictionary represents the name and value of an action - parameter. + :type action_text: str + :param action_text: Value for the specified action. :type conditions: dict :param conditions: A dictionary of conditions that specify when the action should be taken. Each item in the dictionary represents the name and value of a condition. """ - rule = Rule(action, action_params, conditions) + rule = Rule(action, action_text, conditions) self.append(rule) diff -Nru python-boto-2.40.0/boto/__init__.py python-boto-2.44.0/boto/__init__.py --- python-boto-2.40.0/boto/__init__.py 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/boto/__init__.py 2016-12-08 23:54:36.000000000 +0000 @@ -38,7 +38,7 @@ from boto.compat import urlparse from boto.exception import InvalidUriError -__version__ = '2.40.0' +__version__ = '2.44.0' Version = __version__ # for backware compatibility # http://bugs.python.org/issue7980 diff -Nru python-boto-2.40.0/boto/mturk/connection.py python-boto-2.44.0/boto/mturk/connection.py --- python-boto-2.40.0/boto/mturk/connection.py 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/boto/mturk/connection.py 2016-12-08 23:54:36.000000000 +0000 @@ -39,7 +39,7 @@ class MTurkConnection(AWSQueryConnection): - APIVersion = '2012-03-25' + APIVersion = '2014-08-15' def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, is_secure=True, port=None, proxy=None, proxy_port=None, diff -Nru python-boto-2.40.0/boto/mturk/qualification.py python-boto-2.44.0/boto/mturk/qualification.py --- python-boto-2.40.0/boto/mturk/qualification.py 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/boto/mturk/qualification.py 2016-12-08 23:54:36.000000000 +0000 @@ -55,7 +55,10 @@ "QualificationTypeId": self.qualification_type_id, "Comparator": self.comparator, } - if self.comparator != 'Exists' and self.integer_value is not None: + if self.comparator in ('In', 'NotIn'): + for i, integer_value in enumerate(self.integer_value, 1): + params['IntegerValue.%d' % i] = integer_value + elif self.comparator not in ('Exists', 'DoesNotExist') and self.integer_value is not None: params['IntegerValue'] = self.integer_value if self.required_to_preview: params['RequiredToPreview'] = "true" @@ -104,6 +107,11 @@ class NumberHitsApprovedRequirement(Requirement): """ Specifies the total number of HITs submitted by a Worker that have been approved. The value is an integer greater than or equal to 0. + + If specifying a Country and Subdivision, use a tuple of valid ISO 3166 country code and ISO 3166-2 subdivision code, e.g. ('US', 'CA') for the US State of California. + + When using the 'In' and 'NotIn', locale should be a list of Countries and/or (Country, Subdivision) tuples. + """ def __init__(self, comparator, integer_value, required_to_preview=False): @@ -122,8 +130,20 @@ params = { "QualificationTypeId": self.qualification_type_id, "Comparator": self.comparator, - 'LocaleValue.Country': self.locale, } + if self.comparator in ('In', 'NotIn'): + for i, locale in enumerate(self.locale, 1): + if isinstance(locale, tuple): + params['LocaleValue.%d.Country' % i] = locale[0] + params['LocaleValue.%d.Subdivision' % i] = locale[1] + else: + params['LocaleValue.%d.Country' % i] = locale + else: + if isinstance(self.locale, tuple): + params['LocaleValue.Country'] = self.locale[0] + params['LocaleValue.Subdivision'] = self.locale[1] + else: + params['LocaleValue.Country'] = self.locale if self.required_to_preview: params['RequiredToPreview'] = "true" return params diff -Nru python-boto-2.40.0/boto/storage_uri.py python-boto-2.44.0/boto/storage_uri.py --- python-boto-2.40.0/boto/storage_uri.py 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/boto/storage_uri.py 2016-12-08 23:54:36.000000000 +0000 @@ -444,14 +444,25 @@ def get_storage_class(self, validate=False, headers=None): self._check_bucket_uri('get_storage_class') - # StorageClass is defined as a bucket param for GCS, but as a key - # param for S3. + # StorageClass is defined as a bucket and object param for GCS, but + # only as a key param for S3. if self.scheme != 'gs': raise ValueError('get_storage_class() not supported for %s ' 'URIs.' % self.scheme) bucket = self.get_bucket(validate, headers) return bucket.get_storage_class() + def set_storage_class(self, storage_class, validate=False, headers=None): + """Updates a bucket's storage class.""" + self._check_bucket_uri('set_storage_class') + # StorageClass is defined as a bucket and object param for GCS, but + # only as a key param for S3. + if self.scheme != 'gs': + raise ValueError('set_storage_class() not supported for %s ' + 'URIs.' % self.scheme) + bucket = self.get_bucket(validate, headers) + bucket.set_storage_class(storage_class, headers) + def get_subresource(self, subresource, validate=False, headers=None, version_id=None): self._check_bucket_uri('get_subresource') diff -Nru python-boto-2.40.0/debian/changelog python-boto-2.44.0/debian/changelog --- python-boto-2.40.0/debian/changelog 2017-02-03 22:08:16.000000000 +0000 +++ python-boto-2.44.0/debian/changelog 2017-02-03 22:08:16.000000000 +0000 @@ -1,3 +1,22 @@ +python-boto (2.44.0-1ubuntu1) zesty; urgency=medium + + * Merge from Debian unstable. Remaining changes: + * d/tests/unit: Fix autopkgtest error in test_timeout. + + -- Jon Grimm Fri, 03 Feb 2017 13:15:39 -0600 + +python-boto (2.44.0-1) unstable; urgency=medium + + * New upstream release. + + -- Eric Evans Sat, 10 Dec 2016 14:31:42 -0600 + +python-boto (2.43.0-1) unstable; urgency=medium + + * New upstream release. + + -- Eric Evans Tue, 08 Nov 2016 21:17:35 -0600 + python-boto (2.40.0-1ubuntu1) yakkety; urgency=low * Merge from Debian unstable. Remaining changes: diff -Nru python-boto-2.40.0/docs/source/index.rst python-boto-2.44.0/docs/source/index.rst --- python-boto-2.40.0/docs/source/index.rst 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/docs/source/index.rst 2016-12-08 23:54:36.000000000 +0000 @@ -152,6 +152,10 @@ .. toctree:: :titlesonly: + releasenotes/v2.44.0 + releasenotes/v2.43.0 + releasenotes/v2.42.0 + releasenotes/v2.41.0 releasenotes/v2.40.0 releasenotes/v2.39.0 releasenotes/v2.38.0 diff -Nru python-boto-2.40.0/docs/source/releasenotes/v2.41.0.rst python-boto-2.44.0/docs/source/releasenotes/v2.41.0.rst --- python-boto-2.40.0/docs/source/releasenotes/v2.41.0.rst 1970-01-01 00:00:00.000000000 +0000 +++ python-boto-2.44.0/docs/source/releasenotes/v2.41.0.rst 2016-12-08 23:54:36.000000000 +0000 @@ -0,0 +1,12 @@ +boto v2.41.0 +============ + +:date: 2016/06/27 + +Update documentation and endpoints file. + +Changes +------- +* Update endpoints.json (:issue:`3564`, :sha:`5e786b4`) +* Remove the broken link to PDF's (:issue:`3562`, :sha:`46ffb0c`) + diff -Nru python-boto-2.40.0/docs/source/releasenotes/v2.42.0.rst python-boto-2.44.0/docs/source/releasenotes/v2.42.0.rst --- python-boto-2.40.0/docs/source/releasenotes/v2.42.0.rst 1970-01-01 00:00:00.000000000 +0000 +++ python-boto-2.44.0/docs/source/releasenotes/v2.42.0.rst 2016-12-08 23:54:36.000000000 +0000 @@ -0,0 +1,11 @@ +boto v2.42.0 +============ + +:date: 2016/07/19 + +Updates the Mechanical Turk API and fixes some bugs. + +Changes +------- +* Respect is_secure parameter in generate_url_sigv4 (:sha:`59ba28d`) +* Update MTurk API (:issue:`3563`, :sha:`250d891`) diff -Nru python-boto-2.40.0/docs/source/releasenotes/v2.43.0.rst python-boto-2.44.0/docs/source/releasenotes/v2.43.0.rst --- python-boto-2.40.0/docs/source/releasenotes/v2.43.0.rst 1970-01-01 00:00:00.000000000 +0000 +++ python-boto-2.44.0/docs/source/releasenotes/v2.43.0.rst 2016-12-08 23:54:36.000000000 +0000 @@ -0,0 +1,15 @@ +boto v2.43.0 +============ + +:date: 2016/10/17 + +Adds support for ``us-east-2`` endpoint. + + +Changes +------- +* Add support for ``us-east-2`` endpoint (:sha:`262ed00`) +* Account for metadata update propagation delay (:issue:`3615`, :sha:`592dae3`) +* boto.dynamodb2.table.Table#batch_get() fails to paginate results if provisioned throughput is exceeded (:issue:`3574`, :sha:`abb3847`) + + diff -Nru python-boto-2.40.0/docs/source/releasenotes/v2.44.0.rst python-boto-2.44.0/docs/source/releasenotes/v2.44.0.rst --- python-boto-2.40.0/docs/source/releasenotes/v2.44.0.rst 1970-01-01 00:00:00.000000000 +0000 +++ python-boto-2.44.0/docs/source/releasenotes/v2.44.0.rst 2016-12-08 23:54:36.000000000 +0000 @@ -0,0 +1,13 @@ +boto v2.44.0 +============ + +:date: 2016/12/08 + +Adds support for ``ca-central-1`` region and gs object-level storage class. + +Changes +------- +* Update endpoints (:issue:`3649`, :sha:`a1eae11`) +* Add gs support for object-level storage class features. (:issue:`3635`, :sha:`dc4bf34`) + + diff -Nru python-boto-2.40.0/docs/source/_templates/layout.html python-boto-2.44.0/docs/source/_templates/layout.html --- python-boto-2.40.0/docs/source/_templates/layout.html 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/docs/source/_templates/layout.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -{% extends '!layout.html' %} - -{% block sidebarsearch %}{{ super() }}
PDF Version
{% endblock %} diff -Nru python-boto-2.40.0/README.rst python-boto-2.44.0/README.rst --- python-boto-2.40.0/README.rst 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/README.rst 2016-12-08 23:54:36.000000000 +0000 @@ -1,9 +1,9 @@ #### boto #### -boto 2.40.0 +boto 2.44.0 -Released: 9-Apr-2015 +Released: 08-Dec-2016 .. image:: https://travis-ci.org/boto/boto.svg?branch=develop :target: https://travis-ci.org/boto/boto diff -Nru python-boto-2.40.0/scripts/rebuild-endpoints.py python-boto-2.44.0/scripts/rebuild-endpoints.py --- python-boto-2.40.0/scripts/rebuild-endpoints.py 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/scripts/rebuild-endpoints.py 2016-12-08 23:54:36.000000000 +0000 @@ -271,7 +271,8 @@ builder = StaticEndpointBuilder(strict_resolver) static_endpoints = builder.build_static_endpoints( known_services_in_existing_endpoints) - json_data = json.dumps(static_endpoints, indent=4, sort_keys=True) + json_data = json.dumps( + static_endpoints, indent=4, sort_keys=True, separators=(',', ': ')) if args.overwrite: with open(EXISTING_ENDPOINTS_FILE, 'w') as f: f.write(json_data) diff -Nru python-boto-2.40.0/tests/integration/gs/test_basic.py python-boto-2.44.0/tests/integration/gs/test_basic.py --- python-boto-2.40.0/tests/integration/gs/test_basic.py 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/tests/integration/gs/test_basic.py 2016-12-08 23:54:36.000000000 +0000 @@ -56,15 +56,22 @@ LIFECYCLE_DOC = ('' '' '' - '365' + '''true' + 'STANDARD' + '365' '2013-01-15' '3' - 'true' - '') -LIFECYCLE_CONDITIONS = {'Age': '365', - 'CreatedBefore': '2013-01-15', - 'NumberOfNewerVersions': '3', - 'IsLive': 'true'} + '' + 'NEARLINE' + '366' + '') +LIFECYCLE_CONDITIONS_FOR_DELETE_RULE = { + 'Age': '365', + 'CreatedBefore': '2013-01-15', + 'NumberOfNewerVersions': '3', + 'IsLive': 'true', + 'MatchesStorageClass': ['STANDARD']} +LIFECYCLE_CONDITIONS_FOR_SET_STORAGE_CLASS_RULE = {'Age': '366'} # Regexp for matching project-private default object ACL. PROJECT_PRIVATE_RE = ('\s*\s*\s*' @@ -412,7 +419,11 @@ self.assertEqual(xml, LIFECYCLE_EMPTY) # set lifecycle config lifecycle_config = LifecycleConfig() - lifecycle_config.add_rule('Delete', None, LIFECYCLE_CONDITIONS) + lifecycle_config.add_rule( + 'Delete', None, LIFECYCLE_CONDITIONS_FOR_DELETE_RULE) + lifecycle_config.add_rule( + 'SetStorageClass', 'NEARLINE', + LIFECYCLE_CONDITIONS_FOR_SET_STORAGE_CLASS_RULE) bucket.configure_lifecycle(lifecycle_config) xml = bucket.get_lifecycle_config().to_xml() self.assertEqual(xml, LIFECYCLE_DOC) @@ -428,7 +439,11 @@ self.assertEqual(xml, LIFECYCLE_EMPTY) # set lifecycle config lifecycle_config = LifecycleConfig() - lifecycle_config.add_rule('Delete', None, LIFECYCLE_CONDITIONS) + lifecycle_config.add_rule( + 'Delete', None, LIFECYCLE_CONDITIONS_FOR_DELETE_RULE) + lifecycle_config.add_rule( + 'SetStorageClass', 'NEARLINE', + LIFECYCLE_CONDITIONS_FOR_SET_STORAGE_CLASS_RULE) uri.configure_lifecycle(lifecycle_config) xml = uri.get_lifecycle_config().to_xml() self.assertEqual(xml, LIFECYCLE_DOC) diff -Nru python-boto-2.40.0/tests/integration/gs/testcase.py python-boto-2.44.0/tests/integration/gs/testcase.py --- python-boto-2.40.0/tests/integration/gs/testcase.py 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/tests/integration/gs/testcase.py 2016-12-08 23:54:36.000000000 +0000 @@ -113,6 +113,7 @@ deleted.""" b = self._MakeBucket() b.configure_versioning(True) + time.sleep(30) # Ensure versioning config propagates. return b def _MakeTempDir(self): diff -Nru python-boto-2.40.0/tests/unit/auth/test_sigv4.py python-boto-2.44.0/tests/unit/auth/test_sigv4.py --- python-boto-2.40.0/tests/unit/auth/test_sigv4.py 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/tests/unit/auth/test_sigv4.py 2016-12-08 23:54:36.000000000 +0000 @@ -551,8 +551,16 @@ self.assertEqual(fake._required_auth_capability(), ['nope']) def test_sigv4_non_optional(self): - region_groups = ['.cn-north', '.eu-central', '-eu-central'] - specific_regions = ['.ap-northeast-2', '-ap-northeast-2'] + region_groups = [ + '.cn-north', + '.eu-central', '-eu-central', + '.ca-central', '-ca-central' + ] + specific_regions = [ + '.ap-northeast-2', '-ap-northeast-2', + '.ap-south-1', '-ap-south-1', + '.us-east-2', '-us-east-2', + ] # Create a connection for a sample region in each of these groups # and ensure sigv4 is used. @@ -568,7 +576,6 @@ self.assertEqual( fake._required_auth_capability(), ['hmac-v4-s3']) - def test_sigv4_opt_in_config(self): # Opt-in via the config. self.config = { diff -Nru python-boto-2.40.0/tests/unit/dynamodb2/test_table.py python-boto-2.44.0/tests/unit/dynamodb2/test_table.py --- python-boto-2.40.0/tests/unit/dynamodb2/test_table.py 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/tests/unit/dynamodb2/test_table.py 2016-12-08 23:54:36.000000000 +0000 @@ -1131,7 +1131,7 @@ self.assertFalse(self.results._results_left) def test_fetch_more_empty(self): - self.results.to_call(lambda keys: {'results': [], 'last_key': None}) + self.results.to_call(lambda keys: {'results': [], 'last_key': None}) self.results.fetch_more() self.assertEqual(self.results._results, []) @@ -2913,9 +2913,11 @@ # Now alter the expected. del expected['Responses']['users'][2] expected['UnprocessedKeys'] = { - 'Keys': [ - {'username': {'S': 'jane',}}, - ], + 'users': { + 'Keys': [ + {'username': {'S': 'jane',}}, + ], + }, } with mock.patch.object( diff -Nru python-boto-2.40.0/tests/unit/ec2/test_connection.py python-boto-2.44.0/tests/unit/ec2/test_connection.py --- python-boto-2.40.0/tests/unit/ec2/test_connection.py 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/tests/unit/ec2/test_connection.py 2016-12-08 23:54:36.000000000 +0000 @@ -1,6 +1,4 @@ #!/usr/bin/env python -import httplib - from datetime import datetime, timedelta from mock import MagicMock, Mock from tests.unit import unittest @@ -13,6 +11,7 @@ from boto.ec2.connection import EC2Connection from boto.ec2.snapshot import Snapshot from boto.ec2.reservedinstance import ReservedInstancesConfiguration +from boto.compat import http_client class TestEC2ConnectionBase(AWSMockServiceTestCase): @@ -990,12 +989,12 @@ class TestConnectToRegion(unittest.TestCase): def setUp(self): - self.https_connection = Mock(spec=httplib.HTTPSConnection) + self.https_connection = Mock(spec=http_client.HTTPSConnection) self.https_connection_factory = ( Mock(return_value=self.https_connection), ()) def test_aws_region(self): - region = boto.ec2.RegionData.keys()[0] + region = list(boto.ec2.RegionData.keys())[0] self.ec2 = boto.ec2.connect_to_region( region, https_connection_factory=self.https_connection_factory, diff -Nru python-boto-2.40.0/tests/unit/ec2containerservice/test_connection.py python-boto-2.44.0/tests/unit/ec2containerservice/test_connection.py --- python-boto-2.40.0/tests/unit/ec2containerservice/test_connection.py 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/tests/unit/ec2containerservice/test_connection.py 2016-12-08 23:54:36.000000000 +0000 @@ -20,14 +20,25 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. # +from mock import Mock from tests.unit import unittest import boto.ec2containerservice from boto.ec2containerservice.layer1 import EC2ContainerServiceConnection +from boto.compat import http_client class TestConnectToRegion(unittest.TestCase): + def setUp(self): + self.https_connection = Mock(spec=http_client.HTTPSConnection) + self.https_connection_factory = ( + Mock(return_value=self.https_connection), ()) + def test_aws_region(self): - ecs = boto.ec2containerservice.connect_to_region('us-east-1') + ecs = boto.ec2containerservice.connect_to_region('us-east-1', + https_connection_factory=self.https_connection_factory, + aws_access_key_id='aws_access_key_id', + aws_secret_access_key='aws_secret_access_key' + ) self.assertIsInstance(ecs, EC2ContainerServiceConnection) diff -Nru python-boto-2.40.0/tests/unit/mturk/test_locale_qualification_in.py python-boto-2.44.0/tests/unit/mturk/test_locale_qualification_in.py --- python-boto-2.40.0/tests/unit/mturk/test_locale_qualification_in.py 1970-01-01 00:00:00.000000000 +0000 +++ python-boto-2.44.0/tests/unit/mturk/test_locale_qualification_in.py 2016-12-08 23:54:36.000000000 +0000 @@ -0,0 +1,133 @@ +# -*- coding: utf-8 -*- + +from tests.unit import AWSMockServiceTestCase + +from boto.mturk.connection import MTurkConnection +from boto.mturk.question import ExternalQuestion +from boto.mturk.qualification import \ + Qualifications, LocaleRequirement + +MOCK_SERVER_RESPONSE = b""" + + + True + +""" + + +class TestMTurkPostingWithQualificationsIn(AWSMockServiceTestCase): + connection_class = MTurkConnection + + def setUp(self): + super(TestMTurkPostingWithQualificationsIn, self).setUp() + + def test_locale_qualification_in(self): + self.set_http_response( + status_code=200, + body=MOCK_SERVER_RESPONSE) + q = ExternalQuestion( + external_url="http://samplesite", + frame_height=800) + keywords = ['boto', 'test', 'doctest'] + title = "Boto External Question Test" + annotation = 'An annotation from boto external question test' + qualifications = Qualifications() + test_requirement = LocaleRequirement( + comparator='In', + locale=[('US', 'WA'), 'CA']) + qualifications.add(test_requirement) + create_hit_rs = self.service_connection.create_hit( + question=q, + lifetime=60*65, + max_assignments=2, + title=title, + keywords=keywords, + reward=0.05, + duration=60*6, + approval_delay=60*60, + annotation=annotation, + qualifications=qualifications) + self.assert_request_parameters({ + 'QualificationRequirement.1.Comparator': 'In', + 'QualificationRequirement.1.LocaleValue.1.Country': 'US', + 'QualificationRequirement.1.LocaleValue.1.Subdivision': 'WA', + 'QualificationRequirement.1.LocaleValue.2.Country': 'CA', + 'QualificationRequirement.1.QualificationTypeId': + '00000000000000000071'}, + ignore_params_values=['AWSAccessKeyId', + 'SignatureVersion', + 'Timestamp', + 'Title', + 'Question', + 'AssignmentDurationInSeconds', + 'RequesterAnnotation', + 'Version', + 'LifetimeInSeconds', + 'AutoApprovalDelayInSeconds', + 'Reward.1.Amount', + 'Description', + 'MaxAssignments', + 'Reward.1.CurrencyCode', + 'Keywords', + 'Operation']) + self.assertEquals(create_hit_rs.status, True) + + def test_locale_qualification_notin_in(self): + self.set_http_response( + status_code=200, + body=MOCK_SERVER_RESPONSE) + q = ExternalQuestion( + external_url="http://samplesite", + frame_height=800) + keywords = ['boto', 'test', 'doctest'] + title = "Boto External Question Test" + annotation = 'An annotation from boto external question test' + qualifications = Qualifications() + test_requirement1 = LocaleRequirement( + comparator='NotIn', + locale=[('US', 'WA'), 'CA']) + test_requirement2 = LocaleRequirement( + comparator='In', + locale=[('US', 'CA')]) + qualifications.add(test_requirement1) + qualifications.add(test_requirement2) + create_hit_rs = self.service_connection.create_hit( + question=q, + lifetime=60*65, + max_assignments=2, + title=title, + keywords=keywords, + reward=0.05, + duration=60*6, + approval_delay=60*60, + annotation=annotation, + qualifications=qualifications) + self.assert_request_parameters({ + 'QualificationRequirement.1.Comparator': 'NotIn', + 'QualificationRequirement.1.LocaleValue.1.Country': 'US', + 'QualificationRequirement.1.LocaleValue.1.Subdivision': 'WA', + 'QualificationRequirement.1.LocaleValue.2.Country': 'CA', + 'QualificationRequirement.1.QualificationTypeId': + '00000000000000000071', + 'QualificationRequirement.2.Comparator': 'In', + 'QualificationRequirement.2.LocaleValue.1.Country': 'US', + 'QualificationRequirement.2.LocaleValue.1.Subdivision': 'CA', + 'QualificationRequirement.2.QualificationTypeId': + '00000000000000000071'}, + ignore_params_values=['AWSAccessKeyId', + 'SignatureVersion', + 'Timestamp', + 'Title', + 'Question', + 'AssignmentDurationInSeconds', + 'RequesterAnnotation', + 'Version', + 'LifetimeInSeconds', + 'AutoApprovalDelayInSeconds', + 'Reward.1.Amount', + 'Description', + 'MaxAssignments', + 'Reward.1.CurrencyCode', + 'Keywords', + 'Operation']) + self.assertEquals(create_hit_rs.status, True) diff -Nru python-boto-2.40.0/tests/unit/mturk/test_locale_qualification_notin.py python-boto-2.44.0/tests/unit/mturk/test_locale_qualification_notin.py --- python-boto-2.40.0/tests/unit/mturk/test_locale_qualification_notin.py 1970-01-01 00:00:00.000000000 +0000 +++ python-boto-2.44.0/tests/unit/mturk/test_locale_qualification_notin.py 2016-12-08 23:54:36.000000000 +0000 @@ -0,0 +1,133 @@ +# -*- coding: utf-8 -*- + +from tests.unit import AWSMockServiceTestCase + +from boto.mturk.connection import MTurkConnection +from boto.mturk.question import ExternalQuestion +from boto.mturk.qualification import \ + Qualifications, LocaleRequirement + +MOCK_SERVER_RESPONSE = b""" + + + True + +""" + + +class TestMTurkPostingWithQualificationsNotin(AWSMockServiceTestCase): + connection_class = MTurkConnection + + def setUp(self): + super(TestMTurkPostingWithQualificationsNotin, self).setUp() + + def test_locale_qualification_notin(self): + self.set_http_response( + status_code=200, + body=MOCK_SERVER_RESPONSE) + q = ExternalQuestion( + external_url="http://samplesite", + frame_height=800) + keywords = ['boto', 'test', 'doctest'] + title = "Boto External Question Test" + annotation = 'An annotation from boto external question test' + qualifications = Qualifications() + test_requirement = LocaleRequirement( + comparator='NotIn', + locale=[('US', 'WA'), 'CA']) + qualifications.add(test_requirement) + create_hit_rs = self.service_connection.create_hit( + question=q, + lifetime=60*65, + max_assignments=2, + title=title, + keywords=keywords, + reward=0.05, + duration=60*6, + approval_delay=60*60, + annotation=annotation, + qualifications=qualifications) + self.assert_request_parameters({ + 'QualificationRequirement.1.Comparator': 'NotIn', + 'QualificationRequirement.1.LocaleValue.1.Country': 'US', + 'QualificationRequirement.1.LocaleValue.1.Subdivision': 'WA', + 'QualificationRequirement.1.LocaleValue.2.Country': 'CA', + 'QualificationRequirement.1.QualificationTypeId': + '00000000000000000071'}, + ignore_params_values=['AWSAccessKeyId', + 'SignatureVersion', + 'Timestamp', + 'Title', + 'Question', + 'AssignmentDurationInSeconds', + 'RequesterAnnotation', + 'Version', + 'LifetimeInSeconds', + 'AutoApprovalDelayInSeconds', + 'Reward.1.Amount', + 'Description', + 'MaxAssignments', + 'Reward.1.CurrencyCode', + 'Keywords', + 'Operation']) + self.assertEquals(create_hit_rs.status, True) + + def test_locale_qualification_in_notin(self): + self.set_http_response( + status_code=200, + body=MOCK_SERVER_RESPONSE) + q = ExternalQuestion( + external_url="http://samplesite", + frame_height=800) + keywords = ['boto', 'test', 'doctest'] + title = "Boto External Question Test" + annotation = 'An annotation from boto external question test' + qualifications = Qualifications() + test_requirement1 = LocaleRequirement( + comparator='In', + locale=[('US', 'CA')]) + test_requirement2 = LocaleRequirement( + comparator='NotIn', + locale=[('US', 'WA'), 'CA']) + qualifications.add(test_requirement1) + qualifications.add(test_requirement2) + create_hit_rs = self.service_connection.create_hit( + question=q, + lifetime=60*65, + max_assignments=2, + title=title, + keywords=keywords, + reward=0.05, + duration=60*6, + approval_delay=60*60, + annotation=annotation, + qualifications=qualifications) + self.assert_request_parameters({ + 'QualificationRequirement.1.Comparator': 'In', + 'QualificationRequirement.1.LocaleValue.1.Country': 'US', + 'QualificationRequirement.1.LocaleValue.1.Subdivision': 'CA', + 'QualificationRequirement.1.QualificationTypeId': + '00000000000000000071', + 'QualificationRequirement.2.Comparator': 'NotIn', + 'QualificationRequirement.2.LocaleValue.1.Country': 'US', + 'QualificationRequirement.2.LocaleValue.1.Subdivision': 'WA', + 'QualificationRequirement.2.LocaleValue.2.Country': 'CA', + 'QualificationRequirement.2.QualificationTypeId': + '00000000000000000071'}, + ignore_params_values=['AWSAccessKeyId', + 'SignatureVersion', + 'Timestamp', + 'Title', + 'Question', + 'AssignmentDurationInSeconds', + 'RequesterAnnotation', + 'Version', + 'LifetimeInSeconds', + 'AutoApprovalDelayInSeconds', + 'Reward.1.Amount', + 'Description', + 'MaxAssignments', + 'Reward.1.CurrencyCode', + 'Keywords', + 'Operation']) + self.assertEquals(create_hit_rs.status, True) diff -Nru python-boto-2.40.0/tests/unit/mturk/test_qualification_doesnotexist.py python-boto-2.44.0/tests/unit/mturk/test_qualification_doesnotexist.py --- python-boto-2.40.0/tests/unit/mturk/test_qualification_doesnotexist.py 1970-01-01 00:00:00.000000000 +0000 +++ python-boto-2.44.0/tests/unit/mturk/test_qualification_doesnotexist.py 2016-12-08 23:54:36.000000000 +0000 @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- + +from tests.unit import AWSMockServiceTestCase + +from boto.mturk.connection import MTurkConnection +from boto.mturk.question import ExternalQuestion +from boto.mturk.qualification import \ + Qualifications, Requirement + +QUAL_NO_ONE_ELSE_HAS_ID = "333333333333333333333333333333" + +MOCK_SERVER_RESPONSE = b""" + + + True + +""" + + +class TestMTurkPostingWithQualificationsDoesnotexist(AWSMockServiceTestCase): + connection_class = MTurkConnection + + def setUp(self): + super(TestMTurkPostingWithQualificationsDoesnotexist, self).setUp() + + def test_qualification_doesnotexist(self): + self.set_http_response( + status_code=200, + body=MOCK_SERVER_RESPONSE) + q = ExternalQuestion( + external_url="http://samplesite", + frame_height=800) + keywords = ['boto', 'test', 'doctest'] + title = "Boto External Question Test" + annotation = 'An annotation from boto external question test' + qualifications = Qualifications() + test_requirement = Requirement( + qualification_type_id=QUAL_NO_ONE_ELSE_HAS_ID, + comparator='DoesNotExist') + qualifications.add(test_requirement) + create_hit_rs = self.service_connection.create_hit( + question=q, + lifetime=60*65, + max_assignments=2, + title=title, + keywords=keywords, + reward=0.05, + duration=60*6, + approval_delay=60*60, + annotation=annotation, + qualifications=qualifications) + self.assert_request_parameters({ + 'QualificationRequirement.1.Comparator': + 'DoesNotExist', + 'QualificationRequirement.1.QualificationTypeId': + '333333333333333333333333333333'}, + ignore_params_values=['AWSAccessKeyId', + 'SignatureVersion', + 'Timestamp', + 'Title', + 'Question', + 'AssignmentDurationInSeconds', + 'RequesterAnnotation', + 'Version', + 'LifetimeInSeconds', + 'AutoApprovalDelayInSeconds', + 'Reward.1.Amount', + 'Description', + 'MaxAssignments', + 'Reward.1.CurrencyCode', + 'Keywords', + 'Operation']) + self.assertEquals(create_hit_rs.status, True) diff -Nru python-boto-2.40.0/tests/unit/mturk/test_qualification_exists.py python-boto-2.44.0/tests/unit/mturk/test_qualification_exists.py --- python-boto-2.40.0/tests/unit/mturk/test_qualification_exists.py 1970-01-01 00:00:00.000000000 +0000 +++ python-boto-2.44.0/tests/unit/mturk/test_qualification_exists.py 2016-12-08 23:54:36.000000000 +0000 @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- + +from tests.unit import AWSMockServiceTestCase + +from boto.mturk.connection import MTurkConnection +from boto.mturk.question import ExternalQuestion +from boto.mturk.qualification import \ + Qualifications, Requirement + +QUAL_NO_ONE_ELSE_HAS_ID = "333333333333333333333333333333" + +MOCK_SERVER_RESPONSE = b""" + + + True + +""" + + +class TestMTurkPostingWithQualificationsExists(AWSMockServiceTestCase): + connection_class = MTurkConnection + + def setUp(self): + super(TestMTurkPostingWithQualificationsExists, self).setUp() + + def test_qualification_exists(self): + self.set_http_response( + status_code=200, + body=MOCK_SERVER_RESPONSE) + q = ExternalQuestion( + external_url="http://samplesite", + frame_height=800) + keywords = ['boto', 'test', 'doctest'] + title = "Boto External Question Test" + annotation = 'An annotation from boto external question test' + qualifications = Qualifications() + test_requirement = Requirement( + qualification_type_id=QUAL_NO_ONE_ELSE_HAS_ID, + comparator='Exists') + qualifications.add(test_requirement) + create_hit_rs = self.service_connection.create_hit( + question=q, + lifetime=60*65, + max_assignments=2, + title=title, + keywords=keywords, + reward=0.05, + duration=60*6, + approval_delay=60*60, + annotation=annotation, + qualifications=qualifications) + self.assert_request_parameters({ + 'QualificationRequirement.1.Comparator': + 'Exists', + 'QualificationRequirement.1.QualificationTypeId': + '333333333333333333333333333333'}, + ignore_params_values=['AWSAccessKeyId', + 'SignatureVersion', + 'Timestamp', + 'Title', + 'Question', + 'AssignmentDurationInSeconds', + 'RequesterAnnotation', + 'Version', + 'LifetimeInSeconds', + 'AutoApprovalDelayInSeconds', + 'Reward.1.Amount', + 'Description', + 'MaxAssignments', + 'Reward.1.CurrencyCode', + 'Keywords', + 'Operation']) + self.assertEquals(create_hit_rs.status, True) diff -Nru python-boto-2.40.0/tests/unit/mturk/test_qualification_qualtypewithscore_in.py python-boto-2.44.0/tests/unit/mturk/test_qualification_qualtypewithscore_in.py --- python-boto-2.40.0/tests/unit/mturk/test_qualification_qualtypewithscore_in.py 1970-01-01 00:00:00.000000000 +0000 +++ python-boto-2.44.0/tests/unit/mturk/test_qualification_qualtypewithscore_in.py 2016-12-08 23:54:36.000000000 +0000 @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- + +from tests.unit import AWSMockServiceTestCase + +from boto.mturk.connection import MTurkConnection +from boto.mturk.question import ExternalQuestion +from boto.mturk.qualification import \ + Qualifications, Requirement + +QUAL_WITH_SCORE_ID = "333333333333333333333333333333" + +MOCK_SERVER_RESPONSE = b""" + + + True + +""" + + +class TestMTurkPostingWithQualQualtypewithscoreIn(AWSMockServiceTestCase): + connection_class = MTurkConnection + + def setUp(self): + super(TestMTurkPostingWithQualQualtypewithscoreIn, self).setUp() + + def test_qualification_qualtypewithscore_in(self): + self.set_http_response( + status_code=200, + body=MOCK_SERVER_RESPONSE) + q = ExternalQuestion( + external_url="http://samplesite", + frame_height=800) + keywords = ['boto', 'test', 'doctest'] + title = "Boto External Question Test" + annotation = 'An annotation from boto external question test' + qualifications = Qualifications() + test_requirement = Requirement( + qualification_type_id=QUAL_WITH_SCORE_ID, + comparator='In', + integer_value=[100, 90, 80]) + qualifications.add(test_requirement) + create_hit_rs = self.service_connection.create_hit( + question=q, + lifetime=60*65, + max_assignments=2, + title=title, + keywords=keywords, + reward=0.05, + duration=60*6, + approval_delay=60*60, + annotation=annotation, + qualifications=qualifications) + self.assert_request_parameters({ + 'QualificationRequirement.1.Comparator': + 'In', + 'QualificationRequirement.1.QualificationTypeId': + '333333333333333333333333333333', + 'QualificationRequirement.1.IntegerValue.1': + 100, + 'QualificationRequirement.1.IntegerValue.2': + 90, + 'QualificationRequirement.1.IntegerValue.3': + 80}, + ignore_params_values=['AWSAccessKeyId', + 'SignatureVersion', + 'Timestamp', + 'Title', + 'Question', + 'AssignmentDurationInSeconds', + 'RequesterAnnotation', + 'Version', + 'LifetimeInSeconds', + 'AutoApprovalDelayInSeconds', + 'Reward.1.Amount', + 'Description', + 'MaxAssignments', + 'Reward.1.CurrencyCode', + 'Keywords', + 'Operation']) + self.assertEquals(create_hit_rs.status, True) diff -Nru python-boto-2.40.0/tests/unit/s3/test_connection.py python-boto-2.44.0/tests/unit/s3/test_connection.py --- python-boto-2.40.0/tests/unit/s3/test_connection.py 2016-04-28 17:27:42.000000000 +0000 +++ python-boto-2.44.0/tests/unit/s3/test_connection.py 2016-12-08 23:54:36.000000000 +0000 @@ -141,6 +141,37 @@ 'a937f5fbc125d98ac8f04c49e0204ea1526a7b8ca058000a54c192457be05b7d', url) + def test_sigv4_presign_respects_is_secure(self): + self.config = { + 's3': { + 'use-sigv4': True, + } + } + + conn = self.connection_class( + aws_access_key_id='less', + aws_secret_access_key='more', + host='s3.amazonaws.com', + is_secure=True, + ) + + url = conn.generate_url_sigv4(86400, 'GET', bucket='examplebucket', + key='test.txt') + self.assertTrue(url.startswith( + 'https://examplebucket.s3.amazonaws.com/test.txt?')) + + conn = self.connection_class( + aws_access_key_id='less', + aws_secret_access_key='more', + host='s3.amazonaws.com', + is_secure=False, + ) + + url = conn.generate_url_sigv4(86400, 'GET', bucket='examplebucket', + key='test.txt') + self.assertTrue(url.startswith( + 'http://examplebucket.s3.amazonaws.com/test.txt?')) + def test_sigv4_presign_optional_params(self): self.config = { 's3': {