IncludeCPP 3.4.10__py3-none-any.whl → 3.4.21__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.
@@ -3,11 +3,125 @@ CSSL Bridge - Python API for CSSL Language
3
3
  Provides CsslLang class for executing CSSL code from Python.
4
4
  """
5
5
 
6
+ import os
7
+ import pickle
8
+ import random
6
9
  import threading
7
10
  from pathlib import Path
8
11
  from typing import Any, List, Optional, Callable, Dict
9
12
 
10
13
 
14
+ def _get_share_directory() -> Path:
15
+ """Get the directory for shared objects."""
16
+ # Use APPDATA on Windows, ~/.config on Unix
17
+ if os.name == 'nt':
18
+ base = Path(os.environ.get('APPDATA', Path.home() / 'AppData' / 'Roaming'))
19
+ else:
20
+ base = Path(os.environ.get('XDG_CONFIG_HOME', Path.home() / '.config'))
21
+
22
+ share_dir = base / 'IncludeCPP' / 'shared_objects'
23
+ share_dir.mkdir(parents=True, exist_ok=True)
24
+ return share_dir
25
+
26
+
27
+ # Global live object registry - holds actual object references for live sharing
28
+ _live_objects: Dict[str, Any] = {}
29
+
30
+
31
+ class SharedObjectProxy:
32
+ """
33
+ Live proxy for accessing a shared Python object from CSSL.
34
+ Changes made through this proxy are reflected in the original object.
35
+ """
36
+
37
+ def __init__(self, name: str, obj: Any = None):
38
+ object.__setattr__(self, '_name', name)
39
+ object.__setattr__(self, '_direct_object', obj)
40
+
41
+ def _get_object(self):
42
+ """Get the live object reference."""
43
+ # First check direct object (same-instance sharing)
44
+ direct = object.__getattribute__(self, '_direct_object')
45
+ if direct is not None:
46
+ return direct
47
+
48
+ # Fall back to global registry
49
+ name = object.__getattribute__(self, '_name')
50
+ if name in _live_objects:
51
+ return _live_objects[name]
52
+
53
+ return None
54
+
55
+ def __getattr__(self, name: str):
56
+ """Access attributes/methods on the shared object."""
57
+ obj = self._get_object()
58
+ if obj is None:
59
+ obj_name = object.__getattribute__(self, '_name')
60
+ raise AttributeError(f"Shared object '${obj_name}' not available")
61
+
62
+ return getattr(obj, name)
63
+
64
+ def __setattr__(self, name: str, value: Any):
65
+ """Set attributes on the shared object (live update)."""
66
+ if name.startswith('_'):
67
+ object.__setattr__(self, name, value)
68
+ return
69
+
70
+ obj = self._get_object()
71
+ if obj is None:
72
+ obj_name = object.__getattribute__(self, '_name')
73
+ raise AttributeError(f"Shared object '${obj_name}' not available")
74
+
75
+ setattr(obj, name, value)
76
+
77
+ def __repr__(self):
78
+ obj = self._get_object()
79
+ name = object.__getattribute__(self, '_name')
80
+ return f"<SharedObject ${name} type={type(obj).__name__ if obj else 'None'}>"
81
+
82
+ def __call__(self, *args, **kwargs):
83
+ """Allow calling the object if it's callable."""
84
+ obj = self._get_object()
85
+ if obj is None:
86
+ name = object.__getattribute__(self, '_name')
87
+ raise TypeError(f"Shared object '${name}' not available")
88
+ if callable(obj):
89
+ return obj(*args, **kwargs)
90
+ name = object.__getattribute__(self, '_name')
91
+ raise TypeError(f"Shared object '${name}' is not callable")
92
+
93
+ def __getitem__(self, key):
94
+ """Allow indexing on the shared object."""
95
+ obj = self._get_object()
96
+ if obj is None:
97
+ name = object.__getattribute__(self, '_name')
98
+ raise KeyError(f"Shared object '${name}' not available")
99
+ return obj[key]
100
+
101
+ def __setitem__(self, key, value):
102
+ """Allow setting items on the shared object (live update)."""
103
+ obj = self._get_object()
104
+ if obj is None:
105
+ name = object.__getattribute__(self, '_name')
106
+ raise KeyError(f"Shared object '${name}' not available")
107
+ obj[key] = value
108
+
109
+ def __iter__(self):
110
+ """Allow iterating over the shared object."""
111
+ obj = self._get_object()
112
+ if obj is None:
113
+ name = object.__getattribute__(self, '_name')
114
+ raise TypeError(f"Shared object '${name}' not available")
115
+ return iter(obj)
116
+
117
+ def __len__(self):
118
+ """Get length of the shared object."""
119
+ obj = self._get_object()
120
+ if obj is None:
121
+ return 0
122
+ return len(obj)
123
+
124
+
11
125
  class CSSLModule:
12
126
  """
13
127
  A callable CSSL module that executes code with arguments.
@@ -276,6 +390,255 @@ class CsslLang:
276
390
  """
277
391
  return CSSLFunctionModule(self, code)
278
392
 
393
+ def code(self, name: str, code: str) -> None:
394
+ """
395
+ Register inline CSSL code as a payload that can be loaded via payload().
396
+
397
+ This allows creating payloads from Python code without external files.
398
+
399
+ Usage:
400
+ from includecpp import CSSL
401
+ cssl = CSSL.CsslLang()
402
+
403
+ # Register a helper payload
404
+ cssl.code("helpers", '''
405
+ global version = "1.0.0";
406
+ void log(string msg) {
407
+ printl("[LOG] " + msg);
408
+ }
409
+ ''')
410
+
411
+ # Use it in CSSL code
412
+ cssl.exec('''
413
+ payload("helpers"); // Load the inline payload
414
+ @log("Hello!"); // Call the helper function
415
+ printl(@version); // Access the global
416
+ ''')
417
+
418
+ Args:
419
+ name: Name to register the payload under (used in payload("name"))
420
+ code: CSSL code string
421
+ """
422
+ runtime = self._get_runtime()
423
+ if not hasattr(runtime, '_inline_payloads'):
424
+ runtime._inline_payloads = {}
425
+ runtime._inline_payloads[name] = code
426
+
427
+ def share(self, instance: Any, name: str) -> str:
428
+ """
429
+ Share a Python object instance with CSSL scripts (LIVE sharing).
430
+
431
+ The object is stored as a LIVE reference - changes made in CSSL
432
+ will be reflected in the original Python object immediately.
433
+ Call share() again with the same name to update the shared object.
434
+
435
+ Usage in Python:
436
+ from includecpp import CSSL
437
+ cssl = CSSL.CsslLang()
438
+
439
+ # Share a Python object
440
+ class MyAPI:
441
+ def __init__(self):
442
+ self.counter = 0
443
+ def greet(self, name):
444
+ return f"Hello, {name}!"
445
+ def increment(self):
446
+ self.counter += 1
447
+
448
+ api = MyAPI()
449
+ cssl.share(api, "myapi")
450
+
451
+ # Use in CSSL - changes are LIVE!
452
+ cssl.exec('''
453
+ ob <== $myapi;
454
+ printl(ob.greet("World"));
455
+ ob.increment();
456
+ printl(ob.counter); // 1
457
+ ''')
458
+
459
+ # Changes reflect back to Python!
460
+ print(api.counter) # 1
461
+
462
+ Args:
463
+ instance: Python object to share
464
+ name: Name for the shared object (accessed as $name in CSSL)
465
+
466
+ Returns:
467
+ Path to the shared object marker file
468
+ """
469
+ global _live_objects
470
+ runtime = self._get_runtime()
471
+
472
+ # Initialize shared objects registry
473
+ if not hasattr(runtime, '_shared_objects'):
474
+ runtime._shared_objects = {}
475
+
476
+ # Generate unique filename: <name>.shareobj<7digits>
477
+ random_suffix = ''.join([str(random.randint(0, 9)) for _ in range(7)])
478
+ share_dir = _get_share_directory()
479
+ filepath = share_dir / f"{name}.shareobj{random_suffix}"
480
+
481
+ # Remove old file if updating
482
+ if name in runtime._shared_objects:
483
+ old_path = runtime._shared_objects[name]['path']
484
+ try:
485
+ Path(old_path).unlink(missing_ok=True)
486
+ except Exception:
487
+ pass
488
+
489
+ # Store LIVE object reference in global registry
490
+ _live_objects[name] = instance
491
+
492
+ # Write marker file with metadata (not the actual object)
493
+ import json
494
+ metadata = {
495
+ 'name': name,
496
+ 'type': type(instance).__name__,
497
+ 'live': True,
498
+ 'id': id(instance)
499
+ }
500
+ with open(filepath, 'w', encoding='utf-8') as f:
501
+ json.dump(metadata, f)
502
+
503
+ # Register in runtime
504
+ runtime._shared_objects[name] = {
505
+ 'path': str(filepath),
506
+ 'type': type(instance).__name__,
507
+ 'live': True
508
+ }
509
+
510
+ # Also register the live proxy in the runtime's scope for $name access
511
+ proxy = SharedObjectProxy(name, instance)
512
+ runtime.global_scope.set(f'${name}', proxy)
513
+
514
+ return str(filepath)
515
+
516
+ def unshare(self, name: str) -> bool:
517
+ """
518
+ Remove a shared object.
519
+
520
+ Args:
521
+ name: Name of the shared object to remove
522
+
523
+ Returns:
524
+ True if removed, False if not found
525
+ """
526
+ global _live_objects
527
+ runtime = self._get_runtime()
528
+
529
+ if not hasattr(runtime, '_shared_objects'):
530
+ return False
531
+
532
+ if name not in runtime._shared_objects:
533
+ return False
534
+
535
+ # Remove from live objects registry
536
+ if name in _live_objects:
537
+ del _live_objects[name]
538
+
539
+ # Remove from runtime scope
540
+ try:
541
+ runtime.global_scope.delete(f'${name}')
542
+ except Exception:
543
+ pass
544
+
545
+ # Remove marker file
546
+ filepath = runtime._shared_objects[name]['path']
547
+ try:
548
+ Path(filepath).unlink(missing_ok=True)
549
+ except Exception:
550
+ pass
551
+
552
+ del runtime._shared_objects[name]
553
+ return True
554
+
555
+ def get_shared(self, name: str) -> Optional[Any]:
556
+ """
557
+ Get a shared object by name (for Python-side access).
558
+
559
+ Returns the actual live object reference, not a copy.
560
+
561
+ Args:
562
+ name: Name of the shared object
563
+
564
+ Returns:
565
+ The live shared object or None if not found
566
+ """
567
+ global _live_objects
568
+
569
+ # Return live object if available
570
+ if name in _live_objects:
571
+ return _live_objects[name]
572
+
573
+ return None
574
+
575
+
576
+ # Global shared objects registry (for cross-instance sharing)
577
+ _global_shared_objects: Dict[str, str] = {}
578
+
579
+
580
+ def share(instance: Any, name: str) -> str:
581
+ """
582
+ Share a Python object globally for all CSSL instances (LIVE sharing).
583
+
584
+ Changes made through CSSL will reflect back to the original object.
585
+ """
586
+ global _live_objects
587
+
588
+ random_suffix = ''.join([str(random.randint(0, 9)) for _ in range(7)])
589
+ share_dir = _get_share_directory()
590
+ filepath = share_dir / f"{name}.shareobj{random_suffix}"
591
+
592
+ # Remove old file if updating
593
+ if name in _global_shared_objects:
594
+ try:
595
+ Path(_global_shared_objects[name]).unlink(missing_ok=True)
596
+ except Exception:
597
+ pass
598
+
599
+ # Store LIVE object reference
600
+ _live_objects[name] = instance
601
+
602
+ # Write marker file with metadata
603
+ import json
604
+ metadata = {
605
+ 'name': name,
606
+ 'type': type(instance).__name__,
607
+ 'live': True,
608
+ 'id': id(instance)
609
+ }
610
+ with open(filepath, 'w', encoding='utf-8') as f:
611
+ json.dump(metadata, f)
612
+
613
+ _global_shared_objects[name] = str(filepath)
614
+ return str(filepath)
615
+
616
+
617
+ def unshare(name: str) -> bool:
618
+ """Remove a globally shared object."""
619
+ global _live_objects
620
+
621
+ if name not in _global_shared_objects:
622
+ return False
623
+
624
+ # Remove from live objects
625
+ if name in _live_objects:
626
+ del _live_objects[name]
627
+
628
+ try:
629
+ Path(_global_shared_objects[name]).unlink(missing_ok=True)
630
+ except Exception:
631
+ pass
632
+
633
+ del _global_shared_objects[name]
634
+ return True
635
+
636
+
637
+ def get_shared(name: str) -> Optional[Any]:
638
+ """Get a globally shared object by name."""
639
+ global _live_objects
640
+ return _live_objects.get(name)
641
+
279
642
 
280
643
  # Singleton for convenience
281
644
  _default_instance: Optional[CsslLang] = None
@@ -705,7 +705,7 @@ ModuleDescriptor API::parse_cp_file(const std::string& filepath) {
705
705
  std::ifstream source_file(desc.source_path);
706
706
  if (source_file.is_open()) {
707
707
  std::string line;
708
- std::regex include_regex(R"(^\s*#include\s*"([^"]+\.h(?:pp)?)")");
708
+ std::regex include_regex(R"re(^\s*#include\s*"([^"]+\.h(?:pp)?)")re");
709
709
  std::smatch match;
710
710
 
711
711
  while (std::getline(source_file, line)) {
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: IncludeCPP
3
- Version: 3.4.10
3
+ Version: 3.4.21
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
@@ -621,10 +621,277 @@ Then check **"Enable Experimental Features"** and save.
621
621
  - Have breaking changes between versions
622
622
  - Be removed or significantly changed
623
623
 
624
- Use at your own discretion. Report issues at: https://github.com/hatte/IncludeCPP/issues
624
+ Use at your own discretion. Report issues at: https://github.com/liliassg/IncludeCPP/issues
625
+
626
+ # CSSL - CSO Service Script Language
627
+
628
+ IncludeCPP includes CSSL, a scripting language with advanced data manipulation features.
629
+
630
+ ## Basic Usage
631
+
632
+ ```python
633
+ from includecpp import CSSL
634
+
635
+ # Execute CSSL code
636
+ CSSL.exec('''
637
+ printl("Hello from CSSL!");
638
+
639
+ int x = 10;
640
+ for (i in range(0, 5)) {
641
+ x = x + i;
642
+ }
643
+ printl(x);
644
+ ''')
645
+
646
+ # Execute with arguments
647
+ result = CSSL.exec('''
648
+ int a = parameter.get(0);
649
+ int b = parameter.get(1);
650
+ parameter.return(a + b);
651
+ ''', 5, 3)
652
+ print(result) # 8
653
+ ```
654
+
655
+ ## Live Object Sharing
656
+
657
+ Share Python objects with CSSL scripts. Changes in CSSL reflect back to Python:
658
+
659
+ ```python
660
+ from includecpp import CSSL
661
+
662
+ class Counter:
663
+ def __init__(self):
664
+ self.value = 100
665
+
666
+ counter = Counter()
667
+ cssl = CSSL.CsslLang()
668
+ cssl.share(counter, "cnt")
669
+
670
+ # Modify in CSSL - changes reflect in Python!
671
+ cssl.exec('''
672
+ $cnt.value = $cnt.value - 10;
673
+ printl($cnt.value); // 90
674
+ ''')
675
+
676
+ print(counter.value) # 90 - Changed!
677
+ ```
678
+
679
+ ### Shared Object Syntax
680
+
681
+ - `$name` - Access shared object
682
+ - `$name.property` - Access/modify properties
683
+ - `$name.method()` - Call methods
684
+ - `delete("name")` - Remove shared object
685
+
686
+ ## Data Types
687
+
688
+ ```cssl
689
+ // Basic types
690
+ int x = 42;
691
+ float pi = 3.14;
692
+ string name = "CSSL";
693
+ bool active = true;
694
+
695
+ // Collections
696
+ array<int> arr;
697
+ arr.push(1);
698
+ arr.push(2);
699
+ printl(arr.length()); // 2
700
+
701
+ vector<string> vec;
702
+ vec.push("A");
703
+ vec.push("B");
704
+
705
+ stack<int> s;
706
+ s.push(10);
707
+ s.pop();
708
+ ```
709
+
710
+ ## Control Flow
711
+
712
+ ```cssl
713
+ // If/elif/else
714
+ if (x > 10) {
715
+ printl("big");
716
+ } elif (x > 5) {
717
+ printl("medium");
718
+ } else {
719
+ printl("small");
720
+ }
721
+
722
+ // For loops
723
+ for (i in range(0, 10)) {
724
+ printl(i);
725
+ }
726
+
727
+ for (i in range(0, 10, 2)) { // with step
728
+ printl(i); // 0, 2, 4, 6, 8
729
+ }
730
+
731
+ // Foreach
732
+ array<string> items;
733
+ items.push("A");
734
+ items.push("B");
735
+ foreach (item in items) {
736
+ printl(item);
737
+ }
738
+
739
+ // While
740
+ int count = 0;
741
+ while (count < 5) {
742
+ printl(count);
743
+ count = count + 1;
744
+ }
745
+ ```
746
+
747
+ ## Functions
748
+
749
+ ```cssl
750
+ // Basic function
751
+ void greet(string name) {
752
+ printl("Hello, " + name + "!");
753
+ }
754
+
755
+ // Return value
756
+ int add(int a, int b) {
757
+ return a + b;
758
+ }
759
+
760
+ // Global variables
761
+ global version = "1.0.0";
762
+ printl(@version);
763
+
764
+ // r@ syntax for global declaration
765
+ r@myGlobal = "value";
766
+ printl(@myGlobal);
767
+ ```
768
+
769
+ ## BruteForce Injection System
770
+
771
+ CSSL's unique injection operators for data manipulation:
772
+
773
+ ```cssl
774
+ // <== Move data (replaces target)
775
+ target <== source;
776
+
777
+ // +<== Copy & add to target
778
+ target +<== source;
779
+
780
+ // -<== Move & remove from source
781
+ target -<== source;
782
+
783
+ // <<== Code infusion into functions
784
+ myFunc() <<== {
785
+ printl("Injected code!");
786
+ };
787
+
788
+ // +<<== Add code without replacing
789
+ myFunc() +<<== {
790
+ printl("Additional code!");
791
+ };
792
+ ```
793
+
794
+ ## String Methods
795
+
796
+ ```cssl
797
+ string s = "Hello World";
798
+
799
+ // Methods
800
+ s.length(); // 11
801
+ s.toUpper(); // "HELLO WORLD"
802
+ s.toLower(); // "hello world"
803
+ s.contains("World"); // true
804
+ s.startsWith("Hello"); // true
805
+ s.endsWith("World"); // true
806
+ s.replace("World", "CSSL");
807
+ s.split(" "); // ["Hello", "World"]
808
+ s.trim(); // Remove whitespace
809
+ s.substring(0, 5); // "Hello"
810
+ ```
811
+
812
+ ## CSSL Modules
813
+
814
+ ```python
815
+ # Create callable module
816
+ module = CSSL.module('''
817
+ string name = parameter.get(0);
818
+ printl("Hello, " + name + "!");
819
+ ''')
820
+ module("World") # Prints: Hello, World!
821
+
822
+ # Create module with functions
823
+ math_mod = CSSL.makemodule('''
824
+ int add(int a, int b) {
825
+ return a + b;
826
+ }
827
+
828
+ int multiply(int a, int b) {
829
+ return a * b;
830
+ }
831
+ ''')
832
+ print(math_mod.add(2, 3)) # 5
833
+ print(math_mod.multiply(4, 5)) # 20
834
+ ```
835
+
836
+ ## Inline Payloads
837
+
838
+ ```python
839
+ cssl = CSSL.CsslLang()
840
+
841
+ # Register code as payload
842
+ cssl.code("helpers", '''
843
+ global version = "1.0.0";
844
+ void log(string msg) {
845
+ printl("[LOG] " + msg);
846
+ }
847
+ ''')
848
+
849
+ # Use in CSSL
850
+ cssl.exec('''
851
+ payload("helpers");
852
+ @log("Application started");
853
+ printl(@version);
854
+ ''')
855
+ ```
625
856
 
626
857
  # Changelog
627
858
 
859
+ ## v3.4.20
860
+ - **Documentation:**
861
+ - Added complete CSSL language documentation
862
+ - Live object sharing with `$name` syntax
863
+ - Data types, control flow, functions, injection system
864
+ - String methods, modules, and inline payloads
865
+
866
+ ## v3.4.19
867
+ - **Critical Bug Fixes:**
868
+ - Fixed generator raw string literal in parser.cpp (regex pattern with `)"` prematurely terminated)
869
+ - Fixed shared object property writes inside loops not persisting to Python
870
+ - Added member_access handling in flow operations for shared objects
871
+
872
+ ## v3.4.18
873
+ - **Bug Fix:**
874
+ - Attempted fix for shared object loop writes (partially fixed)
875
+
876
+ ## v3.4.17
877
+ - **New Feature: Live Object Sharing**
878
+ - `cssl.share(instance, name)` - Share Python objects with CSSL
879
+ - `$name` syntax for accessing shared objects
880
+ - Live bidirectional updates - changes in CSSL reflect in Python
881
+ - `delete("name")` builtin for removing shared objects
882
+ - Shared object metadata stored in `%APPDATA%/IncludeCPP/shared_objects/`
883
+
884
+ ## v3.4.16
885
+ - **CSSL Bug Fixes:**
886
+ - Fixed `startsWith()` and `endsWith()` parser errors
887
+
888
+ ## v3.4.15
889
+ - **CSSL Enhancements:**
890
+ - Added `elif` keyword support
891
+ - Added `range(start, end, step)` with step parameter
892
+ - Added `begin()` and `end()` methods to all collection types
893
+ - Added `cssl.code(name, code)` for inline payload registration
894
+
628
895
  ## v3.4.2
629
896
  - **New Feature: `exec` Command**
630
897
  - Interactive REPL for quick code testing without creating files
@@ -806,4 +1073,4 @@ Use at your own discretion. Report issues at: https://github.com/hatte/IncludeCP
806
1073
 
807
1074
  ---
808
1075
 
809
- MIT License | v3.4.2 | [GitHub](https://github.com/liliassg/IncludeCPP)
1076
+ MIT License | v3.4.20 | [GitHub](https://github.com/liliassg/IncludeCPP)