44import os
55import re
66from pathlib import Path
7- from typing import Any , Callable
7+ from typing import Any , Callable , TypeVar
88
99import nox
1010from nox .sessions import Session
1313ROOT = Path (__file__ ).parent
1414SRC = ROOT / "src"
1515POSARGS_PATTERN = re .compile (r"^(\w+)\[(.+)\]$" )
16+ TRUE_VALUES = {"true" , "True" , "TRUE" , "1" }
1617
1718
18- def apply_standard_pip_upgrades (
19- function : Callable [[Session ], Any ]
20- ) -> Callable [[Session ], Any ]:
21- @functools .wraps (function )
22- def wrapper (session : Session ) -> None :
23- session .install ("--upgrade" , "pip" , "setuptools" , "wheel" )
24- return function (session )
19+ _Return = TypeVar ("_Return" )
2520
26- return wrapper
21+
22+ def do_first (
23+ first_session_func : Callable [[Session ], None ]
24+ ) -> Callable [[Callable [[Session ], _Return ]], Callable [[Session ], _Return ]]:
25+ """Decorator for functions defining session actions that should happen first
26+
27+ >>> @do_first
28+ >>> def setup(session):
29+ >>> ... # do some setup
30+ >>>
31+ >>> @setup
32+ >>> def the_actual_session(session):
33+ >>> ... # so actual work
34+
35+ This makes it quick an easy to define common setup actions.
36+ """
37+
38+ def setup (
39+ second_session_func : Callable [[Session ], _Return ]
40+ ) -> Callable [[Session ], _Return ]:
41+ @functools .wraps (second_session_func )
42+ def wrapper (session : Session ) -> Any :
43+ first_session_func (session )
44+ return second_session_func (session )
45+
46+ return wrapper
47+
48+ return setup
49+
50+
51+ @do_first
52+ def apply_standard_pip_upgrades (session : Session ) -> None :
53+ session .install ("--upgrade" , "pip" )
54+
55+
56+ @do_first
57+ def install_latest_npm_in_ci (session : Session ) -> None :
58+ if os .environ .get ("CI" ) in TRUE_VALUES :
59+ session .run ("npm" , "install" , "-g" , "npm@latest" )
2760
2861
2962@nox .session (reuse_venv = True )
3063@apply_standard_pip_upgrades
3164def format (session : Session ) -> None :
65+ """Auto format Python and Javascript code"""
3266 # format Python
3367 install_requirements_file (session , "check-style" )
3468 session .run ("black" , "." )
@@ -58,6 +92,7 @@ def example(session: Session) -> None:
5892
5993
6094@nox .session (reuse_venv = True )
95+ @install_latest_npm_in_ci
6196@apply_standard_pip_upgrades
6297def docs (session : Session ) -> None :
6398 """Build and display documentation in the browser (automatically reloads on change)"""
@@ -115,23 +150,31 @@ def docs_in_docker(session: Session) -> None:
115150def test (session : Session ) -> None :
116151 """Run the complete test suite"""
117152 session .notify ("test_python" , posargs = session .posargs )
118- session .notify ("test_types" )
119- session .notify ("test_style" )
120153 session .notify ("test_docs" )
121154 session .notify ("test_javascript" )
122155
123156
124157@nox .session
125- def test_short (session : Session ) -> None :
126- """Run a shortened version of the test suite"""
127- session .notify ("test_python" , posargs = session .posargs )
128- session .notify ("test_docs" )
129- session .notify ("test_javascript" )
158+ def test_python (session : Session ) -> None :
159+ """Run all Python checks"""
160+ session .notify ("test_python_suite" , posargs = session .posargs )
161+ session .notify ("test_python_types" )
162+ session .notify ("test_python_style" )
163+ session .notify ("test_python_build" )
164+
165+
166+ @nox .session
167+ def test_javascript (session : Session ) -> None :
168+ """Run all Javascript checks"""
169+ session .notify ("test_javascript_suite" )
170+ session .notify ("test_javascript_build" )
171+ session .notify ("test_javascript_style" )
130172
131173
132174@nox .session
175+ @install_latest_npm_in_ci
133176@apply_standard_pip_upgrades
134- def test_python (session : Session ) -> None :
177+ def test_python_suite (session : Session ) -> None :
135178 """Run the Python-based test suite"""
136179 session .env ["IDOM_DEBUG_MODE" ] = "1"
137180 install_requirements_file (session , "test-env" )
@@ -149,8 +192,8 @@ def test_python(session: Session) -> None:
149192
150193@nox .session
151194@apply_standard_pip_upgrades
152- def test_types (session : Session ) -> None :
153- """Perform a static type analysis of the codebase"""
195+ def test_python_types (session : Session ) -> None :
196+ """Perform a static type analysis of the Python codebase"""
154197 install_requirements_file (session , "check-types" )
155198 install_requirements_file (session , "pkg-deps" )
156199 install_requirements_file (session , "pkg-extras" )
@@ -159,8 +202,8 @@ def test_types(session: Session) -> None:
159202
160203@nox .session
161204@apply_standard_pip_upgrades
162- def test_style (session : Session ) -> None :
163- """Check that style guidelines are being followed"""
205+ def test_python_style (session : Session ) -> None :
206+ """Check that Python style guidelines are being followed"""
164207 install_requirements_file (session , "check-style" )
165208 session .run ("flake8" , "src/idom" , "tests" , "docs" )
166209 black_default_exclude = r"\.eggs|\.git|\.hg|\.mypy_cache|\.nox|\.tox|\.venv|\.svn|_build|buck-out|build|dist"
@@ -176,6 +219,15 @@ def test_style(session: Session) -> None:
176219
177220@nox .session
178221@apply_standard_pip_upgrades
222+ def test_python_build (session : Session ) -> None :
223+ """Test whether the Python package can be build for distribution"""
224+ install_requirements_file (session , "build-pkg" )
225+ session .run ("python" , "setup.py" , "bdist_wheel" , "sdist" )
226+
227+
228+ @nox .session
229+ @install_latest_npm_in_ci
230+ @apply_standard_pip_upgrades
179231def test_docs (session : Session ) -> None :
180232 """Verify that the docs build and that doctests pass"""
181233 install_requirements_file (session , "build-docs" )
@@ -192,19 +244,47 @@ def test_docs(session: Session) -> None:
192244 "docs/build" ,
193245 )
194246 session .run ("sphinx-build" , "-b" , "doctest" , "docs/source" , "docs/build" )
247+ # ensure docker image build works too
248+ session .run ("docker" , "build" , "." , "--file" , "docs/Dockerfile" , external = True )
195249
196250
197- @nox . session
198- def test_javascript ( session : Session ) -> None :
199- """Run the Javascript-based test suite and ensure it bundles succesfully"""
251+ @do_first
252+ @ install_latest_npm_in_ci
253+ def setup_client_env ( session : Session ) -> None :
200254 session .chdir (SRC / "client" )
201255 session .run ("npm" , "install" , external = True )
256+
257+
258+ @nox .session
259+ @setup_client_env
260+ def test_javascript_suite (session : Session ) -> None :
261+ """Run the Javascript-based test suite and ensure it bundles succesfully"""
262+ session .run ("npm" , "run" , "test" , external = True )
263+
264+
265+ @nox .session
266+ @setup_client_env
267+ def test_javascript_build (session : Session ) -> None :
268+ """Run the Javascript-based test suite and ensure it bundles succesfully"""
202269 session .run ("npm" , "run" , "test" , external = True )
270+
271+
272+ @nox .session
273+ @setup_client_env
274+ def test_javascript_style (session : Session ) -> None :
275+ """Check that Javascript style guidelines are being followed"""
276+ session .run ("npm" , "run" , "check-format" , external = True )
277+
278+
279+ @nox .session
280+ def build_js (session : Session ) -> None :
281+ """Build javascript client code"""
282+ session .chdir (SRC / "client" )
203283 session .run ("npm" , "run" , "build" , external = True )
204284
205285
206286@nox .session
207- def tag (session : Session ):
287+ def tag (session : Session ) -> None :
208288 """Create a new git tag"""
209289 try :
210290 session .run (
@@ -265,12 +345,6 @@ def update_version(session: Session) -> None:
265345 session .install ("-e" , "." )
266346
267347
268- @nox .session
269- def build_js (session : Session ) -> None :
270- session .chdir (SRC / "client" )
271- session .run ("npm" , "run" , "build" , external = True )
272-
273-
274348@nox .session (reuse_venv = True )
275349def latest_pull_requests (session : Session ) -> None :
276350 """A basic script for outputing changelog info"""
0 commit comments