blob: 6df5a8b7040d49bdb9928baf758d52082060069a [file] [log] [blame]
Gilles Boccon-Gibod6ac91f72022-05-16 19:42:31 -07001# Copyright 2021-2022 Google LLC
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# https://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"""
16Invoke tasks
17"""
Gilles Boccon-Gibodc2959da2022-12-10 09:29:51 -080018
19# -----------------------------------------------------------------------------
20# Imports
21# -----------------------------------------------------------------------------
Gilles Boccon-Gibod6ac91f72022-05-16 19:42:31 -070022import os
23
Gilles Boccon-Gibodc2959da2022-12-10 09:29:51 -080024from invoke import task, call, Collection
Gilles Boccon-Gibod99758e42023-01-20 00:20:50 -080025from invoke.exceptions import Exit, UnexpectedExit
Gilles Boccon-Gibod6ac91f72022-05-16 19:42:31 -070026
Gilles Boccon-Gibodc2959da2022-12-10 09:29:51 -080027
28# -----------------------------------------------------------------------------
Gilles Boccon-Gibod6ac91f72022-05-16 19:42:31 -070029ROOT_DIR = os.path.dirname(os.path.realpath(__file__))
30
31ns = Collection()
32
Gilles Boccon-Gibodc2959da2022-12-10 09:29:51 -080033
34# -----------------------------------------------------------------------------
35# Build
36# -----------------------------------------------------------------------------
Gilles Boccon-Gibod6ac91f72022-05-16 19:42:31 -070037build_tasks = Collection()
Ray216ce2a2022-08-16 14:50:30 -040038ns.add_collection(build_tasks, name="build")
Gilles Boccon-Gibod6ac91f72022-05-16 19:42:31 -070039
Gilles Boccon-Gibod135df0d2022-12-10 08:53:51 -080040
Gilles Boccon-Gibodc2959da2022-12-10 09:29:51 -080041# -----------------------------------------------------------------------------
Gilles Boccon-Gibod6ac91f72022-05-16 19:42:31 -070042@task
Gilles Boccon-Gibod1f782432022-08-16 13:37:26 -070043def build(ctx, install=False):
44 if install:
45 ctx.run('python -m pip install .[build]')
46
Ray216ce2a2022-08-16 14:50:30 -040047 ctx.run("python -m build")
Gilles Boccon-Gibod6ac91f72022-05-16 19:42:31 -070048
Gilles Boccon-Gibod135df0d2022-12-10 08:53:51 -080049
Gilles Boccon-Gibodc2959da2022-12-10 09:29:51 -080050# -----------------------------------------------------------------------------
Gilles Boccon-Gibod6ac91f72022-05-16 19:42:31 -070051@task
Ray216ce2a2022-08-16 14:50:30 -040052def release_build(ctx):
Gilles Boccon-Gibod1f782432022-08-16 13:37:26 -070053 build(ctx, install=True)
Ray216ce2a2022-08-16 14:50:30 -040054
Gilles Boccon-Gibod135df0d2022-12-10 08:53:51 -080055
Gilles Boccon-Gibodc2959da2022-12-10 09:29:51 -080056# -----------------------------------------------------------------------------
Ray216ce2a2022-08-16 14:50:30 -040057@task
58def mkdocs(ctx):
59 ctx.run("mkdocs build -f docs/mkdocs/mkdocs.yml")
60
Gilles Boccon-Gibod135df0d2022-12-10 08:53:51 -080061
Gilles Boccon-Gibodc2959da2022-12-10 09:29:51 -080062# -----------------------------------------------------------------------------
63build_tasks.add_task(build, default=True)
64build_tasks.add_task(release_build, name="release")
Ray216ce2a2022-08-16 14:50:30 -040065build_tasks.add_task(mkdocs, name="mkdocs")
66
Gilles Boccon-Gibodc2959da2022-12-10 09:29:51 -080067
68# -----------------------------------------------------------------------------
69# Test
70# -----------------------------------------------------------------------------
Ray216ce2a2022-08-16 14:50:30 -040071test_tasks = Collection()
72ns.add_collection(test_tasks, name="test")
73
Alan Rosenthalf56ac142022-11-28 14:11:27 -050074
Gilles Boccon-Gibodc2959da2022-12-10 09:29:51 -080075# -----------------------------------------------------------------------------
Alan Rosenthalf56ac142022-11-28 14:11:27 -050076@task(incrementable=["verbose"])
Gilles Boccon-Gibodc2959da2022-12-10 09:29:51 -080077def test(ctx, match=None, junit=False, install=False, html=False, verbose=0):
Ray216ce2a2022-08-16 14:50:30 -040078 # Install the package before running the tests
79 if install:
80 ctx.run("python -m pip install .[test]")
Gilles Boccon-Gibod1f782432022-08-16 13:37:26 -070081
Gilles Boccon-Gibod6ac91f72022-05-16 19:42:31 -070082 args = ""
83 if junit:
84 args += "--junit-xml test-results.xml"
Gilles Boccon-Gibodc2959da2022-12-10 09:29:51 -080085 if match is not None:
86 args += f" -k '{match}'"
Alan Rosenthala3e46742022-11-23 11:26:29 -050087 if html:
Alan Rosenthalf56ac142022-11-28 14:11:27 -050088 args += " --html results.html"
89 if verbose > 0:
90 args += f" -{'v' * verbose}"
91 ctx.run(f"python -m pytest {os.path.join(ROOT_DIR, 'tests')} {args}")
Gilles Boccon-Gibod6ac91f72022-05-16 19:42:31 -070092
Gilles Boccon-Gibod135df0d2022-12-10 08:53:51 -080093
Gilles Boccon-Gibodc2959da2022-12-10 09:29:51 -080094# -----------------------------------------------------------------------------
Gilles Boccon-Gibod1f782432022-08-16 13:37:26 -070095@task
96def release_test(ctx):
97 test(ctx, install=True)
98
Gilles Boccon-Gibod135df0d2022-12-10 08:53:51 -080099
Gilles Boccon-Gibodc2959da2022-12-10 09:29:51 -0800100# -----------------------------------------------------------------------------
101test_tasks.add_task(test, default=True)
Gilles Boccon-Gibod1f782432022-08-16 13:37:26 -0700102test_tasks.add_task(release_test, name="release")
Gilles Boccon-Gibodc2959da2022-12-10 09:29:51 -0800103
104# -----------------------------------------------------------------------------
105# Project
106# -----------------------------------------------------------------------------
107project_tasks = Collection()
108ns.add_collection(project_tasks, name="project")
109
110
111# -----------------------------------------------------------------------------
112@task
113def lint(ctx, disable='C,R', errors_only=False):
114 options = []
115 if disable:
116 options.append(f"--disable={disable}")
117 if errors_only:
118 options.append("-E")
119
120 if errors_only:
121 qualifier = ' (errors only)'
122 else:
123 qualifier = f' (disabled: {disable})' if disable else ''
124
125 print(f">>> Running the linter{qualifier}...")
126 try:
127 ctx.run(f"pylint {' '.join(options)} bumble apps examples tasks.py")
128 print("The linter is happy. βœ… 😊 🐝'")
Gilles Boccon-Gibod99758e42023-01-20 00:20:50 -0800129 except UnexpectedExit as exc:
Gilles Boccon-Gibodc2959da2022-12-10 09:29:51 -0800130 print("Please check your code against the linter messages. ❌")
Gilles Boccon-Gibod99758e42023-01-20 00:20:50 -0800131 raise Exit(code=1) from exc
Gilles Boccon-Gibodc2959da2022-12-10 09:29:51 -0800132
133
134# -----------------------------------------------------------------------------
135@task
136def format_code(ctx, check=False, diff=False):
137 options = []
138 if check:
139 options.append("--check")
140 if diff:
141 options.append("--diff")
142
143 print(">>> Running the formatter...")
144 try:
145 ctx.run(f"black -S {' '.join(options)} .")
Gilles Boccon-Gibod99758e42023-01-20 00:20:50 -0800146 except UnexpectedExit as exc:
Gilles Boccon-Gibodc2959da2022-12-10 09:29:51 -0800147 print("Please run 'invoke project.format' or 'black .' to format the code. ❌")
Gilles Boccon-Gibod99758e42023-01-20 00:20:50 -0800148 raise Exit(code=1) from exc
Gilles Boccon-Gibodc2959da2022-12-10 09:29:51 -0800149
150
151# -----------------------------------------------------------------------------
Gilles Boccon-Gibod99758e42023-01-20 00:20:50 -0800152@task
153def check_types(ctx):
154 checklist = ["apps", "bumble", "examples", "tests", "tasks.py"]
155 try:
156 ctx.run(f"mypy {' '.join(checklist)}")
157 except UnexpectedExit as exc:
158 print("Please check your code against the mypy messages.")
159 raise Exit(code=1) from exc
160
161
162# -----------------------------------------------------------------------------
163@task(
164 pre=[
165 call(format_code, check=True),
166 call(lint, errors_only=True),
167 call(check_types),
168 test,
169 ]
170)
Gilles Boccon-Gibodc2959da2022-12-10 09:29:51 -0800171def pre_commit(_ctx):
172 print("All good!")
173
174
175# -----------------------------------------------------------------------------
176project_tasks.add_task(lint)
177project_tasks.add_task(format_code, name="format")
Gilles Boccon-Gibod99758e42023-01-20 00:20:50 -0800178project_tasks.add_task(check_types, name="check-types")
Gilles Boccon-Gibodc2959da2022-12-10 09:29:51 -0800179project_tasks.add_task(pre_commit)
Gilles Boccon-Gibod640b9cd2023-06-04 10:24:07 -0700180
181
182# -----------------------------------------------------------------------------
183# Web
184# -----------------------------------------------------------------------------
185web_tasks = Collection()
186ns.add_collection(web_tasks, name="web")
187
188
189# -----------------------------------------------------------------------------
190@task
191def serve(ctx, port=8000):
192 """
193 Run a simple HTTP server for the examples under the `web` directory.
194 """
195 import http.server
196
197 address = ("", port)
Gilles Boccon-Gibod71e11b72023-08-15 15:20:48 -0700198
Gilles Boccon-Gibod640b9cd2023-06-04 10:24:07 -0700199 class Handler(http.server.SimpleHTTPRequestHandler):
200 def __init__(self, *args, **kwargs):
201 super().__init__(*args, directory="web", **kwargs)
Gilles Boccon-Gibod71e11b72023-08-15 15:20:48 -0700202
Gilles Boccon-Gibod640b9cd2023-06-04 10:24:07 -0700203 server = http.server.HTTPServer(address, Handler)
204 print(f"Now serving on port {port} πŸ•ΈοΈ")
205 server.serve_forever()
206
207
208# -----------------------------------------------------------------------------
209web_tasks.add_task(serve)