swizzle 0.1.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.
swizzle/__init__.py ADDED
@@ -0,0 +1,70 @@
1
+ from functools import wraps
2
+ import sys
3
+ import types
4
+ import inspect
5
+
6
+ __version__ = "0.1.0"
7
+
8
+ def _swizzle(func):
9
+ def _getattr(obj, name, default=object()):
10
+ try:
11
+ return func(obj, name)
12
+ except AttributeError:
13
+ return default
14
+
15
+ @wraps(func)
16
+ def _swizzle_attributes(obj, name):
17
+ """Find attributes of an object that match substrings of a given name."""
18
+ found_attributes = []
19
+ sentinel = object()
20
+ i = 0
21
+ while i < len(name):
22
+ match_found = False
23
+ for j in range(len(name), i, -1):
24
+ substr = name[i:j]
25
+ attr = _getattr(obj, substr, sentinel)
26
+ if attr is not sentinel:
27
+ found_attributes.append(attr)
28
+ i = j # Move index to end of the matched substring
29
+ match_found = True
30
+ break
31
+ if not match_found:
32
+ raise AttributeError(f"No matching attribute found for substring: {name[i:]}")
33
+ return tuple(found_attributes)
34
+ return _swizzle_attributes
35
+
36
+ def swizzle(cls=None, meta = False):
37
+ def decorator(cls):
38
+ # Decorate the class's __getattr__ or __getattribute__
39
+ cls_fn = cls.__getattr__ if hasattr(cls, '__getattr__') else cls.__getattribute__
40
+ setattr(cls, cls_fn.__name__, _swizzle(cls_fn))
41
+
42
+ # Handle the meta class
43
+ if meta:
44
+ meta_cls = type(cls)
45
+ if meta_cls == type:
46
+ class SwizzleType(meta_cls): pass
47
+ meta_cls = SwizzleType
48
+ cls = meta_cls(cls.__name__, cls.__bases__, dict(cls.__dict__))
49
+ meta_fn = meta_cls.__getattr__ if hasattr(meta_cls, '__getattr__') else meta_cls.__getattribute__
50
+ setattr(meta_cls, meta_fn.__name__, _swizzle(meta_fn))
51
+ return cls
52
+
53
+ if cls is None:
54
+ return decorator
55
+ else:
56
+ return decorator(cls)
57
+
58
+
59
+
60
+ # make swizzle a callable module
61
+ class Swizzle(types.ModuleType):
62
+ def __init__(self):
63
+ types.ModuleType.__init__(self, __name__)
64
+ self.__dict__.update(sys.modules[__name__].__dict__)
65
+
66
+ def __call__(self, cls=None, meta=False):
67
+ return swizzle(cls, meta)
68
+
69
+ sys.modules[__name__] = Swizzle()
70
+
@@ -0,0 +1,118 @@
1
+ Metadata-Version: 2.1
2
+ Name: swizzle
3
+ Version: 0.1.0
4
+ Summary: Transforms a string representation of a Python literal into the corresponding Python object.
5
+ Home-page: https://github.com/janthmueller/swizzle
6
+ Author: Jan T. Müller
7
+ Author-email: mail@jantmueller.com
8
+ License: MIT
9
+ Project-URL: Documentation, https://github.com/janthmueller/swizzle/blob/main/README.md
10
+ Project-URL: Source, https://github.com/janthmueller/swizzle
11
+ Project-URL: Tracker, https://github.com/janthmueller/swizzle/issues
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Requires-Python: >=3.6
18
+ Description-Content-Type: text/markdown
19
+
20
+ # Swizzle Decorator
21
+
22
+ 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:
23
+
24
+ ```python
25
+ import swizzle
26
+
27
+ @swizzle
28
+ class Vector:
29
+ def __init__(self, x, y, z):
30
+ self.x = x
31
+ self.y = y
32
+ self.z = z
33
+
34
+ print(Vector(1, 2, 3).yzx) # Output: (2, 3, 1)
35
+ ```
36
+
37
+ ## Installation
38
+ ```bash
39
+ pip install git+https://github.com/janthmueller/swizzle.git
40
+ ```
41
+
42
+ ## Further Examples
43
+
44
+ ### Using `swizzle` with `dataclass`
45
+
46
+ ```python
47
+ import swizzle
48
+ from dataclasses import dataclass
49
+
50
+ @swizzle
51
+ @dataclass
52
+ class XYZ:
53
+ x: int
54
+ y: int
55
+ z: int
56
+
57
+ # Test the swizzle
58
+ xyz = XYZ(1, 2, 3)
59
+ print(xyz.yzx) # Output: (2, 3, 1)
60
+ ```
61
+
62
+ ### Using `swizzle` with `IntEnum`
63
+
64
+ ```python
65
+ import swizzle
66
+ from enum import IntEnum
67
+
68
+ @swizzle(meta=True)
69
+ class XYZ(IntEnum):
70
+ X = 1
71
+ Y = 2
72
+ Z = 3
73
+
74
+ # Test the swizzle
75
+ print(XYZ.yxz) # Output: (2, 3, 1)
76
+ ```
77
+ 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.
78
+
79
+ ### Using `swizzle` with `NamedTuple`
80
+
81
+ ```python
82
+ import swizzle
83
+ from typing import NamedTuple
84
+
85
+ @swizzle
86
+ class XYZ(NamedTuple):
87
+ x: int
88
+ y: int
89
+ z: int
90
+
91
+ # Test the swizzle
92
+ xyz = XYZ(1, 2, 3)
93
+ print(xyz.yzx) # Output: (2, 3, 1)
94
+ ```
95
+
96
+
97
+ ### Sequential matching
98
+ Attributes are matched from left to right, starting with the longest substring match.
99
+ ```python
100
+ import swizzle
101
+
102
+ @swizzle(meta=True)
103
+ class Test:
104
+ x = 1
105
+ y = 2
106
+ z = 3
107
+ xy = 4
108
+ yz = 5
109
+ xz = 6
110
+ xyz = 7
111
+
112
+ # Test the swizzle
113
+ print(Test.xz) # Output: (6,)
114
+ print(Test.yz) # Output: (5,)
115
+ print(Test.xyyz) # Output: (4, 5)
116
+ print(Test.xyzx) # Output: (7, 1)
117
+ ```
118
+
@@ -0,0 +1,5 @@
1
+ swizzle/__init__.py,sha256=6xrT6tZERBQWGNPvWofOiSnVGzq-0-nRWbAjt9-czJY,2281
2
+ swizzle-0.1.0.dist-info/METADATA,sha256=f4MejVS5TgwsY0hroO6wR7gWIJjLl1Guzx4K_zhm8j4,2807
3
+ swizzle-0.1.0.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
4
+ swizzle-0.1.0.dist-info/top_level.txt,sha256=XFSQti81x2zM0zAMCY1YD0lqB1eSg5my9BB03uFgCic,8
5
+ swizzle-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.38.4)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ swizzle