mirror of
https://github.com/gradio-app/gradio.git
synced 2025-03-31 12:20:26 +08:00
Add python-3.7 tests (#1818)
* Add python-3.7 tests * Format components * Use latest images * Use python instead of python3 * Force reset cache * Reset cache * Use Ipython 7 for python 3.7 support * Install chrome * Add two text files * Reset cache * Use Literal from typing extensions * Update cache key * Linting * Fix requests tests * Exit if running from wrong python version * Use one requirements file * Fix comment * Fix comment * Use python 3.7.13 * empty commit * Delete chrome driver to see if it works * Test no chrome with new cache * Remove chrome driver install entirely
This commit is contained in:
parent
4149d00822
commit
74d632eab5
@ -8,15 +8,17 @@ jobs:
|
||||
parameters:
|
||||
test-type:
|
||||
type: string
|
||||
python-version:
|
||||
type: string
|
||||
environment:
|
||||
NODE_OPTIONS: --max-old-space-size=4096
|
||||
docker:
|
||||
- image: circleci/python:3.9.2-browsers
|
||||
- image: cimg/python:<< parameters.python-version >>-browsers
|
||||
steps:
|
||||
- checkout
|
||||
- run: mkdir test-reports
|
||||
- restore_cache:
|
||||
key: deps1-{{ .Branch }}-{{ checksum "requirements.txt" }}
|
||||
key: deps4-{{ .Branch }}-{{ checksum "requirements.txt" }}-<< parameters.python-version >>
|
||||
- run:
|
||||
name: Install ffmpeg
|
||||
command: |
|
||||
@ -25,16 +27,12 @@ jobs:
|
||||
- run:
|
||||
name: Install Python deps in a venv
|
||||
command: |
|
||||
python3 -m venv venv
|
||||
python -m venv venv
|
||||
. venv/bin/activate
|
||||
bash scripts/install_gradio.sh
|
||||
bash scripts/install_test_requirements.sh
|
||||
- run:
|
||||
command: |
|
||||
chromedriver --version
|
||||
name: Check chrome driver install
|
||||
- save_cache:
|
||||
key: deps1-{{ .Branch }}-{{ checksum "requirements.txt" }}
|
||||
key: deps4-{{ .Branch }}-{{ checksum "requirements.txt" }}-<< parameters.python-version >>
|
||||
paths:
|
||||
- "venv"
|
||||
- node/install:
|
||||
@ -81,3 +79,4 @@ workflows:
|
||||
matrix:
|
||||
parameters:
|
||||
test-type: ["not flaky", "flaky"]
|
||||
python-version: ["3.9.2", "3.7.13"]
|
||||
|
@ -12,17 +12,19 @@ import operator
|
||||
import os
|
||||
import pathlib
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
import warnings
|
||||
from copy import deepcopy
|
||||
from types import ModuleType
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple
|
||||
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple
|
||||
|
||||
if sys.version_info[0] == 3 and sys.version_info[1] >= 8:
|
||||
if TYPE_CHECKING:
|
||||
from typing import TypedDict
|
||||
else:
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
class DataframeData(TypedDict):
|
||||
headers: List[str]
|
||||
data: List[List[str | int | bool]]
|
||||
|
||||
|
||||
import matplotlib.figure
|
||||
import numpy as np
|
||||
@ -2400,11 +2402,6 @@ class File(Changeable, Clearable, IOComponent):
|
||||
)
|
||||
|
||||
|
||||
class DataframeData(TypedDict):
|
||||
headers: List[str]
|
||||
data: List[List[str | int | bool]]
|
||||
|
||||
|
||||
@document()
|
||||
class Dataframe(Changeable, IOComponent):
|
||||
"""
|
||||
|
@ -18,5 +18,4 @@ uvicorn
|
||||
Jinja2
|
||||
fsspec
|
||||
httpx
|
||||
pydantic
|
||||
typing-extensions
|
||||
pydantic
|
@ -3,8 +3,8 @@ if [ -z "$(ls | grep CONTRIBUTING.md)" ]; then
|
||||
echo "Please run the script from repo directory"
|
||||
exit -1
|
||||
else
|
||||
echo "Creating requirements under test/requirements.txt using requirements.in. Please run this script from unix or wsl!"
|
||||
echo "Creating requirements under test/requirements.txt using requirements.in. Please run this script from unix or wsl in a python3.7 env!"
|
||||
cd test
|
||||
pip install --upgrade pip-tools
|
||||
pip-compile
|
||||
pip-compile --output-file requirements.txt
|
||||
fi
|
||||
|
@ -17,4 +17,5 @@ black
|
||||
isort
|
||||
flake8
|
||||
httpx
|
||||
pydantic
|
||||
pydantic
|
||||
respx
|
@ -1,76 +1,52 @@
|
||||
#
|
||||
# This file is autogenerated by pip-compile with python 3.9
|
||||
# This file is autogenerated by pip-compile with python 3.7
|
||||
# To update, run:
|
||||
#
|
||||
# pip-compile
|
||||
# pip-compile --output-file=requirements.txt
|
||||
#
|
||||
absl-py==1.0.0
|
||||
# via
|
||||
# tensorboard
|
||||
# tensorflow
|
||||
alembic==1.7.6
|
||||
alembic==1.8.1
|
||||
# via mlflow
|
||||
asttokens==2.0.5
|
||||
# via stack-data
|
||||
astunparse==1.6.3
|
||||
# via tensorflow
|
||||
anyio==3.6.1
|
||||
# via httpcore
|
||||
asyncio==3.4.3
|
||||
# via -r requirements.in
|
||||
atomicwrites==1.4.1
|
||||
# via pytest
|
||||
attrs==21.4.0
|
||||
# via
|
||||
# jsonschema
|
||||
# pytest
|
||||
backcall==0.2.0
|
||||
# via ipython
|
||||
black==22.1.0
|
||||
# via
|
||||
# -r requirements.in
|
||||
# ipython
|
||||
cachetools==5.0.0
|
||||
# via google-auth
|
||||
certifi==2021.10.8
|
||||
black==22.6.0
|
||||
# via -r requirements.in
|
||||
certifi==2022.6.15
|
||||
# via
|
||||
# dulwich
|
||||
# httpcore
|
||||
# httpx
|
||||
# requests
|
||||
# sentry-sdk
|
||||
# urllib3
|
||||
cffi==1.15.0
|
||||
# via cryptography
|
||||
charset-normalizer==2.0.11
|
||||
charset-normalizer==2.1.0
|
||||
# via requests
|
||||
click==8.0.3
|
||||
click==8.1.3
|
||||
# via
|
||||
# black
|
||||
# databricks-cli
|
||||
# flask
|
||||
# mlflow
|
||||
# sacremoses
|
||||
# wandb
|
||||
cloudpickle==2.0.0
|
||||
cloudpickle==2.1.0
|
||||
# via
|
||||
# mlflow
|
||||
# shap
|
||||
colorama==0.4.4
|
||||
# via
|
||||
# click
|
||||
# ipython
|
||||
# pytest
|
||||
# tqdm
|
||||
comet-ml==3.25.0
|
||||
comet-ml==3.31.6
|
||||
# via -r requirements.in
|
||||
configobj==5.0.6
|
||||
# via everett
|
||||
coverage[toml]==6.3.1
|
||||
coverage[toml]==6.4.2
|
||||
# via
|
||||
# -r requirements.in
|
||||
# pytest-cov
|
||||
cryptography==36.0.1
|
||||
# via
|
||||
# pyopenssl
|
||||
# urllib3
|
||||
databricks-cli==0.16.4
|
||||
databricks-cli==0.17.0
|
||||
# via mlflow
|
||||
decorator==5.1.1
|
||||
# via ipython
|
||||
@ -78,95 +54,90 @@ docker==5.0.3
|
||||
# via mlflow
|
||||
docker-pycreds==0.4.0
|
||||
# via wandb
|
||||
dulwich==0.20.32
|
||||
dulwich==0.20.45
|
||||
# via comet-ml
|
||||
entrypoints==0.4
|
||||
# via mlflow
|
||||
everett[ini]==3.0.0
|
||||
# via comet-ml
|
||||
executing==0.8.2
|
||||
# via stack-data
|
||||
filelock==3.4.2
|
||||
filelock==3.7.1
|
||||
# via
|
||||
# huggingface-hub
|
||||
# transformers
|
||||
flake8==4.0.1
|
||||
# via -r requirements.in
|
||||
flask==2.0.2
|
||||
flask==2.1.3
|
||||
# via
|
||||
# mlflow
|
||||
# prometheus-flask-exporter
|
||||
flatbuffers==2.0
|
||||
# via tensorflow
|
||||
gast==0.5.3
|
||||
# via tensorflow
|
||||
gitdb==4.0.9
|
||||
# via gitpython
|
||||
gitpython==3.1.26
|
||||
gitpython==3.1.27
|
||||
# via
|
||||
# mlflow
|
||||
# wandb
|
||||
google-auth==2.6.0
|
||||
# via
|
||||
# google-auth-oauthlib
|
||||
# tensorboard
|
||||
google-auth-oauthlib==0.4.6
|
||||
# via tensorboard
|
||||
google-pasta==0.2.0
|
||||
# via tensorflow
|
||||
greenlet==1.1.2
|
||||
# via sqlalchemy
|
||||
grpcio==1.43.0
|
||||
gunicorn==20.1.0
|
||||
# via mlflow
|
||||
h11==0.12.0
|
||||
# via httpcore
|
||||
httpcore==0.15.0
|
||||
# via httpx
|
||||
httpx==0.23.0
|
||||
# via
|
||||
# tensorboard
|
||||
# tensorflow
|
||||
h5py==3.6.0
|
||||
# via tensorflow
|
||||
huggingface-hub==0.4.0
|
||||
# -r requirements.in
|
||||
# respx
|
||||
huggingface-hub==0.8.1
|
||||
# via
|
||||
# -r requirements.in
|
||||
# transformers
|
||||
idna==3.3
|
||||
# via
|
||||
# anyio
|
||||
# requests
|
||||
# urllib3
|
||||
imageio==2.14.1
|
||||
# rfc3986
|
||||
imageio==2.19.5
|
||||
# via scikit-image
|
||||
importlib-metadata==4.10.1
|
||||
importlib-metadata==4.2.0
|
||||
# via
|
||||
# markdown
|
||||
# alembic
|
||||
# click
|
||||
# flake8
|
||||
# flask
|
||||
# huggingface-hub
|
||||
# jsonschema
|
||||
# mako
|
||||
# mlflow
|
||||
# pluggy
|
||||
# pytest
|
||||
# sqlalchemy
|
||||
# transformers
|
||||
importlib-resources==5.8.0
|
||||
# via
|
||||
# alembic
|
||||
# jsonschema
|
||||
iniconfig==1.1.1
|
||||
# via pytest
|
||||
ipython==8.0.1
|
||||
ipython==7.34.0
|
||||
# via -r requirements.in
|
||||
isort==5.10.1
|
||||
# via -r requirements.in
|
||||
itsdangerous==2.0.1
|
||||
itsdangerous==2.1.2
|
||||
# via flask
|
||||
jedi==0.18.1
|
||||
# via ipython
|
||||
jinja2==3.0.3
|
||||
jinja2==3.1.2
|
||||
# via flask
|
||||
joblib==1.1.0
|
||||
# via
|
||||
# sacremoses
|
||||
# scikit-learn
|
||||
jsonschema==4.4.0
|
||||
# via scikit-learn
|
||||
jsonschema==4.7.2
|
||||
# via comet-ml
|
||||
keras==2.8.0
|
||||
# via tensorflow
|
||||
keras-preprocessing==1.1.2
|
||||
# via tensorflow
|
||||
libclang==13.0.0
|
||||
# via tensorflow
|
||||
llvmlite==0.38.0
|
||||
llvmlite==0.38.1
|
||||
# via numba
|
||||
mako==1.1.6
|
||||
mako==1.2.1
|
||||
# via alembic
|
||||
markdown==3.3.6
|
||||
# via tensorboard
|
||||
markupsafe==2.0.1
|
||||
markupsafe==2.1.1
|
||||
# via
|
||||
# jinja2
|
||||
# mako
|
||||
@ -174,38 +145,31 @@ matplotlib-inline==0.1.3
|
||||
# via ipython
|
||||
mccabe==0.6.1
|
||||
# via flake8
|
||||
mlflow==1.23.1
|
||||
mlflow==1.27.0
|
||||
# via -r requirements.in
|
||||
mypy-extensions==0.4.3
|
||||
# via black
|
||||
networkx==2.6.3
|
||||
# via scikit-image
|
||||
numba==0.55.1
|
||||
numba==0.55.2
|
||||
# via shap
|
||||
numpy==1.21.5
|
||||
numpy==1.21.6
|
||||
# via
|
||||
# h5py
|
||||
# imageio
|
||||
# keras-preprocessing
|
||||
# mlflow
|
||||
# numba
|
||||
# opt-einsum
|
||||
# pandas
|
||||
# pywavelets
|
||||
# scikit-image
|
||||
# scikit-learn
|
||||
# scipy
|
||||
# shap
|
||||
# tensorboard
|
||||
# tensorflow
|
||||
# tifffile
|
||||
# transformers
|
||||
nvidia-ml-py3==7.352.0
|
||||
# via comet-ml
|
||||
oauthlib==3.2.0
|
||||
# via requests-oauthlib
|
||||
opt-einsum==3.3.0
|
||||
# via tensorflow
|
||||
# via databricks-cli
|
||||
packaging==21.3
|
||||
# via
|
||||
# huggingface-hub
|
||||
@ -214,7 +178,7 @@ packaging==21.3
|
||||
# scikit-image
|
||||
# shap
|
||||
# transformers
|
||||
pandas==1.4.0
|
||||
pandas==1.3.5
|
||||
# via
|
||||
# mlflow
|
||||
# shap
|
||||
@ -224,74 +188,66 @@ pathspec==0.9.0
|
||||
# via black
|
||||
pathtools==0.1.2
|
||||
# via wandb
|
||||
pexpect==4.8.0
|
||||
# via ipython
|
||||
pickleshare==0.7.5
|
||||
# via ipython
|
||||
pillow==9.0.1
|
||||
pillow==9.2.0
|
||||
# via
|
||||
# imageio
|
||||
# scikit-image
|
||||
platformdirs==2.4.1
|
||||
platformdirs==2.5.2
|
||||
# via black
|
||||
pluggy==1.0.0
|
||||
# via pytest
|
||||
prometheus-client==0.13.1
|
||||
prometheus-client==0.14.1
|
||||
# via prometheus-flask-exporter
|
||||
prometheus-flask-exporter==0.18.7
|
||||
prometheus-flask-exporter==0.20.2
|
||||
# via mlflow
|
||||
promise==2.3
|
||||
# via wandb
|
||||
prompt-toolkit==3.0.26
|
||||
prompt-toolkit==3.0.30
|
||||
# via ipython
|
||||
protobuf==3.19.4
|
||||
protobuf==3.20.1
|
||||
# via
|
||||
# mlflow
|
||||
# tensorboard
|
||||
# tensorflow
|
||||
# wandb
|
||||
psutil==5.9.0
|
||||
psutil==5.9.1
|
||||
# via wandb
|
||||
pure-eval==0.2.2
|
||||
# via stack-data
|
||||
ptyprocess==0.7.0
|
||||
# via pexpect
|
||||
py==1.11.0
|
||||
# via pytest
|
||||
pyasn1==0.4.8
|
||||
# via
|
||||
# pyasn1-modules
|
||||
# rsa
|
||||
pyasn1-modules==0.2.8
|
||||
# via google-auth
|
||||
pycodestyle==2.8.0
|
||||
# via flake8
|
||||
pycparser==2.21
|
||||
# via cffi
|
||||
pydantic==1.9.1
|
||||
# via -r requirements.in
|
||||
pyflakes==2.4.0
|
||||
# via flake8
|
||||
pygments==2.11.2
|
||||
pygments==2.12.0
|
||||
# via ipython
|
||||
pyopenssl==22.0.0
|
||||
# via urllib3
|
||||
pyparsing==3.0.7
|
||||
pyjwt==2.4.0
|
||||
# via databricks-cli
|
||||
pyparsing==3.0.9
|
||||
# via packaging
|
||||
pyrsistent==0.18.1
|
||||
# via jsonschema
|
||||
pytest==7.0.0
|
||||
pytest==7.1.2
|
||||
# via
|
||||
# -r requirements.in
|
||||
# pytest-asyncio
|
||||
# pytest-cov
|
||||
pytest-asyncio==0.18.3
|
||||
pytest-asyncio==0.19.0
|
||||
# via -r requirements.in
|
||||
pytest-cov==3.0.0
|
||||
# via -r requirements.in
|
||||
python-dateutil==2.8.2
|
||||
# via
|
||||
# pandas
|
||||
# wandb
|
||||
pytz==2021.3
|
||||
# via pandas
|
||||
pytz==2022.1
|
||||
# via
|
||||
# mlflow
|
||||
# pandas
|
||||
pywavelets==1.2.0
|
||||
pywavelets==1.3.0
|
||||
# via scikit-image
|
||||
pyyaml==6.0
|
||||
# via
|
||||
@ -301,164 +257,133 @@ pyyaml==6.0
|
||||
# wandb
|
||||
querystring-parser==1.2.4
|
||||
# via mlflow
|
||||
regex==2022.1.18
|
||||
# via
|
||||
# sacremoses
|
||||
# transformers
|
||||
requests==2.27.1
|
||||
regex==2022.7.9
|
||||
# via transformers
|
||||
requests==2.28.1
|
||||
# via
|
||||
# comet-ml
|
||||
# databricks-cli
|
||||
# docker
|
||||
# huggingface-hub
|
||||
# mlflow
|
||||
# requests-oauthlib
|
||||
# requests-toolbelt
|
||||
# tensorboard
|
||||
# transformers
|
||||
# wandb
|
||||
requests-oauthlib==1.3.1
|
||||
# via google-auth-oauthlib
|
||||
requests-toolbelt==0.9.1
|
||||
# via comet-ml
|
||||
rsa==4.8
|
||||
# via google-auth
|
||||
sacremoses==0.0.47
|
||||
# via transformers
|
||||
scikit-image==0.19.1
|
||||
respx==0.19.2
|
||||
# via -r requirements.in
|
||||
rfc3986[idna2008]==1.5.0
|
||||
# via httpx
|
||||
scikit-image==0.19.3
|
||||
# via -r requirements.in
|
||||
scikit-learn==1.0.2
|
||||
# via shap
|
||||
scipy==1.8.0
|
||||
scipy==1.7.3
|
||||
# via
|
||||
# mlflow
|
||||
# scikit-image
|
||||
# scikit-learn
|
||||
# shap
|
||||
selenium==4.0.0a6.post2
|
||||
# via -r requirements.in
|
||||
semantic-version==2.9.0
|
||||
semantic-version==2.10.0
|
||||
# via comet-ml
|
||||
sentry-sdk==1.5.4
|
||||
sentry-sdk==1.7.2
|
||||
# via
|
||||
# comet-ml
|
||||
# wandb
|
||||
setproctitle==1.2.3
|
||||
# via wandb
|
||||
shap==0.40.0
|
||||
shap==0.41.0
|
||||
# via -r requirements.in
|
||||
shortuuid==1.0.8
|
||||
shortuuid==1.0.9
|
||||
# via wandb
|
||||
six==1.16.0
|
||||
# via
|
||||
# absl-py
|
||||
# asttokens
|
||||
# astunparse
|
||||
# comet-ml
|
||||
# configobj
|
||||
# databricks-cli
|
||||
# docker-pycreds
|
||||
# google-auth
|
||||
# google-pasta
|
||||
# grpcio
|
||||
# keras-preprocessing
|
||||
# promise
|
||||
# python-dateutil
|
||||
# querystring-parser
|
||||
# sacremoses
|
||||
# tensorflow
|
||||
# wandb
|
||||
slicer==0.0.7
|
||||
# via shap
|
||||
smmap==5.0.0
|
||||
# via gitdb
|
||||
sqlalchemy==1.4.31
|
||||
sniffio==1.2.0
|
||||
# via
|
||||
# anyio
|
||||
# httpcore
|
||||
# httpx
|
||||
sqlalchemy==1.4.39
|
||||
# via
|
||||
# alembic
|
||||
# mlflow
|
||||
sqlparse==0.4.2
|
||||
# via mlflow
|
||||
stack-data==0.1.4
|
||||
# via ipython
|
||||
tabulate==0.8.9
|
||||
tabulate==0.8.10
|
||||
# via databricks-cli
|
||||
tensorboard==2.8.0
|
||||
# via tensorflow
|
||||
tensorboard-data-server==0.6.1
|
||||
# via tensorboard
|
||||
tensorboard-plugin-wit==1.8.1
|
||||
# via tensorboard
|
||||
tensorflow==2.8.0
|
||||
# via -r requirements.in
|
||||
tensorflow-io-gcs-filesystem==0.24.0
|
||||
# via tensorflow
|
||||
termcolor==1.1.0
|
||||
# via
|
||||
# tensorflow
|
||||
# yaspin
|
||||
tf-estimator-nightly==2.8.0.dev2021122109
|
||||
# via tensorflow
|
||||
threadpoolctl==3.1.0
|
||||
# via scikit-learn
|
||||
tifffile==2022.2.2
|
||||
tifffile==2021.11.2
|
||||
# via scikit-image
|
||||
tokenizers==0.11.4
|
||||
tokenizers==0.12.1
|
||||
# via transformers
|
||||
tomli==2.0.0
|
||||
tomli==2.0.1
|
||||
# via
|
||||
# black
|
||||
# coverage
|
||||
# pytest
|
||||
torch==1.10.2
|
||||
torch==1.12.0
|
||||
# via -r requirements.in
|
||||
tqdm==4.62.3
|
||||
tqdm==4.64.0
|
||||
# via
|
||||
# huggingface-hub
|
||||
# sacremoses
|
||||
# shap
|
||||
# transformers
|
||||
traitlets==5.1.1
|
||||
traitlets==5.3.0
|
||||
# via
|
||||
# ipython
|
||||
# matplotlib-inline
|
||||
transformers==4.16.2
|
||||
transformers==4.20.1
|
||||
# via -r requirements.in
|
||||
typing-extensions==4.0.1
|
||||
typed-ast==1.5.4
|
||||
# via black
|
||||
typing-extensions==4.3.0
|
||||
# via
|
||||
# anyio
|
||||
# black
|
||||
# gitpython
|
||||
# huggingface-hub
|
||||
# tensorflow
|
||||
# importlib-metadata
|
||||
# jsonschema
|
||||
# pydantic
|
||||
# pytest-asyncio
|
||||
# torch
|
||||
urllib3[secure]==1.26.8
|
||||
urllib3==1.26.10
|
||||
# via
|
||||
# dulwich
|
||||
# requests
|
||||
# selenium
|
||||
# sentry-sdk
|
||||
waitress==2.1.1
|
||||
# via mlflow
|
||||
wandb==0.12.10
|
||||
wandb==0.12.21
|
||||
# via -r requirements.in
|
||||
wcwidth==0.2.5
|
||||
# via prompt-toolkit
|
||||
websocket-client==1.2.3
|
||||
websocket-client==1.3.3
|
||||
# via
|
||||
# comet-ml
|
||||
# docker
|
||||
werkzeug==2.0.2
|
||||
# via
|
||||
# flask
|
||||
# tensorboard
|
||||
wheel==0.37.1
|
||||
# via
|
||||
# astunparse
|
||||
# tensorboard
|
||||
wrapt==1.13.3
|
||||
# via
|
||||
# comet-ml
|
||||
# tensorflow
|
||||
werkzeug==2.1.2
|
||||
# via flask
|
||||
wrapt==1.14.1
|
||||
# via comet-ml
|
||||
wurlitzer==3.0.2
|
||||
# via comet-ml
|
||||
yaspin==2.1.0
|
||||
# via wandb
|
||||
zipp==3.7.0
|
||||
# via importlib-metadata
|
||||
zipp==3.8.1
|
||||
# via
|
||||
# importlib-metadata
|
||||
# importlib-resources
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
# setuptools
|
||||
|
@ -1,9 +1,16 @@
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import pytest
|
||||
|
||||
import gradio as gr
|
||||
|
||||
|
||||
class TestDocumentatino(unittest.TestCase):
|
||||
class TestDocumentation(unittest.TestCase):
|
||||
@pytest.mark.skipif(
|
||||
sys.version_info < (3, 8),
|
||||
reason="Docs use features in inspect module not available in py 3.7",
|
||||
)
|
||||
def test_documentation(self):
|
||||
documentation = gr.documentation.generate_documentation()
|
||||
assert len(documentation) > 0
|
||||
|
@ -3,13 +3,13 @@ import os
|
||||
import unittest
|
||||
import unittest.mock as mock
|
||||
import warnings
|
||||
from typing import Literal
|
||||
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
import requests
|
||||
from httpx import AsyncClient
|
||||
from httpx import AsyncClient, Response
|
||||
from pydantic import BaseModel
|
||||
from typing_extensions import Literal
|
||||
|
||||
from gradio.test_data.blocks_configs import (
|
||||
XRAY_CONFIG,
|
||||
@ -259,143 +259,155 @@ async def client():
|
||||
|
||||
|
||||
def make_mock_response(return_value):
|
||||
response = mock.MagicMock(name="mock_response")
|
||||
response.status_code = 201
|
||||
response.json.return_value = return_value
|
||||
return response
|
||||
return Response(201, json=return_value)
|
||||
|
||||
|
||||
@mock.patch("gradio.utils.client.send")
|
||||
class TestRequest:
|
||||
@pytest.mark.asyncio
|
||||
async def test_get(self, mock_send):
|
||||
MOCK_REQUEST_URL = "https://very_real_url.com"
|
||||
|
||||
mock_send.return_value = make_mock_response({"Host": "headers.jsontest.com"})
|
||||
|
||||
client_response: Request = await Request(
|
||||
method=Request.Method.GET,
|
||||
url="very_real_url.com",
|
||||
)
|
||||
validated_data = client_response.get_validated_data()
|
||||
assert client_response.is_valid() is True
|
||||
assert validated_data["Host"] == "headers.jsontest.com"
|
||||
@pytest.mark.asyncio
|
||||
async def test_get(respx_mock):
|
||||
respx_mock.get(MOCK_REQUEST_URL).mock(
|
||||
make_mock_response({"Host": "headers.jsontest.com"})
|
||||
)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_post(self, mock_send):
|
||||
client_response: Request = await Request(
|
||||
method=Request.Method.GET,
|
||||
url=MOCK_REQUEST_URL,
|
||||
)
|
||||
validated_data = client_response.get_validated_data()
|
||||
assert client_response.is_valid() is True
|
||||
assert validated_data["Host"] == "headers.jsontest.com"
|
||||
|
||||
payload = {"name": "morpheus", "job": "leader"}
|
||||
mock_send.return_value = make_mock_response(payload)
|
||||
|
||||
client_response: Request = await Request(
|
||||
method=Request.Method.POST,
|
||||
url="very_real_url.com",
|
||||
json=payload,
|
||||
)
|
||||
validated_data = client_response.get_validated_data()
|
||||
assert client_response.status == 201
|
||||
assert validated_data["job"] == "leader"
|
||||
assert validated_data["name"] == "morpheus"
|
||||
@pytest.mark.asyncio
|
||||
async def test_post(respx_mock):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_validate_with_model(self, mock_send):
|
||||
mock_send.return_value = make_mock_response(
|
||||
{
|
||||
"name": "morpheus",
|
||||
"id": "1",
|
||||
"job": "leader",
|
||||
"createdAt": "2",
|
||||
}
|
||||
)
|
||||
payload = {"name": "morpheus", "job": "leader"}
|
||||
respx_mock.post(MOCK_REQUEST_URL).mock(make_mock_response(payload))
|
||||
|
||||
class TestModel(BaseModel):
|
||||
name: str
|
||||
job: str
|
||||
id: str
|
||||
createdAt: str
|
||||
client_response: Request = await Request(
|
||||
method=Request.Method.POST,
|
||||
url=MOCK_REQUEST_URL,
|
||||
json=payload,
|
||||
)
|
||||
validated_data = client_response.get_validated_data()
|
||||
assert client_response.status == 201
|
||||
assert validated_data["job"] == "leader"
|
||||
assert validated_data["name"] == "morpheus"
|
||||
|
||||
client_response: Request = await Request(
|
||||
method=Request.Method.POST,
|
||||
url="very_real_url.com",
|
||||
json={"name": "morpheus", "job": "leader"},
|
||||
validation_model=TestModel,
|
||||
)
|
||||
assert isinstance(client_response.get_validated_data(), TestModel)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_validate_and_fail_with_model(self, mock_send):
|
||||
class TestModel(BaseModel):
|
||||
name: Literal[str] = "John"
|
||||
job: str
|
||||
@pytest.mark.asyncio
|
||||
async def test_validate_with_model(respx_mock):
|
||||
|
||||
payload = {"name": "morpheus", "job": "leader"}
|
||||
mock_send.return_value = make_mock_response(payload)
|
||||
response = make_mock_response(
|
||||
{
|
||||
"name": "morpheus",
|
||||
"id": "1",
|
||||
"job": "leader",
|
||||
"createdAt": "2",
|
||||
}
|
||||
)
|
||||
respx_mock.post(MOCK_REQUEST_URL).mock(response)
|
||||
|
||||
client_response: Request = await Request(
|
||||
method=Request.Method.POST,
|
||||
url="very_real_url.com",
|
||||
json=payload,
|
||||
validation_model=TestModel,
|
||||
)
|
||||
with pytest.raises(Exception):
|
||||
client_response.is_valid(raise_exceptions=True)
|
||||
assert client_response.has_exception is True
|
||||
assert isinstance(client_response.exception, Exception)
|
||||
class TestModel(BaseModel):
|
||||
name: str
|
||||
job: str
|
||||
id: str
|
||||
createdAt: str
|
||||
|
||||
@mock.patch("gradio.utils.Request._validate_response_data")
|
||||
@pytest.mark.asyncio
|
||||
async def test_exception_type(self, validate_response_data, mock_send):
|
||||
class ResponseValidationException(Exception):
|
||||
message = "Response object is not valid."
|
||||
client_response: Request = await Request(
|
||||
method=Request.Method.POST,
|
||||
url=MOCK_REQUEST_URL,
|
||||
json={"name": "morpheus", "job": "leader"},
|
||||
validation_model=TestModel,
|
||||
)
|
||||
assert isinstance(client_response.get_validated_data(), TestModel)
|
||||
|
||||
validate_response_data.side_effect = Exception()
|
||||
|
||||
client_response: Request = await Request(
|
||||
method=Request.Method.GET,
|
||||
url="very_real_url.com",
|
||||
exception_type=ResponseValidationException,
|
||||
)
|
||||
assert isinstance(client_response.exception, ResponseValidationException)
|
||||
@pytest.mark.asyncio
|
||||
async def test_validate_and_fail_with_model(respx_mock):
|
||||
class TestModel(BaseModel):
|
||||
name: Literal[str] = "John"
|
||||
job: str
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_validate_with_function(self, mock_send):
|
||||
mock_send.return_value = make_mock_response({"name": "morpheus", "id": 1})
|
||||
payload = {"name": "morpheus", "job": "leader"}
|
||||
respx_mock.post(MOCK_REQUEST_URL).mock(make_mock_response(payload))
|
||||
|
||||
def has_name(response):
|
||||
if response["name"] is not None:
|
||||
client_response: Request = await Request(
|
||||
method=Request.Method.POST,
|
||||
url=MOCK_REQUEST_URL,
|
||||
json=payload,
|
||||
validation_model=TestModel,
|
||||
)
|
||||
with pytest.raises(Exception):
|
||||
client_response.is_valid(raise_exceptions=True)
|
||||
assert client_response.has_exception is True
|
||||
assert isinstance(client_response.exception, Exception)
|
||||
|
||||
|
||||
@mock.patch("gradio.utils.Request._validate_response_data")
|
||||
@pytest.mark.asyncio
|
||||
async def test_exception_type(validate_response_data, respx_mock):
|
||||
class ResponseValidationException(Exception):
|
||||
message = "Response object is not valid."
|
||||
|
||||
validate_response_data.side_effect = Exception()
|
||||
|
||||
respx_mock.get(MOCK_REQUEST_URL).mock(Response(201))
|
||||
|
||||
client_response: Request = await Request(
|
||||
method=Request.Method.GET,
|
||||
url=MOCK_REQUEST_URL,
|
||||
exception_type=ResponseValidationException,
|
||||
)
|
||||
assert isinstance(client_response.exception, ResponseValidationException)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_validate_with_function(respx_mock):
|
||||
|
||||
respx_mock.post(MOCK_REQUEST_URL).mock(
|
||||
make_mock_response({"name": "morpheus", "id": 1})
|
||||
)
|
||||
|
||||
def has_name(response):
|
||||
if response["name"] is not None:
|
||||
return response
|
||||
raise Exception
|
||||
|
||||
client_response: Request = await Request(
|
||||
method=Request.Method.POST,
|
||||
url=MOCK_REQUEST_URL,
|
||||
json={"name": "morpheus", "job": "leader"},
|
||||
validation_function=has_name,
|
||||
)
|
||||
validated_data = client_response.get_validated_data()
|
||||
assert client_response.is_valid() is True
|
||||
assert validated_data["id"] is not None
|
||||
assert client_response.exception is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_validate_and_fail_with_function(respx_mock):
|
||||
def has_name(response):
|
||||
if response["name"] is not None:
|
||||
if response["name"] == "Alex":
|
||||
return response
|
||||
raise Exception
|
||||
raise Exception
|
||||
|
||||
client_response: Request = await Request(
|
||||
method=Request.Method.POST,
|
||||
url="very_real_url.com",
|
||||
json={"name": "morpheus", "job": "leader"},
|
||||
validation_function=has_name,
|
||||
)
|
||||
validated_data = client_response.get_validated_data()
|
||||
assert client_response.is_valid() is True
|
||||
assert validated_data["id"] is not None
|
||||
assert client_response.exception is None
|
||||
respx_mock.post(MOCK_REQUEST_URL).mock(make_mock_response({"name": "morpheus"}))
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_validate_and_fail_with_function(self, mock_send):
|
||||
def has_name(response):
|
||||
if response["name"] is not None:
|
||||
if response["name"] == "Alex":
|
||||
return response
|
||||
raise Exception
|
||||
|
||||
mock_send.return_value = make_mock_response({"name": "morpheus"})
|
||||
|
||||
client_response: Request = await Request(
|
||||
method=Request.Method.POST,
|
||||
url="very_real_url.com",
|
||||
json={"name": "morpheus", "job": "leader"},
|
||||
validation_function=has_name,
|
||||
)
|
||||
assert client_response.is_valid() is False
|
||||
with pytest.raises(Exception):
|
||||
client_response.is_valid(raise_exceptions=True)
|
||||
assert client_response.exception is not None
|
||||
client_response: Request = await Request(
|
||||
method=Request.Method.POST,
|
||||
url=MOCK_REQUEST_URL,
|
||||
json={"name": "morpheus", "job": "leader"},
|
||||
validation_function=has_name,
|
||||
)
|
||||
assert client_response.is_valid() is False
|
||||
with pytest.raises(Exception):
|
||||
client_response.is_valid(raise_exceptions=True)
|
||||
assert client_response.exception is not None
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
Loading…
x
Reference in New Issue
Block a user