IncludeCPP 3.7.26__tar.gz → 3.8.1__tar.gz

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 (60) hide show
  1. {includecpp-3.7.26 → includecpp-3.8.1}/IncludeCPP.egg-info/PKG-INFO +53 -1
  2. {includecpp-3.7.26 → includecpp-3.8.1}/PKG-INFO +53 -1
  3. {includecpp-3.7.26 → includecpp-3.8.1}/README.md +53 -1
  4. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/__init__.py +1 -1
  5. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/cli/commands.py +26 -6
  6. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/cssl/cssl_builtins.py +210 -0
  7. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/cssl/cssl_runtime.py +19 -1
  8. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/vscode/cssl/package.json +1 -1
  9. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/vscode/cssl/snippets/cssl.snippets.json +38 -0
  10. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +8 -0
  11. {includecpp-3.7.26 → includecpp-3.8.1}/pyproject.toml +1 -1
  12. {includecpp-3.7.26 → includecpp-3.8.1}/IncludeCPP.egg-info/SOURCES.txt +0 -0
  13. {includecpp-3.7.26 → includecpp-3.8.1}/IncludeCPP.egg-info/dependency_links.txt +0 -0
  14. {includecpp-3.7.26 → includecpp-3.8.1}/IncludeCPP.egg-info/entry_points.txt +0 -0
  15. {includecpp-3.7.26 → includecpp-3.8.1}/IncludeCPP.egg-info/requires.txt +0 -0
  16. {includecpp-3.7.26 → includecpp-3.8.1}/IncludeCPP.egg-info/top_level.txt +0 -0
  17. {includecpp-3.7.26 → includecpp-3.8.1}/LICENSE +0 -0
  18. {includecpp-3.7.26 → includecpp-3.8.1}/MANIFEST.in +0 -0
  19. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/__init__.pyi +0 -0
  20. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/__main__.py +0 -0
  21. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/cli/__init__.py +0 -0
  22. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/cli/config_parser.py +0 -0
  23. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/__init__.py +0 -0
  24. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/ai_integration.py +0 -0
  25. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/build_manager.py +0 -0
  26. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/cpp_api.py +0 -0
  27. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/cpp_api.pyi +0 -0
  28. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/cppy_converter.py +0 -0
  29. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/cssl/CSSL_DOCUMENTATION.md +0 -0
  30. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/cssl/__init__.py +0 -0
  31. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/cssl/cssl_builtins.pyi +0 -0
  32. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/cssl/cssl_events.py +0 -0
  33. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/cssl/cssl_modules.py +0 -0
  34. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/cssl/cssl_parser.py +0 -0
  35. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/cssl/cssl_syntax.py +0 -0
  36. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/cssl/cssl_types.py +0 -0
  37. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/cssl_bridge.py +0 -0
  38. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/cssl_bridge.pyi +0 -0
  39. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/error_catalog.py +0 -0
  40. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/error_formatter.py +0 -0
  41. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/exceptions.py +0 -0
  42. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/path_discovery.py +0 -0
  43. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/project_ui.py +0 -0
  44. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/core/settings_ui.py +0 -0
  45. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/generator/__init__.py +0 -0
  46. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/generator/parser.cpp +0 -0
  47. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/generator/parser.h +0 -0
  48. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/generator/type_resolver.cpp +0 -0
  49. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/generator/type_resolver.h +0 -0
  50. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/py.typed +0 -0
  51. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/templates/cpp.proj.template +0 -0
  52. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/vscode/__init__.py +0 -0
  53. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/vscode/cssl/__init__.py +0 -0
  54. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/vscode/cssl/extension.js +0 -0
  55. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/vscode/cssl/images/cssl.png +0 -0
  56. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/vscode/cssl/images/cssl_pl.png +0 -0
  57. {includecpp-3.7.26 → includecpp-3.8.1}/includecpp/vscode/cssl/language-configuration.json +0 -0
  58. {includecpp-3.7.26 → includecpp-3.8.1}/requirements.txt +0 -0
  59. {includecpp-3.7.26 → includecpp-3.8.1}/setup.cfg +0 -0
  60. {includecpp-3.7.26 → includecpp-3.8.1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: IncludeCPP
3
- Version: 3.7.26
3
+ Version: 3.8.1
4
4
  Summary: Professional C++ Python bindings with type-generic templates, pystubs and native threading
5
5
  Home-page: https://github.com/liliassg/IncludeCPP
6
6
  Author: Lilias Hatterscheidt
@@ -853,3 +853,55 @@ cssl.run('''
853
853
  printl(@version);
854
854
  ''')
855
855
  ```
856
+
857
+ ## Return CSSL Classes to Python
858
+
859
+ Use `python::pythonize()` to convert CSSL class instances into Python-usable objects:
860
+
861
+ ```python
862
+ from includecpp import CSSL
863
+
864
+ cssl = CSSL.CsslLang()
865
+
866
+ # Create and return a CSSL class as a Python object
867
+ greeter = cssl.run('''
868
+ class Greeter {
869
+ string name;
870
+
871
+ Greeter(string n) {
872
+ this->name = n;
873
+ }
874
+
875
+ string sayHello() {
876
+ return "Hello, " + this->name + "!";
877
+ }
878
+
879
+ void setName(string newName) {
880
+ this->name = newName;
881
+ }
882
+
883
+ string getName() {
884
+ return this->name;
885
+ }
886
+ }
887
+
888
+ instance = new Greeter("World");
889
+ pyclass = python::pythonize(instance);
890
+ parameter.return(pyclass);
891
+ ''')
892
+
893
+ # Now use it like a normal Python object!
894
+ print(greeter.name) # "World"
895
+ print(greeter.sayHello()) # "Hello, World!"
896
+ greeter.setName("Python")
897
+ print(greeter.getName()) # "Python"
898
+ print(greeter.name) # "Python"
899
+ ```
900
+
901
+ ### Aliases
902
+
903
+ - `python::pythonize(instance)` - Main function
904
+ - `python::wrap(instance)` - Alias
905
+ - `python::export(instance)` - Alias
906
+
907
+ All three do the same thing: wrap a CSSL class instance for Python use.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: IncludeCPP
3
- Version: 3.7.26
3
+ Version: 3.8.1
4
4
  Summary: Professional C++ Python bindings with type-generic templates, pystubs and native threading
5
5
  Home-page: https://github.com/liliassg/IncludeCPP
6
6
  Author: Lilias Hatterscheidt
@@ -853,3 +853,55 @@ cssl.run('''
853
853
  printl(@version);
854
854
  ''')
855
855
  ```
856
+
857
+ ## Return CSSL Classes to Python
858
+
859
+ Use `python::pythonize()` to convert CSSL class instances into Python-usable objects:
860
+
861
+ ```python
862
+ from includecpp import CSSL
863
+
864
+ cssl = CSSL.CsslLang()
865
+
866
+ # Create and return a CSSL class as a Python object
867
+ greeter = cssl.run('''
868
+ class Greeter {
869
+ string name;
870
+
871
+ Greeter(string n) {
872
+ this->name = n;
873
+ }
874
+
875
+ string sayHello() {
876
+ return "Hello, " + this->name + "!";
877
+ }
878
+
879
+ void setName(string newName) {
880
+ this->name = newName;
881
+ }
882
+
883
+ string getName() {
884
+ return this->name;
885
+ }
886
+ }
887
+
888
+ instance = new Greeter("World");
889
+ pyclass = python::pythonize(instance);
890
+ parameter.return(pyclass);
891
+ ''')
892
+
893
+ # Now use it like a normal Python object!
894
+ print(greeter.name) # "World"
895
+ print(greeter.sayHello()) # "Hello, World!"
896
+ greeter.setName("Python")
897
+ print(greeter.getName()) # "Python"
898
+ print(greeter.name) # "Python"
899
+ ```
900
+
901
+ ### Aliases
902
+
903
+ - `python::pythonize(instance)` - Main function
904
+ - `python::wrap(instance)` - Alias
905
+ - `python::export(instance)` - Alias
906
+
907
+ All three do the same thing: wrap a CSSL class instance for Python use.
@@ -818,4 +818,56 @@ cssl.run('''
818
818
  @log("Application started");
819
819
  printl(@version);
820
820
  ''')
821
- ```
821
+ ```
822
+
823
+ ## Return CSSL Classes to Python
824
+
825
+ Use `python::pythonize()` to convert CSSL class instances into Python-usable objects:
826
+
827
+ ```python
828
+ from includecpp import CSSL
829
+
830
+ cssl = CSSL.CsslLang()
831
+
832
+ # Create and return a CSSL class as a Python object
833
+ greeter = cssl.run('''
834
+ class Greeter {
835
+ string name;
836
+
837
+ Greeter(string n) {
838
+ this->name = n;
839
+ }
840
+
841
+ string sayHello() {
842
+ return "Hello, " + this->name + "!";
843
+ }
844
+
845
+ void setName(string newName) {
846
+ this->name = newName;
847
+ }
848
+
849
+ string getName() {
850
+ return this->name;
851
+ }
852
+ }
853
+
854
+ instance = new Greeter("World");
855
+ pyclass = python::pythonize(instance);
856
+ parameter.return(pyclass);
857
+ ''')
858
+
859
+ # Now use it like a normal Python object!
860
+ print(greeter.name) # "World"
861
+ print(greeter.sayHello()) # "Hello, World!"
862
+ greeter.setName("Python")
863
+ print(greeter.getName()) # "Python"
864
+ print(greeter.name) # "Python"
865
+ ```
866
+
867
+ ### Aliases
868
+
869
+ - `python::pythonize(instance)` - Main function
870
+ - `python::wrap(instance)` - Alias
871
+ - `python::export(instance)` - Alias
872
+
873
+ All three do the same thing: wrap a CSSL class instance for Python use.
@@ -2,7 +2,7 @@ from .core.cpp_api import CppApi
2
2
  from .core import cssl_bridge as CSSL
3
3
  import warnings
4
4
 
5
- __version__ = "3.7.26"
5
+ __version__ = "3.8.1"
6
6
  __all__ = ["CppApi", "CSSL"]
7
7
 
8
8
  # Module-level cache for C++ modules
@@ -7457,11 +7457,24 @@ def cssl():
7457
7457
  pass
7458
7458
 
7459
7459
 
7460
+ @cssl.command(name='run')
7461
+ @click.argument('path', required=False, type=click.Path())
7462
+ @click.option('--code', '-c', type=str, help='Execute code directly')
7463
+ def cssl_run(path, code):
7464
+ """Run/execute CSSL code or file."""
7465
+ _cssl_execute(path, code)
7466
+
7467
+
7460
7468
  @cssl.command(name='exec')
7461
7469
  @click.argument('path', required=False, type=click.Path())
7462
7470
  @click.option('--code', '-c', type=str, help='Execute code directly')
7463
7471
  def cssl_exec(path, code):
7464
- """Execute CSSL code or file."""
7472
+ """Execute CSSL code or file (alias for 'run')."""
7473
+ _cssl_execute(path, code)
7474
+
7475
+
7476
+ def _cssl_execute(path, code):
7477
+ """Internal: Execute CSSL code or file."""
7465
7478
  from pathlib import Path as PathLib
7466
7479
 
7467
7480
  try:
@@ -7923,16 +7936,18 @@ cli.add_command(cssl)
7923
7936
 
7924
7937
  @cli.command()
7925
7938
  @click.option('--force', '-f', is_flag=True, help='Force overwrite existing files')
7939
+ @click.option('--reinstall', '-r', is_flag=True, help='Reinstall extension (removes all versions first)')
7926
7940
  @click.option('--stubs-only', is_flag=True, help='Only update stubs, skip extension files')
7927
- def vscode(force, stubs_only):
7941
+ def vscode(force, reinstall, stubs_only):
7928
7942
  """Initialize or update VSCode configuration for IncludeCPP/CSSL.
7929
7943
 
7930
7944
  Installs CSSL extension globally and sets up project stubs.
7931
7945
 
7932
7946
  \b
7933
7947
  Usage:
7934
- includecpp vscode # Install/update extension + stubs
7935
- includecpp vscode --force # Force reinstall extension
7948
+ includecpp vscode # Install/update extension + stubs
7949
+ includecpp vscode --force # Force reinstall extension
7950
+ includecpp vscode --reinstall # Remove ALL versions & reinstall fresh
7936
7951
  includecpp vscode --stubs-only # Only update stubs
7937
7952
 
7938
7953
  \b
@@ -7999,13 +8014,18 @@ def vscode(force, stubs_only):
7999
8014
  target_dir = global_ext_dir / f'includecpp.cssl-{current_version}'
8000
8015
 
8001
8016
  # Check if already installed with same or older version
8002
- needs_install = force
8017
+ needs_install = force or reinstall
8003
8018
  existing_version = None
8004
8019
 
8005
8020
  # Find existing installations
8006
8021
  for existing in global_ext_dir.glob('includecpp.cssl-*'):
8007
8022
  existing_version = existing.name.split('-')[-1]
8008
- if existing_version != current_version:
8023
+ if reinstall:
8024
+ # --reinstall: Remove ALL versions
8025
+ click.echo(f" Removing version: {existing_version}")
8026
+ shutil.rmtree(existing)
8027
+ needs_install = True
8028
+ elif existing_version != current_version:
8009
8029
  # Remove old version
8010
8030
  click.echo(f" Removing old version: {existing_version}")
8011
8031
  shutil.rmtree(existing)
@@ -205,6 +205,11 @@ class CSSLBuiltins:
205
205
  self._functions['isavailable'] = self.builtin_isavailable
206
206
  self._functions['instance::exists'] = self.builtin_isavailable # Alias
207
207
 
208
+ # Python interop functions
209
+ self._functions['python::pythonize'] = self.builtin_python_pythonize
210
+ self._functions['python::wrap'] = self.builtin_python_pythonize # Alias
211
+ self._functions['python::export'] = self.builtin_python_pythonize # Alias
212
+
208
213
  # Regex functions
209
214
  self._functions['match'] = self.builtin_match
210
215
  self._functions['search'] = self.builtin_search
@@ -2445,6 +2450,211 @@ class CSSLBuiltins:
2445
2450
 
2446
2451
  return None
2447
2452
 
2453
+ # ============= Python Interop Functions =============
2454
+
2455
+ def builtin_python_pythonize(self, cssl_instance: Any) -> Any:
2456
+ """Convert a CSSL class instance to a Python-usable object.
2457
+
2458
+ This allows CSSL classes to be returned and used in Python code
2459
+ with proper attribute access and method calls.
2460
+
2461
+ Usage in CSSL:
2462
+ class Greeter {
2463
+ string name;
2464
+
2465
+ Greeter(string n) {
2466
+ this->name = n;
2467
+ }
2468
+
2469
+ string sayHello() {
2470
+ return "Hello, " + this->name + "!";
2471
+ }
2472
+
2473
+ void setName(string newName) {
2474
+ this->name = newName;
2475
+ }
2476
+
2477
+ string getName() {
2478
+ return this->name;
2479
+ }
2480
+ }
2481
+
2482
+ greeter = new Greeter("World");
2483
+ pyclass = python::pythonize(greeter);
2484
+ parameter.return(pyclass);
2485
+
2486
+ Usage in Python:
2487
+ from includecpp import CSSL
2488
+
2489
+ cssl = CSSL.CsslLang()
2490
+ greeter = cssl.run('''
2491
+ class Greeter { ... }
2492
+ g = new Greeter("World");
2493
+ parameter.return(python::pythonize(g));
2494
+ ''')
2495
+
2496
+ # Now use it like a normal Python object:
2497
+ print(greeter.name) # "World"
2498
+ print(greeter.sayHello()) # "Hello, World!"
2499
+ greeter.setName("Python")
2500
+ print(greeter.getName()) # "Python"
2501
+
2502
+ Args:
2503
+ cssl_instance: A CSSLInstance object (created via 'new ClassName()')
2504
+
2505
+ Returns:
2506
+ PythonizedCSSLInstance - A Python-friendly wrapper
2507
+ """
2508
+ from .cssl_types import CSSLInstance, CSSLClass
2509
+
2510
+ if cssl_instance is None:
2511
+ return None
2512
+
2513
+ # Already pythonized
2514
+ if isinstance(cssl_instance, PythonizedCSSLInstance):
2515
+ return cssl_instance
2516
+
2517
+ # Must be a CSSLInstance
2518
+ if not isinstance(cssl_instance, CSSLInstance):
2519
+ # If it's a dict, wrap it as a simple object
2520
+ if isinstance(cssl_instance, dict):
2521
+ return PythonizedDict(cssl_instance)
2522
+ # Return as-is for primitives
2523
+ return cssl_instance
2524
+
2525
+ return PythonizedCSSLInstance(cssl_instance, self.runtime)
2526
+
2527
+
2528
+ class PythonizedCSSLInstance:
2529
+ """Python wrapper for CSSL class instances.
2530
+
2531
+ Provides Pythonic attribute access and method calling for CSSL objects.
2532
+ """
2533
+
2534
+ def __init__(self, instance: Any, runtime: Any = None):
2535
+ # Use object.__setattr__ to avoid triggering our custom __setattr__
2536
+ object.__setattr__(self, '_cssl_instance', instance)
2537
+ object.__setattr__(self, '_cssl_runtime', runtime)
2538
+ object.__setattr__(self, '_cssl_class_name', instance._class.name if hasattr(instance, '_class') else 'Unknown')
2539
+
2540
+ def __getattr__(self, name: str) -> Any:
2541
+ """Get member or method from CSSL instance."""
2542
+ if name.startswith('_'):
2543
+ raise AttributeError(f"'{self._cssl_class_name}' has no attribute '{name}'")
2544
+
2545
+ instance = object.__getattribute__(self, '_cssl_instance')
2546
+ runtime = object.__getattribute__(self, '_cssl_runtime')
2547
+
2548
+ # Check for member variable first
2549
+ if instance.has_member(name):
2550
+ value = instance.get_member(name)
2551
+ # Recursively pythonize nested CSSL instances
2552
+ from .cssl_types import CSSLInstance
2553
+ if isinstance(value, CSSLInstance):
2554
+ return PythonizedCSSLInstance(value, runtime)
2555
+ return value
2556
+
2557
+ # Check for method
2558
+ method = instance.get_method(name)
2559
+ if method is not None:
2560
+ # Return a callable wrapper for the method
2561
+ return PythonizedMethod(instance, name, method, runtime)
2562
+
2563
+ raise AttributeError(f"'{self._cssl_class_name}' has no attribute '{name}'")
2564
+
2565
+ def __setattr__(self, name: str, value: Any) -> None:
2566
+ """Set member value on CSSL instance."""
2567
+ if name.startswith('_'):
2568
+ object.__setattr__(self, name, value)
2569
+ return
2570
+
2571
+ instance = object.__getattribute__(self, '_cssl_instance')
2572
+ instance.set_member(name, value)
2573
+
2574
+ def __repr__(self) -> str:
2575
+ class_name = object.__getattribute__(self, '_cssl_class_name')
2576
+ instance = object.__getattribute__(self, '_cssl_instance')
2577
+ members = list(instance._members.keys()) if hasattr(instance, '_members') else []
2578
+ return f"<PythonizedCSSL '{class_name}' members={members}>"
2579
+
2580
+ def __dir__(self) -> list:
2581
+ """List available attributes."""
2582
+ instance = object.__getattribute__(self, '_cssl_instance')
2583
+ members = list(instance._members.keys()) if hasattr(instance, '_members') else []
2584
+ methods = list(instance._class.methods.keys()) if hasattr(instance._class, 'methods') else []
2585
+ return members + methods
2586
+
2587
+ def _to_dict(self) -> dict:
2588
+ """Convert to Python dictionary."""
2589
+ instance = object.__getattribute__(self, '_cssl_instance')
2590
+ result = {}
2591
+ for name, value in instance._members.items():
2592
+ from .cssl_types import CSSLInstance
2593
+ if isinstance(value, CSSLInstance):
2594
+ result[name] = PythonizedCSSLInstance(value, None)._to_dict()
2595
+ else:
2596
+ result[name] = value
2597
+ return result
2598
+
2599
+
2600
+ class PythonizedMethod:
2601
+ """Wrapper that makes CSSL methods callable from Python."""
2602
+
2603
+ def __init__(self, instance: Any, method_name: str, method_ast: Any, runtime: Any):
2604
+ self._instance = instance
2605
+ self._method_name = method_name
2606
+ self._method_ast = method_ast
2607
+ self._runtime = runtime
2608
+
2609
+ def __call__(self, *args, **kwargs) -> Any:
2610
+ """Call the CSSL method with arguments."""
2611
+ if self._runtime is None:
2612
+ raise RuntimeError(f"Cannot call method '{self._method_name}' - no runtime available")
2613
+
2614
+ # Execute the method through the runtime
2615
+ # Pass the method AST node, not the method name
2616
+ result = self._runtime._call_method(self._instance, self._method_ast, list(args), kwargs)
2617
+
2618
+ # Pythonize the result if it's a CSSL instance
2619
+ from .cssl_types import CSSLInstance
2620
+ if isinstance(result, CSSLInstance):
2621
+ return PythonizedCSSLInstance(result, self._runtime)
2622
+
2623
+ return result
2624
+
2625
+ def __repr__(self) -> str:
2626
+ return f"<method '{self._method_name}' of '{self._instance._class.name}'>"
2627
+
2628
+
2629
+ class PythonizedDict:
2630
+ """Simple wrapper for dict objects with attribute access."""
2631
+
2632
+ def __init__(self, data: dict):
2633
+ object.__setattr__(self, '_data', data)
2634
+
2635
+ def __getattr__(self, name: str) -> Any:
2636
+ data = object.__getattribute__(self, '_data')
2637
+ if name in data:
2638
+ value = data[name]
2639
+ if isinstance(value, dict):
2640
+ return PythonizedDict(value)
2641
+ return value
2642
+ raise AttributeError(f"No attribute '{name}'")
2643
+
2644
+ def __setattr__(self, name: str, value: Any) -> None:
2645
+ if name.startswith('_'):
2646
+ object.__setattr__(self, name, value)
2647
+ return
2648
+ data = object.__getattribute__(self, '_data')
2649
+ data[name] = value
2650
+
2651
+ def __repr__(self) -> str:
2652
+ data = object.__getattribute__(self, '_data')
2653
+ return f"<PythonizedDict {data}>"
2654
+
2655
+ def _to_dict(self) -> dict:
2656
+ return object.__getattribute__(self, '_data')
2657
+
2448
2658
 
2449
2659
  # Module-level convenience functions
2450
2660
  _default_builtins: Optional[CSSLBuiltins] = None
@@ -2186,7 +2186,12 @@ class CSSLRuntime:
2186
2186
 
2187
2187
  if isinstance(target, ASTNode):
2188
2188
  if target.type == 'identifier':
2189
- self.scope.set(target.value, value)
2189
+ # Check if we're in a class method and this is a class member
2190
+ # If so, set the member instead of creating a local variable
2191
+ if self._current_instance is not None and self._current_instance.has_member(target.value):
2192
+ self._current_instance.set_member(target.value, value)
2193
+ else:
2194
+ self.scope.set(target.value, value)
2190
2195
  elif target.type == 'global_ref':
2191
2196
  # r@Name = value - store in promoted globals
2192
2197
  self._promoted_globals[target.value] = value
@@ -2303,6 +2308,9 @@ class CSSLRuntime:
2303
2308
 
2304
2309
  if node.type == 'literal':
2305
2310
  value = node.value
2311
+ # Handle dict-format literals from parser: {'type': 'int', 'value': 0}
2312
+ if isinstance(value, dict) and 'value' in value:
2313
+ value = value['value']
2306
2314
  # String interpolation - replace {var} or <var> with scope values
2307
2315
  if isinstance(value, str):
2308
2316
  has_fstring = '{' in value and '}' in value
@@ -2323,6 +2331,16 @@ class CSSLRuntime:
2323
2331
  if node.type == 'identifier':
2324
2332
  name = node.value
2325
2333
  value = self.scope.get(name)
2334
+ # Check if it's a class member in current instance context
2335
+ # This allows accessing members without 'this->' inside methods
2336
+ if value is None and self._current_instance is not None:
2337
+ if self._current_instance.has_member(name):
2338
+ value = self._current_instance.get_member(name)
2339
+ elif self._current_instance.has_method(name):
2340
+ # Return bound method
2341
+ method_node = self._current_instance.get_method(name)
2342
+ instance = self._current_instance
2343
+ value = lambda *args, **kwargs: self._call_method(instance, method_node, list(args), kwargs)
2326
2344
  # Fallback to global scope
2327
2345
  if value is None:
2328
2346
  value = self.global_scope.get(name)
@@ -2,7 +2,7 @@
2
2
  "name": "cssl",
3
3
  "displayName": "CSSL Language",
4
4
  "description": "Professional syntax highlighting, snippets, and language support for CSSL scripts (.cssl, .cssl-pl, .cssl-mod)",
5
- "version": "1.3.0",
5
+ "version": "1.3.1",
6
6
  "publisher": "IncludeCPP",
7
7
  "icon": "images/cssl.png",
8
8
  "engines": {
@@ -1164,5 +1164,43 @@
1164
1164
  "}"
1165
1165
  ],
1166
1166
  "description": "Function with selectable modifier combinations"
1167
+ },
1168
+ "Python Pythonize": {
1169
+ "prefix": ["python::pythonize", "pythonize"],
1170
+ "body": "python::pythonize(${1:instance})$0",
1171
+ "description": "Convert CSSL class instance to Python-usable object"
1172
+ },
1173
+ "Return Pythonized Class": {
1174
+ "prefix": "returnpython",
1175
+ "body": [
1176
+ "${1:instance} = new ${2:ClassName}(${3:args});",
1177
+ "pyobj = python::pythonize(${1});",
1178
+ "parameter.return(pyobj);"
1179
+ ],
1180
+ "description": "Create class instance and return as Python object"
1181
+ },
1182
+ "Class with Python Export": {
1183
+ "prefix": "pyclass",
1184
+ "body": [
1185
+ "class ${1:ClassName} {",
1186
+ "\t${2:string} ${3:name};",
1187
+ "",
1188
+ "\t${1}(${4:params}) {",
1189
+ "\t\tthis->${3} = ${5:value};",
1190
+ "\t}",
1191
+ "",
1192
+ "\t${6:string} get${3/(.*)/${1:/capitalize}/}() {",
1193
+ "\t\treturn this->${3};",
1194
+ "\t}",
1195
+ "",
1196
+ "\tvoid set${3/(.*)/${1:/capitalize}/}(${2} newValue) {",
1197
+ "\t\tthis->${3} = newValue;",
1198
+ "\t}",
1199
+ "}",
1200
+ "",
1201
+ "${7:obj} = new ${1}(${8:args});",
1202
+ "parameter.return(python::pythonize(${7}));$0"
1203
+ ],
1204
+ "description": "Create a class and export as Python object"
1167
1205
  }
1168
1206
  }
@@ -319,6 +319,14 @@
319
319
  {
320
320
  "name": "support.function.namespace.combo.cssl",
321
321
  "match": "\\bcombo::(filterdb|blocked|like)\\b"
322
+ },
323
+ {
324
+ "name": "support.function.namespace.python.cssl",
325
+ "match": "\\bpython::(pythonize|wrap|export)\\b"
326
+ },
327
+ {
328
+ "name": "support.function.namespace.filter.cssl",
329
+ "match": "\\bfilter::(register|unregister|list|exists)\\b"
322
330
  }
323
331
  ]
324
332
  },
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "IncludeCPP"
7
- version = "3.7.26"
7
+ version = "3.8.1"
8
8
  description = "Professional C++ Python bindings with type-generic templates, pystubs and native threading"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
File without changes
File without changes
File without changes
File without changes
File without changes