From: Daniele Varrazzo Date: Thu, 27 Mar 2025 16:36:29 +0000 (+0100) Subject: refactor: use assignment expressions in loops with assignment and break X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F1035%2Fhead;p=thirdparty%2Fpsycopg.git refactor: use assignment expressions in loops with assignment and break --- diff --git a/psycopg/psycopg/_copy.py b/psycopg/psycopg/_copy.py index d03549464..0934a63a2 100644 --- a/psycopg/psycopg/_copy.py +++ b/psycopg/psycopg/_copy.py @@ -81,9 +81,7 @@ class Copy(BaseCopy["Connection[Any]"]): def __iter__(self) -> Iterator[Buffer]: """Implement block-by-block iteration on :sql:`COPY TO`.""" - while True: - if not (data := self.read()): - break + while data := self.read(): yield data def read(self) -> Buffer: @@ -101,9 +99,7 @@ class Copy(BaseCopy["Connection[Any]"]): Note that the records returned will be tuples of unparsed strings or bytes, unless data types are specified using `set_types()`. """ - while True: - if (record := self.read_row()) is None: - break + while (record := self.read_row()) is not None: yield record def read_row(self) -> tuple[Any, ...] | None: @@ -252,9 +248,7 @@ class QueuedLibpqWriter(LibpqWriter): The function is designed to be run in a separate task. """ try: - while True: - if not (data := self._queue.get()): - break + while data := self._queue.get(): self.connection.wait(copy_to(self._pgconn, data, flush=PREFER_FLUSH)) except BaseException as ex: # Propagate the error to the main thread. diff --git a/psycopg/psycopg/_copy_async.py b/psycopg/psycopg/_copy_async.py index 0070ba8b5..05ec0f98f 100644 --- a/psycopg/psycopg/_copy_async.py +++ b/psycopg/psycopg/_copy_async.py @@ -78,9 +78,7 @@ class AsyncCopy(BaseCopy["AsyncConnection[Any]"]): async def __aiter__(self) -> AsyncIterator[Buffer]: """Implement block-by-block iteration on :sql:`COPY TO`.""" - while True: - if not (data := (await self.read())): - break + while data := (await self.read()): yield data async def read(self) -> Buffer: @@ -98,9 +96,7 @@ class AsyncCopy(BaseCopy["AsyncConnection[Any]"]): Note that the records returned will be tuples of unparsed strings or bytes, unless data types are specified using `set_types()`. """ - while True: - if (record := (await self.read_row())) is None: - break + while (record := (await self.read_row())) is not None: yield record async def read_row(self) -> tuple[Any, ...] | None: @@ -251,9 +247,7 @@ class AsyncQueuedLibpqWriter(AsyncLibpqWriter): The function is designed to be run in a separate task. """ try: - while True: - if not (data := (await self._queue.get())): - break + while data := (await self._queue.get()): await self.connection.wait( copy_to(self._pgconn, data, flush=PREFER_FLUSH) ) diff --git a/psycopg/psycopg/cursor.py b/psycopg/psycopg/cursor.py index fe6b28c35..fb2df08eb 100644 --- a/psycopg/psycopg/cursor.py +++ b/psycopg/psycopg/cursor.py @@ -231,9 +231,7 @@ class Cursor(BaseCursor["Connection[Any]", Row]): def load(pos: int) -> Row | None: return self._tx.load_row(pos, self._make_row) - while True: - if (row := load(self._pos)) is None: - break + while (row := load(self._pos)) is not None: self._pos += 1 yield row diff --git a/psycopg/psycopg/cursor_async.py b/psycopg/psycopg/cursor_async.py index 0d2886664..4c6bdc55f 100644 --- a/psycopg/psycopg/cursor_async.py +++ b/psycopg/psycopg/cursor_async.py @@ -235,9 +235,7 @@ class AsyncCursor(BaseCursor["AsyncConnection[Any]", Row]): def load(pos: int) -> Row | None: return self._tx.load_row(pos, self._make_row) - while True: - if (row := load(self._pos)) is None: - break + while (row := load(self._pos)) is not None: self._pos += 1 yield row diff --git a/psycopg/psycopg/generators.py b/psycopg/psycopg/generators.py index 0e1fbe9c8..f7ade8a35 100644 --- a/psycopg/psycopg/generators.py +++ b/psycopg/psycopg/generators.py @@ -148,13 +148,10 @@ def _send(pgconn: PGconn) -> PQGen[None]: After this generator has finished you may want to cycle using `fetch()` to retrieve the results available. """ - while True: - if pgconn.flush() == 0: - break + while pgconn.flush() != 0: - while True: - if ready := (yield WAIT_RW): - break + while not (ready := (yield WAIT_RW)): + continue if ready & READY_R: # This call may read notifies: they will be saved in the @@ -216,17 +213,15 @@ def _fetch(pgconn: PGconn) -> PQGen[PGresult | None]: Return a result from the database (whether success or error). """ if pgconn.is_busy(): - while True: - if (yield WAIT_R): - break + while not (yield WAIT_R): + continue while True: pgconn.consume_input() if not pgconn.is_busy(): break - while True: - if (yield WAIT_R): - break + while not (yield WAIT_R): + continue _consume_notifies(pgconn) @@ -244,9 +239,8 @@ def _pipeline_communicate( results = [] while True: - while True: - if ready := (yield WAIT_RW): - break + while not (ready := (yield WAIT_RW)): + continue if ready & READY_R: pgconn.consume_input() @@ -283,9 +277,7 @@ def _pipeline_communicate( def _consume_notifies(pgconn: PGconn) -> None: # Consume notifies - while True: - if not (n := pgconn.notifies()): - break + while n := pgconn.notifies(): if pgconn.notify_handler: pgconn.notify_handler(n) @@ -295,13 +287,10 @@ def notifies(pgconn: PGconn) -> PQGen[list[pq.PGnotify]]: pgconn.consume_input() ns = [] - while True: - if n := pgconn.notifies(): - ns.append(n) - if pgconn.notify_handler: - pgconn.notify_handler(n) - else: - break + while n := pgconn.notifies(): + ns.append(n) + if pgconn.notify_handler: + pgconn.notify_handler(n) return ns @@ -313,9 +302,8 @@ def copy_from(pgconn: PGconn) -> PQGen[memoryview | PGresult]: break # would block - while True: - if (yield WAIT_R): - break + while not (yield WAIT_R): + continue pgconn.consume_input() if nbytes > 0: @@ -342,9 +330,8 @@ def copy_to(pgconn: PGconn, buffer: Buffer, flush: bool = True) -> PQGen[None]: # into smaller ones. We prefer to do it there instead of here in order to # do it upstream the queue decoupling the writer task from the producer one. while pgconn.put_copy_data(buffer) == 0: - while True: - if (yield WAIT_W): - break + while not (yield WAIT_W): + continue # Flushing often has a good effect on macOS because memcpy operations # seem expensive on this platform so accumulating a large buffer has a @@ -352,9 +339,8 @@ def copy_to(pgconn: PGconn, buffer: Buffer, flush: bool = True) -> PQGen[None]: if flush: # Repeat until it the message is flushed to the server while True: - while True: - if (yield WAIT_W): - break + while not (yield WAIT_W): + continue if pgconn.flush() == 0: break @@ -363,15 +349,13 @@ def copy_to(pgconn: PGconn, buffer: Buffer, flush: bool = True) -> PQGen[None]: def copy_end(pgconn: PGconn, error: bytes | None) -> PQGen[PGresult]: # Retry enqueuing end copy message until successful while pgconn.put_copy_end(error) == 0: - while True: - if (yield WAIT_W): - break + while not (yield WAIT_W): + continue # Repeat until it the message is flushed to the server while True: - while True: - if (yield WAIT_W): - break + while not (yield WAIT_W): + continue if pgconn.flush() == 0: break diff --git a/tests/pq/test_async.py b/tests/pq/test_async.py index 404239fb4..dd54efe66 100644 --- a/tests/pq/test_async.py +++ b/tests/pq/test_async.py @@ -23,9 +23,7 @@ def test_send_query(pgconn): # send loop waited_on_send = 0 - while True: - if pgconn.flush() == 0: - break + while pgconn.flush() != 0: waited_on_send += 1 diff --git a/tests/test_copy.py b/tests/test_copy.py index 949ec0caf..3c64196d4 100644 --- a/tests/test_copy.py +++ b/tests/test_copy.py @@ -144,9 +144,7 @@ def test_copy_out_allchars(conn, format): ) with cur.copy(query) as copy: copy.set_types(["text"]) - while True: - if not (row := copy.read_row()): - break + while row := copy.read_row(): assert len(row) == 1 rows.append(row[0]) @@ -158,9 +156,7 @@ def test_read_row_notypes(conn, format): cur = conn.cursor() with cur.copy(f"copy ({sample_values}) to stdout (format {format.name})") as copy: rows = [] - while True: - if not (row := copy.read_row()): - break + while row := copy.read_row(): rows.append(row) ref = [tuple((py_to_raw(i, format) for i in record)) for record in sample_records] @@ -733,15 +729,13 @@ def test_copy_to_leaks(conn_cls, dsn, faker, fmt, set_types, method, gc): copy.set_types(faker.types_names) if method == "read": - while True: - if not copy.read(): - break + while copy.read(): + pass elif method == "iter": list(copy) elif method == "row": - while True: - if copy.read_row() is None: - break + while copy.read_row() is not None: + pass elif method == "rows": list(copy.rows()) @@ -859,9 +853,7 @@ class DataGenerator: def blocks(self): f = self.file() - while True: - if not (block := f.read(self.block_size)): - break + while block := f.read(self.block_size): yield block def assert_data(self): @@ -874,9 +866,7 @@ class DataGenerator: def sha(self, f): m = hashlib.sha256() - while True: - if not (block := f.read()): - break + while block := f.read(): if isinstance(block, str): block = block.encode() m.update(block) diff --git a/tests/test_copy_async.py b/tests/test_copy_async.py index 290c43c85..7fa8223d6 100644 --- a/tests/test_copy_async.py +++ b/tests/test_copy_async.py @@ -148,9 +148,7 @@ async def test_copy_out_allchars(aconn, format): ) async with cur.copy(query) as copy: copy.set_types(["text"]) - while True: - if not (row := (await copy.read_row())): - break + while row := (await copy.read_row()): assert len(row) == 1 rows.append(row[0]) @@ -164,9 +162,7 @@ async def test_read_row_notypes(aconn, format): f"copy ({sample_values}) to stdout (format {format.name})" ) as copy: rows = [] - while True: - if not (row := (await copy.read_row())): - break + while row := (await copy.read_row()): rows.append(row) ref = [tuple(py_to_raw(i, format) for i in record) for record in sample_records] @@ -749,15 +745,13 @@ async def test_copy_to_leaks(aconn_cls, dsn, faker, fmt, set_types, method, gc): copy.set_types(faker.types_names) if method == "read": - while True: - if not (await copy.read()): - break + while await copy.read(): + pass elif method == "iter": await alist(copy) elif method == "row": - while True: - if (await copy.read_row()) is None: - break + while (await copy.read_row()) is not None: + pass elif method == "rows": await alist(copy.rows()) @@ -874,9 +868,7 @@ class DataGenerator: def blocks(self): f = self.file() - while True: - if not (block := f.read(self.block_size)): - break + while block := f.read(self.block_size): yield block async def assert_data(self): @@ -889,9 +881,7 @@ class DataGenerator: def sha(self, f): m = hashlib.sha256() - while True: - if not (block := f.read()): - break + while block := f.read(): if isinstance(block, str): block = block.encode() m.update(block) diff --git a/tests/test_cursor.py b/tests/test_cursor.py index cf5551ca0..bb7af9f79 100644 --- a/tests/test_cursor.py +++ b/tests/test_cursor.py @@ -85,13 +85,11 @@ def test_leak(conn_cls, dsn, faker, fmt, fmt_out, fetch, row_factory, gc): cur.execute(faker.select_stmt) if fetch == "one": - while True: - if cur.fetchone() is None: - break + while cur.fetchone() is not None: + pass elif fetch == "many": - while True: - if not cur.fetchmany(3): - break + while cur.fetchmany(3): + pass elif fetch == "all": cur.fetchall() elif fetch == "iter": diff --git a/tests/test_cursor_async.py b/tests/test_cursor_async.py index fa6b70175..4f683d1ed 100644 --- a/tests/test_cursor_async.py +++ b/tests/test_cursor_async.py @@ -86,13 +86,11 @@ async def test_leak(aconn_cls, dsn, faker, fmt, fmt_out, fetch, row_factory, gc) await cur.execute(faker.select_stmt) if fetch == "one": - while True: - if (await cur.fetchone()) is None: - break + while (await cur.fetchone()) is not None: + pass elif fetch == "many": - while True: - if not (await cur.fetchmany(3)): - break + while await cur.fetchmany(3): + pass elif fetch == "all": await cur.fetchall() elif fetch == "iter": diff --git a/tests/test_cursor_client.py b/tests/test_cursor_client.py index fd87cf551..de4c08541 100644 --- a/tests/test_cursor_client.py +++ b/tests/test_cursor_client.py @@ -95,13 +95,11 @@ def test_leak(conn_cls, dsn, faker, fetch, row_factory, gc): cur.execute(faker.select_stmt) if fetch == "one": - while True: - if cur.fetchone() is None: - break + while cur.fetchone() is not None: + pass elif fetch == "many": - while True: - if not cur.fetchmany(3): - break + while cur.fetchmany(3): + pass elif fetch == "all": cur.fetchall() elif fetch == "iter": diff --git a/tests/test_cursor_client_async.py b/tests/test_cursor_client_async.py index a580f0d66..7945c1b7e 100644 --- a/tests/test_cursor_client_async.py +++ b/tests/test_cursor_client_async.py @@ -96,13 +96,11 @@ async def test_leak(aconn_cls, dsn, faker, fetch, row_factory, gc): await cur.execute(faker.select_stmt) if fetch == "one": - while True: - if (await cur.fetchone()) is None: - break + while (await cur.fetchone()) is not None: + pass elif fetch == "many": - while True: - if not (await cur.fetchmany(3)): - break + while await cur.fetchmany(3): + pass elif fetch == "all": await cur.fetchall() elif fetch == "iter": diff --git a/tests/test_cursor_raw.py b/tests/test_cursor_raw.py index 0f2155e3f..b12128cf5 100644 --- a/tests/test_cursor_raw.py +++ b/tests/test_cursor_raw.py @@ -93,13 +93,11 @@ def test_leak(conn_cls, dsn, faker, fmt, fmt_out, fetch, row_factory, gc): cur.execute(ph(cur, faker.select_stmt)) if fetch == "one": - while True: - if cur.fetchone() is None: - break + while cur.fetchone() is not None: + pass elif fetch == "many": - while True: - if not cur.fetchmany(3): - break + while cur.fetchmany(3): + pass elif fetch == "all": cur.fetchall() elif fetch == "iter": diff --git a/tests/test_cursor_raw_async.py b/tests/test_cursor_raw_async.py index f2f9553ad..089d0ff4b 100644 --- a/tests/test_cursor_raw_async.py +++ b/tests/test_cursor_raw_async.py @@ -90,13 +90,11 @@ async def test_leak(aconn_cls, dsn, faker, fmt, fmt_out, fetch, row_factory, gc) await cur.execute(ph(cur, faker.select_stmt)) if fetch == "one": - while True: - if (await cur.fetchone()) is None: - break + while (await cur.fetchone()) is not None: + pass elif fetch == "many": - while True: - if not (await cur.fetchmany(3)): - break + while await cur.fetchmany(3): + pass elif fetch == "all": await cur.fetchall() elif fetch == "iter": diff --git a/tests/test_cursor_server.py b/tests/test_cursor_server.py index 365f0b762..d5342a689 100644 --- a/tests/test_cursor_server.py +++ b/tests/test_cursor_server.py @@ -384,9 +384,7 @@ def test_row_factory(conn): cur.execute("select generate_series(1, 3) as x") recs = cur.fetchall() cur.scroll(0, "absolute") - while True: - if not (rec := cur.fetchone()): - break + while rec := cur.fetchone(): recs.append(rec) assert recs == [[1, -1], [1, -2], [1, -3]] * 2 diff --git a/tests/test_cursor_server_async.py b/tests/test_cursor_server_async.py index cede008f7..682859984 100644 --- a/tests/test_cursor_server_async.py +++ b/tests/test_cursor_server_async.py @@ -390,9 +390,7 @@ async def test_row_factory(aconn): await cur.execute("select generate_series(1, 3) as x") recs = await cur.fetchall() await cur.scroll(0, "absolute") - while True: - if not (rec := (await cur.fetchone())): - break + while rec := (await cur.fetchone()): recs.append(rec) assert recs == [[1, -1], [1, -2], [1, -3]] * 2