IncludeCPP 3.7.3__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 (49) hide show
  1. includecpp/__init__.py +59 -0
  2. includecpp/__init__.pyi +255 -0
  3. includecpp/__main__.py +4 -0
  4. includecpp/cli/__init__.py +4 -0
  5. includecpp/cli/commands.py +8270 -0
  6. includecpp/cli/config_parser.py +127 -0
  7. includecpp/core/__init__.py +19 -0
  8. includecpp/core/ai_integration.py +2132 -0
  9. includecpp/core/build_manager.py +2416 -0
  10. includecpp/core/cpp_api.py +376 -0
  11. includecpp/core/cpp_api.pyi +95 -0
  12. includecpp/core/cppy_converter.py +3448 -0
  13. includecpp/core/cssl/CSSL_DOCUMENTATION.md +2075 -0
  14. includecpp/core/cssl/__init__.py +42 -0
  15. includecpp/core/cssl/cssl_builtins.py +2271 -0
  16. includecpp/core/cssl/cssl_builtins.pyi +1393 -0
  17. includecpp/core/cssl/cssl_events.py +621 -0
  18. includecpp/core/cssl/cssl_modules.py +2803 -0
  19. includecpp/core/cssl/cssl_parser.py +2575 -0
  20. includecpp/core/cssl/cssl_runtime.py +3051 -0
  21. includecpp/core/cssl/cssl_syntax.py +488 -0
  22. includecpp/core/cssl/cssl_types.py +1512 -0
  23. includecpp/core/cssl_bridge.py +882 -0
  24. includecpp/core/cssl_bridge.pyi +488 -0
  25. includecpp/core/error_catalog.py +802 -0
  26. includecpp/core/error_formatter.py +1016 -0
  27. includecpp/core/exceptions.py +97 -0
  28. includecpp/core/path_discovery.py +77 -0
  29. includecpp/core/project_ui.py +3370 -0
  30. includecpp/core/settings_ui.py +326 -0
  31. includecpp/generator/__init__.py +1 -0
  32. includecpp/generator/parser.cpp +1903 -0
  33. includecpp/generator/parser.h +281 -0
  34. includecpp/generator/type_resolver.cpp +363 -0
  35. includecpp/generator/type_resolver.h +68 -0
  36. includecpp/py.typed +0 -0
  37. includecpp/templates/cpp.proj.template +18 -0
  38. includecpp/vscode/__init__.py +1 -0
  39. includecpp/vscode/cssl/__init__.py +1 -0
  40. includecpp/vscode/cssl/language-configuration.json +38 -0
  41. includecpp/vscode/cssl/package.json +50 -0
  42. includecpp/vscode/cssl/snippets/cssl.snippets.json +1080 -0
  43. includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +341 -0
  44. includecpp-3.7.3.dist-info/METADATA +1076 -0
  45. includecpp-3.7.3.dist-info/RECORD +49 -0
  46. includecpp-3.7.3.dist-info/WHEEL +5 -0
  47. includecpp-3.7.3.dist-info/entry_points.txt +2 -0
  48. includecpp-3.7.3.dist-info/licenses/LICENSE +21 -0
  49. includecpp-3.7.3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,376 @@
1
+ import os
2
+ import sys
3
+ import json
4
+ import hashlib
5
+ import warnings
6
+ import platform
7
+ from pathlib import Path
8
+ from typing import Optional, Any, Dict, TYPE_CHECKING
9
+
10
+ from .exceptions import (
11
+ CppApiError,
12
+ CppBuildError,
13
+ CppModuleNotFoundError,
14
+ CppModuleOutdatedError,
15
+ CppReloadWarning,
16
+ CppValidationError
17
+ )
18
+ from ..cli.config_parser import CppProjectConfig
19
+
20
+ # Import type stubs for VSCode IntelliSense (only used for type checking, not at runtime)
21
+ if TYPE_CHECKING:
22
+ try:
23
+ from .cpp_api_extensions import * # type: ignore
24
+ except ImportError:
25
+ pass # Stubs not generated yet
26
+
27
+ class ModuleWrapper:
28
+ """Wrapper for C++ modules to provide getInfo() method and VSCode IntelliSense support."""
29
+
30
+ def __init__(self, module, info: Dict[str, Any]):
31
+ # Use object.__setattr__ to bypass our custom __setattr__ during init
32
+ object.__setattr__(self, '_module', module)
33
+ object.__setattr__(self, '_info', info)
34
+
35
+ # Dynamically expose all C++ types for VSCode IntelliSense
36
+ # This makes autocomplete work: Engine.SomeClass instead of just Engine.getInfo()
37
+ self._expose_cpp_types()
38
+
39
+ def _expose_cpp_types(self):
40
+ """Dynamically expose all C++ classes, functions, and structs as attributes."""
41
+ # Expose all attributes from the actual C++ module
42
+ module = object.__getattribute__(self, '_module')
43
+ if module:
44
+ for attr_name in dir(module):
45
+ if not attr_name.startswith('_'):
46
+ try:
47
+ attr_value = getattr(module, attr_name)
48
+ # Set as instance attribute so VSCode can see it
49
+ object.__setattr__(self, attr_name, attr_value)
50
+ except Exception:
51
+ pass # Skip attributes that can't be accessed
52
+
53
+ def getInfo(self) -> Dict[str, Any]:
54
+ """Get complete module metadata including function signatures (v2.3.5+).
55
+
56
+ Returns dictionary with structure:
57
+ {
58
+ "sources": List[str],
59
+ "functions": [
60
+ {
61
+ "name": str,
62
+ "return_type": str,
63
+ "parameters": [
64
+ {
65
+ "name": str,
66
+ "type": str,
67
+ "default": Optional[str],
68
+ "const": Optional[bool],
69
+ "reference": Optional[bool],
70
+ "pointer": Optional[bool]
71
+ },
72
+ ...
73
+ ],
74
+ "doc": Optional[str],
75
+ "static": Optional[bool],
76
+ "const": Optional[bool],
77
+ "inline": Optional[bool]
78
+ },
79
+ ...
80
+ ],
81
+ "classes": [
82
+ {
83
+ "name": str,
84
+ "doc": Optional[str],
85
+ "methods": [
86
+ {"name": str, "doc": Optional[str]},
87
+ ...
88
+ ]
89
+ },
90
+ ...
91
+ ],
92
+ "structs": [...],
93
+ "dependencies": [...]
94
+ }
95
+
96
+ Returns:
97
+ Complete module metadata dictionary
98
+ """
99
+ return object.__getattribute__(self, '_info')
100
+
101
+ def __getattr__(self, name):
102
+ """Delegate attribute access to wrapped module (fallback for dynamic attributes)."""
103
+ if name.startswith('_'):
104
+ raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")
105
+ module = object.__getattribute__(self, '_module')
106
+ return getattr(module, name)
107
+
108
+ def __dir__(self):
109
+ """Return list of attributes for autocomplete."""
110
+ # Combine wrapper attributes with C++ module attributes
111
+ module = object.__getattribute__(self, '_module')
112
+ wrapper_attrs = ['getInfo']
113
+ if module:
114
+ module_attrs = [attr for attr in dir(module) if not attr.startswith('__')]
115
+ return sorted(set(wrapper_attrs + module_attrs))
116
+ return wrapper_attrs
117
+
118
+ class CppApi:
119
+ # Inbuilt module constants
120
+ FileSystem = "filesystem"
121
+ Crypto = "crypto"
122
+ JSON = "json"
123
+ StringUtils = "string_utils"
124
+ Networking = "networking"
125
+ DataStructures = "data_structures"
126
+ Threading = "threading"
127
+ StandardMenus = "standard_menus"
128
+
129
+ def __init__(self, verbose: bool = False, auto_update: bool = False, config_path: Optional[Path] = None):
130
+ """Initialize C++ API.
131
+
132
+ Args:
133
+ verbose: Enable detailed logging
134
+ auto_update: Auto-rebuild outdated modules on include()
135
+ config_path: Path to cpp.proj (defaults to cwd/cpp.proj)
136
+ """
137
+ self.project_root = Path.cwd()
138
+ self.config = CppProjectConfig(config_path or (self.project_root / "cpp.proj"))
139
+ self.base_dir = self.config.base_dir
140
+ self.registry_file = self.base_dir / ".module_registry.json"
141
+ self.bindings_dir = self.base_dir / "bindings"
142
+
143
+ self.verbose = verbose
144
+ self.auto_update = auto_update
145
+ self.silent = False
146
+
147
+ if str(self.bindings_dir) not in sys.path:
148
+ sys.path.insert(0, str(self.bindings_dir))
149
+
150
+ self.registry = self._load_registry()
151
+ self.loaded_modules = {}
152
+ self.api_module = None
153
+ self._import_api()
154
+
155
+ def _load_registry(self):
156
+ """Load module registry (v1.6 or v2.0 format)."""
157
+ if not self.registry_file.exists():
158
+ if self.verbose:
159
+ print(f"[WARNING] Registry file not found: {self.registry_file}")
160
+ print(f"[INFO] Run 'python -m includecpp rebuild' in project directory")
161
+ return {}
162
+
163
+ try:
164
+ with open(self.registry_file, 'r', encoding='utf-8') as f:
165
+ data = json.load(f)
166
+
167
+ if "schema_version" in data and data["schema_version"] == "2.0":
168
+ return data.get("modules", {})
169
+ else:
170
+ return data
171
+
172
+ except Exception as e:
173
+ if self.verbose:
174
+ print(f"[WARNING] Failed to load registry: {e}")
175
+ return {}
176
+
177
+ def _save_registry(self):
178
+ try:
179
+ with open(self.registry_file, 'w', encoding='utf-8') as f:
180
+ json.dump(self.registry, f, indent=2)
181
+ except Exception:
182
+ pass
183
+
184
+ def _import_api(self):
185
+ try:
186
+ if 'api' in sys.modules:
187
+ self.api_module = sys.modules['api']
188
+ else:
189
+ import api
190
+ self.api_module = api
191
+ except ImportError:
192
+ if self.verbose:
193
+ print(f"[WARNING] api module not found in {self.bindings_dir}")
194
+ print(f"[INFO] Run 'python -m includecpp rebuild' to build C++ modules")
195
+ self.api_module = None
196
+
197
+ def _compute_hash(self, filepath):
198
+ if not os.path.exists(filepath):
199
+ return "0"
200
+
201
+ try:
202
+ with open(filepath, 'rb') as f:
203
+ return hashlib.sha256(f.read()).hexdigest()
204
+ except Exception:
205
+ return "0"
206
+
207
+ def exists(self, module_name):
208
+ if module_name not in self.registry:
209
+ return False
210
+
211
+ if self.api_module is None:
212
+ return False
213
+
214
+ try:
215
+ return hasattr(self.api_module, module_name)
216
+ except Exception:
217
+ return False
218
+
219
+ def include(self, module_name: str, auto_update: Optional[bool] = None):
220
+ """Load a C++ module (v2.0 per-module .pyd support).
221
+
222
+ Tries to load:
223
+ 1. Per-module .pyd: api_modulename.pyd (v2.0)
224
+ 2. Fallback to monolithic: api.modulename (v1.6 backward compatibility)
225
+
226
+ Args:
227
+ module_name: Name of module to load
228
+ auto_update: Override instance auto_update setting (None = use instance setting)
229
+
230
+ Returns:
231
+ ModuleWrapper object with getInfo() support
232
+
233
+ Raises:
234
+ CppModuleNotFoundError: If module not found or not built
235
+ """
236
+ # Check cache first
237
+ if module_name in self.loaded_modules:
238
+ return self.loaded_modules[module_name]
239
+
240
+ # Check if module is registered
241
+ if module_name not in self.registry:
242
+ raise CppModuleNotFoundError(
243
+ f"Module '{module_name}' not registered.\n"
244
+ f"Available modules: {list(self.registry.keys())}\n"
245
+ f"Run 'python -m includecpp rebuild' to build modules."
246
+ )
247
+
248
+ should_auto_update = auto_update if auto_update is not None else self.auto_update
249
+ if self.need_update(module_name):
250
+ if not self.silent:
251
+ print(f"[WARNING] Module '{module_name}' source is newer than build")
252
+ if should_auto_update:
253
+ if not self.silent:
254
+ print(f"[INFO] Auto-updating module '{module_name}'...")
255
+ self.update(module_name)
256
+ elif not self.silent:
257
+ print(f"[INFO] Run api.update('{module_name}') to rebuild")
258
+
259
+ module_info = self.registry.get(module_name, {})
260
+
261
+ # Try v2.0 per-module .pyd first: api_modulename
262
+ pyd_name = f"api_{module_name}"
263
+ pyd_suffix = ".pyd" if platform.system() == "Windows" else ".so"
264
+ pyd_path = self.bindings_dir / f"{pyd_name}{pyd_suffix}"
265
+
266
+ try:
267
+ if pyd_path.exists():
268
+ if self.verbose:
269
+ print(f"[INFO] Loading per-module .pyd: {pyd_name}")
270
+
271
+ imported = __import__(pyd_name)
272
+ wrapped = ModuleWrapper(imported, module_info)
273
+ self.loaded_modules[module_name] = wrapped
274
+ return wrapped
275
+
276
+ except ImportError as e:
277
+ if self.verbose:
278
+ print(f"[WARNING] Failed to import {pyd_name}: {e}")
279
+ print(f"[INFO] Falling back to monolithic api module")
280
+
281
+ # Fallback to v1.6 monolithic api module
282
+ if self.api_module is None:
283
+ raise CppModuleNotFoundError(
284
+ f"Module '{module_name}' not built.\n"
285
+ f"Expected: {pyd_path} or api{pyd_suffix}\n"
286
+ f"Run 'python -m includecpp rebuild' to build."
287
+ )
288
+
289
+ try:
290
+ # v1.6: Access from monolithic api module
291
+ module = getattr(self.api_module, module_name)
292
+ wrapped = ModuleWrapper(module, module_info)
293
+ self.loaded_modules[module_name] = wrapped
294
+ return wrapped
295
+
296
+ except AttributeError:
297
+ raise CppModuleNotFoundError(
298
+ f"Module '{module_name}' not found.\n"
299
+ f"Neither {pyd_name}{pyd_suffix} nor api.{module_name} exists.\n"
300
+ f"Run 'python -m includecpp rebuild' to build."
301
+ )
302
+
303
+ def noFeedback(self):
304
+ """Disable all warnings and feedback messages."""
305
+ self.silent = True
306
+
307
+ def need_update(self, module_name: str) -> bool:
308
+ """Check if module needs rebuild by comparing source file hashes.
309
+
310
+ Supports both v2.3.5 (source_hashes) and v1.6 (hashes) registry formats.
311
+ """
312
+ if module_name not in self.registry:
313
+ return True
314
+
315
+ module_info = self.registry[module_name]
316
+ sources = module_info.get('sources', [])
317
+
318
+ # Try v2.3.5 format first, fall back to v1.6 format
319
+ stored_hashes = module_info.get('source_hashes', module_info.get('hashes', {}))
320
+
321
+ # If no hashes stored at all, rebuild needed
322
+ if not stored_hashes:
323
+ return True
324
+
325
+ for source in sources:
326
+ source_path = self.project_root / source
327
+ current_hash = self._compute_hash(str(source_path))
328
+
329
+ # Try exact source path first, then just filename (v1.6 compatibility)
330
+ stored_hash = stored_hashes.get(source, stored_hashes.get(Path(source).name, None))
331
+
332
+ # If no hash found for this source, rebuild needed
333
+ if stored_hash is None:
334
+ return True
335
+
336
+ # Handle hash length mismatch (v1.6 = 16 chars, v2.3.5 = 64 chars)
337
+ if len(stored_hash) == 16 and len(current_hash) == 64:
338
+ # Compare first 16 chars for backwards compatibility
339
+ if current_hash[:16] != stored_hash:
340
+ return True
341
+ elif current_hash != stored_hash:
342
+ return True
343
+
344
+ return False
345
+
346
+ def update(self, module_name: str, verbose: Optional[bool] = None):
347
+ from .build_manager import BuildManager
348
+ if verbose is None:
349
+ verbose = self.verbose
350
+ if module_name not in self.registry:
351
+ raise CppModuleNotFoundError(f"Module '{module_name}' not found in registry")
352
+ builder = BuildManager(self.project_root, self.base_dir, self.config)
353
+ success = builder.rebuild(
354
+ modules=[module_name],
355
+ incremental=True,
356
+ parallel=False,
357
+ clean=False,
358
+ verbose=verbose
359
+ )
360
+ if success:
361
+ self.registry = self._load_registry()
362
+ if module_name in self.loaded_modules:
363
+ del self.loaded_modules[module_name]
364
+ if not self.silent and verbose:
365
+ print(f"[INFO] Module '{module_name}' rebuilt successfully")
366
+ else:
367
+ raise CppBuildError(f"Failed to rebuild module '{module_name}'")
368
+
369
+ def list_modules(self):
370
+ return list(self.registry.keys())
371
+
372
+ def get_module_info(self, module_name):
373
+ if module_name not in self.registry:
374
+ return None
375
+
376
+ return self.registry[module_name]
@@ -0,0 +1,95 @@
1
+ """Type stubs for cpp_api module - VSCode IntelliSense support.
2
+
3
+ This stub file provides proper type hints for the CppAPI.include() method
4
+ so VSCode can show autocomplete suggestions when using C++ modules.
5
+ """
6
+
7
+ from typing import Any, Dict, Optional, Union, overload, Literal
8
+ from pathlib import Path
9
+
10
+ # Import the generated module wrapper protocols
11
+ try:
12
+ from .cpp_api_extensions import *
13
+ except ImportError:
14
+ pass # Not yet generated
15
+
16
+ class ModuleWrapper:
17
+ """Wrapper for C++ modules with dynamic attribute exposure."""
18
+
19
+ def __init__(self, module: Any, info: Dict[str, Any]) -> None: ...
20
+ def getInfo(self) -> Dict[str, Any]: ...
21
+ def __getattr__(self, name: str) -> Any: ...
22
+ def __dir__(self) -> list[str]: ...
23
+
24
+ class CppApi:
25
+ """Main API class for including C++ modules."""
26
+
27
+ # Inbuilt module constants
28
+ FileSystem: str
29
+ Crypto: str
30
+ JSON: str
31
+ StringUtils: str
32
+ Networking: str
33
+ DataStructures: str
34
+ Threading: str
35
+ StandardMenus: str
36
+
37
+ def __init__(
38
+ self,
39
+ verbose: bool = False,
40
+ auto_update: bool = False,
41
+ config_path: Optional[Path] = None
42
+ ) -> None: ...
43
+
44
+ @property
45
+ def Inbuilds(self) -> list[str]: ...
46
+
47
+ def exists(self, module_name: str) -> bool: ...
48
+
49
+ # Overloaded include() signatures for each inbuilt module using Literal types
50
+ # This allows VSCode to show module-specific autocomplete based on the string literal
51
+ @overload
52
+ def include(self, module_name: Literal["crypto"], auto_update: Optional[bool] = None) -> CryptoModuleWrapper: ...
53
+ @overload
54
+ def include(self, module_name: Literal["filesystem"], auto_update: Optional[bool] = None) -> FilesystemModuleWrapper: ...
55
+ @overload
56
+ def include(self, module_name: Literal["json"], auto_update: Optional[bool] = None) -> JsonModuleWrapper: ...
57
+ @overload
58
+ def include(self, module_name: Literal["string_utils"], auto_update: Optional[bool] = None) -> String_utilsModuleWrapper: ...
59
+ @overload
60
+ def include(self, module_name: Literal["networking"], auto_update: Optional[bool] = None) -> NetworkingModuleWrapper: ...
61
+ @overload
62
+ def include(self, module_name: Literal["data_structures"], auto_update: Optional[bool] = None) -> Data_structuresModuleWrapper: ...
63
+ @overload
64
+ def include(self, module_name: Literal["threading"], auto_update: Optional[bool] = None) -> ThreadingModuleWrapper: ...
65
+ @overload
66
+ def include(self, module_name: Literal["standard_menus"], auto_update: Optional[bool] = None) -> Standard_menusModuleWrapper: ...
67
+
68
+ # Fallback for user-defined modules - returns generic ModuleWrapper
69
+ def include(
70
+ self,
71
+ module_name: str,
72
+ auto_update: Optional[bool] = None
73
+ ) -> ModuleWrapper:
74
+ """Include a C++ module.
75
+
76
+ The returned ModuleWrapper will have attributes matching the module's
77
+ classes, functions, and structs. VSCode autocomplete will show these
78
+ based on the generated type stubs.
79
+
80
+ Args:
81
+ module_name: Name of the module to include
82
+ auto_update: Whether to auto-rebuild if module is outdated
83
+
84
+ Returns:
85
+ ModuleWrapper with module-specific attributes for autocomplete
86
+ """
87
+ ...
88
+
89
+ def rebuild(
90
+ self,
91
+ verbose: bool = False,
92
+ clean: bool = False
93
+ ) -> None: ...
94
+
95
+ def list_modules(self) -> list[str]: ...