omdev 0.0.0.dev416__py3-none-any.whl → 0.0.0.dev500__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.

Potentially problematic release.


This version of omdev might be problematic. Click here for more details.

Files changed (211) hide show
  1. omdev/{.manifests.json → .omlish-manifests.json} +23 -47
  2. omdev/README.md +51 -0
  3. omdev/__about__.py +12 -8
  4. omdev/amalg/cli/main.py +1 -2
  5. omdev/amalg/gen/gen.py +49 -6
  6. omdev/amalg/gen/imports.py +1 -1
  7. omdev/amalg/gen/manifests.py +1 -1
  8. omdev/amalg/gen/resources.py +1 -1
  9. omdev/amalg/gen/srcfiles.py +26 -3
  10. omdev/amalg/gen/strip.py +1 -1
  11. omdev/amalg/gen/types.py +1 -1
  12. omdev/amalg/gen/typing.py +1 -1
  13. omdev/amalg/info.py +32 -0
  14. omdev/cache/compute/storage.py +3 -1
  15. omdev/cache/data/actions.py +1 -1
  16. omdev/cache/data/cache.py +2 -2
  17. omdev/cache/data/specs.py +1 -1
  18. omdev/cexts/_boilerplate.cc +2 -3
  19. omdev/cexts/_distutils/build_ext.py +5 -2
  20. omdev/cexts/_distutils/compilers/ccompiler.py +5 -2
  21. omdev/cexts/_distutils/compilers/options.py +3 -0
  22. omdev/cexts/_distutils/compilers/unixccompiler.py +6 -2
  23. omdev/cexts/_distutils/dir_util.py +6 -2
  24. omdev/cexts/_distutils/errors.py +3 -0
  25. omdev/cexts/_distutils/extension.py +3 -0
  26. omdev/cexts/_distutils/file_util.py +6 -2
  27. omdev/cexts/_distutils/modified.py +3 -0
  28. omdev/cexts/_distutils/spawn.py +6 -2
  29. omdev/cexts/_distutils/sysconfig.py +3 -0
  30. omdev/cexts/_distutils/util.py +6 -2
  31. omdev/cexts/_distutils/version.py +3 -0
  32. omdev/cexts/cmake.py +5 -3
  33. omdev/cexts/scan.py +1 -2
  34. omdev/ci/cache.py +7 -3
  35. omdev/ci/cli.py +6 -4
  36. omdev/ci/docker/buildcaching.py +3 -1
  37. omdev/ci/docker/cache.py +2 -1
  38. omdev/ci/docker/cacheserved/cache.py +4 -1
  39. omdev/ci/docker/cacheserved/manifests.py +2 -2
  40. omdev/ci/docker/dataserver.py +2 -2
  41. omdev/ci/docker/imagepulling.py +2 -1
  42. omdev/ci/docker/packing.py +1 -1
  43. omdev/ci/docker/repositories.py +2 -1
  44. omdev/ci/github/api/clients.py +8 -4
  45. omdev/ci/github/api/v1/client.py +4 -1
  46. omdev/ci/github/api/v2/api.py +2 -0
  47. omdev/ci/github/api/v2/azure.py +4 -1
  48. omdev/ci/github/api/v2/client.py +4 -1
  49. omdev/cli/clicli.py +37 -7
  50. omdev/clipboard/clipboard.py +1 -1
  51. omdev/cmake.py +2 -1
  52. omdev/cmdlog/cli.py +1 -2
  53. omdev/dataclasses/_dumping.py +1960 -0
  54. omdev/dataclasses/_template.py +22 -0
  55. omdev/dataclasses/cli.py +7 -2
  56. omdev/dataclasses/codegen.py +342 -62
  57. omdev/dataclasses/dumping.py +200 -0
  58. omdev/dataserver/handlers.py +3 -2
  59. omdev/dataserver/targets.py +2 -2
  60. omdev/imgur.py +2 -2
  61. omdev/interp/cli.py +1 -1
  62. omdev/interp/inspect.py +2 -1
  63. omdev/interp/providers/base.py +3 -2
  64. omdev/interp/providers/standalone.py +4 -1
  65. omdev/interp/providers/system.py +2 -2
  66. omdev/interp/pyenv/install.py +2 -1
  67. omdev/interp/pyenv/provider.py +2 -2
  68. omdev/interp/types.py +3 -2
  69. omdev/interp/uv/provider.py +40 -2
  70. omdev/interp/uv/uv.py +2 -2
  71. omdev/interp/venvs.py +3 -2
  72. omdev/irc/messages/base.py +50 -0
  73. omdev/irc/messages/formats.py +92 -0
  74. omdev/irc/messages/messages.py +775 -0
  75. omdev/irc/messages/parsing.py +99 -0
  76. omdev/irc/numerics/formats.py +97 -0
  77. omdev/irc/numerics/numerics.py +865 -0
  78. omdev/irc/numerics/types.py +59 -0
  79. omdev/irc/protocol/LICENSE +11 -0
  80. omdev/irc/protocol/__init__.py +61 -0
  81. omdev/irc/protocol/consts.py +6 -0
  82. omdev/irc/protocol/errors.py +30 -0
  83. omdev/irc/protocol/message.py +21 -0
  84. omdev/irc/protocol/nuh.py +55 -0
  85. omdev/irc/protocol/parsing.py +158 -0
  86. omdev/irc/protocol/rendering.py +153 -0
  87. omdev/irc/protocol/tags.py +102 -0
  88. omdev/irc/protocol/utils.py +30 -0
  89. omdev/manifests/_dumping.py +529 -136
  90. omdev/manifests/building.py +6 -3
  91. omdev/manifests/main.py +1 -1
  92. omdev/markdown/__init__.py +0 -0
  93. omdev/markdown/incparse.py +116 -0
  94. omdev/markdown/tokens.py +51 -0
  95. omdev/oci/data.py +2 -2
  96. omdev/oci/datarefs.py +2 -2
  97. omdev/oci/media.py +2 -2
  98. omdev/oci/repositories.py +3 -2
  99. omdev/packaging/marshal.py +9 -9
  100. omdev/packaging/requires.py +6 -6
  101. omdev/packaging/revisions.py +5 -2
  102. omdev/packaging/specifiers.py +41 -42
  103. omdev/packaging/versions.py +10 -10
  104. omdev/packaging/wheelfile.py +4 -2
  105. omdev/precheck/blanklines.py +66 -0
  106. omdev/precheck/caches.py +1 -1
  107. omdev/precheck/imports.py +14 -1
  108. omdev/precheck/lite.py +2 -2
  109. omdev/precheck/main.py +5 -5
  110. omdev/precheck/unicode.py +39 -15
  111. omdev/py/asts/__init__.py +0 -0
  112. omdev/py/asts/parents.py +28 -0
  113. omdev/py/asts/toplevel.py +123 -0
  114. omdev/py/asts/visitors.py +18 -0
  115. omdev/py/attrdocs.py +6 -7
  116. omdev/py/bracepy.py +12 -4
  117. omdev/py/docstrings/numpydoc.py +4 -4
  118. omdev/py/reprs.py +32 -0
  119. omdev/py/scripts/execstat.py +31 -26
  120. omdev/py/srcheaders.py +1 -1
  121. omdev/py/tokens/__init__.py +0 -0
  122. omdev/{tokens → py/tokens}/utils.py +2 -1
  123. omdev/py/tools/importscan.py +2 -2
  124. omdev/py/tools/mkrelimp.py +3 -4
  125. omdev/py/tools/pipdepup.py +686 -0
  126. omdev/pyproject/cli.py +1 -1
  127. omdev/pyproject/pkg.py +197 -48
  128. omdev/pyproject/reqs.py +36 -10
  129. omdev/pyproject/tools/__init__.py +0 -0
  130. omdev/pyproject/tools/aboutdeps.py +60 -0
  131. omdev/pyproject/venvs.py +12 -2
  132. omdev/rs/__init__.py +0 -0
  133. omdev/scripts/ci.py +9551 -6982
  134. omdev/scripts/interp.py +1323 -892
  135. omdev/scripts/lib/__init__.py +0 -0
  136. omdev/scripts/lib/inject.py +2086 -0
  137. omdev/scripts/lib/logs.py +2175 -0
  138. omdev/scripts/lib/marshal.py +1731 -0
  139. omdev/scripts/pyproject.py +4979 -1874
  140. omdev/tools/docker.py +19 -7
  141. omdev/tools/git/cli.py +56 -16
  142. omdev/tools/git/messages.py +2 -2
  143. omdev/tools/json/cli.py +6 -6
  144. omdev/tools/json/formats.py +2 -0
  145. omdev/tools/json/parsing.py +5 -5
  146. omdev/tools/json/processing.py +6 -3
  147. omdev/tools/json/rendering.py +2 -2
  148. omdev/tools/jsonview/cli.py +49 -65
  149. omdev/tools/jsonview/resources/jsonview.html.j2 +43 -0
  150. omdev/tools/pawk/README.md +195 -0
  151. omdev/tools/pawk/pawk.py +2 -2
  152. omdev/tools/pip.py +8 -0
  153. omdev/tui/__init__.py +0 -0
  154. omdev/tui/apps/__init__.py +0 -0
  155. omdev/tui/apps/edit/__init__.py +0 -0
  156. omdev/tui/apps/edit/main.py +167 -0
  157. omdev/tui/apps/irc/__init__.py +0 -0
  158. omdev/tui/apps/irc/__main__.py +4 -0
  159. omdev/tui/apps/irc/app.py +286 -0
  160. omdev/tui/apps/irc/client.py +187 -0
  161. omdev/tui/apps/irc/commands.py +175 -0
  162. omdev/tui/apps/irc/main.py +26 -0
  163. omdev/tui/apps/markdown/__init__.py +0 -0
  164. omdev/tui/apps/markdown/__main__.py +11 -0
  165. omdev/{ptk → tui/apps}/markdown/cli.py +5 -7
  166. omdev/tui/rich/__init__.py +46 -0
  167. omdev/tui/rich/console2.py +20 -0
  168. omdev/tui/rich/markdown2.py +186 -0
  169. omdev/tui/textual/__init__.py +265 -0
  170. omdev/tui/textual/app2.py +16 -0
  171. omdev/tui/textual/autocomplete/LICENSE +21 -0
  172. omdev/tui/textual/autocomplete/__init__.py +33 -0
  173. omdev/tui/textual/autocomplete/matching.py +226 -0
  174. omdev/tui/textual/autocomplete/paths.py +202 -0
  175. omdev/tui/textual/autocomplete/widget.py +612 -0
  176. omdev/tui/textual/debug/__init__.py +10 -0
  177. omdev/tui/textual/debug/dominfo.py +151 -0
  178. omdev/tui/textual/debug/screen.py +24 -0
  179. omdev/tui/textual/devtools.py +187 -0
  180. omdev/tui/textual/drivers2.py +55 -0
  181. omdev/tui/textual/logging2.py +20 -0
  182. omdev/tui/textual/types.py +45 -0
  183. {omdev-0.0.0.dev416.dist-info → omdev-0.0.0.dev500.dist-info}/METADATA +18 -12
  184. omdev-0.0.0.dev500.dist-info/RECORD +386 -0
  185. omdev/ptk/__init__.py +0 -103
  186. omdev/ptk/apps/ncdu.py +0 -167
  187. omdev/ptk/confirm.py +0 -60
  188. omdev/ptk/markdown/LICENSE +0 -22
  189. omdev/ptk/markdown/__init__.py +0 -10
  190. omdev/ptk/markdown/__main__.py +0 -11
  191. omdev/ptk/markdown/border.py +0 -94
  192. omdev/ptk/markdown/markdown.py +0 -390
  193. omdev/ptk/markdown/parser.py +0 -42
  194. omdev/ptk/markdown/styles.py +0 -29
  195. omdev/ptk/markdown/tags.py +0 -299
  196. omdev/ptk/markdown/utils.py +0 -366
  197. omdev/pyproject/cexts.py +0 -110
  198. omdev/tools/antlr/__main__.py +0 -11
  199. omdev/tools/antlr/cli.py +0 -62
  200. omdev/tools/antlr/consts.py +0 -7
  201. omdev/tools/antlr/gen.py +0 -188
  202. omdev-0.0.0.dev416.dist-info/RECORD +0 -332
  203. /omdev/{ptk/apps → irc}/__init__.py +0 -0
  204. /omdev/{tokens → irc/messages}/__init__.py +0 -0
  205. /omdev/{tools/antlr → irc/numerics}/__init__.py +0 -0
  206. /omdev/{tokens → py/tokens}/all.py +0 -0
  207. /omdev/{tokens → py/tokens}/tokenizert.py +0 -0
  208. {omdev-0.0.0.dev416.dist-info → omdev-0.0.0.dev500.dist-info}/WHEEL +0 -0
  209. {omdev-0.0.0.dev416.dist-info → omdev-0.0.0.dev500.dist-info}/entry_points.txt +0 -0
  210. {omdev-0.0.0.dev416.dist-info → omdev-0.0.0.dev500.dist-info}/licenses/LICENSE +0 -0
  211. {omdev-0.0.0.dev416.dist-info → omdev-0.0.0.dev500.dist-info}/top_level.txt +0 -0
omdev/pyproject/pkg.py CHANGED
@@ -28,16 +28,19 @@ vcs+protocol://repo_url/#egg=pkg&subdirectory=pkg_dir
28
28
  import abc
29
29
  import dataclasses as dc
30
30
  import importlib
31
+ import inspect
31
32
  import os.path
32
33
  import shutil
33
34
  import sys
34
35
  import tempfile
36
+ import textwrap
35
37
  import types
36
38
  import typing as ta
37
39
 
38
40
  from omlish.formats.toml.writer import TomlWriter
41
+ from omlish.lite.abstract import Abstract
39
42
  from omlish.lite.cached import cached_nullary
40
- from omlish.lite.logs import log
43
+ from omlish.logs.modules import get_module_logger
41
44
  from omlish.subprocesses.sync import subprocesses
42
45
 
43
46
  from ..cexts.magic import CextMagic
@@ -45,10 +48,13 @@ from ..magic.find import find_magic_files
45
48
  from ..packaging.revisions import GitRevisionAdder
46
49
 
47
50
 
51
+ log = get_module_logger(globals()) # noqa
52
+
53
+
48
54
  ##
49
55
 
50
56
 
51
- class BasePyprojectPackageGenerator(abc.ABC):
57
+ class BasePyprojectPackageGenerator(Abstract):
52
58
  def __init__(
53
59
  self,
54
60
  dir_name: str,
@@ -87,7 +93,7 @@ class BasePyprojectPackageGenerator(abc.ABC):
87
93
 
88
94
  def _write_git_ignore(self) -> None:
89
95
  with open(os.path.join(self._pkg_dir(), '.gitignore'), 'w') as f:
90
- f.write('\n'.join(self._GIT_IGNORE))
96
+ f.write('\n'.join([*self._GIT_IGNORE, '']))
91
97
 
92
98
  #
93
99
 
@@ -256,6 +262,7 @@ class BasePyprojectPackageGenerator(abc.ABC):
256
262
  )
257
263
 
258
264
  if output_dir is not None:
265
+ log.info(lambda: f'Copying {dist_dir} to {output_dir}')
259
266
  for fn in os.listdir(dist_dir):
260
267
  shutil.copyfile(os.path.join(dist_dir, fn), os.path.join(output_dir, fn))
261
268
 
@@ -311,7 +318,11 @@ class PyprojectPackageGenerator(BasePyprojectPackageGenerator):
311
318
  st = dict(specs.setuptools)
312
319
  pyp_dct['tool.setuptools'] = st
313
320
 
314
- st.pop('cexts', None)
321
+ for k in [
322
+ 'cext',
323
+ 'rs',
324
+ ]:
325
+ st.pop(k, None)
315
326
 
316
327
  #
317
328
 
@@ -333,7 +344,7 @@ class PyprojectPackageGenerator(BasePyprojectPackageGenerator):
333
344
  # '*.c',
334
345
  # '*.cc',
335
346
  # '*.h',
336
- # '.manifests.json',
347
+ # '.omlish-manifests.json',
337
348
  # 'LICENSE',
338
349
  # ],
339
350
  # }
@@ -384,13 +395,20 @@ class PyprojectPackageGenerator(BasePyprojectPackageGenerator):
384
395
  def children(self) -> ta.Sequence[BasePyprojectPackageGenerator]:
385
396
  out: ta.List[BasePyprojectPackageGenerator] = []
386
397
 
387
- if self.build_specs().setuptools.get('cexts'):
398
+ if self.build_specs().setuptools.get('cext'):
388
399
  out.append(_PyprojectCextPackageGenerator(
389
400
  self._dir_name,
390
401
  self._pkgs_root,
391
402
  pkg_suffix='-cext',
392
403
  ))
393
404
 
405
+ if self.build_specs().setuptools.get('rs'):
406
+ out.append(_PyprojectRsPackageGenerator(
407
+ self._dir_name,
408
+ self._pkgs_root,
409
+ pkg_suffix='-rs',
410
+ ))
411
+
394
412
  if self.build_specs().pyproject.get('cli_scripts'):
395
413
  out.append(_PyprojectCliPackageGenerator(
396
414
  self._dir_name,
@@ -401,10 +419,67 @@ class PyprojectPackageGenerator(BasePyprojectPackageGenerator):
401
419
  return out
402
420
 
403
421
 
404
- #
422
+ ##
423
+
424
+
425
+ class _PyprojectExtensionPackageGenerator(BasePyprojectPackageGenerator, Abstract):
426
+ #
427
+
428
+ def _build_project_dict(self) -> ta.Dict[str, ta.Any]:
429
+ prj = dict(self.build_specs().pyproject)
430
+
431
+ prj['dependencies'] = [f'{prj["name"]} == {prj["version"]}']
432
+ prj['name'] += self._pkg_suffix
433
+
434
+ for k in [
435
+ 'optional_dependencies',
436
+ 'entry_points',
437
+ 'scripts',
438
+ 'cli_scripts',
439
+ ]:
440
+ prj.pop(k, None)
441
+
442
+ return prj
443
+
444
+ def _build_setuptools_dict(self) -> ta.Dict[str, ta.Any]:
445
+ st = dict(self.build_specs().setuptools)
446
+
447
+ for k in [
448
+ 'cext',
449
+ 'rs',
450
+
451
+ 'find_packages',
452
+ 'package_data',
453
+ 'manifest_in',
454
+ ]:
455
+ st.pop(k, None)
456
+
457
+ return st
405
458
 
459
+ #
460
+
461
+ @dc.dataclass(frozen=True)
462
+ class FileContents:
463
+ pyproject_dct: ta.Mapping[str, ta.Any]
464
+ setup_py: str
465
+
466
+ @abc.abstractmethod
467
+ def file_contents(self) -> FileContents:
468
+ raise NotImplementedError
406
469
 
407
- class _PyprojectCextPackageGenerator(BasePyprojectPackageGenerator):
470
+ #
471
+
472
+ def _write_file_contents(self) -> None:
473
+ fc = self.file_contents()
474
+
475
+ with open(os.path.join(self._pkg_dir(), 'pyproject.toml'), 'w') as f:
476
+ TomlWriter(f).write_root(fc.pyproject_dct)
477
+
478
+ with open(os.path.join(self._pkg_dir(), 'setup.py'), 'w') as f:
479
+ f.write(fc.setup_py)
480
+
481
+
482
+ class _PyprojectCextPackageGenerator(_PyprojectExtensionPackageGenerator):
408
483
  @cached_nullary
409
484
  def find_cext_srcs(self) -> ta.Sequence[str]:
410
485
  return sorted(find_magic_files(
@@ -415,14 +490,10 @@ class _PyprojectCextPackageGenerator(BasePyprojectPackageGenerator):
415
490
 
416
491
  #
417
492
 
418
- @dc.dataclass(frozen=True)
419
- class FileContents:
420
- pyproject_dct: ta.Mapping[str, ta.Any]
421
- setup_py: str
422
-
423
493
  @cached_nullary
424
- def file_contents(self) -> FileContents:
425
- specs = self.build_specs()
494
+ def file_contents(self) -> _PyprojectExtensionPackageGenerator.FileContents:
495
+ prj = self._build_project_dict()
496
+ st = self._build_setuptools_dict()
426
497
 
427
498
  #
428
499
 
@@ -433,33 +504,9 @@ class _PyprojectCextPackageGenerator(BasePyprojectPackageGenerator):
433
504
  'build-backend': 'setuptools.build_meta',
434
505
  }
435
506
 
436
- prj = specs.pyproject
437
- prj['dependencies'] = [f'{prj["name"]} == {prj["version"]}']
438
- prj['name'] += self._pkg_suffix
439
- for k in [
440
- 'optional_dependencies',
441
- 'entry_points',
442
- 'scripts',
443
- 'cli_scripts',
444
- ]:
445
- prj.pop(k, None)
446
-
447
507
  pyp_dct['project'] = prj
448
-
449
- #
450
-
451
- st = dict(specs.setuptools)
452
508
  pyp_dct['tool.setuptools'] = st
453
509
 
454
- for k in [
455
- 'cexts',
456
-
457
- 'find_packages',
458
- 'package_data',
459
- 'manifest_in',
460
- ]:
461
- st.pop(k, None)
462
-
463
510
  pyp_dct['tool.setuptools.packages.find'] = {
464
511
  'include': [],
465
512
  }
@@ -469,12 +516,17 @@ class _PyprojectCextPackageGenerator(BasePyprojectPackageGenerator):
469
516
  ext_lines = []
470
517
 
471
518
  for ext_src in self.find_cext_srcs():
519
+ ext_lang = ext_src.rpartition('.')[2]
520
+ compile_args = {
521
+ 'c': ['-std=c11'],
522
+ 'cc': ['-std=c++20'],
523
+ }.get(ext_lang, [])
472
524
  ext_name = ext_src.rpartition('.')[0].replace(os.sep, '.')
473
525
  ext_lines.extend([
474
526
  'st.Extension(',
475
527
  f" name='{ext_name}',",
476
528
  f" sources=['{ext_src}'],",
477
- " extra_compile_args=['-std=c++20'],",
529
+ f' extra_compile_args={compile_args!r},',
478
530
  '),',
479
531
  ])
480
532
 
@@ -485,7 +537,7 @@ class _PyprojectCextPackageGenerator(BasePyprojectPackageGenerator):
485
537
  'st.setup(',
486
538
  ' ext_modules=[',
487
539
  *[' ' + l for l in ext_lines],
488
- ' ]',
540
+ ' ],',
489
541
  ')',
490
542
  '',
491
543
  ])
@@ -497,14 +549,110 @@ class _PyprojectCextPackageGenerator(BasePyprojectPackageGenerator):
497
549
  src,
498
550
  )
499
551
 
500
- def _write_file_contents(self) -> None:
501
- fc = self.file_contents()
502
552
 
503
- with open(os.path.join(self._pkg_dir(), 'pyproject.toml'), 'w') as f:
504
- TomlWriter(f).write_root(fc.pyproject_dct)
553
+ class _PyprojectRsPackageGenerator(_PyprojectExtensionPackageGenerator):
554
+ @cached_nullary
555
+ def find_rs_dirs(self) -> ta.Sequence[str]:
556
+ return sorted(
557
+ dp
558
+ for dp, dns, fns in os.walk(self._dir_name)
559
+ for fn in fns
560
+ if fn == '.omlish-rs-ext'
561
+ )
505
562
 
506
- with open(os.path.join(self._pkg_dir(), 'setup.py'), 'w') as f:
507
- f.write(fc.setup_py)
563
+ #
564
+
565
+ @staticmethod
566
+ def _sdist_patch_body() -> None:
567
+ def _patch_sdist():
568
+ def _sdist_add_defaults(old, self):
569
+ import os.path
570
+
571
+ old(self)
572
+
573
+ if self.distribution.rust_extensions and len(self.distribution.rust_extensions) > 0:
574
+ build_rust = self.get_finalized_command('build_rust') # noqa
575
+ for ext in build_rust.extensions:
576
+ ext_dir = os.path.dirname(ext.path)
577
+ for n in os.listdir(ext_dir):
578
+ if n.startswith('.') or n == 'target':
579
+ continue
580
+ p = os.path.join(ext_dir, n)
581
+ if os.path.isfile(p):
582
+ self.filelist.append(p)
583
+ elif os.path.isdir(p):
584
+ self.filelist.extend(os.path.join(dp, f) for dp, dn, fn in os.walk(p) for f in fn)
585
+
586
+ # Sadly, we can't just subclass sdist and override it via cmdclass because manifest_maker calls
587
+ # `sdist.add_defaults` as an unbound function, not a bound method:
588
+ # https://github.com/pypa/setuptools/blob/9c4d383631d3951fcae0afd73b5d08ff5a262976/setuptools/command/egg_info.py#L581
589
+ from setuptools.command.sdist import sdist # noqa
590
+ setattr(sdist, 'add_defaults', (lambda old: lambda sdist: _sdist_add_defaults(old, sdist))(sdist.add_defaults)) # noqa
591
+
592
+ _patch_sdist()
593
+
594
+ @cached_nullary
595
+ def sdist_patch_code(self) -> str:
596
+ return textwrap.dedent(''.join(inspect.getsource(self._sdist_patch_body).splitlines(keepends=True)[2:])).strip()
597
+
598
+ #
599
+
600
+ @cached_nullary
601
+ def file_contents(self) -> _PyprojectExtensionPackageGenerator.FileContents:
602
+ prj = self._build_project_dict()
603
+ st = self._build_setuptools_dict()
604
+
605
+ #
606
+
607
+ pyp_dct = {}
608
+
609
+ pyp_dct['build-system'] = {
610
+ 'requires': ['setuptools', 'setuptools-rust'],
611
+ 'build-backend': 'setuptools.build_meta',
612
+ }
613
+
614
+ pyp_dct['project'] = prj
615
+ pyp_dct['tool.setuptools'] = st
616
+
617
+ pyp_dct['tool.setuptools.packages.find'] = {
618
+ 'include': [],
619
+ }
620
+
621
+ #
622
+
623
+ ext_lines: list = []
624
+
625
+ for ext_dir in self.find_rs_dirs(): # noqa
626
+ ext_name = ext_dir.replace(os.sep, '.')
627
+ ext_lines.extend([
628
+ 'st_rs.RustExtension(',
629
+ f" '{ext_name}',",
630
+ f" path='{ext_dir}/Cargo.toml',",
631
+ '),',
632
+ ])
633
+
634
+ src = '\n'.join([
635
+ 'import setuptools as st',
636
+ 'import setuptools_rust as st_rs',
637
+ '',
638
+ '',
639
+ self.sdist_patch_code(),
640
+ '',
641
+ '',
642
+ 'st.setup(',
643
+ ' rust_extensions=[',
644
+ *[' ' + l for l in ext_lines],
645
+ ' ],',
646
+ ')',
647
+ '',
648
+ ])
649
+
650
+ #
651
+
652
+ return self.FileContents(
653
+ pyp_dct,
654
+ src,
655
+ )
508
656
 
509
657
 
510
658
  ##
@@ -549,7 +697,8 @@ class _PyprojectCliPackageGenerator(BasePyprojectPackageGenerator):
549
697
  pyp_dct['tool.setuptools'] = st
550
698
 
551
699
  for k in [
552
- 'cexts',
700
+ 'cext',
701
+ 'rs',
553
702
 
554
703
  'find_packages',
555
704
  'package_data',
omdev/pyproject/reqs.py CHANGED
@@ -4,11 +4,18 @@ TODO:
4
4
  """
5
5
  # ruff: noqa: UP007 UP045
6
6
  import os.path
7
+ import re
7
8
  import tempfile
8
9
  import typing as ta
9
10
 
10
11
  from omlish.lite.cached import cached_nullary
11
- from omlish.lite.logs import log
12
+ from omlish.logs.modules import get_module_logger
13
+
14
+ from ..packaging.requires import RequiresParserSyntaxError
15
+ from ..packaging.requires import parse_requirement
16
+
17
+
18
+ log = get_module_logger(globals()) # noqa
12
19
 
13
20
 
14
21
  ##
@@ -17,11 +24,14 @@ from omlish.lite.logs import log
17
24
  class RequirementsRewriter:
18
25
  def __init__(
19
26
  self,
27
+ *,
20
28
  venv: ta.Optional[str] = None,
29
+ only_pats: ta.Optional[ta.Sequence[re.Pattern]] = None,
21
30
  ) -> None:
22
31
  super().__init__()
23
32
 
24
33
  self._venv = venv
34
+ self._only_pats = only_pats
25
35
 
26
36
  @cached_nullary
27
37
  def _tmp_dir(self) -> str:
@@ -37,17 +47,33 @@ class RequirementsRewriter:
37
47
  out_lines = []
38
48
 
39
49
  for l in in_lines:
40
- if self.VENV_MAGIC in l:
41
- lp, _, rp = l.partition(self.VENV_MAGIC)
42
- rp = rp.partition('#')[0]
50
+ if l.split('#')[0].strip():
43
51
  omit = False
44
- for v in rp.split():
45
- if v[0] == '!':
46
- if self._venv is not None and self._venv == v[1:]:
47
- omit = True
48
- break
52
+
53
+ if self.VENV_MAGIC in l:
54
+ lp, _, rp = l.partition(self.VENV_MAGIC)
55
+ rp = rp.partition('#')[0]
56
+ vs = set(rp.split())
57
+ nvs = {v[1:] for v in vs if v.startswith('!')}
58
+ pvs = {v for v in vs if not v.startswith('!')}
59
+ if (
60
+ (nvs and self._venv in nvs) or
61
+ (pvs and self._venv not in pvs)
62
+ ):
63
+ omit = True
64
+
65
+ if (
66
+ not omit and
67
+ (ops := self._only_pats) is not None and
68
+ not l.strip().startswith('-')
69
+ ):
70
+ try:
71
+ pr = parse_requirement(l.split('#')[0].strip())
72
+ except RequiresParserSyntaxError:
73
+ pass
49
74
  else:
50
- raise NotImplementedError
75
+ if not any(op.fullmatch(pr.name) for op in ops):
76
+ omit = True
51
77
 
52
78
  if omit:
53
79
  out_lines.append('# OMITTED: ' + l)
File without changes
@@ -0,0 +1,60 @@
1
+ """
2
+ TODO:
3
+ - pyproject api!
4
+ """
5
+ import importlib.metadata
6
+ import re
7
+ import sys
8
+
9
+ from omlish.formats.toml.parser import toml_loads
10
+
11
+ from ...packaging.names import canonicalize_name
12
+ from ...packaging.requires import parse_requirement
13
+ from ...packaging.specifiers import Specifier
14
+
15
+
16
+ ##
17
+
18
+
19
+ def _main() -> None:
20
+ dist_dct = {}
21
+ for dist in importlib.metadata.distributions(paths=sys.path):
22
+ dist_cn = canonicalize_name(dist.metadata['Name'], validate=True)
23
+ if dist_cn in dist_dct:
24
+ continue
25
+ dist_dct[dist_cn] = dist
26
+
27
+ #
28
+
29
+ with open('pyproject.toml') as f:
30
+ dct = toml_loads(f.read())
31
+
32
+ pkgs = dct['tool']['omlish']['pyproject']['pkgs']
33
+
34
+ for pkg in pkgs:
35
+ pkg_about = importlib.import_module('.'.join([pkg, '__about__']))
36
+ pkg_prj = pkg_about.Project
37
+
38
+ pkg_opt_deps = {d for ds in pkg_prj.optional_dependencies.values() for d in ds}
39
+ for opt_dep in sorted(pkg_opt_deps):
40
+ opt_req = parse_requirement(opt_dep)
41
+
42
+ opt_cn = canonicalize_name(opt_req.name, validate=True)
43
+
44
+ opt_spec = Specifier(opt_req.specifier)
45
+ if re.fullmatch(r'~=\s*\d+(\.\d+)*', str(opt_spec)):
46
+ opt_spec = Specifier(str(opt_spec) + '.0')
47
+
48
+ if opt_cn in pkgs:
49
+ continue
50
+
51
+ opt_dist = dist_dct[opt_cn]
52
+ opt_ver = opt_dist.version
53
+
54
+ # print((opt_dep, opt_spec, opt_ver))
55
+ if not opt_spec.contains(opt_ver):
56
+ print(f'{pkg} :: {opt_cn} : {opt_spec} ! {opt_ver}')
57
+
58
+
59
+ if __name__ == '__main__':
60
+ _main()
omdev/pyproject/venvs.py CHANGED
@@ -1,11 +1,12 @@
1
1
  # ruff: noqa: UP006 UP007 UP045
2
2
  import glob
3
3
  import os.path
4
+ import re
4
5
  import typing as ta
5
6
 
6
7
  from omlish.lite.cached import async_cached_nullary
7
8
  from omlish.lite.cached import cached_nullary
8
- from omlish.lite.logs import log
9
+ from omlish.logs.modules import get_module_logger
9
10
 
10
11
  from ..interp.venvs import InterpVenv
11
12
  from ..interp.venvs import InterpVenvRequirementsProcessor
@@ -13,6 +14,9 @@ from .configs import VenvConfig
13
14
  from .reqs import RequirementsRewriter
14
15
 
15
16
 
17
+ log = get_module_logger(globals()) # noqa
18
+
19
+
16
20
  ##
17
21
 
18
22
 
@@ -39,7 +43,13 @@ class Venv:
39
43
 
40
44
  @cached_nullary
41
45
  def _iv(self) -> InterpVenv:
42
- rr = RequirementsRewriter(self._name)
46
+ rr = RequirementsRewriter(
47
+ venv=self._name,
48
+ only_pats=(
49
+ [re.compile(p) for p in self._cfg.requires_pats]
50
+ if self._cfg.requires_pats is not None else None
51
+ ),
52
+ )
43
53
 
44
54
  return InterpVenv(
45
55
  self.dir_name,
omdev/rs/__init__.py ADDED
File without changes