Skip to content

Commit 482b87f

Browse files
committed
Standard: Classes: Mitigate Pyright false positives for subclasses.
Thread about better mitigation, which includes base classes too: microsoft/pyright#10537 Also, * Exceptions: Remove Pyright ignores since subclasses case has been mitigated with unfortunate '__init_subclass__' hack. * Internals: Centralize definition of 'type'-constrained type variable. * Standard: Nomina: Add type alias for Dynadoc configuration.
1 parent 0de159b commit 482b87f

8 files changed

Lines changed: 77 additions & 27 deletions

File tree

sources/classcore/__/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
from .nomina import *
2727

2828

29+
T = typx.TypeVar( 'T', bound = type )
30+
31+
2932
dictproxy_empty: cabc.Mapping[ str, str ] = types.MappingProxyType( { } )
3033

3134

sources/classcore/decorators.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@
2626
from . import utilities as _utilities
2727

2828

29-
_T = __.typx.TypeVar( '_T', bound = type )
30-
31-
3229
def apply_decorators( cls: type, decorators: _nomina.Decorators ) -> type:
3330
''' Applies sequence of decorators to class.
3431
@@ -75,14 +72,14 @@ def produce_class_construction_decorator(
7572
7673
Decorator overrides ``__new__`` on metaclass.
7774
'''
78-
def decorate( clscls: type[ _T ] ) -> type[ _T ]:
75+
def decorate( clscls: type[ __.T ] ) -> type[ __.T ]:
7976
constructor_name = attributes_namer( 'classes', 'constructor' )
8077
extant = getattr( clscls, constructor_name, None )
8178
original = getattr( clscls, '__new__' )
8279
if extant is original: return clscls
8380

8481
def construct(
85-
clscls_: type[ _T ],
82+
clscls_: type[ __.T ],
8683
name: str,
8784
bases: tuple[ type, ... ],
8885
namespace: dict[ str, __.typx.Any ], *,
@@ -108,7 +105,7 @@ def produce_class_initialization_decorator(
108105
109106
Decorator overrides ``__init__`` on metaclass.
110107
'''
111-
def decorate( clscls: type[ _T ] ) -> type[ _T ]:
108+
def decorate( clscls: type[ __.T ] ) -> type[ __.T ]:
112109
initializer_name = attributes_namer( 'classes', 'initializer' )
113110
extant = getattr( clscls, initializer_name, None )
114111
original = getattr( clscls, '__init__' )

sources/classcore/exceptions.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,11 @@
2929
# Exception classes are immutable. Exclude from docstring updates.
3030
__.dynadoc.IntrospectionLimit(
3131
targets_exclusions = __.dynadoc.IntrospectionTargets.Class ) )
32-
# TODO: Mix 'with_docstring' decorator into standard sequence.
3332

3433

35-
class Omniexception( # pyright: ignore[reportGeneralTypeIssues]
34+
class Omniexception(
3635
BaseException, _standard.Object,
37-
instances_visibles = ( '__cause__', '__context__' ), # pyright: ignore[reportCallIssue]
36+
instances_visibles = ( '__cause__', '__context__' ),
3837
):
3938
''' Base exception for package. '''
4039

sources/classcore/factories.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@
2727
from . import utilities as _utilities
2828

2929

30-
_T = __.typx.TypeVar( '_T', bound = type )
31-
32-
3330
def produce_class_constructor(
3431
attributes_namer: _nomina.AttributesNamer,
3532
preprocessors: _nomina.ProduceConstructorPreprocsArgument = ( ),
@@ -38,7 +35,7 @@ def produce_class_constructor(
3835
''' Produces constructors for classes. '''
3936

4037
def construct( # noqa: PLR0913
41-
clscls: type[ _T ],
38+
clscls: type[ __.T ],
4239
superf: _nomina.ClassConstructorLigation,
4340
name: str,
4441
bases: tuple[ type, ... ],

sources/classcore/standard/behaviors.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,6 @@ def produce_dynadoc_configuration(
295295
preserve: _nomina.DynadocPreserveArgument = True,
296296
table: _nomina.DynadocTableArgument = __.dictproxy_empty,
297297
) -> _nomina.ProduceDynadocConfigurationReturn:
298-
# TODO: Move to Dynadoc package.
299298
return __.types.MappingProxyType( dict(
300299
context = _dynadoc_context,
301300
introspection = _dynadoc_introspection,

sources/classcore/standard/classes.py

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,47 @@
1919

2020

2121
''' Standard classes and class factories. '''
22+
# TODO: Mitigate issue with decoration obscuring signature of '__new__'
23+
# to typecheckers:
24+
# https://github.com/microsoft/pyright/discussions/10537.
25+
# Get rid of '__init_subclass__' hack which only addresses problem
26+
# for subclasses but not base classes.
2227

2328

2429
from . import __
2530
from . import decorators as _decorators
31+
# from . import nomina as _nomina
2632

2733

2834
_dynadoc_introspection_limit_ = (
2935
# Standard classes are immutable. Exclude from docstring updates.
3036
__.dynadoc.IntrospectionLimit(
3137
targets_exclusions = __.dynadoc.IntrospectionTargets.Class ) )
32-
# TODO: Mix 'with_docstring' decorator into standard sequence.
38+
39+
40+
# class _CfcExtraArguments( __.typx.TypedDict, total = False ):
41+
#
42+
# class_mutables: _nomina.BehaviorExclusionVerifiersOmni
43+
# class_visibles: _nomina.BehaviorExclusionVerifiersOmni
44+
# decorators: _nomina.Decorators
45+
# dynadoc_configuration: _nomina.DynadocConfiguration
46+
# instances_mutables: _nomina.BehaviorExclusionVerifiersOmni
47+
# instances_visibles: _nomina.BehaviorExclusionVerifiersOmni
3348

3449

3550
@_decorators.decoration_by( *_decorators.class_factory_decorators )
3651
class Class( type ): pass
3752

53+
# def __new__(
54+
# clscls: type[ __.T ],
55+
# name: str,
56+
# bases: tuple[ type, ... ],
57+
# namespace: dict[ str, __.typx.Any ],
58+
# *,
59+
# instances_mutables: _nomina.BehaviorExclusionVerifiersOmni = ( ),
60+
# ) -> __.T:
61+
# return super( ).__new__( clscls, name, bases, namespace )
62+
3863

3964
@_decorators.decoration_by( *_decorators.class_factory_decorators )
4065
@__.typx.dataclass_transform( frozen_default = True, kw_only_default = True )
@@ -60,36 +85,68 @@ class ProtocolDataclass( type( __.typx.Protocol ) ): pass
6085
class ProtocolDataclassMutable( type( __.typx.Protocol ) ): pass
6186

6287

63-
class Object( metaclass = Class ): pass
88+
class Object( metaclass = Class ):
89+
90+
def __init_subclass__( # Typechecker appeasement.
91+
cls: type, /, **arguments: __.typx.Any
92+
) -> None: super( ).__init_subclass__( **arguments )
6493

6594

6695
class ObjectMutable( # pyright: ignore[reportGeneralTypeIssues]
6796
metaclass = Class,
6897
instances_mutables = '*', # pyright: ignore[reportCallIssue]
69-
): pass
98+
):
99+
100+
def __init_subclass__( # Typechecker appeasement.
101+
cls: type, /, **arguments: __.typx.Any
102+
) -> None: super( ).__init_subclass__( **arguments )
103+
70104

105+
class DataclassObject( metaclass = Dataclass ):
71106

72-
class DataclassObject( metaclass = Dataclass ): pass
107+
def __init_subclass__( # Typechecker appeasement.
108+
cls: type, /, **arguments: __.typx.Any
109+
) -> None: super( ).__init_subclass__( **arguments )
73110

74111

75-
class DataclassObjectMutable( metaclass = DataclassMutable ): pass
112+
class DataclassObjectMutable( metaclass = DataclassMutable ):
76113

114+
def __init_subclass__( # Typechecker appeasement.
115+
cls: type, /, **arguments: __.typx.Any
116+
) -> None: super( ).__init_subclass__( **arguments )
77117

78-
class Protocol( __.typx.Protocol, metaclass = ProtocolClass ): pass
118+
119+
class Protocol( __.typx.Protocol, metaclass = ProtocolClass ):
120+
121+
def __init_subclass__( # Typechecker appeasement.
122+
cls: type, /, **arguments: __.typx.Any
123+
) -> None: super( ).__init_subclass__( **arguments )
79124

80125

81126
class ProtocolMutable( # pyright: ignore[reportGeneralTypeIssues]
82127
__.typx.Protocol,
83128
metaclass = ProtocolClass,
84129
instances_mutables = '*', # pyright: ignore[reportCallIssue]
85-
): pass
130+
):
131+
132+
def __init_subclass__( # Typechecker appeasement.
133+
cls: type, /, **arguments: __.typx.Any
134+
) -> None: super( ).__init_subclass__( **arguments )
86135

87136

88137
class DataclassProtocol(
89138
__.typx.Protocol, metaclass = ProtocolDataclass,
90-
): pass
139+
):
140+
141+
def __init_subclass__( # Typechecker appeasement.
142+
cls: type, /, **arguments: __.typx.Any
143+
) -> None: super( ).__init_subclass__( **arguments )
91144

92145

93146
class DataclassProtocolMutable(
94147
__.typx.Protocol, metaclass = ProtocolDataclassMutable,
95-
): pass
148+
):
149+
150+
def __init_subclass__( # Typechecker appeasement.
151+
cls: type, /, **arguments: __.typx.Any
152+
) -> None: super( ).__init_subclass__( **arguments )

sources/classcore/standard/modules.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
# Standard classes are immutable. Exclude from docstring updates.
3333
__.dynadoc.IntrospectionLimit(
3434
targets_exclusions = __.dynadoc.IntrospectionTargets.Class ) )
35-
# TODO: Mix 'with_docstring' decorator into standard sequence.
3635

3736

3837
class Module( __.types.ModuleType, _classes.Object ):

sources/classcore/standard/nomina.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,7 @@ def __call__( # pragma: no branch
9898
) -> None: raise NotImplementedError
9999

100100

101-
# TODO: Remove Dynadoc-related argument aliases after
102-
# 'produce_dynadoc_configuration' is moved to Dynadoc package.
101+
DynadocConfiguration: __.typx.TypeAlias = __.cabc.Mapping[ str, __.typx.Any ]
103102
DynadocContextArgument: __.typx.TypeAlias = __.typx.Annotated[
104103
__.dynadoc.Context,
105104
__.dynadoc.Doc(
@@ -128,7 +127,7 @@ def __call__( # pragma: no branch
128127
__.dynadoc.Doc( ''' Table of documentation fragments. ''' ),
129128
]
130129
ProduceDynadocConfigurationReturn: __.typx.TypeAlias = __.typx.Annotated[
131-
__.cabc.Mapping[ str, __.typx.Any ],
130+
DynadocConfiguration,
132131
__.dynadoc.Doc(
133132
''' Dynadoc configuration dictionary.
134133

0 commit comments

Comments
 (0)