IncludeCPP 3.4.10__py3-none-any.whl → 3.5.0__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.
@@ -175,7 +289,12 @@ class CsslLang:
175
289
 
176
290
  return result
177
291
  except Exception as e:
178
- raise RuntimeError(f"CSSL Error: {e}") from e
292
+ # Format error message nicely
293
+ error_msg = str(e)
294
+ # Don't double-wrap error messages
295
+ if error_msg.startswith("CSSL Error:"):
296
+ raise RuntimeError(error_msg) from e
297
+ raise RuntimeError(f"CSSL Error:\n{error_msg}") from e
179
298
 
180
299
  def T_exec(self, path_or_code: str, *args, callback: Optional[Callable[[Any], None]] = None) -> threading.Thread:
181
300
  """
@@ -276,6 +395,255 @@ class CsslLang:
276
395
  """
277
396
  return CSSLFunctionModule(self, code)
278
397
 
398
+ def code(self, name: str, code: str) -> None:
399
+ """
400
+ Register inline CSSL code as a payload that can be loaded via payload().
401
+
402
+ This allows creating payloads from Python code without external files.
403
+
404
+ Usage:
405
+ from includecpp import CSSL
406
+ cssl = CSSL.CsslLang()
407
+
408
+ # Register a helper payload
409
+ cssl.code("helpers", '''
410
+ global version = "1.0.0";
411
+ void log(string msg) {
412
+ printl("[LOG] " + msg);
413
+ }
414
+ ''')
415
+
416
+ # Use it in CSSL code
417
+ cssl.exec('''
418
+ payload("helpers"); // Load the inline payload
419
+ @log("Hello!"); // Call the helper function
420
+ printl(@version); // Access the global
421
+ ''')
422
+
423
+ Args:
424
+ name: Name to register the payload under (used in payload("name"))
425
+ code: CSSL code string
426
+ """
427
+ runtime = self._get_runtime()
428
+ if not hasattr(runtime, '_inline_payloads'):
429
+ runtime._inline_payloads = {}
430
+ runtime._inline_payloads[name] = code
431
+
432
+ def share(self, instance: Any, name: str) -> str:
433
+ """
434
+ Share a Python object instance with CSSL scripts (LIVE sharing).
435
+
436
+ The object is stored as a LIVE reference - changes made in CSSL
437
+ will be reflected in the original Python object immediately.
438
+ Call share() again with the same name to update the shared object.
439
+
440
+ Usage in Python:
441
+ from includecpp import CSSL
442
+ cssl = CSSL.CsslLang()
443
+
444
+ # Share a Python object
445
+ class MyAPI:
446
+ def __init__(self):
447
+ self.counter = 0
448
+ def greet(self, name):
449
+ return f"Hello, {name}!"
450
+ def increment(self):
451
+ self.counter += 1
452
+
453
+ api = MyAPI()
454
+ cssl.share(api, "myapi")
455
+
456
+ # Use in CSSL - changes are LIVE!
457
+ cssl.exec('''
458
+ ob <== $myapi;
459
+ printl(ob.greet("World"));
460
+ ob.increment();
461
+ printl(ob.counter); // 1
462
+ ''')
463
+
464
+ # Changes reflect back to Python!
465
+ print(api.counter) # 1
466
+
467
+ Args:
468
+ instance: Python object to share
469
+ name: Name for the shared object (accessed as $name in CSSL)
470
+
471
+ Returns:
472
+ Path to the shared object marker file
473
+ """
474
+ global _live_objects
475
+ runtime = self._get_runtime()
476
+
477
+ # Initialize shared objects registry
478
+ if not hasattr(runtime, '_shared_objects'):
479
+ runtime._shared_objects = {}
480
+
481
+ # Generate unique filename: <name>.shareobj<7digits>
482
+ random_suffix = ''.join([str(random.randint(0, 9)) for _ in range(7)])
483
+ share_dir = _get_share_directory()
484
+ filepath = share_dir / f"{name}.shareobj{random_suffix}"
485
+
486
+ # Remove old file if updating
487
+ if name in runtime._shared_objects:
488
+ old_path = runtime._shared_objects[name]['path']
489
+ try:
490
+ Path(old_path).unlink(missing_ok=True)
491
+ except Exception:
492
+ pass
493
+
494
+ # Store LIVE object reference in global registry
495
+ _live_objects[name] = instance
496
+
497
+ # Write marker file with metadata (not the actual object)
498
+ import json
499
+ metadata = {
500
+ 'name': name,
501
+ 'type': type(instance).__name__,
502
+ 'live': True,
503
+ 'id': id(instance)
504
+ }
505
+ with open(filepath, 'w', encoding='utf-8') as f:
506
+ json.dump(metadata, f)
507
+
508
+ # Register in runtime
509
+ runtime._shared_objects[name] = {
510
+ 'path': str(filepath),
511
+ 'type': type(instance).__name__,
512
+ 'live': True
513
+ }
514
+
515
+ # Also register the live proxy in the runtime's scope for $name access
516
+ proxy = SharedObjectProxy(name, instance)
517
+ runtime.global_scope.set(f'${name}', proxy)
518
+
519
+ return str(filepath)
520
+
521
+ def unshare(self, name: str) -> bool:
522
+ """
523
+ Remove a shared object.
524
+
525
+ Args:
526
+ name: Name of the shared object to remove
527
+
528
+ Returns:
529
+ True if removed, False if not found
530
+ """
531
+ global _live_objects
532
+ runtime = self._get_runtime()
533
+
534
+ if not hasattr(runtime, '_shared_objects'):
535
+ return False
536
+
537
+ if name not in runtime._shared_objects:
538
+ return False
539
+
540
+ # Remove from live objects registry
541
+ if name in _live_objects:
542
+ del _live_objects[name]
543
+
544
+ # Remove from runtime scope
545
+ try:
546
+ runtime.global_scope.delete(f'${name}')
547
+ except Exception:
548
+ pass
549
+
550
+ # Remove marker file
551
+ filepath = runtime._shared_objects[name]['path']
552
+ try:
553
+ Path(filepath).unlink(missing_ok=True)
554
+ except Exception:
555
+ pass
556
+
557
+ del runtime._shared_objects[name]
558
+ return True
559
+
560
+ def get_shared(self, name: str) -> Optional[Any]:
561
+ """
562
+ Get a shared object by name (for Python-side access).
563
+
564
+ Returns the actual live object reference, not a copy.
565
+
566
+ Args:
567
+ name: Name of the shared object
568
+
569
+ Returns:
570
+ The live shared object or None if not found
571
+ """
572
+ global _live_objects
573
+
574
+ # Return live object if available
575
+ if name in _live_objects:
576
+ return _live_objects[name]
577
+
578
+ return None
579
+
580
+
581
+ # Global shared objects registry (for cross-instance sharing)
582
+ _global_shared_objects: Dict[str, str] = {}
583
+
584
+
585
+ def share(instance: Any, name: str) -> str:
586
+ """
587
+ Share a Python object globally for all CSSL instances (LIVE sharing).
588
+
589
+ Changes made through CSSL will reflect back to the original object.
590
+ """
591
+ global _live_objects
592
+
593
+ random_suffix = ''.join([str(random.randint(0, 9)) for _ in range(7)])
594
+ share_dir = _get_share_directory()
595
+ filepath = share_dir / f"{name}.shareobj{random_suffix}"
596
+
597
+ # Remove old file if updating
598
+ if name in _global_shared_objects:
599
+ try:
600
+ Path(_global_shared_objects[name]).unlink(missing_ok=True)
601
+ except Exception:
602
+ pass
603
+
604
+ # Store LIVE object reference
605
+ _live_objects[name] = instance
606
+
607
+ # Write marker file with metadata
608
+ import json
609
+ metadata = {
610
+ 'name': name,
611
+ 'type': type(instance).__name__,
612
+ 'live': True,
613
+ 'id': id(instance)
614
+ }
615
+ with open(filepath, 'w', encoding='utf-8') as f:
616
+ json.dump(metadata, f)
617
+
618
+ _global_shared_objects[name] = str(filepath)
619
+ return str(filepath)
620
+
621
+
622
+ def unshare(name: str) -> bool:
623
+ """Remove a globally shared object."""
624
+ global _live_objects
625
+
626
+ if name not in _global_shared_objects:
627
+ return False
628
+
629
+ # Remove from live objects
630
+ if name in _live_objects:
631
+ del _live_objects[name]
632
+
633
+ try:
634
+ Path(_global_shared_objects[name]).unlink(missing_ok=True)
635
+ except Exception:
636
+ pass
637
+
638
+ del _global_shared_objects[name]
639
+ return True
640
+
641
+
642
+ def get_shared(name: str) -> Optional[Any]:
643
+ """Get a globally shared object by name."""
644
+ global _live_objects
645
+ return _live_objects.get(name)
646
+
279
647
 
280
648
  # Singleton for convenience
281
649
  _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)) {
@@ -0,0 +1 @@
1
+ # VSCode extension resources for CSSL
@@ -0,0 +1 @@
1
+ # CSSL VSCode extension files
@@ -0,0 +1,38 @@
1
+ {
2
+ "comments": {
3
+ "lineComment": "//",
4
+ "blockComment": ["/*", "*/"]
5
+ },
6
+ "brackets": [
7
+ ["{", "}"],
8
+ ["[", "]"],
9
+ ["(", ")"],
10
+ ["<", ">"]
11
+ ],
12
+ "autoClosingPairs": [
13
+ { "open": "{", "close": "}" },
14
+ { "open": "[", "close": "]" },
15
+ { "open": "(", "close": ")" },
16
+ { "open": "<", "close": ">" },
17
+ { "open": "\"", "close": "\"", "notIn": ["string"] },
18
+ { "open": "'", "close": "'", "notIn": ["string", "comment"] }
19
+ ],
20
+ "surroundingPairs": [
21
+ ["{", "}"],
22
+ ["[", "]"],
23
+ ["(", ")"],
24
+ ["<", ">"],
25
+ ["\"", "\""],
26
+ ["'", "'"]
27
+ ],
28
+ "folding": {
29
+ "markers": {
30
+ "start": "^\\s*//\\s*#?region\\b",
31
+ "end": "^\\s*//\\s*#?endregion\\b"
32
+ }
33
+ },
34
+ "indentationRules": {
35
+ "increaseIndentPattern": "^.*\\{[^}]*$",
36
+ "decreaseIndentPattern": "^\\s*\\}"
37
+ }
38
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "cssl",
3
+ "displayName": "CSSL - CSO Service Script Language",
4
+ "description": "Syntax highlighting and language support for CSSL scripts",
5
+ "version": "1.0.0",
6
+ "publisher": "IncludeCPP",
7
+ "engines": {
8
+ "vscode": "^1.60.0"
9
+ },
10
+ "categories": [
11
+ "Programming Languages"
12
+ ],
13
+ "contributes": {
14
+ "languages": [
15
+ {
16
+ "id": "cssl",
17
+ "aliases": ["CSSL", "cssl", "CSO Service Script"],
18
+ "extensions": [".cssl", ".cssl-pl", ".cssl-mod"],
19
+ "configuration": "./language-configuration.json"
20
+ }
21
+ ],
22
+ "grammars": [
23
+ {
24
+ "language": "cssl",
25
+ "scopeName": "source.cssl",
26
+ "path": "./syntaxes/cssl.tmLanguage.json"
27
+ }
28
+ ]
29
+ }
30
+ }