micropython-stubber 1.23.1.post1__py3-none-any.whl → 1.23.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. {micropython_stubber-1.23.1.post1.dist-info → micropython_stubber-1.23.3.dist-info}/LICENSE +30 -30
  2. {micropython_stubber-1.23.1.post1.dist-info → micropython_stubber-1.23.3.dist-info}/METADATA +5 -5
  3. micropython_stubber-1.23.3.dist-info/RECORD +158 -0
  4. mpflash/README.md +220 -220
  5. mpflash/libusb_flash.ipynb +203 -203
  6. mpflash/mpflash/add_firmware.py +98 -98
  7. mpflash/mpflash/ask_input.py +236 -236
  8. mpflash/mpflash/basicgit.py +304 -284
  9. mpflash/mpflash/bootloader/__init__.py +2 -2
  10. mpflash/mpflash/bootloader/activate.py +60 -60
  11. mpflash/mpflash/bootloader/detect.py +82 -82
  12. mpflash/mpflash/bootloader/manual.py +101 -101
  13. mpflash/mpflash/bootloader/micropython.py +12 -12
  14. mpflash/mpflash/bootloader/touch1200.py +36 -36
  15. mpflash/mpflash/cli_download.py +129 -129
  16. mpflash/mpflash/cli_flash.py +224 -216
  17. mpflash/mpflash/cli_group.py +111 -111
  18. mpflash/mpflash/cli_list.py +87 -87
  19. mpflash/mpflash/cli_main.py +39 -39
  20. mpflash/mpflash/common.py +207 -166
  21. mpflash/mpflash/config.py +44 -44
  22. mpflash/mpflash/connected.py +96 -77
  23. mpflash/mpflash/download.py +364 -364
  24. mpflash/mpflash/downloaded.py +130 -130
  25. mpflash/mpflash/errors.py +9 -9
  26. mpflash/mpflash/flash/__init__.py +55 -55
  27. mpflash/mpflash/flash/esp.py +59 -59
  28. mpflash/mpflash/flash/stm32.py +19 -19
  29. mpflash/mpflash/flash/stm32_dfu.py +104 -104
  30. mpflash/mpflash/flash/uf2/__init__.py +88 -88
  31. mpflash/mpflash/flash/uf2/boardid.py +15 -15
  32. mpflash/mpflash/flash/uf2/linux.py +136 -130
  33. mpflash/mpflash/flash/uf2/macos.py +42 -42
  34. mpflash/mpflash/flash/uf2/uf2disk.py +12 -12
  35. mpflash/mpflash/flash/uf2/windows.py +43 -43
  36. mpflash/mpflash/flash/worklist.py +170 -170
  37. mpflash/mpflash/list.py +106 -106
  38. mpflash/mpflash/logger.py +41 -41
  39. mpflash/mpflash/mpboard_id/__init__.py +93 -93
  40. mpflash/mpflash/mpboard_id/add_boards.py +251 -251
  41. mpflash/mpflash/mpboard_id/board.py +37 -37
  42. mpflash/mpflash/mpboard_id/board_id.py +86 -86
  43. mpflash/mpflash/mpboard_id/store.py +48 -43
  44. mpflash/mpflash/mpremoteboard/__init__.py +266 -266
  45. mpflash/mpflash/mpremoteboard/mpy_fw_info.py +152 -141
  46. mpflash/mpflash/mpremoteboard/runner.py +140 -140
  47. mpflash/mpflash/vendor/click_aliases.py +91 -91
  48. mpflash/mpflash/vendor/dfu.py +165 -165
  49. mpflash/mpflash/vendor/pydfu.py +605 -605
  50. mpflash/mpflash/vendor/readme.md +2 -2
  51. mpflash/mpflash/versions.py +135 -135
  52. mpflash/poetry.lock +1687 -1599
  53. mpflash/pyproject.toml +65 -65
  54. mpflash/stm32_udev_rules.md +62 -62
  55. stubber/__init__.py +3 -3
  56. stubber/board/board_info.csv +193 -193
  57. stubber/board/boot.py +34 -34
  58. stubber/board/createstubs.py +986 -986
  59. stubber/board/createstubs_db.py +825 -825
  60. stubber/board/createstubs_db_min.py +331 -331
  61. stubber/board/createstubs_lvgl.py +741 -741
  62. stubber/board/createstubs_lvgl_min.py +741 -741
  63. stubber/board/createstubs_mem.py +766 -766
  64. stubber/board/createstubs_mem_min.py +306 -306
  65. stubber/board/createstubs_min.py +294 -294
  66. stubber/board/fw_info.py +141 -141
  67. stubber/board/info.py +183 -183
  68. stubber/board/main.py +19 -19
  69. stubber/board/modulelist.txt +247 -247
  70. stubber/board/pyrightconfig.json +34 -34
  71. stubber/bulk/mcu_stubber.py +437 -437
  72. stubber/codemod/_partials/__init__.py +48 -48
  73. stubber/codemod/_partials/db_main.py +147 -147
  74. stubber/codemod/_partials/lvgl_main.py +77 -77
  75. stubber/codemod/_partials/modules_reader.py +80 -80
  76. stubber/codemod/add_comment.py +53 -53
  77. stubber/codemod/add_method.py +65 -65
  78. stubber/codemod/board.py +317 -317
  79. stubber/codemod/enrich.py +145 -145
  80. stubber/codemod/merge_docstub.py +284 -284
  81. stubber/codemod/modify_list.py +54 -54
  82. stubber/codemod/utils.py +56 -56
  83. stubber/commands/build_cmd.py +94 -94
  84. stubber/commands/cli.py +49 -49
  85. stubber/commands/clone_cmd.py +78 -78
  86. stubber/commands/config_cmd.py +29 -29
  87. stubber/commands/enrich_folder_cmd.py +71 -71
  88. stubber/commands/get_core_cmd.py +71 -71
  89. stubber/commands/get_docstubs_cmd.py +92 -92
  90. stubber/commands/get_frozen_cmd.py +117 -117
  91. stubber/commands/get_mcu_cmd.py +102 -102
  92. stubber/commands/merge_cmd.py +66 -66
  93. stubber/commands/publish_cmd.py +118 -118
  94. stubber/commands/stub_cmd.py +31 -31
  95. stubber/commands/switch_cmd.py +62 -62
  96. stubber/commands/variants_cmd.py +48 -48
  97. stubber/cst_transformer.py +178 -178
  98. stubber/data/board_info.csv +193 -193
  99. stubber/data/board_info.json +1729 -1729
  100. stubber/data/micropython_tags.csv +15 -15
  101. stubber/data/requirements-core-micropython.txt +38 -38
  102. stubber/data/requirements-core-pycopy.txt +39 -39
  103. stubber/downloader.py +37 -37
  104. stubber/freeze/common.py +72 -72
  105. stubber/freeze/freeze_folder.py +69 -69
  106. stubber/freeze/freeze_manifest_2.py +126 -126
  107. stubber/freeze/get_frozen.py +131 -131
  108. stubber/get_cpython.py +112 -112
  109. stubber/get_lobo.py +59 -59
  110. stubber/minify.py +423 -423
  111. stubber/publish/bump.py +86 -86
  112. stubber/publish/candidates.py +275 -275
  113. stubber/publish/database.py +18 -18
  114. stubber/publish/defaults.py +40 -40
  115. stubber/publish/enums.py +24 -24
  116. stubber/publish/helpers.py +29 -29
  117. stubber/publish/merge_docstubs.py +132 -132
  118. stubber/publish/missing_class_methods.py +51 -51
  119. stubber/publish/package.py +150 -150
  120. stubber/publish/pathnames.py +51 -51
  121. stubber/publish/publish.py +120 -120
  122. stubber/publish/pypi.py +42 -42
  123. stubber/publish/stubpackage.py +1051 -1051
  124. stubber/rst/__init__.py +9 -9
  125. stubber/rst/classsort.py +78 -78
  126. stubber/rst/lookup.py +531 -531
  127. stubber/rst/output_dict.py +401 -401
  128. stubber/rst/reader.py +814 -814
  129. stubber/rst/report_return.py +77 -77
  130. stubber/rst/rst_utils.py +541 -541
  131. stubber/stubber.py +38 -38
  132. stubber/stubs_from_docs.py +90 -90
  133. stubber/tools/manifestfile.py +654 -654
  134. stubber/tools/readme.md +6 -6
  135. stubber/update_fallback.py +117 -117
  136. stubber/update_module_list.py +123 -123
  137. stubber/utils/__init__.py +6 -6
  138. stubber/utils/config.py +137 -137
  139. stubber/utils/makeversionhdr.py +54 -54
  140. stubber/utils/manifest.py +90 -90
  141. stubber/utils/post.py +80 -80
  142. stubber/utils/repos.py +156 -156
  143. stubber/utils/stubmaker.py +139 -139
  144. stubber/utils/typed_config_toml.py +80 -80
  145. stubber/variants.py +106 -106
  146. micropython_stubber-1.23.1.post1.dist-info/RECORD +0 -159
  147. mpflash/basicgit.py +0 -288
  148. {micropython_stubber-1.23.1.post1.dist-info → micropython_stubber-1.23.3.dist-info}/WHEEL +0 -0
  149. {micropython_stubber-1.23.1.post1.dist-info → micropython_stubber-1.23.3.dist-info}/entry_points.txt +0 -0
@@ -1,284 +1,304 @@
1
- """
2
- Simple Git module, where needed via powershell
3
-
4
- Some of the functions are based on the PyGithub module
5
- """
6
-
7
- import os
8
- import subprocess
9
- from pathlib import Path
10
- from typing import List, Optional, Union
11
-
12
- import cachetools.func
13
- from github import Auth, Github
14
- from loguru import logger as log
15
- from packaging.version import parse
16
-
17
- # from mpflash.versions import SET_PREVIEW
18
-
19
- # Token with no permissions to avoid throttling
20
- # https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2022-11-28#getting-a-higher-rate-limit
21
- PAT_NO_ACCESS = "github_pat" + "_11AAHPVFQ0qAkDnSUaMKSp" + "_ZkDl5NRRwBsUN6EYg9ahp1Dvj4FDDONnXVgimxC2EtpY7Q7BUKBoQ0Jq72X"
22
- PAT = os.environ.get("GITHUB_TOKEN") or PAT_NO_ACCESS
23
- GH_CLIENT = Github(auth=Auth.Token(PAT))
24
-
25
-
26
- def _run_local_git(
27
- cmd: List[str],
28
- repo: Optional[Union[Path, str]] = None,
29
- expect_stderr=False,
30
- capture_output=True,
31
- echo_output=True,
32
- ):
33
- "run a external (git) command in the repo's folder and deal with some of the errors"
34
- try:
35
- if repo:
36
- if isinstance(repo, str):
37
- repo = Path(repo)
38
- result = subprocess.run(cmd, capture_output=capture_output, check=True, cwd=repo.absolute().as_posix(), encoding="utf-8")
39
- else:
40
- result = subprocess.run(cmd, capture_output=capture_output, check=True, encoding="utf-8")
41
- except (NotADirectoryError, FileNotFoundError) as e: # pragma: no cover
42
- return None
43
- except subprocess.CalledProcessError as e: # pragma: no cover
44
- # add some logging for github actions
45
- log.error(f"{str(e)} : { e.stderr}")
46
- return None
47
- if result.stderr and result.stderr != b"":
48
- stderr = result.stderr
49
- if "cloning into" in stderr.lower():
50
- # log.info(stderr)
51
- expect_stderr = True
52
- if "warning" in stderr.lower():
53
- log.warning(stderr)
54
- expect_stderr = True
55
- elif capture_output and echo_output: # pragma: no cover
56
- log.info(stderr)
57
- if not expect_stderr:
58
- raise ChildProcessError(stderr)
59
-
60
- if result.returncode and result.returncode < 0:
61
- raise ChildProcessError(result.stderr)
62
- return result
63
-
64
-
65
- def clone(remote_repo: str, path: Path, shallow: bool = False, tag: Optional[str] = None) -> bool:
66
- """git clone [--depth 1] [--branch <tag_name>] <remote> <directory>"""
67
- cmd = ["git", "clone"]
68
- if shallow:
69
- cmd += ["--depth", "1"]
70
- if tag in {"preview", "latest", "master"}:
71
- tag = None
72
- cmd += [remote_repo, "--branch", tag, str(path)] if tag else [remote_repo, str(path)]
73
- if result := _run_local_git(cmd, expect_stderr=True, capture_output=False):
74
- return result.returncode == 0
75
- else:
76
- return False
77
-
78
-
79
- def get_local_tag(repo: Optional[Union[str, Path]] = None, abbreviate: bool = True) -> Union[str, None]:
80
- """
81
- get the most recent git version tag of a local repo
82
- repo Path should be in the form of : repo = "./repo/micropython"
83
-
84
- returns the tag or None
85
- """
86
- if not repo:
87
- repo = Path(".")
88
- elif isinstance(repo, str):
89
- repo = Path(repo)
90
-
91
- result = _run_local_git(
92
- # ["git", "describe", "--tags"],
93
- ["git", "describe", "--tags", "--dirty", "--always", "--match", "v[1-9].*"],
94
- repo=repo.as_posix(),
95
- expect_stderr=True,
96
- )
97
- if not result:
98
- return None
99
- tag: str = result.stdout
100
- tag = tag.replace("\r", "").replace("\n", "")
101
- if not abbreviate or "-" not in tag:
102
- return tag
103
- if "-preview" in tag:
104
- tag = tag.split("-preview")[0] + "-preview"
105
- return tag
106
-
107
-
108
- def get_local_tags(repo: Optional[Path] = None, minver: Optional[str] = None) -> List[str]:
109
- """
110
- get list of all tags of a local repo
111
- """
112
- if not repo:
113
- repo = Path(".")
114
-
115
- result = _run_local_git(["git", "tag", "-l"], repo=repo.as_posix(), expect_stderr=True)
116
- if not result or result.returncode != 0:
117
- return []
118
- tags = result.stdout.replace("\r", "").split("\n")
119
- tags = [tag for tag in tags if tag.startswith("v")]
120
- if minver:
121
- tags = [tag for tag in tags if parse(tag) >= parse(minver)]
122
- return sorted(tags)
123
-
124
-
125
- @cachetools.func.ttl_cache(maxsize=16, ttl=60) # 60 seconds
126
- def get_tags(repo: str, minver: Optional[str] = None) -> List[str]:
127
- """
128
- Get list of tag of a repote github repo
129
- """
130
- if not repo or not isinstance(repo, str) or "/" not in repo: # type: ignore
131
- return []
132
- try:
133
- gh_repo = GH_CLIENT.get_repo(repo)
134
- except ConnectionError as e:
135
- # TODO: unable to capture the exeption
136
- log.warning(f"Unable to get tags - {e}")
137
- return []
138
- tags = [tag.name for tag in gh_repo.get_tags()]
139
- if minver:
140
- tags = [tag for tag in tags if parse(tag) >= parse(minver)]
141
- return sorted(tags)
142
-
143
-
144
- def checkout_tag(tag: str, repo: Optional[Union[str, Path]] = None) -> bool:
145
- """
146
- checkout a specific git tag
147
- """
148
- cmd = ["git", "checkout", tag, "--quiet", "--force"]
149
- result = _run_local_git(cmd, repo=repo, expect_stderr=True, capture_output=True)
150
- if not result:
151
- return False
152
- # actually a good result
153
- msg = {result.stdout}
154
- if msg != {""}:
155
- log.warning(f"git message: {msg}")
156
- return True
157
-
158
-
159
- def sync_submodules(repo: Optional[Union[Path, str]] = None) -> bool:
160
- """
161
- make sure any submodules are in sync
162
- """
163
- cmds = [
164
- ["git", "submodule", "sync", "--quiet"],
165
- # ["git", "submodule", "update", "--quiet"],
166
- ["git", "submodule", "update", "--init", "lib/micropython-lib"],
167
- ]
168
- for cmd in cmds:
169
- if result := _run_local_git(cmd, repo=repo, expect_stderr=True):
170
- # actually a good result
171
- log.debug(result.stderr)
172
- else:
173
- return False
174
- return True
175
-
176
-
177
- def checkout_commit(commit_hash: str, repo: Optional[Union[Path, str]] = None) -> bool:
178
- """
179
- Checkout a specific commit
180
- """
181
- cmd = ["git", "checkout", commit_hash, "--quiet", "--force"]
182
- result = _run_local_git(cmd, repo=repo, expect_stderr=True)
183
- if not result:
184
- return False
185
- # actually a good result
186
- log.debug(result.stderr)
187
- return True
188
-
189
-
190
- def switch_tag(tag: Union[str, Path], repo: Optional[Union[Path, str]] = None) -> bool:
191
- """
192
- switch to the specified version tag of a local repo
193
- repo should be in the form of : path/.git
194
- repo = '../micropython/.git'
195
- returns None
196
- """
197
-
198
- cmd = ["git", "switch", "--detach", tag, "--quiet", "--force"]
199
- result = _run_local_git(cmd, repo=repo, expect_stderr=True)
200
- if not result:
201
- return False
202
- # actually a good result
203
- log.debug(result.stderr)
204
- return True
205
-
206
-
207
- def switch_branch(branch: str, repo: Optional[Union[Path, str]] = None) -> bool:
208
- """
209
- switch to the specified branch in a local repo"
210
- repo should be in the form of : path/.git
211
- repo = '../micropython/.git'
212
- returns None
213
- """
214
- cmd = ["git", "switch", branch, "--quiet", "--force"]
215
- result = _run_local_git(cmd, repo=repo, expect_stderr=True)
216
- if not result:
217
- return False
218
- # actually a good result
219
- log.debug(result.stderr)
220
- return True
221
-
222
-
223
- def fetch(repo: Union[Path, str]) -> bool:
224
- """
225
- fetches a repo
226
- repo should be in the form of : path/.git
227
- repo = '../micropython/.git'
228
- returns True on success
229
- """
230
- if not repo:
231
- raise NotADirectoryError
232
-
233
- cmd = ["git", "fetch", "--all", "--tags", "--quiet"]
234
- result = _run_local_git(cmd, repo=repo, echo_output=False)
235
- return result.returncode == 0 if result else False
236
-
237
-
238
- def pull(repo: Union[Path, str], branch: str = "main") -> bool:
239
- """
240
- pull a repo origin into main
241
- repo should be in the form of : path/.git
242
- repo = '../micropython/.git'
243
- returns True on success
244
- """
245
- if not repo:
246
- raise NotADirectoryError
247
- repo = Path(repo)
248
- # first checkout HEAD
249
- cmd = ["git", "checkout", branch, "--quiet", "--force"]
250
- result = _run_local_git(cmd, repo=repo, expect_stderr=True)
251
- if not result:
252
- log.error("error during git checkout main", result)
253
- return False
254
-
255
- cmd = ["git", "pull", "origin", branch, "--quiet", "--autostash"]
256
- result = _run_local_git(cmd, repo=repo, expect_stderr=True)
257
- if not result:
258
- log.error("error durign pull", result)
259
- return False
260
- return result.returncode == 0
261
-
262
-
263
- def get_git_describe(folder: Optional[str] = None):
264
- """
265
- Based on MicroPython makeversionhdr.py
266
- returns : current git tag, commits ,commit hash : "v1.19.1-841-g3446"
267
- """
268
- # Note: git describe doesn't work if no tag is available
269
- try:
270
- git_describe = subprocess.check_output(
271
- ["git", "describe", "--tags", "--dirty", "--always", "--match", "v[1-9].*"],
272
- stderr=subprocess.STDOUT,
273
- universal_newlines=True,
274
- cwd=folder,
275
- ).strip()
276
- except subprocess.CalledProcessError as er:
277
- if er.returncode == 128:
278
- # git exit code of 128 means no repository found
279
- return None
280
- git_describe = ""
281
- except OSError:
282
- return None
283
- # format
284
- return git_describe
1
+ """
2
+ Simple Git module, where needed via powershell
3
+
4
+ Some of the functions are based on the PyGithub module
5
+ """
6
+
7
+ import os
8
+ import subprocess
9
+ from pathlib import Path
10
+ from typing import List, Optional, Union
11
+
12
+ import cachetools.func
13
+ from github import Auth, BadCredentialsException, Github
14
+ from loguru import logger as log
15
+ from packaging.version import parse
16
+
17
+ # from mpflash.versions import SET_PREVIEW
18
+
19
+ # Token with no permissions to avoid throttling
20
+ # https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2022-11-28#getting-a-higher-rate-limit
21
+ PAT_NO_ACCESS = (
22
+ "github_pat_"
23
+ + "11AAHPVFQ0G4NTaQ73Bw5J"
24
+ + "_fAp7K9sZ1qL8VFnI9g78eUlCdmOXHB3WzSdj2jtEYb4XF3N7PDJBl32qIxq"
25
+ )
26
+ PAT = os.environ.get("GITHUB_TOKEN") or PAT_NO_ACCESS
27
+ GH_CLIENT = Github(auth=Auth.Token(PAT))
28
+
29
+
30
+ def _run_local_git(
31
+ cmd: List[str],
32
+ repo: Optional[Union[Path, str]] = None,
33
+ expect_stderr=False,
34
+ capture_output=True,
35
+ echo_output=True,
36
+ ):
37
+ "run a external (git) command in the repo's folder and deal with some of the errors"
38
+ try:
39
+ if repo:
40
+ if isinstance(repo, str):
41
+ repo = Path(repo)
42
+ result = subprocess.run(
43
+ cmd,
44
+ capture_output=capture_output,
45
+ check=True,
46
+ cwd=repo.absolute().as_posix(),
47
+ encoding="utf-8",
48
+ )
49
+ else:
50
+ result = subprocess.run(
51
+ cmd, capture_output=capture_output, check=True, encoding="utf-8"
52
+ )
53
+ except (NotADirectoryError, FileNotFoundError) as e: # pragma: no cover
54
+ return None
55
+ except subprocess.CalledProcessError as e: # pragma: no cover
56
+ # add some logging for github actions
57
+ log.error(f"{str(e)} : { e.stderr}")
58
+ return None
59
+ if result.stderr and result.stderr != b"":
60
+ stderr = result.stderr
61
+ if "cloning into" in stderr.lower():
62
+ # log.info(stderr)
63
+ expect_stderr = True
64
+ if "warning" in stderr.lower():
65
+ log.warning(stderr)
66
+ expect_stderr = True
67
+ elif capture_output and echo_output: # pragma: no cover
68
+ log.info(stderr)
69
+ if not expect_stderr:
70
+ raise ChildProcessError(stderr)
71
+
72
+ if result.returncode and result.returncode < 0:
73
+ raise ChildProcessError(result.stderr)
74
+ return result
75
+
76
+
77
+ def clone(remote_repo: str, path: Path, shallow: bool = False, tag: Optional[str] = None) -> bool:
78
+ """git clone [--depth 1] [--branch <tag_name>] <remote> <directory>"""
79
+ cmd = ["git", "clone"]
80
+ if shallow:
81
+ cmd += ["--depth", "1"]
82
+ if tag in {"preview", "latest", "master"}:
83
+ tag = None
84
+ cmd += [remote_repo, "--branch", tag, str(path)] if tag else [remote_repo, str(path)]
85
+ if result := _run_local_git(cmd, expect_stderr=True, capture_output=False):
86
+ return result.returncode == 0
87
+ else:
88
+ return False
89
+
90
+
91
+ def get_local_tag(
92
+ repo: Optional[Union[str, Path]] = None, abbreviate: bool = True
93
+ ) -> Union[str, None]:
94
+ """
95
+ get the most recent git version tag of a local repo
96
+ repo Path should be in the form of : repo = "./repo/micropython"
97
+
98
+ returns the tag or None
99
+ """
100
+ if not repo:
101
+ repo = Path(".")
102
+ elif isinstance(repo, str):
103
+ repo = Path(repo)
104
+
105
+ result = _run_local_git(
106
+ # ["git", "describe", "--tags"],
107
+ ["git", "describe", "--tags", "--dirty", "--always", "--match", "v[1-9].*"],
108
+ repo=repo.as_posix(),
109
+ expect_stderr=True,
110
+ )
111
+ if not result:
112
+ return None
113
+ tag: str = result.stdout
114
+ tag = tag.replace("\r", "").replace("\n", "")
115
+ if not abbreviate or "-" not in tag:
116
+ return tag
117
+ if "-preview" in tag:
118
+ tag = tag.split("-preview")[0] + "-preview"
119
+ return tag
120
+
121
+
122
+ def get_local_tags(repo: Optional[Path] = None, minver: Optional[str] = None) -> List[str]:
123
+ """
124
+ get list of all tags of a local repo
125
+ """
126
+ if not repo:
127
+ repo = Path(".")
128
+
129
+ result = _run_local_git(["git", "tag", "-l"], repo=repo.as_posix(), expect_stderr=True)
130
+ if not result or result.returncode != 0:
131
+ return []
132
+ tags = result.stdout.replace("\r", "").split("\n")
133
+ tags = [tag for tag in tags if tag.startswith("v")]
134
+ if minver:
135
+ tags = [tag for tag in tags if parse(tag) >= parse(minver)]
136
+ return sorted(tags)
137
+
138
+
139
+ @cachetools.func.ttl_cache(maxsize=16, ttl=60) # 60 seconds
140
+ def get_tags(repo: str, minver: Optional[str] = None) -> List[str]:
141
+ """
142
+ Get list of tag of a repote github repo.
143
+ only the last -preview tag is kept
144
+ """
145
+ if not repo or not isinstance(repo, str) or "/" not in repo: # type: ignore
146
+ return []
147
+ try:
148
+ gh_repo = GH_CLIENT.get_repo(repo)
149
+ except BadCredentialsException as e:
150
+ log.error(f"Github authentication error - {e}")
151
+ return []
152
+ except ConnectionError as e:
153
+ # TODO: unable to capture the exeption
154
+ log.warning(f"Unable to get tags - {e}")
155
+ return []
156
+ tags = [tag.name for tag in gh_repo.get_tags()]
157
+ if minver:
158
+ tags = [tag for tag in tags if parse(tag) >= parse(minver)]
159
+ # remove all but the last preview
160
+ tags = [t for t in sorted(tags[:-1]) if "-preview" not in t] + sorted(tags)[-1:]
161
+ return tags
162
+
163
+
164
+ def checkout_tag(tag: str, repo: Optional[Union[str, Path]] = None) -> bool:
165
+ """
166
+ checkout a specific git tag
167
+ """
168
+ cmd = ["git", "checkout", tag, "--quiet", "--force"]
169
+ result = _run_local_git(cmd, repo=repo, expect_stderr=True, capture_output=True)
170
+ if not result:
171
+ return False
172
+ # actually a good result
173
+ msg = {result.stdout}
174
+ if msg != {""}:
175
+ log.warning(f"git message: {msg}")
176
+ return True
177
+
178
+
179
+ def sync_submodules(repo: Optional[Union[Path, str]] = None) -> bool:
180
+ """
181
+ make sure any submodules are in sync
182
+ """
183
+ cmds = [
184
+ ["git", "submodule", "sync", "--quiet"],
185
+ # ["git", "submodule", "update", "--quiet"],
186
+ ["git", "submodule", "update", "--init", "lib/micropython-lib"],
187
+ ]
188
+ for cmd in cmds:
189
+ if result := _run_local_git(cmd, repo=repo, expect_stderr=True):
190
+ # actually a good result
191
+ log.debug(result.stderr)
192
+ else:
193
+ return False
194
+ return True
195
+
196
+
197
+ def checkout_commit(commit_hash: str, repo: Optional[Union[Path, str]] = None) -> bool:
198
+ """
199
+ Checkout a specific commit
200
+ """
201
+ cmd = ["git", "checkout", commit_hash, "--quiet", "--force"]
202
+ result = _run_local_git(cmd, repo=repo, expect_stderr=True)
203
+ if not result:
204
+ return False
205
+ # actually a good result
206
+ log.debug(result.stderr)
207
+ return True
208
+
209
+
210
+ def switch_tag(tag: Union[str, Path], repo: Optional[Union[Path, str]] = None) -> bool:
211
+ """
212
+ switch to the specified version tag of a local repo
213
+ repo should be in the form of : path/.git
214
+ repo = '../micropython/.git'
215
+ returns None
216
+ """
217
+
218
+ cmd = ["git", "switch", "--detach", tag, "--quiet", "--force"]
219
+ result = _run_local_git(cmd, repo=repo, expect_stderr=True)
220
+ if not result:
221
+ return False
222
+ # actually a good result
223
+ log.debug(result.stderr)
224
+ return True
225
+
226
+
227
+ def switch_branch(branch: str, repo: Optional[Union[Path, str]] = None) -> bool:
228
+ """
229
+ switch to the specified branch in a local repo"
230
+ repo should be in the form of : path/.git
231
+ repo = '../micropython/.git'
232
+ returns None
233
+ """
234
+ cmd = ["git", "switch", branch, "--quiet", "--force"]
235
+ result = _run_local_git(cmd, repo=repo, expect_stderr=True)
236
+ if not result:
237
+ return False
238
+ # actually a good result
239
+ log.debug(result.stderr)
240
+ return True
241
+
242
+
243
+ def fetch(repo: Union[Path, str]) -> bool:
244
+ """
245
+ fetches a repo
246
+ repo should be in the form of : path/.git
247
+ repo = '../micropython/.git'
248
+ returns True on success
249
+ """
250
+ if not repo:
251
+ raise NotADirectoryError
252
+
253
+ cmd = ["git", "fetch", "--all", "--tags", "--quiet"]
254
+ result = _run_local_git(cmd, repo=repo, echo_output=False)
255
+ return result.returncode == 0 if result else False
256
+
257
+
258
+ def pull(repo: Union[Path, str], branch: str = "main") -> bool:
259
+ """
260
+ pull a repo origin into main
261
+ repo should be in the form of : path/.git
262
+ repo = '../micropython/.git'
263
+ returns True on success
264
+ """
265
+ if not repo:
266
+ raise NotADirectoryError
267
+ repo = Path(repo)
268
+ # first checkout HEAD
269
+ cmd = ["git", "checkout", branch, "--quiet", "--force"]
270
+ result = _run_local_git(cmd, repo=repo, expect_stderr=True)
271
+ if not result:
272
+ log.error("error during git checkout main", result)
273
+ return False
274
+
275
+ cmd = ["git", "pull", "origin", branch, "--quiet", "--autostash"]
276
+ result = _run_local_git(cmd, repo=repo, expect_stderr=True)
277
+ if not result:
278
+ log.error("error durign pull", result)
279
+ return False
280
+ return result.returncode == 0
281
+
282
+
283
+ def get_git_describe(folder: Optional[str] = None):
284
+ """
285
+ Based on MicroPython makeversionhdr.py
286
+ returns : current git tag, commits ,commit hash : "v1.19.1-841-g3446"
287
+ """
288
+ # Note: git describe doesn't work if no tag is available
289
+ try:
290
+ git_describe = subprocess.check_output(
291
+ ["git", "describe", "--tags", "--dirty", "--always", "--match", "v[1-9].*"],
292
+ stderr=subprocess.STDOUT,
293
+ universal_newlines=True,
294
+ cwd=folder,
295
+ ).strip()
296
+ except subprocess.CalledProcessError as er:
297
+ if er.returncode == 128:
298
+ # git exit code of 128 means no repository found
299
+ return None
300
+ git_describe = ""
301
+ except OSError:
302
+ return None
303
+ # format
304
+ return git_describe
@@ -1,2 +1,2 @@
1
- from .activate import enter_bootloader # type: ignore
2
- from .detect import in_bootloader # type: ignore
1
+ from .activate import enter_bootloader # type: ignore
2
+ from .detect import in_bootloader # type: ignore