Skip to content

Commit d56ea3d

Browse files
committed
Merge pull request #1375 from dhermes/check-left-out-modules
Adding check that all public modules are documented.
2 parents b30d3f4 + 27da413 commit d56ea3d

File tree

9 files changed

+189
-9
lines changed

9 files changed

+189
-9
lines changed

docs/bigquery-query.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Query
2+
~~~~~
3+
4+
.. automodule:: gcloud.bigquery.query
5+
:members:
6+
:undoc-members:
7+
:show-inheritance:

docs/datastore-helpers.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Helpers
2+
~~~~~~~
3+
4+
.. automodule:: gcloud.datastore.helpers
5+
:members:
6+
:undoc-members:
7+
:show-inheritance:

docs/gcloud-api.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,11 @@ Exceptions
3333
:members:
3434
:undoc-members:
3535
:show-inheritance:
36+
37+
Environment Variables
38+
~~~~~~~~~~~~~~~~~~~~~
39+
40+
.. automodule:: gcloud.environment_vars
41+
:members:
42+
:undoc-members:
43+
:show-inheritance:

docs/index.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
datastore-queries
1818
datastore-transactions
1919
datastore-batches
20+
datastore-helpers
2021

2122
.. toctree::
2223
:maxdepth: 0
@@ -27,6 +28,7 @@
2728
storage-blobs
2829
storage-buckets
2930
storage-acl
31+
storage-batch
3032

3133
.. toctree::
3234
:maxdepth: 0
@@ -49,6 +51,7 @@
4951
bigquery-dataset
5052
bigquery-job
5153
bigquery-table
54+
bigquery-query
5255

5356
.. toctree::
5457
:maxdepth: 0

docs/storage-batch.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Batches
2+
~~~~~~~
3+
4+
.. automodule:: gcloud.storage.batch
5+
:members:
6+
:undoc-members:
7+
:show-inheritance:

scripts/run_pylint.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
violations (hence it has a reduced number of style checks).
2222
"""
2323

24+
from __future__ import print_function
25+
2426
import ConfigParser
2527
import copy
2628
import os
@@ -152,12 +154,12 @@ def get_files_for_linting(allow_limited=True):
152154
if diff_base is not None and allow_limited:
153155
result = subprocess.check_output(['git', 'diff', '--name-only',
154156
diff_base])
155-
print 'Using files changed relative to %s:' % (diff_base,)
156-
print '-' * 60
157-
print result.rstrip('\n') # Don't print trailing newlines.
158-
print '-' * 60
157+
print('Using files changed relative to %s:' % (diff_base,))
158+
print('-' * 60)
159+
print(result.rstrip('\n')) # Don't print trailing newlines.
160+
print('-' * 60)
159161
else:
160-
print 'Diff base not specified, listing all files in repository.'
162+
print('Diff base not specified, listing all files in repository.')
161163
result = subprocess.check_output(['git', 'ls-files'])
162164

163165
return result.rstrip('\n').split('\n'), diff_base
@@ -212,10 +214,10 @@ def lint_fileset(filenames, rcfile, description):
212214
if status_code != 0:
213215
error_message = ('Pylint failed on %s with '
214216
'status %d.' % (description, status_code))
215-
print >> sys.stderr, error_message
217+
print(error_message, file=sys.stderr)
216218
sys.exit(status_code)
217219
else:
218-
print 'Skipping %s, no files to lint.' % (description,)
220+
print('Skipping %s, no files to lint.' % (description,))
219221

220222

221223
def main():
@@ -230,7 +232,7 @@ def main():
230232
raise
231233

232234
message = 'Restricted lint failed, expanding to full fileset.'
233-
print >> sys.stderr, message
235+
print(message, file=sys.stderr)
234236
all_files, _ = get_files_for_linting(allow_limited=False)
235237
library_files, non_library_files, _ = get_python_files(
236238
all_files=all_files)

scripts/update_docs.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ if [[ "${TRAVIS_BRANCH}" == "master" ]] && \
2525
elif [[ -n "${TRAVIS_TAG}" ]]; then
2626
echo "Building new docs on a tag."
2727
else
28-
echo "Not on Travis, doing nothing."
28+
echo "No docs to update for a new tag or merged commit on Travis."
29+
echo "Verifying docs build successfully."
30+
tox -e docs
2931
exit
3032
fi
3133

scripts/verify_included_modules.py

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# Copyright 2016 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Check if all public modules are included in our docs."""
16+
17+
18+
from __future__ import print_function
19+
20+
import os
21+
import sys
22+
import warnings
23+
24+
from sphinx.ext.intersphinx import fetch_inventory
25+
26+
27+
BASE_DIR = os.path.abspath(
28+
os.path.join(os.path.dirname(__file__), '..'))
29+
DOCS_DIR = os.path.join(BASE_DIR, 'docs')
30+
OBJECT_INVENTORY_RELPATH = os.path.join('_build', 'html', 'objects.inv')
31+
IGNORED_PREFIXES = ('test_', '_')
32+
IGNORED_MODULES = frozenset([
33+
'gcloud.bigtable.client',
34+
'gcloud.bigtable.cluster',
35+
'gcloud.bigtable.column_family',
36+
'gcloud.bigtable.happybase.connection',
37+
'gcloud.bigtable.row',
38+
'gcloud.bigtable.table',
39+
'gcloud.datastore.demo.demo',
40+
'gcloud.demo',
41+
'gcloud.iterator',
42+
'gcloud.storage.demo.demo',
43+
'gcloud.streaming.buffered_stream',
44+
'gcloud.streaming.exceptions',
45+
'gcloud.streaming.http_wrapper',
46+
'gcloud.streaming.stream_slice',
47+
'gcloud.streaming.transfer',
48+
'gcloud.streaming.util',
49+
])
50+
51+
52+
class SphinxApp(object):
53+
"""Mock app to interact with Sphinx helpers."""
54+
warn = warnings.warn
55+
srcdir = DOCS_DIR
56+
57+
58+
def is_valid_module(filename):
59+
"""Determines if a filename is a valid Python module.
60+
61+
Assumes if is just the end of a path (i.e. does not contain
62+
``os.path.sep``.
63+
64+
:type filename: string
65+
:param filename: The name of a file.
66+
67+
:rtype: bool
68+
:returns: Flag indicating if the filename is valid.
69+
"""
70+
if not filename.endswith('.py'):
71+
return False
72+
for prefix in IGNORED_PREFIXES:
73+
if filename.startswith(prefix):
74+
return False
75+
return True
76+
77+
78+
def get_public_modules(path, base_package=None):
79+
"""Get list of all public modules relative to a path.
80+
81+
:type path: string
82+
:param path: The path containing the python modules.
83+
84+
:type base_package: string
85+
:param base_package: (Optional) A package to prepend in
86+
front of the path.
87+
88+
:rtype: list
89+
:returns: List of all modules found.
90+
"""
91+
result = []
92+
for subdir, _, files in os.walk(path):
93+
# Skip folders that start with _.
94+
if any([part.startswith('_')
95+
for part in subdir.split(os.path.sep)]):
96+
continue
97+
_, rel_dir = subdir.split(path)
98+
rel_dir = rel_dir.lstrip(os.path.sep)
99+
for filename in files:
100+
if is_valid_module(filename):
101+
mod_name, _ = os.path.splitext(filename)
102+
rel_path = os.path.join(rel_dir, mod_name)
103+
if base_package is not None:
104+
rel_path = os.path.join(base_package, rel_path)
105+
# Turn into a Python module rather than a file path.
106+
result.append(rel_path.replace(os.path.sep, '.'))
107+
108+
return result
109+
110+
111+
def main():
112+
"""Main script to verify modules included."""
113+
mock_uri = ''
114+
inventory = fetch_inventory(SphinxApp, mock_uri,
115+
OBJECT_INVENTORY_RELPATH)
116+
sphinx_mods = set(inventory['py:module'].keys())
117+
118+
library_dir = os.path.join(BASE_DIR, 'gcloud')
119+
public_mods = get_public_modules(library_dir,
120+
base_package='gcloud')
121+
public_mods = set(public_mods)
122+
123+
if not sphinx_mods <= public_mods:
124+
message = ('Unexpected error. There were modules referenced by '
125+
'Sphinx that are not among the public modules.')
126+
print(message, file=sys.stderr)
127+
sys.exit(1)
128+
129+
undocumented_mods = public_mods - sphinx_mods
130+
# Remove ignored modules.
131+
undocumented_mods -= IGNORED_MODULES
132+
if undocumented_mods:
133+
message_parts = ['Found undocumented public modules:']
134+
message_parts.extend(['- ' + mod_name
135+
for mod_name in sorted(undocumented_mods)])
136+
print('\n'.join(message_parts), file=sys.stderr)
137+
sys.exit(1)
138+
139+
140+
if __name__ == '__main__':
141+
main()

tox.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ basepython =
4545
commands =
4646
python -c "import shutil; shutil.rmtree('docs/_build', ignore_errors=True)"
4747
sphinx-build -W -b html -d docs/_build/doctrees docs docs/_build/html
48+
python {toxinidir}/scripts/verify_included_modules.py
4849
deps =
4950
Sphinx
5051
passenv = {[testenv:system-tests]passenv} SPHINX_RELEASE READTHEDOCS LOCAL_RTD
@@ -57,6 +58,7 @@ basepython = {[testenv:docs]basepython}
5758
commands =
5859
python -c "import shutil; shutil.rmtree('docs/_build_rtd', ignore_errors=True)"
5960
sphinx-build -W -b html -d docs/_build_rtd/doctrees docs docs/_build_rtd/html
61+
python {toxinidir}/scripts/verify_included_modules.py
6062
deps = {[testenv:docs]deps}
6163
passenv = {[testenv:docs]passenv}
6264

@@ -75,6 +77,7 @@ deps =
7577
pylint
7678
unittest2
7779
psutil
80+
Sphinx
7881
passenv = {[testenv:system-tests]passenv}
7982

8083
[testenv:system-tests]

0 commit comments

Comments
 (0)