connect = r.connect # module-level factory: r.connect == r.r.connect
The vendored driver/python3/rethinkdb/__init__.py ends with r = RethinkDB() but never binds the module-level connect symbol, so import rethinkdb as r; r.connect(...) raises AttributeError — only from rethinkdb import r worked (the instance carries connect). The fix exposes the instance's bound connect as a module attribute and adds it to __all__.
The core fix (2 lines, at the bottom of driver/python3/rethinkdb/__init__.py):
# (existing module ends with:)
r = RethinkDB()
# --- fix ---
connect = r.connect # module-level factory: r.connect == r.r.connect
And in __all__:
# before:
__all__ = ["RethinkDB"] + errors.__all__
# after:
__all__ = ["RethinkDB", "connect"] + errors.__all__
One companion line was required to make star-import actually resolve (see Evidence — pre-existing upstream bug): every name in __all__ must be a module attribute, but the error classes come from rethinkdb.errors and are not. Add near the top:
from rethinkdb import errors, version
from rethinkdb.errors import * # makes errors.__all__ names resolvable for star-import
Complete resulting tail of the file:
def connect(self, *args, **kwargs):
return self.make_connection(self.connection_type, *args, **kwargs)
r = RethinkDB()
# Expose the module-level connection factory directly on the package so
# `import rethinkdb as r; r.connect(...)` works, matching the documented
# `from rethinkdb import r; r.connect(...)` behavior.
connect = r.connect
Usage after the fix:
import rethinkdb as r
conn = r.connect(host='<ip-address>', port=38015) # was AttributeError, now works
conn.close()
from rethinkdb import * # star-import now resolves
conn = connect(host='<ip-address>', port=38015) # was AttributeError too
Reproduced against the upstream source (pip `rethinkdb==2.4.10.post1+source`, identical to `rethinkdb-python` master and the vendored driver) copied into a vendored tree, and verified live against the RethinkDB server on **port 38015**. **1. Bug reproduced (before fix):** ``` module has connect attr: False REPRODUCED AttributeError: module 'rethinkdb' has no attribute 'connect' instance connect exists: True # from rethinkdb import r; r.connect(...) worked ``` **2. After fix — module-level connect, live (port 38015):** ``` type: DefaultConnection | is DefaultConnection: True live expr(1).add(1) -> 2 live db_list -> ['rethinkdb', 'test'] live server_status row -> karaHermes_mde_7840hs_kom close OK ``` **3. After fix — star-import connect, live:** ``` 'connect' in star ns: True | 'RethinkDB': True | 'ReqlDriverError': True type: DefaultConnection | is DefaultConnection: True live query via star-imported connect: 3 close OK ``` **4. Edge cases tested:** - **Alias identity:** `r.connect == r.r.connect` → `True` (exact bound method, no wrapper indirection). - **Argument passthrough:** signature is `(*args, **kwargs)`; all `host/port/auth_key/db/timeout` flow through untouched. A no-arg `r.connect(timeout=3)` correctly targeted default `localhost:28015` and raised `ReqlDriverError` (proving defaults aren't swallowed). - **Pre-existing star-import bug (upstream, not introduced by this fix):** with *only* the two documented changes, `from rethinkdb import *` still fails — `AttributeError: module 'rethinkdb' has no attribute 'ReqlAuthError'` — because upstream `__all__` lists `errors.__all__` names that aren't module attributes. Verified this fails on the **unfixed upstream package too**. The one-line `from rethinkdb.errors import *` companion fixes it; the two documented changes remain the core of the fix. - **Regression:** `from rethinkdb import r; r.connect(...)` and `rethinkdb.RethinkDB().connect(...)` still return live `DefaultConnection`s; `__version__` intact. - **Scope limitation (upstream behavior, unchanged):** the module alias covers `connect` only; query API (`expr`, `table`, …) lives on the instance `r`, so `import rethinkdb as r; r.expr(...)` still requires the instance (`r.r.expr(...)` or `from rethinkdb import r`) — this matches upstream and is outside this fix's scope. - **Unrelated gotcha noted:** `DefaultCursor` is not subscriptable; use `.next()`. **Files verified:** `/tmp/vendored2/rethinkdb/__init__.py` (fixed copy of the vendored driver). Diff vs upstream is exactly the 3 lines above. ---
{"model": "deepseek-v4-flash", "problem_class": "python-driver-module-level-connect-api", "result": "passed", "tests": 9}