diff --git a/Makefile b/Makefile index 0eac7e03a2..9263c2772a 100644 --- a/Makefile +++ b/Makefile @@ -317,17 +317,11 @@ test-python-universal: FEAST_USAGE=False IS_TEST=True python -m pytest -n 8 --integration sdk/python/tests format-python: - # Sort - cd ${ROOT_DIR}/sdk/python; python -m isort feast/ tests/ - - # Format - cd ${ROOT_DIR}/sdk/python; python -m black --target-version py38 feast tests + cd ${ROOT_DIR}/sdk/python; python -m ruff check --fix feast/ tests/ lint-python: cd ${ROOT_DIR}/sdk/python; python -m mypy feast - cd ${ROOT_DIR}/sdk/python; python -m isort feast/ tests/ --check-only - cd ${ROOT_DIR}/sdk/python; python -m flake8 feast/ tests/ - cd ${ROOT_DIR}/sdk/python; python -m black --check feast tests + cd ${ROOT_DIR}/sdk/python; python -m ruff check feast/ tests/ # Java diff --git a/docs/project/development-guide.md b/docs/project/development-guide.md index 43dae1d678..28baa789bb 100644 --- a/docs/project/development-guide.md +++ b/docs/project/development-guide.md @@ -168,8 +168,8 @@ docker build -t docker-whale -f ./sdk/python/feast/infra/feature_servers/multicl Feast Python SDK / CLI codebase: - Conforms to [Black code style](https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html) - Has type annotations as enforced by `mypy` -- Has imports sorted by `isort` -- Is lintable by `flake8` +- Has imports sorted by `ruff` (see [isort (I) rules](https://docs.astral.sh/ruff/rules/#isort-i)) +- Is lintable by `ruff` To ensure your Python code conforms to Feast Python code standards: - Autoformat your code to conform to the code style: diff --git a/sdk/python/feast/__init__.py b/sdk/python/feast/__init__.py index 3eff91d65f..f51eb2983c 100644 --- a/sdk/python/feast/__init__.py +++ b/sdk/python/feast/__init__.py @@ -2,7 +2,8 @@ from importlib.metadata import PackageNotFoundError from importlib.metadata import version as _version except ModuleNotFoundError: - from importlib_metadata import PackageNotFoundError, version as _version # type: ignore + from importlib_metadata import PackageNotFoundError # type: ignore + from importlib_metadata import version as _version from feast.infra.offline_stores.bigquery_source import BigQuerySource from feast.infra.offline_stores.contrib.athena_offline_store.athena_source import ( diff --git a/sdk/python/feast/infra/materialization/contrib/bytewax/bytewax_materialization_dataflow.py b/sdk/python/feast/infra/materialization/contrib/bytewax/bytewax_materialization_dataflow.py index 6fc53b67f2..cd11abc2d0 100644 --- a/sdk/python/feast/infra/materialization/contrib/bytewax/bytewax_materialization_dataflow.py +++ b/sdk/python/feast/infra/materialization/contrib/bytewax/bytewax_materialization_dataflow.py @@ -4,11 +4,11 @@ import pyarrow as pa import pyarrow.parquet as pq + from bytewax.dataflow import Dataflow # type: ignore from bytewax.execution import cluster_main from bytewax.inputs import ManualInputConfig from bytewax.outputs import ManualOutputConfig - from feast import FeatureStore, FeatureView, RepoConfig from feast.utils import _convert_arrow_to_proto, _run_pyarrow_field_mapping diff --git a/sdk/python/feast/infra/materialization/contrib/bytewax/bytewax_materialization_engine.py b/sdk/python/feast/infra/materialization/contrib/bytewax/bytewax_materialization_engine.py index 060a47ce58..41b2442769 100644 --- a/sdk/python/feast/infra/materialization/contrib/bytewax/bytewax_materialization_engine.py +++ b/sdk/python/feast/infra/materialization/contrib/bytewax/bytewax_materialization_engine.py @@ -5,9 +5,8 @@ from typing import Callable, List, Literal, Sequence, Union import yaml -from kubernetes import client +from kubernetes import client, utils from kubernetes import config as k8s_config -from kubernetes import utils from kubernetes.client.exceptions import ApiException from kubernetes.utils import FailToCreateError from pydantic import StrictStr diff --git a/sdk/python/feast/infra/materialization/contrib/spark/spark_materialization_engine.py b/sdk/python/feast/infra/materialization/contrib/spark/spark_materialization_engine.py index 798d3a8e6f..c2e44a99c4 100644 --- a/sdk/python/feast/infra/materialization/contrib/spark/spark_materialization_engine.py +++ b/sdk/python/feast/infra/materialization/contrib/spark/spark_materialization_engine.py @@ -3,7 +3,6 @@ from typing import Callable, List, Literal, Optional, Sequence, Union, cast import dill -import pandas import pandas as pd import pyarrow from tqdm import tqdm diff --git a/sdk/python/pyproject.toml b/sdk/python/pyproject.toml new file mode 100644 index 0000000000..10ad007fa9 --- /dev/null +++ b/sdk/python/pyproject.toml @@ -0,0 +1,15 @@ +[tool.ruff] +exclude = [".git","__pycache__","docs/conf.py","dist","feast/protos","feast/embedded_go/lib","feast/infra/utils/snowflake/snowpark/snowflake_udfs.py"] + +[tool.ruff.lint] +select = ["E","F","W","I"] +ignore = ["E203", "E266", "E501", "E721"] + +[tool.ruff.lint.isort] +known-first-party = ["feast", "feast", "feast_serving_server", "feast_core_server"] +default-section = "third-party" + +[tool.mypy] +files = ["feast","tests"] +ignore_missing_imports = true +exclude = ["feast/embedded_go/lib"] diff --git a/sdk/python/requirements/py3.10-ci-requirements.txt b/sdk/python/requirements/py3.10-ci-requirements.txt index 8f0ef90d77..30b5369f16 100644 --- a/sdk/python/requirements/py3.10-ci-requirements.txt +++ b/sdk/python/requirements/py3.10-ci-requirements.txt @@ -18,6 +18,8 @@ anyio==4.3.0 # watchfiles appdirs==1.4.4 # via fissix +appnope==0.1.4 + # via ipykernel argon2-cffi==23.1.0 # via jupyter-server argon2-cffi-bindings==21.2.0 @@ -57,8 +59,6 @@ beautifulsoup4==4.12.3 # via nbconvert bidict==0.23.1 # via ibis-framework -black==22.12.0 - # via feast (setup.py) bleach==6.1.0 # via nbconvert boto3==1.34.65 @@ -105,7 +105,6 @@ charset-normalizer==3.3.2 # snowflake-connector-python click==8.1.7 # via - # black # bowler # dask # feast (setup.py) @@ -187,8 +186,6 @@ firebase-admin==5.4.0 # via feast (setup.py) fissix==21.11.13 # via bowler -flake8==6.0.0 - # via feast (setup.py) fqdn==1.5.1 # via jsonschema fsspec==2023.12.2 @@ -348,8 +345,6 @@ isodate==0.6.1 # via azure-storage-blob isoduration==20.11.0 # via jsonschema -isort==5.13.2 - # via feast (setup.py) jedi==0.19.1 # via ipython jinja2==3.1.3 @@ -441,8 +436,6 @@ matplotlib-inline==0.1.6 # via # ipykernel # ipython -mccabe==0.7.0 - # via flake8 mdurl==0.1.2 # via markdown-it-py minio==7.1.0 @@ -476,9 +469,7 @@ mypy==1.9.0 # feast (setup.py) # sqlalchemy mypy-extensions==1.0.0 - # via - # black - # mypy + # via mypy mypy-protobuf==3.3.0 # via feast (setup.py) nbclient==0.10.0 @@ -553,8 +544,6 @@ parsy==2.1 # via ibis-framework partd==1.4.1 # via dask -pathspec==0.12.1 - # via black pbr==6.0.0 # via mock pexpect==4.9.0 @@ -563,7 +552,6 @@ pip-tools==7.4.1 # via feast (setup.py) platformdirs==3.11.0 # via - # black # jupyter-core # snowflake-connector-python # virtualenv @@ -640,8 +628,6 @@ pyasn1-modules==0.3.0 # via google-auth pybindgen==0.22.1 # via feast (setup.py) -pycodestyle==2.10.0 - # via flake8 pycparser==2.21 # via cffi pydantic==2.6.4 @@ -651,8 +637,6 @@ pydantic==2.6.4 # great-expectations pydantic-core==2.16.3 # via pydantic -pyflakes==3.0.1 - # via flake8 pygments==2.17.2 # via # feast (setup.py) @@ -797,6 +781,8 @@ rsa==4.9 # via google-auth ruamel-yaml==0.17.17 # via great-expectations +ruff==0.3.4 + # via feast (setup.py) s3transfer==0.10.1 # via boto3 scipy==1.12.0 @@ -874,7 +860,6 @@ toml==0.10.2 # via feast (setup.py) tomli==2.0.1 # via - # black # build # coverage # jupyterlab diff --git a/sdk/python/requirements/py3.8-ci-requirements.txt b/sdk/python/requirements/py3.8-ci-requirements.txt index 3d3dbe764b..cf34faa5f0 100644 --- a/sdk/python/requirements/py3.8-ci-requirements.txt +++ b/sdk/python/requirements/py3.8-ci-requirements.txt @@ -18,6 +18,10 @@ anyio==4.3.0 # watchfiles appdirs==1.4.4 # via fissix +appnope==0.1.4 + # via + # ipykernel + # ipython argon2-cffi==23.1.0 # via jupyter-server argon2-cffi-bindings==21.2.0 @@ -41,8 +45,6 @@ attrs==23.2.0 # bowler # jsonschema # referencing -avro==1.11.3 - # via feast (setup.py) azure-core==1.30.1 # via # azure-identity @@ -63,8 +65,6 @@ backports-zoneinfo==0.2.1 # tzlocal beautifulsoup4==4.12.3 # via nbconvert -black==22.12.0 - # via feast (setup.py) bleach==6.1.0 # via nbconvert boto3==1.34.60 @@ -111,7 +111,6 @@ charset-normalizer==3.3.2 # snowflake-connector-python click==8.1.7 # via - # black # bowler # dask # feast (setup.py) @@ -192,8 +191,6 @@ firebase-admin==5.4.0 # via feast (setup.py) fissix==21.11.13 # via bowler -flake8==6.0.0 - # via feast (setup.py) fqdn==1.5.1 # via jsonschema fsspec==2023.12.2 @@ -365,8 +362,6 @@ isodate==0.6.1 # via azure-storage-blob isoduration==20.11.0 # via jsonschema -isort==5.13.2 - # via feast (setup.py) jedi==0.19.1 # via ipython jinja2==3.1.3 @@ -458,8 +453,6 @@ matplotlib-inline==0.1.6 # via # ipykernel # ipython -mccabe==0.7.0 - # via flake8 mdurl==0.1.2 # via markdown-it-py minio==7.1.0 @@ -493,9 +486,7 @@ mypy==1.9.0 # feast (setup.py) # sqlalchemy mypy-extensions==1.0.0 - # via - # black - # mypy + # via mypy mypy-protobuf==3.3.0 # via feast (setup.py) nbclient==0.9.1 @@ -553,7 +544,7 @@ packaging==24.0 # pytest # snowflake-connector-python # sphinx -pandas==1.5.3 ; python_version < "3.9" +pandas==1.5.3 # via # altair # db-dtypes @@ -570,8 +561,6 @@ parsy==2.1 # via ibis-framework partd==1.4.1 # via dask -pathspec==0.12.1 - # via black pbr==6.0.0 # via mock pexpect==4.9.0 @@ -584,7 +573,6 @@ pkgutil-resolve-name==1.3.10 # via jsonschema platformdirs==3.11.0 # via - # black # jupyter-core # snowflake-connector-python # virtualenv @@ -602,7 +590,6 @@ prompt-toolkit==3.0.43 # via ipython proto-plus==1.23.0 # via - # feast (setup.py) # google-cloud-bigquery # google-cloud-bigquery-storage # google-cloud-bigtable @@ -659,8 +646,6 @@ pyasn1-modules==0.3.0 # via google-auth pybindgen==0.22.1 # via feast (setup.py) -pycodestyle==2.10.0 - # via flake8 pycparser==2.21 # via cffi pydantic==2.6.4 @@ -670,8 +655,6 @@ pydantic==2.6.4 # great-expectations pydantic-core==2.16.3 # via pydantic -pyflakes==3.0.1 - # via flake8 pygments==2.17.2 # via # feast (setup.py) @@ -819,6 +802,8 @@ ruamel-yaml==0.17.17 # via great-expectations ruamel-yaml-clib==0.2.8 # via ruamel-yaml +ruff==0.3.4 + # via feast (setup.py) s3transfer==0.10.0 # via boto3 scipy==1.10.1 @@ -866,7 +851,9 @@ sphinxcontrib-qthelp==1.0.3 sphinxcontrib-serializinghtml==1.1.5 # via sphinx sqlalchemy[mypy]==1.4.52 - # via feast (setup.py) + # via + # feast (setup.py) + # sqlalchemy sqlalchemy2-stubs==0.0.2a38 # via sqlalchemy sqlglot==10.6.4 @@ -893,7 +880,6 @@ toml==0.10.2 # via feast (setup.py) tomli==2.0.1 # via - # black # build # coverage # jupyterlab @@ -973,7 +959,6 @@ typing-extensions==4.10.0 # async-lru # azure-core # azure-storage-blob - # black # fastapi # great-expectations # ibis-framework diff --git a/sdk/python/requirements/py3.9-ci-requirements.txt b/sdk/python/requirements/py3.9-ci-requirements.txt index dc96554431..8e50cb11c5 100644 --- a/sdk/python/requirements/py3.9-ci-requirements.txt +++ b/sdk/python/requirements/py3.9-ci-requirements.txt @@ -18,6 +18,8 @@ anyio==4.3.0 # watchfiles appdirs==1.4.4 # via fissix +appnope==0.1.4 + # via ipykernel argon2-cffi==23.1.0 # via jupyter-server argon2-cffi-bindings==21.2.0 @@ -57,8 +59,6 @@ beautifulsoup4==4.12.3 # via nbconvert bidict==0.23.1 # via ibis-framework -black==22.12.0 - # via feast (setup.py) bleach==6.1.0 # via nbconvert boto3==1.34.65 @@ -105,7 +105,6 @@ charset-normalizer==3.3.2 # snowflake-connector-python click==8.1.7 # via - # black # bowler # dask # feast (setup.py) @@ -187,8 +186,6 @@ firebase-admin==5.4.0 # via feast (setup.py) fissix==21.11.13 # via bowler -flake8==6.0.0 - # via feast (setup.py) fqdn==1.5.1 # via jsonschema fsspec==2023.12.2 @@ -356,8 +353,6 @@ isodate==0.6.1 # via azure-storage-blob isoduration==20.11.0 # via jsonschema -isort==5.13.2 - # via feast (setup.py) jedi==0.19.1 # via ipython jinja2==3.1.3 @@ -449,8 +444,6 @@ matplotlib-inline==0.1.6 # via # ipykernel # ipython -mccabe==0.7.0 - # via flake8 mdurl==0.1.2 # via markdown-it-py minio==7.1.0 @@ -484,9 +477,7 @@ mypy==1.9.0 # feast (setup.py) # sqlalchemy mypy-extensions==1.0.0 - # via - # black - # mypy + # via mypy mypy-protobuf==3.3.0 # via feast (setup.py) nbclient==0.10.0 @@ -561,8 +552,6 @@ parsy==2.1 # via ibis-framework partd==1.4.1 # via dask -pathspec==0.12.1 - # via black pbr==6.0.0 # via mock pexpect==4.9.0 @@ -571,7 +560,6 @@ pip-tools==7.4.1 # via feast (setup.py) platformdirs==3.11.0 # via - # black # jupyter-core # snowflake-connector-python # virtualenv @@ -648,8 +636,6 @@ pyasn1-modules==0.3.0 # via google-auth pybindgen==0.22.1 # via feast (setup.py) -pycodestyle==2.10.0 - # via flake8 pycparser==2.21 # via cffi pydantic==2.6.4 @@ -659,8 +645,6 @@ pydantic==2.6.4 # great-expectations pydantic-core==2.16.3 # via pydantic -pyflakes==3.0.1 - # via flake8 pygments==2.17.2 # via # feast (setup.py) @@ -807,6 +791,8 @@ ruamel-yaml==0.17.17 # via great-expectations ruamel-yaml-clib==0.2.8 # via ruamel-yaml +ruff==0.3.3 + # via feast (setup.py) s3transfer==0.10.1 # via boto3 scipy==1.12.0 @@ -884,7 +870,6 @@ toml==0.10.2 # via feast (setup.py) tomli==2.0.1 # via - # black # build # coverage # jupyterlab @@ -963,7 +948,6 @@ typing-extensions==4.10.0 # async-lru # azure-core # azure-storage-blob - # black # fastapi # great-expectations # ibis-framework diff --git a/sdk/python/setup.cfg b/sdk/python/setup.cfg deleted file mode 100644 index d934249d69..0000000000 --- a/sdk/python/setup.cfg +++ /dev/null @@ -1,22 +0,0 @@ -[isort] -src_paths = feast,tests -multi_line_output=3 -include_trailing_comma=True -force_grid_wrap=0 -use_parentheses=True -line_length=88 -skip=feast/protos,feast/embedded_go/lib -known_first_party=feast,feast_serving_server,feast_core_server -default_section=THIRDPARTY - -[flake8] -ignore = E203, E266, E501, W503, C901 -max-line-length = 88 -max-complexity = 20 -select = B,C,E,F,W,T4 -exclude = .git,__pycache__,docs/conf.py,dist,feast/protos,feast/embedded_go/lib,feast/infra/utils/snowflake/snowpark/snowflake_udfs.py - -[mypy] -files=feast,tests -ignore_missing_imports=true -exclude=feast/embedded_go/lib diff --git a/setup.cfg b/setup.cfg index 2781169a71..2a9acf13da 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,25 +1,2 @@ -[isort] -src_paths = feast,tests -multi_line_output=3 -include_trailing_comma=True -force_grid_wrap=0 -use_parentheses=True -line_length=88 -skip=feast/protos,feast/embedded_go/lib -known_first_party=feast,feast_serving_server,feast_core_server -default_section=THIRDPARTY - -[flake8] -ignore = E203, E266, E501, W503 -max-line-length = 88 -max-complexity = 20 -select = B,C,E,F,W,T4 -exclude = .git,__pycache__,docs/conf.py,dist,feast/protos,feast/embedded_go/lib - -[mypy] -files=feast,tests -ignore_missing_imports=true -exclude=feast/embedded_go/lib - [bdist_wheel] universal = 1 diff --git a/setup.py b/setup.py index b32d03ed77..158a181ecd 100644 --- a/setup.py +++ b/setup.py @@ -156,9 +156,7 @@ "build", "virtualenv==20.23.0", "cryptography>=35.0,<43", - "flake8>=6.0.0,<6.1.0", - "black>=22.6.0,<23", - "isort>=5,<6", + "ruff>=0.3.3", "grpcio-testing>=1.56.2,<2", # FastAPI does not correctly pull starlette dependency on httpx see thread(https://github.com/tiangolo/fastapi/issues/5656). "httpx>=0.23.3",