Skip to content

Commit

Permalink
Allow python 3.8 for context builder but not CLI, (partial revert of #…
Browse files Browse the repository at this point in the history
…921)

* Import guard for chains requiring py3.9+ and pydantic v2
  • Loading branch information
marius-baseten committed May 30, 2024
1 parent c356870 commit a61b557
Show file tree
Hide file tree
Showing 19 changed files with 142 additions and 106 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
python_version: ["3.9", "3.10", "3.11"]
python_version: ["3.8", "3.9", "3.10", "3.11"]
use_gpu: ["y", "n"]
job_type: ["server"]
steps:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
python_version: ["3.9", "3.10", "3.11"]
python_version: ["3.8", "3.9", "3.10", "3.11"]
use_gpu: ["y", "n"]
job_type: ["server"]
steps:
Expand Down
11 changes: 10 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,14 @@ repos:
entry: poetry run mypy
language: python
types: [python]
exclude: ^examples/|^truss/test.+/|model.py$
exclude: ^examples/|^truss/test.+/|model.py$|^truss-chains/.*
pass_filenames: true
- id: mypy
name: mypy-local (3.9)
entry: poetry run mypy
language: python
types: [python]
files: ^truss-chains/.*
args:
- --python-version=3.9
pass_filenames: true
141 changes: 83 additions & 58 deletions poetry.lock

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ pathspec = ">=0.9.0"
psutil = ">=5.9.4"
pydantic = ">=1.10.0"
pytest-asyncio = "^0.23.6"
python = ">=3.9,<3.12"
# Note: when using chains, 3.9 will be required at runtime, but other truss functionality works with 3.8.
python = ">=3.8,<3.12"
python-json-logger = ">=2.0.2"
python-on-whales = "^0.68.0"
PyYAML = ">=6.0"
Expand All @@ -72,7 +73,7 @@ loguru = ">=0.7.2"
packaging = ">=20.9"
pathspec = ">=0.9.0"
psutil = ">=5.9.4"
python = ">=3.9,<3.12"
python = ">=3.8,<3.12"
python-json-logger = ">=2.0.2"
PyYAML = ">=6.0"
requests = ">=2.31"
Expand Down Expand Up @@ -117,7 +118,7 @@ src_paths = ["isort", "test"]

[tool.mypy]
ignore_missing_imports = true
python_version = "3.9"
python_version = "3.8"
plugins = ["pydantic.mypy"]

[tool.pytest.ini_options]
Expand Down
17 changes: 11 additions & 6 deletions truss-chains/truss_chains/__init__.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import warnings
import sys

if (sys.version_info.major, sys.version_info.minor) <= (3, 8):
raise RuntimeError(
"Python version 3.8 or older is not supported for `Truss-Chains`. Please"
"upgrade to Python 3.9 or newer. You can still use other Truss functionality."
)
del sys
import pydantic

pydantic_major_version = int(pydantic.VERSION.split(".")[0])
if pydantic_major_version < 2:
warnings.warn(
f"Pydantic major version is less than 2 ({pydantic.VERSION}). You use Truss, "
"but for using Truss-Chains, you must upgrade to pydantic-v2.",
UserWarning,
raise RuntimeError(
f"Pydantic v2 is not supported for `Truss-Chains`. Please upgrade to v2. "
"You can still use other Truss functionality."
)

del pydantic
del warnings


# flake8: noqa F401
from truss_chains.definitions import (
Expand Down
14 changes: 4 additions & 10 deletions truss/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,16 +112,10 @@ def image():

class ChainsGroup(click.Group):
def invoke(self, ctx: click.Context) -> None:
import pydantic

pydantic_major_version = int(pydantic.VERSION.split(".")[0])
if pydantic_major_version < 2:
raise ImportError(
f"Pydantic major version is less than 2 ({pydantic.VERSION}). "
"You can use Truss, but for using Truss-Chains, you must upgrade "
"to pydantic-v2.",
)
del pydantic
# This import raises error messages if pydantic v2 or python older than 3.9
# are installed.
import truss_chains # noqa: F401

super().invoke(ctx)


Expand Down
2 changes: 1 addition & 1 deletion truss/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
)
CONTROL_SERVER_CODE_DIR: pathlib.Path = TEMPLATES_DIR / "control"

SUPPORTED_PYTHON_VERSIONS = {"3.9", "3.10", "3.11"}
SUPPORTED_PYTHON_VERSIONS = {"3.8", "3.9", "3.10", "3.11"}


# Alias for TEMPLATES_DIR
Expand Down
9 changes: 5 additions & 4 deletions truss/model_inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def map_to_supported_python_version(python_version: str) -> str:
python_major_version = int(python_version[2:3])
python_minor_version = int(python_version[3:])

if python_major_version != 3:
if python_major_version > 3:
raise NotImplementedError("Only python version 3 is supported")

if python_minor_version > 11:
Expand All @@ -46,12 +46,13 @@ def map_to_supported_python_version(python_version: str) -> str:
)
return "py311"

if python_minor_version < 9:
if python_minor_version < 8:
# TODO: consider raising an error instead - it doesn't' seem safe.
logger.info(
f"Mapping python version {python_major_version}.{python_minor_version}"
" to 3.9, the lowest version that Truss currently supports."
" to 3.8, the lowest version that Truss currently supports."
)
return "py39"
return "py38"

return python_version

Expand Down
4 changes: 2 additions & 2 deletions truss/templates/base.Dockerfile.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ ENV PYTHON_EXECUTABLE {{ config.base_image.python_executable_path or 'python3' }

{% block fail_fast %}
RUN grep -w 'ID=debian\|ID_LIKE=debian' /etc/os-release || { echo "ERROR: Supplied base image is not a debian image"; exit 1; }
RUN $PYTHON_EXECUTABLE -c "import sys; sys.exit(0) if sys.version_info.major == 3 and sys.version_info.minor >=9 and sys.version_info.minor <=11 else sys.exit(1)" \
|| { echo "ERROR: Supplied base image does not have 3.9 <= python <= 3.11"; exit 1; }
RUN $PYTHON_EXECUTABLE -c "import sys; sys.exit(0) if sys.version_info.major == 3 and sys.version_info.minor >=8 and sys.version_info.minor <=11 else sys.exit(1)" \
|| { echo "ERROR: Supplied base image does not have 3.8 <= python <= 3.11"; exit 1; }
{% endblock %}

RUN pip install --upgrade pip --no-cache-dir \
Expand Down
2 changes: 1 addition & 1 deletion truss/templates/control/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
dataclasses-json==0.5.7
truss==0.9.12
truss==0.9.10 # This needs to support py3.8. It can be incremented to releases after #955 (i.e. >0.9.12).
fastapi==0.109.1
uvicorn==0.24.0
uvloop==0.19.0
Expand Down
4 changes: 2 additions & 2 deletions truss/test_data/server.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ FROM baseten/truss-server-base:3.9-v0.4.3 as truss_server
ENV PYTHON_EXECUTABLE /usr/local/bin/python3

RUN grep -w 'ID=debian\|ID_LIKE=debian' /etc/os-release || { echo "ERROR: Supplied base image is not a debian image"; exit 1; }
RUN $PYTHON_EXECUTABLE -c "import sys; sys.exit(0) if sys.version_info.major == 3 and sys.version_info.minor >=9 and sys.version_info.minor <=11 else sys.exit(1)" \
|| { echo "ERROR: Supplied base image does not have 3.9 <= python <= 3.11"; exit 1; }
RUN $PYTHON_EXECUTABLE -c "import sys; sys.exit(0) if sys.version_info.major == 3 and sys.version_info.minor >=8 and sys.version_info.minor <=11 else sys.exit(1)" \
|| { echo "ERROR: Supplied base image does not have 3.8 <= python <= 3.11"; exit 1; }

RUN pip install --upgrade pip --no-cache-dir \
&& rm -rf /root/.cache/pip
Expand Down
2 changes: 1 addition & 1 deletion truss/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ def custom_model_truss_dir_with_hidden_files(tmp_path):
_ = init(str(truss_dir_path))
(truss_dir_path / "__pycache__").mkdir(parents=True, exist_ok=True)
(truss_dir_path / ".git").mkdir(parents=True, exist_ok=True)
(truss_dir_path / "__pycache__" / "test.cpython-39.pyc").touch()
(truss_dir_path / "__pycache__" / "test.cpython-311.pyc").touch()
(truss_dir_path / ".DS_Store").touch()
(truss_dir_path / ".git" / ".test_file").touch()
(truss_dir_path / "data" / "test_file").write_text("123456789")
Expand Down
3 changes: 1 addition & 2 deletions truss/tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,10 +350,9 @@ def test_from_yaml_secrets_as_list():


def test_from_yaml_python_version():
yaml_path = Path("test.yaml")
invalid_py_version_data = {
"description": "this is a test",
"python_version": "py38",
"python_version": "py37",
}
with tempfile.NamedTemporaryFile(mode="w", delete=False) as yaml_file:
yaml_path = Path(yaml_file.name)
Expand Down
6 changes: 3 additions & 3 deletions truss/tests/test_model_inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@ def join(self, timeout=None):
@pytest.mark.parametrize(
"python_version, expected_python_version",
[
("py36", "py39"),
("py37", "py39"),
("py38", "py39"),
("py37", "py38"),
("py38", "py38"),
("py39", "py39"),
("py310", "py310"),
("py311", "py311"),
("py312", "py311"),
("py36", "py38"),
],
)
def test_map_to_supported_python_version(python_version, expected_python_version):
Expand Down
4 changes: 3 additions & 1 deletion truss/tests/test_truss_handle.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def test_build_docker_image(custom_model_truss_dir_with_pre_and_post):
"base_image, path, expected_fail",
[
("baseten/truss-server-base:3.9-v0.4.8rc4", "/usr/local/bin/python3", False),
("python:3.9", "/usr/local/bin/python3", False),
("python:3.8", "/usr/local/bin/python3", False),
("python:3.10", "/usr/local/bin/python3", False),
("python:3.11", "/usr/local/bin/python3", False),
("python:alpine", "/usr/local/bin/python3", True),
Expand Down Expand Up @@ -396,6 +396,8 @@ def test_enable_gpu(custom_model_truss_dir_with_pre_and_post):
@pytest.mark.parametrize(
"python_version, expected_python_version",
[
("3.8", "py38"),
("py38", "py38"),
("3.9", "py39"),
("py39", "py39"),
],
Expand Down
10 changes: 5 additions & 5 deletions truss/tests/util/test_path.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def test_copy_tree_path_with_hidden_files(custom_model_truss_dir_with_hidden_fil
with path.given_or_temporary_dir() as dir:
path.copy_tree_path(custom_model_truss_dir_with_hidden_files, dir)

assert not (dir / "__pycache__" / "test.cpython-39.pyc").exists()
assert not (dir / "__pycache__" / "test.cpython-311.pyc").exists()
assert not (dir / ".DS_Store").exists()
assert not (dir / ".git").exists()
assert (dir / "model").exists()
Expand All @@ -56,7 +56,7 @@ def test_is_ignored(custom_model_truss_dir_with_hidden_files):
assert path.is_ignored(
custom_model_truss_dir_with_hidden_files
/ "__pycache__"
/ "test.cpython-39.pyc",
/ "test.cpython-311.pyc",
patterns,
)

Expand Down Expand Up @@ -127,15 +127,15 @@ def test_ignored_files_in_docker_context(

assert dir.exists()

assert not (dir / "__pycache__" / "test.cpython-39.pyc").exists()
assert not (dir / "__pycache__" / "test.cpython-311.pyc").exists()
assert not (dir / ".DS_Store").exists()
assert not (dir / ".git").exists()
assert (dir / "model").exists()

assert (
custom_model_truss_dir_with_hidden_files
/ "__pycache__"
/ "test.cpython-39.pyc"
/ "test.cpython-311.pyc"
).exists()
assert (custom_model_truss_dir_with_hidden_files / ".DS_Store").exists()
assert (custom_model_truss_dir_with_hidden_files / ".git").exists()
Expand Down Expand Up @@ -220,7 +220,7 @@ def test_get_ignored_relative_paths_from_root(custom_model_truss_dir_with_hidden
)
ignored_relative_paths_strs = {
"__pycache__",
"__pycache__/test.cpython-39.pyc",
"__pycache__/test.cpython-311.pyc",
".DS_Store",
".git",
".git/.test_file",
Expand Down
6 changes: 4 additions & 2 deletions truss/truss_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

DEFAULT_BLOB_BACKEND = HTTP_PUBLIC_BLOB_BACKEND

VALID_PYTHON_VERSIONS = ["py39", "py310", "py311"]
VALID_PYTHON_VERSIONS = ["py38", "py39", "py310", "py311"]

# Set up logging
logging.basicConfig(level=logging.INFO)
Expand Down Expand Up @@ -502,8 +502,10 @@ class TrussConfig:
@property
def canonical_python_version(self) -> str:
return {
"py39": "3.9",
"py311": "3.11",
"py39": "3.9",
"py38": "3.8",
"py37": "3.7",
}[self.python_version]

@staticmethod
Expand Down
2 changes: 0 additions & 2 deletions truss/truss_handle.py
Original file line number Diff line number Diff line change
Expand Up @@ -703,8 +703,6 @@ def update_python_version(self, python_version: str):
self._update_config(
lambda conf: replace(
conf,
# TODO: should this be wrapped in
# `map_to_supported_python_version`?
python_version=inferred_python_version,
)
)
Expand Down

0 comments on commit a61b557

Please sign in to comment.