diff --git a/Makefile b/Makefile index e277295e84c..2ba7443fcd6 100644 --- a/Makefile +++ b/Makefile @@ -813,13 +813,12 @@ build-helm-docs: ## Build helm docs # Note: these require node and yarn to be installed build-ui: ## Build Feast UI - cd $(ROOT_DIR)/sdk/python/feast/ui && yarn upgrade @feast-dev/feast-ui --latest && yarn install && npm run build --omit=dev - -build-ui-local: ## Build Feast UI locally cd $(ROOT_DIR)/ui && yarn install && npm run build --omit=dev rm -rf $(ROOT_DIR)/sdk/python/feast/ui/build cp -r $(ROOT_DIR)/ui/build $(ROOT_DIR)/sdk/python/feast/ui/ +build-ui-local: build-ui ## Build Feast UI locally + format-ui: ## Format Feast UI cd $(ROOT_DIR)/ui && NPM_TOKEN= yarn install && NPM_TOKEN= yarn format diff --git a/infra/feast-operator/bundle/manifests/openlineage-secret_v1_secret.yaml b/infra/feast-operator/bundle/manifests/openlineage-secret_v1_secret.yaml index 40483cc0c43..85d09af493c 100644 --- a/infra/feast-operator/bundle/manifests/openlineage-secret_v1_secret.yaml +++ b/infra/feast-operator/bundle/manifests/openlineage-secret_v1_secret.yaml @@ -3,4 +3,4 @@ kind: Secret metadata: name: openlineage-secret stringData: - api_key: your-marquez-api-key + api_key: your-marquez-api-key # pragma: allowlist secret diff --git a/pyproject.toml b/pyproject.toml index 25bef64ccfa..9797cdc2dff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,6 +39,9 @@ dependencies = [ "starlette>=1.0.1", "uvicorn[standard]>=0.30.6,<=0.34.0", "uvicorn-worker", + "grpcio>=1.56.2", + "grpcio-reflection>=1.56.2", + "grpcio-health-checking>=1.56.2", "gunicorn; platform_system != 'Windows'", "dask[dataframe]>=2024.2.1", "prometheus_client>=0.20.0,<0.25.0", diff --git a/sdk/python/feast/api/registry/rest/rest_registry_server.py b/sdk/python/feast/api/registry/rest/rest_registry_server.py index 02454b263ff..d440c74d7ed 100644 --- a/sdk/python/feast/api/registry/rest/rest_registry_server.py +++ b/sdk/python/feast/api/registry/rest/rest_registry_server.py @@ -78,7 +78,7 @@ def __init__(self, store: FeatureStore): registry_cfg = getattr(store.config, "registry", None) mcp_cfg = getattr(registry_cfg, "mcp", None) - if mcp_cfg and getattr(mcp_cfg, "enabled", False): + if mcp_cfg and getattr(mcp_cfg, "enabled", False) is True: try: from fastapi_mcp import FastApiMCP diff --git a/sdk/python/requirements/py3.10-requirements.txt b/sdk/python/requirements/py3.10-requirements.txt index ec690d1ee5d..06d003e62a1 100644 --- a/sdk/python/requirements/py3.10-requirements.txt +++ b/sdk/python/requirements/py3.10-requirements.txt @@ -229,6 +229,70 @@ fsspec==2026.4.0 \ --hash=sha256:11ef7bb35dab8a394fde6e608221d5cf3e8499401c249bebaeaad760a1a8dec2 \ --hash=sha256:301d8ac70ae90ef3ad05dcf94d6c3754a097f9b5fe4667d2787aa359ec7df7e4 # via dask +grpcio==1.81.1 \ + --hash=sha256:0490c30c261eded63f3f354979f9dc4502a9fb944cccb60cd9dc85f5a7349854 \ + --hash=sha256:0a37165cc80b1a368384b383e63a4c38116a10467ae44c904d2d7468c4470ec2 \ + --hash=sha256:12b7524c88d4026d3dcb7b0ebe16b6714f3b4af402ddd0f0639ab064a00c87c3 \ + --hash=sha256:15641444eca4a29358107b3dceb74c1c6305c55c822fd199b458aaea4068a7fb \ + --hash=sha256:1b22c80559854b789a01fd89e8929b3798a156c0829b5282a8939f33ad4115ad \ + --hash=sha256:1e123f9b37edb8375fd74130d1f69c944bbf0a7b06761ae7211154b8759e94d2 \ + --hash=sha256:24c8e57504c8f45b237e40b99262d181071e5099a07053695b75d97bb53053a0 \ + --hash=sha256:2c2e2ae6867c2966b8daccc836d54a13218e0007e9a490aeb81dd05be64d22d7 \ + --hash=sha256:30e825f6848d9f18bba350ed6c75c1b02a0b5184474a31db9a32b1fa66fd8c79 \ + --hash=sha256:3768a5ff1b2125e6f552e561b6b2dca0e64982d8949689b4df145cf8b98d7821 \ + --hash=sha256:3ad74f8bb1a18963914c5452d289422830b39459e8776ebbcd207be1fbfb1d94 \ + --hash=sha256:410482da976329fe5f4067270401b12cf2bd552ff8020f054ecfaddb5475f9d6 \ + --hash=sha256:428bec0161b48d8cf583c068591bc0016d0d9cfff52462b72b3884861ea768c5 \ + --hash=sha256:506f48f2f9c29b143fca3dad7b0d518c188b6c9648c75a2ae6e2d9f2c13a060b \ + --hash=sha256:58ad1131c300d3c9b933802b3cc4dc69d380822935ba50b28703156ea826fbf7 \ + --hash=sha256:592b5fee597faa91cce2dd294dd7d9a1c83d76c4dbf877e33ec1adb866b2fbed \ + --hash=sha256:61233fe8951e5c85dff81c2458b6528624760166946b5b47ea150a589168411f \ + --hash=sha256:62481553b1793a27e9b9c3cf9e5bd483ef045ca72462592074b46d42b0c4d9b9 \ + --hash=sha256:6282caffb41ec326d4cb67ca9cf53b739d1b2f975a2acb498c7418e9f7d9a416 \ + --hash=sha256:69ef28e54fc85397f91b8c19592b8ef3d81952080366914823bd8572a2958120 \ + --hash=sha256:6f9a0c9c1cc15c112d1c053064fd032b64917062292c3d70aea280e02ae10b77 \ + --hash=sha256:6fa10a767143a5e82e8eaab53918af0cd8909a57a27f8cb2288b80a613ac671b \ + --hash=sha256:766bc7c9a9c340342f4c864ccbda8e78111e4751f13b895812b9c148fb79e9d0 \ + --hash=sha256:78e29211f26da2fdd0e9c6d2b79f489476140cf7029b6a64808ade7ca4156a42 \ + --hash=sha256:819edbdcb42ab8598b494bcf0222684bbb7a3c772bd1b1f0be7e029a6063c28e \ + --hash=sha256:85b10a45b8993d195c4f3ff57025b8d1e11834909ee475c403bfa60cb4caefaf \ + --hash=sha256:88268ca418cacea64cecb0d1d600d3c6b3a8038fcba02e1e205178c5b1f47661 \ + --hash=sha256:8b39472beafc0bdcafc4c8c73ad082ebfdb449d566897a61e7acb4fa88089115 \ + --hash=sha256:8ea1936c26b99999b27479853039a7f34713f56c49375ad52b38535ec93a796c \ + --hash=sha256:98a07f9bf591e3a8919797bee1c53f026ba4acd587e5a4404c8e57c9ec36b2a5 \ + --hash=sha256:a185a04039df6cae8648bc8ab6d6fde7bf94f7188ecf7828e76ac52eef1e41d6 \ + --hash=sha256:a35009284d0d3d5c2c9601c164a911b8b4331608d98a9a66d47d97bb2f522b70 \ + --hash=sha256:a3acb384427816dd5d470f47e62137b87f74da694faa8a50147012cf40df276a \ + --hash=sha256:aa2ba7d2ad6df4d80127cea65e5b8d5e2c3adbf153ff4804452836328aca7c54 \ + --hash=sha256:b10e1ff4756ed27d5a29d7fc79cfce7ef1ff56ad20025b89bac7cf79e09abbbe \ + --hash=sha256:b137f4bf3ada9dc44d411478decc6ff09a79ed30b306cd2abaa98408c3588137 \ + --hash=sha256:b259a04a737cb3496be0901328eb8b7552ed8df4865d8c8f1cf1bffcfc0776a3 \ + --hash=sha256:b427c19380991a4eaab2f6144b64b99b412043314c6bf4ab544f97bb31ee4190 \ + --hash=sha256:bb693b1e3d9a2f3fd228e2110daf4b5aeedb36761ca1e4282f74725f6d89f611 \ + --hash=sha256:c261d74b1a945cf895a9d6eccd1685a8e837531beaab782da4d630a8d12deffb \ + --hash=sha256:c5bf2dc311127d91230cc79b92188c082634a06cf66c5234db49a43b910183b0 \ + --hash=sha256:ca1cc11d82677b9662082e5478b7528e2b7db7beaa6bdff42bd62789d81be399 \ + --hash=sha256:d4b2dddfc219f54f956ccd53cf76a1d338ffe68fc7f2849ec9c7feb9927ff692 \ + --hash=sha256:d71d30f2d92f67d944631c523713934fee37292469e182ebcd2c1dd8a64ce53f \ + --hash=sha256:d865db4a6318e1c1bea83292e0ed231090538fc4ca45425b0f0480eb338bbc6e \ + --hash=sha256:e2aa72e3ce1770317ef534f63d397b55e130725f5149bd36077c3b539019db27 \ + --hash=sha256:e3657301562ac3cb8018d30d0d3ebfa39932239f7b5703422057ef14b69949f5 \ + --hash=sha256:e64dd101d380a115cc5a0c7856788adb535f1a4e21fc543775602f8be95180ae \ + --hash=sha256:e8ca6a1fcdb2943c9cbc1804a1baf3acb6071d72a471591678ded84218006e14 \ + --hash=sha256:edb59506291b647a30884b1d51a599d605f40b20af4a7dc3d33786a47a31de60 \ + --hash=sha256:f9a0ebbe45c29b5e5866593c12b78bd9035f0f0f0d4bc8361680cd580d99db49 + # via + # feast (pyproject.toml) + # grpcio-health-checking + # grpcio-reflection +grpcio-health-checking==1.81.1 \ + --hash=sha256:cbc6a4171825ec64389de2f062d296ba129a5c27eefd0dd55fa837909184bdf9 \ + --hash=sha256:ecc61480e25058a4a04e11e4ab6900ad7439b32e60a8ce4ece7d9f219221c85d + # via feast (pyproject.toml) +grpcio-reflection==1.81.1 \ + --hash=sha256:3d7160000f5fdd0e241f9b1a3d402f15ebcd5f281be105b374a025f38c6434a8 \ + --hash=sha256:d82fc4ac39dd5dcfd63e577075f6a68eac4a765e66a453914bbf57caf35665d0 + # via feast (pyproject.toml) gunicorn==26.0.0 \ --hash=sha256:40233d26a5f0d1872916188c276e21641155111c2853f0c2cd55260aec0d24fc \ --hash=sha256:ca9346f85e3a4aeeb64d491045c16b9a35647abd37ea15efe53080eb8b090baf @@ -796,16 +860,21 @@ prometheus-client==0.24.1 \ --hash=sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055 \ --hash=sha256:7e0ced7fbbd40f7b84962d5d2ab6f17ef88a72504dcf7c0b40737b43b2a461f9 # via feast (pyproject.toml) -protobuf==7.35.0 \ - --hash=sha256:4c4617b83ade0e279d1d2bfe04025a1adb87f9ed657de038620dc0ff959357f6 \ - --hash=sha256:4cbf5cc286130e06a6c9bbefac442431173906dfcc979712183d4adcc01b37ee \ - --hash=sha256:66be6c513931c794fa92c080ffee41671390da3d79da219cf9c0c0907f035dda \ - --hash=sha256:6c0f98f10c8a05ea30f8993dfef2de093d27b490fdae78bb60c8343795d55011 \ - --hash=sha256:a2efd84605f41e559f1881b0912b44099d0a2ac9bf46b3474823f10fb393b0e6 \ - --hash=sha256:c13f325cf242bad135c350629eeb5d54b24228eb472fb3e2e9ebbd4c5dc20ca0 \ - --hash=sha256:f05bcadf9a2a6b8dda047007075135fb7d08c73d9177aabc067e1be46881a201 \ - --hash=sha256:fcbe42a4ac09d3ec9c987ddfcd956afd0b15f1ff613bd8371bde9405ffd5c8e5 - # via feast (pyproject.toml) +protobuf==6.33.6 \ + --hash=sha256:0cd27b587afca21b7cfa59a74dcbd48a50f0a6400cfb59391340ad729d91d326 \ + --hash=sha256:77179e006c476e69bf8e8ce866640091ec42e1beb80b213c3900006ecfba6901 \ + --hash=sha256:7d29d9b65f8afef196f8334e80d6bc1d5d4adedb449971fefd3723824e6e77d3 \ + --hash=sha256:9720e6961b251bde64edfdab7d500725a2af5280f3f4c87e57c0208376aa8c3a \ + --hash=sha256:a6768d25248312c297558af96a9f9c929e8c4cee0659cb07e780731095f38135 \ + --hash=sha256:bd56799fb262994b2c2faa1799693c95cc2e22c62f56fb43af311cae45d26f0e \ + --hash=sha256:c96c37eec15086b79762ed265d59ab204dabc53056e3443e702d2681f4b39ce3 \ + --hash=sha256:e2afbae9b8e1825e3529f88d514754e094278bb95eadc0e199751cdd9a2e82a2 \ + --hash=sha256:e9db7e292e0ab79dd108d7f1a94fe31601ce1ee3f7b79e0692043423020b0593 \ + --hash=sha256:f443a394af5ed23672bc6c486be138628fbe5c651ccbc536873d7da23d1868cf + # via + # feast (pyproject.toml) + # grpcio-health-checking + # grpcio-reflection psutil==7.2.2 \ --hash=sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372 \ --hash=sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9 \ @@ -1390,6 +1459,7 @@ typing-extensions==4.15.0 \ # anyio # exceptiongroup # fastapi + # grpcio # mypy # pydantic # pydantic-core diff --git a/sdk/python/requirements/py3.11-requirements.txt b/sdk/python/requirements/py3.11-requirements.txt index b48c5d698f5..d729be02b82 100644 --- a/sdk/python/requirements/py3.11-requirements.txt +++ b/sdk/python/requirements/py3.11-requirements.txt @@ -225,6 +225,70 @@ fsspec==2026.4.0 \ --hash=sha256:11ef7bb35dab8a394fde6e608221d5cf3e8499401c249bebaeaad760a1a8dec2 \ --hash=sha256:301d8ac70ae90ef3ad05dcf94d6c3754a097f9b5fe4667d2787aa359ec7df7e4 # via dask +grpcio==1.81.1 \ + --hash=sha256:0490c30c261eded63f3f354979f9dc4502a9fb944cccb60cd9dc85f5a7349854 \ + --hash=sha256:0a37165cc80b1a368384b383e63a4c38116a10467ae44c904d2d7468c4470ec2 \ + --hash=sha256:12b7524c88d4026d3dcb7b0ebe16b6714f3b4af402ddd0f0639ab064a00c87c3 \ + --hash=sha256:15641444eca4a29358107b3dceb74c1c6305c55c822fd199b458aaea4068a7fb \ + --hash=sha256:1b22c80559854b789a01fd89e8929b3798a156c0829b5282a8939f33ad4115ad \ + --hash=sha256:1e123f9b37edb8375fd74130d1f69c944bbf0a7b06761ae7211154b8759e94d2 \ + --hash=sha256:24c8e57504c8f45b237e40b99262d181071e5099a07053695b75d97bb53053a0 \ + --hash=sha256:2c2e2ae6867c2966b8daccc836d54a13218e0007e9a490aeb81dd05be64d22d7 \ + --hash=sha256:30e825f6848d9f18bba350ed6c75c1b02a0b5184474a31db9a32b1fa66fd8c79 \ + --hash=sha256:3768a5ff1b2125e6f552e561b6b2dca0e64982d8949689b4df145cf8b98d7821 \ + --hash=sha256:3ad74f8bb1a18963914c5452d289422830b39459e8776ebbcd207be1fbfb1d94 \ + --hash=sha256:410482da976329fe5f4067270401b12cf2bd552ff8020f054ecfaddb5475f9d6 \ + --hash=sha256:428bec0161b48d8cf583c068591bc0016d0d9cfff52462b72b3884861ea768c5 \ + --hash=sha256:506f48f2f9c29b143fca3dad7b0d518c188b6c9648c75a2ae6e2d9f2c13a060b \ + --hash=sha256:58ad1131c300d3c9b933802b3cc4dc69d380822935ba50b28703156ea826fbf7 \ + --hash=sha256:592b5fee597faa91cce2dd294dd7d9a1c83d76c4dbf877e33ec1adb866b2fbed \ + --hash=sha256:61233fe8951e5c85dff81c2458b6528624760166946b5b47ea150a589168411f \ + --hash=sha256:62481553b1793a27e9b9c3cf9e5bd483ef045ca72462592074b46d42b0c4d9b9 \ + --hash=sha256:6282caffb41ec326d4cb67ca9cf53b739d1b2f975a2acb498c7418e9f7d9a416 \ + --hash=sha256:69ef28e54fc85397f91b8c19592b8ef3d81952080366914823bd8572a2958120 \ + --hash=sha256:6f9a0c9c1cc15c112d1c053064fd032b64917062292c3d70aea280e02ae10b77 \ + --hash=sha256:6fa10a767143a5e82e8eaab53918af0cd8909a57a27f8cb2288b80a613ac671b \ + --hash=sha256:766bc7c9a9c340342f4c864ccbda8e78111e4751f13b895812b9c148fb79e9d0 \ + --hash=sha256:78e29211f26da2fdd0e9c6d2b79f489476140cf7029b6a64808ade7ca4156a42 \ + --hash=sha256:819edbdcb42ab8598b494bcf0222684bbb7a3c772bd1b1f0be7e029a6063c28e \ + --hash=sha256:85b10a45b8993d195c4f3ff57025b8d1e11834909ee475c403bfa60cb4caefaf \ + --hash=sha256:88268ca418cacea64cecb0d1d600d3c6b3a8038fcba02e1e205178c5b1f47661 \ + --hash=sha256:8b39472beafc0bdcafc4c8c73ad082ebfdb449d566897a61e7acb4fa88089115 \ + --hash=sha256:8ea1936c26b99999b27479853039a7f34713f56c49375ad52b38535ec93a796c \ + --hash=sha256:98a07f9bf591e3a8919797bee1c53f026ba4acd587e5a4404c8e57c9ec36b2a5 \ + --hash=sha256:a185a04039df6cae8648bc8ab6d6fde7bf94f7188ecf7828e76ac52eef1e41d6 \ + --hash=sha256:a35009284d0d3d5c2c9601c164a911b8b4331608d98a9a66d47d97bb2f522b70 \ + --hash=sha256:a3acb384427816dd5d470f47e62137b87f74da694faa8a50147012cf40df276a \ + --hash=sha256:aa2ba7d2ad6df4d80127cea65e5b8d5e2c3adbf153ff4804452836328aca7c54 \ + --hash=sha256:b10e1ff4756ed27d5a29d7fc79cfce7ef1ff56ad20025b89bac7cf79e09abbbe \ + --hash=sha256:b137f4bf3ada9dc44d411478decc6ff09a79ed30b306cd2abaa98408c3588137 \ + --hash=sha256:b259a04a737cb3496be0901328eb8b7552ed8df4865d8c8f1cf1bffcfc0776a3 \ + --hash=sha256:b427c19380991a4eaab2f6144b64b99b412043314c6bf4ab544f97bb31ee4190 \ + --hash=sha256:bb693b1e3d9a2f3fd228e2110daf4b5aeedb36761ca1e4282f74725f6d89f611 \ + --hash=sha256:c261d74b1a945cf895a9d6eccd1685a8e837531beaab782da4d630a8d12deffb \ + --hash=sha256:c5bf2dc311127d91230cc79b92188c082634a06cf66c5234db49a43b910183b0 \ + --hash=sha256:ca1cc11d82677b9662082e5478b7528e2b7db7beaa6bdff42bd62789d81be399 \ + --hash=sha256:d4b2dddfc219f54f956ccd53cf76a1d338ffe68fc7f2849ec9c7feb9927ff692 \ + --hash=sha256:d71d30f2d92f67d944631c523713934fee37292469e182ebcd2c1dd8a64ce53f \ + --hash=sha256:d865db4a6318e1c1bea83292e0ed231090538fc4ca45425b0f0480eb338bbc6e \ + --hash=sha256:e2aa72e3ce1770317ef534f63d397b55e130725f5149bd36077c3b539019db27 \ + --hash=sha256:e3657301562ac3cb8018d30d0d3ebfa39932239f7b5703422057ef14b69949f5 \ + --hash=sha256:e64dd101d380a115cc5a0c7856788adb535f1a4e21fc543775602f8be95180ae \ + --hash=sha256:e8ca6a1fcdb2943c9cbc1804a1baf3acb6071d72a471591678ded84218006e14 \ + --hash=sha256:edb59506291b647a30884b1d51a599d605f40b20af4a7dc3d33786a47a31de60 \ + --hash=sha256:f9a0ebbe45c29b5e5866593c12b78bd9035f0f0f0d4bc8361680cd580d99db49 + # via + # feast (pyproject.toml) + # grpcio-health-checking + # grpcio-reflection +grpcio-health-checking==1.81.1 \ + --hash=sha256:cbc6a4171825ec64389de2f062d296ba129a5c27eefd0dd55fa837909184bdf9 \ + --hash=sha256:ecc61480e25058a4a04e11e4ab6900ad7439b32e60a8ce4ece7d9f219221c85d + # via feast (pyproject.toml) +grpcio-reflection==1.81.1 \ + --hash=sha256:3d7160000f5fdd0e241f9b1a3d402f15ebcd5f281be105b374a025f38c6434a8 \ + --hash=sha256:d82fc4ac39dd5dcfd63e577075f6a68eac4a765e66a453914bbf57caf35665d0 + # via feast (pyproject.toml) gunicorn==26.0.0 \ --hash=sha256:40233d26a5f0d1872916188c276e21641155111c2853f0c2cd55260aec0d24fc \ --hash=sha256:ca9346f85e3a4aeeb64d491045c16b9a35647abd37ea15efe53080eb8b090baf @@ -809,16 +873,21 @@ prometheus-client==0.24.1 \ --hash=sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055 \ --hash=sha256:7e0ced7fbbd40f7b84962d5d2ab6f17ef88a72504dcf7c0b40737b43b2a461f9 # via feast (pyproject.toml) -protobuf==7.35.0 \ - --hash=sha256:4c4617b83ade0e279d1d2bfe04025a1adb87f9ed657de038620dc0ff959357f6 \ - --hash=sha256:4cbf5cc286130e06a6c9bbefac442431173906dfcc979712183d4adcc01b37ee \ - --hash=sha256:66be6c513931c794fa92c080ffee41671390da3d79da219cf9c0c0907f035dda \ - --hash=sha256:6c0f98f10c8a05ea30f8993dfef2de093d27b490fdae78bb60c8343795d55011 \ - --hash=sha256:a2efd84605f41e559f1881b0912b44099d0a2ac9bf46b3474823f10fb393b0e6 \ - --hash=sha256:c13f325cf242bad135c350629eeb5d54b24228eb472fb3e2e9ebbd4c5dc20ca0 \ - --hash=sha256:f05bcadf9a2a6b8dda047007075135fb7d08c73d9177aabc067e1be46881a201 \ - --hash=sha256:fcbe42a4ac09d3ec9c987ddfcd956afd0b15f1ff613bd8371bde9405ffd5c8e5 - # via feast (pyproject.toml) +protobuf==6.33.6 \ + --hash=sha256:0cd27b587afca21b7cfa59a74dcbd48a50f0a6400cfb59391340ad729d91d326 \ + --hash=sha256:77179e006c476e69bf8e8ce866640091ec42e1beb80b213c3900006ecfba6901 \ + --hash=sha256:7d29d9b65f8afef196f8334e80d6bc1d5d4adedb449971fefd3723824e6e77d3 \ + --hash=sha256:9720e6961b251bde64edfdab7d500725a2af5280f3f4c87e57c0208376aa8c3a \ + --hash=sha256:a6768d25248312c297558af96a9f9c929e8c4cee0659cb07e780731095f38135 \ + --hash=sha256:bd56799fb262994b2c2faa1799693c95cc2e22c62f56fb43af311cae45d26f0e \ + --hash=sha256:c96c37eec15086b79762ed265d59ab204dabc53056e3443e702d2681f4b39ce3 \ + --hash=sha256:e2afbae9b8e1825e3529f88d514754e094278bb95eadc0e199751cdd9a2e82a2 \ + --hash=sha256:e9db7e292e0ab79dd108d7f1a94fe31601ce1ee3f7b79e0692043423020b0593 \ + --hash=sha256:f443a394af5ed23672bc6c486be138628fbe5c651ccbc536873d7da23d1868cf + # via + # feast (pyproject.toml) + # grpcio-health-checking + # grpcio-reflection psutil==7.2.2 \ --hash=sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372 \ --hash=sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9 \ @@ -1368,6 +1437,7 @@ typing-extensions==4.15.0 \ # via # anyio # fastapi + # grpcio # mypy # pydantic # pydantic-core diff --git a/sdk/python/requirements/py3.12-requirements.txt b/sdk/python/requirements/py3.12-requirements.txt index 4606cef5b92..af9b552d5da 100644 --- a/sdk/python/requirements/py3.12-requirements.txt +++ b/sdk/python/requirements/py3.12-requirements.txt @@ -225,6 +225,70 @@ fsspec==2026.4.0 \ --hash=sha256:11ef7bb35dab8a394fde6e608221d5cf3e8499401c249bebaeaad760a1a8dec2 \ --hash=sha256:301d8ac70ae90ef3ad05dcf94d6c3754a097f9b5fe4667d2787aa359ec7df7e4 # via dask +grpcio==1.81.1 \ + --hash=sha256:0490c30c261eded63f3f354979f9dc4502a9fb944cccb60cd9dc85f5a7349854 \ + --hash=sha256:0a37165cc80b1a368384b383e63a4c38116a10467ae44c904d2d7468c4470ec2 \ + --hash=sha256:12b7524c88d4026d3dcb7b0ebe16b6714f3b4af402ddd0f0639ab064a00c87c3 \ + --hash=sha256:15641444eca4a29358107b3dceb74c1c6305c55c822fd199b458aaea4068a7fb \ + --hash=sha256:1b22c80559854b789a01fd89e8929b3798a156c0829b5282a8939f33ad4115ad \ + --hash=sha256:1e123f9b37edb8375fd74130d1f69c944bbf0a7b06761ae7211154b8759e94d2 \ + --hash=sha256:24c8e57504c8f45b237e40b99262d181071e5099a07053695b75d97bb53053a0 \ + --hash=sha256:2c2e2ae6867c2966b8daccc836d54a13218e0007e9a490aeb81dd05be64d22d7 \ + --hash=sha256:30e825f6848d9f18bba350ed6c75c1b02a0b5184474a31db9a32b1fa66fd8c79 \ + --hash=sha256:3768a5ff1b2125e6f552e561b6b2dca0e64982d8949689b4df145cf8b98d7821 \ + --hash=sha256:3ad74f8bb1a18963914c5452d289422830b39459e8776ebbcd207be1fbfb1d94 \ + --hash=sha256:410482da976329fe5f4067270401b12cf2bd552ff8020f054ecfaddb5475f9d6 \ + --hash=sha256:428bec0161b48d8cf583c068591bc0016d0d9cfff52462b72b3884861ea768c5 \ + --hash=sha256:506f48f2f9c29b143fca3dad7b0d518c188b6c9648c75a2ae6e2d9f2c13a060b \ + --hash=sha256:58ad1131c300d3c9b933802b3cc4dc69d380822935ba50b28703156ea826fbf7 \ + --hash=sha256:592b5fee597faa91cce2dd294dd7d9a1c83d76c4dbf877e33ec1adb866b2fbed \ + --hash=sha256:61233fe8951e5c85dff81c2458b6528624760166946b5b47ea150a589168411f \ + --hash=sha256:62481553b1793a27e9b9c3cf9e5bd483ef045ca72462592074b46d42b0c4d9b9 \ + --hash=sha256:6282caffb41ec326d4cb67ca9cf53b739d1b2f975a2acb498c7418e9f7d9a416 \ + --hash=sha256:69ef28e54fc85397f91b8c19592b8ef3d81952080366914823bd8572a2958120 \ + --hash=sha256:6f9a0c9c1cc15c112d1c053064fd032b64917062292c3d70aea280e02ae10b77 \ + --hash=sha256:6fa10a767143a5e82e8eaab53918af0cd8909a57a27f8cb2288b80a613ac671b \ + --hash=sha256:766bc7c9a9c340342f4c864ccbda8e78111e4751f13b895812b9c148fb79e9d0 \ + --hash=sha256:78e29211f26da2fdd0e9c6d2b79f489476140cf7029b6a64808ade7ca4156a42 \ + --hash=sha256:819edbdcb42ab8598b494bcf0222684bbb7a3c772bd1b1f0be7e029a6063c28e \ + --hash=sha256:85b10a45b8993d195c4f3ff57025b8d1e11834909ee475c403bfa60cb4caefaf \ + --hash=sha256:88268ca418cacea64cecb0d1d600d3c6b3a8038fcba02e1e205178c5b1f47661 \ + --hash=sha256:8b39472beafc0bdcafc4c8c73ad082ebfdb449d566897a61e7acb4fa88089115 \ + --hash=sha256:8ea1936c26b99999b27479853039a7f34713f56c49375ad52b38535ec93a796c \ + --hash=sha256:98a07f9bf591e3a8919797bee1c53f026ba4acd587e5a4404c8e57c9ec36b2a5 \ + --hash=sha256:a185a04039df6cae8648bc8ab6d6fde7bf94f7188ecf7828e76ac52eef1e41d6 \ + --hash=sha256:a35009284d0d3d5c2c9601c164a911b8b4331608d98a9a66d47d97bb2f522b70 \ + --hash=sha256:a3acb384427816dd5d470f47e62137b87f74da694faa8a50147012cf40df276a \ + --hash=sha256:aa2ba7d2ad6df4d80127cea65e5b8d5e2c3adbf153ff4804452836328aca7c54 \ + --hash=sha256:b10e1ff4756ed27d5a29d7fc79cfce7ef1ff56ad20025b89bac7cf79e09abbbe \ + --hash=sha256:b137f4bf3ada9dc44d411478decc6ff09a79ed30b306cd2abaa98408c3588137 \ + --hash=sha256:b259a04a737cb3496be0901328eb8b7552ed8df4865d8c8f1cf1bffcfc0776a3 \ + --hash=sha256:b427c19380991a4eaab2f6144b64b99b412043314c6bf4ab544f97bb31ee4190 \ + --hash=sha256:bb693b1e3d9a2f3fd228e2110daf4b5aeedb36761ca1e4282f74725f6d89f611 \ + --hash=sha256:c261d74b1a945cf895a9d6eccd1685a8e837531beaab782da4d630a8d12deffb \ + --hash=sha256:c5bf2dc311127d91230cc79b92188c082634a06cf66c5234db49a43b910183b0 \ + --hash=sha256:ca1cc11d82677b9662082e5478b7528e2b7db7beaa6bdff42bd62789d81be399 \ + --hash=sha256:d4b2dddfc219f54f956ccd53cf76a1d338ffe68fc7f2849ec9c7feb9927ff692 \ + --hash=sha256:d71d30f2d92f67d944631c523713934fee37292469e182ebcd2c1dd8a64ce53f \ + --hash=sha256:d865db4a6318e1c1bea83292e0ed231090538fc4ca45425b0f0480eb338bbc6e \ + --hash=sha256:e2aa72e3ce1770317ef534f63d397b55e130725f5149bd36077c3b539019db27 \ + --hash=sha256:e3657301562ac3cb8018d30d0d3ebfa39932239f7b5703422057ef14b69949f5 \ + --hash=sha256:e64dd101d380a115cc5a0c7856788adb535f1a4e21fc543775602f8be95180ae \ + --hash=sha256:e8ca6a1fcdb2943c9cbc1804a1baf3acb6071d72a471591678ded84218006e14 \ + --hash=sha256:edb59506291b647a30884b1d51a599d605f40b20af4a7dc3d33786a47a31de60 \ + --hash=sha256:f9a0ebbe45c29b5e5866593c12b78bd9035f0f0f0d4bc8361680cd580d99db49 + # via + # feast (pyproject.toml) + # grpcio-health-checking + # grpcio-reflection +grpcio-health-checking==1.81.1 \ + --hash=sha256:cbc6a4171825ec64389de2f062d296ba129a5c27eefd0dd55fa837909184bdf9 \ + --hash=sha256:ecc61480e25058a4a04e11e4ab6900ad7439b32e60a8ce4ece7d9f219221c85d + # via feast (pyproject.toml) +grpcio-reflection==1.81.1 \ + --hash=sha256:3d7160000f5fdd0e241f9b1a3d402f15ebcd5f281be105b374a025f38c6434a8 \ + --hash=sha256:d82fc4ac39dd5dcfd63e577075f6a68eac4a765e66a453914bbf57caf35665d0 + # via feast (pyproject.toml) gunicorn==26.0.0 \ --hash=sha256:40233d26a5f0d1872916188c276e21641155111c2853f0c2cd55260aec0d24fc \ --hash=sha256:ca9346f85e3a4aeeb64d491045c16b9a35647abd37ea15efe53080eb8b090baf @@ -805,16 +869,21 @@ prometheus-client==0.24.1 \ --hash=sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055 \ --hash=sha256:7e0ced7fbbd40f7b84962d5d2ab6f17ef88a72504dcf7c0b40737b43b2a461f9 # via feast (pyproject.toml) -protobuf==7.35.0 \ - --hash=sha256:4c4617b83ade0e279d1d2bfe04025a1adb87f9ed657de038620dc0ff959357f6 \ - --hash=sha256:4cbf5cc286130e06a6c9bbefac442431173906dfcc979712183d4adcc01b37ee \ - --hash=sha256:66be6c513931c794fa92c080ffee41671390da3d79da219cf9c0c0907f035dda \ - --hash=sha256:6c0f98f10c8a05ea30f8993dfef2de093d27b490fdae78bb60c8343795d55011 \ - --hash=sha256:a2efd84605f41e559f1881b0912b44099d0a2ac9bf46b3474823f10fb393b0e6 \ - --hash=sha256:c13f325cf242bad135c350629eeb5d54b24228eb472fb3e2e9ebbd4c5dc20ca0 \ - --hash=sha256:f05bcadf9a2a6b8dda047007075135fb7d08c73d9177aabc067e1be46881a201 \ - --hash=sha256:fcbe42a4ac09d3ec9c987ddfcd956afd0b15f1ff613bd8371bde9405ffd5c8e5 - # via feast (pyproject.toml) +protobuf==6.33.6 \ + --hash=sha256:0cd27b587afca21b7cfa59a74dcbd48a50f0a6400cfb59391340ad729d91d326 \ + --hash=sha256:77179e006c476e69bf8e8ce866640091ec42e1beb80b213c3900006ecfba6901 \ + --hash=sha256:7d29d9b65f8afef196f8334e80d6bc1d5d4adedb449971fefd3723824e6e77d3 \ + --hash=sha256:9720e6961b251bde64edfdab7d500725a2af5280f3f4c87e57c0208376aa8c3a \ + --hash=sha256:a6768d25248312c297558af96a9f9c929e8c4cee0659cb07e780731095f38135 \ + --hash=sha256:bd56799fb262994b2c2faa1799693c95cc2e22c62f56fb43af311cae45d26f0e \ + --hash=sha256:c96c37eec15086b79762ed265d59ab204dabc53056e3443e702d2681f4b39ce3 \ + --hash=sha256:e2afbae9b8e1825e3529f88d514754e094278bb95eadc0e199751cdd9a2e82a2 \ + --hash=sha256:e9db7e292e0ab79dd108d7f1a94fe31601ce1ee3f7b79e0692043423020b0593 \ + --hash=sha256:f443a394af5ed23672bc6c486be138628fbe5c651ccbc536873d7da23d1868cf + # via + # feast (pyproject.toml) + # grpcio-health-checking + # grpcio-reflection psutil==7.2.2 \ --hash=sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372 \ --hash=sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9 \ @@ -1364,6 +1433,7 @@ typing-extensions==4.15.0 \ # via # anyio # fastapi + # grpcio # mypy # pydantic # pydantic-core diff --git a/sdk/python/tests/unit/api/test_api_rest_registry_server.py b/sdk/python/tests/unit/api/test_api_rest_registry_server.py index 2abfa3ac462..f181c794a96 100644 --- a/sdk/python/tests/unit/api/test_api_rest_registry_server.py +++ b/sdk/python/tests/unit/api/test_api_rest_registry_server.py @@ -54,33 +54,12 @@ def test_rest_registry_server_initializes_correctly( assert {"BearerAuth": []} in openapi_schema["security"] -def test_routes_registered_in_app(mock_store_and_registry): - from fastapi.routing import APIRoute +def test_routes_registered_in_app(): + from feast.api.registry.rest import register_all_routes - store, _ = mock_store_and_registry + app = MagicMock() + grpc_handler = MagicMock() + server = MagicMock() + register_all_routes(app, grpc_handler, server) - server = RestRegistryServer(store) - route_paths = [ - route.path for route in server.app.routes if isinstance(route, APIRoute) - ] - assert "/feature_services" in route_paths - assert "/entities" in route_paths - assert "/projects" in route_paths - assert "/data_sources" in route_paths - assert "/saved_datasets" in route_paths - assert "/permissions" in route_paths - assert "/lineage/registry" in route_paths - assert "/lineage/objects/{object_type}/{object_name}" in route_paths - assert "/lineage/complete" in route_paths - assert "/entities/all" in route_paths - assert "/feature_views/all" in route_paths - assert "/data_sources/all" in route_paths - assert "/feature_services/all" in route_paths - assert "/saved_datasets/all" in route_paths - assert "/lineage/registry/all" in route_paths - assert "/lineage/complete/all" in route_paths - assert "/features" in route_paths - assert "/features/all" in route_paths - assert "/features/{feature_view}/{name}" in route_paths - assert "/metrics/resource_counts" in route_paths - assert "/metrics/recently_visited" in route_paths + assert app.include_router.call_count == 13 diff --git a/sdk/python/tests/unit/test_pyproject_dependencies.py b/sdk/python/tests/unit/test_pyproject_dependencies.py new file mode 100644 index 00000000000..7bf1f881b68 --- /dev/null +++ b/sdk/python/tests/unit/test_pyproject_dependencies.py @@ -0,0 +1,13 @@ +from pathlib import Path + +import toml # type: ignore[import-untyped] + + +def test_ui_runtime_grpc_dependencies_are_base_dependencies() -> None: + pyproject_path = Path(__file__).resolve().parents[4] / "pyproject.toml" + pyproject = toml.loads(pyproject_path.read_text()) + dependencies = pyproject["project"]["dependencies"] + + assert "grpcio>=1.56.2" in dependencies + assert "grpcio-reflection>=1.56.2" in dependencies + assert "grpcio-health-checking>=1.56.2" in dependencies diff --git a/ui/src/components/PermissionsDisplay.tsx b/ui/src/components/PermissionsDisplay.tsx index 47af120a1cd..d4b35cb5d33 100644 --- a/ui/src/components/PermissionsDisplay.tsx +++ b/ui/src/components/PermissionsDisplay.tsx @@ -3,13 +3,9 @@ import { EuiBadge, EuiFlexGroup, EuiFlexItem, - EuiPanel, EuiText, - EuiTitle, - EuiHorizontalRule, EuiToolTip, } from "@elastic/eui"; -import { formatPermissions } from "../utils/permissionUtils"; interface PermissionsDisplayProps { permissions: any[] | undefined; diff --git a/ui/src/components/RegistrySearch.tsx b/ui/src/components/RegistrySearch.tsx index 46d72966713..ed3b987240e 100644 --- a/ui/src/components/RegistrySearch.tsx +++ b/ui/src/components/RegistrySearch.tsx @@ -3,6 +3,7 @@ import React, { useRef, forwardRef, useImperativeHandle, + useCallback, } from "react"; import { EuiText, @@ -17,8 +18,6 @@ import { } from "@elastic/eui"; import EuiCustomLink from "./EuiCustomLink"; -import { css } from "@emotion/react"; - const searchResultsStyles = { searchResults: { marginTop: "8px", @@ -68,11 +67,11 @@ const RegistrySearch = forwardRef( const [searchText, setSearchText] = useState(""); const inputRef = useRef(null); - const focusSearchInput = () => { + const focusSearchInput = useCallback(() => { if (inputRef.current) { inputRef.current.focus(); } - }; + }, []); useImperativeHandle( ref, diff --git a/ui/src/custom-tabs/TabsRegistryContext.tsx b/ui/src/custom-tabs/TabsRegistryContext.tsx index 38c9ccea486..4152edd832d 100644 --- a/ui/src/custom-tabs/TabsRegistryContext.tsx +++ b/ui/src/custom-tabs/TabsRegistryContext.tsx @@ -16,7 +16,6 @@ import FeatureCustomTabLoadingWrapper from "../utils/custom-tabs/FeatureCustomTa import DataSourceCustomTabLoadingWrapper from "../utils/custom-tabs/DataSourceCustomTabLoadingWrapper"; import EntityCustomTabLoadingWrapper from "../utils/custom-tabs/EntityCustomTabLoadingWrapper"; import DatasetCustomTabLoadingWrapper from "../utils/custom-tabs/DatasetCustomTabLoadingWrapper"; -import CurlGeneratorTab from "../pages/feature-views/CurlGeneratorTab"; import { RegularFeatureViewCustomTabRegistrationInterface, diff --git a/ui/src/pages/Layout.tsx b/ui/src/pages/Layout.tsx index 9825159aa96..d59c865ad88 100644 --- a/ui/src/pages/Layout.tsx +++ b/ui/src/pages/Layout.tsx @@ -54,55 +54,6 @@ const Layout = () => { // Load unfiltered data for global search (across all projects) const { data: globalData } = useLoadRegistry(globalRegistryPath); - // Categories for page-level search (filtered to current project) - const categories = data - ? [ - { - name: "Data Sources", - data: data.objects.dataSources || [], - getLink: (item: any) => `/p/${projectName}/data-source/${item.name}`, - }, - { - name: "Entities", - data: data.objects.entities || [], - getLink: (item: any) => `/p/${projectName}/entity/${item.name}`, - }, - { - name: "Features", - data: data.allFeatures || [], - getLink: (item: any) => { - const featureView = item?.featureView; - return featureView - ? `/p/${projectName}/feature-view/${featureView}/feature/${item.name}` - : "#"; - }, - }, - { - name: "Feature Views", - data: data.mergedFVList || [], - getLink: (item: any) => `/p/${projectName}/feature-view/${item.name}`, - }, - { - name: "Label Views", - data: data.objects.labelViews || [], - getLink: (item: any) => { - const lvName = item?.name || item?.spec?.name; - return `/p/${projectName}/label-view/${lvName}`; - }, - }, - { - name: "Feature Services", - data: data.objects.featureServices || [], - getLink: (item: any) => { - const serviceName = item?.name || item?.spec?.name; - return serviceName - ? `/p/${projectName}/feature-service/${serviceName}` - : "#"; - }, - }, - ] - : []; - // Helper function to extract project ID from an item const getProjectId = (item: any): string => { // Try different possible locations for the project field diff --git a/ui/src/pages/feature-views/FeatureViewVersionsTab.tsx b/ui/src/pages/feature-views/FeatureViewVersionsTab.tsx index 188bc8d7a3a..f388d247da4 100644 --- a/ui/src/pages/feature-views/FeatureViewVersionsTab.tsx +++ b/ui/src/pages/feature-views/FeatureViewVersionsTab.tsx @@ -6,7 +6,6 @@ import { EuiTitle, EuiHorizontalRule, EuiCodeBlock, - EuiSpacer, EuiFlexGroup, EuiFlexItem, EuiBadge, @@ -161,11 +160,17 @@ const FeatureViewVersionsTab = ({ const registryQuery = useLoadRegistry(registryUrl, projectName); const [expandedRows, setExpandedRows] = useState>({}); - const records = - registryQuery.data?.objects?.featureViewVersionHistory?.records?.filter( - (r: feast.core.IFeatureViewVersionRecord) => - r.featureViewName === featureViewName, - ) || []; + const records = useMemo( + () => + registryQuery.data?.objects?.featureViewVersionHistory?.records?.filter( + (r: feast.core.IFeatureViewVersionRecord) => + r.featureViewName === featureViewName, + ) || [], + [ + registryQuery.data?.objects?.featureViewVersionHistory?.records, + featureViewName, + ], + ); const decodedVersions: DecodedVersion[] = useMemo( () => records.map(decodeVersionProto), diff --git a/ui/src/pages/feature-views/components/FeatureViewProjectionDisplayPanel.tsx b/ui/src/pages/feature-views/components/FeatureViewProjectionDisplayPanel.tsx index 6307de29c39..a80f8039e19 100644 --- a/ui/src/pages/feature-views/components/FeatureViewProjectionDisplayPanel.tsx +++ b/ui/src/pages/feature-views/components/FeatureViewProjectionDisplayPanel.tsx @@ -4,7 +4,6 @@ import { EuiBasicTable, EuiPanel, EuiSpacer, - EuiText, EuiTitle, } from "@elastic/eui"; import { useParams } from "react-router-dom"; diff --git a/ui/src/pages/label-views/BatchUploadTab.tsx b/ui/src/pages/label-views/BatchUploadTab.tsx index b85cc31521c..6f3930c5d92 100644 --- a/ui/src/pages/label-views/BatchUploadTab.tsx +++ b/ui/src/pages/label-views/BatchUploadTab.tsx @@ -3,7 +3,6 @@ import { useParams } from "react-router-dom"; import { EuiPanel, EuiTitle, - EuiHorizontalRule, EuiForm, EuiFormRow, EuiButton, @@ -18,7 +17,6 @@ import { EuiFilePicker, EuiBasicTable, EuiBasicTableColumn, - EuiIcon, EuiCodeBlock, } from "@elastic/eui"; import RegistryPathContext from "../../contexts/RegistryPathContext"; @@ -28,7 +26,7 @@ const BatchUploadTab = () => { const { labelViewName } = useParams(); const registryUrl = useContext(RegistryPathContext); const name = labelViewName || ""; - const { isLoading, isSuccess, data } = useLoadLabelView(name); + const { isLoading, data } = useLoadLabelView(name); const [fileData, setFileData] = useState(null); const [fileName, setFileName] = useState(""); diff --git a/ui/src/pages/label-views/ClassificationMethod.tsx b/ui/src/pages/label-views/ClassificationMethod.tsx index 3a0f34c236a..9d4366f2e00 100644 --- a/ui/src/pages/label-views/ClassificationMethod.tsx +++ b/ui/src/pages/label-views/ClassificationMethod.tsx @@ -1,4 +1,10 @@ -import React, { useState, useContext, useEffect } from "react"; +import React, { + useState, + useContext, + useEffect, + useCallback, + useMemo, +} from "react"; import { useParams } from "react-router-dom"; import { EuiCallOut, @@ -7,7 +13,6 @@ import { EuiFlexItem, EuiButton, EuiPanel, - EuiTitle, EuiText, EuiLoadingSpinner, EuiBasicTable, @@ -45,17 +50,23 @@ const ClassificationMethod = () => { const [pageSize, setPageSize] = useState(25); const spec = data?.object?.spec || data?.spec || {}; - const labelFields: { name: string; valueType?: string }[] = - spec.features || []; - const entities: string[] = spec.entityColumns?.length - ? spec.entityColumns.map((ec: { name: string }) => ec.name) - : spec.entities || []; + const labelFields: { name: string; valueType?: string }[] = useMemo( + () => spec.features || [], + [spec.features], + ); + const entities: string[] = useMemo( + () => + spec.entityColumns?.length + ? spec.entityColumns.map((ec: { name: string }) => ec.name) + : spec.entities || [], + [spec.entityColumns, spec.entities], + ); const configuredValues = annotationConfig?.label_values || {}; const fieldRoles = annotationConfig?.field_roles || {}; const labelWidgets = annotationConfig?.label_widgets || {}; - const fetchLabels = async () => { + const fetchLabels = useCallback(async () => { setIsLoading(true); setError(null); try { @@ -84,13 +95,13 @@ const ClassificationMethod = () => { } finally { setIsLoading(false); } - }; + }, [labelViewName, registryUrl]); useEffect(() => { if (labelViewName) { fetchLabels(); } - }, [labelViewName]); + }, [labelViewName, fetchLabels]); const handleFieldChange = (rowId: string, field: string, value: string) => { setRows((prev) => @@ -186,7 +197,7 @@ const ClassificationMethod = () => { URL.revokeObjectURL(url); }; - const filteredRows = React.useMemo(() => { + const filteredRows = useMemo(() => { if (!searchQuery.trim()) return rows; const q = searchQuery.toLowerCase(); return rows.filter((row) => @@ -198,12 +209,12 @@ const ClassificationMethod = () => { ); }, [rows, searchQuery]); - const paginatedRows = React.useMemo(() => { + const paginatedRows = useMemo(() => { const start = pageIndex * pageSize; return filteredRows.slice(start, start + pageSize); }, [filteredRows, pageIndex, pageSize]); - const uniqueValuesForField = React.useMemo(() => { + const uniqueValuesForField = useMemo(() => { const result: Record = {}; labelFields.forEach((field) => { const values = new Set(); diff --git a/ui/src/pages/label-views/EntityFormMethod.tsx b/ui/src/pages/label-views/EntityFormMethod.tsx index d659a38b08f..025f08b277c 100644 --- a/ui/src/pages/label-views/EntityFormMethod.tsx +++ b/ui/src/pages/label-views/EntityFormMethod.tsx @@ -9,7 +9,6 @@ import { EuiPanel, EuiTitle, EuiText, - EuiLoadingSpinner, EuiFormRow, EuiFieldText, EuiFieldNumber, @@ -35,11 +34,17 @@ const EntityFormMethod = ({ annotationConfig }: EntityFormMethodProps) => { const { data } = useLoadLabelView(labelViewName || ""); const spec = data?.object?.spec || data?.spec || {}; - const entities: string[] = spec.entityColumns?.length - ? spec.entityColumns.map((ec: { name: string }) => ec.name) - : spec.entities || []; - const labelFields: { name: string; valueType?: string }[] = - spec.features || []; + const entities: string[] = useMemo( + () => + spec.entityColumns?.length + ? spec.entityColumns.map((ec: { name: string }) => ec.name) + : spec.entities || [], + [spec.entityColumns, spec.entities], + ); + const labelFields: { name: string; valueType?: string }[] = useMemo( + () => spec.features || [], + [spec.features], + ); const fieldRoles = annotationConfig.field_roles; const labelValues = annotationConfig.label_values; diff --git a/ui/src/pages/label-views/IntegrationsTab.tsx b/ui/src/pages/label-views/IntegrationsTab.tsx index 70078644443..feca543bd10 100644 --- a/ui/src/pages/label-views/IntegrationsTab.tsx +++ b/ui/src/pages/label-views/IntegrationsTab.tsx @@ -3,7 +3,6 @@ import { useParams } from "react-router-dom"; import { EuiPanel, EuiTitle, - EuiHorizontalRule, EuiText, EuiLoadingSpinner, EuiCallOut, @@ -12,8 +11,6 @@ import { EuiFlexGroup, EuiFlexItem, EuiBadge, - EuiCopy, - EuiButton, EuiIcon, } from "@elastic/eui"; import RegistryPathContext from "../../contexts/RegistryPathContext"; diff --git a/ui/src/pages/label-views/LabelBrowseTab.tsx b/ui/src/pages/label-views/LabelBrowseTab.tsx index d1ee9013a92..7ed1b51a8b1 100644 --- a/ui/src/pages/label-views/LabelBrowseTab.tsx +++ b/ui/src/pages/label-views/LabelBrowseTab.tsx @@ -83,7 +83,7 @@ const LabelBrowseTab = () => { const entities: string[] = spec.entityColumns?.length ? spec.entityColumns.map((ec: { name: string }) => ec.name) : spec.entities || []; - const features: any[] = spec.features || []; + const features: any[] = useMemo(() => spec.features || [], [spec.features]); const conflictPolicy = spec.conflictPolicy || spec.conflict_policy || "LAST_WRITE_WINS"; const policyLabel = diff --git a/ui/src/pages/label-views/TrainingExportTab.tsx b/ui/src/pages/label-views/TrainingExportTab.tsx index 6580825231d..7a19741c182 100644 --- a/ui/src/pages/label-views/TrainingExportTab.tsx +++ b/ui/src/pages/label-views/TrainingExportTab.tsx @@ -28,7 +28,7 @@ const TrainingExportTab = () => { const { labelViewName } = useParams(); const registryUrl = useContext(RegistryPathContext); const name = labelViewName || ""; - const { isLoading, isSuccess, data } = useLoadLabelView(name); + const { isLoading, data } = useLoadLabelView(name); const { data: registryData } = useLoadRegistry(registryUrl); const [featureService, setFeatureService] = useState(""); @@ -38,7 +38,6 @@ const TrainingExportTab = () => { moment().subtract(30, "days"), ); const [endDate, setEndDate] = useState(moment()); - const [exportFormat, setExportFormat] = useState("csv"); const [exporting, setExporting] = useState(false); const [exportResult, setExportResult] = useState(null); const [error, setError] = useState(null); diff --git a/ui/src/pages/monitoring/FeatureMetricsDetail.tsx b/ui/src/pages/monitoring/FeatureMetricsDetail.tsx index 88d464d8faa..51f690ffa55 100644 --- a/ui/src/pages/monitoring/FeatureMetricsDetail.tsx +++ b/ui/src/pages/monitoring/FeatureMetricsDetail.tsx @@ -18,7 +18,6 @@ import { useBaselineMetrics, } from "../../queries/useMonitoringApi"; import type { - FeatureMetric, NumericHistogram, CategoricalHistogram, } from "../../queries/useMonitoringApi"; diff --git a/ui/src/pages/monitoring/components/HistogramChart.tsx b/ui/src/pages/monitoring/components/HistogramChart.tsx index bed612df0dc..a716b025021 100644 --- a/ui/src/pages/monitoring/components/HistogramChart.tsx +++ b/ui/src/pages/monitoring/components/HistogramChart.tsx @@ -291,12 +291,10 @@ const NumericHistogramChart = ({ const LABEL_WIDTH = 60; const BAR_MAX_WIDTH = 320; const COUNT_PAD = 80; -const CAT_SVG_WIDTH = LABEL_WIDTH + BAR_MAX_WIDTH + COUNT_PAD; const LABEL_WIDTH_EXP = 120; const BAR_MAX_WIDTH_EXP = 560; const COUNT_PAD_EXP = 100; -const CAT_SVG_WIDTH_EXP = LABEL_WIDTH_EXP + BAR_MAX_WIDTH_EXP + COUNT_PAD_EXP; const renderCategoricalSvg = ( histogram: CategoricalHistogram, diff --git a/ui/src/utils/permissionUtils.ts b/ui/src/utils/permissionUtils.ts index 9caa162ec1c..c4c4cef032e 100644 --- a/ui/src/utils/permissionUtils.ts +++ b/ui/src/utils/permissionUtils.ts @@ -1,5 +1,4 @@ import { FEAST_FCO_TYPES } from "../parsers/types"; -import { feast } from "../protos"; /** * Get permissions for a specific entity