Add max deps and bump old ones
All checks were successful
Publish documentation / publish (push) Successful in 51s
Check / Test on Python 3.10 (push) Successful in 1m1s
Check / Lint, format & type checks (push) Successful in 1m9s
Check / Test on Python 3.11 (push) Successful in 51s
Check / Test on Python 3.12 (push) Successful in 58s
Check / Test on Python 3.13 (push) Successful in 55s

This commit is contained in:
Andras Schmelczer 2026-06-06 22:29:16 +01:00
parent 2403a20ed0
commit c55eba2077
18 changed files with 98 additions and 75 deletions

View file

@ -6,6 +6,7 @@ from typing import (
Callable,
Generic,
List,
Literal,
Optional,
Sequence,
Tuple,
@ -17,7 +18,6 @@ from typing import (
from fastapi import FastAPI
from tqdm import tqdm
from typing_extensions import Literal # <= Python 3.7
from ..constants import DASHBOARD_PATH
from ..context import get_context

View file

@ -1,7 +1,7 @@
from pathlib import Path
from a2wsgi import WSGIMiddleware
from fastapi import FastAPI
from fastapi.middleware.wsgi import WSGIMiddleware
from fastapi.responses import FileResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
@ -19,7 +19,10 @@ def bootstrap_dashboard(app: FastAPI, function_name: str, documentation: str) ->
def get_favicon() -> FileResponse:
return FileResponse(PATH / "dashboard/assets/favicon.ico")
app.mount(DASHBOARD_PATH, WSGIMiddleware(dash_app))
# a2wsgi types its WSGI input (Flask) and ASGI output more strictly than
# Starlette's loose WSGIApp/ASGIApp aliases, so mypy flags the mount despite
# this being the canonical, runtime-correct way to bridge the Dash app.
app.mount(DASHBOARD_PATH, WSGIMiddleware(dash_app)) # type: ignore[arg-type]
@app.get("/", include_in_schema=False)
def redirect_to_entrypoint() -> RedirectResponse:

View file

@ -16,7 +16,8 @@ def get_description(
style={"color": accent_color},
),
dcc.Markdown(
strip_lines(f"""
strip_lines(
f"""
> View the live data of your deployment here.
## Using the API
@ -26,7 +27,8 @@ def get_description(
## Details
{function_docs}
"""),
"""
),
className="description",
),
]

View file

@ -7,9 +7,7 @@ from abc import ABC, abstractmethod
from functools import lru_cache
from pathlib import Path
from types import TracebackType
from typing import IO, Any, List, Optional, Type, Union, cast
from typing_extensions import Literal # <= Python 3.7
from typing import IO, Any, List, Literal, Optional, Type, Union, cast
from great_ai.utilities import ConfigFile, get_logger

View file

@ -1,8 +1,19 @@
from functools import wraps
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, TypeVar, Union, cast
from typing import (
Any,
Callable,
Dict,
List,
Literal,
Optional,
Set,
Tuple,
TypeVar,
Union,
cast,
)
from dill import load
from typing_extensions import Literal # <= Python 3.7
from ..context import get_context
from ..helper import get_function_metadata_store

View file

@ -1,4 +1,4 @@
from datetime import datetime
from datetime import datetime, timezone
from math import ceil
from random import shuffle
from typing import Any, Iterable, List, TypeVar, Union, cast
@ -94,7 +94,7 @@ def add_ground_truth(
)
shuffle(split_tags)
created = datetime.utcnow().isoformat()
created = datetime.now(timezone.utc).replace(tzinfo=None).isoformat()
traces = [
cast(
Trace[T],

View file

@ -1,12 +1,10 @@
from contextvars import ContextVar
from datetime import datetime
from datetime import datetime, timezone
from time import perf_counter
from types import TracebackType
from typing import Any, Dict, Generic, List, Optional, Type, TypeVar, cast
from typing import Any, Dict, Generic, List, Literal, Optional, Type, TypeVar, cast
from uuid import uuid4
from typing_extensions import Literal # <= Python 3.7
from ..constants import DEVELOPMENT_TAG_NAME, ONLINE_TAG_NAME, PRODUCTION_TAG_NAME
from ..context import get_context
from ..views import Model, Trace
@ -25,7 +23,7 @@ class TracingContext(Generic[T]):
self._models: List[Model] = []
self._values: Dict[str, Any] = {}
self._trace: Optional[Trace[T]] = None
self._start_datetime = datetime.utcnow()
self._start_datetime = datetime.now(timezone.utc).replace(tzinfo=None)
self._start_time = perf_counter()
self._name = function_name

View file

@ -94,9 +94,11 @@ class ConfigFile(Mapping[str, str]):
try:
value = next(v for v in values if v)
except StopIteration:
raise ParseError(f"""Cannot parse config file ({
raise ParseError(
f"""Cannot parse config file ({
self._path.absolute()
}), error at key `{key}`""")
}), error at key `{key}`"""
)
already_exists = key in self._key_values
if already_exists and not value.startswith(

View file

@ -39,9 +39,11 @@ def manage_communication(
is_iteration_over = True
except Exception as e:
if ignore_exceptions:
logger.error(f"""Exception {e} encountered in input, traceback:\n{
logger.error(
f"""Exception {e} encountered in input, traceback:\n{
traceback.format_exc()
}""")
}"""
)
else:
raise

View file

@ -3,6 +3,7 @@ from typing import (
Awaitable,
Callable,
Iterable,
Literal,
Optional,
Sequence,
TypeVar,
@ -11,7 +12,6 @@ from typing import (
)
import dill
from typing_extensions import Literal # <= Python 3.7
from .get_config import get_config
from .manage_communication import manage_communication

View file

@ -4,6 +4,7 @@ from typing import (
Awaitable,
Callable,
Iterable,
Literal,
Optional,
Sequence,
TypeVar,
@ -11,8 +12,6 @@ from typing import (
overload,
)
from typing_extensions import Literal # <= Python 3.7
from .get_config import get_config
from .manage_communication import manage_communication
from .mapper_function import mapper_function

View file

@ -1,6 +1,4 @@
from typing import List
from typing_extensions import Literal # <= Python 3.7
from typing import List, Literal
Operator = Literal[">=", "<=", "<", ">", "!=", "=", "contains"]

View file

@ -1,6 +1,4 @@
from typing import Any, List, Optional
from typing_extensions import Literal # <= Python 3.7
from typing import Any, List, Literal, Optional
from ..hashable_base_model import HashableBaseModel

View file

@ -1,5 +1,6 @@
from typing import Literal
from pydantic import BaseModel
from typing_extensions import Literal # <= Python 3.7
class SortBy(BaseModel):

View file

@ -9,7 +9,7 @@ from .model import Model
T = TypeVar("T")
class Trace(Generic[T], HashableBaseModel):
class Trace(HashableBaseModel, Generic[T]):
"""Universal structure for storing prediction traces and training data.
Attributes:

View file

@ -21,49 +21,51 @@ classifiers = [
"Natural Language :: English",
]
keywords = ["SE4ML", "MLOps", "AI engineering", "general", "robust", "end-to-end", "automated", "trustworthy", "ai", "deployment"]
requires-python = ">= 3.7"
requires-python = ">= 3.10"
dependencies = [
"scikit-learn",
"matplotlib",
"numpy",
"nbconvert",
"ipython",
"unidecode >= 1.3.0",
"syntok >= 1.4.0",
"langcodes[data] >= 3.3.0",
"langdetect >= 1.0.9",
"tinydb >= 4.7.0",
"boto3 >= 1.23.0",
"plotly >= 5.8.0",
"pandas",
"dash >= 2.4.0",
"fastapi >= 0.70.0",
"uvicorn[standard] >= 0.18.0",
"watchdog >= 2.1.0",
"typeguard >= 2.10.0",
"pymongo >= 4.0.0",
"dill >= 0.3.5.0",
"tqdm",
"httpx >= 0.20.0",
"scikit-learn >= 1.3, < 2",
"matplotlib >= 3.7, < 4",
"numpy >= 1.24, < 3",
"nbconvert >= 7.0, < 8",
"ipython >= 8.0, < 10",
"unidecode >= 1.3.0, < 2",
"syntok >= 1.4.0, < 2",
"langcodes[data] >= 3.3.0, < 4",
"langdetect >= 1.0.9, < 2",
"tinydb >= 4.7.0, < 5",
"boto3 >= 1.34, < 2",
"plotly >= 5.20, < 7",
"pandas >= 2.0, < 4",
"dash >= 2.16, < 5",
"fastapi >= 0.110, < 1",
"uvicorn[standard] >= 0.27, < 1",
"a2wsgi >= 1.9, < 2",
"watchdog >= 3.0, < 7",
"typeguard >= 4.0, < 5",
"pydantic >= 2.5, < 3",
"pymongo >= 4.6, < 5",
"dill >= 0.3.6, < 1",
"tqdm >= 4.64, < 5",
"httpx >= 0.24, < 1",
]
[project.optional-dependencies]
dev = [
"flit",
"mkdocs",
"mkdocstrings[python]",
"mkdocs-material",
"mkdocs-jupyter",
"mkdocs-git-revision-date-localized-plugin",
"autoflake",
"isort",
"black[jupyter]",
"mypy",
"flake8",
"tox",
"pytest",
"pytest-cov",
"pytest-asyncio",
"flit >= 3.9, < 4",
"mkdocs >= 1.5, < 2",
"mkdocstrings[python] >= 0.24, < 1",
"mkdocs-material >= 9.5, < 10",
"mkdocs-jupyter >= 0.24, < 1",
"mkdocs-git-revision-date-localized-plugin >= 1.2, < 2",
"autoflake >= 2.0, < 3",
"isort >= 5.12, < 7",
"black[jupyter] >= 25.1, < 26",
"mypy >= 1.8, < 2",
"flake8 >= 7.0, < 8",
"tox >= 4.0, < 5",
"pytest >= 7.4, < 9",
"pytest-cov >= 4.1, < 8",
"pytest-asyncio >= 0.23, < 2",
]
[tool.pytest.ini_options]

View file

@ -3,7 +3,7 @@
set -e
echo "Installing dependencies if necessary"
python3 -m pip install --upgrade autoflake isort black[jupyter] mypy flake8
python3 -m pip install autoflake isort black[jupyter] mypy flake8
for dir in "$@"; do
echo "Checking $dir"
@ -19,7 +19,7 @@ for dir in "$@"; do
python3 -m mypy --namespace-packages --ignore-missing-imports --install-types --non-interactive --disallow-untyped-defs --disallow-incomplete-defs --follow-imports=silent --exclude=external/ --exclude=/build/ --exclude='(^|/)__main__\.py$' --pretty .
fi
python3 -m flake8 . --count --show-source --statistics --exclude=__init__.py,.env,external --ignore=E501,E402,F821,W503,E722,E203,E704
python3 -m flake8 . --count --show-source --statistics --exclude=__init__.py,.env,external --extend-ignore=E501,E402,F821,W503,E722,E203,E704
cd -
done

View file

@ -14,11 +14,14 @@ def test_simple() -> None:
assert c.first_key == "András"
assert c.second_key == "test 2"
assert c.third_key == "test= 2=="
assert c.fourth_key == """
assert (
c.fourth_key
== """
this#
is
multiline
"""
)
assert c.whitespace == "hardly matters"
with pytest.raises(KeyError):
c.this
@ -31,11 +34,14 @@ def test_simple_dict() -> None:
assert c["my_hashtag"] == "#great_ai"
assert c["second_key"] == "test 2"
assert c["third_key"] == "test= 2=="
assert c["fourth_key"] == """
assert (
c["fourth_key"]
== """
this#
is
multiline
"""
)
assert c["whitespace"] == "hardly matters"
with pytest.raises(KeyError):
c["#this"]
@ -49,11 +55,14 @@ def test_string_path() -> None:
assert c.second_key == "test 2"
assert c.third_key == "test= 2=="
assert c.fourth_key == """
assert (
c.fourth_key
== """
this#
is
multiline
"""
)
assert c.whitespace == "hardly matters"