diff --git a/exabel_data_sdk/client/api/export_api.py b/exabel_data_sdk/client/api/export_api.py index 09eca9f..fea6f6c 100644 --- a/exabel_data_sdk/client/api/export_api.py +++ b/exabel_data_sdk/client/api/export_api.py @@ -81,7 +81,7 @@ def run_query_bytes(self, query: Union[str, Query], file_format: str) -> bytes: if error_message.startswith('"') and error_message.endswith('"'): error_message = error_message[1:-1] error_message = f"{response.status_code}: {error_message}" - raise Exception(error_message) + raise ValueError(error_message) def run_query(self, query: Union[str, Query]) -> pd.DataFrame: """ diff --git a/exabel_data_sdk/client/api/time_series_api.py b/exabel_data_sdk/client/api/time_series_api.py index 3e6403e..10aad4b 100644 --- a/exabel_data_sdk/client/api/time_series_api.py +++ b/exabel_data_sdk/client/api/time_series_api.py @@ -460,7 +460,6 @@ def bulk_upsert_time_series( """ def import_func(ts_sequence: Sequence[pd.Series]) -> Sequence[ResourceCreationResult]: - result = self.import_time_series( parent="signals/-", series=ts_sequence, diff --git a/exabel_data_sdk/client/user_login.py b/exabel_data_sdk/client/user_login.py index 442b336..8ce28ee 100644 --- a/exabel_data_sdk/client/user_login.py +++ b/exabel_data_sdk/client/user_login.py @@ -142,7 +142,7 @@ def start_http_server(self) -> HTTPServer: if error.errno != errno.EADDRINUSE: raise error if httpd is None: - raise Exception("Cannot start a local HTTP server to receive the login token.") + raise ValueError("Cannot start a local HTTP server to receive the login token.") thread = threading.Thread(target=httpd.serve_forever, daemon=True) thread.start() @@ -288,7 +288,7 @@ def auth_headers(self) -> Dict[str, str]: def get_auth_headers(self) -> Dict[str, str]: """Log in and get the authentication headers for HTTPS requests to the Exabel API.""" if not self.log_in(): - raise Exception("Failed to log in.") + raise ValueError("Failed to log in.") return self.auth_headers diff --git a/exabel_data_sdk/scripts/create_entity_mapping_from_csv.py b/exabel_data_sdk/scripts/create_entity_mapping_from_csv.py index 747efd7..7abe849 100644 --- a/exabel_data_sdk/scripts/create_entity_mapping_from_csv.py +++ b/exabel_data_sdk/scripts/create_entity_mapping_from_csv.py @@ -84,7 +84,6 @@ def __init__(self, argv: Sequence[str], description: str): def get_entity_mapping( self, client: ExabelClient, args: argparse.Namespace, mapping_input: pd.DataFrame ) -> pd.DataFrame: - """ Find the entity type we are creating mapping for. @@ -222,7 +221,6 @@ def get_markets(self, market: str) -> List[str]: return markets def run_script(self, client: ExabelClient, args: argparse.Namespace) -> None: - mapping_input = CsvReader.read_file( args.filename_input, separator=args.sep, string_columns=[0], keep_default_na=True ) diff --git a/exabel_data_sdk/services/sql/sql_reader_configuration.py b/exabel_data_sdk/services/sql/sql_reader_configuration.py index db2061e..5089f12 100644 --- a/exabel_data_sdk/services/sql/sql_reader_configuration.py +++ b/exabel_data_sdk/services/sql/sql_reader_configuration.py @@ -1,5 +1,6 @@ import abc import argparse +from dataclasses import dataclass from typing import Any, Mapping, NamedTuple, NewType ConnectionString = NewType("ConnectionString", str) @@ -12,6 +13,7 @@ class EngineArgs(NamedTuple): kwargs: Mapping[str, Any] +@dataclass class SqlReaderConfiguration(abc.ABC): """Base class for SQL reader configurations.""" diff --git a/exabel_data_sdk/stubs/exabel/api/analytics/v1/prediction_model_messages_pb2.pyi b/exabel_data_sdk/stubs/exabel/api/analytics/v1/prediction_model_messages_pb2.pyi index d6ba7fa..375af87 100644 --- a/exabel_data_sdk/stubs/exabel/api/analytics/v1/prediction_model_messages_pb2.pyi +++ b/exabel_data_sdk/stubs/exabel/api/analytics/v1/prediction_model_messages_pb2.pyi @@ -21,24 +21,24 @@ class _ModelConfiguration: class _ModelConfigurationEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_ModelConfiguration.ValueType], builtins.type): DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor MODEL_CONFIGURATION_NOT_SPECIFIED: _ModelConfiguration.ValueType - 'Not specified.' + 'Not specified - defaults to use the latest configuration.' LATEST: _ModelConfiguration.ValueType 'Latest configuration.' ACTIVE: _ModelConfiguration.ValueType - 'Configuration of the active run.' + 'Configuration of the active run. A specific run may be activated from the prediction model user interface.' SPECIFIC_RUN: _ModelConfiguration.ValueType - 'Configuration of a specific run.' + 'Configuration of a specific run. The run number must be specified as well.' class ModelConfiguration(_ModelConfiguration, metaclass=_ModelConfigurationEnumTypeWrapper): """Specifies which model configuration to use.""" MODEL_CONFIGURATION_NOT_SPECIFIED: ModelConfiguration.ValueType -'Not specified.' +'Not specified - defaults to use the latest configuration.' LATEST: ModelConfiguration.ValueType 'Latest configuration.' ACTIVE: ModelConfiguration.ValueType -'Configuration of the active run.' +'Configuration of the active run. A specific run may be activated from the prediction model user interface.' SPECIFIC_RUN: ModelConfiguration.ValueType -'Configuration of a specific run.' +'Configuration of a specific run. The run number must be specified as well.' global___ModelConfiguration = ModelConfiguration @typing_extensions.final @@ -57,7 +57,7 @@ class PredictionModelRun(google.protobuf.message.Message): configuration: global___ModelConfiguration.ValueType 'Which model configuration to use.\n If not specified, the latest model configuration is used.\n ' configuration_source: builtins.int - 'Specifies a prediction model run from which model configuration should be retrieved.\n Only relevant when `configuration` is set to `ModelConfiguration.SPECIFIC_RUN`.\n ' + 'Prediction model run number from which model configuration should be retrieved, e.g. `1`.\n Only relevant when `configuration` is set to `ModelConfiguration.SPECIFIC_RUN`.\n ' auto_activate: builtins.bool 'Whether to automatically set this run as active once it completes.\n The run will not be activated if it fails for any of the entities in the model.\n ' diff --git a/exabel_data_sdk/stubs/exabel/api/management/v1/folder_messages_pb2.py b/exabel_data_sdk/stubs/exabel/api/management/v1/folder_messages_pb2.py index 8231289..bc17cf9 100644 --- a/exabel_data_sdk/stubs/exabel/api/management/v1/folder_messages_pb2.py +++ b/exabel_data_sdk/stubs/exabel/api/management/v1/folder_messages_pb2.py @@ -8,7 +8,7 @@ from google.api import field_behavior_pb2 as google_dot_api_dot_field__behavior__pb2 from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 from .....protoc_gen_openapiv2.options import annotations_pb2 as protoc__gen__openapiv2_dot_options_dot_annotations__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n.exabel/api/management/v1/folder_messages.proto\x12\x18exabel.api.management.v1\x1a,exabel/api/management/v1/user_messages.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a.protoc_gen_openapiv2/options/annotations.proto"\xf3\x01\n\x06Folder\x120\n\x04name\x18\x01 \x01(\tB"\x92A\x1fJ\r"folders/123"\xca>\r\xfa\x02\nfolderName\x120\n\x0cdisplay_name\x18\x02 \x01(\tB\x1a\xe0A\x02\x92A\x14J\x12"My shared folder"\x12\x12\n\x05write\x18\x03 \x01(\x08B\x03\xe0A\x03\x12;\n\x05items\x18\x04 \x03(\x0b2$.exabel.api.management.v1.FolderItemB\x06\xe0A\x06\xe0A\x03\x124\n\x0bdescription\x18\x05 \x01(\tB\x1f\x92A\x1cJ\x1a"This is my shared folder""\xf0\x02\n\nFolderItem\x122\n\x06parent\x18\x01 \x01(\tB"\x92A\x1fJ\r"folders/123"\xca>\r\xfa\x02\nfolderName\x12*\n\x04name\x18\x02 \x01(\tB\x1c\xe0A\x03\x92A\x16J\x14"derivedSignals/123"\x12&\n\x0cdisplay_name\x18\x03 \x01(\tB\x10\x92A\rJ\x0b"my_signal"\x12\x13\n\x0bdescription\x18\t \x01(\t\x12;\n\titem_type\x18\x04 \x01(\x0e2(.exabel.api.management.v1.FolderItemType\x12/\n\x0bcreate_time\x18\x05 \x01(\x0b2\x1a.google.protobuf.Timestamp\x12/\n\x0bupdate_time\x18\x06 \x01(\x0b2\x1a.google.protobuf.Timestamp\x12\x12\n\ncreated_by\x18\x07 \x01(\t\x12\x12\n\nupdated_by\x18\x08 \x01(\t"O\n\x0eFolderAccessor\x12.\n\x05group\x18\x01 \x01(\x0b2\x1f.exabel.api.management.v1.Group\x12\r\n\x05write\x18\x02 \x01(\x08"B\n\x0cSearchResult\x122\n\x04item\x18\x01 \x01(\x0b2$.exabel.api.management.v1.FolderItem*\xc4\x01\n\x0eFolderItemType\x12\x1c\n\x18FOLDER_ITEM_TYPE_INVALID\x10\x00\x12\x12\n\x0eDERIVED_SIGNAL\x10\x01\x12\x14\n\x10PREDICTION_MODEL\x10\x02\x12\x16\n\x12PORTFOLIO_STRATEGY\x10\x03\x12\r\n\tDASHBOARD\x10\x04\x12\x0e\n\nDRILL_DOWN\x10\x05\x12\x07\n\x03TAG\x10\x06\x12\n\n\x06SCREEN\x10\x07\x12\x13\n\x0fFINANCIAL_MODEL\x10\x08\x12\t\n\x05CHART\x10\tBS\n\x1ccom.exabel.api.management.v1B\x13FolderMessagesProtoP\x01Z\x1cexabel.com/api/management/v1b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n.exabel/api/management/v1/folder_messages.proto\x12\x18exabel.api.management.v1\x1a,exabel/api/management/v1/user_messages.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a.protoc_gen_openapiv2/options/annotations.proto"\xf3\x01\n\x06Folder\x120\n\x04name\x18\x01 \x01(\tB"\x92A\x1fJ\r"folders/123"\xca>\r\xfa\x02\nfolderName\x120\n\x0cdisplay_name\x18\x02 \x01(\tB\x1a\xe0A\x02\x92A\x14J\x12"My shared folder"\x124\n\x0bdescription\x18\x05 \x01(\tB\x1f\x92A\x1cJ\x1a"This is my shared folder"\x12\x12\n\x05write\x18\x03 \x01(\x08B\x03\xe0A\x03\x12;\n\x05items\x18\x04 \x03(\x0b2$.exabel.api.management.v1.FolderItemB\x06\xe0A\x06\xe0A\x03"\xf0\x02\n\nFolderItem\x122\n\x06parent\x18\x01 \x01(\tB"\x92A\x1fJ\r"folders/123"\xca>\r\xfa\x02\nfolderName\x12*\n\x04name\x18\x02 \x01(\tB\x1c\xe0A\x03\x92A\x16J\x14"derivedSignals/123"\x12&\n\x0cdisplay_name\x18\x03 \x01(\tB\x10\x92A\rJ\x0b"my_signal"\x12\x13\n\x0bdescription\x18\t \x01(\t\x12;\n\titem_type\x18\x04 \x01(\x0e2(.exabel.api.management.v1.FolderItemType\x12/\n\x0bcreate_time\x18\x05 \x01(\x0b2\x1a.google.protobuf.Timestamp\x12/\n\x0bupdate_time\x18\x06 \x01(\x0b2\x1a.google.protobuf.Timestamp\x12\x12\n\ncreated_by\x18\x07 \x01(\t\x12\x12\n\nupdated_by\x18\x08 \x01(\t"O\n\x0eFolderAccessor\x12.\n\x05group\x18\x01 \x01(\x0b2\x1f.exabel.api.management.v1.Group\x12\r\n\x05write\x18\x02 \x01(\x08"B\n\x0cSearchResult\x122\n\x04item\x18\x01 \x01(\x0b2$.exabel.api.management.v1.FolderItem*\xc4\x01\n\x0eFolderItemType\x12\x1c\n\x18FOLDER_ITEM_TYPE_INVALID\x10\x00\x12\x12\n\x0eDERIVED_SIGNAL\x10\x01\x12\x14\n\x10PREDICTION_MODEL\x10\x02\x12\x16\n\x12PORTFOLIO_STRATEGY\x10\x03\x12\r\n\tDASHBOARD\x10\x04\x12\x0e\n\nDRILL_DOWN\x10\x05\x12\x07\n\x03TAG\x10\x06\x12\n\n\x06SCREEN\x10\x07\x12\x13\n\x0fFINANCIAL_MODEL\x10\x08\x12\t\n\x05CHART\x10\tBS\n\x1ccom.exabel.api.management.v1B\x13FolderMessagesProtoP\x01Z\x1cexabel.com/api/management/v1b\x06proto3') _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'exabel.api.management.v1.folder_messages_pb2', globals()) if _descriptor._USE_C_DESCRIPTORS == False: @@ -18,12 +18,12 @@ _FOLDER.fields_by_name['name']._serialized_options = b'\x92A\x1fJ\r"folders/123"\xca>\r\xfa\x02\nfolderName' _FOLDER.fields_by_name['display_name']._options = None _FOLDER.fields_by_name['display_name']._serialized_options = b'\xe0A\x02\x92A\x14J\x12"My shared folder"' + _FOLDER.fields_by_name['description']._options = None + _FOLDER.fields_by_name['description']._serialized_options = b'\x92A\x1cJ\x1a"This is my shared folder"' _FOLDER.fields_by_name['write']._options = None _FOLDER.fields_by_name['write']._serialized_options = b'\xe0A\x03' _FOLDER.fields_by_name['items']._options = None _FOLDER.fields_by_name['items']._serialized_options = b'\xe0A\x06\xe0A\x03' - _FOLDER.fields_by_name['description']._options = None - _FOLDER.fields_by_name['description']._serialized_options = b'\x92A\x1cJ\x1a"This is my shared folder"' _FOLDERITEM.fields_by_name['parent']._options = None _FOLDERITEM.fields_by_name['parent']._serialized_options = b'\x92A\x1fJ\r"folders/123"\xca>\r\xfa\x02\nfolderName' _FOLDERITEM.fields_by_name['name']._options = None diff --git a/exabel_data_sdk/stubs/exabel/api/management/v1/folder_messages_pb2.pyi b/exabel_data_sdk/stubs/exabel/api/management/v1/folder_messages_pb2.pyi index a602eb1..c68baf0 100644 --- a/exabel_data_sdk/stubs/exabel/api/management/v1/folder_messages_pb2.pyi +++ b/exabel_data_sdk/stubs/exabel/api/management/v1/folder_messages_pb2.pyi @@ -75,23 +75,23 @@ class Folder(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor NAME_FIELD_NUMBER: builtins.int DISPLAY_NAME_FIELD_NUMBER: builtins.int + DESCRIPTION_FIELD_NUMBER: builtins.int WRITE_FIELD_NUMBER: builtins.int ITEMS_FIELD_NUMBER: builtins.int - DESCRIPTION_FIELD_NUMBER: builtins.int name: builtins.str 'Unique resource name of the folder, e.g. `folders/123`. In the "Create folder" method, this is\n ignored and may be left empty.\n ' display_name: builtins.str 'Appears in the Exabel Library in the list of folders.' + description: builtins.str + 'The description of the folder.' write: builtins.bool 'Whether the API caller has write access to the folder.' @property def items(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___FolderItem]: """List of items in the folder. To add or remove folder items, use the "Move folder items" method.""" - description: builtins.str - 'The description of the folder.' - def __init__(self, *, name: builtins.str | None=..., display_name: builtins.str | None=..., write: builtins.bool | None=..., items: collections.abc.Iterable[global___FolderItem] | None=..., description: builtins.str | None=...) -> None: + def __init__(self, *, name: builtins.str | None=..., display_name: builtins.str | None=..., description: builtins.str | None=..., write: builtins.bool | None=..., items: collections.abc.Iterable[global___FolderItem] | None=...) -> None: ... def ClearField(self, field_name: typing_extensions.Literal['description', b'description', 'display_name', b'display_name', 'items', b'items', 'name', b'name', 'write', b'write']) -> None: diff --git a/exabel_data_sdk/tests/resources/data/corrupt_dates_1.xlsx b/exabel_data_sdk/tests/resources/data/corrupt_dates_1.xlsx index 08b8d55..5300cab 100644 Binary files a/exabel_data_sdk/tests/resources/data/corrupt_dates_1.xlsx and b/exabel_data_sdk/tests/resources/data/corrupt_dates_1.xlsx differ diff --git a/exabel_data_sdk/tests/scripts/test_create_entity_mapping_from_csv.py b/exabel_data_sdk/tests/scripts/test_create_entity_mapping_from_csv.py index eddd1c2..353847d 100644 --- a/exabel_data_sdk/tests/scripts/test_create_entity_mapping_from_csv.py +++ b/exabel_data_sdk/tests/scripts/test_create_entity_mapping_from_csv.py @@ -17,7 +17,6 @@ def tearDown(self): self.temp_file.close() def test_create_mapping_ticker(self): - args = [ "script-name", "--filename-input", @@ -77,7 +76,6 @@ def test_create_mapping_ticker(self): ) def test_create_mapping_isin(self): - args = [ "script-name", "--filename-input", @@ -101,7 +99,6 @@ def test_create_mapping_isin(self): ) def test_create_mapping_factset_identifier(self): - args = [ "script-name", "--filename-input", @@ -134,7 +131,6 @@ def test_create_mapping_factset_identifier(self): ) def test_create_mapping_bloomberg_ticker(self): - args = [ "script-name", "--filename-input", @@ -167,7 +163,6 @@ def test_create_mapping_bloomberg_ticker(self): ) def test_create_mapping_figi(self): - args = [ "script-name", "--filename-input", diff --git a/exabel_data_sdk/util/deprecate_arguments.py b/exabel_data_sdk/util/deprecate_arguments.py index 4f1610f..04f7560 100644 --- a/exabel_data_sdk/util/deprecate_arguments.py +++ b/exabel_data_sdk/util/deprecate_arguments.py @@ -6,6 +6,7 @@ FunctionT = TypeVar("FunctionT", bound=Callable[..., Any]) + # Pylint flags '__func' as an invalid argument name, but we want the '__' prefix to make Mypy # interpret it as a positional-only argument. Therefore, we disable the check for this argument. @overload