Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 34 additions & 3 deletions .github/workflows/run_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,31 @@ jobs:
test:
name: Run Tests
runs-on: ubuntu-latest
# 3.15 is an allowed failure (see the matrix note). Tolerating it stops a
# failure from failing the workflow and, under the default fail-fast, from
# cancelling the 3.10-3.14 legs.
continue-on-error: ${{ matrix.python-version == '3.15' }}
env:
# fastuuid has no cp315 wheel and its pyo3 rejects 3.15; build it against
# the stable ABI on the 3.15 leg. pyo3 reads only the value "1".
PYO3_USE_ABI3_FORWARD_COMPATIBILITY: ${{ matrix.python-version == '3.15' && '1' || '0' }}
permissions:
contents: read
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
# 3.15 is an allowed failure (continue-on-error above) while Python 3.15
# is a release candidate. Its deps install from cp315 wheels except
# fastuuid (a litellm dep), whose pyo3 rejects a Python past 3.14; the
# job env builds it against the stable ABI on the 3.15 leg only.
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14", "3.15"]
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
- name: Install uv with caching
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
Expand All @@ -103,18 +116,27 @@ jobs:
extra_test:
name: Run Extra and Deno Tests
runs-on: ubuntu-latest
# 3.15 is an allowed failure (see the note in the `test` job); tolerated so
# it does not fail the workflow or, under fail-fast, cancel the 3.10-3.14 legs.
continue-on-error: ${{ matrix.python-version == '3.15' }}
env:
# fastuuid has no cp315 wheel and its pyo3 rejects 3.15; build it against
# the stable ABI on the 3.15 leg. pyo3 reads only the value "1".
PYO3_USE_ABI3_FORWARD_COMPATIBILITY: ${{ matrix.python-version == '3.15' && '1' || '0' }}
permissions:
contents: read
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
# 3.15 is an allowed failure (see the note in the `test` job above).
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14", "3.15"]
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
- name: Install uv with caching
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
Expand Down Expand Up @@ -256,18 +278,27 @@ jobs:
build_package:
name: Build Package
runs-on: ubuntu-latest
# 3.15 is an allowed failure (see the note in the `test` job); tolerated so
# it does not fail the workflow or, under fail-fast, cancel the 3.10-3.14 legs.
continue-on-error: ${{ matrix.python-version == '3.15' }}
env:
# fastuuid has no cp315 wheel and its pyo3 rejects 3.15; build it against
# the stable ABI on the 3.15 leg. pyo3 reads only the value "1".
PYO3_USE_ABI3_FORWARD_COMPATIBILITY: ${{ matrix.python-version == '3.15' && '1' || '0' }}
permissions:
contents: read
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
# 3.15 is an allowed failure (see the note in the `test` job above).
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14", "3.15"]
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
- name: Install uv with caching
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
Expand Down
19 changes: 18 additions & 1 deletion dspy/teleprompt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,24 @@
from dspy.teleprompt.teleprompt_optuna import BootstrapFewShotWithOptuna
from dspy.teleprompt.vanilla import LabeledFewShot

from .gepa.gepa import GEPA
try:
from .gepa.gepa import GEPA
except ModuleNotFoundError as error:
if error.name != "gepa":
raise

class GEPA(Teleprompter):
"""Stand-in for GEPA when the gepa package is not installed.

DSPy installs gepa only on Python < 3.15, because gepa declares requires-python <3.15. The stand-in keeps
GEPA's Teleprompter interface, so code that inspects or wraps GEPA.__init__ and GEPA.compile still imports.
"""

def __init__(self, *args, **kwargs):
raise ImportError(
"gepa is required to use dspy.GEPA. It is not installed by default on Python 3.15 and later "
"because gepa declares requires-python <3.15."
)

__all__ = [
"AvatarOptimizer",
Expand Down
14 changes: 9 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ description = "DSPy"
readme = "README.md"
authors = [{ name = "Omar Khattab", email = "okhattab@stanford.edu" }]
license = {file = "LICENSE"}
requires-python = ">=3.10, <3.15"
requires-python = ">=3.10, <3.16"
Comment thread
greptile-apps[bot] marked this conversation as resolved.
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Science/Research",
Expand All @@ -28,14 +28,17 @@ dependencies = [
"requests>=2.31.0",
"pydantic>=2.11.0",
"pyyaml>=6.0.1",
"litellm>=1.65.8",
# litellm and gepa declare requires-python <3.15, so pip cannot install them on 3.15.
# The bundled lm15 engine serves LM calls without litellm; `dspy[litellm]` opts back in.
"litellm>=1.65.8; python_version < '3.15'",
"jsonschema>=4.0.0",
"diskcache>=5.6.0",
"json-repair>=0.54.2",
"tenacity>=8.2.3", # undeclared runtime dep of litellm, needed for exponential_backoff_retry
"anyio",
"cachetools>=5.5.0",
"cloudpickle>=3.1.2",
"gepa[dspy]==0.1.4",
"gepa[dspy]==0.1.4; python_version < '3.15'",
]

[project.optional-dependencies]
Expand All @@ -61,8 +64,9 @@ dev = [
"numpy>=1.26.0",
# LiteLLM proxy imports an internal FastAPI helper removed in 0.140.7.
"fastapi<0.140.7; sys_platform != 'win32' and python_version < '3.14'",
"litellm>=1.65.8; sys_platform == 'win32' or python_version == '3.14'",
"litellm[proxy]>=1.65.8; sys_platform != 'win32' and python_version < '3.14'", # Remove 3.14 condition once uvloop supports
"litellm>=1.65.8; sys_platform == 'win32' or python_version >= '3.14'",
"litellm[proxy]>=1.65.8; sys_platform != 'win32' and python_version < '3.14'", # Remove the 3.14+ condition once uvloop supports it
"gepa[dspy]==0.1.4",
]
test_extras = [
"mcp; python_version >= '3.10'",
Expand Down
4 changes: 2 additions & 2 deletions tests/test_utils/server/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ def _litellm_test_server() -> Iterator[tuple[str, str]]:
Start one LiteLLM test server per pytest worker and tear it down when the
session completes.
"""
if sys.version_info[:2] == (3, 14):
pytest.skip("Litellm proxy server is not supported on Python 3.14.")
if sys.version_info[:2] >= (3, 14):
pytest.skip("Litellm proxy server is not supported on Python 3.14+.")
with tempfile.TemporaryDirectory() as server_log_dir_path:
# Create a server log file used to store request logs
server_log_file_path = os.path.join(server_log_dir_path, "request_logs.jsonl")
Expand Down
Loading
Loading