Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow python 3.8 for context builder but not CLI, (partial revert of #921) #955

Merged
merged 1 commit into from
May 30, 2024
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
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
Loading