Skip to content

Commit 75f127b

Browse files
More basedpyright progress
1 parent 5a696ce commit 75f127b

File tree

12 files changed

+58
-200
lines changed

12 files changed

+58
-200
lines changed

tools/pyproject.toml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,12 +224,17 @@ include = [
224224
# We will allow code where the types of things are partially unknown, as there is
225225
# lots of legacy code in that category.
226226
# Also the PlatformIO code has to work with SCons, which is fundamentally type
227-
# annotation proof, so that can likely never pass these checks.
227+
# annotation proof, so it can likely never pass these checks.
228228
reportUnknownVariableType = false
229229
reportUnknownMemberType = false
230230
reportUnknownLambdaType = false
231231
reportMissingTypeArgument = false
232232
reportUnknownArgumentType = false
233233
reportUnknownParameterType = false
234234
reportAny = false
235-
reportExplicitAny = false
235+
reportExplicitAny = false
236+
237+
# Use "medium strict" member variable annotation rules, where the type checker
238+
# is allowed to infer the types of class variables based on what gets assigned in __init__
239+
reportIncompatibleUnannotatedOverride = true
240+
reportUnannotatedClassAttribute = false

tools/python/mbed_tools/cli/main.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,12 @@ def print_version(context: click.Context, _param: Union[click.Option, click.Para
6666
count=True,
6767
help="Set the verbosity level, enter multiple times to increase verbosity.",
6868
)
69-
def cli(verbose: int) -> None:
69+
@click.option("-t", "--traceback", is_flag=True, show_default=True, help="Show a traceback when an error is raised.")
70+
def cli(verbose: int, _traceback: bool) -> None:
7071
"""Command line tool for interacting with Mbed OS."""
72+
# note: traceback parameter not used here but is accessed through
73+
# click.context.params in GroupWithExceptionHandling
74+
7175
set_log_level(verbose)
7276

7377

tools/python/mbed_tools/project/_internal/git_utils.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
import logging
88
from dataclasses import dataclass
99
from pathlib import Path
10-
from typing import Optional
10+
from typing import Callable, Optional, TypedDict, Union
1111

1212
import git
13+
from typing_extensions import NotRequired
1314

1415
from mbed_tools.project._internal.progress import ProgressReporter
1516
from mbed_tools.project.exceptions import VersionControlError
@@ -52,13 +53,25 @@ def clone(url: str, dst_dir: Path, ref: Optional[str] = None, depth: int = 1) ->
5253
msg = f"{dst_dir} exists and is not an empty directory."
5354
raise VersionControlError(msg)
5455

55-
clone_from_kwargs = {"url": url, "to_path": str(dst_dir), "progress": ProgressReporter(name=url), "depth": depth}
56+
class CloneFromKwargs(TypedDict):
57+
url: str
58+
to_path: str
59+
progress: Callable[[int, Union[str, float], Union[str, float, None], str], None]
60+
depth: int
61+
branch: NotRequired[str]
62+
63+
clone_from_kwargs: CloneFromKwargs = {
64+
"url": url,
65+
"to_path": str(dst_dir),
66+
"progress": ProgressReporter(name=url),
67+
"depth": depth,
68+
}
5669
if ref:
5770
clone_from_kwargs["branch"] = ref
5871

5972
try:
6073
return git.Repo.clone_from(**clone_from_kwargs)
61-
except git.exc.GitCommandError as err:
74+
except git.GitCommandError as err:
6275
msg = f"Cloning git repository from url '{url}' failed. Error from VCS: {err}"
6376
raise VersionControlError(msg) from err
6477

@@ -77,7 +90,7 @@ def checkout(repo: git.Repo, ref: str, force: bool = False) -> None:
7790
try:
7891
git_args = [ref, "--force"] if force else [ref]
7992
repo.git.checkout(*git_args)
80-
except git.exc.GitCommandError as err:
93+
except git.GitCommandError as err:
8194
msg = f"Failed to check out revision '{ref}'. Error from VCS: {err}"
8295
raise VersionControlError(msg) from err
8396

@@ -95,7 +108,7 @@ def fetch(repo: git.Repo, ref: str) -> None:
95108
"""
96109
try:
97110
repo.git.fetch("origin", ref)
98-
except git.exc.GitCommandError as err:
111+
except git.GitCommandError as err:
99112
msg = f"Failed to fetch. Error from VCS: {err}"
100113
raise VersionControlError(msg) from err
101114

@@ -115,7 +128,7 @@ def init(path: Path) -> git.Repo:
115128
"""
116129
try:
117130
return git.Repo.init(str(path))
118-
except git.exc.GitCommandError as err:
131+
except git.GitCommandError as err:
119132
msg = f"Failed to initialise git repository at path '{path}'. Error from VCS: {err}"
120133
raise VersionControlError(msg) from err
121134

@@ -135,7 +148,7 @@ def get_repo(path: Path) -> git.Repo:
135148
"""
136149
try:
137150
return git.Repo(str(path))
138-
except git.exc.InvalidGitRepositoryError as err:
151+
except git.InvalidGitRepositoryError as err:
139152
msg = "Could not find a valid git repository at this path. Please perform a `git init` command."
140153
raise VersionControlError(msg) from err
141154

@@ -155,6 +168,6 @@ def get_default_branch(repo: git.Repo) -> str:
155168
"""
156169
try:
157170
return str(repo.git.symbolic_ref("refs/remotes/origin/HEAD").rsplit("/", maxsplit=1)[-1])
158-
except git.exc.GitCommandError as err:
171+
except git.GitCommandError as err:
159172
msg = f"Could not resolve default repository branch name. Error from VCS: {err}"
160173
raise VersionControlError(msg) from err

tools/python/mbed_tools/project/_internal/libraries.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ def _clone_at_ref(url: str, path: Path, ref: str) -> None:
124124
if ref:
125125
logger.info(f"Checking out revision {ref} for library {url}.")
126126
try:
127-
git_utils.clone(url, path, ref)
127+
_ = git_utils.clone(url, path, ref)
128128
except VersionControlError:
129129
# We weren't able to clone. Try again without the ref.
130130
repo = git_utils.clone(url, path)
@@ -135,4 +135,4 @@ def _clone_at_ref(url: str, path: Path, ref: str) -> None:
135135
git_utils.fetch(repo, ref)
136136
git_utils.checkout(repo, "FETCH_HEAD")
137137
else:
138-
git_utils.clone(url, path)
138+
_ = git_utils.clone(url, path)

tools/python/mbed_tools/project/_internal/progress.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@
44
#
55
"""Progress bar for git operations."""
66

7+
from __future__ import annotations
8+
79
import sys
810
from typing import Any, Optional
911

1012
from git import RemoteProgress
1113
from tqdm import tqdm
14+
from typing_extensions import override
15+
16+
from mbed_tools.project.exceptions import VersionControlError
1217

1318

1419
class ProgressBar(tqdm):
@@ -27,12 +32,14 @@ def update_progress(self, block_num: float = 1, block_size: float = 1, total_siz
2732
"""
2833
if total_size is not None and self.total != total_size:
2934
self.total = total_size
30-
self.update(block_num * block_size - self.n)
35+
_ = self.update(block_num * block_size - self.n)
3136

3237

3338
class ProgressReporter(RemoteProgress):
3439
"""GitPython RemoteProgress subclass that displays a progress bar for git fetch and push operations."""
3540

41+
bar: Optional[ProgressBar] = None
42+
3643
def __init__(self, *args: Any, name: str = "", **kwargs: Any) -> None:
3744
"""
3845
Initialiser.
@@ -43,19 +50,30 @@ def __init__(self, *args: Any, name: str = "", **kwargs: Any) -> None:
4350
self.name = name
4451
super().__init__(*args, **kwargs)
4552

46-
def update(self, op_code: int, cur_count: float, max_count: Optional[float] = None, _message: str = "") -> None:
53+
@override
54+
def update(
55+
self, op_code: int, cur_count: str | float, max_count: str | float | None = None, message: str = ""
56+
) -> None:
4757
"""
4858
Called whenever the progress changes.
4959
5060
Args:
5161
op_code: Integer describing the stage of the current operation.
5262
cur_count: Current item count.
5363
max_count: Maximum number of items expected.
54-
_message: Message string describing the number of bytes transferred in the WRITING operation.
64+
message: Message string describing the number of bytes transferred in the WRITING operation.
5565
"""
66+
cur_count = float(cur_count)
67+
if max_count is not None:
68+
max_count = float(max_count)
69+
5670
if self.BEGIN & op_code:
5771
self.bar = ProgressBar(total=max_count, file=sys.stderr, leave=False)
5872

73+
if self.bar is None:
74+
err_message = "Did not get BEGIN opcode from git first!"
75+
raise VersionControlError(err_message)
76+
5977
self.bar.desc = f"{self.name} {self._cur_line}"
6078
self.bar.update_progress(block_num=cur_count, total_size=max_count)
6179

tools/python/mbed_tools/project/_internal/project_data.py

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,11 @@
44
#
55
"""Objects representing Mbed program and library data."""
66

7-
import json
87
import logging
98
from dataclasses import dataclass
109
from pathlib import Path
1110
from typing import Optional
1211

13-
from mbed_tools.project._internal.render_templates import (
14-
render_cmakelists_template,
15-
render_gitignore_template,
16-
render_main_cpp_template,
17-
)
18-
1912
logger = logging.getLogger(__name__)
2013

2114
# Mbed program file names and constants.
@@ -63,44 +56,6 @@ class MbedProgramFiles:
6356
cmake_build_dir: Path
6457
custom_targets_json: Path
6558

66-
@classmethod
67-
def from_new(cls, root_path: Path) -> "MbedProgramFiles":
68-
"""
69-
Create MbedProgramFiles from a new directory.
70-
71-
A "new directory" in this context means it doesn't already contain an Mbed program.
72-
73-
Args:
74-
root_path: The directory in which to create the program data files.
75-
76-
Raises:
77-
ValueError: A program .mbed or mbed-os.lib file already exists at this path.
78-
"""
79-
app_config = root_path / APP_CONFIG_FILE_NAME_JSON5
80-
mbed_os_ref = root_path / MBED_OS_REFERENCE_FILE_NAME
81-
cmakelists_file = root_path / CMAKELISTS_FILE_NAME
82-
main_cpp = root_path / MAIN_CPP_FILE_NAME
83-
gitignore = root_path / ".gitignore"
84-
cmake_build_dir = root_path / BUILD_DIR
85-
custom_targets_json = root_path / CUSTOM_TARGETS_JSON_FILE_NAME
86-
87-
if mbed_os_ref.exists():
88-
msg = f"Program already exists at path {root_path}."
89-
raise ValueError(msg)
90-
91-
app_config.write_text(json.dumps(DEFAULT_APP_CONFIG, indent=4))
92-
mbed_os_ref.write_text(f"{MBED_OS_REFERENCE_URL}#{MBED_OS_REFERENCE_ID}")
93-
render_cmakelists_template(cmakelists_file, root_path.stem)
94-
render_main_cpp_template(main_cpp)
95-
render_gitignore_template(gitignore)
96-
return cls(
97-
app_config_file=app_config,
98-
mbed_os_ref=mbed_os_ref,
99-
cmakelists_file=cmakelists_file,
100-
cmake_build_dir=cmake_build_dir,
101-
custom_targets_json=custom_targets_json,
102-
)
103-
10459
@classmethod
10560
def from_existing(cls, root_path: Path, build_dir: Path) -> "MbedProgramFiles":
10661
"""

tools/python/mbed_tools/project/_internal/render_templates.py

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,49 +4,13 @@
44
#
55
"""Render jinja templates required by the project package."""
66

7-
import datetime
87
from pathlib import Path
98

109
import jinja2
1110

1211
TEMPLATES_DIRECTORY = Path("_internal", "templates")
1312

1413

15-
def render_cmakelists_template(cmakelists_file: Path, program_name: str) -> None:
16-
"""
17-
Render CMakeLists.tmpl with the copyright year and program name as the app target name.
18-
19-
Args:
20-
cmakelists_file: The path where CMakeLists.txt will be written.
21-
program_name: The name of the program, will be used as the app target name.
22-
"""
23-
cmakelists_file.write_text(
24-
render_jinja_template(
25-
"CMakeLists.tmpl", {"program_name": program_name, "year": str(datetime.datetime.now().year)}
26-
)
27-
)
28-
29-
30-
def render_main_cpp_template(main_cpp: Path) -> None:
31-
"""
32-
Render a basic main.cpp which prints a hello message and returns.
33-
34-
Args:
35-
main_cpp: Path where the main.cpp file will be written.
36-
"""
37-
main_cpp.write_text(render_jinja_template("main.tmpl", {"year": str(datetime.datetime.now().year)}))
38-
39-
40-
def render_gitignore_template(gitignore: Path) -> None:
41-
"""
42-
Write out a basic gitignore file ignoring the build and config directory.
43-
44-
Args:
45-
gitignore: The path where the gitignore file will be written.
46-
"""
47-
gitignore.write_text(render_jinja_template("gitignore.tmpl", {}))
48-
49-
5014
def render_jinja_template(template_name: str, context: dict) -> str:
5115
"""
5216
Render a jinja template.

tools/python/mbed_tools/project/_internal/templates/CMakeLists.tmpl

Lines changed: 0 additions & 27 deletions
This file was deleted.

tools/python/mbed_tools/project/_internal/templates/gitignore.tmpl

Lines changed: 0 additions & 2 deletions
This file was deleted.

tools/python/mbed_tools/project/_internal/templates/main.tmpl

Lines changed: 0 additions & 13 deletions
This file was deleted.

0 commit comments

Comments
 (0)