- Move basic model code into noisicaa.model. - Change internal property storage to protobufs. - Commands also use protobufs. - All serializations uses protobufs. - Object are managed by a Pool object. - Object references are stored as object IDs and dereferenced lazily. Also: - Everything is pylint clean. - noisicaa.music and most of noisicaa.ui are now mypy strict. - Generate mypy stubs for generated protobuf code. - Cleaned up some obsolete cruft. - Some improvements to runtests.looper
parent
1007c3968d
commit
e60d6a11d0
@ -0,0 +1 @@
|
||||
__version__ = ... # type: str
|
@ -0,0 +1,161 @@
|
||||
from typing import Any
|
||||
|
||||
from .message import Message
|
||||
|
||||
class Error(Exception): ...
|
||||
class TypeTransformationError(Error): ...
|
||||
|
||||
class DescriptorMetaclass(type):
|
||||
def __instancecheck__(cls, obj): ...
|
||||
|
||||
class DescriptorBase:
|
||||
__metaclass__ = DescriptorMetaclass
|
||||
has_options = ... # type: Any
|
||||
def __init__(self, options, options_class_name) -> None: ...
|
||||
def GetOptions(self): ...
|
||||
|
||||
class _NestedDescriptorBase(DescriptorBase):
|
||||
name = ... # type: Any
|
||||
full_name = ... # type: Any
|
||||
file = ... # type: Any
|
||||
containing_type = ... # type: Any
|
||||
def __init__(self, options, options_class_name, name, full_name, file, containing_type, serialized_start=..., serialized_end=...) -> None: ...
|
||||
def GetTopLevelContainingType(self): ...
|
||||
def CopyToProto(self, proto): ...
|
||||
|
||||
class Descriptor(_NestedDescriptorBase):
|
||||
def __new__(cls, name, full_name, filename, containing_type, fields, nested_types, enum_types, extensions, options=..., is_extendable=..., extension_ranges=..., oneofs=..., file=..., serialized_start=..., serialized_end=..., syntax=...): ...
|
||||
fields = ... # type: Any
|
||||
fields_by_number = ... # type: Any
|
||||
fields_by_name = ... # type: Any
|
||||
nested_types = ... # type: Any
|
||||
nested_types_by_name = ... # type: Any
|
||||
enum_types = ... # type: Any
|
||||
enum_types_by_name = ... # type: Any
|
||||
enum_values_by_name = ... # type: Any
|
||||
extensions = ... # type: Any
|
||||
extensions_by_name = ... # type: Any
|
||||
is_extendable = ... # type: Any
|
||||
extension_ranges = ... # type: Any
|
||||
oneofs = ... # type: Any
|
||||
oneofs_by_name = ... # type: Any
|
||||
syntax = ... # type: Any
|
||||
def __init__(self, name, full_name, filename, containing_type, fields, nested_types, enum_types, extensions, options=..., is_extendable=..., extension_ranges=..., oneofs=..., file=..., serialized_start=..., serialized_end=..., syntax=...) -> None: ...
|
||||
def EnumValueName(self, enum, value): ...
|
||||
def CopyToProto(self, proto): ...
|
||||
|
||||
class FieldDescriptor(DescriptorBase):
|
||||
TYPE_DOUBLE = ... # type: Any
|
||||
TYPE_FLOAT = ... # type: Any
|
||||
TYPE_INT64 = ... # type: Any
|
||||
TYPE_UINT64 = ... # type: Any
|
||||
TYPE_INT32 = ... # type: Any
|
||||
TYPE_FIXED64 = ... # type: Any
|
||||
TYPE_FIXED32 = ... # type: Any
|
||||
TYPE_BOOL = ... # type: Any
|
||||
TYPE_STRING = ... # type: Any
|
||||
TYPE_GROUP = ... # type: Any
|
||||
TYPE_MESSAGE = ... # type: Any
|
||||
TYPE_BYTES = ... # type: Any
|
||||
TYPE_UINT32 = ... # type: Any
|
||||
TYPE_ENUM = ... # type: Any
|
||||
TYPE_SFIXED32 = ... # type: Any
|
||||
TYPE_SFIXED64 = ... # type: Any
|
||||
TYPE_SINT32 = ... # type: Any
|
||||
TYPE_SINT64 = ... # type: Any
|
||||
MAX_TYPE = ... # type: Any
|
||||
CPPTYPE_INT32 = ... # type: Any
|
||||
CPPTYPE_INT64 = ... # type: Any
|
||||
CPPTYPE_UINT32 = ... # type: Any
|
||||
CPPTYPE_UINT64 = ... # type: Any
|
||||
CPPTYPE_DOUBLE = ... # type: Any
|
||||
CPPTYPE_FLOAT = ... # type: Any
|
||||
CPPTYPE_BOOL = ... # type: Any
|
||||
CPPTYPE_ENUM = ... # type: Any
|
||||
CPPTYPE_STRING = ... # type: Any
|
||||
CPPTYPE_MESSAGE = ... # type: Any
|
||||
MAX_CPPTYPE = ... # type: Any
|
||||
LABEL_OPTIONAL = ... # type: Any
|
||||
LABEL_REQUIRED = ... # type: Any
|
||||
LABEL_REPEATED = ... # type: Any
|
||||
MAX_LABEL = ... # type: Any
|
||||
MAX_FIELD_NUMBER = ... # type: Any
|
||||
FIRST_RESERVED_FIELD_NUMBER = ... # type: Any
|
||||
LAST_RESERVED_FIELD_NUMBER = ... # type: Any
|
||||
def __new__(cls, name, full_name, index, number, type, cpp_type, label, default_value, message_type, enum_type, containing_type, is_extension, extension_scope, options=..., file=..., has_default_value=..., containing_oneof=...): ...
|
||||
name = ... # type: Any
|
||||
full_name = ... # type: Any
|
||||
index = ... # type: Any
|
||||
number = ... # type: Any
|
||||
type = ... # type: Any
|
||||
cpp_type = ... # type: Any
|
||||
label = ... # type: Any
|
||||
has_default_value = ... # type: Any
|
||||
default_value = ... # type: Any
|
||||
containing_type = ... # type: Any
|
||||
message_type = ... # type: Any
|
||||
enum_type = ... # type: Any
|
||||
is_extension = ... # type: Any
|
||||
extension_scope = ... # type: Any
|
||||
containing_oneof = ... # type: Any
|
||||
def __init__(self, name, full_name, index, number, type, cpp_type, label, default_value, message_type, enum_type, containing_type, is_extension, extension_scope, options=..., file=..., has_default_value=..., containing_oneof=...) -> None: ...
|
||||
@staticmethod
|
||||
def ProtoTypeToCppProtoType(proto_type): ...
|
||||
|
||||
class EnumDescriptor(_NestedDescriptorBase):
|
||||
def __new__(cls, name, full_name, filename, values, containing_type=..., options=..., file=..., serialized_start=..., serialized_end=...): ...
|
||||
values = ... # type: Any
|
||||
values_by_name = ... # type: Any
|
||||
values_by_number = ... # type: Any
|
||||
def __init__(self, name, full_name, filename, values, containing_type=..., options=..., file=..., serialized_start=..., serialized_end=...) -> None: ...
|
||||
def CopyToProto(self, proto): ...
|
||||
|
||||
class EnumValueDescriptor(DescriptorBase):
|
||||
def __new__(cls, name, index, number, type=..., options=...): ...
|
||||
name = ... # type: Any
|
||||
index = ... # type: Any
|
||||
number = ... # type: Any
|
||||
type = ... # type: Any
|
||||
def __init__(self, name, index, number, type=..., options=...) -> None: ...
|
||||
|
||||
class OneofDescriptor:
|
||||
def __new__(cls, name, full_name, index, containing_type, fields): ...
|
||||
name = ... # type: Any
|
||||
full_name = ... # type: Any
|
||||
index = ... # type: Any
|
||||
containing_type = ... # type: Any
|
||||
fields = ... # type: Any
|
||||
def __init__(self, name, full_name, index, containing_type, fields) -> None: ...
|
||||
|
||||
class ServiceDescriptor(_NestedDescriptorBase):
|
||||
index = ... # type: Any
|
||||
methods = ... # type: Any
|
||||
def __init__(self, name, full_name, index, methods, options=..., file=..., serialized_start=..., serialized_end=...) -> None: ...
|
||||
def FindMethodByName(self, name): ...
|
||||
def CopyToProto(self, proto): ...
|
||||
|
||||
class MethodDescriptor(DescriptorBase):
|
||||
name = ... # type: Any
|
||||
full_name = ... # type: Any
|
||||
index = ... # type: Any
|
||||
containing_service = ... # type: Any
|
||||
input_type = ... # type: Any
|
||||
output_type = ... # type: Any
|
||||
def __init__(self, name, full_name, index, containing_service, input_type, output_type, options=...) -> None: ...
|
||||
|
||||
class FileDescriptor(DescriptorBase):
|
||||
def __new__(cls, name, package, options=..., serialized_pb=..., dependencies=..., syntax=...): ...
|
||||
_options = ... # type: Any
|
||||
message_types_by_name = ... # type: Any
|
||||
name = ... # type: Any
|
||||
package = ... # type: Any
|
||||
syntax = ... # type: Any
|
||||
serialized_pb = ... # type: Any
|
||||
enum_types_by_name = ... # type: Any
|
||||
extensions_by_name = ... # type: Any
|
||||
dependencies = ... # type: Any
|
||||
def __init__(self, name, package, options=..., serialized_pb=..., dependencies=..., syntax=...) -> None: ...
|
||||
def CopyToProto(self, proto): ...
|
||||
|
||||
def MakeDescriptor(desc_proto, package=..., build_file_if_cpp=..., syntax=...): ...
|
||||
def _ParseOptions(message: Message, string: str) -> Message: ...
|
@ -0,0 +1,2 @@
|
||||
class FileOptions(object): ...
|
||||
class FieldOptions(object): ...
|
@ -0,0 +1,18 @@
|
||||
from typing import Any, Optional
|
||||
|
||||
class DescriptorPool:
|
||||
def __new__(cls, descriptor_db: Optional[Any] = ...): ...
|
||||
def __init__(self, descriptor_db: Optional[Any] = ...) -> None: ...
|
||||
def Add(self, file_desc_proto): ...
|
||||
def AddSerializedFile(self, serialized_file_desc_proto): ...
|
||||
def AddDescriptor(self, desc): ...
|
||||
def AddEnumDescriptor(self, enum_desc): ...
|
||||
def AddFileDescriptor(self, file_desc): ...
|
||||
def FindFileByName(self, file_name): ...
|
||||
def FindFileContainingSymbol(self, symbol): ...
|
||||
def FindMessageTypeByName(self, full_name): ...
|
||||
def FindEnumTypeByName(self, full_name): ...
|
||||
def FindFieldByName(self, full_name): ...
|
||||
def FindExtensionByName(self, full_name): ...
|
||||
|
||||
def Default(): ...
|
@ -0,0 +1,35 @@
|
||||
from google.protobuf.descriptor import Descriptor
|
||||
from google.protobuf.internal.message_listener import MessageListener
|
||||
from google.protobuf.message import Message
|
||||
from typing import (
|
||||
MutableSequence, Sequence, TypeVar, Generic, Any, Iterator, Iterable,
|
||||
Union, Optional, Callable
|
||||
)
|
||||
|
||||
_T = TypeVar('_T')
|
||||
class BaseContainer(Generic[_T], MutableSequence[_T]):
|
||||
def __init__(self, message_listener: MessageListener) -> None: ...
|
||||
def __len__(self) -> int: ...
|
||||
def __ne__(self, other: object) -> bool: ...
|
||||
def __hash__(self) -> int: ...
|
||||
def __repr__(self) -> str: ...
|
||||
def sort(self, *, key: Optional[Callable[[_T], Any]] = ..., reverse: bool = ...) -> None: ...
|
||||
|
||||
class RepeatedScalarFieldContainer(Generic[_T], BaseContainer[_T]):
|
||||
def __init__(self, message_listener: MessageListener, message_descriptor: Descriptor) -> None: ...
|
||||
def MergeFrom(self, other: RepeatedScalarFieldContainer[_T]) -> None: ...
|
||||
|
||||
class RepeatedCompositeFieldContainer(Generic[_T], BaseContainer[_T]):
|
||||
def __init__(self, message_listener: MessageListener, type_checker: Any) -> None: ...
|
||||
def add(self, **kwargs: Any) -> _T: ...
|
||||
def MergeFrom(self, other: RepeatedCompositeFieldContainer[_T]) -> None: ...
|
||||
|
||||
# Classes not yet typed
|
||||
class Mapping(Any):
|
||||
pass
|
||||
class MutableMapping(Mapping):
|
||||
pass
|
||||
class ScalarMap(MutableMapping):
|
||||
pass
|
||||
class MessageMap(MutableMapping):
|
||||
pass
|
@ -0,0 +1,30 @@
|
||||
from typing import Any
|
||||
|
||||
def ReadTag(buffer, pos): ...
|
||||
def EnumDecoder(field_number, is_repeated, is_packed, key, new_default): ...
|
||||
|
||||
Int32Decoder = ... # type: Any
|
||||
Int64Decoder = ... # type: Any
|
||||
UInt32Decoder = ... # type: Any
|
||||
UInt64Decoder = ... # type: Any
|
||||
SInt32Decoder = ... # type: Any
|
||||
SInt64Decoder = ... # type: Any
|
||||
Fixed32Decoder = ... # type: Any
|
||||
Fixed64Decoder = ... # type: Any
|
||||
SFixed32Decoder = ... # type: Any
|
||||
SFixed64Decoder = ... # type: Any
|
||||
FloatDecoder = ... # type: Any
|
||||
DoubleDecoder = ... # type: Any
|
||||
BoolDecoder = ... # type: Any
|
||||
|
||||
def StringDecoder(field_number, is_repeated, is_packed, key, new_default): ...
|
||||
def BytesDecoder(field_number, is_repeated, is_packed, key, new_default): ...
|
||||
def GroupDecoder(field_number, is_repeated, is_packed, key, new_default): ...
|
||||
def MessageDecoder(field_number, is_repeated, is_packed, key, new_default): ...
|
||||
|
||||
MESSAGE_SET_ITEM_TAG = ... # type: Any
|
||||
|
||||
def MessageSetItemDecoder(extensions_by_number): ...
|
||||
def MapDecoder(field_descriptor, new_default, is_message_map): ...
|
||||
|
||||
SkipField = ... # type: Any
|
@ -0,0 +1,34 @@
|
||||
from typing import Any
|
||||
|
||||
Int32Sizer = ... # type: Any
|
||||
UInt32Sizer = ... # type: Any
|
||||
SInt32Sizer = ... # type: Any
|
||||
Fixed32Sizer = ... # type: Any
|
||||
Fixed64Sizer = ... # type: Any
|
||||
BoolSizer = ... # type: Any
|
||||
|
||||
def StringSizer(field_number, is_repeated, is_packed): ...
|
||||
def BytesSizer(field_number, is_repeated, is_packed): ...
|
||||
def GroupSizer(field_number, is_repeated, is_packed): ...
|
||||
def MessageSizer(field_number, is_repeated, is_packed): ...
|
||||
def MessageSetItemSizer(field_number): ...
|
||||
def MapSizer(field_descriptor): ...
|
||||
def TagBytes(field_number, wire_type): ...
|
||||
|
||||
Int32Encoder = ... # type: Any
|
||||
UInt32Encoder = ... # type: Any
|
||||
SInt32Encoder = ... # type: Any
|
||||
Fixed32Encoder = ... # type: Any
|
||||
Fixed64Encoder = ... # type: Any
|
||||
SFixed32Encoder = ... # type: Any
|
||||
SFixed64Encoder = ... # type: Any
|
||||
FloatEncoder = ... # type: Any
|
||||
DoubleEncoder = ... # type: Any
|
||||
|
||||
def BoolEncoder(field_number, is_repeated, is_packed): ...
|
||||
def StringEncoder(field_number, is_repeated, is_packed): ...
|
||||
def BytesEncoder(field_number, is_repeated, is_packed): ...
|
||||
def GroupEncoder(field_number, is_repeated, is_packed): ...
|
||||
def MessageEncoder(field_number, is_repeated, is_packed): ...
|
||||
def MessageSetItemEncoder(field_number): ...
|
||||
def MapEncoder(field_descriptor): ...
|
@ -0,0 +1,11 @@
|
||||
from typing import Any, List, Tuple
|
||||
|
||||
class EnumTypeWrapper(object):
|
||||
def __init__(self, enum_type: Any) -> None: ...
|
||||
def Name(self, number: int) -> str: ...
|
||||
def Value(self, name: str) -> int: ...
|
||||
def keys(self) -> List[str]: ...
|
||||
def values(self) -> List[int]: ...
|
||||
|
||||
@classmethod
|
||||
def items(cls) -> List[Tuple[str, int]]: ...
|
@ -0,0 +1,5 @@
|
||||
class MessageListener(object):
|
||||
def Modified(self) -> None: ...
|
||||
|
||||
class NullMessageListener(MessageListener):
|
||||
def Modified(self) -> None: ...
|
@ -0,0 +1,50 @@
|
||||
from typing import Any
|
||||
|
||||
TAG_TYPE_BITS = ... # type: Any
|
||||
TAG_TYPE_MASK = ... # type: Any
|
||||
WIRETYPE_VARINT = ... # type: Any
|
||||
WIRETYPE_FIXED64 = ... # type: Any
|
||||
WIRETYPE_LENGTH_DELIMITED = ... # type: Any
|
||||
WIRETYPE_START_GROUP = ... # type: Any
|
||||
WIRETYPE_END_GROUP = ... # type: Any
|
||||
WIRETYPE_FIXED32 = ... # type: Any
|
||||
INT32_MAX = ... # type: Any
|
||||
INT32_MIN = ... # type: Any
|
||||
UINT32_MAX = ... # type: Any
|
||||
INT64_MAX = ... # type: Any
|
||||
INT64_MIN = ... # type: Any
|
||||
UINT64_MAX = ... # type: Any
|
||||
FORMAT_UINT32_LITTLE_ENDIAN = ... # type: Any
|
||||
FORMAT_UINT64_LITTLE_ENDIAN = ... # type: Any
|
||||
FORMAT_FLOAT_LITTLE_ENDIAN = ... # type: Any
|
||||
FORMAT_DOUBLE_LITTLE_ENDIAN = ... # type: Any
|
||||
|
||||
def PackTag(field_number, wire_type): ...
|
||||
def UnpackTag(tag): ...
|
||||
def ZigZagEncode(value): ...
|
||||
def ZigZagDecode(value): ...
|
||||
def Int32ByteSize(field_number, int32): ...
|
||||
def Int32ByteSizeNoTag(int32): ...
|
||||
def Int64ByteSize(field_number, int64): ...
|
||||
def UInt32ByteSize(field_number, uint32): ...
|
||||
def UInt64ByteSize(field_number, uint64): ...
|
||||
def SInt32ByteSize(field_number, int32): ...
|
||||
def SInt64ByteSize(field_number, int64): ...
|
||||
def Fixed32ByteSize(field_number, fixed32): ...
|
||||
def Fixed64ByteSize(field_number, fixed64): ...
|
||||
def SFixed32ByteSize(field_number, sfixed32): ...
|
||||
def SFixed64ByteSize(field_number, sfixed64): ...
|
||||
def FloatByteSize(field_number, flt): ...
|
||||
def DoubleByteSize(field_number, double): ...
|
||||
def BoolByteSize(field_number, b): ...
|
||||
def EnumByteSize(field_number, enum): ...
|
||||
def StringByteSize(field_number, string): ...
|
||||
def BytesByteSize(field_number, b): ...
|
||||
def GroupByteSize(field_number, message): ...
|
||||
def MessageByteSize(field_number, message): ...
|
||||
def MessageSetItemByteSize(field_number, msg): ...
|
||||
def TagByteSize(field_number): ...
|
||||
|
||||
NON_PACKABLE_TYPES = ... # type: Any
|
||||
|
||||
def IsTypePackable(field_type): ...
|
@ -0,0 +1,34 @@
|
||||
from typing import Any, Dict, Sequence, Optional, Text, Tuple
|
||||
|
||||
from .descriptor import FieldDescriptor
|
||||
|
||||
class Error(Exception): ...
|
||||
class DecodeError(Error): ...
|
||||
class EncodeError(Error): ...
|
||||
|
||||
class Message:
|
||||
DESCRIPTOR = ... # type: Any
|
||||
Extensions = ... # type: Dict[Any, Any]
|
||||
|
||||
def __deepcopy__(self, memo=...): ...
|
||||
def __eq__(self, other_msg): ...
|
||||
def __ne__(self, other_msg): ...
|
||||
def MergeFrom(self, other_msg: Message) -> None: ...
|
||||
def CopyFrom(self, other_msg: Message) -> None: ...
|
||||
def Clear(self) -> None: ...
|
||||
def SetInParent(self) -> None: ...
|
||||
def IsInitialized(self) -> bool: ...
|
||||
def MergeFromString(self, serialized: bytes) -> int: ... # TODO: we need to be able to call buffer() on serialized
|
||||
def ParseFromString(self, serialized: bytes) -> None: ...
|
||||
def SerializeToString(self) -> bytes: ...
|
||||
def SerializePartialToString(self) -> bytes: ...
|
||||
def ListFields(self) -> Sequence[Tuple[FieldDescriptor, Any]]: ...
|
||||
def HasField(self, field_name: Text) -> bool: ...
|
||||
def ClearField(self, field_name: Text) -> None: ...
|
||||
def WhichOneof(self, oneof_group) -> Optional[str]: ...
|
||||
def HasExtension(self, extension_handle): ...
|
||||
def ClearExtension(self, extension_handle): ...
|
||||
def ByteSize(self) -> int: ...
|
||||
|
||||
# TODO: check kwargs
|
||||
def __init__(self, **kwargs) -> None: ...
|
@ -0,0 +1,13 @@
|
||||
from typing import Any, Dict, Iterable, Optional, Type
|
||||
|
||||
from .message import Message
|
||||
from .descriptor import Descriptor
|
||||
from .descriptor_pool import DescriptorPool
|
||||
|
||||
class MessageFactory:
|
||||
pool = ... # type: Any
|
||||
def __init__(self, pool: Optional[DescriptorPool] = ...) -> None: ...
|
||||
def GetPrototype(self, descriptor: Descriptor) -> Type[Message]: ...
|
||||
def GetMessages(self, files: Iterable[str]) -> Dict[str, Type[Message]]: ...
|
||||
|
||||
def GetMessages(file_protos: Iterable[str]) -> Dict[str, Type[Message]]: ...
|
@ -0,0 +1,6 @@
|
||||
class GeneratedProtocolMessageType(type):
|
||||
def __new__(cls, name, bases, dictionary): ...
|
||||
def __init__(cls, name, bases, dictionary) -> None: ...
|
||||
|
||||
def ParseMessage(descriptor, byte_str): ...
|
||||
def MakeClass(descriptor): ...
|
@ -0,0 +1,14 @@
|
||||
from typing import Dict, Iterable, Type
|
||||
|
||||
from .descriptor import EnumDescriptor, FileDescriptor
|
||||
from .message import Message
|
||||
from .message_factory import MessageFactory
|
||||
|
||||
class SymbolDatabase(MessageFactory):
|
||||
def RegisterMessage(self, message: Type[Message]) -> Type[Message]: ...
|
||||
def RegisterEnumDescriptor(self, enum_descriptor: Type[EnumDescriptor]) -> EnumDescriptor: ...
|
||||
def RegisterFileDescriptor(self, file_descriptor: Type[FileDescriptor]) -> FileDescriptor: ...
|
||||
def GetSymbol(self, symbol: str) -> Type[Message]: ...
|
||||
def GetMessages(self, files: Iterable[str]) -> Dict[str, Type[Message]]: ...
|
||||
|
||||
def Default(): ...
|
@ -1,27 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
# @begin:license
|
||||
#
|
||||
# Copyright (c) 2015-2018, Benjamin Niemann <pink@odahoda.de>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# @end:license
|
||||
|
||||
class Error(Exception):
|
||||
pass
|
||||
|
||||
class SetupError(Error):
|
||||
pass
|