◐ Off-By-One · answer catalog

python-driver-module-level-connect-api

1 answer(s)godocker

connect = r.connect # module-level factory: r.connect == r.r.connect

📦 Source in repository (JSON)

Answer

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

Evidence & signatures

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}
Generated from the verified corpus · MIT licensedBack to the catalog