classcore 1.0rc0__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.
@@ -0,0 +1,25 @@
1
+ # vim: set filetype=python fileencoding=utf-8:
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #============================================================================#
5
+ # #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
7
+ # you may not use this file except in compliance with the License. #
8
+ # You may obtain a copy of the License at #
9
+ # #
10
+ # http://www.apache.org/licenses/LICENSE-2.0 #
11
+ # #
12
+ # Unless required by applicable law or agreed to in writing, software #
13
+ # distributed under the License is distributed on an "AS IS" BASIS, #
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15
+ # See the License for the specific language governing permissions and #
16
+ # limitations under the License. #
17
+ # #
18
+ #============================================================================#
19
+
20
+
21
+ ''' Common constants, imports, and utilities. '''
22
+
23
+
24
+ from .imports import *
25
+ from .nomina import *
@@ -0,0 +1,42 @@
1
+ # vim: set filetype=python fileencoding=utf-8:
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #============================================================================#
5
+ # #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
7
+ # you may not use this file except in compliance with the License. #
8
+ # You may obtain a copy of the License at #
9
+ # #
10
+ # http://www.apache.org/licenses/LICENSE-2.0 #
11
+ # #
12
+ # Unless required by applicable law or agreed to in writing, software #
13
+ # distributed under the License is distributed on an "AS IS" BASIS, #
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15
+ # See the License for the specific language governing permissions and #
16
+ # limitations under the License. #
17
+ # #
18
+ #============================================================================#
19
+
20
+
21
+ ''' Common imports and type aliases used throughout the package. '''
22
+
23
+ # ruff: noqa: F401
24
+
25
+
26
+ from __future__ import annotations
27
+
28
+ import collections.abc as cabc
29
+ import dataclasses as dcls
30
+ import functools as funct
31
+ import inspect
32
+ import platform
33
+ import re
34
+ import sys
35
+ import types
36
+
37
+ import typing_extensions as typx
38
+ # --- BEGIN: Injected by Copier ---
39
+ # --- END: Injected by Copier ---
40
+
41
+
42
+ ComparisonResult: typx.TypeAlias = bool | types.NotImplementedType
classcore/__/nomina.py ADDED
@@ -0,0 +1,37 @@
1
+ # vim: set filetype=python fileencoding=utf-8:
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #============================================================================#
5
+ # #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
7
+ # you may not use this file except in compliance with the License. #
8
+ # You may obtain a copy of the License at #
9
+ # #
10
+ # http://www.apache.org/licenses/LICENSE-2.0 #
11
+ # #
12
+ # Unless required by applicable law or agreed to in writing, software #
13
+ # distributed under the License is distributed on an "AS IS" BASIS, #
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15
+ # See the License for the specific language governing permissions and #
16
+ # limitations under the License. #
17
+ # #
18
+ #============================================================================#
19
+
20
+
21
+ ''' Catalog of common type aliases. '''
22
+
23
+
24
+ from __future__ import annotations
25
+
26
+ from . import imports as __
27
+
28
+
29
+ NominativeArguments: __.typx.TypeAlias = __.cabc.Mapping[ str, __.typx.Any ]
30
+ PositionalArguments: __.typx.TypeAlias = __.cabc.Sequence[ __.typx.Any ]
31
+
32
+
33
+ package_name = __name__.split( '.', maxsplit = 1 )[ 0 ]
34
+
35
+
36
+ def calculate_attrname( level: str, core: str ) -> str:
37
+ return f"_{package_name}_{level}_{core}_"
classcore/__init__.py ADDED
@@ -0,0 +1,38 @@
1
+ # vim: set filetype=python fileencoding=utf-8:
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #============================================================================#
5
+ # #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
7
+ # you may not use this file except in compliance with the License. #
8
+ # You may obtain a copy of the License at #
9
+ # #
10
+ # http://www.apache.org/licenses/LICENSE-2.0 #
11
+ # #
12
+ # Unless required by applicable law or agreed to in writing, software #
13
+ # distributed under the License is distributed on an "AS IS" BASIS, #
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15
+ # See the License for the specific language governing permissions and #
16
+ # limitations under the License. #
17
+ # #
18
+ #============================================================================#
19
+
20
+
21
+ ''' Foundational class factories and decorators. '''
22
+
23
+
24
+ from . import __
25
+ from . import exceptions
26
+ from . import nomina
27
+ from . import standard
28
+ # --- BEGIN: Injected by Copier ---
29
+ # --- END: Injected by Copier ---
30
+
31
+ from .decorators import *
32
+ from .factories import *
33
+
34
+
35
+ __version__ = '1.0rc0'
36
+
37
+
38
+ standard.reclassify_modules( __name__, recursive = True )
@@ -0,0 +1,130 @@
1
+ # vim: set filetype=python fileencoding=utf-8:
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #============================================================================#
5
+ # #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
7
+ # you may not use this file except in compliance with the License. #
8
+ # You may obtain a copy of the License at #
9
+ # #
10
+ # http://www.apache.org/licenses/LICENSE-2.0 #
11
+ # #
12
+ # Unless required by applicable law or agreed to in writing, software #
13
+ # distributed under the License is distributed on an "AS IS" BASIS, #
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15
+ # See the License for the specific language governing permissions and #
16
+ # limitations under the License. #
17
+ # #
18
+ #============================================================================#
19
+
20
+
21
+ ''' Utilities for the decoration of classes, including metaclasses. '''
22
+
23
+
24
+ from __future__ import annotations
25
+
26
+ from . import __
27
+ from . import nomina as _nomina
28
+ from . import utilities as _utilities
29
+
30
+
31
+ _T = __.typx.TypeVar( '_T', bound = type )
32
+
33
+
34
+ def apply_decorators( cls: type, decorators: _nomina.Decorators ) -> type:
35
+ ''' Applies sequence of decorators to class.
36
+
37
+ If decorators replace classes (e.g., ``dataclass( slots = True )``),
38
+ then any necessary repairs are performed on the replacement class with
39
+ respect to the original. E.g., on CPython, the class closure cell is
40
+ repaired so that ``super`` operates correctly in methods of the
41
+ replacement class.
42
+ '''
43
+ for decorator in decorators:
44
+ cls_ = decorator( cls )
45
+ if cls is cls_: continue # Simple mutation. No replacement.
46
+ _utilities.repair_class_reproduction( cls, cls_ )
47
+ cls = cls_ # Use the replacement class.
48
+ return cls
49
+
50
+
51
+ def decoration_by(
52
+ *decorators: _nomina.Decorator,
53
+ preparers: _nomina.DecorationPreparers = ( ),
54
+ ) -> _nomina.Decorator:
55
+ ''' Class decorator which applies other class decorators.
56
+
57
+ Useful to apply a stack of decorators as a sequence.
58
+
59
+ Can optionally execute a sequence of decoration preparers before
60
+ applying the decorators proper. These can be used to alter the
61
+ decorators list itself, such as to inject decorators based on
62
+ introspection of the class.
63
+ '''
64
+ def decorate( cls: type ) -> type:
65
+ decorators_ = list( decorators )
66
+ for preparer in preparers: preparer( cls, decorators_ )
67
+ return apply_decorators( cls, decorators_ )
68
+
69
+ return decorate
70
+
71
+
72
+ def produce_class_construction_decorator(
73
+ attributes_namer: _nomina.AttributesNamer,
74
+ constructor: _nomina.ClassConstructor,
75
+ ) -> _nomina.Decorator:
76
+ ''' Produces metaclass decorator to control class construction.
77
+
78
+ Decorator overrides ``__new__`` on metaclass.
79
+ '''
80
+ def decorate( clscls: type[ _T ] ) -> type[ _T ]:
81
+ constructor_name = attributes_namer( 'classes', 'constructor' )
82
+ extant = getattr( clscls, constructor_name, None )
83
+ original = getattr( clscls, '__new__' )
84
+ if extant is original: return clscls
85
+
86
+ def construct(
87
+ clscls_: type[ _T ],
88
+ name: str,
89
+ bases: tuple[ type, ... ],
90
+ namespace: dict[ str, __.typx.Any ], *,
91
+ decorators: _nomina.Decorators = ( ),
92
+ **arguments: __.typx.Any,
93
+ ) -> type[ object ]:
94
+ return constructor(
95
+ clscls_, original,
96
+ name, bases, namespace, arguments, decorators )
97
+
98
+ setattr( clscls, constructor_name, construct )
99
+ setattr( clscls, '__new__', construct )
100
+ return clscls
101
+
102
+ return decorate
103
+
104
+
105
+ def produce_class_initialization_decorator(
106
+ attributes_namer: _nomina.AttributesNamer,
107
+ initializer: _nomina.ClassInitializer,
108
+ ) -> _nomina.Decorator:
109
+ ''' Produces metaclass decorator to control class initialization.
110
+
111
+ Decorator overrides ``__init__`` on metaclass.
112
+ '''
113
+ def decorate( clscls: type[ _T ] ) -> type[ _T ]:
114
+ initializer_name = attributes_namer( 'classes', 'initializer' )
115
+ extant = getattr( clscls, initializer_name, None )
116
+ original = getattr( clscls, '__init__' )
117
+ if extant is original: return clscls
118
+
119
+ @__.funct.wraps( original )
120
+ def initialize(
121
+ cls: type, *posargs: __.typx.Any, **nomargs: __.typx.Any
122
+ ) -> None:
123
+ ligation = __.funct.partial( original, cls )
124
+ initializer( cls, ligation, posargs, nomargs )
125
+
126
+ setattr( clscls, initializer_name, initialize )
127
+ clscls.__init__ = initialize
128
+ return clscls
129
+
130
+ return decorate
@@ -0,0 +1,59 @@
1
+ # vim: set filetype=python fileencoding=utf-8:
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #============================================================================#
5
+ # #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
7
+ # you may not use this file except in compliance with the License. #
8
+ # You may obtain a copy of the License at #
9
+ # #
10
+ # http://www.apache.org/licenses/LICENSE-2.0 #
11
+ # #
12
+ # Unless required by applicable law or agreed to in writing, software #
13
+ # distributed under the License is distributed on an "AS IS" BASIS, #
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15
+ # See the License for the specific language governing permissions and #
16
+ # limitations under the License. #
17
+ # #
18
+ #============================================================================#
19
+
20
+
21
+ ''' Exceptions from package. '''
22
+
23
+
24
+ from __future__ import annotations
25
+
26
+ from . import __
27
+ from . import standard as _standard
28
+
29
+
30
+ class Omniexception( # pyright: ignore[reportGeneralTypeIssues]
31
+ BaseException, _standard.Object,
32
+ instances_visibles = ( '__cause__', '__context__' ), # pyright: ignore[reportCallIssue]
33
+ ):
34
+ ''' Base exception for package. '''
35
+
36
+
37
+ class Omnierror( Exception, Omniexception ):
38
+ ''' Base error for package. '''
39
+
40
+
41
+ class AttributeImmutability( AttributeError, Omnierror ):
42
+
43
+ def __init__( self, name: str, target: str ):
44
+ super( ).__init__(
45
+ f"Could not assign or delete attribute {name!r} on {target}." )
46
+
47
+
48
+ class BehaviorExclusionInvalidity( TypeError, ValueError, Omnierror ):
49
+
50
+ def __init__( self, verifier: __.typx.Any ):
51
+ super( ).__init__(
52
+ f"Invalid behavior exclusion verifier: {verifier!r}" )
53
+
54
+
55
+ class ErrorProvideFailure( RuntimeError, Omnierror ):
56
+
57
+ def __init__( self, name: str, reason: str ):
58
+ super( ).__init__(
59
+ f"Could not provide error class {name!r}. Reason: {reason}" )
classcore/factories.py ADDED
@@ -0,0 +1,92 @@
1
+ # vim: set filetype=python fileencoding=utf-8:
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #============================================================================#
5
+ # #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
7
+ # you may not use this file except in compliance with the License. #
8
+ # You may obtain a copy of the License at #
9
+ # #
10
+ # http://www.apache.org/licenses/LICENSE-2.0 #
11
+ # #
12
+ # Unless required by applicable law or agreed to in writing, software #
13
+ # distributed under the License is distributed on an "AS IS" BASIS, #
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15
+ # See the License for the specific language governing permissions and #
16
+ # limitations under the License. #
17
+ # #
18
+ #============================================================================#
19
+
20
+
21
+ ''' Factories which produce metaclass implementations. '''
22
+
23
+
24
+ from __future__ import annotations
25
+
26
+ from . import __
27
+ from . import decorators as _decorators
28
+ from . import nomina as _nomina
29
+ from . import utilities as _utilities
30
+
31
+
32
+ _T = __.typx.TypeVar( '_T', bound = type )
33
+
34
+
35
+ def produce_class_constructor(
36
+ attributes_namer: _nomina.AttributesNamer,
37
+ preprocessors: _nomina.ProduceConstructorPreprocsArgument = ( ),
38
+ postprocessors: _nomina.ProduceConstructorPostprocsArgument = ( ),
39
+ ) -> _nomina.ClassConstructor:
40
+ ''' Produces constructors for classes. '''
41
+
42
+ def construct( # noqa: PLR0913
43
+ clscls: type[ _T ],
44
+ superf: _nomina.ClassConstructorLigation,
45
+ name: str,
46
+ bases: tuple[ type, ... ],
47
+ namespace: dict[ str, __.typx.Any ],
48
+ arguments: __.NominativeArguments,
49
+ decorators: _nomina.Decorators,
50
+ ) -> type:
51
+ ''' Constructs class, applying decorators and hooks. '''
52
+ bases_ = list( bases )
53
+ arguments_ = dict( arguments )
54
+ decorators_ = list( decorators )
55
+ for prep in preprocessors:
56
+ prep( clscls, name, bases_, namespace, arguments_, decorators_ )
57
+ cls = superf( clscls, name, tuple( bases_ ), namespace, **arguments_ )
58
+ # Some decorators create new classes, which invokes this method again.
59
+ # Short-circuit to prevent recursive decoration and other tangles.
60
+ progress_name = attributes_namer( 'class', 'in_progress' )
61
+ in_progress = _utilities.getattr0( cls, progress_name, False )
62
+ if in_progress: return cls
63
+ setattr( cls, progress_name, True )
64
+ for postp in postprocessors: postp( cls, decorators_ )
65
+ cls = _decorators.apply_decorators( cls, decorators_ )
66
+ setattr( cls, progress_name, False )
67
+ return cls
68
+
69
+ return construct
70
+
71
+
72
+ def produce_class_initializer(
73
+ attributes_namer: _nomina.AttributesNamer,
74
+ completers: _nomina.ProduceInitializerCompletersArgument = ( ),
75
+ ) -> _nomina.ClassInitializer:
76
+ ''' Produces initializers for classes. '''
77
+
78
+ def initialize(
79
+ cls: type,
80
+ superf: _nomina.InitializerLigation,
81
+ posargs: __.PositionalArguments,
82
+ nomargs: __.NominativeArguments,
83
+ ) -> None:
84
+ ''' Initializes class, applying hooks. '''
85
+ superf( *posargs, **nomargs )
86
+ progress_name = attributes_namer( 'class', 'in_progress' )
87
+ in_progress = _utilities.getattr0( cls, progress_name, False )
88
+ if in_progress: return # If non-empty, then not top-level.
89
+ delattr( cls, progress_name )
90
+ for completer in completers: completer( cls )
91
+
92
+ return initialize
classcore/nomina.py ADDED
@@ -0,0 +1,162 @@
1
+ # vim: set filetype=python fileencoding=utf-8:
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #============================================================================#
5
+ # #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
7
+ # you may not use this file except in compliance with the License. #
8
+ # You may obtain a copy of the License at #
9
+ # #
10
+ # http://www.apache.org/licenses/LICENSE-2.0 #
11
+ # #
12
+ # Unless required by applicable law or agreed to in writing, software #
13
+ # distributed under the License is distributed on an "AS IS" BASIS, #
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15
+ # See the License for the specific language governing permissions and #
16
+ # limitations under the License. #
17
+ # #
18
+ #============================================================================#
19
+
20
+
21
+ ''' Catalog of common type aliases. '''
22
+
23
+
24
+ from __future__ import annotations
25
+
26
+ from . import __
27
+
28
+
29
+ AttributesNamer: __.typx.TypeAlias = (
30
+ __.cabc.Callable[ [ str, str ], str ] )
31
+
32
+ Decorator: __.typx.TypeAlias = __.cabc.Callable[ [ type ], type ]
33
+ Decorators: __.typx.TypeAlias = __.cabc.Sequence[ Decorator ]
34
+ DecoratorsMutable: __.typx.TypeAlias = __.cabc.MutableSequence[ Decorator ]
35
+
36
+ DecorationPreparer: __.typx.TypeAlias = (
37
+ __.cabc.Callable[ [ type, DecoratorsMutable ], None ] )
38
+ DecorationPreparers: __.typx.TypeAlias = (
39
+ __.cabc.Sequence[ DecorationPreparer ] )
40
+
41
+ ClassConstructorLigation: __.typx.TypeAlias = __.typx.Annotated[
42
+ __.cabc.Callable[ ..., type ],
43
+ __.typx.Doc(
44
+ ''' Bound class constructor function.
45
+
46
+ Usually from ``super( ).__new__`` or a partial function.
47
+ ''' ),
48
+ ]
49
+ InitializerLigation: __.typx.TypeAlias = __.typx.Annotated[
50
+ __.cabc.Callable[ ..., None ],
51
+ __.typx.Doc(
52
+ ''' Bound initializer function.
53
+
54
+ Usually from ``super( ).__init__`` or a partial function.
55
+ ''' ),
56
+ ]
57
+ AssignerLigation: __.typx.TypeAlias = __.typx.Annotated[
58
+ __.cabc.Callable[ [ str, __.typx.Any ], None ],
59
+ __.typx.Doc(
60
+ ''' Bound attributes assigner function.
61
+
62
+ Usually from ``super( ).__setattr__`` or a partial function.
63
+ ''' ),
64
+ ]
65
+ DeleterLigation: __.typx.TypeAlias = __.typx.Annotated[
66
+ __.cabc.Callable[ [ str ], None ],
67
+ __.typx.Doc(
68
+ ''' Bound attributes deleter function.
69
+
70
+ Usually from ``super( ).__delattr__`` or a partial function.
71
+ ''' ),
72
+ ]
73
+ SurveyorLigation: __.typx.TypeAlias = __.typx.Annotated[
74
+ __.cabc.Callable[ [ ], __.cabc.Iterable[ str ] ],
75
+ __.typx.Doc(
76
+ ''' Bound attributes surveyor function.
77
+
78
+ Usually from ``super( ).__dir__`` or a partial function.
79
+ ''' ),
80
+ ]
81
+
82
+
83
+ ClassConstructionPreprocessor: __.typx.TypeAlias = __.typx.Annotated[
84
+ __.cabc.Callable[
85
+ [
86
+ type[ type ], # metaclass
87
+ str, # class name
88
+ list[ type ], # bases (mutable)
89
+ dict[ str, __.typx.Any ], # namespace (mutable)
90
+ dict[ str, __.typx.Any ], # arguments (mutable)
91
+ DecoratorsMutable, # decorators (mutable)
92
+ ],
93
+ None
94
+ ],
95
+ __.typx.Doc(
96
+ ''' Processes class data before construction.
97
+
98
+ For use cases, such as argument conversion.
99
+ ''' ),
100
+ ]
101
+ ClassConstructionPostprocessor: __.typx.TypeAlias = __.typx.Annotated[
102
+ __.cabc.Callable[ [ type, DecoratorsMutable ], None ],
103
+ __.typx.Doc(
104
+ ''' Processes class before decoration.
105
+
106
+ For use cases, such as decorator list manipulation.
107
+ ''' ),
108
+ ]
109
+ # TODO: ClassInitializationPreparer (arguments mutation)
110
+ ClassInitializationCompleter: __.typx.TypeAlias = __.typx.Annotated[
111
+ __.cabc.Callable[ [ type ], None ],
112
+ __.typx.Doc(
113
+ ''' Completes initialization of class.
114
+
115
+ For use cases, such as enabling immutability once all other
116
+ initialization has occurred.
117
+ ''' ),
118
+ ]
119
+
120
+
121
+ ClassConstructor: __.typx.TypeAlias = __.typx.Annotated[
122
+ __.cabc.Callable[
123
+ [
124
+ type,
125
+ ClassConstructorLigation,
126
+ str,
127
+ tuple[ type, ... ],
128
+ dict[ str, __.typx.Any ],
129
+ __.NominativeArguments,
130
+ Decorators,
131
+ ],
132
+ type
133
+ ],
134
+ __.typx.Doc( ''' Constructor to use with metaclass. ''' ),
135
+ ]
136
+ ClassInitializer: __.typx.TypeAlias = __.typx.Annotated[
137
+ __.cabc.Callable[
138
+ [
139
+ type,
140
+ InitializerLigation,
141
+ __.PositionalArguments,
142
+ __.NominativeArguments,
143
+ ],
144
+ None
145
+ ],
146
+ __.typx.Doc( ''' Initializer to use with metaclass. ''' ),
147
+ ]
148
+
149
+
150
+ ProduceConstructorPreprocsArgument: __.typx.TypeAlias = __.typx.Annotated[
151
+ __.cabc.Sequence[ ClassConstructionPreprocessor ],
152
+ __.typx.Doc( ''' Processors to apply before construction of class. ''' ),
153
+ ]
154
+ ProduceConstructorPostprocsArgument: __.typx.TypeAlias = __.typx.Annotated[
155
+ __.cabc.Sequence[ ClassConstructionPostprocessor ],
156
+ __.typx.Doc( ''' Processors to apply before decoration of class. ''' ),
157
+ ]
158
+ ProduceInitializerCompletersArgument: __.typx.TypeAlias = __.typx.Annotated[
159
+ __.cabc.Sequence[ ClassInitializationCompleter ],
160
+ __.typx.Doc(
161
+ ''' Processors to apply at final stage of class initialization. ''' ),
162
+ ]
classcore/py.typed ADDED
File without changes
@@ -0,0 +1,46 @@
1
+ # vim: set filetype=python fileencoding=utf-8:
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #============================================================================#
5
+ # #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
7
+ # you may not use this file except in compliance with the License. #
8
+ # You may obtain a copy of the License at #
9
+ # #
10
+ # http://www.apache.org/licenses/LICENSE-2.0 #
11
+ # #
12
+ # Unless required by applicable law or agreed to in writing, software #
13
+ # distributed under the License is distributed on an "AS IS" BASIS, #
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15
+ # See the License for the specific language governing permissions and #
16
+ # limitations under the License. #
17
+ # #
18
+ #============================================================================#
19
+
20
+
21
+ ''' Common constants, imports, and utilities. '''
22
+
23
+
24
+ from __future__ import annotations
25
+
26
+ from ..__ import * # noqa: F403
27
+
28
+
29
+ def is_public_identifier( name: str ) -> bool:
30
+ ''' Is Python identifier public? '''
31
+ return not name.startswith( '_' )
32
+
33
+
34
+ def provide_error_class( name: str ) -> type[ Exception ]:
35
+ ''' Produces error class for this package. '''
36
+ match name:
37
+ case 'AttributeImmutability':
38
+ from ..exceptions import AttributeImmutability as error
39
+ case _:
40
+ from ..exceptions import ErrorProvideFailure
41
+ raise ErrorProvideFailure( name, reason = 'Does not exist.' )
42
+ return error
43
+
44
+
45
+ mutables_default = ( )
46
+ visibles_default = ( is_public_identifier, )
@@ -0,0 +1,28 @@
1
+ # vim: set filetype=python fileencoding=utf-8:
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #============================================================================#
5
+ # #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); #
7
+ # you may not use this file except in compliance with the License. #
8
+ # You may obtain a copy of the License at #
9
+ # #
10
+ # http://www.apache.org/licenses/LICENSE-2.0 #
11
+ # #
12
+ # Unless required by applicable law or agreed to in writing, software #
13
+ # distributed under the License is distributed on an "AS IS" BASIS, #
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15
+ # See the License for the specific language governing permissions and #
16
+ # limitations under the License. #
17
+ # #
18
+ #============================================================================#
19
+
20
+
21
+ ''' Decorators and class factories providing concealment and immutability. '''
22
+
23
+
24
+ from __future__ import annotations
25
+
26
+ from .classes import *
27
+ from .decorators import *
28
+ from .modules import *