micropython-stubber 1.16.2__py3-none-any.whl → 1.17.0__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 (55) hide show
  1. {micropython_stubber-1.16.2.dist-info → micropython_stubber-1.17.0.dist-info}/METADATA +2 -1
  2. {micropython_stubber-1.16.2.dist-info → micropython_stubber-1.17.0.dist-info}/RECORD +54 -54
  3. stubber/__init__.py +1 -1
  4. stubber/basicgit.py +27 -33
  5. stubber/board/board_info.csv +137 -103
  6. stubber/board/createstubs.py +222 -189
  7. stubber/board/createstubs_db.py +284 -214
  8. stubber/board/createstubs_db_min.py +286 -265
  9. stubber/board/createstubs_db_mpy.mpy +0 -0
  10. stubber/board/createstubs_lvgl.py +171 -113
  11. stubber/board/createstubs_lvgl_min.py +738 -275
  12. stubber/board/createstubs_lvgl_mpy.mpy +0 -0
  13. stubber/board/createstubs_mem.py +237 -174
  14. stubber/board/createstubs_mem_min.py +263 -247
  15. stubber/board/createstubs_mem_mpy.mpy +0 -0
  16. stubber/board/createstubs_min.py +242 -227
  17. stubber/board/createstubs_mpy.mpy +0 -0
  18. stubber/board/fw_info.py +135 -0
  19. stubber/board/modulelist.txt +1 -2
  20. stubber/codemod/_partials/__init__.py +1 -1
  21. stubber/codemod/_partials/db_main.py +90 -72
  22. stubber/codemod/_partials/modules_reader.py +29 -17
  23. stubber/codemod/board.py +2 -4
  24. stubber/codemod/enrich.py +1 -1
  25. stubber/commands/build_cmd.py +6 -4
  26. stubber/commands/get_docstubs_cmd.py +6 -11
  27. stubber/commands/get_frozen_cmd.py +6 -11
  28. stubber/commands/switch_cmd.py +6 -4
  29. stubber/data/board_info.csv +134 -101
  30. stubber/data/board_info.json +1357 -901
  31. stubber/freeze/freeze_manifest_2.py +2 -1
  32. stubber/freeze/get_frozen.py +28 -13
  33. stubber/minify.py +56 -43
  34. stubber/publish/candidates.py +15 -23
  35. stubber/publish/defaults.py +2 -2
  36. stubber/publish/merge_docstubs.py +5 -7
  37. stubber/publish/missing_class_methods.py +2 -2
  38. stubber/publish/pathnames.py +2 -2
  39. stubber/publish/publish.py +2 -1
  40. stubber/publish/stubpackage.py +20 -40
  41. stubber/rst/lookup.py +9 -7
  42. stubber/rst/reader.py +2 -1
  43. stubber/stubber.py +5 -6
  44. stubber/update_fallback.py +3 -1
  45. stubber/update_module_list.py +1 -1
  46. stubber/utils/__init__.py +1 -1
  47. stubber/utils/config.py +7 -9
  48. stubber/utils/post.py +1 -1
  49. stubber/utils/repos.py +10 -7
  50. stubber/utils/versions.py +48 -7
  51. stubber/variants.py +3 -3
  52. stubber/board/logging.py +0 -99
  53. {micropython_stubber-1.16.2.dist-info → micropython_stubber-1.17.0.dist-info}/LICENSE +0 -0
  54. {micropython_stubber-1.16.2.dist-info → micropython_stubber-1.17.0.dist-info}/WHEEL +0 -0
  55. {micropython_stubber-1.16.2.dist-info → micropython_stubber-1.17.0.dist-info}/entry_points.txt +0 -0
@@ -57,7 +57,8 @@ def freeze_one_manifest_2(manifest: Path, frozen_stub_path: Path, mpy_path: Path
57
57
  # so we need to get the port and board from the path
58
58
  log.info(f"input_manifest: {manifest}")
59
59
  port, board = get_portboard(manifest)
60
- log.info(f"port-board: '{port}-{board}'")
60
+
61
+ log.info("port-board: {}".format((port + "-" +board).rstrip("-")))
61
62
 
62
63
  path_vars = make_path_vars(port=port, board=board, mpy_path=mpy_path, mpy_lib_path=mpy_lib_path)
63
64
  upy_manifest = ManifestFile(MODE_FREEZE, path_vars)
@@ -24,14 +24,15 @@ from typing import List, Optional
24
24
 
25
25
  from loguru import logger as log
26
26
  from packaging.version import Version
27
+
28
+ import stubber.basicgit as git
27
29
  from stubber import utils
30
+ from stubber.codemod.add_comment import AddComment
28
31
  from stubber.freeze.freeze_folder import freeze_folders # Micropython < v1.12
29
32
  from stubber.freeze.freeze_manifest_2 import freeze_one_manifest_2
30
33
  from stubber.utils.config import CONFIG
31
- from stubber.codemod.add_comment import AddComment
32
-
34
+ from stubber.utils.versions import SET_PREVIEW, V_PREVIEW
33
35
 
34
- # globals
35
36
  FAMILY = "micropython"
36
37
 
37
38
 
@@ -54,13 +55,18 @@ def add_comment_to_path(path: Path, comment: str) -> None:
54
55
  Add a comment to the top of each file in the path
55
56
  using a codemod
56
57
  """
57
- #TODO: #305 add comment line to each file with the micropython version it was generated from
58
+ # TODO: #305 add comment line to each file with the micropython version it was generated from
58
59
  # frozen_stub_path
59
60
  # python -m libcst.tool codemod --include-stubs --no-format add_comment.AddComment .\repos\micropython-stubs\stubs\micropython-v1_19_1-frozen\ --comment "# Micropython 1.19.1 frozen stubs"
60
61
  pass
61
62
 
62
63
 
63
- def freeze_any(stub_folder: Path, version: str, mpy_path: Optional[Path] = None, mpy_lib_path: Optional[Path] = None) -> int:
64
+ def freeze_any(
65
+ stub_folder: Optional[Path] = None,
66
+ version: str = V_PREVIEW,
67
+ mpy_path: Optional[Path] = None,
68
+ mpy_lib_path: Optional[Path] = None,
69
+ ) -> Path:
64
70
  """
65
71
  Get and parse the to-be-frozen .py modules for micropython to extract the static type information
66
72
  - requires that the MicroPython and Micropython-lib repos are checked out and available on a local path
@@ -73,24 +79,24 @@ def freeze_any(stub_folder: Path, version: str, mpy_path: Optional[Path] = None,
73
79
  current_dir = os.getcwd()
74
80
  mpy_path = Path(mpy_path).absolute() if mpy_path else CONFIG.mpy_path.absolute()
75
81
  mpy_lib_path = Path(mpy_lib_path).absolute() if mpy_lib_path else CONFIG.mpy_path.absolute()
76
- if not stub_folder:
77
- frozen_stub_path = Path("{}/{}_{}_frozen".format(CONFIG.stub_path, FAMILY, utils.clean_version(version, flat=True))).absolute()
78
- else:
79
- frozen_stub_path: Path = Path(stub_folder).absolute()
80
82
 
81
83
  # if old version of micropython, use the old freeze method
82
- if version not in ["master", "latest"] and Version(version) <= Version("1.11"):
84
+ if version not in SET_PREVIEW and Version(version) <= Version("1.11"):
85
+ frozen_stub_path = get_fsp(version, stub_folder)
83
86
  log.debug("MicroPython v1.11, older or other")
84
87
  # others
85
88
  modules = freeze_folders(frozen_stub_path.as_posix(), mpy_path.as_posix(), mpy_lib_path.as_posix(), version)
86
89
  count = len(modules)
87
90
  else:
91
+ # get the current checked out version
92
+ version = utils.checkedout_version(CONFIG.mpy_path)
93
+
94
+ frozen_stub_path = get_fsp(version, stub_folder)
88
95
  # get the manifests of the different ports and boards
89
96
  all_manifests = get_manifests(mpy_path)
90
97
 
91
98
  # process all_manifests under the ports folder and update the frozen files in the stubs folder
92
- # we are goning to jump around, avoid relative paths
93
- frozen_stub_path = frozen_stub_path.absolute()
99
+ # we are going to jump around, avoid relative paths
94
100
  mpy_path = mpy_path.absolute()
95
101
  mpy_lib_path = mpy_lib_path.absolute()
96
102
 
@@ -111,4 +117,13 @@ def freeze_any(stub_folder: Path, version: str, mpy_path: Optional[Path] = None,
111
117
 
112
118
  # restore cwd
113
119
  os.chdir(current_dir)
114
- return count
120
+ return frozen_stub_path
121
+
122
+
123
+ def get_fsp(version: str, stub_folder: Optional[Path] = None) -> Path:
124
+ if not stub_folder:
125
+ frozen_stub_path = CONFIG.stub_path / f"{FAMILY}-{utils.clean_version(version, flat=True)}-frozen"
126
+ frozen_stub_path = frozen_stub_path.absolute()
127
+ else:
128
+ frozen_stub_path: Path = Path(stub_folder).absolute()
129
+ return frozen_stub_path
stubber/minify.py CHANGED
@@ -13,6 +13,8 @@ from typing import List, Tuple, Union
13
13
  import python_minifier
14
14
  from loguru import logger as log
15
15
 
16
+ from stubber.utils.versions import SET_PREVIEW, V_PREVIEW
17
+
16
18
  # Type Aliases for minify
17
19
  StubSource = Union[Path, str, StringIO, TextIOWrapper]
18
20
  XCompileDest = Union[Path, BytesIO]
@@ -192,19 +194,62 @@ def minify_script(source_script: StubSource, keep_report: bool = True, diff: boo
192
194
 
193
195
  source_content = ""
194
196
  if isinstance(source_script, Path):
195
- source_content = source_script.read_text()
197
+ source_content = source_script.read_text(encoding="utf-8")
196
198
  elif isinstance(source_script, (StringIO, TextIOWrapper)):
197
199
  source_content = "".join(source_script.readlines())
198
200
  elif isinstance(source_script, str): # type: ignore
199
201
  source_content = source_script
200
202
  else:
201
- raise TypeError(
202
- f"source_script must be str, Path, or file-like object, not {type(source_script)}"
203
- )
203
+ raise TypeError(f"source_script must be str, Path, or file-like object, not {type(source_script)}")
204
204
 
205
205
  if not source_content:
206
206
  raise ValueError("No source content")
207
+ len_1 = len(source_content)
208
+
209
+ if 0:
210
+ min_source = reduce_log_print(keep_report, diff, source_content)
211
+ else:
212
+ min_source = source_content
213
+ len_2 = len(min_source)
214
+
215
+ min_source = python_minifier.minify(
216
+ min_source,
217
+ filename=getattr(source_script, "name", None),
218
+ combine_imports=True,
219
+ remove_literal_statements=True, # no Docstrings
220
+ remove_annotations=True, # not used runtime anyways
221
+ hoist_literals=True, # remove redundant strings
222
+ rename_locals=True, # short names save memory
223
+ preserve_locals=["stubber", "path"], # names to keep
224
+ rename_globals=True, # short names save memory
225
+ # keep these globals to allow testing/mocking to work against the minified not compiled version
226
+ preserve_globals=[
227
+ "main",
228
+ "Stubber",
229
+ "read_path",
230
+ "get_root",
231
+ "_info",
232
+ "os",
233
+ "sys",
234
+ "__version__",
235
+ ],
236
+ # remove_pass=True, # no dead code
237
+ # convert_posargs_to_args=True, # Does not save any space
238
+ )
239
+ len_3 = len(min_source)
240
+ if 1:
241
+ # write to temp file for debugging
242
+ with open("tmp_minified.py", "w+") as f:
243
+ f.write(min_source)
244
+
245
+ log.info(f"Original length : {len_1}")
246
+ log.info(f"Reduced length : {len_2}")
247
+ log.info(f"Minified length : {len_3}")
248
+ log.info(f"Reduced by : {len_1-len_3} ")
249
+ return min_source
207
250
 
251
+
252
+ def reduce_log_print(keep_report, diff, source_content):
208
253
  edits: LineEdits = [
209
254
  ("keepprint", "print('Debug: "),
210
255
  ("keepprint", "print('DEBUG: "),
@@ -250,40 +295,7 @@ def minify_script(source_script: StubSource, keep_report: bool = True, diff: boo
250
295
  ] + edits
251
296
 
252
297
  content = edit_lines(source_content, edits, diff=diff)
253
-
254
- if 1:
255
- # write to temp file for debugging
256
- with open("tmp_minified.py", "w+") as f:
257
- f.write(content)
258
-
259
- source = python_minifier.minify(
260
- content,
261
- filename=getattr(source_script, "name", None),
262
- combine_imports=True,
263
- remove_literal_statements=True, # no Docstrings
264
- remove_annotations=True, # not used runtime anyways
265
- hoist_literals=True, # remove redundant strings
266
- rename_locals=True, # short names save memory
267
- preserve_locals=["stubber", "path"], # names to keep
268
- rename_globals=True, # short names save memory
269
- # keep these globals to allow testing/mocking to work against the minified not compiled version
270
- preserve_globals=[
271
- "main",
272
- "Stubber",
273
- "read_path",
274
- "get_root",
275
- "_info",
276
- "os",
277
- "sys",
278
- "__version__",
279
- ],
280
- # remove_pass=True, # no dead code
281
- # convert_posargs_to_args=True, # Does not save any space
282
- )
283
- log.debug(f"Original length : {len(content)}")
284
- log.info(f"Minified length : {len(source)}")
285
- log.info(f"Reduced by : {len(content)-len(source)} ")
286
- return source
298
+ return content
287
299
 
288
300
 
289
301
  def minify(
@@ -347,11 +359,10 @@ def cross_compile(
347
359
  else:
348
360
  # target must be a Path object
349
361
  _target = get_temp_file(suffix=".mpy")
350
-
351
362
  result = pipx_mpy_cross(version, source_file, _target)
352
363
  if result.stderr and "No matching distribution found for mpy-cross==" in result.stderr:
353
364
  log.warning(f"mpy-cross=={version} not found, using latest")
354
- result = pipx_mpy_cross("latest", source_file, _target)
365
+ result = pipx_mpy_cross(V_PREVIEW, source_file, _target)
355
366
 
356
367
  if result.returncode == 0:
357
368
  log.debug(f"mpy-cross compiled to : {_target.name}")
@@ -367,9 +378,11 @@ def cross_compile(
367
378
  return result.returncode
368
379
 
369
380
 
370
- def pipx_mpy_cross(version, source_file, _target):
381
+ def pipx_mpy_cross(version: str, source_file, _target):
371
382
  """Run mpy-cross using pipx"""
372
- if version == "latest":
383
+
384
+ log.info(f"Compiling with mpy-cross version: {version}")
385
+ if version in SET_PREVIEW:
373
386
  version = ""
374
387
  if version:
375
388
  version = "==" + version
@@ -378,7 +391,7 @@ def pipx_mpy_cross(version, source_file, _target):
378
391
  # Add params
379
392
  cmd += ["-O2", str(source_file), "-o", str(_target), "-s", "createstubs.py"]
380
393
  log.trace(" ".join(cmd))
381
- result = subprocess.run(cmd, capture_output=True, text=True)
394
+ result = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8") # Specify the encoding
382
395
  return result
383
396
 
384
397
 
@@ -10,7 +10,6 @@ what versions are available. This module provides functions to :
10
10
  - get a list of the firmware/board stubs (firmware candidates)
11
11
  """
12
12
 
13
-
14
13
  import re
15
14
  from pathlib import Path
16
15
  from typing import Any, Dict, Generator, List, Optional, Union
@@ -18,15 +17,11 @@ from typing import Any, Dict, Generator, List, Optional, Union
18
17
  from packaging.version import parse
19
18
 
20
19
  import stubber.basicgit as git
21
- from stubber.publish.enums import COMBO_STUBS, DOC_STUBS, FIRMWARE_STUBS
20
+ from stubber import utils
22
21
  from stubber.publish.defaults import GENERIC, GENERIC_L, GENERIC_U
22
+ from stubber.publish.enums import COMBO_STUBS, DOC_STUBS, FIRMWARE_STUBS
23
23
  from stubber.utils.config import CONFIG
24
- from stubber.utils.versions import clean_version, micropython_versions
25
-
26
- OLDEST_VERSION = "1.16"
27
- "This is the oldest MicroPython version to build the stubs on"
28
-
29
- V_LATEST = "latest"
24
+ from stubber.utils.versions import OLDEST_VERSION, SET_PREVIEW, V_PREVIEW, clean_version, micropython_versions
30
25
 
31
26
 
32
27
  def subfolder_names(path: Path):
@@ -50,13 +45,13 @@ def version_candidates(
50
45
  for name in subfolder_names(path):
51
46
  if match := re.match(folder_re, name):
52
47
  folder_ver = clean_version(match[1])
53
- if folder_ver == V_LATEST or parse(folder_ver) >= parse(oldest):
48
+ if folder_ver == V_PREVIEW or parse(folder_ver) >= parse(oldest):
54
49
  yield folder_ver
55
50
 
56
51
 
57
52
  def list_frozen_ports(
58
53
  family: str = "micropython",
59
- version: str = V_LATEST,
54
+ version: str = V_PREVIEW,
60
55
  path: Path = CONFIG.stub_path,
61
56
  ):
62
57
  "get list of ports with frozen stubs for a given family and version"
@@ -94,7 +89,7 @@ def list_micropython_port_boards(
94
89
 
95
90
  def frozen_candidates(
96
91
  family: str = "micropython",
97
- versions: Union[str, List[str]] = V_LATEST,
92
+ versions: Union[str, List[str]] = V_PREVIEW,
98
93
  ports: Union[str, List[str]] = "all",
99
94
  boards: Union[str, List[str]] = "all",
100
95
  *,
@@ -111,7 +106,7 @@ def frozen_candidates(
111
106
  auto_port = is_auto(ports)
112
107
  auto_board = is_auto(boards)
113
108
  if is_auto(versions):
114
- versions = list(version_candidates(suffix="frozen", prefix=family, path=path)) + [V_LATEST]
109
+ versions = list(version_candidates(suffix="frozen", prefix=family, path=path)) + [V_PREVIEW]
115
110
  else:
116
111
  versions = [versions] if isinstance(versions, str) else versions
117
112
 
@@ -129,9 +124,7 @@ def frozen_candidates(
129
124
  # lookup the (frozen) micropython ports
130
125
  ports = list_frozen_ports(family, version, path=path)
131
126
  else:
132
- raise NotImplementedError(
133
- f"auto ports not implemented for family {family}"
134
- ) # pragma: no cover
127
+ raise NotImplementedError(f"auto ports not implemented for family {family}") # pragma: no cover
135
128
  # elif family == "pycom":
136
129
  # ports = ["esp32"]
137
130
  # elif family == "lobo":
@@ -164,9 +157,7 @@ def frozen_candidates(
164
157
 
165
158
  else:
166
159
  # raise NotImplementedError(f"auto boards not implemented for family {family}") # pragma: no cover
167
- raise NotImplementedError(
168
- f"auto boards not implemented for family {family}"
169
- ) # pragma: no cover
160
+ raise NotImplementedError(f"auto boards not implemented for family {family}") # pragma: no cover
170
161
  # elif family == "pycom":
171
162
  # boards = ["wipy", "lopy", "gpy", "fipy"]
172
163
  # ---------------------------------------------------------------------------
@@ -199,7 +190,7 @@ def is_auto(thing: Union[None, str, List[str]]):
199
190
 
200
191
  def docstub_candidates(
201
192
  family: str = "micropython",
202
- versions: Union[str, List[str]] = V_LATEST,
193
+ versions: Union[str, List[str]] = V_PREVIEW,
203
194
  path: Path = CONFIG.stub_path,
204
195
  ):
205
196
  """
@@ -220,7 +211,7 @@ def docstub_candidates(
220
211
 
221
212
  def board_candidates(
222
213
  family: str = "micropython",
223
- versions: Union[str, List[str]] = V_LATEST,
214
+ versions: Union[str, List[str]] = V_PREVIEW,
224
215
  *,
225
216
  mpy_path: Path = CONFIG.mpy_path,
226
217
  pt: str = FIRMWARE_STUBS,
@@ -237,8 +228,10 @@ def board_candidates(
237
228
 
238
229
  for version in versions:
239
230
  # check out the micropython repo for this version
240
- if version in ["latest", "master"]:
231
+ if version in SET_PREVIEW:
241
232
  r = git.switch_branch(repo=mpy_path, branch="master")
233
+ # get the current checked out version
234
+ version = utils.checkedout_version(mpy_path)
242
235
  else:
243
236
  r = git.checkout_tag(repo=mpy_path, tag=version)
244
237
  if not r:
@@ -283,7 +276,6 @@ def filter_list(
283
276
  worklist = [
284
277
  i
285
278
  for i in worklist
286
- if i["board"].lower() in boards_
287
- or i["board"].lower().replace("generic_", "") in boards_
279
+ if i["board"].lower() in boards_ or i["board"].lower().replace("generic_", "") in boards_
288
280
  ]
289
281
  return worklist
@@ -2,7 +2,7 @@
2
2
  from typing import Dict, List
3
3
 
4
4
  from stubber.utils.config import CONFIG
5
- from stubber.utils.versions import clean_version
5
+ from stubber.utils.versions import V_PREVIEW, clean_version
6
6
 
7
7
  # The default board for the ports modules documented with base name only
8
8
  # as the MicroPython BOARD naming convention has changed over time there are different options to try
@@ -24,7 +24,7 @@ GENERIC = {GENERIC_L, GENERIC_U}
24
24
  "GENERIC eithercase"
25
25
 
26
26
 
27
- def default_board(port: str, version="latest") -> str: # sourcery skip: assign-if-exp
27
+ def default_board(port: str, version=V_PREVIEW) -> str: # sourcery skip: assign-if-exp
28
28
  """Return the default board for the given version and port"""
29
29
  ver_flat = clean_version(version, flat=True)
30
30
  if port in DEFAULT_BOARDS:
@@ -49,9 +49,7 @@ def merge_all_docstubs(
49
49
  for candidate in candidates:
50
50
  # use the default board for the port
51
51
  if candidate["board"] in GENERIC:
52
- candidate["board"] = default_board(
53
- port=candidate["port"], version=candidate["version"]
54
- )
52
+ candidate["board"] = default_board(port=candidate["port"], version=candidate["version"])
55
53
  # check if we have board stubs of this version and port
56
54
  doc_path = CONFIG.stub_path / f"{get_base(candidate)}-docstubs"
57
55
  # src and dest paths
@@ -120,13 +118,13 @@ def copy_and_merge_docstubs(fw_path: Path, dest_path: Path, docstub_path: Path):
120
118
  "pycopy_imphook", # is not intended to be used directly, and has an unresolved subclass
121
119
  ]:
122
120
  for suffix in [".py", ".pyi"]:
123
- if (dest_path / name).with_suffix(suffix).exists():
124
- (dest_path / name).with_suffix(suffix).unlink()
121
+ if (dest_path / name).with_suffix(suffix).exists(): # type: ignore
122
+ (dest_path / name).with_suffix(suffix).unlink() # type: ignore
125
123
 
126
124
  # 2 - Enrich the firmware stubs with the document stubs
127
125
  result = enrich_folder(dest_path, docstub_path=docstub_path, write_back=True)
128
126
 
129
127
  # copy the docstubs manifest.json file to the package folder
130
- # if (docstub_path / "modules.json").exists():
131
- shutil.copy(docstub_path / "modules.json", dest_path / "doc_stubs.json")
128
+ if (docstub_path / "modules.json").exists():
129
+ shutil.copy(docstub_path / "modules.json", dest_path / "doc_stubs.json")
132
130
  return result
@@ -27,7 +27,7 @@ def add_machine_pin_call(merged_path: Path, version: str):
27
27
  log.error(f"no docstubs found for {version}")
28
28
  return False
29
29
  log.trace(f"Parsing {mod_path} for __call__ method")
30
- source = mod_path.read_text()
30
+ source = mod_path.read_text(encoding="utf-8")
31
31
  module = cst.parse_module(source)
32
32
 
33
33
  call_finder = CallFinder()
@@ -40,7 +40,7 @@ def add_machine_pin_call(merged_path: Path, version: str):
40
40
  # then use the CallAdder to add the __call__ method to all machine and pyb stubs
41
41
  mod_paths = [f for f in merged_path.rglob("*.*") if f.stem in {"machine", "umachine", "pyb"}]
42
42
  for mod_path in mod_paths:
43
- source = mod_path.read_text()
43
+ source = mod_path.read_text(encoding="utf-8")
44
44
  machine_module = cst.parse_module(source)
45
45
  new_module = machine_module.visit(CallAdder(call_finder.call_meth))
46
46
  mod_path.write_text(new_module.code)
@@ -11,7 +11,7 @@ from loguru import logger as log
11
11
  from stubber.publish.defaults import default_board
12
12
  from stubber.publish.package import GENERIC
13
13
  from stubber.utils.config import CONFIG
14
- from stubber.utils.versions import clean_version
14
+ from stubber.utils.versions import V_PREVIEW, clean_version
15
15
 
16
16
 
17
17
  ## Helper functions
@@ -40,7 +40,7 @@ def board_folder_name(fw: Dict, *, version: Optional[str] = None) -> str:
40
40
 
41
41
  def get_board_path(candidate: Dict) -> Path:
42
42
  board_path = CONFIG.stub_path / board_folder_name(candidate)
43
- if candidate["version"] == "latest" and not board_path.exists():
43
+ if V_PREVIEW in candidate["version"] and not board_path.exists():
44
44
  log.debug(f"no board stubs found for {candidate['version']}, trying stable")
45
45
  board_path = CONFIG.stub_path / board_folder_name(candidate, version=CONFIG.stable_version)
46
46
 
@@ -13,11 +13,12 @@ from stubber.publish.defaults import GENERIC_U
13
13
  from stubber.publish.enums import COMBO_STUBS
14
14
  from stubber.publish.package import get_package
15
15
  from stubber.utils.config import CONFIG
16
+ from stubber.utils.versions import V_PREVIEW
16
17
 
17
18
 
18
19
  def build_multiple(
19
20
  family: str = "micropython",
20
- versions: List[str] = ["v1.19.1"],
21
+ versions: List[str] = [V_PREVIEW],
21
22
  ports: List[str] = ["all"],
22
23
  boards: List[str] = [GENERIC_U],
23
24
  production: bool = False,
@@ -29,7 +29,7 @@ from stubber.publish.defaults import GENERIC_U, default_board
29
29
  from stubber.publish.enums import StubSource
30
30
  from stubber.publish.pypi import Version, get_pypi_versions
31
31
  from stubber.utils.config import CONFIG
32
- from stubber.utils.versions import clean_version
32
+ from stubber.utils.versions import SET_PREVIEW, V_PREVIEW, clean_version
33
33
 
34
34
  Status = NewType("Status", Dict[str, Union[str, None]])
35
35
  StubSources = List[Tuple[StubSource, Path]]
@@ -108,7 +108,7 @@ class VersionedPackage(object):
108
108
  return self._get_next_package_version(production)
109
109
 
110
110
  def is_preview(self):
111
- return self.mpy_version == "latest" or "preview" in self.mpy_version
111
+ return self.mpy_version in SET_PREVIEW or V_PREVIEW in self.mpy_version
112
112
 
113
113
  def _get_next_preview_package_version(self, production: bool = False) -> str:
114
114
  """
@@ -125,17 +125,9 @@ class VersionedPackage(object):
125
125
  parts = describe.split("-", 3)
126
126
  ver = parts[0]
127
127
  if len(parts) > 1:
128
- rc = (
129
- parts[1]
130
- if parts[1].isdigit()
131
- else parts[2]
132
- if len(parts) > 2 and parts[2].isdigit()
133
- else 1
134
- )
128
+ rc = parts[1] if parts[1].isdigit() else parts[2] if len(parts) > 2 and parts[2].isdigit() else 1
135
129
  rc = int(rc)
136
- base = (
137
- bump_version(Version(ver), minor_bump=True) if parts[1] != "preview" else Version(ver)
138
- )
130
+ base = bump_version(Version(ver), minor_bump=True) if parts[1] != V_PREVIEW else Version(ver)
139
131
  return str(bump_version(base, rc=rc))
140
132
  # raise ValueError("cannot determine next version number micropython")
141
133
 
@@ -312,9 +304,7 @@ class Builder(VersionedPackage):
312
304
  # Check if all stub source folders exist
313
305
  for stub_type, src_path in self.stub_sources:
314
306
  if not (CONFIG.stub_path / src_path).exists():
315
- raise FileNotFoundError(
316
- f"Could not find stub source folder {CONFIG.stub_path / src_path}"
317
- )
307
+ raise FileNotFoundError(f"Could not find stub source folder {CONFIG.stub_path / src_path}")
318
308
 
319
309
  # 1 - Copy the stubs to the package, directly in the package folder (no folders)
320
310
  # for stub_type, fw_path in [s for s in self.stub_sources]:
@@ -325,9 +315,7 @@ class Builder(VersionedPackage):
325
315
  self.copy_folder(stub_type, src_path)
326
316
  except OSError as e:
327
317
  if stub_type != StubSource.FROZEN:
328
- raise FileNotFoundError(
329
- f"Could not find stub source folder {src_path}"
330
- ) from e
318
+ raise FileNotFoundError(f"Could not find stub source folder {src_path}") from e
331
319
  else:
332
320
  log.debug(f"Error copying stubs from : {CONFIG.stub_path / src_path}, {e}")
333
321
  finally:
@@ -594,7 +582,7 @@ class PoetryBuilder(Builder):
594
582
  with open(_toml, "rb") as f:
595
583
  pyproject = tomllib.load(f)
596
584
  ver = pyproject["tool"]["poetry"]["version"]
597
- return str(parse(ver)) if ver != "latest" else ver
585
+ return str(parse(ver)) if ver not in SET_PREVIEW else ver
598
586
 
599
587
  @pkg_version.setter
600
588
  def pkg_version(self, version: str) -> None:
@@ -654,6 +642,7 @@ class PoetryBuilder(Builder):
654
642
  # stdout=subprocess.PIPE,
655
643
  stdout=subprocess.PIPE, # interestingly: errors on stdout , output on stderr .....
656
644
  universal_newlines=True,
645
+ encoding="utf-8",
657
646
  )
658
647
  log.trace(f"poetry {parameters} completed")
659
648
  except (NotADirectoryError, FileNotFoundError) as e: # pragma: no cover # InvalidVersion
@@ -718,8 +707,7 @@ class PoetryBuilder(Builder):
718
707
  _pyproject = self.pyproject
719
708
  assert _pyproject is not None, "No pyproject.toml file found"
720
709
  _pyproject["tool"]["poetry"]["packages"] = [
721
- {"include": p.relative_to(self.package_path).as_posix()}
722
- for p in sorted((self.package_path).rglob("*.pyi"))
710
+ {"include": p.relative_to(self.package_path).as_posix()} for p in sorted((self.package_path).rglob("*.pyi"))
723
711
  ]
724
712
  # write out the pyproject.toml file
725
713
  self.pyproject = _pyproject
@@ -862,9 +850,7 @@ class StubPackage(PoetryBuilder):
862
850
  # check if the sources exist
863
851
  ok = self.are_package_sources_available()
864
852
  if not ok:
865
- log.debug(
866
- f"{self.package_name}: skipping as one or more source stub folders are missing"
867
- )
853
+ log.debug(f"{self.package_name}: skipping as one or more source stub folders are missing")
868
854
  self.status["error"] = "Skipped, stub folder(s) missing"
869
855
  shutil.rmtree(self.package_path.as_posix())
870
856
  self._publish = False # type: ignore
@@ -886,9 +872,7 @@ class StubPackage(PoetryBuilder):
886
872
  self,
887
873
  production: bool, # PyPI or Test-PyPi - USED TO FIND THE NEXT VERSION NUMBER
888
874
  force=False, # BUILD even if no changes
889
- ) -> (
890
- bool
891
- ): # sourcery skip: default-mutable-arg, extract-duplicate-method, require-parameter-annotation
875
+ ) -> bool: # sourcery skip: default-mutable-arg, extract-duplicate-method, require-parameter-annotation
892
876
  """
893
877
  Build a package
894
878
  look up the previous package version in the dabase
@@ -908,14 +892,14 @@ class StubPackage(PoetryBuilder):
908
892
  if not self.status["error"]:
909
893
  self.status["error"] = "Could not build/update package"
910
894
  return False
911
- # If there are changes to the package, then publish it
912
- if self.is_changed():
913
- log.info(f"Found changes to package sources: {self.package_name} {self.pkg_version} ")
914
- log.trace(f"Old hash {self.hash} != New hash {self.calculate_hash()}")
915
- elif force:
916
- log.info(f"Force build: {self.package_name} {self.pkg_version} ")
917
895
 
896
+ # If there are changes to the package, then publish it
918
897
  if self.is_changed() or force:
898
+ if force:
899
+ log.info(f"Force build: {self.package_name} {self.pkg_version} ")
900
+ else:
901
+ log.info(f"Found changes to package sources: {self.package_name} {self.pkg_version} ")
902
+ log.trace(f"Old hash {self.hash} != New hash {self.calculate_hash()}")
919
903
  # Build the distribution files
920
904
  old_ver = self.pkg_version
921
905
  self.pkg_version = self.next_package_version(production)
@@ -975,10 +959,8 @@ class StubPackage(PoetryBuilder):
975
959
  self.next_package_version(production=production)
976
960
  # Publish the package to PyPi, Test-PyPi or Github
977
961
  if self.is_changed():
978
- if self.mpy_version == "latest" and production and not force:
979
- log.warning(
980
- "version: `latest` package will only be available on Github, and not published to PyPi."
981
- )
962
+ if self.mpy_version in SET_PREVIEW and production and not force:
963
+ log.warning("version: `latest` package will only be available on Github, and not published to PyPi.")
982
964
  self.status["result"] = "Published to GitHub"
983
965
  else:
984
966
  return self.publish_distribution(dry_run, production, db)
@@ -1007,9 +989,7 @@ class StubPackage(PoetryBuilder):
1007
989
  if not dry_run:
1008
990
  pub_ok = self.poetry_publish(production=production)
1009
991
  else:
1010
- log.warning(
1011
- f"{self.package_name}: Dry run, not publishing to {'' if production else 'Test-'}PyPi"
1012
- )
992
+ log.warning(f"{self.package_name}: Dry run, not publishing to {'' if production else 'Test-'}PyPi")
1013
993
  pub_ok = True
1014
994
  if not pub_ok:
1015
995
  log.warning(f"{self.package_name}: Publish failed for {self.pkg_version}")
stubber/rst/lookup.py CHANGED
@@ -20,6 +20,7 @@ __all__ = [
20
20
 
21
21
  # all possible Types needed for the stubs - exxess types should be removed later , and otherwise won't do much harm
22
22
  TYPING_IMPORT: List[str] = [
23
+ "from __future__ import annotations",
23
24
  "from typing import IO, Any, Callable, Coroutine, Dict, Generator, Iterator, List, NoReturn, Optional, Tuple, Union, NamedTuple, TypeVar",
24
25
  "from _typeshed import Incomplete",
25
26
  ]
@@ -483,17 +484,18 @@ PARAM_FIXES = [
483
484
  # List of classes and their parent classes that should be added to the class definition
484
485
  CHILD_PARENT_CLASS = {
485
486
  # machine
486
- # "SoftSPI": "SPI", # BUG: SoftSPI is defined before SPI, so baseclass is not yet available
487
+ # SoftSPI is defined before SPI, so baseclass is not yet available - but in a .pyi that is OK
488
+ "SoftSPI": "SPI",
487
489
  "SoftI2C": "I2C",
488
490
  "Switch": "Pin",
489
491
  "Signal": "Pin",
490
492
  # uio # unclear regarding deprecation in python 3.12
491
493
  # "IOBase": "IO", # DOCME not in documentation
492
- "TextIOWrapper": "IO",
493
- "FileIO": "IO",
494
- "StringIO": "IO",
495
- "BytesIO": "IO",
496
- "BufferedWriter": "IOBase", # DOCME: not in documentation
494
+ "TextIOWrapper": "IO", # "TextIOBase, TextIO", # based on Stdlib
495
+ "FileIO": "IO", # "RawIOBase, BinaryIO", # based on Stdlib
496
+ "StringIO": "IO", # "BufferedIOBase, BinaryIO", # based on Stdlib
497
+ "BytesIO": "IO", # "BufferedIOBase, BinaryIO", # based on Stdlib
498
+ "BufferedWriter": "IOBase", # DOCME: not in documentation # "BufferedWriter": "BufferedIOBase", # based on Stdlib
497
499
  # uzlib
498
500
  # "DecompIO": "IO", # https://docs.python.org/3/library/typing.html#other-concrete-types
499
501
  # -------------------------------------------------------------------------------------
@@ -512,7 +514,7 @@ CHILD_PARENT_CLASS = {
512
514
  "namedtuple": "tuple",
513
515
  "deque": "stdlib_deque",
514
516
  # ESPNow
515
- "ESPNow": "ESPNowBase,Iterator", # causes issue with mypy
517
+ "ESPNow": "ESPNowBase,Iterator", # causes issue with mypy
516
518
  "AIOESPNow": "ESPNow",
517
519
  # array
518
520
  "array": "List",