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/precheck/unicode.py CHANGED
@@ -29,6 +29,18 @@ class UnicodePrecheck(Precheck['UnicodePrecheck.Config']):
29
29
 
30
30
  permitted_categories: ta.AbstractSet[str] = DEFAULT_PERMITTED_CATEGORIES
31
31
 
32
+ DEFAULT_FILE_EXTENSIONS: ta.ClassVar[ta.AbstractSet[str]] = frozenset([
33
+ 'py',
34
+
35
+ 'c',
36
+ 'cc',
37
+ 'cu',
38
+ 'h',
39
+ 'hh',
40
+ ])
41
+
42
+ file_extensions: ta.AbstractSet[str] = DEFAULT_FILE_EXTENSIONS
43
+
32
44
  def __init__(
33
45
  self,
34
46
  context: PrecheckContext,
@@ -46,19 +58,15 @@ class UnicodePrecheck(Precheck['UnicodePrecheck.Config']):
46
58
  self._text_file_cache = text_file_cache
47
59
  self._headers_cache = headers_cache
48
60
 
49
- async def _run_py_file(self, py_file: str) -> ta.AsyncGenerator[Precheck.Violation]:
50
- if isinstance(header_lines := self._headers_cache.get_file_headers(py_file), Exception):
51
- return
52
- if any(hl.src.strip() == '# @omlish-precheck-allow-any-unicode' for hl in header_lines):
53
- return
54
-
55
- src = self._text_file_cache.get_entry(py_file).text()
61
+ async def _run_file(self, file: str, src: str | None = None) -> ta.AsyncGenerator[Precheck.Violation]:
62
+ if src is None:
63
+ src = self._text_file_cache.get_entry(file).text()
56
64
 
57
65
  illegal_chars = {
58
66
  ch
59
67
  for ch in src
60
- if ord(ch) > 255 and
61
- unicodedata.category(ch) not in self._config.permitted_categories
68
+ if ord(ch) > 255
69
+ and unicodedata.category(ch) not in self._config.permitted_categories
62
70
  }
63
71
 
64
72
  if illegal_chars:
@@ -66,16 +74,32 @@ class UnicodePrecheck(Precheck['UnicodePrecheck.Config']):
66
74
  f'({ch!r}, {unicodedata.category(ch)})'
67
75
  for ch in sorted(illegal_chars)
68
76
  ]
69
- yield Precheck.Violation(self, f'source file {py_file} has illegal unicode characters: {", ".join(sl)}')
77
+ yield Precheck.Violation(self, f'source file {file} has illegal unicode characters: {", ".join(sl)}')
78
+
79
+ async def _run_py_file(self, py_file: str) -> ta.AsyncGenerator[Precheck.Violation]:
80
+ if isinstance(header_lines := self._headers_cache.get_file_headers(py_file), Exception):
81
+ return
82
+ if any(hl.src.strip() == '# @omlish-precheck-allow-any-unicode' for hl in header_lines):
83
+ return
84
+
85
+ async for v in self._run_file(py_file):
86
+ yield v
70
87
 
71
88
  async def run(self) -> ta.AsyncGenerator[Precheck.Violation]:
72
- py_files = [
89
+ files = [
73
90
  os.path.join(e.root, f)
74
91
  for src_root in self._context.src_roots
75
92
  for e in self._dir_walk_cache.list_dir(src_root)
76
93
  for f in e.files
77
- if f.endswith('.py')
94
+ if '.' in f
95
+ and any(f.endswith('.' + ext) for ext in self._config.file_extensions)
78
96
  ]
79
- for py_file in sorted(py_files):
80
- async for v in self._run_py_file(py_file):
81
- yield v
97
+
98
+ for file in sorted(files):
99
+ if file.endswith('.py'):
100
+ async for v in self._run_py_file(file):
101
+ yield v
102
+
103
+ else:
104
+ async for v in self._run_file(file):
105
+ yield v
File without changes
@@ -0,0 +1,28 @@
1
+ import ast
2
+
3
+ from omlish import check
4
+
5
+
6
+ ##
7
+
8
+
9
+ class _ParentsNodeVisitor(ast.NodeVisitor):
10
+ def __init__(self) -> None:
11
+ super().__init__()
12
+
13
+ self.parents: dict[ast.AST, ast.AST | None] = {}
14
+
15
+ parent: ast.AST | None = None
16
+
17
+ def generic_visit(self, node: ast.AST) -> None:
18
+ check.not_in(node, self.parents)
19
+ prev_parent = self.parents[node] = self.parent
20
+ self.parent = node
21
+ super().generic_visit(node)
22
+ self.parent = prev_parent
23
+
24
+
25
+ def get_node_parents(node: ast.AST) -> dict[ast.AST, ast.AST | None]:
26
+ visitor = _ParentsNodeVisitor()
27
+ visitor.visit(node)
28
+ return visitor.parents
@@ -0,0 +1,123 @@
1
+ """
2
+ Quite, quite lame, but sufficient for immediate needs. Accurate static symbol resolution is in development but can't
3
+ block other work.
4
+ """
5
+ import ast
6
+ import dataclasses as dc
7
+ import typing as ta
8
+
9
+ from omlish import check
10
+
11
+
12
+ ##
13
+
14
+
15
+ @dc.dataclass(frozen=True, kw_only=True)
16
+ class TopLevelImport:
17
+ spec: str
18
+ name: str
19
+ node: ast.Import | ast.ImportFrom
20
+
21
+
22
+ @dc.dataclass(frozen=True, kw_only=True)
23
+ class TopLevelCall:
24
+ node: ast.Call
25
+ imp: TopLevelImport
26
+
27
+
28
+ @dc.dataclass(frozen=True, kw_only=True)
29
+ class TopLevelFindings:
30
+ imports: ta.Mapping[str, TopLevelImport]
31
+ calls: ta.Sequence[TopLevelCall]
32
+
33
+
34
+ ##
35
+
36
+
37
+ class _TopLevelModuleVisitor(ast.NodeVisitor):
38
+ def __init__(self, module_name: str) -> None:
39
+ super().__init__()
40
+
41
+ self.module_name = module_name
42
+ self.module_name_parts = module_name.split('.')
43
+
44
+ self.imports: dict[str, TopLevelImport] = {}
45
+ self.calls: list[TopLevelCall] = []
46
+
47
+ #
48
+
49
+ def visit_Import(self, node: ast.Import) -> None:
50
+ for alias in node.names:
51
+ name = alias.asname if alias.asname else alias.name
52
+ self.imports[name] = TopLevelImport(
53
+ spec=alias.name,
54
+ name=name,
55
+ node=node,
56
+ )
57
+
58
+ self.generic_visit(node)
59
+
60
+ def visit_ImportFrom(self, node: ast.ImportFrom) -> None:
61
+ if node.level:
62
+ check.state(node.level < len(self.module_name_parts))
63
+ module = '.'.join([
64
+ *self.module_name_parts[:-node.level],
65
+ *([node.module] if node.module else []),
66
+ ])
67
+ else:
68
+ module = check.not_none(node.module)
69
+
70
+ for alias in node.names:
71
+ name = alias.asname if alias.asname else alias.name
72
+ self.imports[name] = TopLevelImport(
73
+ spec='.'.join([module, alias.name]),
74
+ name=name,
75
+ node=node,
76
+ )
77
+
78
+ self.generic_visit(node)
79
+
80
+ #
81
+
82
+ def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> None:
83
+ pass
84
+
85
+ def visit_ClassDef(self, node: ast.ClassDef) -> None:
86
+ pass
87
+
88
+ def visit_FunctionDef(self, node: ast.FunctionDef) -> None:
89
+ pass
90
+
91
+ #
92
+
93
+ def handle_call(self, node: ast.Call) -> None:
94
+ if not (
95
+ isinstance(attr := node.func, ast.Attribute) and
96
+ isinstance(attr.ctx, ast.Load) and
97
+ isinstance(name := attr.value, ast.Name) and
98
+ isinstance(name.ctx, ast.Load)
99
+ ):
100
+ return
101
+
102
+ if (imp := self.imports.get(name.id)) is None:
103
+ return
104
+
105
+ self.calls.append(TopLevelCall(
106
+ node=node,
107
+ imp=imp,
108
+ ))
109
+
110
+ def visit_Call(self, node: ast.Call) -> None:
111
+ self.handle_call(node)
112
+
113
+
114
+ def analyze_module_top_level(
115
+ module: ast.Module,
116
+ module_name: str,
117
+ ) -> TopLevelFindings:
118
+ visitor = _TopLevelModuleVisitor(module_name)
119
+ visitor.visit(module)
120
+ return TopLevelFindings(
121
+ imports=visitor.imports,
122
+ calls=visitor.calls,
123
+ )
@@ -0,0 +1,18 @@
1
+ import ast
2
+
3
+ from omlish import check
4
+
5
+
6
+ ##
7
+
8
+
9
+ class StackNodeVisitor(ast.NodeVisitor):
10
+ def __init__(self) -> None:
11
+ super().__init__()
12
+
13
+ self.node_stack: list[ast.AST] = []
14
+
15
+ def generic_visit(self, node: ast.AST) -> None:
16
+ self.node_stack.append(node)
17
+ super().generic_visit(node)
18
+ check.is_(self.node_stack.pop(), node)
omdev/py/attrdocs.py CHANGED
@@ -12,7 +12,7 @@ import typing as ta
12
12
  from omlish import check
13
13
  from omlish import lang
14
14
 
15
- from ..tokens import all as tks
15
+ from .tokens import all as tks
16
16
 
17
17
 
18
18
  ##
@@ -24,12 +24,11 @@ class AttrDoc:
24
24
  trailing_comment: str | None = None
25
25
  preceding_comment: str | None = None
26
26
 
27
- __repr__ = lang.attr_ops(
28
- 'docstring',
29
- 'trailing_comment',
30
- 'preceding_comment',
31
- repr_filter=bool,
32
- ).repr
27
+ __repr__ = lang.attr_ops(lambda o: (
28
+ o.docstring,
29
+ o.trailing_comment,
30
+ o.preceding_comment,
31
+ ), repr_filter=bool).repr
33
32
 
34
33
 
35
34
  _EMPTY_ATTR_DOC = AttrDoc()
omdev/py/bracepy.py CHANGED
@@ -101,18 +101,26 @@ _CLI_MODULE = {'!.cli.types.CliModule': {
101
101
  if __name__ == '__main__':
102
102
  def _main(argv=None) -> None:
103
103
  import argparse
104
+ import sys
104
105
 
105
106
  parser = argparse.ArgumentParser()
106
107
  parser.add_argument('-x', '--exec', action='store_true')
107
- parser.add_argument('cmd')
108
+ parser.add_argument('-i', '--indent', type=int)
109
+ parser.add_argument('code', nargs='?')
108
110
 
109
111
  args = parser.parse_args(argv)
110
112
 
111
- src = translate_brace_python(args.cmd)
113
+ if (code := args.code) is None:
114
+ code = sys.stdin.read()
115
+
116
+ out = translate_brace_python(
117
+ code,
118
+ **(dict(indent_width=args.indent) if args.indent is not None else {}),
119
+ )
112
120
 
113
121
  if args.exec:
114
- exec(src)
122
+ exec(out)
115
123
  else:
116
- print(src)
124
+ print(out)
117
125
 
118
126
  _main()
omdev/py/reprs.py ADDED
@@ -0,0 +1,32 @@
1
+ def textwrap_repr(text: str, width: int = 120, quote_char: str = '"') -> list[str]:
2
+ escaped_quote = '\\' + quote_char
3
+ content_width = width - 2
4
+
5
+ lines: list[str] = []
6
+ current_line: list[str] = []
7
+ current_length = 0
8
+
9
+ for char in text:
10
+ if char == quote_char:
11
+ safe_char = escaped_quote
12
+ elif char == '\\':
13
+ safe_char = '\\\\'
14
+ elif not char.isprintable():
15
+ safe_char = repr(char)[1:-1]
16
+ if quote_char in safe_char:
17
+ safe_char = safe_char.replace(quote_char, escaped_quote)
18
+ else:
19
+ safe_char = char
20
+
21
+ if current_length + len(safe_char) > content_width:
22
+ lines.append(f"{quote_char}{''.join(current_line)}{quote_char}")
23
+ current_line = []
24
+ current_length = 0
25
+
26
+ current_line.append(safe_char)
27
+ current_length += len(safe_char)
28
+
29
+ if current_line:
30
+ lines.append(f"{quote_char}{''.join(current_line)}{quote_char}")
31
+
32
+ return lines
omdev/py/srcheaders.py CHANGED
@@ -4,7 +4,7 @@ import typing as ta
4
4
 
5
5
  from omlish.lite.check import check
6
6
 
7
- from ..tokens import all as tks
7
+ from .tokens import all as tks
8
8
 
9
9
 
10
10
  ##
File without changes
@@ -6,7 +6,7 @@ import typing as ta
6
6
  from omlish.logs import all as logs
7
7
 
8
8
  from ...cli import CliModule
9
- from ...tokens import all as tks
9
+ from ..tokens import all as tks
10
10
 
11
11
 
12
12
  T = ta.TypeVar('T')