18
18
19
19
from __future__ import absolute_import
20
20
21
+ from functools import wraps
21
22
import os
22
23
import pathlib
23
24
import re
24
25
import shutil
25
26
import subprocess
27
+ import time
26
28
import warnings
27
29
28
30
import nox
76
78
77
79
CURRENT_DIRECTORY = pathlib .Path (__file__ ).parent .absolute ()
78
80
81
+
82
+ def _calculate_duration (func ):
83
+ """This decorator prints the execution time for the decorated function."""
84
+
85
+ @wraps (func )
86
+ def wrapper (* args , ** kwargs ):
87
+ start = time .monotonic ()
88
+ result = func (* args , ** kwargs )
89
+ end = time .monotonic ()
90
+ total_seconds = round (end - start )
91
+ hours = total_seconds // 3600 # Integer division to get hours
92
+ remaining_seconds = total_seconds % 3600 # Modulo to find remaining seconds
93
+ minutes = remaining_seconds // 60
94
+ seconds = remaining_seconds % 60
95
+ human_time = f"{ hours :} :{ minutes :0>2} :{ seconds :0>2} "
96
+ print (f"Session ran in { total_seconds } seconds ({ human_time } )" )
97
+ return result
98
+
99
+ return wrapper
100
+
101
+
79
102
# 'docfx' is excluded since it only needs to run in 'docs-presubmit'
80
103
nox .options .sessions = [
81
104
"unit" ,
92
115
93
116
94
117
@nox .session (python = DEFAULT_PYTHON_VERSION )
118
+ @_calculate_duration
95
119
def lint (session ):
96
120
"""Run linters.
97
121
@@ -108,6 +132,7 @@ def lint(session):
108
132
109
133
110
134
@nox .session (python = DEFAULT_PYTHON_VERSION )
135
+ @_calculate_duration
111
136
def blacken (session ):
112
137
"""Run black. Format code to uniform standard."""
113
138
session .install (BLACK_VERSION )
@@ -118,6 +143,7 @@ def blacken(session):
118
143
119
144
120
145
@nox .session (python = DEFAULT_PYTHON_VERSION )
146
+ @_calculate_duration
121
147
def format (session ):
122
148
"""
123
149
Run isort to sort imports. Then run black
@@ -138,6 +164,7 @@ def format(session):
138
164
139
165
140
166
@nox .session (python = DEFAULT_PYTHON_VERSION )
167
+ @_calculate_duration
141
168
def lint_setup_py (session ):
142
169
"""Verify that setup.py is valid (including RST check)."""
143
170
session .install ("docutils" , "pygments" )
@@ -199,6 +226,7 @@ def default(session):
199
226
200
227
201
228
@nox .session (python = UNIT_TEST_PYTHON_VERSIONS )
229
+ @_calculate_duration
202
230
def unit (session ):
203
231
"""Run the unit test suite."""
204
232
default (session )
@@ -235,6 +263,7 @@ def install_systemtest_dependencies(session, *constraints):
235
263
236
264
237
265
@nox .session (python = SYSTEM_TEST_PYTHON_VERSIONS )
266
+ @_calculate_duration
238
267
def system (session ):
239
268
"""Run the system test suite."""
240
269
constraints_path = str (
@@ -281,6 +310,7 @@ def system(session):
281
310
282
311
283
312
@nox .session (python = DEFAULT_PYTHON_VERSION )
313
+ @_calculate_duration
284
314
def prerelease (session ):
285
315
session .install (
286
316
"--extra-index-url" ,
@@ -334,7 +364,7 @@ def prerelease(session):
334
364
constraints_text = constraints_file .read ()
335
365
336
366
# Ignore leading whitespace and comment lines.
337
- deps = [
367
+ constraints_deps = [
338
368
match .group (1 )
339
369
for match in re .finditer (
340
370
r"^\s*(\S+)(?===\S+)" , constraints_text , flags = re .MULTILINE
@@ -343,7 +373,7 @@ def prerelease(session):
343
373
344
374
# We use --no-deps to ensure that pre-release versions aren't overwritten
345
375
# by the version ranges in setup.py.
346
- session .install (* deps )
376
+ session .install (* constraints_deps )
347
377
session .install ("--no-deps" , "-e" , ".[all]" )
348
378
349
379
# Print out prerelease package versions.
@@ -368,6 +398,7 @@ def prerelease(session):
368
398
369
399
370
400
@nox .session (python = DEFAULT_PYTHON_VERSION )
401
+ @_calculate_duration
371
402
def cover (session ):
372
403
"""Run the final coverage report.
373
404
@@ -390,6 +421,7 @@ def cover(session):
390
421
391
422
392
423
@nox .session (python = "3.9" )
424
+ @_calculate_duration
393
425
def docs (session ):
394
426
"""Build the docs for this library."""
395
427
@@ -425,6 +457,7 @@ def docs(session):
425
457
426
458
427
459
@nox .session (python = "3.10" )
460
+ @_calculate_duration
428
461
def docfx (session ):
429
462
"""Build the docfx yaml files for this library."""
430
463
@@ -470,92 +503,6 @@ def docfx(session):
470
503
)
471
504
472
505
473
- @nox .session (python = SYSTEM_TEST_PYTHON_VERSIONS )
474
- def prerelease_deps (session ):
475
- """Run all tests with prerelease versions of dependencies installed."""
476
-
477
- # Install all dependencies
478
- session .install ("-e" , ".[all, tests, tracing]" )
479
- unit_deps_all = UNIT_TEST_STANDARD_DEPENDENCIES + UNIT_TEST_EXTERNAL_DEPENDENCIES
480
- session .install (* unit_deps_all )
481
- system_deps_all = (
482
- SYSTEM_TEST_STANDARD_DEPENDENCIES + SYSTEM_TEST_EXTERNAL_DEPENDENCIES
483
- )
484
- session .install (* system_deps_all )
485
-
486
- # Because we test minimum dependency versions on the minimum Python
487
- # version, the first version we test with in the unit tests sessions has a
488
- # constraints file containing all dependencies and extras.
489
- with open (
490
- CURRENT_DIRECTORY
491
- / "testing"
492
- / f"constraints-{ UNIT_TEST_PYTHON_VERSIONS [0 ]} .txt" ,
493
- encoding = "utf-8" ,
494
- ) as constraints_file :
495
- constraints_text = constraints_file .read ()
496
-
497
- # Ignore leading whitespace and comment lines.
498
- constraints_deps = [
499
- match .group (1 )
500
- for match in re .finditer (
501
- r"^\s*(\S+)(?===\S+)" , constraints_text , flags = re .MULTILINE
502
- )
503
- ]
504
-
505
- session .install (* constraints_deps )
506
-
507
- prerel_deps = [
508
- # "protobuf",
509
- # dependency of grpc
510
- "six" ,
511
- "googleapis-common-protos" ,
512
- # Exclude version 1.52.0rc1 which has a known issue. See https://github.com/grpc/grpc/issues/32163
513
- "grpcio!=1.52.0rc1" ,
514
- "grpcio-status" ,
515
- "google-api-core" ,
516
- "google-auth" ,
517
- "proto-plus" ,
518
- "google-cloud-testutils" ,
519
- # dependencies of google-cloud-testutils"
520
- "click" ,
521
- ]
522
-
523
- for dep in prerel_deps :
524
- session .install ("--pre" , "--no-deps" , "--upgrade" , dep )
525
-
526
- # Remaining dependencies
527
- other_deps = [
528
- "requests" ,
529
- ]
530
- session .install (* other_deps )
531
-
532
- # Print out package versions.
533
- session .run ("python" , "-m" , "pip" , "freeze" )
534
-
535
- session .run ("py.test" , "tests/unit" )
536
-
537
- system_test_path = os .path .join ("tests" , "system.py" )
538
- system_test_folder_path = os .path .join ("tests" , "system" )
539
-
540
- # Only run system tests if found.
541
- if os .path .exists (system_test_path ):
542
- session .run (
543
- "py.test" ,
544
- "--verbose" ,
545
- f"--junitxml=system_{ session .python } _sponge_log.xml" ,
546
- system_test_path ,
547
- * session .posargs ,
548
- )
549
- if os .path .exists (system_test_folder_path ):
550
- session .run (
551
- "py.test" ,
552
- "--verbose" ,
553
- f"--junitxml=system_{ session .python } _sponge_log.xml" ,
554
- system_test_folder_path ,
555
- * session .posargs ,
556
- )
557
-
558
-
559
506
def install_conda_unittest_dependencies (session , standard_deps , conda_forge_packages ):
560
507
"""Installs packages from conda forge, pypi, and locally."""
561
508
@@ -573,6 +520,7 @@ def install_conda_unittest_dependencies(session, standard_deps, conda_forge_pack
573
520
574
521
575
522
@nox .session (python = CONDA_TEST_PYTHON_VERSIONS , venv_backend = "mamba" )
523
+ @_calculate_duration
576
524
def conda_test (session ):
577
525
"""Run test suite in a conda virtual environment.
578
526
0 commit comments