diff --git a/datastore/google/cloud/datastore/__init__.py b/datastore/google/cloud/datastore/__init__.py index 7ca8e3f116f0..51c742d2b17f 100644 --- a/datastore/google/cloud/datastore/__init__.py +++ b/datastore/google/cloud/datastore/__init__.py @@ -16,14 +16,26 @@ You'll typically use these to get started with the API: -.. code-block:: python +.. testsetup:: constructors - from google.cloud import datastore + import os + os.environ['GOOGLE_CLOUD_PROJECT'] = u'my-project' - client = datastore.Client() - key = client.key('EntityKind', 1234) - entity = datastore.Entity(key) - query = client.query(kind='EntityKind') +.. doctest:: constructors + + >>> from google.cloud import datastore + >>> + >>> client = datastore.Client() + >>> print(client.project) + my-project + >>> key = client.key('EntityKind', 1234) + >>> key + + >>> entity = datastore.Entity(key) + >>> entity['answer'] = 42 + >>> entity + + >>> query = client.query(kind='EntityKind') The main concepts with this API are: diff --git a/datastore/google/cloud/datastore/entity.py b/datastore/google/cloud/datastore/entity.py index 02ef0fd3ac73..2728768a3af8 100644 --- a/datastore/google/cloud/datastore/entity.py +++ b/datastore/google/cloud/datastore/entity.py @@ -144,7 +144,7 @@ def exclude_from_indexes(self): def __repr__(self): if self.key: - return '' % (self.key.path, + return '' % (self.key._flat_path, super(Entity, self).__repr__()) else: - return '' % (super(Entity, self).__repr__()) + return '' % (super(Entity, self).__repr__(),) diff --git a/datastore/google/cloud/datastore/key.py b/datastore/google/cloud/datastore/key.py index 72a50340ec84..1ccabf171857 100644 --- a/datastore/google/cloud/datastore/key.py +++ b/datastore/google/cloud/datastore/key.py @@ -380,7 +380,7 @@ def parent(self): return self._parent def __repr__(self): - return '' % (self.path, self.project) + return '' % (self._flat_path, self.project) def _validate_project(project, parent): diff --git a/datastore/unit_tests/test_entity.py b/datastore/unit_tests/test_entity.py index 30d40f947cc6..31c60a172001 100644 --- a/datastore/unit_tests/test_entity.py +++ b/datastore/unit_tests/test_entity.py @@ -190,10 +190,13 @@ def test___repr___no_key_empty(self): def test___repr___w_key_non_empty(self): key = _Key() - key._path = '/bar/baz' + flat_path = ('bar', 12, 'baz', 'himom') + key._flat_path = flat_path entity = self._make_one(key=key) - entity['foo'] = 'Foo' - self.assertEqual(repr(entity), "") + entity_vals = {'foo': 'Foo'} + entity.update(entity_vals) + expected = '' % (flat_path, entity_vals) + self.assertEqual(repr(entity), expected) class _Key(object): @@ -206,7 +209,3 @@ class _Key(object): def __init__(self, project=_PROJECT): self.project = project - - @property - def path(self): - return self._path diff --git a/system_tests/datastore.py b/system_tests/datastore.py index 51e1ffdf17e6..7e25f0c7e6a1 100644 --- a/system_tests/datastore.py +++ b/system_tests/datastore.py @@ -14,6 +14,8 @@ import datetime import os +import pkgutil +import tempfile import unittest import httplib2 @@ -31,6 +33,23 @@ from system_test_utils import unique_resource_id +SPHINX_CONF = """\ +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.doctest', +] +""" + +SPHINX_SECTION_TEMPLATE = """\ +Section %02d +=========== + +.. automodule:: google.cloud.%s + :members: + +""" + + class Config(object): """Run-time configuration to be modified at set-up. @@ -495,3 +514,59 @@ def test_failure_with_contention(self): # transaction. entity_in_txn[contention_prop_name] = u'inside' txn.put(entity_in_txn) + + +class TestDoctest(unittest.TestCase): + + def _submodules(self): + pkg_iter = pkgutil.iter_modules(datastore.__path__) + result = [] + for _, mod_name, ispkg in pkg_iter: + if mod_name == '_generated': + self.assertTrue(ispkg) + else: + self.assertFalse(ispkg) + result.append(mod_name) + + self.assertNotIn('__init__', result) + return result + + @staticmethod + def _add_section(index, mod_name, file_obj): + mod_part = 'datastore' + if mod_name != '__init__': + mod_part += '.' + mod_name + content = SPHINX_SECTION_TEMPLATE % (index, mod_part) + file_obj.write(content) + + def _make_temp_docs(self): + docs_dir = tempfile.mkdtemp(prefix='datastore-') + + conf_file = os.path.join(docs_dir, 'conf.py') + + with open(conf_file, 'w') as file_obj: + file_obj.write(SPHINX_CONF) + + index_file = os.path.join(docs_dir, 'contents.rst') + datastore_modules = self._submodules() + with open(index_file, 'w') as file_obj: + self._add_section(0, '__init__', file_obj) + for index, datastore_module in enumerate(datastore_modules): + self._add_section(index + 1, datastore_module, file_obj) + + return docs_dir + + def test_it(self): + from sphinx import application + + docs_dir = self._make_temp_docs() + outdir = os.path.join(docs_dir, 'doctest', 'out') + doctreedir = os.path.join(docs_dir, 'doctest', 'doctrees') + + app = application.Sphinx( + srcdir=docs_dir, confdir=docs_dir, + outdir=outdir, doctreedir=doctreedir, + buildername='doctest', warningiserror=True, parallel=1) + + app.build() + self.assertEqual(app.statuscode, 0) diff --git a/tox.ini b/tox.ini index 4174b7659829..388cfeef859d 100644 --- a/tox.ini +++ b/tox.ini @@ -265,6 +265,7 @@ commands = python {toxinidir}/system_tests/attempt_system_tests.py {posargs} deps = {[testing]deps} + Sphinx passenv = {[testing]passenv} encrypted_* @@ -273,10 +274,9 @@ passenv = basepython = python3.5 commands = - {[testing]localdeps} - python {toxinidir}/system_tests/attempt_system_tests.py {posargs} + {[testenv:system-tests]commands} deps = - {[testing]deps} + {[testenv:system-tests]deps} passenv = {[testenv:system-tests]passenv}