Skip to content

Commit 0698846

Browse files
committed
fix typecheck
1 parent 0fe9a83 commit 0698846

2 files changed

Lines changed: 47 additions & 44 deletions

File tree

qcodes/instrument/instrument.py

Lines changed: 3 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -29,56 +29,15 @@
2929
log = logging.getLogger(__name__)
3030

3131

32-
class InstrumentMeta(ABCMeta):
33-
"""
34-
Metaclass used to customize Instrument creation. We want to register the
35-
instance iff __init__ successfully runs, however we can only do this if
36-
we customize the instance initialization process, otherwise there is no
37-
way to run `register_instance` after `__init__` but before the created
38-
instance is returned to the caller.
39-
40-
Instead we use the fact that `__new__` and `__init__` are called inside
41-
`type.__call__`
42-
(https://github.com/python/cpython/blob/main/Objects/typeobject.c#L1077,
43-
https://github.com/python/typeshed/blob/master/stdlib/builtins.pyi#L156)
44-
which we will overload to insert our own custom code AFTER `__init__` is
45-
complete. Note this is part of the spec and will work in alternate python
46-
implementations like pypy too.
47-
48-
We inherit from ABCMeta rather than type for backwards compatibility
49-
reasons. There may be instrument interfaces that are defined in
50-
terms of an ABC. Inheriting directly from type here would then give
51-
`TypeError: metaclass conflict: the metaclass of a derived class must
52-
be a (non-strict) subclass of the metaclasses of all its bases`
53-
for a class that inherits from ABC
54-
"""
55-
56-
def __call__(cls, *args: Any, **kwargs: Any) -> Any:
57-
"""
58-
Overloads `type.__call__` to add code that runs only if __init__ completes
59-
successfully.
60-
"""
61-
new_inst = super().__call__(*args, **kwargs)
62-
is_abstract = new_inst._is_abstract()
63-
if is_abstract:
64-
new_inst.close()
65-
raise NotImplementedError(
66-
f"{new_inst} has un-implemented Abstract Parameter "
67-
f"and cannot be initialized"
68-
)
69-
70-
new_inst.record_instance(new_inst)
71-
return new_inst
72-
7332

7433
# setting the metaclass will cause sphinx
7534
# to document the signature of `__call__`
7635
# rather than `__init__` that is unhelpful
7736
# for instruments.
7837
if "sphinx" in sys.modules:
79-
InstrumentMetaclass = ABCMeta
38+
from abc import ABCMeta as InstrumentMeta
8039
else:
81-
InstrumentMetaclass = InstrumentMeta
40+
from .instrument_meta import InstrumentMeta
8241

8342

8443
class InstrumentProtocol(Protocol):
@@ -96,7 +55,7 @@ def write(self, cmd: str) -> None:
9655
T = TypeVar("T", bound="Instrument")
9756

9857

99-
class Instrument(InstrumentBase, metaclass=InstrumentMetaclass):
58+
class Instrument(InstrumentBase, metaclass=InstrumentMeta):
10059

10160
"""
10261
Base class for all QCodes instruments.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
from abc import ABCMeta
2+
from typing import Any
3+
4+
5+
class InstrumentMeta(ABCMeta):
6+
"""
7+
Metaclass used to customize Instrument creation. We want to register the
8+
instance iff __init__ successfully runs, however we can only do this if
9+
we customize the instance initialization process, otherwise there is no
10+
way to run `register_instance` after `__init__` but before the created
11+
instance is returned to the caller.
12+
13+
Instead we use the fact that `__new__` and `__init__` are called inside
14+
`type.__call__`
15+
(https://github.com/python/cpython/blob/main/Objects/typeobject.c#L1077,
16+
https://github.com/python/typeshed/blob/master/stdlib/builtins.pyi#L156)
17+
which we will overload to insert our own custom code AFTER `__init__` is
18+
complete. Note this is part of the spec and will work in alternate python
19+
implementations like pypy too.
20+
21+
We inherit from ABCMeta rather than type for backwards compatibility
22+
reasons. There may be instrument interfaces that are defined in
23+
terms of an ABC. Inheriting directly from type here would then give
24+
`TypeError: metaclass conflict: the metaclass of a derived class must
25+
be a (non-strict) subclass of the metaclasses of all its bases`
26+
for a class that inherits from ABC
27+
"""
28+
29+
def __call__(cls, *args: Any, **kwargs: Any) -> Any:
30+
"""
31+
Overloads `type.__call__` to add code that runs only if __init__ completes
32+
successfully.
33+
"""
34+
new_inst = super().__call__(*args, **kwargs)
35+
is_abstract = new_inst._is_abstract()
36+
if is_abstract:
37+
new_inst.close()
38+
raise NotImplementedError(
39+
f"{new_inst} has un-implemented Abstract Parameter "
40+
f"and cannot be initialized"
41+
)
42+
43+
new_inst.record_instance(new_inst)
44+
return new_inst

0 commit comments

Comments
 (0)