diff --git a/boto3/docs/service.py b/boto3/docs/service.py index edea4eaf48..e8de7323c4 100644 --- a/boto3/docs/service.py +++ b/boto3/docs/service.py @@ -10,6 +10,9 @@ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. +import os + +import boto3 from botocore.exceptions import DataNotFoundError from botocore.docs.paginator import PaginatorDocumenter from botocore.docs.waiter import WaiterDocumenter @@ -22,6 +25,9 @@ class ServiceDocumenter(object): + # The path used to find examples + EXAMPLE_PATH = os.path.join(os.path.dirname(boto3.__file__), 'examples') + def __init__(self, service_name, session): self._service_name = service_name self._session = session @@ -39,7 +45,8 @@ def __init__(self, service_name, session): 'paginators', 'waiters', 'service-resource', - 'resources' + 'resources', + 'examples' ] def document_service(self): @@ -60,6 +67,7 @@ def document_service(self): self._document_service_resource( doc_structure.get_section('service-resource')) self._document_resources(doc_structure.get_section('resources')) + self._document_examples(doc_structure.get_section('examples')) return doc_structure.flush_structure() def _document_title(self, section): @@ -120,3 +128,19 @@ def _document_resources(self, section): ResourceDocumenter( resource, self._botocore_session).document_resource( section.add_new_section(resource.meta.resource_model.name)) + + def _get_example_file(self): + return os.path.realpath( + os.path.join(self.EXAMPLE_PATH, + self._service_name + '.rst')) + + def _document_examples(self, section): + examples_file = self._get_example_file() + if os.path.isfile(examples_file): + section.style.h2('Examples') + section.style.new_line() + section.write(".. contents::\n :local:\n :depth: 1") + section.style.new_line() + section.style.new_line() + with open(examples_file, 'r') as f: + section.write(f.read()) diff --git a/boto3/examples/s3.rst b/boto3/examples/s3.rst new file mode 100644 index 0000000000..366a4b7c08 --- /dev/null +++ b/boto3/examples/s3.rst @@ -0,0 +1,14 @@ +List objects in an Amazon S3 bucket +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following example shows how to use an Amazon S3 bucket resource to list +the objects in the bucket. + +.. code-block:: python + + import boto3 + + s3 = boto3.resource('s3') + bucket = s3.Bucket('my-bucket') + for obj in bucket.objects.all(): + print(obj.key) diff --git a/setup.py b/setup.py index 191c8420a1..042aa6b97a 100644 --- a/setup.py +++ b/setup.py @@ -43,6 +43,7 @@ def get_version(): package_data={ 'boto3': [ 'data/aws/resources/*.json', + 'examples/*.rst' ] }, include_package_data=True, diff --git a/tests/unit/data/examples/myservice.rst b/tests/unit/data/examples/myservice.rst new file mode 100644 index 0000000000..1658ddcceb --- /dev/null +++ b/tests/unit/data/examples/myservice.rst @@ -0,0 +1,3 @@ +** This is an example ** + +This is the contents! diff --git a/tests/unit/data/examples/otherservice.rst b/tests/unit/data/examples/otherservice.rst new file mode 100644 index 0000000000..c0119a9f68 --- /dev/null +++ b/tests/unit/data/examples/otherservice.rst @@ -0,0 +1,3 @@ +**Other example** + +This is for another service diff --git a/tests/unit/docs/test_service.py b/tests/unit/docs/test_service.py index 802e8c7376..f4227ffab9 100644 --- a/tests/unit/docs/test_service.py +++ b/tests/unit/docs/test_service.py @@ -11,7 +11,9 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. import os +import mock +import boto3 from tests.unit.docs import BaseDocsTest from boto3.docs.service import ServiceDocumenter @@ -111,3 +113,21 @@ def test_document_service_no_waiter(self): service_documenter = ServiceDocumenter('myservice', self.session) contents = service_documenter.document_service().decode('utf-8') self.assertNotIn('Waiters', contents) + + def test_creates_correct_path_to_examples_based_on_service_name(self): + path = os.sep.join([os.path.dirname(boto3.__file__), 'boto3', + 'examples', 'myservice.rst']) + path = os.path.realpath(path) + with mock.patch('os.path.isfile') as patch: + ServiceDocumenter('myservice', self.session) + patch.assert_has_call_with(path) + + def test_injects_examples_when_found(self): + examples_path = os.sep.join([os.path.dirname(__file__), '..', 'data', + 'examples']) + service_documenter = ServiceDocumenter( + 'myservice', self.session) + service_documenter.EXAMPLE_PATH = examples_path + contents = service_documenter.document_service().decode('utf-8') + self.assertIn('This is an example', contents) + self.assertNotIn('This is for another service', contents)