omarlib 1.0.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.
- omarlib-1.0.0/LICENSE +21 -0
- omarlib-1.0.0/PKG-INFO +199 -0
- omarlib-1.0.0/README.md +167 -0
- omarlib-1.0.0/pyproject.toml +65 -0
- omarlib-1.0.0/setup.cfg +4 -0
- omarlib-1.0.0/src/omarlib/__init__.py +46 -0
- omarlib-1.0.0/src/omarlib/nameof.py +164 -0
- omarlib-1.0.0/src/omarlib/overload.py +277 -0
- omarlib-1.0.0/src/omarlib/private.py +169 -0
- omarlib-1.0.0/src/omarlib/ptr.py +214 -0
- omarlib-1.0.0/src/omarlib/py.typed +2 -0
- omarlib-1.0.0/src/omarlib/ref.py +181 -0
- omarlib-1.0.0/src/omarlib/xor.py +40 -0
- omarlib-1.0.0/src/omarlib.egg-info/PKG-INFO +199 -0
- omarlib-1.0.0/src/omarlib.egg-info/SOURCES.txt +17 -0
- omarlib-1.0.0/src/omarlib.egg-info/dependency_links.txt +1 -0
- omarlib-1.0.0/src/omarlib.egg-info/requires.txt +6 -0
- omarlib-1.0.0/src/omarlib.egg-info/top_level.txt +1 -0
- omarlib-1.0.0/tests/test_all.py +355 -0
omarlib-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 OmarYauh
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
omarlib-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: omarlib
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Extended Python features: xor, pointers, references, nameof, private methods, and function overloading
|
|
5
|
+
Author-email: OmarYauh <omaryauh@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/SlackPen/omarlib
|
|
8
|
+
Project-URL: Documentation, https://github.com/SlackPen/omarlib#readme
|
|
9
|
+
Project-URL: Repository, https://github.com/SlackPen/omarlib
|
|
10
|
+
Project-URL: Issues, https://github.com/SlackPen/omarlib/issues
|
|
11
|
+
Keywords: xor,pointer,reference,nameof,private,overload,utilities,extensions,metaprogramming
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.8
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
30
|
+
Requires-Dist: black>=23.0; extra == "dev"
|
|
31
|
+
Requires-Dist: mypy>=1.0; extra == "dev"
|
|
32
|
+
|
|
33
|
+
# omarlib
|
|
34
|
+
|
|
35
|
+
Extended Python features inspired by other programming languages.
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install omarlib
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Features
|
|
44
|
+
|
|
45
|
+
### 1. `xor(a, b)` - Logical XOR
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from omarlib import xor
|
|
49
|
+
|
|
50
|
+
xor(True, False) # True
|
|
51
|
+
xor(True, True) # False
|
|
52
|
+
xor(False, False) # False
|
|
53
|
+
xor(1, 0) # True (truthy/falsy)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 2. `ptr(obj)` - Pointers
|
|
57
|
+
|
|
58
|
+
C-style pointers for Python objects.
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from omarlib import ptr
|
|
62
|
+
|
|
63
|
+
x = [1, 2, 3]
|
|
64
|
+
p = ptr(x)
|
|
65
|
+
|
|
66
|
+
print(p.value) # [1, 2, 3] - dereference
|
|
67
|
+
print(p.addr) # memory address (id)
|
|
68
|
+
print(~p) # [1, 2, 3] - dereference with ~
|
|
69
|
+
|
|
70
|
+
# Pointer arithmetic with sequences
|
|
71
|
+
arr = [10, 20, 30, 40, 50]
|
|
72
|
+
p = ptr(arr)
|
|
73
|
+
print((p + 2).value) # 30
|
|
74
|
+
|
|
75
|
+
# Null pointer
|
|
76
|
+
p.set_null()
|
|
77
|
+
print(p.is_null()) # True
|
|
78
|
+
print(bool(p)) # False
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### 3. `ref(name)` - Real References
|
|
82
|
+
|
|
83
|
+
Create references that can modify the original variable.
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
from omarlib import ref
|
|
87
|
+
|
|
88
|
+
x = 42
|
|
89
|
+
r = ref('x')
|
|
90
|
+
print(r.value) # 42
|
|
91
|
+
|
|
92
|
+
r.value = 100
|
|
93
|
+
print(x) # 100 - x was modified!
|
|
94
|
+
|
|
95
|
+
# Swap example
|
|
96
|
+
a, b = 1, 2
|
|
97
|
+
ref('a').value, ref('b').value = ref('b').value, ref('a').value
|
|
98
|
+
print(a, b) # 2, 1
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 4. `nameof(var)` - Get Variable Name
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
from omarlib import nameof
|
|
105
|
+
|
|
106
|
+
my_variable = 42
|
|
107
|
+
print(nameof(my_variable)) # 'my_variable'
|
|
108
|
+
|
|
109
|
+
user_name = "Omar"
|
|
110
|
+
print(nameof(user_name)) # 'user_name'
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 5. `nameof_all(*vars)` - Get Multiple Variable Names
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
from omarlib import nameof_all
|
|
117
|
+
|
|
118
|
+
a = 1
|
|
119
|
+
b = 2
|
|
120
|
+
c = 3
|
|
121
|
+
|
|
122
|
+
names = nameof_all(a, b, c)
|
|
123
|
+
print(names) # ['a', 'b', 'c']
|
|
124
|
+
|
|
125
|
+
# Useful for iteration
|
|
126
|
+
for name, value in zip(nameof_all(a, b, c), [a, b, c]):
|
|
127
|
+
print(f"{name} = {value}")
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### 6. `@private` - Real Private Methods
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
from omarlib import private
|
|
134
|
+
|
|
135
|
+
class BankAccount:
|
|
136
|
+
def __init__(self, balance):
|
|
137
|
+
self._balance = balance
|
|
138
|
+
|
|
139
|
+
@private
|
|
140
|
+
def _calculate_interest(self):
|
|
141
|
+
return self._balance * 0.05
|
|
142
|
+
|
|
143
|
+
def apply_interest(self):
|
|
144
|
+
# OK - called from inside the class
|
|
145
|
+
interest = self._calculate_interest()
|
|
146
|
+
self._balance += interest
|
|
147
|
+
return interest
|
|
148
|
+
|
|
149
|
+
account = BankAccount(1000)
|
|
150
|
+
account.apply_interest() # OK
|
|
151
|
+
account._calculate_interest() # PermissionError!
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### 7. `@overload` - Function Overloading
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
from omarlib import overload
|
|
158
|
+
|
|
159
|
+
@overload
|
|
160
|
+
def process(x: int):
|
|
161
|
+
return x * 2
|
|
162
|
+
|
|
163
|
+
@process.register
|
|
164
|
+
def process(x: str):
|
|
165
|
+
return x.upper()
|
|
166
|
+
|
|
167
|
+
@process.register
|
|
168
|
+
def process(x: int, y: int):
|
|
169
|
+
return x + y
|
|
170
|
+
|
|
171
|
+
print(process(5)) # 10
|
|
172
|
+
print(process("hello")) # HELLO
|
|
173
|
+
print(process(3, 4)) # 7
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Import Everything
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
from omarlib import *
|
|
180
|
+
|
|
181
|
+
# Now you have: xor, ptr, ref, nameof, nameof_all, private, overload
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Requirements
|
|
185
|
+
|
|
186
|
+
- Python 3.8+
|
|
187
|
+
- No external dependencies
|
|
188
|
+
|
|
189
|
+
## License
|
|
190
|
+
|
|
191
|
+
MIT License - see LICENSE file.
|
|
192
|
+
|
|
193
|
+
## Author
|
|
194
|
+
|
|
195
|
+
OmarYauh
|
|
196
|
+
|
|
197
|
+
## Contributing
|
|
198
|
+
|
|
199
|
+
Contributions are welcome! Please open an issue or submit a pull request.
|
omarlib-1.0.0/README.md
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# omarlib
|
|
2
|
+
|
|
3
|
+
Extended Python features inspired by other programming languages.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install omarlib
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
### 1. `xor(a, b)` - Logical XOR
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from omarlib import xor
|
|
17
|
+
|
|
18
|
+
xor(True, False) # True
|
|
19
|
+
xor(True, True) # False
|
|
20
|
+
xor(False, False) # False
|
|
21
|
+
xor(1, 0) # True (truthy/falsy)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### 2. `ptr(obj)` - Pointers
|
|
25
|
+
|
|
26
|
+
C-style pointers for Python objects.
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from omarlib import ptr
|
|
30
|
+
|
|
31
|
+
x = [1, 2, 3]
|
|
32
|
+
p = ptr(x)
|
|
33
|
+
|
|
34
|
+
print(p.value) # [1, 2, 3] - dereference
|
|
35
|
+
print(p.addr) # memory address (id)
|
|
36
|
+
print(~p) # [1, 2, 3] - dereference with ~
|
|
37
|
+
|
|
38
|
+
# Pointer arithmetic with sequences
|
|
39
|
+
arr = [10, 20, 30, 40, 50]
|
|
40
|
+
p = ptr(arr)
|
|
41
|
+
print((p + 2).value) # 30
|
|
42
|
+
|
|
43
|
+
# Null pointer
|
|
44
|
+
p.set_null()
|
|
45
|
+
print(p.is_null()) # True
|
|
46
|
+
print(bool(p)) # False
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 3. `ref(name)` - Real References
|
|
50
|
+
|
|
51
|
+
Create references that can modify the original variable.
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
from omarlib import ref
|
|
55
|
+
|
|
56
|
+
x = 42
|
|
57
|
+
r = ref('x')
|
|
58
|
+
print(r.value) # 42
|
|
59
|
+
|
|
60
|
+
r.value = 100
|
|
61
|
+
print(x) # 100 - x was modified!
|
|
62
|
+
|
|
63
|
+
# Swap example
|
|
64
|
+
a, b = 1, 2
|
|
65
|
+
ref('a').value, ref('b').value = ref('b').value, ref('a').value
|
|
66
|
+
print(a, b) # 2, 1
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 4. `nameof(var)` - Get Variable Name
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from omarlib import nameof
|
|
73
|
+
|
|
74
|
+
my_variable = 42
|
|
75
|
+
print(nameof(my_variable)) # 'my_variable'
|
|
76
|
+
|
|
77
|
+
user_name = "Omar"
|
|
78
|
+
print(nameof(user_name)) # 'user_name'
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### 5. `nameof_all(*vars)` - Get Multiple Variable Names
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from omarlib import nameof_all
|
|
85
|
+
|
|
86
|
+
a = 1
|
|
87
|
+
b = 2
|
|
88
|
+
c = 3
|
|
89
|
+
|
|
90
|
+
names = nameof_all(a, b, c)
|
|
91
|
+
print(names) # ['a', 'b', 'c']
|
|
92
|
+
|
|
93
|
+
# Useful for iteration
|
|
94
|
+
for name, value in zip(nameof_all(a, b, c), [a, b, c]):
|
|
95
|
+
print(f"{name} = {value}")
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 6. `@private` - Real Private Methods
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from omarlib import private
|
|
102
|
+
|
|
103
|
+
class BankAccount:
|
|
104
|
+
def __init__(self, balance):
|
|
105
|
+
self._balance = balance
|
|
106
|
+
|
|
107
|
+
@private
|
|
108
|
+
def _calculate_interest(self):
|
|
109
|
+
return self._balance * 0.05
|
|
110
|
+
|
|
111
|
+
def apply_interest(self):
|
|
112
|
+
# OK - called from inside the class
|
|
113
|
+
interest = self._calculate_interest()
|
|
114
|
+
self._balance += interest
|
|
115
|
+
return interest
|
|
116
|
+
|
|
117
|
+
account = BankAccount(1000)
|
|
118
|
+
account.apply_interest() # OK
|
|
119
|
+
account._calculate_interest() # PermissionError!
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 7. `@overload` - Function Overloading
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
from omarlib import overload
|
|
126
|
+
|
|
127
|
+
@overload
|
|
128
|
+
def process(x: int):
|
|
129
|
+
return x * 2
|
|
130
|
+
|
|
131
|
+
@process.register
|
|
132
|
+
def process(x: str):
|
|
133
|
+
return x.upper()
|
|
134
|
+
|
|
135
|
+
@process.register
|
|
136
|
+
def process(x: int, y: int):
|
|
137
|
+
return x + y
|
|
138
|
+
|
|
139
|
+
print(process(5)) # 10
|
|
140
|
+
print(process("hello")) # HELLO
|
|
141
|
+
print(process(3, 4)) # 7
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Import Everything
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
from omarlib import *
|
|
148
|
+
|
|
149
|
+
# Now you have: xor, ptr, ref, nameof, nameof_all, private, overload
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Requirements
|
|
153
|
+
|
|
154
|
+
- Python 3.8+
|
|
155
|
+
- No external dependencies
|
|
156
|
+
|
|
157
|
+
## License
|
|
158
|
+
|
|
159
|
+
MIT License - see LICENSE file.
|
|
160
|
+
|
|
161
|
+
## Author
|
|
162
|
+
|
|
163
|
+
OmarYauh
|
|
164
|
+
|
|
165
|
+
## Contributing
|
|
166
|
+
|
|
167
|
+
Contributions are welcome! Please open an issue or submit a pull request.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "omarlib"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Extended Python features: xor, pointers, references, nameof, private methods, and function overloading"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
requires-python = ">=3.8"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "OmarYauh", email = "omaryauh@gmail.com"}
|
|
14
|
+
]
|
|
15
|
+
keywords = [
|
|
16
|
+
"xor", "pointer", "reference", "nameof", "private", "overload",
|
|
17
|
+
"utilities", "extensions", "metaprogramming"
|
|
18
|
+
]
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Development Status :: 5 - Production/Stable",
|
|
21
|
+
"Intended Audience :: Developers",
|
|
22
|
+
"License :: OSI Approved :: MIT License",
|
|
23
|
+
"Operating System :: OS Independent",
|
|
24
|
+
"Programming Language :: Python :: 3",
|
|
25
|
+
"Programming Language :: Python :: 3.8",
|
|
26
|
+
"Programming Language :: Python :: 3.9",
|
|
27
|
+
"Programming Language :: Python :: 3.10",
|
|
28
|
+
"Programming Language :: Python :: 3.11",
|
|
29
|
+
"Programming Language :: Python :: 3.12",
|
|
30
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
31
|
+
"Typing :: Typed",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.urls]
|
|
35
|
+
Homepage = "https://github.com/SlackPen/omarlib"
|
|
36
|
+
Documentation = "https://github.com/SlackPen/omarlib#readme"
|
|
37
|
+
Repository = "https://github.com/SlackPen/omarlib"
|
|
38
|
+
Issues = "https://github.com/SlackPen/omarlib/issues"
|
|
39
|
+
|
|
40
|
+
[project.optional-dependencies]
|
|
41
|
+
dev = [
|
|
42
|
+
"pytest>=7.0",
|
|
43
|
+
"pytest-cov>=4.0",
|
|
44
|
+
"black>=23.0",
|
|
45
|
+
"mypy>=1.0",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
[tool.setuptools.packages.find]
|
|
49
|
+
where = ["src"]
|
|
50
|
+
|
|
51
|
+
[tool.setuptools.package-data]
|
|
52
|
+
omarlib = ["py.typed"]
|
|
53
|
+
|
|
54
|
+
[tool.black]
|
|
55
|
+
line-length = 100
|
|
56
|
+
target-version = ["py38", "py39", "py310", "py311", "py312"]
|
|
57
|
+
|
|
58
|
+
[tool.mypy]
|
|
59
|
+
python_version = "3.8"
|
|
60
|
+
warn_return_any = true
|
|
61
|
+
warn_unused_configs = true
|
|
62
|
+
|
|
63
|
+
[tool.pytest.ini_options]
|
|
64
|
+
testpaths = ["tests"]
|
|
65
|
+
python_files = ["test_*.py"]
|
omarlib-1.0.0/setup.cfg
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""
|
|
2
|
+
omarlib - Extended Python features.
|
|
3
|
+
|
|
4
|
+
A library providing additional language features inspired by other
|
|
5
|
+
programming languages:
|
|
6
|
+
|
|
7
|
+
- xor(a, b): Logical XOR operation
|
|
8
|
+
- ptr(obj): C-style pointers
|
|
9
|
+
- ref(name): Real references that modify original variables
|
|
10
|
+
- nameof(var): Get variable name as string
|
|
11
|
+
- nameof_all(*vars): Get multiple variable names
|
|
12
|
+
- @private: Make methods truly private
|
|
13
|
+
- @overload: Function overloading
|
|
14
|
+
|
|
15
|
+
Basic usage:
|
|
16
|
+
from omarlib import xor, ptr, ref, nameof, nameof_all, private, overload
|
|
17
|
+
|
|
18
|
+
Import everything:
|
|
19
|
+
from omarlib import *
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
__version__ = "1.0.0"
|
|
23
|
+
__author__ = "OmarYauh"
|
|
24
|
+
|
|
25
|
+
# Import all features
|
|
26
|
+
from omarlib.xor import xor
|
|
27
|
+
from omarlib.ptr import ptr
|
|
28
|
+
from omarlib.ref import ref
|
|
29
|
+
from omarlib.nameof import nameof, nameof_all
|
|
30
|
+
from omarlib.private import private
|
|
31
|
+
from omarlib.overload import overload
|
|
32
|
+
|
|
33
|
+
# Define what gets exported with "from omarlib import *"
|
|
34
|
+
__all__ = [
|
|
35
|
+
# Version info
|
|
36
|
+
"__version__",
|
|
37
|
+
"__author__",
|
|
38
|
+
# Features
|
|
39
|
+
"xor",
|
|
40
|
+
"ptr",
|
|
41
|
+
"ref",
|
|
42
|
+
"nameof",
|
|
43
|
+
"nameof_all",
|
|
44
|
+
"private",
|
|
45
|
+
"overload",
|
|
46
|
+
]
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"""
|
|
2
|
+
nameof - Get variable names as strings.
|
|
3
|
+
|
|
4
|
+
Provides functions to retrieve the name of a variable as a string,
|
|
5
|
+
useful for debugging, logging, and metaprogramming.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import inspect
|
|
9
|
+
from typing import Any, List, Set
|
|
10
|
+
|
|
11
|
+
__all__ = ["nameof", "nameof_all"]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def nameof(var: Any) -> str:
|
|
15
|
+
"""
|
|
16
|
+
Return the name of a variable as a string.
|
|
17
|
+
|
|
18
|
+
This function inspects the caller's namespace to find the name
|
|
19
|
+
of the variable that was passed as an argument.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
var: The variable whose name you want to get
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
str: The name of the variable
|
|
26
|
+
|
|
27
|
+
Raises:
|
|
28
|
+
ValueError: If the variable name cannot be determined
|
|
29
|
+
|
|
30
|
+
Examples:
|
|
31
|
+
>>> my_variable = 42
|
|
32
|
+
>>> nameof(my_variable)
|
|
33
|
+
'my_variable'
|
|
34
|
+
|
|
35
|
+
>>> user_name = "Omar"
|
|
36
|
+
>>> nameof(user_name)
|
|
37
|
+
'user_name'
|
|
38
|
+
|
|
39
|
+
>>> # Useful for debugging
|
|
40
|
+
>>> x = [1, 2, 3]
|
|
41
|
+
>>> print(f"{nameof(x)} = {x}")
|
|
42
|
+
'x = [1, 2, 3]'
|
|
43
|
+
|
|
44
|
+
Note:
|
|
45
|
+
This function works by comparing object identity (using `is`).
|
|
46
|
+
In loops like `for i in x: nameof(i)`, it will return 'i',
|
|
47
|
+
not the original variable name. Use nameof_all() before the loop
|
|
48
|
+
to capture original names.
|
|
49
|
+
"""
|
|
50
|
+
frame = inspect.currentframe()
|
|
51
|
+
if frame is None:
|
|
52
|
+
raise RuntimeError("nameof() cannot determine caller frame")
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
caller_frame = frame.f_back
|
|
56
|
+
if caller_frame is None:
|
|
57
|
+
raise RuntimeError("nameof() cannot determine caller frame")
|
|
58
|
+
|
|
59
|
+
# Search in locals first
|
|
60
|
+
for name, value in caller_frame.f_locals.items():
|
|
61
|
+
if value is var and name not in ("nameof", "nameof_all"):
|
|
62
|
+
return name
|
|
63
|
+
|
|
64
|
+
# Search in globals
|
|
65
|
+
for name, value in caller_frame.f_globals.items():
|
|
66
|
+
if value is var and name not in ("nameof", "nameof_all"):
|
|
67
|
+
return name
|
|
68
|
+
|
|
69
|
+
raise ValueError(
|
|
70
|
+
"nameof() could not determine variable name. "
|
|
71
|
+
"Only simple variable names are supported, not expressions."
|
|
72
|
+
)
|
|
73
|
+
finally:
|
|
74
|
+
del frame
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def nameof_all(*args: Any) -> List[str]:
|
|
78
|
+
"""
|
|
79
|
+
Return a list with the names of all variables passed as arguments.
|
|
80
|
+
|
|
81
|
+
This function inspects the caller's namespace to find the names
|
|
82
|
+
of all variables passed as arguments.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
*args: The variables whose names you want to get
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
List[str]: A list of variable names in the order they were passed
|
|
89
|
+
|
|
90
|
+
Raises:
|
|
91
|
+
TypeError: If no arguments are provided
|
|
92
|
+
|
|
93
|
+
Examples:
|
|
94
|
+
>>> a = 1
|
|
95
|
+
>>> b = 2
|
|
96
|
+
>>> c = 3
|
|
97
|
+
>>> nameof_all(a, b, c)
|
|
98
|
+
['a', 'b', 'c']
|
|
99
|
+
|
|
100
|
+
>>> # Useful for iteration - capture names BEFORE the loop
|
|
101
|
+
>>> x = 10
|
|
102
|
+
>>> y = 20
|
|
103
|
+
>>> z = 30
|
|
104
|
+
>>> names = nameof_all(x, y, z)
|
|
105
|
+
>>> values = [x, y, z]
|
|
106
|
+
>>> for name, value in zip(names, values):
|
|
107
|
+
... print(f"{name} = {value}")
|
|
108
|
+
x = 10
|
|
109
|
+
y = 20
|
|
110
|
+
z = 30
|
|
111
|
+
|
|
112
|
+
Note:
|
|
113
|
+
Each variable's name is found by comparing object identity.
|
|
114
|
+
Variables with the same value will return the first matching name found
|
|
115
|
+
that hasn't been used yet in the result list.
|
|
116
|
+
"""
|
|
117
|
+
if not args:
|
|
118
|
+
raise TypeError("nameof_all() requires at least 1 argument")
|
|
119
|
+
|
|
120
|
+
frame = inspect.currentframe()
|
|
121
|
+
if frame is None:
|
|
122
|
+
raise RuntimeError("nameof_all() cannot determine caller frame")
|
|
123
|
+
|
|
124
|
+
try:
|
|
125
|
+
caller_frame = frame.f_back
|
|
126
|
+
if caller_frame is None:
|
|
127
|
+
raise RuntimeError("nameof_all() cannot determine caller frame")
|
|
128
|
+
|
|
129
|
+
result: List[str] = []
|
|
130
|
+
used_names: Set[str] = set()
|
|
131
|
+
|
|
132
|
+
locals_dict = caller_frame.f_locals
|
|
133
|
+
globals_dict = caller_frame.f_globals
|
|
134
|
+
|
|
135
|
+
for var in args:
|
|
136
|
+
found_name = None
|
|
137
|
+
|
|
138
|
+
# Search in locals first
|
|
139
|
+
for name, value in locals_dict.items():
|
|
140
|
+
if (value is var and
|
|
141
|
+
name not in ("nameof", "nameof_all") and
|
|
142
|
+
name not in used_names):
|
|
143
|
+
found_name = name
|
|
144
|
+
used_names.add(name)
|
|
145
|
+
break
|
|
146
|
+
|
|
147
|
+
# Search in globals if not found in locals
|
|
148
|
+
if found_name is None:
|
|
149
|
+
for name, value in globals_dict.items():
|
|
150
|
+
if (value is var and
|
|
151
|
+
name not in ("nameof", "nameof_all") and
|
|
152
|
+
name not in used_names):
|
|
153
|
+
found_name = name
|
|
154
|
+
used_names.add(name)
|
|
155
|
+
break
|
|
156
|
+
|
|
157
|
+
if found_name is None:
|
|
158
|
+
found_name = "<unknown>"
|
|
159
|
+
|
|
160
|
+
result.append(found_name)
|
|
161
|
+
|
|
162
|
+
return result
|
|
163
|
+
finally:
|
|
164
|
+
del frame
|