From 0fe40f7222e0c3447b909e0269bd33966f495cb9 Mon Sep 17 00:00:00 2001 From: David Pineda Date: Sat, 19 Feb 2022 13:20:43 -0300 Subject: [PATCH 01/16] Update net_asyncio.py --- rethinkdb/asyncio_net/net_asyncio.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rethinkdb/asyncio_net/net_asyncio.py b/rethinkdb/asyncio_net/net_asyncio.py index 781081e5..6dfd0945 100644 --- a/rethinkdb/asyncio_net/net_asyncio.py +++ b/rethinkdb/asyncio_net/net_asyncio.py @@ -69,7 +69,6 @@ def reusable_waiter(loop, timeout): else: deadline = None - @asyncio.coroutine def wait(future): if deadline is not None: new_timeout = max(deadline - loop.time(), 0) @@ -284,6 +283,7 @@ def close(self, noreply_wait=False, token=None, exception=None): yield from self.run_query(noreply, False) self._streamwriter.close() + await self._streamwriter.wait_closed() # We must not wait for the _reader_task if we got an exception, because that # means that we were called from it. Waiting would lead to a deadlock. if self._reader_task and exception is None: From 41fd1a90e044c792c66da212f48b760a8e217020 Mon Sep 17 00:00:00 2001 From: Sam Hughes Date: Wed, 4 Oct 2023 14:06:24 -0700 Subject: [PATCH 02/16] Replace "is not" against empty string with "!=" Silences warning (or perhaps legit error, now) --- rethinkdb/asyncio_net/net_asyncio.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rethinkdb/asyncio_net/net_asyncio.py b/rethinkdb/asyncio_net/net_asyncio.py index 781081e5..2f9152ac 100644 --- a/rethinkdb/asyncio_net/net_asyncio.py +++ b/rethinkdb/asyncio_net/net_asyncio.py @@ -227,7 +227,7 @@ def connect(self, timeout): break # This may happen in the `V1_0` protocol where we send two requests as # an optimization, then need to read each separately - if request is not "": + if request != "": self._streamwriter.write(request) response = yield from asyncio.wait_for( From 10e95456f6ff0cba1d13ab1d85699cda1bbebdf5 Mon Sep 17 00:00:00 2001 From: Sam Hughes Date: Wed, 4 Oct 2023 14:07:07 -0700 Subject: [PATCH 03/16] Remove loop parameters that are not used in 3.10 In Python 3.9, they are optional, and we default to the active event loop. --- rethinkdb/asyncio_net/net_asyncio.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/rethinkdb/asyncio_net/net_asyncio.py b/rethinkdb/asyncio_net/net_asyncio.py index 2f9152ac..73cbcdd7 100644 --- a/rethinkdb/asyncio_net/net_asyncio.py +++ b/rethinkdb/asyncio_net/net_asyncio.py @@ -75,7 +75,7 @@ def wait(future): new_timeout = max(deadline - loop.time(), 0) else: new_timeout = None - return (yield from asyncio.wait_for(future, new_timeout, loop=loop)) + return (yield from asyncio.wait_for(future, new_timeout)) return wait @@ -202,7 +202,6 @@ def connect(self, timeout): self._streamreader, self._streamwriter = yield from asyncio.open_connection( self._parent.host, self._parent.port, - loop=self._io_loop, ssl=ssl_context, ) self._streamwriter.get_extra_info("socket").setsockopt( @@ -233,7 +232,6 @@ def connect(self, timeout): response = yield from asyncio.wait_for( _read_until(self._streamreader, b"\0"), timeout, - loop=self._io_loop, ) response = response[:-1] except ReqlAuthError: From 13e85df2e76509c8b6f6703dea792d4469cc4d9d Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 30 Jan 2023 17:29:04 +0000 Subject: [PATCH 04/16] asyncio_net/net_asyncio.py: async/await syntax for python 3.11.1 compatibility --- rethinkdb/asyncio_net/net_asyncio.py | 126 ++++++++++++++++----------- 1 file changed, 74 insertions(+), 52 deletions(-) diff --git a/rethinkdb/asyncio_net/net_asyncio.py b/rethinkdb/asyncio_net/net_asyncio.py index 73cbcdd7..12d2e96f 100644 --- a/rethinkdb/asyncio_net/net_asyncio.py +++ b/rethinkdb/asyncio_net/net_asyncio.py @@ -39,13 +39,14 @@ pQuery = ql2_pb2.Query.QueryType -@asyncio.coroutine -def _read_until(streamreader, delimiter): +# @asyncio.coroutine +async def _read_until(streamreader, delimiter): """Naive implementation of reading until a delimiter""" buffer = bytearray() while True: - c = yield from streamreader.read(1) + # c = yield from streamreader.read(1) + c = await streamreader.read(1) if c == b"": break # EOF buffer.append(c[0]) @@ -69,13 +70,14 @@ def reusable_waiter(loop, timeout): else: deadline = None - @asyncio.coroutine - def wait(future): + # @asyncio.coroutine + async def wait(future): if deadline is not None: new_timeout = max(deadline - loop.time(), 0) else: new_timeout = None - return (yield from asyncio.wait_for(future, new_timeout)) + # return (yield from asyncio.wait_for(future, new_timeout)) + return (await asyncio.wait_for(future, new_timeout)) return wait @@ -101,20 +103,22 @@ def __init__(self, *args, **kwargs): def __aiter__(self): return self - @asyncio.coroutine - def __anext__(self): + # @asyncio.coroutine + async def __anext__(self): try: - return (yield from self._get_next(None)) + # return (yield from self._get_next(None)) + return (await self._get_next(None)) except ReqlCursorEmpty: raise StopAsyncIteration - @asyncio.coroutine - def close(self): + # @asyncio.coroutine + async def close(self): if self.error is None: self.error = self._empty_error() if self.conn.is_open(): self.outstanding_requests += 1 - yield from self.conn._parent._stop(self) + # yield from self.conn._parent._stop(self) + await self.conn._parent._stop(self) def _extend(self, res_buf): Cursor._extend(self, res_buf) @@ -123,8 +127,8 @@ def _extend(self, res_buf): # Convenience function so users know when they've hit the end of the cursor # without having to catch an exception - @asyncio.coroutine - def fetch_next(self, wait=True): + # @asyncio.coroutine + async def fetch_next(self, wait=True): timeout = Cursor._wait_to_timeout(wait) waiter = reusable_waiter(self.conn._io_loop, timeout) while len(self.items) == 0 and self.error is None: @@ -132,7 +136,8 @@ def fetch_next(self, wait=True): if self.error is not None: raise self.error with translate_timeout_errors(): - yield from waiter(asyncio.shield(self.new_response)) + # yield from waiter(asyncio.shield(self.new_response)) + await waiter(asyncio.shield(self.new_response)) # If there is a (non-empty) error to be received, we return True, so the # user will receive it on the next `next` call. return len(self.items) != 0 or not isinstance(self.error, RqlCursorEmpty) @@ -142,15 +147,16 @@ def _empty_error(self): # with mechanisms to return from a coroutine. return RqlCursorEmpty() - @asyncio.coroutine - def _get_next(self, timeout): + # @asyncio.coroutine + async def _get_next(self, timeout): waiter = reusable_waiter(self.conn._io_loop, timeout) while len(self.items) == 0: self._maybe_fetch_batch() if self.error is not None: raise self.error with translate_timeout_errors(): - yield from waiter(asyncio.shield(self.new_response)) + # yield from waiter(asyncio.shield(self.new_response)) + await waiter(asyncio.shield(self.new_response)) return self.items.popleft() def _maybe_fetch_batch(self): @@ -186,8 +192,8 @@ def client_address(self): if self.is_open(): return self._streamwriter.get_extra_info("sockname")[0] - @asyncio.coroutine - def connect(self, timeout): + # @asyncio.coroutine + async def connect(self, timeout): try: ssl_context = None if len(self._parent.ssl) > 0: @@ -199,7 +205,8 @@ def connect(self, timeout): ssl_context.check_hostname = True # redundant with match_hostname ssl_context.load_verify_locations(self._parent.ssl["ca_certs"]) - self._streamreader, self._streamwriter = yield from asyncio.open_connection( + # self._streamreader, self._streamwriter = yield from asyncio.open_connection( + self._streamreader, self._streamwriter = await asyncio.open_connection( self._parent.host, self._parent.port, ssl=ssl_context, @@ -229,22 +236,26 @@ def connect(self, timeout): if request != "": self._streamwriter.write(request) - response = yield from asyncio.wait_for( + # response = yield from asyncio.wait_for( + response = await asyncio.wait_for( _read_until(self._streamreader, b"\0"), timeout, ) response = response[:-1] except ReqlAuthError: - yield from self.close() + # yield from self.close() + await self.close() raise except ReqlTimeoutError as err: - yield from self.close() + # yield from self.close() + await self.close() raise ReqlDriverError( "Connection interrupted during handshake with %s:%s. Error: %s" % (self._parent.host, self._parent.port, str(err)) ) except Exception as err: - yield from self.close() + # yield from self.close() + await self.close() raise ReqlDriverError( "Could not connect to %s:%s. Error: %s" % (self._parent.host, self._parent.port, str(err)) @@ -258,8 +269,8 @@ def connect(self, timeout): def is_open(self): return not (self._closing or self._streamreader.at_eof()) - @asyncio.coroutine - def close(self, noreply_wait=False, token=None, exception=None): + # @asyncio.coroutine + async def close(self, noreply_wait=False, token=None, exception=None): self._closing = True if exception is not None: err_message = "Connection is closed (%s)." % str(exception) @@ -279,38 +290,43 @@ def close(self, noreply_wait=False, token=None, exception=None): if noreply_wait: noreply = Query(pQuery.NOREPLY_WAIT, token, None, None) - yield from self.run_query(noreply, False) + # yield from self.run_query(noreply, False) + await self.run_query(noreply, False) self._streamwriter.close() # We must not wait for the _reader_task if we got an exception, because that # means that we were called from it. Waiting would lead to a deadlock. if self._reader_task and exception is None: - yield from self._reader_task + # yield from self._reader_task + await self._reader_task return None - @asyncio.coroutine - def run_query(self, query, noreply): + # @asyncio.coroutine + async def run_query(self, query, noreply): self._streamwriter.write(query.serialize(self._parent._get_json_encoder(query))) if noreply: return None response_future = asyncio.Future() self._user_queries[query.token] = (query, response_future) - return (yield from response_future) + # return (yield from response_future) + return (await response_future) # The _reader coroutine runs in parallel, reading responses # off of the socket and forwarding them to the appropriate Future or Cursor. # This is shut down as a consequence of closing the stream, or an error in the # socket/protocol from the server. Unexpected errors in this coroutine will # close the ConnectionInstance and be passed to any open Futures or Cursors. - @asyncio.coroutine - def _reader(self): + # @asyncio.coroutine + async def _reader(self): try: while True: - buf = yield from self._streamreader.readexactly(12) + # buf = yield from self._streamreader.readexactly(12) + buf = await self._streamreader.readexactly(12) (token, length,) = struct.unpack(" Date: Wed, 4 Oct 2023 14:12:17 -0700 Subject: [PATCH 05/16] Remove commented pre-3.11 asyncio lines --- rethinkdb/asyncio_net/net_asyncio.py | 37 ---------------------------- 1 file changed, 37 deletions(-) diff --git a/rethinkdb/asyncio_net/net_asyncio.py b/rethinkdb/asyncio_net/net_asyncio.py index 12d2e96f..e9bec3ee 100644 --- a/rethinkdb/asyncio_net/net_asyncio.py +++ b/rethinkdb/asyncio_net/net_asyncio.py @@ -39,13 +39,11 @@ pQuery = ql2_pb2.Query.QueryType -# @asyncio.coroutine async def _read_until(streamreader, delimiter): """Naive implementation of reading until a delimiter""" buffer = bytearray() while True: - # c = yield from streamreader.read(1) c = await streamreader.read(1) if c == b"": break # EOF @@ -70,13 +68,11 @@ def reusable_waiter(loop, timeout): else: deadline = None - # @asyncio.coroutine async def wait(future): if deadline is not None: new_timeout = max(deadline - loop.time(), 0) else: new_timeout = None - # return (yield from asyncio.wait_for(future, new_timeout)) return (await asyncio.wait_for(future, new_timeout)) return wait @@ -103,21 +99,17 @@ def __init__(self, *args, **kwargs): def __aiter__(self): return self - # @asyncio.coroutine async def __anext__(self): try: - # return (yield from self._get_next(None)) return (await self._get_next(None)) except ReqlCursorEmpty: raise StopAsyncIteration - # @asyncio.coroutine async def close(self): if self.error is None: self.error = self._empty_error() if self.conn.is_open(): self.outstanding_requests += 1 - # yield from self.conn._parent._stop(self) await self.conn._parent._stop(self) def _extend(self, res_buf): @@ -127,7 +119,6 @@ def _extend(self, res_buf): # Convenience function so users know when they've hit the end of the cursor # without having to catch an exception - # @asyncio.coroutine async def fetch_next(self, wait=True): timeout = Cursor._wait_to_timeout(wait) waiter = reusable_waiter(self.conn._io_loop, timeout) @@ -136,7 +127,6 @@ async def fetch_next(self, wait=True): if self.error is not None: raise self.error with translate_timeout_errors(): - # yield from waiter(asyncio.shield(self.new_response)) await waiter(asyncio.shield(self.new_response)) # If there is a (non-empty) error to be received, we return True, so the # user will receive it on the next `next` call. @@ -147,7 +137,6 @@ def _empty_error(self): # with mechanisms to return from a coroutine. return RqlCursorEmpty() - # @asyncio.coroutine async def _get_next(self, timeout): waiter = reusable_waiter(self.conn._io_loop, timeout) while len(self.items) == 0: @@ -155,7 +144,6 @@ async def _get_next(self, timeout): if self.error is not None: raise self.error with translate_timeout_errors(): - # yield from waiter(asyncio.shield(self.new_response)) await waiter(asyncio.shield(self.new_response)) return self.items.popleft() @@ -192,7 +180,6 @@ def client_address(self): if self.is_open(): return self._streamwriter.get_extra_info("sockname")[0] - # @asyncio.coroutine async def connect(self, timeout): try: ssl_context = None @@ -205,7 +192,6 @@ async def connect(self, timeout): ssl_context.check_hostname = True # redundant with match_hostname ssl_context.load_verify_locations(self._parent.ssl["ca_certs"]) - # self._streamreader, self._streamwriter = yield from asyncio.open_connection( self._streamreader, self._streamwriter = await asyncio.open_connection( self._parent.host, self._parent.port, @@ -236,25 +222,21 @@ async def connect(self, timeout): if request != "": self._streamwriter.write(request) - # response = yield from asyncio.wait_for( response = await asyncio.wait_for( _read_until(self._streamreader, b"\0"), timeout, ) response = response[:-1] except ReqlAuthError: - # yield from self.close() await self.close() raise except ReqlTimeoutError as err: - # yield from self.close() await self.close() raise ReqlDriverError( "Connection interrupted during handshake with %s:%s. Error: %s" % (self._parent.host, self._parent.port, str(err)) ) except Exception as err: - # yield from self.close() await self.close() raise ReqlDriverError( "Could not connect to %s:%s. Error: %s" @@ -269,7 +251,6 @@ async def connect(self, timeout): def is_open(self): return not (self._closing or self._streamreader.at_eof()) - # @asyncio.coroutine async def close(self, noreply_wait=False, token=None, exception=None): self._closing = True if exception is not None: @@ -290,19 +271,16 @@ async def close(self, noreply_wait=False, token=None, exception=None): if noreply_wait: noreply = Query(pQuery.NOREPLY_WAIT, token, None, None) - # yield from self.run_query(noreply, False) await self.run_query(noreply, False) self._streamwriter.close() # We must not wait for the _reader_task if we got an exception, because that # means that we were called from it. Waiting would lead to a deadlock. if self._reader_task and exception is None: - # yield from self._reader_task await self._reader_task return None - # @asyncio.coroutine async def run_query(self, query, noreply): self._streamwriter.write(query.serialize(self._parent._get_json_encoder(query))) if noreply: @@ -310,7 +288,6 @@ async def run_query(self, query, noreply): response_future = asyncio.Future() self._user_queries[query.token] = (query, response_future) - # return (yield from response_future) return (await response_future) # The _reader coroutine runs in parallel, reading responses @@ -318,14 +295,11 @@ async def run_query(self, query, noreply): # This is shut down as a consequence of closing the stream, or an error in the # socket/protocol from the server. Unexpected errors in this coroutine will # close the ConnectionInstance and be passed to any open Futures or Cursors. - # @asyncio.coroutine async def _reader(self): try: while True: - # buf = yield from self._streamreader.readexactly(12) buf = await self._streamreader.readexactly(12) (token, length,) = struct.unpack(" Date: Thu, 5 Oct 2023 10:43:36 -0700 Subject: [PATCH 06/16] Use looseversion module --- requirements.txt | 1 + rethinkdb/utils_common.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index b35831ca..b3b8d035 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ async-generator==1.10; python_version>="3.6" codacy-coverage==1.3.11 +looseversion==1.3.0 mock==3.0.5 pytest-cov==2.10.1 pytest-tornasync==0.6.0.post2; python_version >= '3.5' diff --git a/rethinkdb/utils_common.py b/rethinkdb/utils_common.py index 8c9afa1d..1d33f040 100644 --- a/rethinkdb/utils_common.py +++ b/rethinkdb/utils_common.py @@ -19,7 +19,7 @@ import collections import copy -import distutils.version +from looseversion import LooseVersion import getpass import inspect import optparse @@ -146,7 +146,7 @@ def print_progress(ratio, indent=0, read=None, write=None): def check_minimum_version(options, minimum_version="1.6", raise_exception=True): - minimum_version = distutils.version.LooseVersion(minimum_version) + minimum_version = LooseVersion(minimum_version) version_string = options.retryQuery( "get server version", query.db("rethinkdb").table("server_status")[0]["process"]["version"], @@ -159,7 +159,7 @@ def check_minimum_version(options, minimum_version="1.6", raise_exception=True): if not matches: raise RuntimeError("invalid version string format: %s" % version_string) - if distutils.version.LooseVersion(matches.group("version")) < minimum_version: + if LooseVersion(matches.group("version")) < minimum_version: if raise_exception: raise RuntimeError( "Incompatible version, expected >= %s got: %s" From d6f2f5685db4ccf1b09486588f7b323763dc5778 Mon Sep 17 00:00:00 2001 From: Sam Hughes Date: Thu, 5 Oct 2023 12:11:32 -0700 Subject: [PATCH 07/16] Update asyncio example program in README.md --- README.md | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 59d6b6fa..049c1e65 100644 --- a/README.md +++ b/README.md @@ -57,36 +57,35 @@ for hero in marvel_heroes.run(connection): ``` ### Asyncio mode -Asyncio mode is compatible with Python ≥ 3.4, which is when asyncio was -introduced into the standard library. +Asyncio mode is compatible with Python ≥ 3.5. ```python import asyncio from rethinkdb import r -# Native coroutines are supported in Python ≥ 3.5. In Python 3.4, you should -# use the @asyncio.couroutine decorator instead of "async def", and "yield from" -# instead of "await". async def main(): - r.set_loop_type('asyncio') - connection = await r.connect(db='test') - - await r.table_create('marvel').run(connection) - - marvel_heroes = r.table('marvel') - await marvel_heroes.insert({ - 'id': 1, - 'name': 'Iron Man', - 'first_appearance': 'Tales of Suspense #39' - }).run(connection) - - # "async for" is supported in Python ≥ 3.6. In earlier versions, you should - # call "await cursor.next()" in a loop. - cursor = await marvel_heroes.run(connection) - async for hero in cursor: - print(hero['name']) - -asyncio.get_event_loop().run_until_complete(main()) + async with await r.connect(db='test') as connection: + await r.table_create('marvel').run(connection) + + marvel_heroes = r.table('marvel') + await marvel_heroes.insert({ + 'id': 1, + 'name': 'Iron Man', + 'first_appearance': 'Tales of Suspense #39' + }).run(connection) + + # "async for" is supported in Python ≥ 3.6. In earlier versions, you should + # call "await cursor.next()" in a loop. + cursor = await marvel_heroes.run(connection) + async for hero in cursor: + print(hero['name']) + # The `with` block performs `await connection.close(noreply_wait=False)`. + +r.set_loop_type('asyncio') + +# "asyncio.run" was added in Python 3.7. In earlier versions, you +# might try asyncio.get_event_loop().run_until_complete(main()). +asyncio.run(main()) ``` ### Gevent mode From a7e1de07e95de565f31395db50d6964ffca2fe79 Mon Sep 17 00:00:00 2001 From: Sam Hughes Date: Thu, 5 Oct 2023 16:36:32 -0700 Subject: [PATCH 08/16] Constrain coverage requirement version to one that supports Python 3.5 --- requirements.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/requirements.txt b/requirements.txt index b3b8d035..4d2e981d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,6 @@ async-generator==1.10; python_version>="3.6" +coverage<=4.5.4; python_version<"3.5" +coverage==5.5; python_version>="3.5" codacy-coverage==1.3.11 looseversion==1.3.0 mock==3.0.5 From 4c594ddfa8a66b178122f3ec1ca5496ad87cccf4 Mon Sep 17 00:00:00 2001 From: Sam Hughes Date: Sat, 21 Oct 2023 14:05:28 -0700 Subject: [PATCH 09/16] Only call wait_closed when Python >= 3.7 --- rethinkdb/asyncio_net/net_asyncio.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/rethinkdb/asyncio_net/net_asyncio.py b/rethinkdb/asyncio_net/net_asyncio.py index 56522c38..e0058c4d 100644 --- a/rethinkdb/asyncio_net/net_asyncio.py +++ b/rethinkdb/asyncio_net/net_asyncio.py @@ -20,6 +20,7 @@ import socket import ssl import struct +import sys from rethinkdb import ql2_pb2 from rethinkdb.errors import ( @@ -156,6 +157,8 @@ def _maybe_fetch_batch(self): self.outstanding_requests += 1 asyncio.ensure_future(self.conn._parent._continue(self)) +# Python <3.7's StreamWriter has no wait_closed(). +DO_WAIT_CLOSED = sys.version_info >= (3, 7) class ConnectionInstance(object): _streamreader = None @@ -274,7 +277,9 @@ async def close(self, noreply_wait=False, token=None, exception=None): await self.run_query(noreply, False) self._streamwriter.close() - await self._streamwriter.wait_closed() + # Python <3.7 has no wait_closed(). + if DO_WAIT_CLOSED: + await self._streamwriter.wait_closed() # We must not wait for the _reader_task if we got an exception, because that # means that we were called from it. Waiting would lead to a deadlock. if self._reader_task and exception is None: From 034208052ed0dcdaddef3920550b04488b6fa1db Mon Sep 17 00:00:00 2001 From: Sam Hughes Date: Fri, 10 Nov 2023 07:25:38 -0800 Subject: [PATCH 10/16] Make _restore.py -i db.table option work --- rethinkdb/_restore.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rethinkdb/_restore.py b/rethinkdb/_restore.py index 178f1bdc..2c29eb1c 100755 --- a/rethinkdb/_restore.py +++ b/rethinkdb/_restore.py @@ -244,7 +244,7 @@ def do_unzip(temp_dir, options): ) # filter out tables we are not looking for - table = os.path.splitext(file_name) + table = os.path.splitext(file_name)[0] if tables_to_export and not ( (db, table) in tables_to_export or (db, None) in tables_to_export ): From 292e661d676d2a7e8fdeb29c7b8528bc0041a2bf Mon Sep 17 00:00:00 2001 From: lsabi <13497689+lsabi@users.noreply.github.com> Date: Mon, 20 Nov 2023 22:38:46 +0100 Subject: [PATCH 11/16] Add looseversion to setup and update tags to most recent python version --- setup.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index 62aa03c3..c696efb0 100644 --- a/setup.py +++ b/setup.py @@ -66,13 +66,15 @@ classifiers=[ 'Intended Audience :: Developers', 'Natural Language :: English', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', ], packages=[ 'rethinkdb', @@ -95,9 +97,10 @@ 'rethinkdb-repl = rethinkdb.__main__:startInterpreter' ] }, - python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", + python_requires=">=3.5", install_requires=[ - 'six' + 'six', + 'looseversion' ], test_suite='tests' ) From b227a12593c00c3e9f66965e8bb81f90c9c5774d Mon Sep 17 00:00:00 2001 From: lsabi <13497689+lsabi@users.noreply.github.com> Date: Sat, 25 Nov 2023 15:53:07 +0100 Subject: [PATCH 12/16] Update setup.py to still support python 2.7 --- setup.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index c696efb0..674c8253 100644 --- a/setup.py +++ b/setup.py @@ -66,6 +66,8 @@ classifiers=[ 'Intended Audience :: Developers', 'Natural Language :: English', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', @@ -97,7 +99,7 @@ 'rethinkdb-repl = rethinkdb.__main__:startInterpreter' ] }, - python_requires=">=3.5", + python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, >=3.5", install_requires=[ 'six', 'looseversion' From 85410ce8df25a67c8fe140bc5e514e038845e5f3 Mon Sep 17 00:00:00 2001 From: Gabor Boros Date: Sat, 9 Dec 2023 13:11:49 +0400 Subject: [PATCH 13/16] fix: do not depend on package to get the version Signed-off-by: Gabor Boros --- rethinkdb/version.py | 2 +- setup.py | 24 +++++++++--------------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/rethinkdb/version.py b/rethinkdb/version.py index 9c4ac378..bf0c23cc 100644 --- a/rethinkdb/version.py +++ b/rethinkdb/version.py @@ -15,4 +15,4 @@ # This file incorporates work covered by the following copyright: # Copyright 2010-2016 RethinkDB, all rights reserved. -VERSION = "2.4.0+source" +VERSION = "2.4.11+source" diff --git a/setup.py b/setup.py index 674c8253..23f505e2 100644 --- a/setup.py +++ b/setup.py @@ -21,8 +21,6 @@ import setuptools -from rethinkdb.version import VERSION - try: import asyncio @@ -32,26 +30,22 @@ RETHINKDB_VERSION_DESCRIBE = os.environ.get("RETHINKDB_VERSION_DESCRIBE") -VERSION_RE = r"^v(?P\d+\.\d+)\.(?P\d+)?(\.(?P\w+))?$" - -if RETHINKDB_VERSION_DESCRIBE: - MATCH = re.match(VERSION_RE, RETHINKDB_VERSION_DESCRIBE) +VERSION_RE = r"(?P[0-9]+)\.(?P[0-9]+)\.(?P[0-9]+)(?P:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?P:\+[0-9A-Za-z-]+)?" - if MATCH: - VERSION = MATCH.group("version") +with open("rethinkdb/version.py", "r") as f: + version_parts = re.search(VERSION_RE, f.read()).groups() + VERSION = ".".join(filter(lambda x: x is not None, version_parts)) - if MATCH.group("patch"): - VERSION += "." + MATCH.group("patch") - if MATCH.group("post"): - VERSION += "." + MATCH.group("post") +if RETHINKDB_VERSION_DESCRIBE: + version_parts = re.match(VERSION_RE, RETHINKDB_VERSION_DESCRIBE) - with open("rethinkdb/version.py", "w") as f: - f.write('VERSION = {0}'.format(repr(VERSION))) - else: + if not version_parts: raise RuntimeError("{!r} does not match version format {!r}".format( RETHINKDB_VERSION_DESCRIBE, VERSION_RE)) + VERSION = ".".join(filter(lambda x: x is not None, version_parts.groups())) + setuptools.setup( name='rethinkdb', From c978af710ebd4567bae1a16fc95daf2ef211a972 Mon Sep 17 00:00:00 2001 From: Gabor Boros Date: Sun, 10 Dec 2023 09:44:01 +0400 Subject: [PATCH 14/16] chore: correct the version number Signed-off-by: Gabor Boros --- rethinkdb/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rethinkdb/version.py b/rethinkdb/version.py index bf0c23cc..572868c2 100644 --- a/rethinkdb/version.py +++ b/rethinkdb/version.py @@ -15,4 +15,4 @@ # This file incorporates work covered by the following copyright: # Copyright 2010-2016 RethinkDB, all rights reserved. -VERSION = "2.4.11+source" +VERSION = "2.4.10.post1+source" From f6cbffc90bfb5b2435ee31df25af8d8c66def9cb Mon Sep 17 00:00:00 2001 From: Gabor Boros Date: Sun, 10 Dec 2023 09:56:13 +0400 Subject: [PATCH 15/16] chore: simplify regex for rethinkdb case Signed-off-by: Gabor Boros --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 23f505e2..ded5627f 100644 --- a/setup.py +++ b/setup.py @@ -30,7 +30,7 @@ RETHINKDB_VERSION_DESCRIBE = os.environ.get("RETHINKDB_VERSION_DESCRIBE") -VERSION_RE = r"(?P[0-9]+)\.(?P[0-9]+)\.(?P[0-9]+)(?P:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?P:\+[0-9A-Za-z-]+)?" +VERSION_RE = r"(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?Ppost[1-9]\d*)" with open("rethinkdb/version.py", "r") as f: version_parts = re.search(VERSION_RE, f.read()).groups() From 339cd9a8b895ed3b1d74b2d8878eb7f0a5d4a9e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Boros?= Date: Thu, 22 May 2025 10:09:35 +0400 Subject: [PATCH 16/16] fix: add r strings for regex escape (#313) --- scripts/convert_protofile.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/convert_protofile.py b/scripts/convert_protofile.py index 98f676e3..ec80b3e8 100644 --- a/scripts/convert_protofile.py +++ b/scripts/convert_protofile.py @@ -86,9 +86,9 @@ def convertFile(inputFile, outputFile, language): assert(outputFile is not None and hasattr(outputFile, 'write')) assert(language in languageDefs) - messageRegex = re.compile('\s*(message|enum) (?P\w+) \{') - valueRegex = re.compile('\s*(?P\w+)\s*=\s*(?P\w+)') - endRegex = re.compile('\s*\}') + messageRegex = re.compile(r'\s*(message|enum) (?P\w+) \{') + valueRegex = re.compile(r'\s*(?P\w+)\s*=\s*(?P\w+)') + endRegex = re.compile(r'\s*\}') indentLevel = languageDefs[language]["initialIndentLevel"] lastIndentLevel = languageDefs[language]["initialIndentLevel"] - 1