Skip to content

Commit f08bd21

Browse files
authored
Chore/clean dependencies (#29)
* Disables retry by default * Update README * Make tenacity as an optional dependency
1 parent a3a25b6 commit f08bd21

6 files changed

Lines changed: 70 additions & 11 deletions

File tree

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,15 @@ PyMongoSQL implements the DB API 2.0 interfaces to provide SQL-like access to Mo
4949
- **JMESPath** (JSON/Dict Path Query)
5050
- jmespath >= 1.0.0
5151

52-
- **Tenacity** (Transient Failure Retry)
53-
- tenacity >= 9.0.0
54-
5552
### Optional Dependencies
5653

54+
- **Tenacity** (Transient Failure Retry)
55+
- tenacity >= 9.0.0
56+
- Install with: `pip install pymongosql[retry]`
57+
5758
- **SQLAlchemy** (for ORM/Core support)
5859
- sqlalchemy >= 1.4.0 (SQLAlchemy 1.4+ and 2.0+ supported)
60+
- Install with: `pip install pymongosql[sqlalchemy]`
5961

6062
## Installation
6163

@@ -212,12 +214,12 @@ Parameters are substituted into the MongoDB filter during execution, providing p
212214

213215
### Retry on Transient System Errors
214216

215-
PyMongoSQL supports retrying transient, system-level MongoDB failures (for example connection timeout and reconnect errors) using Tenacity.
217+
PyMongoSQL supports retrying transient, system-level MongoDB failures (for example connection timeout and reconnect errors) using [Tenacity](https://github.com/jd/tenacity). This feature requires the optional `tenacity` package — install it with `pip install pymongosql[retry]`. If retry is enabled but tenacity is not installed, operations will proceed without retry.
216218

217219
```python
218220
connection = connect(
219221
host="mongodb://localhost:27017/database",
220-
retry_enabled=True, # default: True
222+
retry_enabled=False, # default: False
221223
retry_attempts=3, # default: 3
222224
retry_wait_min=0.1, # default: 0.1 seconds
223225
retry_wait_max=1.0, # default: 1.0 seconds

pymongosql/retry.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44
from typing import Any, Callable, Optional, Tuple, TypeVar
55

66
from pymongo.errors import AutoReconnect, ConnectionFailure, NetworkTimeout, PyMongoError, ServerSelectionTimeoutError
7-
from tenacity import Retrying, retry_if_exception_type, stop_after_attempt, wait_exponential
7+
8+
try:
9+
from tenacity import Retrying, retry_if_exception_type, stop_after_attempt, wait_exponential
10+
11+
_has_tenacity = True
12+
except ImportError:
13+
_has_tenacity = False
814

915
_logger = logging.getLogger(__name__)
1016
_T = TypeVar("_T")
@@ -19,14 +25,14 @@
1925

2026
@dataclass(frozen=True)
2127
class RetryConfig:
22-
enabled: bool = True
28+
enabled: bool = False
2329
attempts: int = 3
2430
wait_min: float = 0.1
2531
wait_max: float = 1.0
2632

2733
@classmethod
2834
def from_kwargs(cls, kwargs: dict) -> "RetryConfig":
29-
enabled = bool(kwargs.pop("retry_enabled", True))
35+
enabled = bool(kwargs.pop("retry_enabled", False))
3036
attempts = int(kwargs.pop("retry_attempts", 3))
3137
wait_min = float(kwargs.pop("retry_wait_min", 0.1))
3238
wait_max = float(kwargs.pop("retry_wait_max", 1.0))
@@ -57,6 +63,13 @@ def execute_with_retry(
5763
if not config.enabled or config.attempts <= 1:
5864
return operation()
5965

66+
if not _has_tenacity:
67+
_logger.warning(
68+
"Retry is enabled but 'tenacity' package is not installed. "
69+
"Falling back to no-retry. Install it with: pip install pymongosql[retry]"
70+
)
71+
return operation()
72+
6073
def _before_sleep(retry_state: Any) -> None:
6174
error = retry_state.outcome.exception() if retry_state.outcome else None
6275
_logger.warning(

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ dependencies = [
3535
"pymongo>=4.15.0",
3636
"antlr4-python3-runtime>=4.13.0",
3737
"jmespath>=1.0.0",
38-
"tenacity>=9.0.0",
3938
]
4039

4140
[project.optional-dependencies]
41+
retry = ["tenacity>=9.0.0"]
4242
sqlalchemy = ["sqlalchemy>=1.4.0"]
4343
dev = [
4444
"pytest>=7.0.0",

requirements-optional.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1+
# Retry support (optional)
2+
tenacity>=9.0.0
3+
14
# SQLAlchemy support (optional) - supports 1.4+ and 2.x
25
sqlalchemy>=1.4.0,<3.0.0

requirements.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
antlr4-python3-runtime>=4.13.0
22
pymongo>=4.15.0
3-
jmespath>=1.0.0
4-
tenacity>=9.0.0
3+
jmespath>=1.0.0

tests/test_retry.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,45 @@ def command(self, command_payload):
162162
assert row is not None
163163
assert row[0] == "retry-user"
164164
assert state["calls"] == 3
165+
166+
167+
def test_execute_with_retry_works_without_tenacity(monkeypatch):
168+
"""When tenacity is not installed, retry-enabled calls fall back to no-retry."""
169+
monkeypatch.setattr("pymongosql.retry._has_tenacity", False)
170+
171+
state = {"calls": 0}
172+
173+
def operation():
174+
state["calls"] += 1
175+
return "ok"
176+
177+
result = execute_with_retry(
178+
operation,
179+
RetryConfig(enabled=True, attempts=3, wait_min=0.0, wait_max=0.0),
180+
"no-tenacity fallback",
181+
)
182+
183+
assert result == "ok"
184+
assert state["calls"] == 1 # no retry, just one direct call
185+
186+
187+
def test_retry_module_imports_without_tenacity(monkeypatch):
188+
"""The retry module can be imported even if tenacity is absent."""
189+
import importlib
190+
import sys
191+
192+
monkeypatch.setitem(sys.modules, "tenacity", None) # block tenacity import
193+
194+
import pymongosql.retry
195+
196+
importlib.reload(pymongosql.retry)
197+
198+
assert pymongosql.retry._has_tenacity is False
199+
200+
# Still usable with retry disabled
201+
result = pymongosql.retry.execute_with_retry(
202+
lambda: 42,
203+
pymongosql.retry.RetryConfig(enabled=False),
204+
"import test",
205+
)
206+
assert result == 42

0 commit comments

Comments
 (0)