swizzle 0.1.3__tar.gz → 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.
- {swizzle-0.1.3 → swizzle-1.0.0}/PKG-INFO +6 -4
- {swizzle-0.1.3 → swizzle-1.0.0}/README.md +106 -104
- {swizzle-0.1.3 → swizzle-1.0.0}/setup.py +43 -43
- swizzle-1.0.0/swizzle/__init__.py +112 -0
- {swizzle-0.1.3 → swizzle-1.0.0}/swizzle.egg-info/PKG-INFO +6 -4
- swizzle-0.1.3/swizzle/__init__.py +0 -80
- {swizzle-0.1.3 → swizzle-1.0.0}/setup.cfg +0 -0
- {swizzle-0.1.3 → swizzle-1.0.0}/swizzle.egg-info/SOURCES.txt +0 -0
- {swizzle-0.1.3 → swizzle-1.0.0}/swizzle.egg-info/dependency_links.txt +0 -0
- {swizzle-0.1.3 → swizzle-1.0.0}/swizzle.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: swizzle
|
3
|
-
Version: 0.
|
3
|
+
Version: 1.0.0
|
4
4
|
Summary: The Swizzle Decorator enables the retrieval of multiple attributes, similar to swizzling in computer graphics.
|
5
5
|
Home-page: https://github.com/janthmueller/swizzle
|
6
6
|
Author: Jan T. Müller
|
@@ -77,7 +77,7 @@ class XYZ(IntEnum):
|
|
77
77
|
Z = 3
|
78
78
|
|
79
79
|
# Test the swizzle
|
80
|
-
print(XYZ.
|
80
|
+
print(XYZ.YXZ) # Output: (<XYZ.Y: 2>, <XYZ.X: 1>, <XYZ.Z: 3>)
|
81
81
|
```
|
82
82
|
Setting the `meta` argument to `True` in the swizzle decorator extends the `getattr` behavior of the metaclass, enabling attribute swizzling directly on the class itself.
|
83
83
|
|
@@ -99,8 +99,8 @@ print(xyz.yzx) # Output: (2, 3, 1)
|
|
99
99
|
```
|
100
100
|
|
101
101
|
|
102
|
-
### Sequential matching
|
103
|
-
Attributes are matched from left to right, starting with the longest substring match.
|
102
|
+
### Sequential matching
|
103
|
+
Attributes are matched from left to right, starting with the longest substring match.
|
104
104
|
```python
|
105
105
|
import swizzle
|
106
106
|
|
@@ -121,3 +121,5 @@ print(Test.xyyz) # Output: (4, 5)
|
|
121
121
|
print(Test.xyzx) # Output: (7, 1)
|
122
122
|
```
|
123
123
|
|
124
|
+
## To Do
|
125
|
+
- [ ] Swizzle for method args (swizzle+partial)
|
@@ -1,104 +1,106 @@
|
|
1
|
-
# Swizzle Decorator
|
2
|
-
|
3
|
-
The **Swizzle Decorator** for Python enhances attribute lookup methods (`__getattr__` or `__getattribute__`) to facilitate dynamic and flexible retrieval of multiple attributes based on specified arrangements of their names. This concept is reminiscent of swizzling in computer graphics, where it allows efficient access to components of vectors or coordinates in various orders:
|
4
|
-
|
5
|
-
```python
|
6
|
-
import swizzle
|
7
|
-
|
8
|
-
@swizzle
|
9
|
-
class Vector:
|
10
|
-
def __init__(self, x, y, z):
|
11
|
-
self.x = x
|
12
|
-
self.y = y
|
13
|
-
self.z = z
|
14
|
-
|
15
|
-
print(Vector(1, 2, 3).yzx) # Output: (2, 3, 1)
|
16
|
-
```
|
17
|
-
|
18
|
-
## Installation
|
19
|
-
### From PyPI
|
20
|
-
```bash
|
21
|
-
pip install swizzle
|
22
|
-
```
|
23
|
-
### From GitHub
|
24
|
-
```bash
|
25
|
-
pip install git+https://github.com/janthmueller/swizzle.git
|
26
|
-
```
|
27
|
-
|
28
|
-
## Further Examples
|
29
|
-
|
30
|
-
### Using `swizzle` with `dataclass`
|
31
|
-
|
32
|
-
```python
|
33
|
-
import swizzle
|
34
|
-
from dataclasses import dataclass
|
35
|
-
|
36
|
-
@swizzle
|
37
|
-
@dataclass
|
38
|
-
class XYZ:
|
39
|
-
x: int
|
40
|
-
y: int
|
41
|
-
z: int
|
42
|
-
|
43
|
-
# Test the swizzle
|
44
|
-
xyz = XYZ(1, 2, 3)
|
45
|
-
print(xyz.yzx) # Output: (2, 3, 1)
|
46
|
-
```
|
47
|
-
|
48
|
-
### Using `swizzle` with `IntEnum`
|
49
|
-
|
50
|
-
```python
|
51
|
-
import swizzle
|
52
|
-
from enum import IntEnum
|
53
|
-
|
54
|
-
@swizzle(meta=True)
|
55
|
-
class XYZ(IntEnum):
|
56
|
-
X = 1
|
57
|
-
Y = 2
|
58
|
-
Z = 3
|
59
|
-
|
60
|
-
# Test the swizzle
|
61
|
-
print(XYZ.
|
62
|
-
```
|
63
|
-
Setting the `meta` argument to `True` in the swizzle decorator extends the `getattr` behavior of the metaclass, enabling attribute swizzling directly on the class itself.
|
64
|
-
|
65
|
-
### Using `swizzle` with `NamedTuple`
|
66
|
-
|
67
|
-
```python
|
68
|
-
import swizzle
|
69
|
-
from typing import NamedTuple
|
70
|
-
|
71
|
-
@swizzle
|
72
|
-
class XYZ(NamedTuple):
|
73
|
-
x: int
|
74
|
-
y: int
|
75
|
-
z: int
|
76
|
-
|
77
|
-
# Test the swizzle
|
78
|
-
xyz = XYZ(1, 2, 3)
|
79
|
-
print(xyz.yzx) # Output: (2, 3, 1)
|
80
|
-
```
|
81
|
-
|
82
|
-
|
83
|
-
### Sequential matching
|
84
|
-
Attributes are matched from left to right, starting with the longest substring match.
|
85
|
-
```python
|
86
|
-
import swizzle
|
87
|
-
|
88
|
-
@swizzle(meta=True)
|
89
|
-
class Test:
|
90
|
-
x = 1
|
91
|
-
y = 2
|
92
|
-
z = 3
|
93
|
-
xy = 4
|
94
|
-
yz = 5
|
95
|
-
xz = 6
|
96
|
-
xyz = 7
|
97
|
-
|
98
|
-
# Test the swizzle
|
99
|
-
print(Test.xz) # Output: 6
|
100
|
-
print(Test.yz) # Output: 5
|
101
|
-
print(Test.xyyz) # Output: (4, 5)
|
102
|
-
print(Test.xyzx) # Output: (7, 1)
|
103
|
-
```
|
104
|
-
|
1
|
+
# Swizzle Decorator
|
2
|
+
|
3
|
+
The **Swizzle Decorator** for Python enhances attribute lookup methods (`__getattr__` or `__getattribute__`) to facilitate dynamic and flexible retrieval of multiple attributes based on specified arrangements of their names. This concept is reminiscent of swizzling in computer graphics, where it allows efficient access to components of vectors or coordinates in various orders:
|
4
|
+
|
5
|
+
```python
|
6
|
+
import swizzle
|
7
|
+
|
8
|
+
@swizzle
|
9
|
+
class Vector:
|
10
|
+
def __init__(self, x, y, z):
|
11
|
+
self.x = x
|
12
|
+
self.y = y
|
13
|
+
self.z = z
|
14
|
+
|
15
|
+
print(Vector(1, 2, 3).yzx) # Output: (2, 3, 1)
|
16
|
+
```
|
17
|
+
|
18
|
+
## Installation
|
19
|
+
### From PyPI
|
20
|
+
```bash
|
21
|
+
pip install swizzle
|
22
|
+
```
|
23
|
+
### From GitHub
|
24
|
+
```bash
|
25
|
+
pip install git+https://github.com/janthmueller/swizzle.git
|
26
|
+
```
|
27
|
+
|
28
|
+
## Further Examples
|
29
|
+
|
30
|
+
### Using `swizzle` with `dataclass`
|
31
|
+
|
32
|
+
```python
|
33
|
+
import swizzle
|
34
|
+
from dataclasses import dataclass
|
35
|
+
|
36
|
+
@swizzle
|
37
|
+
@dataclass
|
38
|
+
class XYZ:
|
39
|
+
x: int
|
40
|
+
y: int
|
41
|
+
z: int
|
42
|
+
|
43
|
+
# Test the swizzle
|
44
|
+
xyz = XYZ(1, 2, 3)
|
45
|
+
print(xyz.yzx) # Output: (2, 3, 1)
|
46
|
+
```
|
47
|
+
|
48
|
+
### Using `swizzle` with `IntEnum`
|
49
|
+
|
50
|
+
```python
|
51
|
+
import swizzle
|
52
|
+
from enum import IntEnum
|
53
|
+
|
54
|
+
@swizzle(meta=True)
|
55
|
+
class XYZ(IntEnum):
|
56
|
+
X = 1
|
57
|
+
Y = 2
|
58
|
+
Z = 3
|
59
|
+
|
60
|
+
# Test the swizzle
|
61
|
+
print(XYZ.YXZ) # Output: (<XYZ.Y: 2>, <XYZ.X: 1>, <XYZ.Z: 3>)
|
62
|
+
```
|
63
|
+
Setting the `meta` argument to `True` in the swizzle decorator extends the `getattr` behavior of the metaclass, enabling attribute swizzling directly on the class itself.
|
64
|
+
|
65
|
+
### Using `swizzle` with `NamedTuple`
|
66
|
+
|
67
|
+
```python
|
68
|
+
import swizzle
|
69
|
+
from typing import NamedTuple
|
70
|
+
|
71
|
+
@swizzle
|
72
|
+
class XYZ(NamedTuple):
|
73
|
+
x: int
|
74
|
+
y: int
|
75
|
+
z: int
|
76
|
+
|
77
|
+
# Test the swizzle
|
78
|
+
xyz = XYZ(1, 2, 3)
|
79
|
+
print(xyz.yzx) # Output: (2, 3, 1)
|
80
|
+
```
|
81
|
+
|
82
|
+
|
83
|
+
### Sequential matching
|
84
|
+
Attributes are matched from left to right, starting with the longest substring match.
|
85
|
+
```python
|
86
|
+
import swizzle
|
87
|
+
|
88
|
+
@swizzle(meta=True)
|
89
|
+
class Test:
|
90
|
+
x = 1
|
91
|
+
y = 2
|
92
|
+
z = 3
|
93
|
+
xy = 4
|
94
|
+
yz = 5
|
95
|
+
xz = 6
|
96
|
+
xyz = 7
|
97
|
+
|
98
|
+
# Test the swizzle
|
99
|
+
print(Test.xz) # Output: 6
|
100
|
+
print(Test.yz) # Output: 5
|
101
|
+
print(Test.xyyz) # Output: (4, 5)
|
102
|
+
print(Test.xyzx) # Output: (7, 1)
|
103
|
+
```
|
104
|
+
|
105
|
+
## To Do
|
106
|
+
- [ ] Swizzle for method args (swizzle+partial)
|
@@ -1,43 +1,43 @@
|
|
1
|
-
# Copyright (c) 2023 Jan T. Müller <mail@jantmueller.com>
|
2
|
-
|
3
|
-
import sys
|
4
|
-
import os
|
5
|
-
from setuptools import setup, find_packages
|
6
|
-
import swizzle
|
7
|
-
|
8
|
-
if sys.version_info < (3, 6):
|
9
|
-
sys.exit("ERROR: swizzle requires Python 3.6+")
|
10
|
-
|
11
|
-
with open("README.md", "r", encoding="utf-8") as fh:
|
12
|
-
long_description = fh.read()
|
13
|
-
|
14
|
-
setup(
|
15
|
-
name="swizzle",
|
16
|
-
version=swizzle.__version__,
|
17
|
-
packages=find_packages(exclude=["tests"]),
|
18
|
-
author="Jan T. Müller",
|
19
|
-
author_email="mail@jantmueller.com",
|
20
|
-
description="The Swizzle Decorator enables the retrieval of multiple attributes, similar to swizzling in computer graphics.",
|
21
|
-
long_description=long_description,
|
22
|
-
long_description_content_type="text/markdown",
|
23
|
-
url="https://github.com/janthmueller/swizzle",
|
24
|
-
project_urls={
|
25
|
-
"Documentation": "https://github.com/janthmueller/swizzle/blob/main/README.md",
|
26
|
-
"Source": "https://github.com/janthmueller/swizzle",
|
27
|
-
"Tracker": "https://github.com/janthmueller/swizzle/issues",
|
28
|
-
},
|
29
|
-
license="MIT",
|
30
|
-
classifiers=[
|
31
|
-
"Intended Audience :: Developers",
|
32
|
-
"Topic :: Software Development :: Libraries :: Python Modules",
|
33
|
-
"License :: OSI Approved :: MIT License",
|
34
|
-
"Operating System :: OS Independent",
|
35
|
-
"Programming Language :: Python :: 3 :: Only",
|
36
|
-
],
|
37
|
-
python_requires=">=3.6",
|
38
|
-
)
|
39
|
-
|
40
|
-
|
41
|
-
# python setup.py sdist bdist_wheel
|
42
|
-
# twine check dist/*
|
43
|
-
# twine upload dist/* -> insert token
|
1
|
+
# Copyright (c) 2023 Jan T. Müller <mail@jantmueller.com>
|
2
|
+
|
3
|
+
import sys
|
4
|
+
import os
|
5
|
+
from setuptools import setup, find_packages
|
6
|
+
import swizzle
|
7
|
+
|
8
|
+
if sys.version_info < (3, 6):
|
9
|
+
sys.exit("ERROR: swizzle requires Python 3.6+")
|
10
|
+
|
11
|
+
with open("README.md", "r", encoding="utf-8") as fh:
|
12
|
+
long_description = fh.read()
|
13
|
+
|
14
|
+
setup(
|
15
|
+
name="swizzle",
|
16
|
+
version=swizzle.__version__,
|
17
|
+
packages=find_packages(exclude=["tests"]),
|
18
|
+
author="Jan T. Müller",
|
19
|
+
author_email="mail@jantmueller.com",
|
20
|
+
description="The Swizzle Decorator enables the retrieval of multiple attributes, similar to swizzling in computer graphics.",
|
21
|
+
long_description=long_description,
|
22
|
+
long_description_content_type="text/markdown",
|
23
|
+
url="https://github.com/janthmueller/swizzle",
|
24
|
+
project_urls={
|
25
|
+
"Documentation": "https://github.com/janthmueller/swizzle/blob/main/README.md",
|
26
|
+
"Source": "https://github.com/janthmueller/swizzle",
|
27
|
+
"Tracker": "https://github.com/janthmueller/swizzle/issues",
|
28
|
+
},
|
29
|
+
license="MIT",
|
30
|
+
classifiers=[
|
31
|
+
"Intended Audience :: Developers",
|
32
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
33
|
+
"License :: OSI Approved :: MIT License",
|
34
|
+
"Operating System :: OS Independent",
|
35
|
+
"Programming Language :: Python :: 3 :: Only",
|
36
|
+
],
|
37
|
+
python_requires=">=3.6",
|
38
|
+
)
|
39
|
+
|
40
|
+
|
41
|
+
# python setup.py sdist bdist_wheel
|
42
|
+
# twine check dist/*
|
43
|
+
# twine upload dist/* -> insert token
|
@@ -0,0 +1,112 @@
|
|
1
|
+
from functools import wraps
|
2
|
+
import sys
|
3
|
+
import types
|
4
|
+
|
5
|
+
__version__ = "1.0.0"
|
6
|
+
MISSING = object()
|
7
|
+
|
8
|
+
|
9
|
+
# Helper function to split a string based on a separator
|
10
|
+
def split_string(string, separator):
|
11
|
+
if separator == '':
|
12
|
+
return list(string)
|
13
|
+
else:
|
14
|
+
return string.split(separator)
|
15
|
+
|
16
|
+
# Helper function to collect attribute retrieval functions from a class or meta-class
|
17
|
+
def collect_attribute_functions(cls):
|
18
|
+
funcs = []
|
19
|
+
if hasattr(cls, '__getattribute__'):
|
20
|
+
funcs.append(cls.__getattribute__)
|
21
|
+
if hasattr(cls, '__getattr__'):
|
22
|
+
funcs.append(cls.__getattr__)
|
23
|
+
if not funcs:
|
24
|
+
raise AttributeError("No __getattr__ or __getattribute__ found on the class or meta-class")
|
25
|
+
return funcs
|
26
|
+
|
27
|
+
# Function to combine multiple attribute retrieval functions
|
28
|
+
def swizzle_attributes_retriever(attribute_funcs, separator=None):
|
29
|
+
def retrieve_attribute(obj, attr_name):
|
30
|
+
for func in attribute_funcs:
|
31
|
+
try:
|
32
|
+
return func(obj, attr_name)
|
33
|
+
except AttributeError:
|
34
|
+
continue
|
35
|
+
return MISSING
|
36
|
+
|
37
|
+
@wraps(attribute_funcs[-1])
|
38
|
+
def retrieve_swizzled_attributes(obj, attr_name):
|
39
|
+
# Attempt to find an exact attribute match
|
40
|
+
attribute = retrieve_attribute(obj, attr_name)
|
41
|
+
if attribute is not MISSING:
|
42
|
+
return attribute
|
43
|
+
|
44
|
+
matched_attributes = []
|
45
|
+
|
46
|
+
# If a separator is provided, split the name accordingly
|
47
|
+
if separator is not None:
|
48
|
+
attr_parts = split_string(attr_name, separator)
|
49
|
+
for part in attr_parts:
|
50
|
+
attribute = retrieve_attribute(obj, part)
|
51
|
+
if attribute is not MISSING:
|
52
|
+
matched_attributes.append(attribute)
|
53
|
+
else:
|
54
|
+
# No separator provided, attempt to match substrings
|
55
|
+
i = 0
|
56
|
+
while i < len(attr_name):
|
57
|
+
match_found = False
|
58
|
+
for j in range(len(attr_name), i, -1):
|
59
|
+
substring = attr_name[i:j]
|
60
|
+
attribute = retrieve_attribute(obj, substring)
|
61
|
+
if attribute is not MISSING:
|
62
|
+
matched_attributes.append(attribute)
|
63
|
+
i = j # Move index to end of the matched substring
|
64
|
+
match_found = True
|
65
|
+
break
|
66
|
+
if not match_found:
|
67
|
+
raise AttributeError(f"No matching attribute found for substring: {attr_name[i:]}")
|
68
|
+
|
69
|
+
return tuple(matched_attributes)
|
70
|
+
|
71
|
+
return retrieve_swizzled_attributes
|
72
|
+
|
73
|
+
# Decorator function to enable swizzling for a class
|
74
|
+
def swizzle(cls=None, use_meta=False, separator=None):
|
75
|
+
def class_decorator(cls):
|
76
|
+
# Collect attribute retrieval functions from the class
|
77
|
+
attribute_funcs = collect_attribute_functions(cls)
|
78
|
+
|
79
|
+
# Apply the swizzling to the class's attribute retrieval
|
80
|
+
setattr(cls, attribute_funcs[-1].__name__, swizzle_attributes_retriever(attribute_funcs, separator))
|
81
|
+
|
82
|
+
# Handle meta-class swizzling if requested
|
83
|
+
if use_meta:
|
84
|
+
meta_cls = type(cls)
|
85
|
+
if meta_cls == type:
|
86
|
+
class SwizzledMetaType(meta_cls):
|
87
|
+
pass
|
88
|
+
meta_cls = SwizzledMetaType
|
89
|
+
cls = meta_cls(cls.__name__, cls.__bases__, dict(cls.__dict__))
|
90
|
+
meta_cls = SwizzledMetaType
|
91
|
+
cls = meta_cls(cls.__name__, cls.__bases__, dict(cls.__dict__))
|
92
|
+
|
93
|
+
meta_funcs = collect_attribute_functions(meta_cls)
|
94
|
+
setattr(meta_cls, meta_funcs[-1].__name__, swizzle_attributes_retriever(meta_funcs, separator))
|
95
|
+
|
96
|
+
return cls
|
97
|
+
|
98
|
+
if cls is None:
|
99
|
+
return class_decorator
|
100
|
+
else:
|
101
|
+
return class_decorator(cls)
|
102
|
+
|
103
|
+
|
104
|
+
class Swizzle(types.ModuleType):
|
105
|
+
def __init__(self):
|
106
|
+
types.ModuleType.__init__(self, __name__)
|
107
|
+
self.__dict__.update(sys.modules[__name__].__dict__)
|
108
|
+
|
109
|
+
def __call__(self, cls=None, meta=False, sep = None):
|
110
|
+
return swizzle(cls, meta, sep)
|
111
|
+
|
112
|
+
sys.modules[__name__] = Swizzle()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: swizzle
|
3
|
-
Version: 0.
|
3
|
+
Version: 1.0.0
|
4
4
|
Summary: The Swizzle Decorator enables the retrieval of multiple attributes, similar to swizzling in computer graphics.
|
5
5
|
Home-page: https://github.com/janthmueller/swizzle
|
6
6
|
Author: Jan T. Müller
|
@@ -77,7 +77,7 @@ class XYZ(IntEnum):
|
|
77
77
|
Z = 3
|
78
78
|
|
79
79
|
# Test the swizzle
|
80
|
-
print(XYZ.
|
80
|
+
print(XYZ.YXZ) # Output: (<XYZ.Y: 2>, <XYZ.X: 1>, <XYZ.Z: 3>)
|
81
81
|
```
|
82
82
|
Setting the `meta` argument to `True` in the swizzle decorator extends the `getattr` behavior of the metaclass, enabling attribute swizzling directly on the class itself.
|
83
83
|
|
@@ -99,8 +99,8 @@ print(xyz.yzx) # Output: (2, 3, 1)
|
|
99
99
|
```
|
100
100
|
|
101
101
|
|
102
|
-
### Sequential matching
|
103
|
-
Attributes are matched from left to right, starting with the longest substring match.
|
102
|
+
### Sequential matching
|
103
|
+
Attributes are matched from left to right, starting with the longest substring match.
|
104
104
|
```python
|
105
105
|
import swizzle
|
106
106
|
|
@@ -121,3 +121,5 @@ print(Test.xyyz) # Output: (4, 5)
|
|
121
121
|
print(Test.xyzx) # Output: (7, 1)
|
122
122
|
```
|
123
123
|
|
124
|
+
## To Do
|
125
|
+
- [ ] Swizzle for method args (swizzle+partial)
|
@@ -1,80 +0,0 @@
|
|
1
|
-
from functools import wraps
|
2
|
-
import sys
|
3
|
-
import types
|
4
|
-
|
5
|
-
__version__ = "0.1.3"
|
6
|
-
|
7
|
-
def _split(s, sep):
|
8
|
-
if sep == '':
|
9
|
-
return list(s)
|
10
|
-
else:
|
11
|
-
return s.split(sep)
|
12
|
-
|
13
|
-
def _swizzle(func, sep = None):
|
14
|
-
def _getattr(obj, name, default=object()):
|
15
|
-
try:
|
16
|
-
return func(obj, name)
|
17
|
-
except AttributeError:
|
18
|
-
return default
|
19
|
-
|
20
|
-
@wraps(func)
|
21
|
-
def _swizzle_attributes(obj, name):
|
22
|
-
"""Find attributes of an object that match substrings of a given name."""
|
23
|
-
try:
|
24
|
-
return func(obj, name)
|
25
|
-
except AttributeError:
|
26
|
-
pass
|
27
|
-
if sep is not None:
|
28
|
-
names = _split(name, sep)
|
29
|
-
found_attributes = [func(obj, n) for n in names]
|
30
|
-
else:
|
31
|
-
found_attributes = []
|
32
|
-
sentinel = object()
|
33
|
-
i = 0
|
34
|
-
while i < len(name):
|
35
|
-
match_found = False
|
36
|
-
for j in range(len(name), i, -1):
|
37
|
-
substr = name[i:j]
|
38
|
-
attr = _getattr(obj, substr, sentinel)
|
39
|
-
if attr is not sentinel:
|
40
|
-
found_attributes.append(attr)
|
41
|
-
i = j # Move index to end of the matched substring
|
42
|
-
match_found = True
|
43
|
-
break
|
44
|
-
if not match_found:
|
45
|
-
raise AttributeError(f"No matching attribute found for substring: {name[i:]}")
|
46
|
-
return tuple(found_attributes)
|
47
|
-
return _swizzle_attributes
|
48
|
-
|
49
|
-
def swizzle(cls=None, meta = False, sep = None):
|
50
|
-
def decorator(cls):
|
51
|
-
# Decorate the class's __getattr__ or __getattribute__
|
52
|
-
cls_fn = cls.__getattr__ if hasattr(cls, '__getattr__') else cls.__getattribute__
|
53
|
-
setattr(cls, cls_fn.__name__, _swizzle(cls_fn, sep))
|
54
|
-
|
55
|
-
# Handle the meta class
|
56
|
-
if meta:
|
57
|
-
meta_cls = type(cls)
|
58
|
-
if meta_cls == type:
|
59
|
-
class SwizzleType(meta_cls): pass
|
60
|
-
meta_cls = SwizzleType
|
61
|
-
cls = meta_cls(cls.__name__, cls.__bases__, dict(cls.__dict__))
|
62
|
-
meta_fn = meta_cls.__getattr__ if hasattr(meta_cls, '__getattr__') else meta_cls.__getattribute__
|
63
|
-
setattr(meta_cls, meta_fn.__name__, _swizzle(meta_fn, sep))
|
64
|
-
return cls
|
65
|
-
|
66
|
-
if cls is None:
|
67
|
-
return decorator
|
68
|
-
else:
|
69
|
-
return decorator(cls)
|
70
|
-
|
71
|
-
class Swizzle(types.ModuleType):
|
72
|
-
def __init__(self):
|
73
|
-
types.ModuleType.__init__(self, __name__)
|
74
|
-
self.__dict__.update(sys.modules[__name__].__dict__)
|
75
|
-
|
76
|
-
def __call__(self, cls=None, meta=False, sep = None):
|
77
|
-
return swizzle(cls, meta, sep)
|
78
|
-
|
79
|
-
sys.modules[__name__] = Swizzle()
|
80
|
-
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|