Skip to content

Commit

Permalink
Merge branch 'release-0.0.8'
Browse files Browse the repository at this point in the history
  • Loading branch information
danielgtaylor committed Feb 11, 2015
2 parents d7cddec + e593362 commit e8e0fcf
Show file tree
Hide file tree
Showing 16 changed files with 239 additions and 33 deletions.
22 changes: 21 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,14 +1,34 @@
Changelog
=========

0.0.8 - 2015-02-10
------------------

* bugfix:Resources: Fix Amazon S3 resource identifier order.
(`issue 62 <https://github.com/boto/boto3/pull/62>`__)
* bugfix:Resources: Fix collection resource hydration path.
(`issue 61 <https://github.com/boto/boto3/pull/61>`__)
* bugfix:Resources: Re-enable service-level access to all resources,
allowing e.g. ``obj = s3.Object('bucket', 'key')``.
(`issue 60 <https://github.com/boto/boto3/pull/60>`__)
* feature:Botocore: Update to Botocore 0.87.0

* Add support for Amazon DynamoDB secondary index scanning.
* Upgrade to ``requests`` 2.5.1.
* Add support for anonymous (unsigned) clients.
(`botocore issue 448 <https://github.com/boto/botocore/pull/448>`__)

0.0.7 - 2015-02-05
------------------

* feature:Resources: Enable support for Amazon Glacier.
* feature:Resources: Support plural references and nested JMESPath
queries for data members when building parameters and identifiers.
(`issue 52 <https://github.com/boto/boto3/pull/52>`__)
* feature:Resources: Update to the latest resource JSON format.
* feature:Resources: Update to the latest resource JSON format. This is
a **backward-incompatible** change as not all resources are exposed
at the service level anymore. For example, ``s3.Object('bucket', 'key')``
is now ``s3.Bucket('bucket').Object('key')``.
(`issue 51 <https://github.com/boto/boto3/pull/51>`__)
* feature:Resources: Make ``resource.meta`` a proper object. This allows
you to do things like ``resource.meta.client``. This is a **backward-
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright 2013-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Copyright 2013-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License"). You
may not use this file except in compliance with the License. A copy of
Expand Down
32 changes: 24 additions & 8 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,30 @@ pull requests on this repository. Thanks!

Quick Start
-----------
First, install the library and set a default region::
First, install the library and set a default region:

.. code-block:: sh
$ pip install boto3
Next, set up credentials (in e.g. ``~/.aws/credentials``)::
Next, set up credentials (in e.g. ``~/.aws/credentials``):

.. code-block:: ini
[default]
aws_access_key_id = YOUR_KEY
aws_secret_access_key = YOUR_SECRET
Then, set up a default region (in e.g. ``~/.aws/config``)::
Then, set up a default region (in e.g. ``~/.aws/config``):

.. code-block:: ini
[default]
region=us-east-1
Then, from a Python interpreter::
Then, from a Python interpreter:

.. code-block:: python
>>> import boto3
>>> s3 = boto3.resource('s3')
Expand All @@ -69,7 +77,9 @@ Getting Started
~~~~~~~~~~~~~~~
Assuming that you have Python and ``virtualenv`` installed, set up your
environment and install the required dependencies like this instead of
the ``pip install boto3`` defined above::
the ``pip install boto3`` defined above:

.. code-block:: sh
$ git clone https://github.com/boto/boto3.git
$ cd boto3
Expand All @@ -85,20 +95,26 @@ You can run tests in all supported Python versions using ``tox``. Be default,
it will run all of the unit tests, but you can also specify your own
``nosetests`` options. Note that this requires that you have all supported
versions of Python installed, otherwise you must pass ``-e`` or run the
``nosetests`` command directly::
``nosetests`` command directly:

.. code-block:: sh
$ tox
$ tox tests/unit/test_session.py
$ tox -e py26,py33 tests/integration
You can also run individual tests with your default Python version::
You can also run individual tests with your default Python version:

.. code-block:: sh
$ nosetests tests/unit
Generating Documentation
~~~~~~~~~~~~~~~~~~~~~~~~
Sphinx is used for documentation. You can generate HTML locally with the
following::
following:

.. code-block:: sh
$ pip install sphinx sphinx_rtd_theme
$ cd docs
Expand Down
2 changes: 1 addition & 1 deletion boto3/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@


__author__ = 'Amazon Web Services'
__version__ = '0.0.7'
__version__ = '0.0.8'


# The default Boto3 session; autoloaded when needed.
Expand Down
6 changes: 3 additions & 3 deletions boto3/data/resources/cloudformation-2010-05-15.resources.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
"type": "StackResource",
"identifiers": [
{ "target": "StackName", "source": "identifier", "name": "Name" },
{ "target": "StackName", "source": "input" }
{ "target": "LogicalId", "source": "input" }
]
}
}
Expand Down Expand Up @@ -135,7 +135,7 @@
},
"StackResource": {
"identifiers": [
{ "name": "LogicalId" },
{ "name": "LogicalId", "memberName": "LogicalResourceId" },
{ "name": "StackName" }
],
"shape": "StackResourceDetail",
Expand All @@ -162,7 +162,7 @@
},
"StackResourceSummary": {
"identifiers": [
{ "name": "LogicalId" },
{ "name": "LogicalId", "memberName": "LogicalResourceId" },
{ "name": "StackName" }
],
"shape": "StackResourceSummary",
Expand Down
6 changes: 3 additions & 3 deletions boto3/data/resources/glacier-2012-06-01.resources.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,11 @@
]
}
},
"InitiateArchiveRetreival": {
"InitiateArchiveRetrieval": {
"request": {
"operation": "InitiateJob",
"params": [
{ "target": "vaultName", "source": "identifier", "name": "Name" },
{ "target": "vaultName", "source": "identifier", "name": "VaultName" },
{ "target": "accountId", "source": "identifier", "name": "AccountId" },
{ "target": "jobParameters.Type", "source": "string", "value": "archive-retrieval" },
{ "target": "jobParameters.ArchiveId", "source": "identifier", "name": "Id" }
Expand All @@ -125,7 +125,7 @@
"identifiers": [
{ "target": "Id", "source": "response", "path": "jobId" },
{ "target": "AccountId", "source": "identifier", "name": "AccountId" },
{ "target": "VaultName", "source": "identifier", "name": "Name" }
{ "target": "VaultName", "source": "identifier", "name": "VaultName" }
]
}
}
Expand Down
2 changes: 1 addition & 1 deletion boto3/data/resources/iam-2010-05-08.resources.json
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@
"request": {
"operation": "UpdateAssumeRolePolicy",
"params": [
{ "target": "RoleName", "source": "identifier", "name": "Name" }
{ "target": "RoleName", "source": "identifier", "name": "RoleName" }
]
}
}
Expand Down
6 changes: 3 additions & 3 deletions boto3/data/resources/s3-2006-03-01.resources.json
Original file line number Diff line number Diff line change
Expand Up @@ -698,8 +698,8 @@
"type": "MultipartUploadPart",
"identifiers": [
{ "target": "BucketName", "source": "identifier", "name": "BucketName" },
{ "target": "MultipartUploadId", "source": "identifier", "name": "Id" },
{ "target": "ObjectKey", "source": "identifier", "name": "ObjectKey" },
{ "target": "MultipartUploadId", "source": "identifier", "name": "Id" },
{ "target": "PartNumber", "source": "input" }
]
}
Expand Down Expand Up @@ -770,8 +770,8 @@
"type": "MultipartUpload",
"identifiers": [
{ "target": "BucketName", "source": "identifier", "name": "BucketName" },
{ "target": "Id", "source": "identifier", "name": "MultipartUploadId" },
{ "target": "ObjectKey", "source": "identifier", "name": "ObjectKey" }
{ "target": "ObjectKey", "source": "identifier", "name": "ObjectKey" },
{ "target": "Id", "source": "identifier", "name": "MultipartUploadId" }
]
}
}
Expand Down
1 change: 0 additions & 1 deletion boto3/data/resources/sns-2010-03-31.resources.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@
"resource": {
"type": "PlatformEndpoint",
"identifiers": [
{ "target": "PlatformApplicationArn", "source": "identifier", "name": "Arn" },
{ "target": "Arn", "source": "response", "path": "EndpointArn" }
]
}
Expand Down
2 changes: 1 addition & 1 deletion boto3/resources/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ def __init__(self, model, parent, factory, resource_defs,
operation_name = self._model.request.operation
self._parent = parent

search_path = model.path
search_path = model.resource.path
self._handler = ResourceHandler(search_path, factory, resource_defs,
service_model, model.resource, operation_name)

Expand Down
2 changes: 1 addition & 1 deletion boto3/resources/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ def _load_has_relations(self, attrs, service_name, resource_name,
# This is a sub-resource class you can create
# by passing in an identifier, e.g. s3.Bucket(name).
name = subresource.resource.type
attrs[name] = self._create_class_partial(
attrs[subresource.name] = self._create_class_partial(
name, subresource, service_name, resource_name, model,
resource_defs, service_model)

Expand Down
65 changes: 64 additions & 1 deletion boto3/resources/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,69 @@ def batch_actions(self):

return actions

def _get_has_definition(self):
"""
Get a ``has`` relationship definition from a model, where the
service resource model is treated special in that it contains
a relationship to every resource defined for the service. This
allows things like ``s3.Object('bucket-name', 'key')`` to
work even though the JSON doesn't define it explicitly.
:rtype: dict
:return: Mapping of names to subresource and reference
definitions.
"""
if self.name not in self._resource_defs:
# This is the service resource, so let us expose all of
# the defined resources as subresources.
definition = {}

for name, resource_def in self._resource_defs.items():
# It's possible for the service to have renamed a
# resource or to have defined multiple names that
# point to the same resource type, so we need to
# take that into account.
found = False
has_items = self._definition.get('has', {}).items()
for has_name, has_def in has_items:
if has_def.get('resource', {}).get('type') == name:
definition[has_name] = has_def
found = True

if not found:
# Create a relationship definition and attach it
# to the model, such that all identifiers must be
# supplied by the user. It will look something like:
#
# {
# 'resource': {
# 'type': 'ResourceName',
# 'identifiers': [
# {'target': 'Name1', 'source': 'input'},
# {'target': 'Name2', 'source': 'input'},
# ...
# ]
# }
# }
#
fake_has = {
'resource': {
'type': name,
'identifiers': []
}
}

for identifier in resource_def.get('identifiers', []):
fake_has['resource']['identifiers'].append({
'target': identifier['name'], 'source': 'input'
})

definition[name] = fake_has
else:
definition = self._definition.get('has', {})

return definition

def _get_related_resources(self, subresources):
"""
Get a list of sub-resources or references.
Expand All @@ -323,7 +386,7 @@ def _get_related_resources(self, subresources):
"""
resources = []

for name, definition in self._definition.get('has', {}).items():
for name, definition in self._get_has_definition().items():
action = Action(name, definition, self._resource_defs)

data_required = False
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def get_version():
]

requires = [
'botocore==0.86.0',
'botocore==0.87.0',
'bcdoc==0.12.2',
'jmespath==0.6.1',
]
Expand Down
40 changes: 39 additions & 1 deletion tests/integration/test_s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ def test_s3(self):
# Lazy-loaded attribute
self.assertEqual(12, obj.content_length)

# Load a similar attribute from the collection response
self.assertEqual(12, list(bucket.objects.all())[0].size)

# Perform a resource action with a low-level response
self.assertEqual(b'hello, world',
obj.get()['Body'].read())
Expand All @@ -82,4 +85,39 @@ def test_s3_resource_waiter(self):
obj.wait_until_exists()

# List objects and make sure ours is present
self.assertIn('test.txt', [o.key for o in bucket.objects.all()])
self.assertIn('test.txt', [o.key for o in bucket.objects.all()])

def test_can_create_object_directly(self):
obj = self.s3.Object(self.bucket_name, 'test.txt')

self.assertEqual(obj.bucket_name, self.bucket_name)
self.assertEqual(obj.key, 'test.txt')

def test_s3_multipart(self):
# Create the bucket
bucket = self.create_bucket_resource(self.bucket_name)
bucket.wait_until_exists()

# Create the multipart upload
mpu = bucket.Object('mp-test.txt').initiate_multipart_upload()
self.addCleanup(mpu.abort)

# Create and upload a part
part = mpu.Part(1)
response = part.upload(Body='hello, world!')

# Complete the upload, which requires info on all of the parts
part_info = {
'Parts': [
{
'PartNumber': 1,
'ETag': response['ETag']
}
]
}

mpu.complete(MultipartUpload=part_info)
self.addCleanup(bucket.Object('mp-test.txt').delete)

contents = bucket.Object('mp-test.txt').get()['Body'].read()
self.assertEqual(contents, b'hello, world!')
Loading

0 comments on commit e8e0fcf

Please sign in to comment.