omdev 0.0.0.dev439__py3-none-any.whl → 0.0.0.dev486__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 (134) hide show
  1. omdev/.omlish-manifests.json +18 -30
  2. omdev/__about__.py +9 -7
  3. omdev/amalg/gen/gen.py +49 -6
  4. omdev/amalg/gen/imports.py +1 -1
  5. omdev/amalg/gen/manifests.py +1 -1
  6. omdev/amalg/gen/resources.py +1 -1
  7. omdev/amalg/gen/srcfiles.py +13 -3
  8. omdev/amalg/gen/strip.py +1 -1
  9. omdev/amalg/gen/types.py +1 -1
  10. omdev/amalg/gen/typing.py +1 -1
  11. omdev/amalg/info.py +32 -0
  12. omdev/cache/data/actions.py +1 -1
  13. omdev/cache/data/specs.py +1 -1
  14. omdev/cexts/_boilerplate.cc +2 -3
  15. omdev/cexts/cmake.py +4 -1
  16. omdev/ci/cli.py +1 -2
  17. omdev/ci/github/api/v2/api.py +2 -0
  18. omdev/cmdlog/cli.py +1 -2
  19. omdev/dataclasses/_dumping.py +1960 -0
  20. omdev/dataclasses/_template.py +22 -0
  21. omdev/dataclasses/cli.py +6 -1
  22. omdev/dataclasses/codegen.py +340 -60
  23. omdev/dataclasses/dumping.py +200 -0
  24. omdev/interp/uv/provider.py +1 -0
  25. omdev/interp/venvs.py +1 -0
  26. omdev/irc/messages/base.py +50 -0
  27. omdev/irc/messages/formats.py +92 -0
  28. omdev/irc/messages/messages.py +775 -0
  29. omdev/irc/messages/parsing.py +99 -0
  30. omdev/irc/numerics/__init__.py +0 -0
  31. omdev/irc/numerics/formats.py +97 -0
  32. omdev/irc/numerics/numerics.py +865 -0
  33. omdev/irc/numerics/types.py +59 -0
  34. omdev/irc/protocol/LICENSE +11 -0
  35. omdev/irc/protocol/__init__.py +61 -0
  36. omdev/irc/protocol/consts.py +6 -0
  37. omdev/irc/protocol/errors.py +30 -0
  38. omdev/irc/protocol/message.py +21 -0
  39. omdev/irc/protocol/nuh.py +55 -0
  40. omdev/irc/protocol/parsing.py +158 -0
  41. omdev/irc/protocol/rendering.py +153 -0
  42. omdev/irc/protocol/tags.py +102 -0
  43. omdev/irc/protocol/utils.py +30 -0
  44. omdev/manifests/_dumping.py +125 -25
  45. omdev/markdown/__init__.py +0 -0
  46. omdev/markdown/incparse.py +116 -0
  47. omdev/markdown/tokens.py +51 -0
  48. omdev/packaging/marshal.py +8 -8
  49. omdev/packaging/requires.py +6 -6
  50. omdev/packaging/specifiers.py +2 -1
  51. omdev/packaging/versions.py +4 -4
  52. omdev/packaging/wheelfile.py +2 -0
  53. omdev/precheck/blanklines.py +66 -0
  54. omdev/precheck/caches.py +1 -1
  55. omdev/precheck/imports.py +14 -1
  56. omdev/precheck/main.py +4 -3
  57. omdev/precheck/unicode.py +39 -15
  58. omdev/py/asts/__init__.py +0 -0
  59. omdev/py/asts/parents.py +28 -0
  60. omdev/py/asts/toplevel.py +123 -0
  61. omdev/py/asts/visitors.py +18 -0
  62. omdev/py/attrdocs.py +6 -7
  63. omdev/py/bracepy.py +12 -4
  64. omdev/py/reprs.py +32 -0
  65. omdev/py/srcheaders.py +1 -1
  66. omdev/py/tokens/__init__.py +0 -0
  67. omdev/py/tools/mkrelimp.py +1 -1
  68. omdev/py/tools/pipdepup.py +629 -0
  69. omdev/pyproject/pkg.py +190 -45
  70. omdev/pyproject/reqs.py +31 -9
  71. omdev/pyproject/tools/__init__.py +0 -0
  72. omdev/pyproject/tools/aboutdeps.py +55 -0
  73. omdev/pyproject/venvs.py +8 -1
  74. omdev/rs/__init__.py +0 -0
  75. omdev/scripts/ci.py +400 -80
  76. omdev/scripts/interp.py +193 -35
  77. omdev/scripts/lib/__init__.py +0 -0
  78. omdev/scripts/{inject.py → lib/inject.py} +75 -28
  79. omdev/scripts/lib/logs.py +2079 -0
  80. omdev/scripts/{marshal.py → lib/marshal.py} +68 -26
  81. omdev/scripts/pyproject.py +941 -90
  82. omdev/tools/git/cli.py +12 -1
  83. omdev/tools/json/processing.py +5 -2
  84. omdev/tools/jsonview/cli.py +31 -5
  85. omdev/tools/pawk/pawk.py +2 -2
  86. omdev/tools/pip.py +8 -0
  87. omdev/tui/__init__.py +0 -0
  88. omdev/tui/apps/__init__.py +0 -0
  89. omdev/tui/apps/edit/__init__.py +0 -0
  90. omdev/tui/apps/edit/main.py +163 -0
  91. omdev/tui/apps/irc/__init__.py +0 -0
  92. omdev/tui/apps/irc/__main__.py +4 -0
  93. omdev/tui/apps/irc/app.py +278 -0
  94. omdev/tui/apps/irc/client.py +187 -0
  95. omdev/tui/apps/irc/commands.py +175 -0
  96. omdev/tui/apps/irc/main.py +26 -0
  97. omdev/tui/apps/markdown/__init__.py +0 -0
  98. omdev/tui/apps/markdown/__main__.py +11 -0
  99. omdev/{ptk → tui/apps}/markdown/cli.py +5 -7
  100. omdev/tui/rich/__init__.py +34 -0
  101. omdev/tui/rich/console2.py +20 -0
  102. omdev/tui/rich/markdown2.py +186 -0
  103. omdev/tui/textual/__init__.py +226 -0
  104. omdev/tui/textual/app2.py +11 -0
  105. omdev/tui/textual/autocomplete/LICENSE +21 -0
  106. omdev/tui/textual/autocomplete/__init__.py +33 -0
  107. omdev/tui/textual/autocomplete/matching.py +226 -0
  108. omdev/tui/textual/autocomplete/paths.py +202 -0
  109. omdev/tui/textual/autocomplete/widget.py +612 -0
  110. omdev/tui/textual/drivers2.py +55 -0
  111. {omdev-0.0.0.dev439.dist-info → omdev-0.0.0.dev486.dist-info}/METADATA +11 -9
  112. {omdev-0.0.0.dev439.dist-info → omdev-0.0.0.dev486.dist-info}/RECORD +121 -73
  113. omdev/ptk/__init__.py +0 -103
  114. omdev/ptk/apps/ncdu.py +0 -167
  115. omdev/ptk/confirm.py +0 -60
  116. omdev/ptk/markdown/LICENSE +0 -22
  117. omdev/ptk/markdown/__init__.py +0 -10
  118. omdev/ptk/markdown/__main__.py +0 -11
  119. omdev/ptk/markdown/border.py +0 -94
  120. omdev/ptk/markdown/markdown.py +0 -390
  121. omdev/ptk/markdown/parser.py +0 -42
  122. omdev/ptk/markdown/styles.py +0 -29
  123. omdev/ptk/markdown/tags.py +0 -299
  124. omdev/ptk/markdown/utils.py +0 -366
  125. omdev/pyproject/cexts.py +0 -110
  126. /omdev/{ptk/apps → irc}/__init__.py +0 -0
  127. /omdev/{tokens → irc/messages}/__init__.py +0 -0
  128. /omdev/{tokens → py/tokens}/all.py +0 -0
  129. /omdev/{tokens → py/tokens}/tokenizert.py +0 -0
  130. /omdev/{tokens → py/tokens}/utils.py +0 -0
  131. {omdev-0.0.0.dev439.dist-info → omdev-0.0.0.dev486.dist-info}/WHEEL +0 -0
  132. {omdev-0.0.0.dev439.dist-info → omdev-0.0.0.dev486.dist-info}/entry_points.txt +0 -0
  133. {omdev-0.0.0.dev439.dist-info → omdev-0.0.0.dev486.dist-info}/licenses/LICENSE +0 -0
  134. {omdev-0.0.0.dev439.dist-info → omdev-0.0.0.dev486.dist-info}/top_level.txt +0 -0
omdev/pyproject/pkg.py CHANGED
@@ -28,10 +28,12 @@ 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
 
@@ -91,7 +93,7 @@ class BasePyprojectPackageGenerator(Abstract):
91
93
 
92
94
  def _write_git_ignore(self) -> None:
93
95
  with open(os.path.join(self._pkg_dir(), '.gitignore'), 'w') as f:
94
- f.write('\n'.join(self._GIT_IGNORE))
96
+ f.write('\n'.join([*self._GIT_IGNORE, '']))
95
97
 
96
98
  #
97
99
 
@@ -260,6 +262,7 @@ class BasePyprojectPackageGenerator(Abstract):
260
262
  )
261
263
 
262
264
  if output_dir is not None:
265
+ log.info(lambda: f'Copying {dist_dir} to {output_dir}')
263
266
  for fn in os.listdir(dist_dir):
264
267
  shutil.copyfile(os.path.join(dist_dir, fn), os.path.join(output_dir, fn))
265
268
 
@@ -315,7 +318,11 @@ class PyprojectPackageGenerator(BasePyprojectPackageGenerator):
315
318
  st = dict(specs.setuptools)
316
319
  pyp_dct['tool.setuptools'] = st
317
320
 
318
- st.pop('cexts', None)
321
+ for k in [
322
+ 'cext',
323
+ 'rs',
324
+ ]:
325
+ st.pop(k, None)
319
326
 
320
327
  #
321
328
 
@@ -388,13 +395,20 @@ class PyprojectPackageGenerator(BasePyprojectPackageGenerator):
388
395
  def children(self) -> ta.Sequence[BasePyprojectPackageGenerator]:
389
396
  out: ta.List[BasePyprojectPackageGenerator] = []
390
397
 
391
- if self.build_specs().setuptools.get('cexts'):
398
+ if self.build_specs().setuptools.get('cext'):
392
399
  out.append(_PyprojectCextPackageGenerator(
393
400
  self._dir_name,
394
401
  self._pkgs_root,
395
402
  pkg_suffix='-cext',
396
403
  ))
397
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
+
398
412
  if self.build_specs().pyproject.get('cli_scripts'):
399
413
  out.append(_PyprojectCliPackageGenerator(
400
414
  self._dir_name,
@@ -405,10 +419,67 @@ class PyprojectPackageGenerator(BasePyprojectPackageGenerator):
405
419
  return out
406
420
 
407
421
 
408
- #
422
+ ##
409
423
 
410
424
 
411
- class _PyprojectCextPackageGenerator(BasePyprojectPackageGenerator):
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
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
469
+
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):
412
483
  @cached_nullary
413
484
  def find_cext_srcs(self) -> ta.Sequence[str]:
414
485
  return sorted(find_magic_files(
@@ -419,14 +490,10 @@ class _PyprojectCextPackageGenerator(BasePyprojectPackageGenerator):
419
490
 
420
491
  #
421
492
 
422
- @dc.dataclass(frozen=True)
423
- class FileContents:
424
- pyproject_dct: ta.Mapping[str, ta.Any]
425
- setup_py: str
426
-
427
493
  @cached_nullary
428
- def file_contents(self) -> FileContents:
429
- specs = self.build_specs()
494
+ def file_contents(self) -> _PyprojectExtensionPackageGenerator.FileContents:
495
+ prj = self._build_project_dict()
496
+ st = self._build_setuptools_dict()
430
497
 
431
498
  #
432
499
 
@@ -437,33 +504,9 @@ class _PyprojectCextPackageGenerator(BasePyprojectPackageGenerator):
437
504
  'build-backend': 'setuptools.build_meta',
438
505
  }
439
506
 
440
- prj = specs.pyproject
441
- prj['dependencies'] = [f'{prj["name"]} == {prj["version"]}']
442
- prj['name'] += self._pkg_suffix
443
- for k in [
444
- 'optional_dependencies',
445
- 'entry_points',
446
- 'scripts',
447
- 'cli_scripts',
448
- ]:
449
- prj.pop(k, None)
450
-
451
507
  pyp_dct['project'] = prj
452
-
453
- #
454
-
455
- st = dict(specs.setuptools)
456
508
  pyp_dct['tool.setuptools'] = st
457
509
 
458
- for k in [
459
- 'cexts',
460
-
461
- 'find_packages',
462
- 'package_data',
463
- 'manifest_in',
464
- ]:
465
- st.pop(k, None)
466
-
467
510
  pyp_dct['tool.setuptools.packages.find'] = {
468
511
  'include': [],
469
512
  }
@@ -473,12 +516,17 @@ class _PyprojectCextPackageGenerator(BasePyprojectPackageGenerator):
473
516
  ext_lines = []
474
517
 
475
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, [])
476
524
  ext_name = ext_src.rpartition('.')[0].replace(os.sep, '.')
477
525
  ext_lines.extend([
478
526
  'st.Extension(',
479
527
  f" name='{ext_name}',",
480
528
  f" sources=['{ext_src}'],",
481
- " extra_compile_args=['-std=c++20'],",
529
+ f' extra_compile_args={compile_args!r},',
482
530
  '),',
483
531
  ])
484
532
 
@@ -489,7 +537,7 @@ class _PyprojectCextPackageGenerator(BasePyprojectPackageGenerator):
489
537
  'st.setup(',
490
538
  ' ext_modules=[',
491
539
  *[' ' + l for l in ext_lines],
492
- ' ]',
540
+ ' ],',
493
541
  ')',
494
542
  '',
495
543
  ])
@@ -501,14 +549,110 @@ class _PyprojectCextPackageGenerator(BasePyprojectPackageGenerator):
501
549
  src,
502
550
  )
503
551
 
504
- def _write_file_contents(self) -> None:
505
- fc = self.file_contents()
506
552
 
507
- with open(os.path.join(self._pkg_dir(), 'pyproject.toml'), 'w') as f:
508
- 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
+ )
509
562
 
510
- with open(os.path.join(self._pkg_dir(), 'setup.py'), 'w') as f:
511
- 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
+ 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
+ )
512
656
 
513
657
 
514
658
  ##
@@ -553,7 +697,8 @@ class _PyprojectCliPackageGenerator(BasePyprojectPackageGenerator):
553
697
  pyp_dct['tool.setuptools'] = st
554
698
 
555
699
  for k in [
556
- 'cexts',
700
+ 'cext',
701
+ 'rs',
557
702
 
558
703
  'find_packages',
559
704
  'package_data',
omdev/pyproject/reqs.py CHANGED
@@ -4,12 +4,16 @@ 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
12
  from omlish.logs.modules import get_module_logger
12
13
 
14
+ from ..packaging.requires import RequiresParserSyntaxError
15
+ from ..packaging.requires import parse_requirement
16
+
13
17
 
14
18
  log = get_module_logger(globals()) # noqa
15
19
 
@@ -20,11 +24,14 @@ log = get_module_logger(globals()) # noqa
20
24
  class RequirementsRewriter:
21
25
  def __init__(
22
26
  self,
27
+ *,
23
28
  venv: ta.Optional[str] = None,
29
+ only_pats: ta.Optional[ta.Sequence[re.Pattern]] = None,
24
30
  ) -> None:
25
31
  super().__init__()
26
32
 
27
33
  self._venv = venv
34
+ self._only_pats = only_pats
28
35
 
29
36
  @cached_nullary
30
37
  def _tmp_dir(self) -> str:
@@ -40,17 +47,32 @@ class RequirementsRewriter:
40
47
  out_lines = []
41
48
 
42
49
  for l in in_lines:
43
- if self.VENV_MAGIC in l:
44
- lp, _, rp = l.partition(self.VENV_MAGIC)
45
- rp = rp.partition('#')[0]
50
+ if l.split('#')[0].strip():
46
51
  omit = False
47
- for v in rp.split():
48
- if v[0] == '!':
49
- if self._venv is not None and self._venv == v[1:]:
50
- omit = True
51
- break
52
+
53
+ if self.VENV_MAGIC in l:
54
+ lp, _, rp = l.partition(self.VENV_MAGIC)
55
+ rp = rp.partition('#')[0]
56
+ for v in rp.split():
57
+ if v[0] == '!':
58
+ if self._venv is not None and self._venv == v[1:]:
59
+ omit = True
60
+ break
61
+ else:
62
+ raise NotImplementedError
63
+
64
+ if (
65
+ not omit and
66
+ (ops := self._only_pats) is not None and
67
+ not l.strip().startswith('-')
68
+ ):
69
+ try:
70
+ pr = parse_requirement(l.split('#')[0].strip())
71
+ except RequiresParserSyntaxError:
72
+ pass
52
73
  else:
53
- raise NotImplementedError
74
+ if not any(op.fullmatch(pr.name) for op in ops):
75
+ omit = True
54
76
 
55
77
  if omit:
56
78
  out_lines.append('# OMITTED: ' + l)
File without changes
@@ -0,0 +1,55 @@
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
+ opt_cn = canonicalize_name(opt_req.name, validate=True)
42
+ opt_spec = Specifier(opt_req.specifier)
43
+ if re.fullmatch(r'~=\s*\d+(\.\d+)*', str(opt_spec)):
44
+ opt_spec = Specifier(str(opt_spec) + '.0')
45
+
46
+ opt_dist = dist_dct[opt_cn]
47
+ opt_ver = opt_dist.version
48
+
49
+ # print((opt_dep, opt_spec, opt_ver))
50
+ if not opt_spec.contains(opt_ver):
51
+ print(f'{pkg} :: {opt_cn} : {opt_spec} ! {opt_ver}')
52
+
53
+
54
+ if __name__ == '__main__':
55
+ _main()
omdev/pyproject/venvs.py CHANGED
@@ -1,6 +1,7 @@
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
@@ -42,7 +43,13 @@ class Venv:
42
43
 
43
44
  @cached_nullary
44
45
  def _iv(self) -> InterpVenv:
45
- 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
+ )
46
53
 
47
54
  return InterpVenv(
48
55
  self.dir_name,
omdev/rs/__init__.py ADDED
File without changes