Skip to content

Commit d3be2ba

Browse files
committed
QA: Migrate type checker from mypy to ty -- CodeRabbit improvements
1 parent f8cdcac commit d3be2ba

10 files changed

Lines changed: 72 additions & 31 deletions

File tree

cratedb_toolkit/io/awslambda/kinesis.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@
6969
message = f"Invalid value for MESSAGE_FORMAT: {MESSAGE_FORMAT}. Use one of: {message_formats}"
7070
logger.fatal(message)
7171
sys.exit(22)
72+
if MESSAGE_FORMAT == "dynamodb" and not CRATEDB_TABLE:
73+
message = "CRATEDB_TABLE environment variable is required when MESSAGE_FORMAT is 'dynamodb'"
74+
logger.fatal(message)
75+
sys.exit(22)
7276
try:
7377
column_types = ColumnTypeMapStore.from_json(COLUMN_TYPES)
7478
except Exception as ex:
@@ -82,7 +86,8 @@
8286
if MESSAGE_FORMAT == "dms":
8387
cdc = DMSTranslatorCrateDB(column_types=column_types) # ty: ignore[invalid-argument-type]
8488
elif MESSAGE_FORMAT == "dynamodb":
85-
cdc = DynamoDBCDCTranslator(table_name=CRATEDB_TABLE) # ty: ignore[invalid-argument-type]
89+
assert CRATEDB_TABLE is not None # Validated at module startup # noqa: S101
90+
cdc = DynamoDBCDCTranslator(table_name=CRATEDB_TABLE)
8691

8792
# Create the database connection outside the handler to allow
8893
# connections to be re-used by subsequent function invocations.

cratedb_toolkit/io/mongodb/cdc.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ def __init__(
6262
if tm:
6363
address = CollectionAddress(
6464
container=self.mongodb_adapter.database_name,
65+
# TODO: Collection name must be permitted to be None?
6566
name=t.cast(str, self.mongodb_adapter.collection_name),
6667
)
6768
try:

cratedb_toolkit/io/mongodb/copy.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import sqlalchemy as sa
66
from boltons.urlutils import URL
7+
from commons_codec.model import SQLOperation
78
from commons_codec.transform.mongodb import MongoDBCrateDBConverter, MongoDBFullLoadTranslator
89
from tikray.model.collection import CollectionAddress
910
from tqdm import tqdm
@@ -13,6 +14,7 @@
1314
from cratedb_toolkit.io.mongodb.adapter import mongodb_adapter_factory
1415
from cratedb_toolkit.io.mongodb.transform import TransformationManager
1516
from cratedb_toolkit.model import DatabaseAddress
17+
from cratedb_toolkit.util.cli import to_list
1618
from cratedb_toolkit.util.database import DatabaseAdapter
1719

1820
logger = logging.getLogger(__name__)
@@ -51,6 +53,7 @@ def __init__(
5153
if tm:
5254
address = CollectionAddress(
5355
container=self.mongodb_adapter.database_name,
56+
# TODO: Collection name must be permitted to be None?
5457
name=t.cast(str, self.mongodb_adapter.collection_name),
5558
)
5659
try:
@@ -88,10 +91,13 @@ def start(self):
8891
logger.info(f"Target: CrateDB table={self.cratedb_table} count={records_target}")
8992
progress_bar = tqdm(total=records_in)
9093

94+
def batch_to_sql_operation(batch: t.List[t.Dict[str, t.Any]]) -> SQLOperation:
95+
return self.translator.to_sql(to_list(batch, []))
96+
9197
processor = BulkProcessor(
9298
connection=connection,
9399
data=self.mongodb_adapter.query(),
94-
batch_to_operation=self.translator.to_sql, # ty: ignore[invalid-argument-type]
100+
batch_to_operation=batch_to_sql_operation,
95101
progress_bar=progress_bar,
96102
on_error=self.on_error,
97103
debug=self.debug,

cratedb_toolkit/testing/testcontainers/cratedb.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ def get_connection_url(self, dialect: str = "crate", host: Optional[str] = None)
153153
def _connect(self):
154154
if not self._wait_strategy:
155155
raise ValueError("No wait strategy defined")
156-
wait_for_logs(self, predicate=self._wait_strategy)
156+
wait_for_logs(self, predicate=self._wait_strategy, timeout=15)
157157

158158
def _configure_wait_condition(self):
159159
"""Wait for CrateDB node to be fully started."""
@@ -170,17 +170,23 @@ class CrateDBTestAdapter:
170170
"""
171171

172172
def __init__(self, crate_version: str = "nightly", **kwargs):
173-
self.cratedb: CrateDBContainer
174-
self.database: DatabaseAdapter
173+
self.cratedb: Optional[CrateDBContainer] = None
174+
self._database: Optional[DatabaseAdapter] = None
175175
self.image: str = "crate/crate:{}".format(crate_version)
176176

177+
@property
178+
def database(self) -> DatabaseAdapter:
179+
if self._database is None:
180+
raise ValueError("DatabaseAdapter is not initialized")
181+
return self._database
182+
177183
def start(self, **kwargs):
178184
"""
179185
Start testcontainer, used for tests set up
180186
"""
181187
self.cratedb = CrateDBContainer(image=self.image, **kwargs)
182188
self.cratedb.start()
183-
self.database = DatabaseAdapter(dburi=self.get_connection_url(), echo=False)
189+
self._database = DatabaseAdapter(dburi=self.get_connection_url(), echo=False)
184190

185191
def stop(self):
186192
"""
@@ -193,19 +199,19 @@ def reset(self, tables: Optional[list] = None, schemas: Optional[list] = None):
193199
"""
194200
Drop tables from the given list, used for tests set up or tear down
195201
"""
196-
if not self.database:
202+
if not self._database:
197203
return
198204

199205
if schemas:
200206
for reset_schema in schemas:
201-
self.database.connection.exec_driver_sql(
202-
f"DROP SCHEMA IF EXISTS {self.database.quote_relation_name(reset_schema)} CASCADE;"
207+
self._database.connection.exec_driver_sql(
208+
f"DROP SCHEMA IF EXISTS {self._database.quote_relation_name(reset_schema)} CASCADE;"
203209
)
204210

205211
if tables:
206212
for reset_table in tables:
207-
self.database.connection.exec_driver_sql(
208-
f"DROP TABLE IF EXISTS {self.database.quote_relation_name(reset_table)};"
213+
self._database.connection.exec_driver_sql(
214+
f"DROP TABLE IF EXISTS {self._database.quote_relation_name(reset_table)};"
209215
)
210216

211217
def get_connection_url(self, *args, **kwargs):

cratedb_toolkit/testing/testcontainers/mongodb.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from pymongo import MongoClient
1919
from testcontainers.core.exceptions import ContainerStartException
2020
from testcontainers.mongodb import MongoDbContainer
21+
from yarl import URL
2122

2223
from cratedb_toolkit.testing.testcontainers.util import DockerSkippingContainer, KeepaliveContainer
2324

@@ -26,7 +27,7 @@ class MongoDbContainerWithKeepalive(DockerSkippingContainer, KeepaliveContainer,
2627
"""
2728
A Testcontainer for MongoDB with improved configurability.
2829
29-
It honors the `TC_KEEPALIVE` and `MONGODB_VERSION` environment variables.
30+
It honours the `TC_KEEPALIVE` and `MONGODB_VERSION` environment variables.
3031
3132
Defining `TC_KEEPALIVE` will set a signal not to shut down the container
3233
after running the test cases, in order to speed up subsequent invocations.
@@ -87,6 +88,11 @@ def _create_connection_url(
8788
dbname: t.Optional[str] = None,
8889
**kwargs,
8990
) -> str:
91+
"""
92+
TODO: Why does this method need to be overwritten?
93+
Hint: Probably because of getting rid of credentials forwarding,
94+
which is currently intended to reduce configuration complexity.
95+
"""
9096
from testcontainers.core.utils import raise_for_deprecated_parameter
9197

9298
if raise_for_deprecated_parameter(kwargs, "db_name", "dbname"):
@@ -96,16 +102,20 @@ def _create_connection_url(
96102
host = host or self.get_container_host_ip()
97103
assert port is not None # noqa: S101
98104
port = self.get_exposed_port(port)
99-
url = f"{dialect}://{host}:{port}"
105+
url = URL(f"{dialect}://{host}:{port}")
106+
if username:
107+
url = url.with_user(username)
108+
if password:
109+
url = url.with_password(password)
100110
if dbname:
101-
url = f"{url}/{dbname}"
102-
return url
111+
url = url.with_path(dbname)
112+
return str(url)
103113

104114
def get_connection_url(self) -> str:
105115
return self._create_connection_url(
106116
dialect="mongodb",
107-
username="admin",
108-
password="",
117+
username=None, # ty: ignore[invalid-argument-type]
118+
password=None, # ty: ignore[invalid-argument-type]
109119
port=self.port,
110120
)
111121

cratedb_toolkit/testing/testcontainers/util.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from docker.errors import DockerException
2020
from docker.models.containers import Container
2121
from testcontainers.core.container import DockerContainer
22+
from testcontainers.core.generic import DbContainer
2223

2324
from cratedb_toolkit.util.data import asbool
2425

@@ -176,7 +177,7 @@ class PytestTestcontainerAdapter:
176177
"""
177178

178179
def __init__(self):
179-
self.container: DockerContainer
180+
self.container: t.Optional[DbContainer] = None
180181
self.run_setup()
181182

182183
@abstractmethod
@@ -204,7 +205,11 @@ def run_setup(self):
204205
self.start()
205206

206207
def start(self):
208+
if self.container is None:
209+
raise ValueError("Container not initialized")
207210
self.container.start()
208211

209212
def stop(self):
213+
if self.container is None:
214+
raise ValueError("Container not initialized")
210215
self.container.stop()

cratedb_toolkit/util/client.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,18 @@ class jwt_token_patch(contextlib.ContextDecorator):
1414

1515
def __init__(self, jwt_token: Optional[str] = None):
1616
self.jwt_token = jwt_token
17+
self._patch_stack = contextlib.ExitStack()
1718

1819
def __enter__(self):
1920
if self.jwt_token:
20-
self.patcher = patch.object(crate.client.http.Client, "_request", _mk_crate_client_request(self.jwt_token))
21-
self.patcher.start()
21+
self._patch_stack.enter_context(
22+
patch.object(crate.client.http.Client, "_request", _mk_crate_client_request(self.jwt_token))
23+
)
2224
return self
2325

2426
def __exit__(self, type, value, tb): # noqa: A002
25-
if self.jwt_token:
26-
self.patcher.stop()
27-
return self
27+
self._patch_stack.close()
28+
return False
2829

2930

3031
def _mk_crate_client_request(jwt_token: Optional[str] = None):

cratedb_toolkit/util/database.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ def run_sql(
110110
self,
111111
sql: t.Union[str, Path, io.IOBase],
112112
parameters: t.Optional[t.Mapping[str, str]] = None,
113-
records: t.Optional[bool] = False,
113+
records: bool = False,
114114
ignore: t.Optional[str] = None,
115115
):
116116
"""
@@ -136,9 +136,7 @@ def run_sql(
136136
raise
137137
return None
138138

139-
def run_sql_real(
140-
self, sql: str, parameters: t.Optional[t.Mapping[str, str]] = None, records: t.Optional[bool] = False
141-
):
139+
def run_sql_real(self, sql: str, parameters: t.Optional[t.Mapping[str, str]] = None, records: bool = False):
142140
"""
143141
Invoke an SQL statement and return results.
144142
"""
@@ -368,7 +366,7 @@ def import_csv_dask(
368366
chunksize=1000,
369367
if_exists="replace",
370368
npartitions: t.Optional[int] = None,
371-
progress: t.Optional[bool] = False,
369+
progress: bool = False,
372370
):
373371
"""
374372
Import CSV data using Dask.

tests/io/mongodb/conftest.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ def __init__(self, container_class):
3737
)
3838

3939
self.container_class = container_class
40-
self.container: t.Union[MongoDbContainerWithKeepalive, MongoDbReplicasetContainer]
41-
self.client: MongoClient
40+
self.container: t.Optional[t.Union[MongoDbContainerWithKeepalive, MongoDbReplicasetContainer]] = None
41+
self.client: t.Optional[MongoClient] = None
4242
super().__init__()
4343

4444
def setup(self):
@@ -54,19 +54,28 @@ def setup(self):
5454
self.client = self.container.get_connection_client()
5555

5656
def finalize(self):
57+
if not self.container:
58+
return
5759
self.container.stop()
5860

5961
def reset(self):
6062
"""
6163
Drop all databases used for testing.
6264
"""
65+
if self.client is None:
66+
return
67+
6368
for database_name in RESET_DATABASES:
6469
self.client.drop_database(database_name)
6570

6671
def get_connection_url(self):
72+
if not self.container:
73+
raise RuntimeError("Container has not been initialized")
6774
return self.container.get_connection_url()
6875

6976
def get_connection_client(self):
77+
if not self.container:
78+
raise RuntimeError("Container has not been initialized")
7079
return self.container.get_connection_client()
7180

7281

tests/io/mongodb/test_integration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def setUpClass(cls):
4949
logger.debug(f"MongoDB server info: {server_info}")
5050
except pymongo.errors.ServerSelectionTimeoutError as ex:
5151
if cls.SKIP_IF_NOT_RUNNING:
52-
raise cls.skipTest(cls, reason="MongoDB server not running") from ex # ty: ignore[invalid-argument-type]
52+
raise unittest.SkipTest("MongoDB server not running") from ex
5353
else: # noqa: RET506
5454
raise
5555

0 commit comments

Comments
 (0)