pydorust 0.1.0__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 (70) hide show
  1. pydorust-0.1.0/.forgejo/workflows/ci.yml +42 -0
  2. pydorust-0.1.0/.forgejo/workflows/release.yml +27 -0
  3. pydorust-0.1.0/.gitignore +17 -0
  4. pydorust-0.1.0/.python-version +1 -0
  5. pydorust-0.1.0/PKG-INFO +213 -0
  6. pydorust-0.1.0/README.md +195 -0
  7. pydorust-0.1.0/flake.lock +61 -0
  8. pydorust-0.1.0/flake.nix +35 -0
  9. pydorust-0.1.0/pydorust/__init__.py +28 -0
  10. pydorust-0.1.0/pydorust/_internals/__init__.py +10 -0
  11. pydorust-0.1.0/pydorust/_internals/num_macros.py +173 -0
  12. pydorust-0.1.0/pydorust/_internals/num_macros.pyi +15 -0
  13. pydorust-0.1.0/pydorust/adt.py +72 -0
  14. pydorust-0.1.0/pydorust/lock/__init__.py +15 -0
  15. pydorust-0.1.0/pydorust/lock/cell.py +16 -0
  16. pydorust-0.1.0/pydorust/lock/lazy_lock.py +26 -0
  17. pydorust-0.1.0/pydorust/lock/once_lock.py +25 -0
  18. pydorust-0.1.0/pydorust/lock/ref_cell.py +61 -0
  19. pydorust-0.1.0/pydorust/lock/weak.py +14 -0
  20. pydorust-0.1.0/pydorust/macros/__init__.py +18 -0
  21. pydorust-0.1.0/pydorust/macros/__main__.py +205 -0
  22. pydorust-0.1.0/pydorust/macros/builtins/__init__.py +31 -0
  23. pydorust-0.1.0/pydorust/macros/builtins/comptime.py +29 -0
  24. pydorust-0.1.0/pydorust/macros/builtins/declarative.py +123 -0
  25. pydorust-0.1.0/pydorust/macros/builtins/delete.py +20 -0
  26. pydorust-0.1.0/pydorust/macros/builtins/env.py +24 -0
  27. pydorust-0.1.0/pydorust/macros/builtins/ident.py +26 -0
  28. pydorust-0.1.0/pydorust/macros/builtins/include.py +50 -0
  29. pydorust-0.1.0/pydorust/macros/builtins/meta.py +46 -0
  30. pydorust-0.1.0/pydorust/macros/builtins/quote.py +18 -0
  31. pydorust-0.1.0/pydorust/macros/builtins/str.py +14 -0
  32. pydorust-0.1.0/pydorust/macros/call.py +27 -0
  33. pydorust-0.1.0/pydorust/macros/context.py +133 -0
  34. pydorust-0.1.0/pydorust/macros/expander.py +30 -0
  35. pydorust-0.1.0/pydorust/macros/importer.py +85 -0
  36. pydorust-0.1.0/pydorust/macros/macro.py +12 -0
  37. pydorust-0.1.0/pydorust/macros/registry.py +11 -0
  38. pydorust-0.1.0/pydorust/macros/sandbox.py +30 -0
  39. pydorust-0.1.0/pydorust/macros/transformer.py +288 -0
  40. pydorust-0.1.0/pydorust/mem.py +57 -0
  41. pydorust-0.1.0/pydorust/num.py +29 -0
  42. pydorust-0.1.0/pydorust/num.pyi +266 -0
  43. pydorust-0.1.0/pydorust/panics.py +46 -0
  44. pydorust-0.1.0/pydorust/plugins/__init__.py +0 -0
  45. pydorust-0.1.0/pydorust/plugins/hatch.py +68 -0
  46. pydorust-0.1.0/pydorust/plugins/pytest.py +11 -0
  47. pydorust-0.1.0/pydorust/py.typed +0 -0
  48. pydorust-0.1.0/pydorust/sync/__init__.py +10 -0
  49. pydorust-0.1.0/pydorust/sync/mutex.py +53 -0
  50. pydorust-0.1.0/pydorust/sync/rw_lock.py +100 -0
  51. pydorust-0.1.0/pydorust/trait/__init__.py +11 -0
  52. pydorust-0.1.0/pydorust/trait/constants.py +5 -0
  53. pydorust-0.1.0/pydorust/trait/core.py +172 -0
  54. pydorust-0.1.0/pydorust/trait/decorators.py +111 -0
  55. pydorust-0.1.0/pydorust/types/__init__.py +16 -0
  56. pydorust-0.1.0/pydorust/types/iter.py +127 -0
  57. pydorust-0.1.0/pydorust/types/option.py +108 -0
  58. pydorust-0.1.0/pydorust/types/result.py +139 -0
  59. pydorust-0.1.0/pydorust/unsafe.py +319 -0
  60. pydorust-0.1.0/pydorust/utilities.py +36 -0
  61. pydorust-0.1.0/pyproject.toml +55 -0
  62. pydorust-0.1.0/scratch/expanded_num.py +1464 -0
  63. pydorust-0.1.0/scripts/generate_unsafe.py +61 -0
  64. pydorust-0.1.0/tests/conftest.py +13 -0
  65. pydorust-0.1.0/tests/test_lock.py +98 -0
  66. pydorust-0.1.0/tests/test_num.py +98 -0
  67. pydorust-0.1.0/tests/test_option.py +155 -0
  68. pydorust-0.1.0/tests/test_result.py +182 -0
  69. pydorust-0.1.0/tests/test_sync.py +82 -0
  70. pydorust-0.1.0/uv.lock +313 -0
@@ -0,0 +1,42 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - name: Checkout code
14
+ uses: actions/checkout@v4
15
+
16
+ - name: Install uv
17
+ uses: astral-sh/setup-uv@v3
18
+ with:
19
+ version: "latest"
20
+ enable-cache: true
21
+
22
+ - name: Set up Python
23
+ uses: actions/setup-python@v5
24
+ with:
25
+ python-version-file: ".python-version"
26
+
27
+ - name: Install dependencies
28
+ run: uv sync --all-extras --dev
29
+
30
+ - name: Run Ruff
31
+ run: uv run ruff check .
32
+
33
+ - name: Run Mypy
34
+ run: uv run mypy rustipy
35
+
36
+ - name: Run Pylint
37
+ run: uv run pylint rustipy
38
+
39
+ - name: Run Tests with Coverage
40
+ run: uv run pytest --cov=rustipy --cov-report=xml
41
+ env:
42
+ PYTHONPATH: .
@@ -0,0 +1,27 @@
1
+ name: Publish Package
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ jobs:
9
+ build-and-publish:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - name: Checkout code
13
+ uses: actions/checkout@v4
14
+
15
+ - name: Install uv
16
+ uses: astral-sh/setup-uv@v3
17
+
18
+ - name: Set up Python
19
+ uses: actions/setup-python@v5
20
+ with:
21
+ python-version-file: ".python-version"
22
+
23
+ - name: Build package
24
+ run: uv build
25
+
26
+ - name: Publish to PyPI
27
+ run: uv publish --token ${{ secrets.PYPI_TOKEN }}
@@ -0,0 +1,17 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+ *_cache
9
+
10
+ # Virtual environments
11
+ .venv
12
+
13
+ # other
14
+ .envrc
15
+ .direnv
16
+ .coverage
17
+ .vscode
@@ -0,0 +1 @@
1
+ 3.10
@@ -0,0 +1,213 @@
1
+ Metadata-Version: 2.5
2
+ Name: pydorust
3
+ Version: 0.1.0
4
+ Summary: A Python library inspired by Rust
5
+ Project-URL: Homepage, https://git.ruject.fun/RuJect/pydorust
6
+ Project-URL: Repository, https://git.ruject.fun/RuJect/pydorust.git
7
+ Project-URL: Issues, https://git.ruject.fun/RuJect/pydorust/issues
8
+ Author-email: rus07tam <rus07tam+contact@ruject.fun>
9
+ License: MIT
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Requires-Python: >=3.10
14
+ Requires-Dist: exceptiongroup>=1.3.1
15
+ Requires-Dist: pytest>=9.1.1
16
+ Requires-Dist: typing-extensions>=4.16.0
17
+ Description-Content-Type: text/markdown
18
+
19
+ # pydorust
20
+
21
+ A Python library bringing Rust programming language paradigms, semantics, and strict typing patterns to Python. Rather than attempting to enforce strict physical memory safety (which is fundamentally limited by Python's nature), `pydorust` is designed to provide familiar Rust semantics and structural patterns like macros, traits, algebraic data types, strict error handling (panics, `Option`, `Result`), and semantic synchronization primitives.
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ pip install pydorust
27
+ ```
28
+
29
+ ---
30
+
31
+ ## The Macro System (`pydorust.macros`)
32
+
33
+ The Macro system brings advanced, abstract metaprogramming to Python, conceptually similar to Rust's macro system. It allows you to transform syntax and generate code dynamically in a secure environment.
34
+
35
+ ### CLI & Plugins
36
+
37
+ Macros can be evaluated dynamically at runtime, but their true power shines when transforming the Python AST prior to execution. `pydorust` includes a dedicated CLI utility (`python -m pydorust.macros`) and plugins (for `hatch` and `pytest`) to seamlessly expand macros as part of your build step or test suite.
38
+
39
+ ### Core Macro APIs
40
+
41
+ - **`@m_define`**: The standard decorator used to register an AST macro. It takes a function that accepts a `MacroContext` and AST nodes, and returns transformed AST nodes. This is an imperative way to write macros (directly mutating AST).
42
+ - **`@m_define_declarative`**: A specialized, built-in macro used to define *other* macros declaratively using a template approach (inspired by Rust's `macro_rules!`). You write a standard Python function body where arguments act as variables. In the template body, variable references prefixed with `__q_` (e.g., `__q_myvar`) are replaced dynamically by the AST inputs.
43
+ - **`@m_decorator`**: A helper that wraps a macro so it can be used directly as a standard Python decorator. Functionally similar to `m_derive`, but utilizes native Python decorator syntax to pass the decorated function/class as the node.
44
+ - **`m_derive`**: Invokes a macro and automatically passes the *next* AST node (the one immediately following the `m_derive` call) as the primary node, alongside any additional arguments.
45
+ - **`m_call`**: Directly invokes a macro with the provided arguments, where the very first argument explicitly acts as the AST node.
46
+
47
+ ### Example: Defining a Custom Macro
48
+
49
+ ```python
50
+ import ast
51
+ from pydorust.macros import m_define, MacroContext, MacroResult
52
+
53
+ @m_define
54
+ def compile_error(ctx: MacroContext, node: ast.AST, /, *args: ast.AST) -> MacroResult:
55
+ # Extracts the string literal argument passed to the macro
56
+ msg = ctx.except_literal(str, node)
57
+ raise RuntimeError(
58
+ f"Compile Error at {ctx.filename}:{getattr(node, 'lineno', 1)}: {msg}"
59
+ )
60
+
61
+ # When expanded via CLI, plugins, or m_call, this raises an error based on the AST provided.
62
+ ```
63
+
64
+ ---
65
+
66
+ ## Traits System (`pydorust.trait`)
67
+
68
+ `pydorust` introduces Rust-style **Traits**, allowing you to decouple method definitions from class inheritance. This enables true ad-hoc polymorphism.
69
+
70
+ - **`Trait`**: The base class for defining new traits. Use decorators like `@trait_method` (for requirements) and `@default_method` (for defaults).
71
+ - **`@impl`**: Implements a trait for a specific data type.
72
+
73
+ ### Example: Creating and Implementing a Trait
74
+
75
+ ```python
76
+ from pydorust.trait import Trait, impl, trait_method, default_method
77
+
78
+ class Display(Trait):
79
+ @trait_method
80
+ def fmt(self) -> str:
81
+ """Required method for formatting."""
82
+
83
+ @default_method
84
+ def print(self) -> None:
85
+ """Default provided method."""
86
+ print(self.fmt())
87
+
88
+ # Implement `Display` for the built-in `int` type!
89
+ @impl(Display, for_type=int)
90
+ class IntDisplay:
91
+ def fmt(self: int) -> str:
92
+ return f"Integer value: {self}"
93
+
94
+ # Call the trait method directly
95
+ Display.print(42) # Outputs: Integer value: 42
96
+ ```
97
+
98
+ ---
99
+
100
+ ## Types (`pydorust.types`)
101
+
102
+ Rust is famous for eliminating `NullReferenceException` using the `Option` enum and handling errors gracefully using `Result`. `pydorust` implements these explicitly.
103
+
104
+ ### `Option` (Replacing `None`)
105
+
106
+ ```python
107
+ from pydorust.types import Option, Some, Null, ret_option
108
+
109
+ # Using a decorator to convert returns of None into `Null`, and values into `Some`
110
+ @ret_option
111
+ def divide(a: float, b: float) -> float | None:
112
+ if b == 0.0:
113
+ return None
114
+ return a / b
115
+
116
+ result: Option[float] = divide(10.0, 2.0)
117
+ print(result.unwrap_or(0.0)) # 5.0
118
+
119
+ bad_result = divide(10.0, 0.0)
120
+ print(bad_result.is_null()) # True
121
+ ```
122
+
123
+ ### `Result` (Replacing Exceptions)
124
+
125
+ The `Result` module provides `Ok(value)` and `Err(error)`, along with combinators like `.map()`, `.and_then()`, and `.unwrap()` to cleanly chain operations that might fail without massive `try/except` blocks.
126
+
127
+ ---
128
+
129
+ ## Thread Synchronization (`pydorust.sync`)
130
+
131
+ Provides semantic synchronization primitives mirroring Rust's standard library. While these tools cannot physically isolate or protect the inner state of Python objects from being mutated externally, they enforce semantic structure. By utilizing Context Managers as guards, `pydorust` helps prevent lock leaks and logically synchronizes your concurrent code.
132
+
133
+ ### Example: `Mutex`
134
+
135
+ ```python
136
+ import threading
137
+ from pydorust.sync import Mutex
138
+
139
+ # Wrap the data inside the Mutex
140
+ data = Mutex([1, 2, 3])
141
+
142
+ def worker():
143
+ # .lock() returns a MutexGuard. The lock is released when the block exits.
144
+ with data.lock() as guard:
145
+ guard.value.append(4)
146
+
147
+ t = threading.Thread(target=worker)
148
+ t.start(); t.join()
149
+
150
+ with data.lock() as guard:
151
+ print(guard.value) # [1, 2, 3, 4]
152
+ ```
153
+
154
+ *(Also includes `RwLock` for multi-reader / single-writer scenarios).*
155
+
156
+ ---
157
+
158
+ ## Algebraic Data Types (`pydorust.adt`)
159
+
160
+ Using the `Variant` and `Enum` classes, you can build tagged unions/variants to guarantee data shapes securely.
161
+
162
+ ### Example
163
+
164
+ ```python
165
+ from pydorust.adt import Variant, Enum
166
+
167
+ class Point2D(Variant):
168
+ x: int
169
+ y: int
170
+
171
+ class Point3D(Variant):
172
+ x: int
173
+ y: int
174
+ z: int
175
+
176
+ class ShapePoint(Enum):
177
+ D2 = Point2D
178
+ D3 = Point3D
179
+
180
+ p = ShapePoint.D2(x=10, y=20)
181
+ print(isinstance(p, ShapePoint)) # True
182
+ ```
183
+
184
+ ---
185
+
186
+ ## Other Features
187
+
188
+ ### Unrecoverable Errors (`pydorust.panics`)
189
+
190
+ Provides deterministic app termination for unrecoverable states.
191
+
192
+ - `panic("message")`: Immediately terminates the execution.
193
+ - `unimplemented()`: Drop-in for missing functionality (crashes if reached).
194
+ - `unreachable()`: For code paths that logically shouldn't be executed.
195
+
196
+ ### Unsafe Markers (`pydorust.unsafe`)
197
+
198
+ In Rust, dangerous operations that break memory safety guarantees must be wrapped in `unsafe {}`. `pydorust` emulates this semantic contract using decorators.
199
+
200
+ ```python
201
+ from pydorust.unsafe import unsafe_func, unsafe_call
202
+
203
+ @unsafe_func
204
+ def dangerous_operation():
205
+ print("Doing something unsafe...")
206
+
207
+ # dangerous_operation() # type error
208
+ unsafe_call(dangerous_operation)
209
+ ```
210
+
211
+ ### Low-Level Memory (`pydorust.mem`)
212
+
213
+ Exposes `unsafe` wrappers around `ctypes.pythonapi` memory management tools, granting you direct control over allocations with `alloc(size)` and `free(ptr)`. Always use carefully via `RawBuffer` or explicit `unsafe_call`.
@@ -0,0 +1,195 @@
1
+ # pydorust
2
+
3
+ A Python library bringing Rust programming language paradigms, semantics, and strict typing patterns to Python. Rather than attempting to enforce strict physical memory safety (which is fundamentally limited by Python's nature), `pydorust` is designed to provide familiar Rust semantics and structural patterns like macros, traits, algebraic data types, strict error handling (panics, `Option`, `Result`), and semantic synchronization primitives.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install pydorust
9
+ ```
10
+
11
+ ---
12
+
13
+ ## The Macro System (`pydorust.macros`)
14
+
15
+ The Macro system brings advanced, abstract metaprogramming to Python, conceptually similar to Rust's macro system. It allows you to transform syntax and generate code dynamically in a secure environment.
16
+
17
+ ### CLI & Plugins
18
+
19
+ Macros can be evaluated dynamically at runtime, but their true power shines when transforming the Python AST prior to execution. `pydorust` includes a dedicated CLI utility (`python -m pydorust.macros`) and plugins (for `hatch` and `pytest`) to seamlessly expand macros as part of your build step or test suite.
20
+
21
+ ### Core Macro APIs
22
+
23
+ - **`@m_define`**: The standard decorator used to register an AST macro. It takes a function that accepts a `MacroContext` and AST nodes, and returns transformed AST nodes. This is an imperative way to write macros (directly mutating AST).
24
+ - **`@m_define_declarative`**: A specialized, built-in macro used to define *other* macros declaratively using a template approach (inspired by Rust's `macro_rules!`). You write a standard Python function body where arguments act as variables. In the template body, variable references prefixed with `__q_` (e.g., `__q_myvar`) are replaced dynamically by the AST inputs.
25
+ - **`@m_decorator`**: A helper that wraps a macro so it can be used directly as a standard Python decorator. Functionally similar to `m_derive`, but utilizes native Python decorator syntax to pass the decorated function/class as the node.
26
+ - **`m_derive`**: Invokes a macro and automatically passes the *next* AST node (the one immediately following the `m_derive` call) as the primary node, alongside any additional arguments.
27
+ - **`m_call`**: Directly invokes a macro with the provided arguments, where the very first argument explicitly acts as the AST node.
28
+
29
+ ### Example: Defining a Custom Macro
30
+
31
+ ```python
32
+ import ast
33
+ from pydorust.macros import m_define, MacroContext, MacroResult
34
+
35
+ @m_define
36
+ def compile_error(ctx: MacroContext, node: ast.AST, /, *args: ast.AST) -> MacroResult:
37
+ # Extracts the string literal argument passed to the macro
38
+ msg = ctx.except_literal(str, node)
39
+ raise RuntimeError(
40
+ f"Compile Error at {ctx.filename}:{getattr(node, 'lineno', 1)}: {msg}"
41
+ )
42
+
43
+ # When expanded via CLI, plugins, or m_call, this raises an error based on the AST provided.
44
+ ```
45
+
46
+ ---
47
+
48
+ ## Traits System (`pydorust.trait`)
49
+
50
+ `pydorust` introduces Rust-style **Traits**, allowing you to decouple method definitions from class inheritance. This enables true ad-hoc polymorphism.
51
+
52
+ - **`Trait`**: The base class for defining new traits. Use decorators like `@trait_method` (for requirements) and `@default_method` (for defaults).
53
+ - **`@impl`**: Implements a trait for a specific data type.
54
+
55
+ ### Example: Creating and Implementing a Trait
56
+
57
+ ```python
58
+ from pydorust.trait import Trait, impl, trait_method, default_method
59
+
60
+ class Display(Trait):
61
+ @trait_method
62
+ def fmt(self) -> str:
63
+ """Required method for formatting."""
64
+
65
+ @default_method
66
+ def print(self) -> None:
67
+ """Default provided method."""
68
+ print(self.fmt())
69
+
70
+ # Implement `Display` for the built-in `int` type!
71
+ @impl(Display, for_type=int)
72
+ class IntDisplay:
73
+ def fmt(self: int) -> str:
74
+ return f"Integer value: {self}"
75
+
76
+ # Call the trait method directly
77
+ Display.print(42) # Outputs: Integer value: 42
78
+ ```
79
+
80
+ ---
81
+
82
+ ## Types (`pydorust.types`)
83
+
84
+ Rust is famous for eliminating `NullReferenceException` using the `Option` enum and handling errors gracefully using `Result`. `pydorust` implements these explicitly.
85
+
86
+ ### `Option` (Replacing `None`)
87
+
88
+ ```python
89
+ from pydorust.types import Option, Some, Null, ret_option
90
+
91
+ # Using a decorator to convert returns of None into `Null`, and values into `Some`
92
+ @ret_option
93
+ def divide(a: float, b: float) -> float | None:
94
+ if b == 0.0:
95
+ return None
96
+ return a / b
97
+
98
+ result: Option[float] = divide(10.0, 2.0)
99
+ print(result.unwrap_or(0.0)) # 5.0
100
+
101
+ bad_result = divide(10.0, 0.0)
102
+ print(bad_result.is_null()) # True
103
+ ```
104
+
105
+ ### `Result` (Replacing Exceptions)
106
+
107
+ The `Result` module provides `Ok(value)` and `Err(error)`, along with combinators like `.map()`, `.and_then()`, and `.unwrap()` to cleanly chain operations that might fail without massive `try/except` blocks.
108
+
109
+ ---
110
+
111
+ ## Thread Synchronization (`pydorust.sync`)
112
+
113
+ Provides semantic synchronization primitives mirroring Rust's standard library. While these tools cannot physically isolate or protect the inner state of Python objects from being mutated externally, they enforce semantic structure. By utilizing Context Managers as guards, `pydorust` helps prevent lock leaks and logically synchronizes your concurrent code.
114
+
115
+ ### Example: `Mutex`
116
+
117
+ ```python
118
+ import threading
119
+ from pydorust.sync import Mutex
120
+
121
+ # Wrap the data inside the Mutex
122
+ data = Mutex([1, 2, 3])
123
+
124
+ def worker():
125
+ # .lock() returns a MutexGuard. The lock is released when the block exits.
126
+ with data.lock() as guard:
127
+ guard.value.append(4)
128
+
129
+ t = threading.Thread(target=worker)
130
+ t.start(); t.join()
131
+
132
+ with data.lock() as guard:
133
+ print(guard.value) # [1, 2, 3, 4]
134
+ ```
135
+
136
+ *(Also includes `RwLock` for multi-reader / single-writer scenarios).*
137
+
138
+ ---
139
+
140
+ ## Algebraic Data Types (`pydorust.adt`)
141
+
142
+ Using the `Variant` and `Enum` classes, you can build tagged unions/variants to guarantee data shapes securely.
143
+
144
+ ### Example
145
+
146
+ ```python
147
+ from pydorust.adt import Variant, Enum
148
+
149
+ class Point2D(Variant):
150
+ x: int
151
+ y: int
152
+
153
+ class Point3D(Variant):
154
+ x: int
155
+ y: int
156
+ z: int
157
+
158
+ class ShapePoint(Enum):
159
+ D2 = Point2D
160
+ D3 = Point3D
161
+
162
+ p = ShapePoint.D2(x=10, y=20)
163
+ print(isinstance(p, ShapePoint)) # True
164
+ ```
165
+
166
+ ---
167
+
168
+ ## Other Features
169
+
170
+ ### Unrecoverable Errors (`pydorust.panics`)
171
+
172
+ Provides deterministic app termination for unrecoverable states.
173
+
174
+ - `panic("message")`: Immediately terminates the execution.
175
+ - `unimplemented()`: Drop-in for missing functionality (crashes if reached).
176
+ - `unreachable()`: For code paths that logically shouldn't be executed.
177
+
178
+ ### Unsafe Markers (`pydorust.unsafe`)
179
+
180
+ In Rust, dangerous operations that break memory safety guarantees must be wrapped in `unsafe {}`. `pydorust` emulates this semantic contract using decorators.
181
+
182
+ ```python
183
+ from pydorust.unsafe import unsafe_func, unsafe_call
184
+
185
+ @unsafe_func
186
+ def dangerous_operation():
187
+ print("Doing something unsafe...")
188
+
189
+ # dangerous_operation() # type error
190
+ unsafe_call(dangerous_operation)
191
+ ```
192
+
193
+ ### Low-Level Memory (`pydorust.mem`)
194
+
195
+ Exposes `unsafe` wrappers around `ctypes.pythonapi` memory management tools, granting you direct control over allocations with `alloc(size)` and `free(ptr)`. Always use carefully via `RawBuffer` or explicit `unsafe_call`.
@@ -0,0 +1,61 @@
1
+ {
2
+ "nodes": {
3
+ "flake-utils": {
4
+ "inputs": {
5
+ "systems": "systems"
6
+ },
7
+ "locked": {
8
+ "lastModified": 1731533236,
9
+ "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
10
+ "owner": "numtide",
11
+ "repo": "flake-utils",
12
+ "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
13
+ "type": "github"
14
+ },
15
+ "original": {
16
+ "owner": "numtide",
17
+ "repo": "flake-utils",
18
+ "type": "github"
19
+ }
20
+ },
21
+ "nixpkgs": {
22
+ "locked": {
23
+ "lastModified": 1760524057,
24
+ "narHash": "sha256-EVAqOteLBFmd7pKkb0+FIUyzTF61VKi7YmvP1tw4nEw=",
25
+ "owner": "NixOS",
26
+ "repo": "nixpkgs",
27
+ "rev": "544961dfcce86422ba200ed9a0b00dd4b1486ec5",
28
+ "type": "github"
29
+ },
30
+ "original": {
31
+ "owner": "NixOS",
32
+ "ref": "nixos-unstable",
33
+ "repo": "nixpkgs",
34
+ "type": "github"
35
+ }
36
+ },
37
+ "root": {
38
+ "inputs": {
39
+ "flake-utils": "flake-utils",
40
+ "nixpkgs": "nixpkgs"
41
+ }
42
+ },
43
+ "systems": {
44
+ "locked": {
45
+ "lastModified": 1681028828,
46
+ "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
47
+ "owner": "nix-systems",
48
+ "repo": "default",
49
+ "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
50
+ "type": "github"
51
+ },
52
+ "original": {
53
+ "owner": "nix-systems",
54
+ "repo": "default",
55
+ "type": "github"
56
+ }
57
+ }
58
+ },
59
+ "root": "root",
60
+ "version": 7
61
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ inputs = {
3
+ nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
4
+ flake-utils.url = "github:numtide/flake-utils";
5
+ };
6
+
7
+ outputs = {
8
+ nixpkgs,
9
+ flake-utils,
10
+ ...
11
+ }:
12
+ flake-utils.lib.eachDefaultSystem (
13
+ system: let
14
+ pkgs = import nixpkgs {
15
+ inherit system;
16
+ };
17
+ in {
18
+ devShells.default = pkgs.mkShell {
19
+ nativeBuildInputs = with pkgs; [
20
+ python310
21
+ ];
22
+
23
+ buildInputs = with pkgs; [
24
+ black
25
+ nixfmt
26
+ uv
27
+ isort
28
+ mypy
29
+ pylint
30
+ ruff
31
+ ];
32
+ };
33
+ }
34
+ );
35
+ }
@@ -0,0 +1,28 @@
1
+ # ruff: noqa
2
+ # pylint: disable=wrong-import-position
3
+ from .macros import enable_runtime_expand
4
+
5
+ enable_runtime_expand()
6
+
7
+ from . import adt, lock, mem, num, sync, trait, types, utilities
8
+ from .panics import PanicMode, panic, panic_mode, unimplemented, unreachable
9
+ from .unsafe import unsafe_call, unsafe_func
10
+
11
+ __all__ = [
12
+ "adt",
13
+ "panics",
14
+ "unimplemented",
15
+ "unreachable",
16
+ "panic",
17
+ "panic_mode",
18
+ "PanicMode",
19
+ "mem",
20
+ "trait",
21
+ "utilities",
22
+ "lock",
23
+ "sync",
24
+ "types",
25
+ "num",
26
+ "unsafe_func",
27
+ "unsafe_call",
28
+ ]
@@ -0,0 +1,10 @@
1
+ from enum import Enum, auto
2
+ from typing import Literal
3
+
4
+
5
+ class _SentinelType(Enum):
6
+ SENTINEL = auto()
7
+
8
+
9
+ SENTINEL = _SentinelType.SENTINEL
10
+ Sentinel = Literal[_SentinelType.SENTINEL]