pycforge 0.15.2__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 (221) hide show
  1. pycforge/__init__.py +8 -0
  2. pycforge/__main__.py +2 -0
  3. pycforge/_version.py +1 -0
  4. pycforge/converter/__init__.py +0 -0
  5. pycforge/converter/analysis/__init__.py +5 -0
  6. pycforge/converter/analysis/functions.py +723 -0
  7. pycforge/converter/analysis/model.py +158 -0
  8. pycforge/converter/analysis/planning.py +464 -0
  9. pycforge/converter/analysis/stage.py +1976 -0
  10. pycforge/converter/analysis/symbols.py +237 -0
  11. pycforge/converter/analysis/validation.py +2166 -0
  12. pycforge/converter/c_output/__init__.py +2 -0
  13. pycforge/converter/c_output/conformance.py +297 -0
  14. pycforge/converter/c_output/renderer.py +220 -0
  15. pycforge/converter/conditional_regions/__init__.py +71 -0
  16. pycforge/converter/conditional_regions/analysis.py +481 -0
  17. pycforge/converter/conditional_regions/lowering.py +579 -0
  18. pycforge/converter/conditional_regions/model.py +243 -0
  19. pycforge/converter/conditional_regions/validation.py +690 -0
  20. pycforge/converter/containers/__init__.py +19 -0
  21. pycforge/converter/containers/analysis.py +542 -0
  22. pycforge/converter/containers/lowering.py +290 -0
  23. pycforge/converter/containers/model.py +146 -0
  24. pycforge/converter/contracts/__init__.py +0 -0
  25. pycforge/converter/contracts/configuration.py +178 -0
  26. pycforge/converter/contracts/identifiers.py +68 -0
  27. pycforge/converter/contracts/versions.py +71 -0
  28. pycforge/converter/core/__init__.py +0 -0
  29. pycforge/converter/core/artifact_io.py +87 -0
  30. pycforge/converter/core/cancellation.py +7 -0
  31. pycforge/converter/core/canonicalization.py +254 -0
  32. pycforge/converter/core/context.py +13 -0
  33. pycforge/converter/core/diagnostics.py +95 -0
  34. pycforge/converter/core/enums.py +23 -0
  35. pycforge/converter/core/fingerprint.py +22 -0
  36. pycforge/converter/core/pipeline.py +8 -0
  37. pycforge/converter/core/progress.py +25 -0
  38. pycforge/converter/core/request.py +50 -0
  39. pycforge/converter/core/resource_policy.py +31 -0
  40. pycforge/converter/core/result.py +23 -0
  41. pycforge/converter/core/serialization.py +36 -0
  42. pycforge/converter/core/stage.py +10 -0
  43. pycforge/converter/core/stage_artifact.py +80 -0
  44. pycforge/converter/core/stage_outcome.py +15 -0
  45. pycforge/converter/decision_trace/__init__.py +0 -0
  46. pycforge/converter/decision_trace/recorder.py +52 -0
  47. pycforge/converter/facade.py +459 -0
  48. pycforge/converter/frontend/__init__.py +4 -0
  49. pycforge/converter/frontend/normalizer.py +59 -0
  50. pycforge/converter/frontend/parser.py +20 -0
  51. pycforge/converter/frontend/source_document.py +93 -0
  52. pycforge/converter/frontend/stages.py +518 -0
  53. pycforge/converter/frontend/validation.py +76 -0
  54. pycforge/converter/io/__init__.py +0 -0
  55. pycforge/converter/io/atomic_writer.py +33 -0
  56. pycforge/converter/ir/__init__.py +1 -0
  57. pycforge/converter/ir/c_ir/__init__.py +4 -0
  58. pycforge/converter/ir/c_ir/builder.py +26 -0
  59. pycforge/converter/ir/c_ir/model.py +318 -0
  60. pycforge/converter/ir/c_ir/serialization.py +88 -0
  61. pycforge/converter/ir/c_ir/validation.py +834 -0
  62. pycforge/converter/ir/python_ir/__init__.py +17 -0
  63. pycforge/converter/ir/python_ir/nodes.py +86 -0
  64. pycforge/converter/keyword_calls/__init__.py +68 -0
  65. pycforge/converter/keyword_calls/analysis.py +458 -0
  66. pycforge/converter/keyword_calls/lowering.py +271 -0
  67. pycforge/converter/keyword_calls/model.py +304 -0
  68. pycforge/converter/keyword_calls/validation.py +802 -0
  69. pycforge/converter/keyword_only_calls/__init__.py +68 -0
  70. pycforge/converter/keyword_only_calls/analysis.py +640 -0
  71. pycforge/converter/keyword_only_calls/lowering.py +376 -0
  72. pycforge/converter/keyword_only_calls/model.py +328 -0
  73. pycforge/converter/keyword_only_calls/validation.py +1357 -0
  74. pycforge/converter/lowering.py +1000 -0
  75. pycforge/converter/modules/__init__.py +13 -0
  76. pycforge/converter/modules/analysis.py +1250 -0
  77. pycforge/converter/modules/lowering.py +200 -0
  78. pycforge/converter/modules/model.py +73 -0
  79. pycforge/converter/modules/stage.py +192 -0
  80. pycforge/converter/numeric_semantics/__init__.py +23 -0
  81. pycforge/converter/numeric_semantics/analysis.py +420 -0
  82. pycforge/converter/numeric_semantics/lowering.py +153 -0
  83. pycforge/converter/numeric_semantics/model.py +123 -0
  84. pycforge/converter/records/__init__.py +34 -0
  85. pycforge/converter/records/analysis.py +1394 -0
  86. pycforge/converter/records/lowering.py +393 -0
  87. pycforge/converter/records/model.py +319 -0
  88. pycforge/converter/rules/__init__.py +3 -0
  89. pycforge/converter/support_templates/__init__.py +49 -0
  90. pycforge/converter/support_templates/assembly.py +106 -0
  91. pycforge/converter/support_templates/factories.py +348 -0
  92. pycforge/converter/support_templates/model.py +159 -0
  93. pycforge/converter/support_templates/registry.py +388 -0
  94. pycforge/converter/telemetry/__init__.py +0 -0
  95. pycforge/converter/telemetry/sink.py +39 -0
  96. pycforge/ide/__init__.py +19 -0
  97. pycforge/ide/__main__.py +5 -0
  98. pycforge/ide/_worker_event_codec.py +276 -0
  99. pycforge/ide/_worker_protocol_json.py +197 -0
  100. pycforge/ide/_worker_protocol_types.py +90 -0
  101. pycforge/ide/_worker_request_codec.py +200 -0
  102. pycforge/ide/_worker_request_data.py +260 -0
  103. pycforge/ide/_worker_result_data.py +343 -0
  104. pycforge/ide/action_contract.py +469 -0
  105. pycforge/ide/action_validation.py +229 -0
  106. pycforge/ide/command_palette.py +223 -0
  107. pycforge/ide/controller.py +904 -0
  108. pycforge/ide/controller_conversion.py +546 -0
  109. pycforge/ide/controller_io.py +205 -0
  110. pycforge/ide/editor.py +951 -0
  111. pycforge/ide/editor_commands_qt.py +274 -0
  112. pycforge/ide/editor_lexical.py +43 -0
  113. pycforge/ide/editor_sidebars.py +236 -0
  114. pycforge/ide/editor_syntax.py +243 -0
  115. pycforge/ide/find_replace.py +535 -0
  116. pycforge/ide/icons.py +91 -0
  117. pycforge/ide/io_service.py +196 -0
  118. pycforge/ide/model.py +164 -0
  119. pycforge/ide/panels.py +903 -0
  120. pycforge/ide/positions.py +220 -0
  121. pycforge/ide/process_worker.py +130 -0
  122. pycforge/ide/qt.py +230 -0
  123. pycforge/ide/qt_actions.py +418 -0
  124. pycforge/ide/qt_close.py +169 -0
  125. pycforge/ide/qt_command_palette.py +297 -0
  126. pycforge/ide/qt_contract.py +220 -0
  127. pycforge/ide/qt_documents.py +590 -0
  128. pycforge/ide/qt_editor_buffers.py +113 -0
  129. pycforge/ide/qt_editor_surfaces.py +112 -0
  130. pycforge/ide/qt_menus.py +324 -0
  131. pycforge/ide/qt_projection.py +500 -0
  132. pycforge/ide/qt_shell.py +348 -0
  133. pycforge/ide/qt_shell_interactions.py +320 -0
  134. pycforge/ide/qt_state.py +393 -0
  135. pycforge/ide/qt_workspace_features.py +398 -0
  136. pycforge/ide/qt_workspace_navigation.py +208 -0
  137. pycforge/ide/qt_workspace_observers.py +173 -0
  138. pycforge/ide/qt_workspace_panels.py +545 -0
  139. pycforge/ide/qt_workspace_widgets.py +228 -0
  140. pycforge/ide/resources/icons/about.svg +1 -0
  141. pycforge/ide/resources/icons/add-document.svg +1 -0
  142. pycforge/ide/resources/icons/brand-mark.svg +1 -0
  143. pycforge/ide/resources/icons/bundle-search.svg +1 -0
  144. pycforge/ide/resources/icons/cancel.svg +1 -0
  145. pycforge/ide/resources/icons/check.svg +1 -0
  146. pycforge/ide/resources/icons/chevron-right.svg +1 -0
  147. pycforge/ide/resources/icons/close.svg +1 -0
  148. pycforge/ide/resources/icons/collapse-all.svg +1 -0
  149. pycforge/ide/resources/icons/command-palette.svg +1 -0
  150. pycforge/ide/resources/icons/convert.svg +1 -0
  151. pycforge/ide/resources/icons/copy.svg +1 -0
  152. pycforge/ide/resources/icons/cut.svg +1 -0
  153. pycforge/ide/resources/icons/decision-trace.svg +1 -0
  154. pycforge/ide/resources/icons/details.svg +1 -0
  155. pycforge/ide/resources/icons/diagnostics.svg +1 -0
  156. pycforge/ide/resources/icons/duplicate-line.svg +1 -0
  157. pycforge/ide/resources/icons/exit.svg +1 -0
  158. pycforge/ide/resources/icons/expand-all.svg +1 -0
  159. pycforge/ide/resources/icons/export.svg +1 -0
  160. pycforge/ide/resources/icons/find.svg +1 -0
  161. pycforge/ide/resources/icons/go-to-line.svg +1 -0
  162. pycforge/ide/resources/icons/go-to-output.svg +1 -0
  163. pycforge/ide/resources/icons/go-to-source.svg +1 -0
  164. pycforge/ide/resources/icons/history.svg +1 -0
  165. pycforge/ide/resources/icons/indent.svg +1 -0
  166. pycforge/ide/resources/icons/link-c.svg +1 -0
  167. pycforge/ide/resources/icons/mappings.svg +1 -0
  168. pycforge/ide/resources/icons/module.svg +1 -0
  169. pycforge/ide/resources/icons/move-down.svg +1 -0
  170. pycforge/ide/resources/icons/move-line-down.svg +1 -0
  171. pycforge/ide/resources/icons/move-line-up.svg +1 -0
  172. pycforge/ide/resources/icons/move-up.svg +1 -0
  173. pycforge/ide/resources/icons/next.svg +1 -0
  174. pycforge/ide/resources/icons/open.svg +1 -0
  175. pycforge/ide/resources/icons/outdent.svg +1 -0
  176. pycforge/ide/resources/icons/outline.svg +1 -0
  177. pycforge/ide/resources/icons/paste.svg +1 -0
  178. pycforge/ide/resources/icons/previous.svg +1 -0
  179. pycforge/ide/resources/icons/primary-module.svg +1 -0
  180. pycforge/ide/resources/icons/redo.svg +1 -0
  181. pycforge/ide/resources/icons/remove-document.svg +1 -0
  182. pycforge/ide/resources/icons/replace.svg +1 -0
  183. pycforge/ide/resources/icons/save-as.svg +1 -0
  184. pycforge/ide/resources/icons/save.svg +1 -0
  185. pycforge/ide/resources/icons/select-all.svg +1 -0
  186. pycforge/ide/resources/icons/settings.svg +1 -0
  187. pycforge/ide/resources/icons/show-c.svg +1 -0
  188. pycforge/ide/resources/icons/split-view.svg +1 -0
  189. pycforge/ide/resources/icons/summary.svg +1 -0
  190. pycforge/ide/resources/icons/telemetry.svg +1 -0
  191. pycforge/ide/resources/icons/toggle-comment.svg +1 -0
  192. pycforge/ide/resources/icons/toggle-fold.svg +1 -0
  193. pycforge/ide/resources/icons/undo.svg +1 -0
  194. pycforge/ide/resources/icons/whitespace.svg +1 -0
  195. pycforge/ide/revisions.py +400 -0
  196. pycforge/ide/search_service.py +280 -0
  197. pycforge/ide/session_history.py +150 -0
  198. pycforge/ide/source_editing.py +417 -0
  199. pycforge/ide/source_structure.py +558 -0
  200. pycforge/ide/source_structure_async.py +191 -0
  201. pycforge/ide/supervisor.py +503 -0
  202. pycforge/ide/theme.py +119 -0
  203. pycforge/ide/theme_stylesheet.py +598 -0
  204. pycforge/ide/theme_workspace_stylesheet.py +155 -0
  205. pycforge/ide/visual_tokens.py +142 -0
  206. pycforge/ide/worker_protocol.py +80 -0
  207. pycforge/ide/workspace_search.py +462 -0
  208. pycforge/ide/workspace_session.py +256 -0
  209. pycforge/laboratory/__init__.py +6 -0
  210. pycforge/laboratory/audits.py +2244 -0
  211. pycforge/laboratory/checkpoint_e.py +2685 -0
  212. pycforge/laboratory/cli.py +119 -0
  213. pycforge/laboratory/exit_codes.py +11 -0
  214. pycforge/laboratory/keyword_audit.py +661 -0
  215. pycforge/laboratory/keyword_only_audit.py +481 -0
  216. pycforge-0.15.2.dist-info/METADATA +209 -0
  217. pycforge-0.15.2.dist-info/RECORD +221 -0
  218. pycforge-0.15.2.dist-info/WHEEL +5 -0
  219. pycforge-0.15.2.dist-info/entry_points.txt +5 -0
  220. pycforge-0.15.2.dist-info/licenses/LICENSE +674 -0
  221. pycforge-0.15.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,243 @@
1
+ """Deterministic PyQt5 syntax highlighting for PyCForge editors."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from PyQt5.QtCore import QRegularExpression
6
+ from PyQt5.QtGui import (
7
+ QColor,
8
+ QFont,
9
+ QTextCharFormat,
10
+ QSyntaxHighlighter,
11
+ )
12
+
13
+ from .editor_lexical import lexical_protected_spans
14
+ from .visual_tokens import PYCFORGE_COLORS
15
+
16
+
17
+ _PYTHON_KEYWORDS = (
18
+ "and", "as", "assert", "async", "await", "break", "case", "class",
19
+ "continue", "def", "del", "elif", "else", "except", "False",
20
+ "finally", "for", "from", "global", "if", "import", "in", "is",
21
+ "lambda", "match", "None", "nonlocal", "not", "or", "pass", "raise",
22
+ "return", "True", "try", "while", "with", "yield",
23
+ )
24
+ _PYTHON_BUILTINS = (
25
+ "abs", "all", "any", "bool", "bytes", "dict", "enumerate", "float",
26
+ "int", "len", "list", "max", "min", "object", "print", "range",
27
+ "reversed", "set", "str", "sum", "tuple", "type", "zip",
28
+ )
29
+ _C_KEYWORDS = (
30
+ "_Alignas", "_Alignof", "_Atomic", "_Bool", "_Complex", "_Generic",
31
+ "_Imaginary", "_Noreturn", "_Static_assert", "_Thread_local", "auto",
32
+ "break", "case", "char", "const", "continue", "default", "do",
33
+ "double", "else", "enum", "extern", "float", "for", "goto", "if",
34
+ "inline", "int", "long", "register", "restrict", "return", "short",
35
+ "signed", "sizeof", "static", "struct", "switch", "typedef", "union",
36
+ "unsigned", "void", "volatile", "while",
37
+ )
38
+
39
+
40
+ def _format(
41
+ color: str,
42
+ *,
43
+ bold: bool = False,
44
+ italic: bool = False,
45
+ ) -> QTextCharFormat:
46
+ value = QTextCharFormat()
47
+ value.setForeground(QColor(color))
48
+ if bold:
49
+ value.setFontWeight(QFont.DemiBold)
50
+ value.setFontItalic(italic)
51
+ return value
52
+
53
+
54
+ class PyCForgeSyntaxHighlighter(QSyntaxHighlighter):
55
+ """Deterministic Python/C highlighter tuned for a dark source surface."""
56
+
57
+ _COLORS = {
58
+ "keyword": PYCFORGE_COLORS.blue_bright,
59
+ "builtin": PYCFORGE_COLORS.success,
60
+ "type": PYCFORGE_COLORS.success_bright,
61
+ "number": PYCFORGE_COLORS.warm_bright,
62
+ "string": PYCFORGE_COLORS.warning_bright,
63
+ "comment": PYCFORGE_COLORS.text_disabled,
64
+ "decorator": PYCFORGE_COLORS.violet_bright,
65
+ "function": PYCFORGE_COLORS.text,
66
+ "preprocessor": PYCFORGE_COLORS.violet,
67
+ }
68
+
69
+ def __init__(self, document, language: str = "python") -> None:
70
+ super().__init__(document)
71
+ self._language = "python"
72
+ self._rules: tuple[
73
+ tuple[QRegularExpression, QTextCharFormat], ...
74
+ ] = ()
75
+ self.set_language(language)
76
+
77
+ @property
78
+ def language(self) -> str:
79
+ return self._language
80
+
81
+ def set_language(self, language: str) -> None:
82
+ normalized = str(language).strip().lower()
83
+ if normalized in {"py", "python3"}:
84
+ normalized = "python"
85
+ elif normalized in {"c11", "c99", "h", "header"}:
86
+ normalized = "c"
87
+ if normalized not in {"python", "c"}:
88
+ raise ValueError(
89
+ "syntax language must be 'python' or 'c'"
90
+ )
91
+ self._language = normalized
92
+ self._rules = self._build_rules(normalized)
93
+ self.rehighlight()
94
+
95
+ @classmethod
96
+ def _build_rules(
97
+ cls, language: str
98
+ ) -> tuple[tuple[QRegularExpression, QTextCharFormat], ...]:
99
+ keyword_source = (
100
+ _PYTHON_KEYWORDS
101
+ if language == "python"
102
+ else _C_KEYWORDS
103
+ )
104
+ keyword = r"\b(?:" + "|".join(keyword_source) + r")\b"
105
+ rules: list[
106
+ tuple[QRegularExpression, QTextCharFormat]
107
+ ] = [
108
+ (
109
+ QRegularExpression(keyword),
110
+ _format(cls._COLORS["keyword"], bold=True),
111
+ ),
112
+ (
113
+ QRegularExpression(
114
+ r"\b(?:0[xX][0-9a-fA-F]+|0[bB][01]+|"
115
+ r"0[oO][0-7]+|(?:\d+(?:\.\d*)?|\.\d+)"
116
+ r"(?:[eE][+-]?\d+)?)\b"
117
+ ),
118
+ _format(cls._COLORS["number"]),
119
+ ),
120
+ ]
121
+ if language == "python":
122
+ rules.extend(
123
+ [
124
+ (
125
+ QRegularExpression(
126
+ r"\b(?:"
127
+ + "|".join(_PYTHON_BUILTINS)
128
+ + r")\b"
129
+ ),
130
+ _format(cls._COLORS["builtin"]),
131
+ ),
132
+ (
133
+ QRegularExpression(r"^\s*@[^\s(]+"),
134
+ _format(cls._COLORS["decorator"]),
135
+ ),
136
+ (
137
+ QRegularExpression(
138
+ r"\b(?:def|class)\s+([A-Za-z_]\w*)"
139
+ ),
140
+ _format(
141
+ cls._COLORS["function"], bold=True
142
+ ),
143
+ ),
144
+ ]
145
+ )
146
+ else:
147
+ rules.extend(
148
+ [
149
+ (
150
+ QRegularExpression(
151
+ r"\b(?:bool|int\d+_t|uint\d+_t|"
152
+ r"size_t|ptrdiff_t)\b"
153
+ ),
154
+ _format(cls._COLORS["type"]),
155
+ ),
156
+ (
157
+ QRegularExpression(
158
+ r"^\s*#\s*[A-Za-z_]+.*$"
159
+ ),
160
+ _format(cls._COLORS["preprocessor"]),
161
+ ),
162
+ ]
163
+ )
164
+ return tuple(rules)
165
+
166
+ def highlightBlock(self, text: str) -> None: # noqa: N802
167
+ for expression, char_format in self._rules:
168
+ iterator = expression.globalMatch(text)
169
+ while iterator.hasNext():
170
+ match = iterator.next()
171
+ self.setFormat(
172
+ match.capturedStart(),
173
+ match.capturedLength(),
174
+ char_format,
175
+ )
176
+ strings, comment_start = self._protected_spans(text)
177
+ for start, end in strings:
178
+ self.setFormat(
179
+ start,
180
+ end - start,
181
+ _format(self._COLORS["string"]),
182
+ )
183
+ if comment_start is not None:
184
+ self.setFormat(
185
+ comment_start,
186
+ len(text) - comment_start,
187
+ _format(
188
+ self._COLORS["comment"], italic=True
189
+ ),
190
+ )
191
+ if self._language == "python":
192
+ self._highlight_multiline(text, "'''", "'''", 1)
193
+ self._highlight_multiline(text, '"""', '"""', 2)
194
+ else:
195
+ self._highlight_multiline(text, "/*", "*/", 1)
196
+
197
+ def _protected_spans(
198
+ self, text: str
199
+ ) -> tuple[tuple[tuple[int, int], ...], int | None]:
200
+ return lexical_protected_spans(text, self._language)
201
+
202
+ def _highlight_multiline(
203
+ self,
204
+ text: str,
205
+ opener: str,
206
+ closer: str,
207
+ state: int,
208
+ ) -> None:
209
+ if self.previousBlockState() == state:
210
+ start = 0
211
+ else:
212
+ start = text.find(opener)
213
+ while start >= 0:
214
+ search_from = (
215
+ start
216
+ if self.previousBlockState() == state
217
+ else start + len(opener)
218
+ )
219
+ end = text.find(closer, search_from)
220
+ if end < 0:
221
+ self.setCurrentBlockState(state)
222
+ length = len(text) - start
223
+ else:
224
+ length = end - start + len(closer)
225
+ role = (
226
+ "string"
227
+ if self._language == "python"
228
+ else "comment"
229
+ )
230
+ self.setFormat(
231
+ start,
232
+ length,
233
+ _format(
234
+ self._COLORS[role],
235
+ italic=role == "comment",
236
+ ),
237
+ )
238
+ if end < 0:
239
+ break
240
+ start = text.find(opener, start + length)
241
+
242
+
243
+ __all__ = ["PyCForgeSyntaxHighlighter"]