From 33e7004e6662c00c9edf82c669f350163d6bf8f2 Mon Sep 17 00:00:00 2001 From: Aaron <29749331+aarnphm@users.noreply.github.com> Date: Tue, 30 May 2023 14:56:11 -0700 Subject: [PATCH] format: consistent CLI outputs vendorred type-related module from bentoml._internal.types Signed-off-by: Aaron <29749331+aarnphm@users.noreply.github.com> --- src/openllm/_configuration.py | 3 +-- src/openllm/cli.py | 12 ++++++++++-- src/openllm/utils/__init__.py | 26 +++++++++++++++++++++++++- src/openllm/utils/dantic.py | 20 +++++++++----------- 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/src/openllm/_configuration.py b/src/openllm/_configuration.py index 892358f2..3d5b9cec 100644 --- a/src/openllm/_configuration.py +++ b/src/openllm/_configuration.py @@ -48,13 +48,12 @@ import click import inflection import orjson from bentoml._internal.models.model import ModelSignature -from bentoml._internal.types import lenient_issubclass from click_option_group import optgroup import openllm from .exceptions import GpuNotAvailableError, OpenLLMException -from .utils import LazyType, ModelEnv, bentoml_cattr, dantic +from .utils import LazyType, ModelEnv, bentoml_cattr, dantic, lenient_issubclass if t.TYPE_CHECKING: import tensorflow as tf diff --git a/src/openllm/cli.py b/src/openllm/cli.py index 5a5cd153..ca19125a 100644 --- a/src/openllm/cli.py +++ b/src/openllm/cli.py @@ -638,7 +638,11 @@ def create_cli() -> click.Group: click.secho(f"Saved model: {m.tag}") elif output == "json": m = model.ensure_pretrained_exists() - click.secho(orjson.dumps({"previously_setup": False, "framework": env, "tag": str(m.tag)}).decode()) + click.secho( + orjson.dumps( + {"previously_setup": False, "framework": env, "tag": str(m.tag)}, option=orjson.OPT_INDENT_2 + ).decode() + ) else: m = model.ensure_pretrained_exists() click.secho(m.tag) @@ -647,7 +651,11 @@ def create_cli() -> click.Group: if output == "pretty": click.secho(f"{model_name} is already setup for framework '{env}': {str(m.tag)}", nl=True) elif output == "json": - click.secho(orjson.dumps({"previously_setup": True, "framework": env, "model": str(m.tag)}).decode()) + click.secho( + orjson.dumps( + {"previously_setup": True, "framework": env, "model": str(m.tag)}, option=orjson.OPT_INDENT_2 + ).decode() + ) else: click.echo(m.tag) return m diff --git a/src/openllm/utils/__init__.py b/src/openllm/utils/__init__.py index 3c4b0de3..e7484e29 100644 --- a/src/openllm/utils/__init__.py +++ b/src/openllm/utils/__init__.py @@ -22,6 +22,7 @@ import importlib.machinery import itertools import logging import os +import sys import types import typing as t @@ -29,7 +30,6 @@ import attrs import inflection from bentoml._internal.types import LazyType as LazyType from bentoml._internal.types import get_origin as get_origin -from bentoml._internal.types import lenient_issubclass as lenient_issubclass # NOTE: The following exports useful utils from bentoml from bentoml._internal.utils import LazyLoader as LazyLoader @@ -53,6 +53,30 @@ from .import_utils import require_backends as require_backends logger = logging.getLogger(__name__) +try: + from typing import GenericAlias as TypingGenericAlias # type: ignore +except ImportError: + # python < 3.9 does not have GenericAlias (list[int], tuple[str, ...] and so on) + TypingGenericAlias = () + +if sys.version_info < (3, 10): + WithArgsTypes = (TypingGenericAlias,) +else: + WithArgsTypes: t.Any = ( + t._GenericAlias, # type: ignore (_GenericAlias is the actual GenericAlias implementation) + types.GenericAlias, + types.UnionType, + ) + + +def lenient_issubclass(cls: t.Any, class_or_tuple: type[t.Any] | tuple[type[t.Any], ...] | None) -> bool: + try: + return isinstance(cls, type) and issubclass(cls, class_or_tuple) # type: ignore[arg-type] + except TypeError: + if isinstance(cls, WithArgsTypes): + return False + raise + @attrs.define class ModelEnv: diff --git a/src/openllm/utils/dantic.py b/src/openllm/utils/dantic.py index 7d2e3b25..d34597b9 100644 --- a/src/openllm/utils/dantic.py +++ b/src/openllm/utils/dantic.py @@ -22,13 +22,11 @@ import click import orjson from click import ParamType -from . import LazyType, get_origin +import openllm if t.TYPE_CHECKING: from attr import _ValidatorType # type: ignore -from bentoml._internal.types import lenient_issubclass - _T = t.TypeVar("_T") @@ -116,13 +114,13 @@ def is_mapping(field_type: type) -> bool: bool: true when the field is a dict-like object, false otherwise. """ # Early out for standard containers. - if lenient_issubclass(field_type, t.Mapping): + if openllm.utils.lenient_issubclass(field_type, t.Mapping): return True # for everything else or when the typing is more complex, check its origin - origin = get_origin(field_type) + origin = openllm.utils.get_origin(field_type) if origin is None: return False - return lenient_issubclass(origin, t.Mapping) + return openllm.utils.lenient_issubclass(origin, t.Mapping) def is_container(field_type: type) -> bool: @@ -139,13 +137,13 @@ def is_container(field_type: type) -> bool: if field_type in (str, bytes): return False # Early out for standard containers: list, tuple, range - if lenient_issubclass(field_type, t.Container): + if openllm.utils.lenient_issubclass(field_type, t.Container): return True - origin = get_origin(field_type) + origin = openllm.utils.get_origin(field_type) # Early out for non-typing objects if origin is None: return False - return lenient_issubclass(origin, t.Container) + return openllm.utils.lenient_issubclass(origin, t.Container) def parse_container_args(field_type: type) -> ParamType | tuple[ParamType]: @@ -191,7 +189,7 @@ def parse_single_arg(arg: type) -> ParamType: # For containers and nested models, we use JSON if is_container(arg): return JsonType() - if lenient_issubclass(arg, bytes): + if openllm.utils.lenient_issubclass(arg, bytes): return BytesType() return arg @@ -216,7 +214,7 @@ class JsonType(ParamType): self.should_load = should_load def convert(self, value: t.Any, param: click.Parameter | None, ctx: click.Context | None) -> t.Any: - if LazyType[t.Mapping[str, str]](t.Mapping).isinstance(value) or not self.should_load: + if openllm.utils.LazyType[t.Mapping[str, str]](t.Mapping).isinstance(value) or not self.should_load: return value try: return orjson.loads(value)