17
17
import os
18
18
from pathlib import Path
19
19
import sys
20
+ from typing import Callable , Dict , List , Optional
20
21
21
22
import nox
22
23
27
28
# WARNING - WARNING - WARNING - WARNING - WARNING
28
29
# WARNING - WARNING - WARNING - WARNING - WARNING
29
30
30
- # Copy `noxfile_config.py` to your directory and modify it instead.
31
+ BLACK_VERSION = "black==19.10b0"
31
32
33
+ # Copy `noxfile_config.py` to your directory and modify it instead.
32
34
33
35
# `TEST_CONFIG` dict is a configuration hook that allows users to
34
36
# modify the test configurations. The values here should be in sync
37
39
38
40
TEST_CONFIG = {
39
41
# You can opt out from the test for specific Python versions.
40
- 'ignored_versions' : ["2.7" ],
41
-
42
+ "ignored_versions" : [],
43
+ # Old samples are opted out of enforcing Python type hints
44
+ # All new samples should feature them
45
+ "enforce_type_hints" : False ,
42
46
# An envvar key for determining the project id to use. Change it
43
47
# to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a
44
48
# build specific Cloud project. You can also use your own string
45
49
# to use your own Cloud project.
46
- ' gcloud_project_env' : ' GOOGLE_CLOUD_PROJECT' ,
50
+ " gcloud_project_env" : " GOOGLE_CLOUD_PROJECT" ,
47
51
# 'gcloud_project_env': 'BUILD_SPECIFIC_GCLOUD_PROJECT',
48
-
52
+ # If you need to use a specific version of pip,
53
+ # change pip_version_override to the string representation
54
+ # of the version number, for example, "20.2.4"
55
+ "pip_version_override" : None ,
49
56
# A dictionary you want to inject into your test. Don't put any
50
57
# secrets here. These values will override predefined values.
51
- ' envs' : {},
58
+ " envs" : {},
52
59
}
53
60
54
61
55
62
try :
56
63
# Ensure we can import noxfile_config in the project's directory.
57
- sys .path .append ('.' )
64
+ sys .path .append ("." )
58
65
from noxfile_config import TEST_CONFIG_OVERRIDE
59
66
except ImportError as e :
60
67
print ("No user noxfile_config found: detail: {}" .format (e ))
64
71
TEST_CONFIG .update (TEST_CONFIG_OVERRIDE )
65
72
66
73
67
- def get_pytest_env_vars ():
74
+ def get_pytest_env_vars () -> Dict [ str , str ] :
68
75
"""Returns a dict for pytest invocation."""
69
76
ret = {}
70
77
71
78
# Override the GCLOUD_PROJECT and the alias.
72
- env_key = TEST_CONFIG [' gcloud_project_env' ]
79
+ env_key = TEST_CONFIG [" gcloud_project_env" ]
73
80
# This should error out if not set.
74
- ret [' GOOGLE_CLOUD_PROJECT' ] = os .environ [env_key ]
81
+ ret [" GOOGLE_CLOUD_PROJECT" ] = os .environ [env_key ]
75
82
76
83
# Apply user supplied envs.
77
- ret .update (TEST_CONFIG [' envs' ])
84
+ ret .update (TEST_CONFIG [" envs" ])
78
85
return ret
79
86
80
87
81
88
# DO NOT EDIT - automatically generated.
82
- # All versions used to tested samples.
83
- ALL_VERSIONS = ["2. 7" , "3.6 " , "3.7 " , "3.8 " ]
89
+ # All versions used to test samples.
90
+ ALL_VERSIONS = ["3.6" , "3. 7" , "3.8 " , "3.9 " , "3.10 " ]
84
91
85
92
# Any default versions that should be ignored.
86
- IGNORED_VERSIONS = TEST_CONFIG [' ignored_versions' ]
93
+ IGNORED_VERSIONS = TEST_CONFIG [" ignored_versions" ]
87
94
88
95
TESTED_VERSIONS = sorted ([v for v in ALL_VERSIONS if v not in IGNORED_VERSIONS ])
89
96
90
- INSTALL_LIBRARY_FROM_SOURCE = bool (os .environ .get ("INSTALL_LIBRARY_FROM_SOURCE" , False ))
97
+ INSTALL_LIBRARY_FROM_SOURCE = os .environ .get ("INSTALL_LIBRARY_FROM_SOURCE" , False ) in (
98
+ "True" ,
99
+ "true" ,
100
+ )
101
+
102
+ # Error if a python version is missing
103
+ nox .options .error_on_missing_interpreters = True
104
+
91
105
#
92
106
# Style Checks
93
107
#
94
108
95
109
96
- def _determine_local_import_names (start_dir ) :
110
+ def _determine_local_import_names (start_dir : str ) -> List [ str ] :
97
111
"""Determines all import names that should be considered "local".
98
112
99
113
This is used when running the linter to insure that import order is
@@ -131,18 +145,34 @@ def _determine_local_import_names(start_dir):
131
145
132
146
133
147
@nox .session
134
- def lint (session ):
135
- session .install ("flake8" , "flake8-import-order" )
148
+ def lint (session : nox .sessions .Session ) -> None :
149
+ if not TEST_CONFIG ["enforce_type_hints" ]:
150
+ session .install ("flake8" , "flake8-import-order" )
151
+ else :
152
+ session .install ("flake8" , "flake8-import-order" , "flake8-annotations" )
136
153
137
154
local_names = _determine_local_import_names ("." )
138
155
args = FLAKE8_COMMON_ARGS + [
139
156
"--application-import-names" ,
140
157
"," .join (local_names ),
141
- "."
158
+ "." ,
142
159
]
143
160
session .run ("flake8" , * args )
144
161
145
162
163
+ #
164
+ # Black
165
+ #
166
+
167
+
168
+ @nox .session
169
+ def blacken (session : nox .sessions .Session ) -> None :
170
+ session .install (BLACK_VERSION )
171
+ python_files = [path for path in os .listdir ("." ) if path .endswith (".py" )]
172
+
173
+ session .run ("black" , * python_files )
174
+
175
+
146
176
#
147
177
# Sample Tests
148
178
#
@@ -151,13 +181,24 @@ def lint(session):
151
181
PYTEST_COMMON_ARGS = ["--junitxml=sponge_log.xml" ]
152
182
153
183
154
- def _session_tests (session , post_install = None ):
184
+ def _session_tests (
185
+ session : nox .sessions .Session , post_install : Callable = None
186
+ ) -> None :
187
+ if TEST_CONFIG ["pip_version_override" ]:
188
+ pip_version = TEST_CONFIG ["pip_version_override" ]
189
+ session .install (f"pip=={ pip_version } " )
155
190
"""Runs py.test for a particular project."""
156
191
if os .path .exists ("requirements.txt" ):
157
- session .install ("-r" , "requirements.txt" )
192
+ if os .path .exists ("constraints.txt" ):
193
+ session .install ("-r" , "requirements.txt" , "-c" , "constraints.txt" )
194
+ else :
195
+ session .install ("-r" , "requirements.txt" )
158
196
159
197
if os .path .exists ("requirements-test.txt" ):
160
- session .install ("-r" , "requirements-test.txt" )
198
+ if os .path .exists ("constraints-test.txt" ):
199
+ session .install ("-r" , "requirements-test.txt" , "-c" , "constraints-test.txt" )
200
+ else :
201
+ session .install ("-r" , "requirements-test.txt" )
161
202
162
203
if INSTALL_LIBRARY_FROM_SOURCE :
163
204
session .install ("-e" , _get_repo_root ())
@@ -172,27 +213,27 @@ def _session_tests(session, post_install=None):
172
213
# on travis where slow and flaky tests are excluded.
173
214
# See http://doc.pytest.org/en/latest/_modules/_pytest/main.html
174
215
success_codes = [0 , 5 ],
175
- env = get_pytest_env_vars ()
216
+ env = get_pytest_env_vars (),
176
217
)
177
218
178
219
179
220
@nox .session (python = ALL_VERSIONS )
180
- def py (session ) :
221
+ def py (session : nox . sessions . Session ) -> None :
181
222
"""Runs py.test for a sample using the specified version of Python."""
182
223
if session .python in TESTED_VERSIONS :
183
224
_session_tests (session )
184
225
else :
185
- session .skip ("SKIPPED: {} tests are disabled for this sample." . format (
186
- session .python
187
- ))
226
+ session .skip (
227
+ "SKIPPED: {} tests are disabled for this sample." . format ( session .python )
228
+ )
188
229
189
230
190
231
#
191
232
# Readmegen
192
233
#
193
234
194
235
195
- def _get_repo_root ():
236
+ def _get_repo_root () -> Optional [ str ] :
196
237
""" Returns the root folder of the project. """
197
238
# Get root of this repository. Assume we don't have directories nested deeper than 10 items.
198
239
p = Path (os .getcwd ())
@@ -201,6 +242,11 @@ def _get_repo_root():
201
242
break
202
243
if Path (p / ".git" ).exists ():
203
244
return str (p )
245
+ # .git is not available in repos cloned via Cloud Build
246
+ # setup.py is always in the library's root, so use that instead
247
+ # https://github.com/googleapis/synthtool/issues/792
248
+ if Path (p / "setup.py" ).exists ():
249
+ return str (p )
204
250
p = p .parent
205
251
raise Exception ("Unable to detect repository root." )
206
252
@@ -210,7 +256,7 @@ def _get_repo_root():
210
256
211
257
@nox .session
212
258
@nox .parametrize ("path" , GENERATED_READMES )
213
- def readmegen (session , path ) :
259
+ def readmegen (session : nox . sessions . Session , path : str ) -> None :
214
260
"""(Re-)generates the readme for a sample."""
215
261
session .install ("jinja2" , "pyyaml" )
216
262
dir_ = os .path .dirname (path )
0 commit comments