advscope 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.
@@ -0,0 +1,13 @@
1
+ Metadata-Version: 2.4
2
+ Name: advscope
3
+ Version: 0.1.0
4
+ Summary: Advanced scope utilities for Python.
5
+ Author: Olan
6
+ License: MIT
7
+ Keywords: scope,namespace,utilities
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3 :: Only
12
+ Classifier: Operating System :: OS Independent
13
+ Requires-Python: >=3.8
@@ -0,0 +1,19 @@
1
+ from .core import (
2
+ Namespace,
3
+ Scope,
4
+ GlobalScope,
5
+ LocalScope,
6
+ private,
7
+ isnamespace,
8
+ PrivateAccessError,
9
+ )
10
+
11
+ __all__ = [
12
+ "Namespace",
13
+ "Scope",
14
+ "GlobalScope",
15
+ "LocalScope",
16
+ "private",
17
+ "isnamespace",
18
+ "PrivateAccessError",
19
+ ]
@@ -0,0 +1,150 @@
1
+ import functools
2
+ import inspect
3
+ import sys
4
+ import types
5
+ import weakref
6
+
7
+ class Namespace:
8
+ _private_methods = weakref.WeakKeyDictionary()
9
+
10
+ def __new__(cls, *args, **kwargs):
11
+ raise TypeError(
12
+ f"{cls.__name__} is a namespace and cannot be instantiated."
13
+ )
14
+
15
+ def __init_subclass__(cls):
16
+ super().__init_subclass__()
17
+
18
+ for name, value in list(cls.__dict__.items()):
19
+ func = value
20
+
21
+ if isinstance(value, staticmethod):
22
+ func = value.__func__
23
+
24
+ if isinstance(func, types.FunctionType):
25
+ original = getattr(
26
+ func,
27
+ "__advscope_original__",
28
+ func
29
+ )
30
+
31
+ if getattr(func, "__advscope_private__", False):
32
+ Namespace._private_methods[original] = cls
33
+ else:
34
+ setattr(
35
+ cls,
36
+ name,
37
+ staticmethod(func)
38
+ )
39
+
40
+ def isnamespace(obj):
41
+ """
42
+ Return True if obj is a subclass of Namespace.
43
+ """
44
+
45
+ return isinstance(obj, type) and issubclass(obj, Namespace)
46
+
47
+ class PrivateAccessError(Exception):
48
+ """
49
+ Raised when a private member is accessed from outside
50
+ its allowed namespace.
51
+ """
52
+
53
+ pass
54
+
55
+ def private(func):
56
+ if not isinstance(func, types.FunctionType):
57
+ raise TypeError("@private can only be used on functions")
58
+
59
+ @functools.wraps(func)
60
+ def wrapper(*args, **kwargs):
61
+ owner = Namespace._private_methods.get(func)
62
+
63
+ if owner is None:
64
+ raise PrivateAccessError(
65
+ f"Private member '{func.__name__}' has no namespace owner."
66
+ )
67
+
68
+ frame = inspect.currentframe().f_back
69
+
70
+ while frame:
71
+ for member in owner.__dict__.values():
72
+ if isinstance(member, staticmethod):
73
+ member = member.__func__
74
+
75
+ if isinstance(member, types.FunctionType):
76
+ if frame.f_code is member.__code__:
77
+ return func(*args, **kwargs)
78
+
79
+ frame = frame.f_back
80
+
81
+ raise PrivateAccessError(
82
+ f"Cannot access private member "
83
+ f"'{owner.__name__}.{func.__name__}' outside its namespace."
84
+ )
85
+
86
+ wrapper.__advscope_private__ = True
87
+ wrapper.__advscope_original__ = func
88
+
89
+ return wrapper
90
+
91
+ class GlobalScope:
92
+ """
93
+ Represents a global scope shared across the application.
94
+ """
95
+
96
+ def __new__(cls, *args, **kwargs):
97
+ raise TypeError(
98
+ "GlobalScope cannot be instantiated."
99
+ )
100
+
101
+ class LocalScopeMeta(type):
102
+ _storage = {}
103
+
104
+ def __getattr__(cls, name):
105
+ module = sys._getframe(1).f_globals["__name__"]
106
+
107
+ scope = cls._storage.get(module, {})
108
+
109
+ if name in scope:
110
+ return scope[name]
111
+
112
+ raise AttributeError(
113
+ f"{name!r} does not exist in local scope of {module}"
114
+ )
115
+
116
+ def __setattr__(cls, name, value):
117
+ if name == "_storage":
118
+ return super().__setattr__(name, value)
119
+
120
+ module = sys._getframe(1).f_globals["__name__"]
121
+
122
+ if module not in cls._storage:
123
+ cls._storage[module] = {}
124
+
125
+ cls._storage[module][name] = value
126
+
127
+
128
+ class LocalScope(metaclass=LocalScopeMeta):
129
+ """
130
+ Scope that belongs only to the module using it.
131
+ """
132
+
133
+ def __new__(cls, *args, **kwargs):
134
+ raise TypeError("LocalScope cannot be instantiated.")
135
+
136
+ class Scope:
137
+ """
138
+ A dynamic attribute-based scope.
139
+ """
140
+
141
+ def __init__(self, **kwargs):
142
+ for name, value in kwargs.items():
143
+ setattr(self, name, value)
144
+
145
+ def __repr__(self):
146
+ attrs = ", ".join(
147
+ f"{key}={value!r}"
148
+ for key, value in self.__dict__.items()
149
+ )
150
+ return f"Scope({attrs})"
@@ -0,0 +1,13 @@
1
+ Metadata-Version: 2.4
2
+ Name: advscope
3
+ Version: 0.1.0
4
+ Summary: Advanced scope utilities for Python.
5
+ Author: Olan
6
+ License: MIT
7
+ Keywords: scope,namespace,utilities
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3 :: Only
12
+ Classifier: Operating System :: OS Independent
13
+ Requires-Python: >=3.8
@@ -0,0 +1,7 @@
1
+ pyproject.toml
2
+ advscope/__init__.py
3
+ advscope/core.py
4
+ advscope.egg-info/PKG-INFO
5
+ advscope.egg-info/SOURCES.txt
6
+ advscope.egg-info/dependency_links.txt
7
+ advscope.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ advscope
@@ -0,0 +1,25 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "advscope"
7
+ version = "0.1.0"
8
+ description = "Advanced scope utilities for Python."
9
+ requires-python = ">=3.8"
10
+ license = { text = "MIT" }
11
+ authors = [
12
+ { name = "Olan" }
13
+ ]
14
+ keywords = [
15
+ "scope",
16
+ "namespace",
17
+ "utilities"
18
+ ]
19
+ classifiers = [
20
+ "Development Status :: 3 - Alpha",
21
+ "Intended Audience :: Developers",
22
+ "Programming Language :: Python :: 3",
23
+ "Programming Language :: Python :: 3 :: Only",
24
+ "Operating System :: OS Independent"
25
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+