diff --git a/.commitlintrc.yaml b/.commitlintrc.yaml new file mode 100644 index 00000000000..8b13a390116 --- /dev/null +++ b/.commitlintrc.yaml @@ -0,0 +1,45 @@ +extends: + - "@commitlint/config-conventional" + +# Single source of truth for commit/PR title conventions. +# Used by: +# - .pre-commit-config.yaml (commitlint hook on commit-msg) +# - .github/workflows/lint_pr.yml (validates PR titles in CI) +rules: + type-enum: + - 2 + - always + - - feat + - fix + - docs + - style + - refactor + - perf + - test + - build + - ci + - chore + - revert + + # Scope is optional — no enforcement on allowed values. + scope-empty: + - 0 + + # Feast convention: subjects start with an uppercase letter. + # Overrides base config which defaults to "never sentence-case". + subject-case: + - 2 + - always + - - sentence-case + + header-max-length: + - 2 + - always + - 100 + + # Relax body/footer line length from base config's strict 100-char limit. + # Commit bodies often contain URLs, stack traces, or formatted output. + body-max-line-length: + - 0 + footer-max-line-length: + - 0 diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 40986a87db9..48bb592ed84 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -11,7 +11,7 @@ # What this PR does / why we need it: # Which issue(s) this PR fixes: @@ -20,6 +20,16 @@ Outline what you're doing Usage: `Fixes #`, or `Fixes (paste link of issue)`. --> +# Checks +- [ ] I've made sure the tests are passing. +- [ ] My commits are signed off (`git commit -s`) +- [ ] My PR title follows [conventional commits](https://www.conventionalcommits.org/) format + +## Testing Strategy +- [ ] Unit tests +- [ ] Integration tests +- [ ] Manual tests +- [ ] Testing is not required for this change # Misc |manages| Registry + Operator -->|manages| FeatureServer + FeatureServer -->|reads/writes| Redis + FeatureServer -->|reads| OfflineStore + Registry -->|metadata| OfflineStore + + Client(["Client / ML Service"]) -->|REST| FeatureServer + + style Kubernetes fill:#f0f4ff,stroke:#3366cc,color:#000 + style Operator fill:#e8f5e9,stroke:#388e3c,color:#000 + style Registry fill:#fff3e0,stroke:#f57c00,color:#000 + style FeatureServer fill:#e3f2fd,stroke:#1976d2,color:#000 + style Redis fill:#fce4ec,stroke:#c62828,color:#000 + style OfflineStore fill:#f3e5f5,stroke:#7b1fa2,color:#000 +``` + +### Components + +| Component | Configuration | Notes | +|---|---|---| +| **Feast Operator** | Default install | Manages all Feast CRDs | +| **Registry** | REST, 1 replica | Single point of metadata | +| **Online Feature Server** | 1 replica, no autoscaling | Serves online features | +| **Online Store** | Redis standalone (example) | SQLite is simplest for development; Redis for production. See [supported online stores](../reference/online-stores/README.md) for all options | +| **Offline Store** | File-based or MinIO | DuckDB or file-based for development; MinIO/S3 for production. See [supported offline stores](../reference/offline-stores/README.md) for all options | +| **Compute Engine** | In-process (default) | Suitable for small datasets and development; use Spark, Ray, or Snowflake Engine for larger workloads | + +### Sample FeatureStore CR + +```yaml +apiVersion: feast.dev/v1 +kind: FeatureStore +metadata: + name: minimal-production +spec: + feastProject: my_project + services: + onlineStore: + persistence: + store: + type: redis + secretRef: + name: feast-online-store + server: + resources: + requests: + cpu: 500m + memory: 512Mi + limits: + cpu: "1" + memory: 1Gi + registry: + local: + server: + resources: + requests: + cpu: 250m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi +``` + +### Limitations + +{% hint style="warning" %} +* **No high availability** — a single replica failure causes downtime +* **No automatic failover** — manual intervention required on failure +* **Manual scaling** — no HPA configured +* **Limited security** — no TLS, no ingress, no RBAC by default +{% endhint %} + +--- + +## 2. Standard Production (Recommended) + +### When to use + +* Most production ML workloads +* Teams with moderate traffic that need reliability +* Environments that require TLS, RBAC, and automated scaling + +### Architecture + +```mermaid +graph TD + Client(["Client / ML Service"]) -->|HTTPS| Ingress + + subgraph Kubernetes["Kubernetes"] + Ingress["Ingress Controller
(TLS termination)"] + Operator["Feast Operator"] + + subgraph FeastDeployment["Feast Deployment (HPA autoscaled)"] + Registry["Feast Registry
(SQL-backed)"] + FeatureServer["Online Feature Server"] + end + + RedisCluster["Online Store
(e.g. Redis Cluster, DynamoDB, etc.)"] + + Ingress --> FeatureServer + Operator -->|manages| Registry + Operator -->|manages| FeatureServer + FeatureServer -->|reads/writes| RedisCluster + FeatureServer -->|reads metadata| Registry + end + + ObjectStorage["Offline Store
(e.g. S3 / Redshift / BigQuery, etc.)"] + FeatureServer -->|reads| ObjectStorage + Registry -->|metadata| ObjectStorage + + style Kubernetes fill:#f0f4ff,stroke:#3366cc,color:#000 + style FeastDeployment fill:#e8f5e9,stroke:#388e3c,color:#000 + style Ingress fill:#fff9c4,stroke:#f9a825,color:#000 + style Operator fill:#e8f5e9,stroke:#388e3c,color:#000 + style Registry fill:#fff3e0,stroke:#f57c00,color:#000 + style FeatureServer fill:#e3f2fd,stroke:#1976d2,color:#000 + style RedisCluster fill:#fce4ec,stroke:#c62828,color:#000 + style ObjectStorage fill:#f3e5f5,stroke:#7b1fa2,color:#000 +``` + +### Components + +**Core** + +| Component | Configuration | Notes | +|---|---|---| +| **Feast Operator** | Default install | Manages all Feast CRDs | +| **Registry** | SQL-backed (PostgreSQL) | Database-backed for consistency and concurrent access | +| **Online Feature Server** | HPA (min 2 replicas, max based on peak load) | All services scale together in a single shared Deployment | + +**Storage** + +| Component | Configuration | Notes | +|---|---|---| +| **Online Store** | Redis Cluster (example) | Multi-node for availability and low latency; other production stores are also supported — see [supported online stores](../reference/online-stores/README.md) | +| **Offline Store** | S3 / MinIO | Persistent object storage; see [supported offline stores](../reference/offline-stores/README.md) for alternatives | +| **Compute Engine** | Spark, Ray (KubeRay), or Snowflake Engine | Distributed compute for materialization and historical retrieval at scale | + +**Networking & Security** + +| Component | Configuration | Notes | +|---|---|---| +| **Ingress** | TLS-terminated | Secure external access | +| **RBAC** | Kubernetes RBAC | Namespace-scoped permissions | +| **Secrets** | Kubernetes Secrets + `${ENV_VAR}` substitution | Store credentials via `secretRef` / `envFrom` in the FeatureStore CR; inject into `feature_store.yaml` with [environment variable syntax](./running-feast-in-production.md#5-using-environment-variables-in-your-yaml-configuration) | + +### Sample FeatureStore CR + +```yaml +apiVersion: feast.dev/v1 +kind: FeatureStore +metadata: + name: standard-production +spec: + feastProject: my_project + services: + scaling: + autoscaling: + minReplicas: 2 + maxReplicas: 10 # Set based on your peak load + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 70 + podDisruptionBudgets: + maxUnavailable: 1 + onlineStore: + persistence: + store: + type: redis + secretRef: + name: feast-online-store + server: + resources: + requests: + cpu: "1" + memory: 1Gi + limits: + cpu: "2" + memory: 2Gi + registry: + local: + persistence: + store: + type: sql + secretRef: + name: feast-registry-store + server: + resources: + requests: + cpu: 500m + memory: 512Mi + limits: + cpu: "1" + memory: 1Gi +``` + +{% hint style="success" %} +**Key features:** + +* **High availability** — multi-replica deployment with auto-injected pod anti-affinity and topology spread constraints +* **Scalable serving** — HPA adjusts the shared deployment replicas (all services scale together) based on demand +* **Secure external access** — TLS-terminated ingress with RBAC +* **Persistent storage** — Online Store (Redis Cluster shown as example; see [supported online stores](../reference/online-stores/README.md) for all options) + Offline Store (S3) for durability + +See [Horizontal Scaling with the Feast Operator](./scaling-feast.md#horizontal-scaling-with-the-feast-operator) for full scaling configuration details. +{% endhint %} + +--- + +## 3. Enterprise Production + +### When to use + +* Large organizations with multiple ML teams +* Multi-tenant environments requiring strict isolation +* High-scale deployments with governance, compliance, and SLA requirements + +### Architecture — Isolated Registries (per namespace) + +Each team gets its own registry and online feature server in a dedicated namespace. This provides the strongest isolation but has notable trade-offs: feature discovery is siloed per team (no cross-project visibility), and each registry requires its own [Feast UI](../reference/alpha-web-ui.md) deployment — you cannot view multiple projects in a single UI instance. + +```mermaid +graph TD + Client(["Clients / ML Services"]) -->|HTTPS| Gateway + + subgraph Kubernetes["Kubernetes"] + Gateway["API Gateway / Ingress
(TLS + rate limiting)"] + + subgraph NamespaceA["Namespace A — Team A"] + subgraph DeployA["Feast Deployment (HPA autoscaled)"] + RegistryA["Registry (SQL-backed)"] + FeatureServerA["Online Feature Server"] + end + end + + subgraph NamespaceB["Namespace B — Team B"] + subgraph DeployB["Feast Deployment (HPA autoscaled)"] + RegistryB["Registry (SQL-backed)"] + FeatureServerB["Online Feature Server"] + end + end + + Operator["Feast Operator
(cluster-scoped)"] + + Gateway --> FeatureServerA + Gateway --> FeatureServerB + Operator -->|manages| RegistryA + Operator -->|manages| FeatureServerA + Operator -->|manages| RegistryB + Operator -->|manages| FeatureServerB + end + + subgraph ManagedStores["Managed Online Stores"] + RedisA["Online Store
(e.g. Redis, DynamoDB, etc. — Team A)"] + RedisB["Online Store
(e.g. Redis, DynamoDB, etc. — Team B)"] + end + + subgraph ExternalSystems["External Systems"] + ObjectStore["Offline Store
(e.g. S3, Redshift, BigQuery, etc.)"] + DataWarehouse["Data Warehouse
(e.g. Snowflake / BigQuery)"] + Pipelines["Feature Pipelines
(Spark / Ray)"] + end + + subgraph Observability["Observability Stack"] + OTel["OpenTelemetry
(traces + metrics)"] + Prometheus["Prometheus"] + Grafana["Grafana"] + Jaeger["Jaeger"] + end + + FeatureServerA -->|reads/writes| RedisA + FeatureServerB -->|reads/writes| RedisB + FeatureServerA -->|reads| ObjectStore + FeatureServerB -->|reads| ObjectStore + FeatureServerA -->|reads| DataWarehouse + FeatureServerB -->|reads| DataWarehouse + Pipelines -->|materializes| RedisA + Pipelines -->|materializes| RedisB + + style Kubernetes fill:#f0f4ff,stroke:#3366cc,color:#000 + style NamespaceA fill:#e8f5e9,stroke:#388e3c,color:#000 + style NamespaceB fill:#e3f2fd,stroke:#1976d2,color:#000 + style DeployA fill:#c8e6c9,stroke:#2e7d32,color:#000 + style DeployB fill:#bbdefb,stroke:#1565c0,color:#000 + style ManagedStores fill:#fce4ec,stroke:#c62828,color:#000 + style ExternalSystems fill:#f3e5f5,stroke:#7b1fa2,color:#000 + style Observability fill:#fff3e0,stroke:#f57c00,color:#000 + style Gateway fill:#fff9c4,stroke:#f9a825,color:#000 + style Operator fill:#e8f5e9,stroke:#388e3c,color:#000 +``` + +### Architecture — Shared Registry (cross-namespace) + +Alternatively, a single centralized registry server can serve multiple tenant namespaces. Tenant online feature servers connect to the shared registry via the [Remote Registry](../reference/registries/remote.md) gRPC client. This reduces operational overhead, enables cross-team feature discovery, and allows a single [Feast UI](../reference/alpha-web-ui.md) deployment to browse all projects — while Feast [permissions](#feast-permissions-and-rbac) enforce tenant isolation at the data level. + +```mermaid +graph TD + Client(["Clients / ML Services"]) -->|HTTPS| Gateway + + subgraph Kubernetes["Kubernetes"] + Gateway["API Gateway / Ingress
(TLS + rate limiting)"] + + subgraph SharedInfra["Shared Infrastructure Namespace"] + Operator["Feast Operator
(cluster-scoped)"] + subgraph SharedDeploy["Feast Deployment (3 replicas)"] + SharedRegistry["Registry Server
(gRPC + REST)"] + end + SharedDB[("SQL Database
(PostgreSQL)")] + SharedRegistry -->|persists| SharedDB + end + + subgraph NamespaceA["Namespace A — Team A"] + subgraph DeployA2["Feast Deployment (HPA autoscaled)"] + FeatureServerA["Online Feature Server"] + end + ConfigA["registry_type: remote
path: shared-registry:6570"] + end + + subgraph NamespaceB["Namespace B — Team B"] + subgraph DeployB2["Feast Deployment (HPA autoscaled)"] + FeatureServerB["Online Feature Server"] + end + ConfigB["registry_type: remote
path: shared-registry:6570"] + end + + Gateway --> FeatureServerA + Gateway --> FeatureServerB + FeatureServerA -->|gRPC| SharedRegistry + FeatureServerB -->|gRPC| SharedRegistry + Operator -->|manages| SharedRegistry + Operator -->|manages| FeatureServerA + Operator -->|manages| FeatureServerB + end + + subgraph ManagedStores["Per-Tenant Online Stores"] + RedisA["Online Store
(e.g. Redis, DynamoDB, etc. — Team A)"] + RedisB["Online Store
(e.g. Redis, DynamoDB, etc. — Team B)"] + end + + FeatureServerA -->|reads/writes| RedisA + FeatureServerB -->|reads/writes| RedisB + + style Kubernetes fill:#f0f4ff,stroke:#3366cc,color:#000 + style SharedInfra fill:#fff3e0,stroke:#f57c00,color:#000 + style SharedDeploy fill:#ffe0b2,stroke:#e65100,color:#000 + style NamespaceA fill:#e8f5e9,stroke:#388e3c,color:#000 + style NamespaceB fill:#e3f2fd,stroke:#1976d2,color:#000 + style DeployA2 fill:#c8e6c9,stroke:#2e7d32,color:#000 + style DeployB2 fill:#bbdefb,stroke:#1565c0,color:#000 + style ManagedStores fill:#fce4ec,stroke:#c62828,color:#000 + style Gateway fill:#fff9c4,stroke:#f9a825,color:#000 + style Operator fill:#e8f5e9,stroke:#388e3c,color:#000 +``` + +**Shared registry client configuration** — each tenant's `feature_store.yaml` points to the centralized registry: + +```yaml +registry: + registry_type: remote + path: shared-registry.feast-system.svc.cluster.local:6570 +``` + +{% hint style="info" %} +**Shared vs isolated registries:** + +| | Shared Registry | Isolated Registries | +|---|---|---| +| **Feature discovery** | Cross-team — all projects visible | Siloed — each team sees only its own | +| **Feast UI** | Single deployment serves all projects | Separate UI deployment per registry | +| **Isolation** | Logical (Feast permissions + tags) | Physical (separate metadata stores) | +| **Operational cost** | Lower — one registry to manage | Higher — N registries to maintain | +| **Best for** | Feature reuse, shared ML platform | Regulatory/compliance separation | + +Use a shared registry when teams need to discover and reuse features across projects, and rely on Feast permissions for access control. Use isolated registries when regulatory or compliance requirements demand physical separation of metadata. +{% endhint %} + +### Components + +**Multi-tenancy** + +| Aspect | Configuration | Notes | +|---|---|---| +| **Isolation model** | Namespace-per-team | Physical isolation via Kubernetes namespaces | +| **Registry strategy** | Shared (remote) or isolated (per-namespace) | See architecture variants above | +| **Network boundaries** | NetworkPolicy enforced | Cross-namespace traffic denied by default (allow-listed for shared registry) | + +**Storage** + +| Component | Configuration | Notes | +|---|---|---| +| **Online Store** | Managed Redis / DynamoDB / Elasticsearch | Cloud-managed, per-tenant instances; see [supported online stores](../reference/online-stores/README.md) for all options | +| **Offline Store** | External data warehouse (Snowflake, BigQuery) | Shared or per-tenant access controls; see [supported offline stores](../reference/offline-stores/README.md) for all options | +| **Object Storage** | S3 with bucket policies | Tenant-scoped prefixes or buckets | + +**Scaling** + +| Component | Configuration | Notes | +|---|---|---| +| **FeatureStore Deployment** | HPA + Cluster Autoscaler | All services (Online Feature Server, Registry, Offline Feature Server) scale together per tenant; set `maxReplicas` based on your peak load. Independent scaling across tenants. | +| **Cluster** | Multi-zone node pools | Zone-aware scheduling with auto-injected topology spread constraints | + +**Security** + +| Component | Configuration | Notes | +|---|---|---| +| **Authentication** | OIDC via Keycloak | Centralized identity provider | +| **Authorization** | Feast permissions + Kubernetes RBAC | See [Permissions and RBAC](#feast-permissions-and-rbac) below | +| **Network** | NetworkPolicies per namespace | Microsegmentation | +| **Secrets** | Kubernetes Secrets (`secretRef` / `envFrom`) | Credentials injected via FeatureStore CR; use Kubernetes-native tooling (e.g. External Secrets Operator) to sync from external vaults if needed | + +**Observability** + +| Component | Purpose | Notes | +|---|---|---| +| **[OpenTelemetry](../getting-started/components/open-telemetry.md)** | Traces + metrics export | Built-in Feast integration; emits spans for feature retrieval, materialization, and registry operations | +| **Prometheus** | Metrics collection | Collects OpenTelemetry metrics from Online Feature Server + Online Store | +| **Grafana** | Dashboards + traces | Per-tenant and aggregate views; can display OpenTelemetry traces via Tempo or Jaeger data source | +| **Jaeger** | Distributed tracing | Visualize OpenTelemetry traces for request latency analysis and debugging | + +**Reliability & Disaster Recovery** + +| Aspect | Configuration | Notes | +|---|---|---| +| **PodDisruptionBudgets** | Configured per deployment | Protects against voluntary disruptions | +| **Multi-zone** | Topology spread constraints | Auto-injected by operator when scaling; survives single zone failures | +| **Backup / Restore** | See recovery priority below | Strategy depends on component criticality | + +**Recovery priority guidance** + +Not all Feast components carry the same recovery urgency. The table below ranks components by restoration priority and provides guidance for **RPO** (Recovery Point Objective — maximum acceptable data loss) and **RTO** (Recovery Time Objective — maximum acceptable downtime). Specific targets depend on your backing store SLAs and organizational requirements. + +| Priority | Component | RPO guidance | RTO guidance | Rationale | +|---|---|---|---|---| +| 1 — Critical | **Registry DB** (PostgreSQL / MySQL) | Minutes (continuous replication or frequent backups) | Minutes (failover to standby) | Contains all feature definitions and metadata; without it, no service can resolve features | +| 2 — High | **Online Store** (Redis / DynamoDB) | Reconstructible via materialization | Minutes to hours (depends on data volume) | Can be fully rebuilt by re-running materialization from the offline store; no unique data to lose | +| 3 — Medium | **Offline Store** (Redshift / BigQuery) | Per data warehouse SLA | Per data warehouse SLA | Source of truth for historical data; typically managed by the cloud provider with built-in replication | +| 4 — Low | **Feast Operator + CRDs** | N/A (declarative, stored in Git) | Minutes (re-apply manifests) | Stateless; redeployable from version-controlled manifests | + +{% hint style="info" %} +**Key insight:** The online store is *reconstructible* — it can always be rebuilt from the offline store by re-running materialization. This means its RPO is effectively zero (no unique data to lose), but RTO depends on how long full materialization takes for your dataset volume. For large datasets, consider maintaining Redis persistence (RDB snapshots or AOF) to reduce recovery time. +{% endhint %} + +**Backup recommendations by topology** + +| Topology | Registry | Online Store | Offline Store | +|---|---|---|---| +| **Minimal** | Manual file backups; accept downtime on failure | Not backed up (re-materialize) | N/A (file-based) | +| **Standard** | Automated PostgreSQL backups (daily + WAL archiving) | Redis RDB snapshots or AOF persistence | Per cloud provider SLA | +| **Enterprise** | Managed DB replication (multi-AZ); cross-region replicas for DR | Managed Redis with automatic failover (ElastiCache Multi-AZ, Memorystore HA) | Managed warehouse replication (Redshift cross-region, BigQuery cross-region) | + +### Sample FeatureStore CR (per tenant) + +```yaml +apiVersion: feast.dev/v1 +kind: FeatureStore +metadata: + name: team-a-production + namespace: team-a +spec: + feastProject: team_a + services: + scaling: + autoscaling: + minReplicas: 3 + maxReplicas: 20 # Set based on your peak load + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 65 + podDisruptionBudgets: + minAvailable: 2 + onlineStore: + persistence: + store: + type: redis + secretRef: + name: feast-online-store + server: + resources: + requests: + cpu: "2" + memory: 2Gi + limits: + cpu: "4" + memory: 4Gi + registry: + local: + persistence: + store: + type: sql + secretRef: + name: feast-registry-store + server: + resources: + requests: + cpu: "1" + memory: 1Gi + limits: + cpu: "2" + memory: 2Gi +``` + +--- + +## Feast Permissions and RBAC + +Feast provides a built-in permissions framework that secures resources at the application level, independently of Kubernetes RBAC. Permissions are defined as Python objects in your feature repository and registered via `feast apply`. + +For full details, see the [Permission concept](../getting-started/concepts/permission.md) and [RBAC architecture](../getting-started/architecture/rbac.md) docs. + +### How it works + +```mermaid +graph LR + subgraph Client["Client Request"] + Token["Auth Token
(OIDC / K8s SA)"] + end + + subgraph Server["Feast Server"] + Extractor["Token Extractor"] + Parser["Token Parser"] + Enforcer["Policy Enforcer"] + end + + subgraph Registry["Registry"] + Permissions["Permission Objects"] + end + + Token --> Extractor + Extractor --> Parser + Parser -->|user roles/groups/ns| Enforcer + Enforcer -->|match resource + action| Permissions + Enforcer -->|allow / deny| Response(["Response"]) + + style Client fill:#e3f2fd,stroke:#1976d2,color:#000 + style Server fill:#fff3e0,stroke:#f57c00,color:#000 + style Registry fill:#e8f5e9,stroke:#388e3c,color:#000 +``` + +Permission enforcement happens on the server side (Online Feature Server, Offline Feature Server, Registry Server). There is no enforcement when using the Feast SDK with a local provider. + +### Actions + +Feast defines eight granular actions: + +| Action | Description | +|---|---| +| `CREATE` | Create a new Feast object | +| `DESCRIBE` | Read object metadata/state | +| `UPDATE` | Modify an existing object | +| `DELETE` | Remove an object | +| `READ_ONLINE` | Read from the online store | +| `READ_OFFLINE` | Read from the offline store | +| `WRITE_ONLINE` | Write to the online store | +| `WRITE_OFFLINE` | Write to the offline store | + +Convenience aliases are provided: + +| Alias | Includes | +|---|---| +| `ALL_ACTIONS` | All eight actions | +| `READ` | `READ_ONLINE` + `READ_OFFLINE` | +| `WRITE` | `WRITE_ONLINE` + `WRITE_OFFLINE` | +| `CRUD` | `CREATE` + `DESCRIBE` + `UPDATE` + `DELETE` | + +### Protected resource types + +Permissions can be applied to any of these Feast object types: + +`Project`, `Entity`, `FeatureView`, `OnDemandFeatureView`, `BatchFeatureView`, `StreamFeatureView`, `FeatureService`, `DataSource`, `ValidationReference`, `SavedDataset`, `Permission` + +The constant `ALL_RESOURCE_TYPES` includes all of the above. `ALL_FEATURE_VIEW_TYPES` includes all feature view subtypes. + +### Policy types + +| Policy | Match criteria | Use case | +|---|---|---| +| `RoleBasedPolicy(roles=[...])` | User must have at least one of the listed roles | Kubernetes RBAC roles, OIDC roles | +| `GroupBasedPolicy(groups=[...])` | User must belong to at least one of the listed groups | LDAP/OIDC group membership | +| `NamespaceBasedPolicy(namespaces=[...])` | User's service account must be in one of the listed namespaces | Kubernetes namespace-level isolation | +| `CombinedGroupNamespacePolicy(groups=[...], namespaces=[...])` | User must match at least one group **or** one namespace | Flexible cross-cutting policies | +| `AllowAll` | Always grants access | Development / unsecured resources | + +### Example: Role-based permissions + +This is the most common pattern — separate admin and read-only roles: + +```python +from feast.feast_object import ALL_RESOURCE_TYPES +from feast.permissions.action import READ, ALL_ACTIONS, AuthzedAction +from feast.permissions.permission import Permission +from feast.permissions.policy import RoleBasedPolicy + +admin_perm = Permission( + name="feast_admin_permission", + types=ALL_RESOURCE_TYPES, + policy=RoleBasedPolicy(roles=["feast-admin-role"]), + actions=ALL_ACTIONS, +) + +user_perm = Permission( + name="feast_user_permission", + types=ALL_RESOURCE_TYPES, + policy=RoleBasedPolicy(roles=["feast-user-role"]), + actions=[AuthzedAction.DESCRIBE] + READ, +) +``` + +### Example: Namespace-based isolation for multi-tenant deployments + +Use `NamespaceBasedPolicy` to restrict access based on the Kubernetes namespace of the calling service account — ideal for the shared-registry enterprise topology: + +```python +from feast.feast_object import ALL_RESOURCE_TYPES +from feast.permissions.action import ALL_ACTIONS, READ, AuthzedAction +from feast.permissions.permission import Permission +from feast.permissions.policy import NamespaceBasedPolicy + +team_a_write = Permission( + name="team_a_full_access", + types=ALL_RESOURCE_TYPES, + required_tags={"team": "team-a"}, + policy=NamespaceBasedPolicy(namespaces=["team-a"]), + actions=ALL_ACTIONS, +) + +team_a_read_from_others = Permission( + name="team_a_read_shared", + types=ALL_RESOURCE_TYPES, + required_tags={"visibility": "shared"}, + policy=NamespaceBasedPolicy(namespaces=["team-a"]), + actions=[AuthzedAction.DESCRIBE] + READ, +) +``` + +### Example: Combined group + namespace policy + +For organizations that use both OIDC groups and Kubernetes namespaces for identity: + +```python +from feast.feast_object import ALL_RESOURCE_TYPES +from feast.permissions.action import ALL_ACTIONS, READ, AuthzedAction +from feast.permissions.permission import Permission +from feast.permissions.policy import CombinedGroupNamespacePolicy + +dev_test_perm = Permission( + name="dev_test_permission", + types=ALL_RESOURCE_TYPES, + policy=CombinedGroupNamespacePolicy( + groups=["dev-team", "developers"], + namespaces=["test", "staging"], + ), + actions=[AuthzedAction.DESCRIBE] + READ, +) + +data_staging_perm = Permission( + name="data_staging_permission", + types=ALL_RESOURCE_TYPES, + policy=CombinedGroupNamespacePolicy( + groups=["data-team", "ml-engineers"], + namespaces=["staging"], + ), + actions=ALL_ACTIONS, +) +``` + +### Example: Fine-grained resource filtering + +Permissions support `name_patterns` (regex) and `required_tags` for targeting specific resources: + +```python +from feast.feature_view import FeatureView +from feast.data_source import DataSource +from feast.permissions.action import AuthzedAction, READ +from feast.permissions.permission import Permission +from feast.permissions.policy import RoleBasedPolicy + +sensitive_fv_perm = Permission( + name="sensitive_feature_reader", + types=[FeatureView], + name_patterns=[".*sensitive.*", ".*pii.*"], + policy=RoleBasedPolicy(roles=["trusted-reader"]), + actions=[AuthzedAction.READ_OFFLINE], +) + +high_risk_ds_writer = Permission( + name="high_risk_ds_writer", + types=[DataSource], + required_tags={"risk_level": "high"}, + policy=RoleBasedPolicy(roles=["admin", "data_team"]), + actions=[AuthzedAction.WRITE_ONLINE, AuthzedAction.WRITE_OFFLINE], +) +``` + +### Authorization configuration + +Enable auth enforcement in `feature_store.yaml`: + +```yaml +auth: + type: kubernetes # or: oidc +``` + +For OIDC: + +```yaml +auth: + type: oidc + client_id: feast-client + auth_server_url: https://keycloak.example.com/realms/feast + auth_discovery_url: https://keycloak.example.com/realms/feast/.well-known/openid-configuration +``` + +{% hint style="warning" %} +**Permission granting order:** Feast uses an *affirmative* decision strategy — if **any** matching permission grants access, the request is allowed. Access is denied only when **all** matching permissions deny the user. If no permission matches a resource + action combination, access is **denied**. Resources that do not match any configured permission are unsecured. Always define explicit coverage for all critical resources. +{% endhint %} + +### Recommended RBAC by topology + +| Topology | Auth type | Policy type | Guidance | +|---|---|---|---| +| **Minimal** | `no_auth` or `kubernetes` | `RoleBasedPolicy` | Basic admin/reader roles | +| **Standard** | `kubernetes` | `RoleBasedPolicy` | K8s service account roles | +| **Enterprise (isolated)** | `oidc` or `kubernetes` | `RoleBasedPolicy` + `GroupBasedPolicy` | Per-team OIDC groups | +| **Enterprise (shared registry)** | `kubernetes` | `NamespaceBasedPolicy` or `CombinedGroupNamespacePolicy` | Namespace isolation with tag-based resource scoping | + +--- + +## Infrastructure-Specific Recommendations + +Choosing the right online store, offline store, and registry backend depends on your cloud environment and existing infrastructure. The table below maps common deployment environments to recommended Feast components. + +### Recommendation matrix + +```mermaid +graph TD + subgraph AWS["AWS / EKS / ROSA"] + A_Online["Online: ElastiCache Redis
or DynamoDB"] + A_Offline["Offline: Redshift
or Snowflake or Athena"] + A_Registry["Registry: RDS PostgreSQL (SQL)
or S3"] + A_Compute["Compute: Snowflake Engine
or Spark on EMR
or Ray (KubeRay)"] + end + + subgraph GCP["GCP / GKE"] + G_Online["Online: Memorystore Redis
or Bigtable or Datastore"] + G_Offline["Offline: BigQuery
or Snowflake"] + G_Registry["Registry: Cloud SQL PostgreSQL
or GCS"] + G_Compute["Compute: Snowflake Engine
or Spark on Dataproc
or Ray (KubeRay)"] + end + + subgraph OnPrem["On-Premise / OpenShift"] + O_Online["Online: Redis
or PostgreSQL"] + O_Offline["Offline: Spark + MinIO
or PostgreSQL or Trino or Oracle"] + O_Registry["Registry: PostgreSQL (SQL)"] + O_Compute["Compute: Spark
or Ray (KubeRay)"] + end + + style AWS fill:#fff3e0,stroke:#f57c00,color:#000 + style GCP fill:#e3f2fd,stroke:#1976d2,color:#000 + style OnPrem fill:#e8f5e9,stroke:#388e3c,color:#000 +``` + +### AWS / EKS / ROSA + +| Component | Recommended | Alternative | Notes | +|---|---|---|---| +| **Online Store** | **Redis** (ElastiCache) | DynamoDB | Redis offers TTL at retrieval, concurrent writes, Java/Go SDK support. DynamoDB is fully managed with zero ops. | +| **Offline Store** | **Redshift** | Snowflake, Athena (contrib), Spark | Redshift is the core AWS offline store. Use Snowflake if it's already your warehouse. Athena for S3-native query patterns. | +| **Registry** | **SQL** (RDS PostgreSQL) | S3 | SQL registry required for concurrent materialization writers. S3 registry is simpler but limited to single-writer. | +| **Compute Engine** | **Snowflake Engine** | Spark on EMR, [Ray (KubeRay)](../reference/compute-engine/ray.md) | Snowflake engine when your offline/online stores are Snowflake. Spark for S3-based pipelines. Ray with KubeRay for Kubernetes-native distributed processing. | +| **Object Storage** | S3 | — | Feature repo, training data, registry artifacts | + +{% hint style="info" %} +**ROSA (Red Hat OpenShift on AWS):** Same store recommendations as EKS. Use OpenShift Routes instead of Ingress for TLS termination. Leverage OpenShift's built-in OAuth for `auth.type: kubernetes` integration. +{% endhint %} + +### GCP / GKE + +| Component | Recommended | Alternative | Notes | +|---|---|---|---| +| **Online Store** | **Redis** (Memorystore) | Bigtable, Datastore | Redis for latency-sensitive workloads. Bigtable for very large-scale feature storage. Datastore is GCP-native and zero-ops. | +| **Offline Store** | **BigQuery** | Snowflake, Spark (Dataproc) | BigQuery is the core GCP offline store with full feature support. | +| **Registry** | **SQL** (Cloud SQL PostgreSQL) | GCS | SQL for multi-writer. GCS for simple single-writer setups. | +| **Compute Engine** | **Snowflake Engine** | Spark on Dataproc, [Ray (KubeRay)](../reference/compute-engine/ray.md) | Use Snowflake engine if your offline store is Snowflake. Spark for BigQuery + GCS pipelines. Ray with KubeRay for Kubernetes-native distributed processing. | +| **Object Storage** | GCS | — | Feature repo, training data | + +### On-Premise / OpenShift / Self-Managed Kubernetes + +| Component | Recommended | Alternative | Notes | +|---|---|---|---| +| **Online Store** | **Redis** (self-managed or operator) | PostgreSQL (contrib) | Redis for best performance. PostgreSQL if you want to minimize infrastructure components. | +| **Offline Store** | **Spark** + MinIO (contrib) | PostgreSQL (contrib), Trino (contrib), Oracle (contrib), DuckDB | Spark for scale. PostgreSQL for simpler setups. Oracle for enterprise customers with existing Oracle infrastructure. DuckDB for development only. | +| **Registry** | **SQL** (PostgreSQL) | — | Always use SQL registry in production on-prem. File-based registries do not support concurrent writers. | +| **Compute Engine** | **Spark** | [Ray (KubeRay)](../reference/compute-engine/ray.md) | Run Spark on Kubernetes or standalone. Ray with KubeRay for Kubernetes-native distributed DAG execution. | +| **Object Storage** | MinIO (S3-compatible) | Ceph, NFS | S3-compatible storage for feature data and artifacts. | + +{% hint style="warning" %} +**Multi-replica constraint:** When scaling any Feast service to multiple replicas (via the Feast Operator), you **must** use database-backed persistence for all enabled services. File-based stores (SQLite, DuckDB, `registry.db`) are incompatible with multi-replica deployments. See [Scaling Feast](./scaling-feast.md#horizontal-scaling-with-the-feast-operator) for details. +{% endhint %} + +--- + +## Air-Gapped / Disconnected Environment Deployments + +Production environments in regulated industries (finance, government, defense) often have no outbound internet access from the Kubernetes cluster. The Feast Operator supports air-gapped deployments through custom container images, init container controls, and standard Kubernetes image-pull mechanisms. + +### Default init container behavior + +When `feastProjectDir` is set on the FeatureStore CR, the operator creates up to two init containers: + +1. **`feast-init`** — bootstraps the feature repository by running either `git clone` (if `feastProjectDir.git` is set) or `feast init` (if `feastProjectDir.init` is set), then writes the generated `feature_store.yaml` into the repo directory. +2. **`feast-apply`** — runs `feast apply` to register feature definitions in the registry. Controlled by `runFeastApplyOnInit` (defaults to `true`). Skipped when `disableInitContainers` is `true`. + +In air-gapped environments, `git clone` will fail because the cluster cannot reach external Git repositories. The solution is to **pre-bake** the feature repository into a custom container image and disable the init containers entirely. + +### Air-gapped deployment workflow + +```mermaid +graph TD + subgraph BuildEnv["Build Environment (internet access)"] + Code["Feature repo source code"] + Base["Base Feast image
(feastdev/feature-server)"] + Custom["Custom image with
bundled feature repo"] + Code --> Custom + Base --> Custom + end + + subgraph InternalRegistry["Internal Container Registry"] + Mirror["registry.internal.example.com
/feast/feature-server:v0.61"] + end + + subgraph AirGappedCluster["Air-Gapped Kubernetes Cluster"] + SA["ServiceAccount
(imagePullSecrets)"] + CR["FeatureStore CR
disableInitContainers: true
image: registry.internal..."] + Deploy["Feast Deployment
(no init containers)"] + SA --> Deploy + CR --> Deploy + end + + Custom -->|push| Mirror + Mirror -->|pull| Deploy +``` + +**Steps:** + +1. **Build a custom container image** that bundles the feature repository and all Python dependencies into the Feast base image. +2. **Push** the image to your internal container registry. +3. **Set `services.disableInitContainers: true`** on the FeatureStore CR to skip `git clone` / `feast init` and `feast apply`. +4. **Override the image** on each service using the per-service `image` field. +5. **Set `imagePullPolicy: IfNotPresent`** (or `Never` if images are pre-loaded on nodes). +6. **Configure `imagePullSecrets`** on the namespace's ServiceAccount — the FeatureStore CRD does not expose an `imagePullSecrets` field, so use the standard Kubernetes approach of attaching secrets to the ServiceAccount that the pods run under. + +### Sample FeatureStore CR (air-gapped) + +```yaml +apiVersion: feast.dev/v1 +kind: FeatureStore +metadata: + name: airgap-production +spec: + feastProject: my_project + services: + disableInitContainers: true + onlineStore: + persistence: + store: + type: redis + secretRef: + name: feast-online-store + server: + image: registry.internal.example.com/feast/feature-server:v0.61 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: "1" + memory: 1Gi + limits: + cpu: "2" + memory: 2Gi + registry: + local: + persistence: + store: + type: sql + secretRef: + name: feast-registry-store + server: + image: registry.internal.example.com/feast/feature-server:v0.61 + imagePullPolicy: IfNotPresent +``` + +{% hint style="info" %} +**Pre-populating the registry:** With init containers disabled, `feast apply` does not run on pod startup. You can populate the registry by: + +1. **Running `feast apply` from your CI/CD pipeline** that has network access to the registry DB. +2. **Using the FeatureStore CR's built-in CronJob** (`spec.cronJob`) — the operator creates a Kubernetes CronJob that runs `feast apply` and `feast materialize-incremental` on a schedule. The CronJob runs inside the cluster (no external access needed) and can use a custom image just like the main deployment. This is the recommended approach for air-gapped environments. +3. **Running `feast apply` manually** from the build environment before deploying the CR. +{% endhint %} + +### Air-gapped deployment checklist + +{% hint style="warning" %} +**Pre-stage the following artifacts before deploying Feast in an air-gapped environment:** + +* **Container images** — Feast feature server image (with bundled feature repo) pushed to internal registry +* **CRD manifests** — Feast Operator CRDs and operator deployment manifests available locally +* **Store credentials** — Kubernetes Secrets for online store, offline store, and registry DB connections created in the target namespace +* **Python packages** (if using custom on-demand transforms) — bundled into the custom image or available from an internal PyPI mirror +* **ServiceAccount configuration** — `imagePullSecrets` attached to the ServiceAccount used by the Feast deployment +{% endhint %} + +--- + +## Hybrid Store Configuration + +The hybrid store feature allows a single Feast deployment to route feature operations to multiple backends based on tags or data sources. This is useful when different feature views have different latency, cost, or compliance requirements. + +### Hybrid online store + +The `HybridOnlineStore` routes online operations to different backends based on a configurable tag on the `FeatureView`. + +```mermaid +graph LR + FS["Online Feature Server"] --> Router["HybridOnlineStore
(routes by tag)"] + Router -->|"tag: dynamodb"| DDB["DynamoDB"] + Router -->|"tag: redis"| RD["Redis"] + + style Router fill:#fff3e0,stroke:#f57c00,color:#000 + style DDB fill:#e3f2fd,stroke:#1976d2,color:#000 + style RD fill:#fce4ec,stroke:#c62828,color:#000 +``` + +**`feature_store.yaml` configuration:** + +```yaml +project: my_feature_repo +registry: data/registry.db +provider: local +online_store: + type: hybrid + routing_tag: team + online_stores: + - type: dynamodb + conf: + region: us-east-1 + - type: redis + conf: + connection_string: "redis-cluster:6379" + redis_type: redis_cluster +``` + +**Feature view with routing tag:** + +```python +from feast import FeatureView + +user_features = FeatureView( + name="user_features", + entities=[user_entity], + source=user_source, + tags={"team": "dynamodb"}, # Routes to DynamoDB backend +) + +transaction_features = FeatureView( + name="transaction_features", + entities=[txn_entity], + source=txn_source, + tags={"team": "redis"}, # Routes to Redis backend +) +``` + +The tag value must match the online store `type` name (e.g. `dynamodb`, `redis`, `bigtable`). + +### Hybrid offline store + +The `HybridOfflineStore` routes offline operations to different backends based on the `batch_source` type of each `FeatureView`. + +```mermaid +graph LR + Client["Materialization /
Training Job"] --> Router["HybridOfflineStore
(routes by source type)"] + Router -->|"SparkSource"| Spark["Spark"] + Router -->|"RedshiftSource"| RS["Redshift"] + + style Router fill:#fff3e0,stroke:#f57c00,color:#000 + style Spark fill:#e8f5e9,stroke:#388e3c,color:#000 + style RS fill:#e3f2fd,stroke:#1976d2,color:#000 +``` + +**`feature_store.yaml` configuration:** + +```yaml +project: my_feature_repo +registry: data/registry.db +provider: local +offline_store: + type: hybrid_offline_store.HybridOfflineStore + offline_stores: + - type: spark + conf: + spark_master: local[*] + spark_app_name: feast_spark_app + - type: redshift + conf: + cluster_id: my-redshift-cluster + region: us-east-1 + database: feast_db + user: feast_user + s3_staging_location: s3://my-bucket/feast-staging + iam_role: arn:aws:iam::123456789012:role/FeastRedshiftRole +``` + +**Feature views with different sources:** + +```python +from feast import FeatureView, Entity, ValueType +from feast.infra.offline_stores.contrib.spark_offline_store.spark_source import SparkSource +from feast.infra.offline_stores.redshift_source import RedshiftSource + +user_features = FeatureView( + name="user_features", + entities=[user_entity], + source=SparkSource(path="s3://bucket/user_features"), # Routes to Spark +) + +activity_features = FeatureView( + name="user_activity", + entities=[user_entity], + source=RedshiftSource( # Routes to Redshift + table="user_activity", + event_timestamp_column="event_ts", + ), +) +``` + +{% hint style="warning" %} +**Hybrid offline store constraint:** `get_historical_features` requires all requested feature views to share the same `batch_source` type within a single call. You cannot join features across different offline engines in one retrieval request. +{% endhint %} + +--- + +## Performance Considerations + +For detailed server-level tuning (worker counts, timeouts, keep-alive, etc.), see the [Online Server Performance Tuning](./online-server-performance-tuning.md) guide. + +### Online feature server sizing + +| Traffic tier | Replicas | CPU (per pod) | Memory (per pod) | Notes | +|---|---|---|---|---| +| Low (<100 RPS) | 1–2 | 500m–1 | 512Mi–1Gi | Minimal production | +| Medium (100–1000 RPS) | 2–5 (HPA) | 1–2 | 1–2Gi | Standard production | +| High (>1000 RPS) | 5–20 (HPA) | 2–4 | 2–4Gi | Enterprise, per-tenant | + +### Online store latency guidelines + +| Store | p50 latency | p99 latency | Best for | +|---|---|---|---| +| **Redis** (single) | <1ms | <5ms | Lowest latency, small-medium datasets | +| **Redis Cluster** | <2ms | <10ms | High availability + low latency | +| **DynamoDB** | <5ms | <20ms | Serverless, variable traffic | +| **PostgreSQL** | <5ms | <30ms | On-prem, simplicity | +| **Remote (HTTP)** | <10ms | <50ms | Client-server separation | + +### Connection pooling for remote online store + +When using the [Remote Online Store](../reference/online-stores/remote.md) (client-server architecture), connection pooling significantly reduces latency by reusing TCP/TLS connections: + +```yaml +online_store: + type: remote + path: http://feast-feature-server:80 + connection_pool_size: 50 # Max connections in pool (default: 50) + connection_idle_timeout: 300 # Idle timeout in seconds (default: 300) + connection_retries: 3 # Retry count with exponential backoff +``` + +**Tuning by workload:** + +| Workload | `connection_pool_size` | `connection_idle_timeout` | `connection_retries` | +|---|---|---|---| +| High-throughput inference | 100 | 600 | 5 | +| Long-running batch service | 50 | 0 (never close) | 3 | +| Resource-constrained edge | 10 | 60 | 2 | + +### Registry performance + +* **SQL registry** (PostgreSQL, MySQL) is required for concurrent materialization jobs writing to the registry simultaneously. +* **File-based registries** (S3, GCS, local) serialize the entire registry on each write — suitable only for single-writer scenarios. +* For read-heavy workloads, scale the Registry Server to multiple replicas (all connecting to the same database). + +### Registry cache tuning at scale + +Each Feast server pod maintains its own in-memory copy of the registry metadata. With multiple Gunicorn workers per pod, the total number of independent registry copies is **replicas x workers**. For example, 5 replicas with 4 workers each means 20 copies of the registry in memory, each refreshing independently. + +With the default `cache_mode: sync`, the refresh is **synchronous** — when the TTL expires, the next request blocks until the full registry is re-downloaded. At scale, this causes periodic latency spikes across multiple pods simultaneously. + +**Recommendation:** Use `cache_mode: thread` with a higher TTL in production to avoid refresh storms: + +```yaml +# In the Operator secret for SQL/DB-backed registries: +registry: + registry_type: sql + path: postgresql://:@:5432/feast + cache_mode: thread + cache_ttl_seconds: 300 +``` + +For the server-side refresh interval, set `registryTTLSeconds` on the CR: + +```yaml +spec: + services: + onlineStore: + server: + workerConfigs: + registryTTLSeconds: 300 +``` + +| Scenario | `cache_mode` | `cache_ttl_seconds` | `registryTTLSeconds` | +|---|---|---|---| +| Development / iteration | `sync` (default) | 5–10 | 5 | +| Production (low-latency) | `thread` | 300 | 300 | +| Production (frequent schema changes) | `thread` | 60 | 60 | + +{% hint style="info" %} +`registryTTLSeconds` on the CR controls the **server-side** refresh interval. `cache_ttl_seconds` in the registry secret controls the **SDK client** refresh. In Operator deployments, the CR field is what matters for serving performance. For a deep dive into sync vs thread mode trade-offs, memory impact, and freshness considerations, see the [Registry Cache Tuning](./online-server-performance-tuning.md#registry-cache-tuning) section in the performance tuning guide. +{% endhint %} + +### Materialization performance + +| Data volume | Recommended engine | Notes | +|---|---|---| +| <1M rows | In-process (default) | Simple, no external dependencies | +| 1M–100M rows | Snowflake Engine, Spark, or Ray | Distributed processing | +| >100M rows | Spark on Kubernetes / EMR / Dataproc, or Ray via KubeRay | Full cluster-scale materialization with distributed DAG execution | + +For detailed engine configuration, see [Scaling Materialization](./scaling-feast.md#scaling-materialization). + +### Redis sizing guidelines + +| Metric | Guideline | +|---|---| +| **Memory** | ~100 bytes per feature value (varies by data type). For 1M entities x 50 features = ~5GB. | +| **Connections** | Each online feature server replica opens a connection pool. Plan for `replicas x pool_size`. | +| **TTL** | Set `key_ttl_seconds` in `feature_store.yaml` to auto-expire stale data and bound memory usage. | +| **Cluster mode** | Use Redis Cluster for >25GB datasets or >10K connections. | + +--- + +## Design Principles + +Understanding the following principles helps you choose and customize the right topology. + +### Control plane vs data plane + +```mermaid +graph LR + subgraph ControlPlane["Control Plane"] + Operator["Feast Operator"] + Registry["Registry Server"] + end + + subgraph DataPlane["Data Plane"] + OnlineServer["Online Feature Server"] + OfflineServer["Offline Feature Server"] + end + + subgraph BackingStores["Backing Stores (external)"] + OnlineStore["Online Store
(e.g. Redis, DynamoDB, PostgreSQL, etc.)"] + OfflineStore["Offline Store
(e.g. Redshift, BigQuery, Spark, etc.)"] + RegistryDB["Registry DB
(PostgreSQL / MySQL)"] + end + + ControlPlane -->|configures| DataPlane + DataPlane -->|reports status| ControlPlane + OnlineServer --> OnlineStore + OfflineServer --> OfflineStore + Registry --> RegistryDB + + style ControlPlane fill:#e8f5e9,stroke:#388e3c,color:#000 + style DataPlane fill:#e3f2fd,stroke:#1976d2,color:#000 + style BackingStores fill:#fce4ec,stroke:#c62828,color:#000 +``` + +* **Control plane** (Operator + Registry Server) manages feature definitions, metadata, and lifecycle. It changes infrequently and should be highly available. +* **Data plane** (Online Feature Server + Offline Feature Server) handles the actual feature reads/writes at request time. It must scale with traffic. +* **Backing stores** (databases, object storage) hold the actual data. These are stateful and managed independently. + +### Stateless vs stateful components + +The Feast Operator deploys all Feast services (Online Feature Server, Offline Feature Server, Registry Server) in a **single shared Deployment**. When scaling (`spec.replicas > 1` or HPA autoscaling), all services scale together. + +{% hint style="warning" %} +**Scaling requires DB-backed persistence for all enabled services.** The operator enforces this via CRD validation: + +* **Online Store** — must use DB persistence (e.g. `type: redis`, `type: dynamodb`, `type: postgres`) +* **Offline Store** — if enabled, must use DB persistence (e.g. `type: redshift`, `type: bigquery`, `type: spark`, `type: postgres`) +* **Registry** — must use SQL persistence (`type: sql`), a remote registry, or S3/GCS file-backed registry + +File-based stores (SQLite, DuckDB, `registry.db`) are **rejected** when `replicas > 1` or autoscaling is configured. +{% endhint %} + +| Component | Type | Scaling | DB-backed requirement | +|---|---|---|---| +| Online Feature Server | **Stateless** (server) | Scales with the shared Deployment (HPA or `spec.replicas`) | Online store must use DB persistence (e.g. Redis, DynamoDB, PostgreSQL) | +| Offline Feature Server | **Stateless** (server) | Scales with the shared Deployment (HPA or `spec.replicas`) | Offline store must use DB persistence (e.g. Redshift, BigQuery, Spark, PostgreSQL) | +| Registry Server | **Stateless** (server) | Scales with the shared Deployment (HPA or `spec.replicas`) | Registry must use SQL, remote, or S3/GCS persistence | +| Online Store (Redis, DynamoDB, etc.) | **Stateful** (backing store) | Scale via managed service or clustering | Managed independently of Feast services | +| Offline Store (Redshift, BigQuery, etc.) | **Stateful** (backing store) | Scale via cloud-managed infrastructure | Managed independently of Feast services | +| Registry DB (PostgreSQL, MySQL) | **Stateful** (backing store) | Scale via managed database service | Managed independently of Feast services | + +### Scalability guidelines + +```mermaid +graph TD + Read["Read traffic increase"] -->|scale| FS["Online Feature Server replicas (HPA)"] + Write["Write / materialization load"] -->|scale| Engine["Compute Engine
(Spark / Ray / Snowflake)"] + Storage["Data volume growth"] -->|scale| Store["Online / Offline Store capacity"] + + FS -.- Independent["Scale independently"] + Engine -.- Independent + Store -.- Independent + + style Read fill:#e3f2fd,stroke:#1976d2,color:#000 + style Write fill:#fff3e0,stroke:#f57c00,color:#000 + style Storage fill:#f3e5f5,stroke:#7b1fa2,color:#000 + style FS fill:#e3f2fd,stroke:#1976d2,color:#000 + style Engine fill:#fff3e0,stroke:#f57c00,color:#000 + style Store fill:#f3e5f5,stroke:#7b1fa2,color:#000 +``` + +* **Read scaling** — increase Online Feature Server replicas; they are stateless and scale linearly. +* **Write scaling** — use a distributed compute engine ([Spark](../reference/compute-engine/spark.md), [Ray/KubeRay](../reference/compute-engine/ray.md), or [Snowflake](../reference/compute-engine/snowflake.md)) for materialization. +* **Storage scaling** — scale online and offline stores independently based on data volume and query patterns. + +For detailed scaling configuration, see [Scaling Feast](./scaling-feast.md). + +--- + +## Topology Comparison + +| Capability | Minimal | Standard | Enterprise | +|---|:---:|:---:|:---:| +| **High availability** | No | Yes | Yes | +| **Autoscaling** | No | HPA | HPA + Cluster Autoscaler | +| **TLS / Ingress** | No | Yes | Yes + API Gateway | +| **RBAC** | No | Kubernetes RBAC | OIDC + fine-grained RBAC | +| **Multi-tenancy** | No | No | Namespace-per-team | +| **Shared registry** | N/A | N/A | Optional (remote registry) | +| **Hybrid stores** | No | Optional | Recommended for mixed backends | +| **Observability** | Logs only | Basic metrics | OpenTelemetry + Prometheus + Grafana + Jaeger | +| **Disaster recovery** | No | Partial | Full backup/restore | +| **Network policies** | No | Optional | Enforced | +| **Recommended team size** | 1–3 | 3–15 | 15+ | + +--- + +## Next Steps + +* [Feast on Kubernetes](./feast-on-kubernetes.md) — install the Feast Operator and deploy your first FeatureStore CR +* [Scaling Feast](./scaling-feast.md) — detailed HPA, registry scaling, and materialization engine configuration +* [Online Server Performance Tuning](./online-server-performance-tuning.md) — worker counts, timeouts, keep-alive, and server-level tuning +* [Starting Feast Servers in TLS Mode](./starting-feast-servers-tls-mode.md) — enable TLS for secure communication +* [Running Feast in Production](./running-feast-in-production.md) — CI/CD, materialization scheduling, and model serving patterns +* [Multi-Team Feature Store Setup](./federated-feature-store.md) — federated feature store for multi-team environments +* [Permission Concepts](../getting-started/concepts/permission.md) — full permission model reference +* [RBAC Architecture](../getting-started/architecture/rbac.md) — authorization architecture details +* [OpenTelemetry Integration](../getting-started/components/open-telemetry.md) — traces and metrics for Feast servers +* [Hybrid Online Store](../reference/online-stores/hybrid.md) — hybrid online store configuration reference +* [Hybrid Offline Store](../reference/offline-stores/hybrid.md) — hybrid offline store configuration reference diff --git a/docs/how-to-guides/running-feast-in-production.md b/docs/how-to-guides/running-feast-in-production.md index be6fd2afeb4..f073c92931f 100644 --- a/docs/how-to-guides/running-feast-in-production.md +++ b/docs/how-to-guides/running-feast-in-production.md @@ -18,6 +18,10 @@ For example, you might not have a stream source and, thus, no need to write feat Additionally, please check the how-to guide for some specific recommendations on [how to scale Feast](./scaling-feast.md). {% endhint %} +{% hint style="info" %} +**Looking for production deployment patterns?** See the [Feast Production Deployment Topologies](./production-deployment-topologies.md) guide for three Kubernetes-ready topologies (Minimal, Standard, Enterprise), sample FeatureStore CRs, RBAC policies, infrastructure recommendations, and scaling best practices. +{% endhint %} + In this guide we will show you how to: 1. Deploy your feature store and keep your infrastructure in sync with your feature repository diff --git a/docs/how-to-guides/scaling-feast.md b/docs/how-to-guides/scaling-feast.md index d0bd6aef8a0..5982f917674 100644 --- a/docs/how-to-guides/scaling-feast.md +++ b/docs/how-to-guides/scaling-feast.md @@ -23,4 +23,226 @@ However, this process does not scale for large data sets, since it's executed on Feast supports pluggable [Compute Engines](../getting-started/components/compute-engine.md), that allow the materialization process to be scaled up. Aside from the local process, Feast supports a [Lambda-based materialization engine](https://rtd.feast.dev/en/master/#alpha-lambda-based-engine), and a [Bytewax-based materialization engine](https://rtd.feast.dev/en/master/#bytewax-engine). -Users may also be able to build an engine to scale up materialization using existing infrastructure in their organizations. \ No newline at end of file +Users may also be able to build an engine to scale up materialization using existing infrastructure in their organizations. + +### Horizontal Scaling with the Feast Operator + +When running Feast on Kubernetes with the [Feast Operator](./feast-on-kubernetes.md), you can horizontally scale the FeatureStore deployment using `spec.replicas` or HPA autoscaling. The FeatureStore CRD implements the Kubernetes [scale sub-resource](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#scale-subresource), so you can also use `kubectl scale`: + +```bash +kubectl scale featurestore/my-feast --replicas=3 +``` + +**Prerequisites:** Horizontal scaling requires **DB-backed persistence** for all enabled services (online store, offline store, and registry). File-based persistence (SQLite, DuckDB, `registry.db`) is incompatible with multiple replicas because these backends do not support concurrent access from multiple pods. + +#### Static Replicas + +Set a fixed number of replicas via `spec.replicas`: + +```yaml +apiVersion: feast.dev/v1 +kind: FeatureStore +metadata: + name: sample-scaling +spec: + feastProject: my_project + replicas: 3 + services: + onlineStore: + persistence: + store: + type: postgres + secretRef: + name: feast-data-stores + registry: + local: + persistence: + store: + type: sql + secretRef: + name: feast-data-stores +``` + +#### Autoscaling with HPA + +Configure a HorizontalPodAutoscaler to dynamically scale based on metrics. HPA autoscaling is configured under `services.scaling.autoscaling` and is mutually exclusive with `spec.replicas > 1`: + +```yaml +apiVersion: feast.dev/v1 +kind: FeatureStore +metadata: + name: sample-autoscaling +spec: + feastProject: my_project + services: + scaling: + autoscaling: + minReplicas: 2 + maxReplicas: 10 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 70 + podDisruptionBudgets: + maxUnavailable: 1 + onlineStore: + persistence: + store: + type: postgres + secretRef: + name: feast-data-stores + server: + resources: + requests: + cpu: 200m + memory: 256Mi + registry: + local: + persistence: + store: + type: sql + secretRef: + name: feast-data-stores +``` + +{% hint style="info" %} +When autoscaling is configured, the operator automatically sets the deployment strategy to `RollingUpdate` (instead of the default `Recreate`) to ensure zero-downtime scaling, and auto-injects soft pod anti-affinity and zone topology spread constraints. You can override any of these by explicitly setting `deploymentStrategy`, `affinity`, or `topologySpreadConstraints` in the CR. +{% endhint %} + +#### Validation Rules + +The operator enforces the following rules: +- `spec.replicas > 1` and `services.scaling.autoscaling` are **mutually exclusive** -- you cannot set both. +- Scaling with `replicas > 1` or any `autoscaling` config is **rejected** if any enabled service uses file-based persistence. +- S3 (`s3://`) and GCS (`gs://`) backed registry file persistence is allowed with scaling, since these object stores support concurrent readers. + +#### High Availability + +When scaling is enabled (`replicas > 1` or `autoscaling`), the operator provides HA features to improve resilience: + +**Pod Anti-Affinity** — The operator automatically injects a soft (`preferredDuringSchedulingIgnoredDuringExecution`) pod anti-affinity rule that prefers spreading pods across different nodes. This prevents multiple replicas from being co-located on the same node, improving resilience to node failures. You can override this by providing your own `affinity` configuration: + +```yaml +spec: + replicas: 3 + services: + # Override with custom affinity (e.g. strict anti-affinity) + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + feast.dev/name: my-feast + # ... +``` + +**Topology Spread Constraints** — The operator automatically injects a soft zone-spread constraint (`whenUnsatisfiable: ScheduleAnyway`) that distributes pods across availability zones. This is a best-effort spread — if zones are unavailable, pods will still be scheduled. You can override this with explicit constraints or disable it with an empty array: + +```yaml +spec: + replicas: 3 + services: + # Override with custom topology spread (e.g. strict zone spreading) + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: DoNotSchedule + labelSelector: + matchLabels: + feast.dev/name: my-feast + # ... +``` + +To disable the auto-injected topology spread: + +```yaml +spec: + replicas: 3 + services: + topologySpreadConstraints: [] + # ... +``` + +**PodDisruptionBudget** — You can configure a PDB to limit voluntary disruptions (e.g. during node drains or cluster upgrades). The PDB is only created when scaling is enabled. Exactly one of `minAvailable` or `maxUnavailable` must be set: + +```yaml +spec: + replicas: 3 + services: + podDisruptionBudgets: + maxUnavailable: 1 # at most 1 pod unavailable during disruptions + # -- OR -- + # podDisruptionBudgets: + # minAvailable: "50%" # at least 50% of pods must remain available + # ... +``` + +{% hint style="info" %} +The PDB is not auto-injected — you must explicitly configure it. This is intentional because a misconfigured PDB (e.g. `minAvailable` equal to the replica count) can block node drains and cluster upgrades. +{% endhint %} + +#### Using KEDA (Kubernetes Event-Driven Autoscaling) + +[KEDA](https://keda.sh) is also supported as an external autoscaler. KEDA should target the FeatureStore's scale sub-resource directly (since it implements the Kubernetes scale API). This is the recommended approach because the operator manages the Deployment's replica count from `spec.replicas` — targeting the Deployment directly would conflict with the operator's reconciliation. + +When using KEDA, do **not** set `scaling.autoscaling` or `spec.replicas > 1` -- KEDA manages the replica count through the scale sub-resource. + +1. **Ensure DB-backed persistence** -- The CRD's CEL validation rules automatically enforce DB-backed persistence when KEDA scales `spec.replicas` above 1 via the scale sub-resource. The operator also automatically switches the deployment strategy to `RollingUpdate` when `replicas > 1`. + +2. **Configure the FeatureStore** with DB-backed persistence: + +```yaml +apiVersion: feast.dev/v1 +kind: FeatureStore +metadata: + name: sample-keda +spec: + feastProject: my_project + services: + onlineStore: + persistence: + store: + type: postgres + secretRef: + name: feast-data-stores + registry: + local: + persistence: + store: + type: sql + secretRef: + name: feast-data-stores +``` + +3. **Create a KEDA `ScaledObject`** targeting the FeatureStore resource: + +```yaml +apiVersion: keda.sh/v1alpha1 +kind: ScaledObject +metadata: + name: feast-scaledobject +spec: + scaleTargetRef: + apiVersion: feast.dev/v1 + kind: FeatureStore + name: sample-keda + minReplicaCount: 1 + maxReplicaCount: 10 + triggers: + - type: prometheus + metadata: + serverAddress: http://prometheus.monitoring.svc:9090 + metricName: http_requests_total + query: sum(rate(http_requests_total{service="feast"}[2m])) + threshold: "100" +``` + +{% hint style="warning" %} +KEDA-created HPAs are not owned by the Feast operator. The operator will not interfere with them, but it also will not clean them up if the FeatureStore CR is deleted. You must manage the KEDA `ScaledObject` lifecycle independently. +{% endhint %} + +For the full API reference, see the [FeatureStore CRD reference](../../infra/feast-operator/docs/api/markdown/ref.md). \ No newline at end of file diff --git a/docs/project/development-guide.md b/docs/project/development-guide.md index 4f915f64e5c..ee5cc8cfcce 100644 --- a/docs/project/development-guide.md +++ b/docs/project/development-guide.md @@ -217,7 +217,7 @@ make test-python-integration-local To test across clouds, on top of setting up Redis, you also need GCP / AWS / Snowflake setup. > Note: you can manually control what tests are run today by inspecting -> [RepoConfiguration](https://github.com/feast-dev/feast/blob/master/sdk/python/tests/integration/feature_repos/repo_configuration.py) +> [RepoConfiguration](https://github.com/feast-dev/feast/blob/master/sdk/python/tests/universal/feature_repos/repo_configuration.py) > and commenting out tests that are added to `DEFAULT_FULL_REPO_CONFIGS` **GCP** diff --git a/docs/reference/alpha-feature-view-versioning.md b/docs/reference/alpha-feature-view-versioning.md new file mode 100644 index 00000000000..fbfc733afc6 --- /dev/null +++ b/docs/reference/alpha-feature-view-versioning.md @@ -0,0 +1,229 @@ +# \[Alpha\] Feature View Versioning + +{% hint style="warning" %} +**Warning**: This is an _experimental_ feature. It is stable but there are still rough edges. Contributions are welcome! +{% endhint %} + +## Overview + +Feature view versioning automatically tracks schema and UDF changes to feature views. Every time `feast apply` detects a change, a versioned snapshot is saved to the registry. This enables: + +- **Audit trail** — see what a feature view looked like at any point in time +- **Safe rollback** — pin serving to a prior version with `version="v0"` in your definition +- **Multi-version serving** — serve both old and new schemas simultaneously using `@v` syntax +- **Staged publishing** — use `feast apply --no-promote` to publish a new version without making it the default + +## How It Works + +Version tracking is fully automatic. You don't need to set any version parameter — just use `feast apply` as usual: + +1. **First apply** — Your feature view definition is saved as **v0**. +2. **Change something and re-apply** — Feast detects the change, saves the old definition as a snapshot, and saves the new one as **v1**. The version number auto-increments on each real change. +3. **Re-apply without changes** — Nothing happens. Feast compares the new definition against the active one and skips creating a version if they're identical (idempotent). +4. **Another change** — Creates **v2**, and so on. + +``` +feast apply # First apply → v0 +# ... edit schema ... +feast apply # Detects change → v1 +feast apply # No change detected → still v1 (no new version) +# ... edit source ... +feast apply # Detects change → v2 +``` + +**Key details:** + +* **Automatic snapshots**: Versions are created only when Feast detects an actual change to the feature view definition (schema or UDF). Metadata-only changes (description, tags, TTL) update in place without creating a new version. +* **Separate history storage**: Version history is stored separately from the active feature view definition, keeping the main registry lightweight. +* **Backward compatible**: The `version` parameter is fully optional. Omitting it (or setting `version="latest"`) preserves existing behavior — you get automatic versioning with zero changes to your code. + +## Configuration + +{% hint style="info" %} +Version history tracking is **always active** — no configuration needed. Every `feast apply` that changes a feature view automatically records a version snapshot. + +To enable **versioned online reads** (e.g., `fv@v2:feature`), add `enable_online_feature_view_versioning: true` to your registry config in `feature_store.yaml`: + +```yaml +registry: + path: data/registry.db + enable_online_feature_view_versioning: true +``` + +When this flag is off, version-qualified refs (e.g., `fv@v2:feature`) in online reads will raise errors, but version history, version listing, version pinning, and version lookups all work normally. +{% endhint %} + +## Pinning to a Specific Version + +You can pin a feature view to a specific historical version by setting the `version` parameter. When pinned, `feast apply` replaces the active feature view with the snapshot from that version. This is useful for reverting to a known-good definition. + +```python +from feast import FeatureView + +# Default behavior: always use the latest version (auto-increments on changes) +driver_stats = FeatureView( + name="driver_stats", + entities=[driver], + schema=[...], + source=my_source, +) + +# Pin to a specific version (reverts the active definition to v2's snapshot) +driver_stats = FeatureView( + name="driver_stats", + entities=[driver], + schema=[...], + source=my_source, + version="v2", # also accepts "version2" +) +``` + +When pinning, the feature view definition (schema, source, transformations, etc.) must match the currently active definition. If you've also modified the definition alongside the pin, `feast apply` will raise a `FeatureViewPinConflict` error. To apply changes, use `version="latest"`. To revert, only change the `version` parameter. + +The snapshot's content replaces the active feature view. Version history is not modified by a pin; the existing v0, v1, v2, etc. snapshots remain intact. + +After reverting with a pin, you can go back to normal auto-incrementing behavior by removing the `version` parameter (or setting it to `"latest"`) and running `feast apply` again. If the restored definition differs from the pinned snapshot, a new version will be created. + +### Version string formats + +| Format | Meaning | +|--------|---------| +| `"latest"` (or omitted) | Always use the latest version (auto-increments on changes) | +| `"v0"`, `"v1"`, `"v2"`, ... | Pin to a specific version number | +| `"version0"`, `"version1"`, ... | Equivalent long form (case-insensitive) | + +## Staged Publishing (`--no-promote`) + +By default, `feast apply` atomically saves a version snapshot **and** promotes it to the active definition. For breaking schema changes, you may want to stage the new version without disrupting unversioned consumers. + +The `--no-promote` flag saves the version snapshot without updating the active feature view definition. The new version is accessible only via explicit `@v` reads and `--version` materialization. + +**CLI usage:** + +```bash +feast apply --no-promote +``` + +**Python SDK equivalent:** + +```python +store.apply([entity, feature_view], no_promote=True) +``` + +### Phased rollout workflow + +1. **Stage the new version:** + ```bash + feast apply --no-promote + ``` + This publishes v2 without promoting it. All unversioned consumers continue using v1. + +2. **Populate the v2 online table:** + ```bash + feast materialize --views driver_stats --version v2 ... + ``` + +3. **Migrate consumers one at a time:** + - Consumer A switches to `driver_stats@v2:trips_today` + - Consumer B switches to `driver_stats@v2:avg_rating` + +4. **Promote v2 as the default:** + ```bash + feast apply + ``` + Or pin to v2: set `version="v2"` in the definition and run `feast apply`. + +## Listing Version History + +Use the CLI to inspect version history: + +```bash +feast feature-views list-versions driver_stats +``` + +```text +VERSION TYPE CREATED VERSION_ID +v0 feature_view 2024-01-15 10:30:00 a1b2c3d4-... +v1 feature_view 2024-01-16 14:22:00 e5f6g7h8-... +v2 feature_view 2024-01-20 09:15:00 i9j0k1l2-... +``` + +Or programmatically via the Python SDK: + +```python +store = FeatureStore(repo_path=".") +versions = store.list_feature_view_versions("driver_stats") +for v in versions: + print(f"{v['version']} created at {v['created_timestamp']}") +``` + +## Version-Qualified Feature References + +You can read features from a **specific version** of a feature view by using version-qualified feature references with the `@v` syntax: + +```python +online_features = store.get_online_features( + features=[ + "driver_stats:trips_today", # latest version (default) + "driver_stats@v2:trips_today", # specific version + "driver_stats@latest:trips_today", # explicit latest + ], + entity_rows=[{"driver_id": 1001}], +) +``` + +**How it works:** + +* `driver_stats:trips_today` is equivalent to `driver_stats@latest:trips_today` — it reads from the currently active version +* `driver_stats@v2:trips_today` reads from the v2 snapshot stored in version history, using a version-specific online store table +* Multiple versions of the same feature view can be queried in a single request (e.g., `driver_stats@v1:trips` and `driver_stats@v2:trips_daily`) + +**Backward compatibility:** + +* The unversioned online store table (e.g., `project_driver_stats`) is treated as v0 +* Only versions >= 1 get `_v{N}` suffixed tables (e.g., `project_driver_stats_v1`) +* Pre-versioning users' existing data continues to work without changes — `@latest` resolves to the active version, which for existing unversioned FVs is v0 + +**Materialization:** Each version requires its own materialization. After applying a new version, run `feast materialize` to populate the versioned table before querying it with `@v`. + +## Supported Feature View Types + +Versioning is supported on all three feature view types: + +* `FeatureView` (and `BatchFeatureView`) +* `StreamFeatureView` +* `OnDemandFeatureView` + +## Online Store Support + +{% hint style="info" %} +**Currently, version-qualified online reads (`@v`) are only supported with the SQLite online store.** Support for additional online stores (Redis, DynamoDB, Bigtable, Postgres, etc.) will be added based on community priority. + +If you need versioned online reads for a specific online store, please [open a GitHub issue](https://github.com/feast-dev/feast/issues/new) describing your use case and which store you need. This helps us prioritize development. +{% endhint %} + +Version history tracking in the registry (listing versions, pinning, `--no-promote`) works with **all** registry backends (file, SQL, Snowflake). + +## Full Details + +For the complete design, concurrency semantics, and feature service interactions, see the [Feature View Versioning RFC](../rfcs/feature-view-versioning.md). + +## Naming Restrictions + +Feature references use a structured format: `feature_view_name@v:feature_name`. To avoid +ambiguity, the following characters are reserved and must not appear in feature view or feature names: + +- **`@`** — Reserved as the version delimiter (e.g., `driver_stats@v2:trips_today`). `feast apply` + will reject feature views with `@` in their name. If you have existing feature views with `@` in + their names, they will continue to work for unversioned reads, but we recommend renaming them to + avoid ambiguity with the `@v` syntax. +- **`:`** — Reserved as the separator between feature view name and feature name in fully qualified + feature references (e.g., `driver_stats:trips_today`). + +## Known Limitations + +- **Online store coverage** — Version-qualified reads (`@v`) are SQLite-only today. Other online stores are follow-up work. +- **Offline store versioning** — Versioned historical retrieval is not yet supported. +- **Version deletion** — There is no mechanism to prune old versions from the registry. +- **Cross-version joins** — Joining features from different versions of the same feature view in `get_historical_features` is not supported. +- **Feature services** — Feature services always resolve to the active (promoted) version. `--no-promote` versions are not served until promoted. diff --git a/docs/reference/alpha-web-ui.md b/docs/reference/alpha-web-ui.md index 80c5b824c5a..0556482fcf8 100644 --- a/docs/reference/alpha-web-ui.md +++ b/docs/reference/alpha-web-ui.md @@ -35,6 +35,18 @@ Options: This will spin up a Web UI on localhost which automatically refreshes its view of the registry every `registry_ttl_sec` +#### Curl Generator Feature Server URL + +The Curl Generator uses a default Feature Server URL when building the example curl command. You can configure +this default at build time using: + +```bash +REACT_APP_FEAST_FEATURE_SERVER_URL="http://your-server:6566" +``` + +If this environment variable is not set, the UI falls back to `http://localhost:6566`. A user-edited value in +the UI is still stored in localStorage and will take precedence for that browser. + ### Importing as a module to integrate with an existing React App This is the recommended way to use Feast UI for teams maintaining their own internal UI for their deployment of Feast. diff --git a/docs/reference/data-sources/README.md b/docs/reference/data-sources/README.md index 151a948d0af..9d2873c56c3 100644 --- a/docs/reference/data-sources/README.md +++ b/docs/reference/data-sources/README.md @@ -57,3 +57,11 @@ Please see [Data Source](../../getting-started/concepts/data-ingestion.md) for a {% content-ref url="clickhouse.md" %} [clickhouse.md](clickhouse.md) {% endcontent-ref %} + +{% content-ref url="athena.md" %} +[athena.md](athena.md) +{% endcontent-ref %} + +{% content-ref url="oracle.md" %} +[oracle.md](oracle.md) +{% endcontent-ref %} diff --git a/docs/reference/data-sources/athena.md b/docs/reference/data-sources/athena.md new file mode 100644 index 00000000000..d3ca67dcb10 --- /dev/null +++ b/docs/reference/data-sources/athena.md @@ -0,0 +1,37 @@ +# Athena source (contrib) + +## Description + +Athena data sources are AWS Athena tables or views. +These can be specified either by a table reference or a SQL query. + +## Disclaimer + +The Athena data source does not achieve full test coverage. +Please do not assume complete stability. + +## Examples + +Defining an Athena source: + +```python +from feast.infra.offline_stores.contrib.athena_offline_store.athena_source import ( + AthenaSource, +) + +driver_stats_source = AthenaSource( + name="driver_hourly_stats", + table="driver_hourly_stats", + database="my_database", + data_source="AwsDataCatalog", + timestamp_field="event_timestamp", + created_timestamp_column="created", +) +``` + +The full set of configuration options is available [here](https://rtd.feast.dev/en/master/#feast.infra.offline_stores.contrib.athena_offline_store.athena_source.AthenaSource). + +## Supported Types + +Athena data sources support standard Athena types mapped through the AWS Athena API. +For a comparison against other batch data sources, please see [here](overview.md#functionality-matrix). diff --git a/docs/reference/data-sources/oracle.md b/docs/reference/data-sources/oracle.md new file mode 100644 index 00000000000..48c249ba3b8 --- /dev/null +++ b/docs/reference/data-sources/oracle.md @@ -0,0 +1,36 @@ +# Oracle source (contrib) + +## Description + +Oracle data sources are Oracle database tables. +These are specified by a table reference (e.g. `"TRANSACTION_FEATURES"` or `"SCHEMA.TABLE"`). + +## Disclaimer + +The Oracle data source does not achieve full test coverage. +Please do not assume complete stability. + +## Examples + +Defining an Oracle source: + +```python +from feast.infra.offline_stores.contrib.oracle_offline_store.oracle_source import ( + OracleSource, +) + +driver_stats_source = OracleSource( + name="driver_hourly_stats", + table_ref="DRIVER_HOURLY_STATS", + event_timestamp_column="EVENT_TIMESTAMP", + created_timestamp_column="CREATED", +) +``` + +**Note:** Oracle stores unquoted identifiers in uppercase. Reference columns using the casing shown by Oracle (e.g. `USER_ID` for unquoted identifiers). + +## Supported Types + +Oracle data sources support standard Oracle numeric, string, date, and timestamp types mapped through the ibis Oracle backend. +For a comparison against other batch data sources, please see [here](overview.md#functionality-matrix). + diff --git a/docs/reference/data-sources/overview.md b/docs/reference/data-sources/overview.md index 7cffc4154dd..5cc5285f77e 100644 --- a/docs/reference/data-sources/overview.md +++ b/docs/reference/data-sources/overview.md @@ -5,7 +5,7 @@ In Feast, each batch data source is associated with corresponding offline stores. For example, a `SnowflakeSource` can only be processed by the Snowflake offline store, while a `FileSource` can be processed by both File and DuckDB offline stores. Otherwise, the primary difference between batch data sources is the set of supported types. -Feast has an internal type system, and aims to support eight primitive types (`bytes`, `string`, `int32`, `int64`, `float32`, `float64`, `bool`, and `timestamp`) along with the corresponding array types. +Feast has an internal type system that supports primitive types (`bytes`, `string`, `int32`, `int64`, `float32`, `float64`, `bool`, `timestamp`), array types, set types, map/JSON types, and struct types. However, not every batch data source supports all of these types. For more details on the Feast type system, see [here](../type-system.md). @@ -29,3 +29,9 @@ Below is a matrix indicating which data sources support which types. | `bool` | yes | yes | yes | yes | yes | yes | yes | yes | | `timestamp` | yes | yes | yes | yes | yes | yes | yes | yes | | array types | yes | yes | yes | no | yes | yes | yes | no | +| `Map` | yes | no | yes | yes | yes | yes | yes | no | +| `Json` | yes | yes | yes | yes | yes | no | no | no | +| `Struct` | yes | yes | no | no | yes | yes | no | no | +| set types | yes* | no | no | no | no | no | no | no | + +\* **Set types** are defined in Feast's proto and Python type system but are **not inferred** by any backend. They must be explicitly declared in the feature view schema and are best suited for online serving use cases. See [Type System](../type-system.md#set-types) for details. diff --git a/docs/reference/feast-cli-commands.md b/docs/reference/feast-cli-commands.md index eb6fa90d280..535065b5a98 100644 --- a/docs/reference/feast-cli-commands.md +++ b/docs/reference/feast-cli-commands.md @@ -176,6 +176,18 @@ NAME ENTITIES TYPE driver_hourly_stats {'driver'} FeatureView ``` +List version history for a feature view + +```text +feast feature-views list-versions FEATURE_VIEW_NAME +``` + +```text +VERSION TYPE CREATED VERSION_ID +v0 feature_view 2024-01-15 10:30:00 a1b2c3d4-... +v1 feature_view 2024-01-16 14:22:00 e5f6g7h8-... +``` + ## Init Creates a new feature repository diff --git a/docs/reference/feature-servers/mcp-feature-server.md b/docs/reference/feature-servers/mcp-feature-server.md new file mode 100644 index 00000000000..8bfc96b1891 --- /dev/null +++ b/docs/reference/feature-servers/mcp-feature-server.md @@ -0,0 +1,51 @@ +# MCP Feature Server + +## Overview + +Feast can expose the Python Feature Server as an MCP (Model Context Protocol) server using `fastapi_mcp`. When enabled, MCP clients can discover and call Feast tools such as online feature retrieval. + +## Installation + +```bash +pip install feast[mcp] +``` + +## Configuration + +Add an MCP `feature_server` block to your `feature_store.yaml`: + +```yaml +feature_server: + type: mcp + enabled: true + mcp_enabled: true + mcp_transport: http + mcp_server_name: "feast-feature-store" + mcp_server_version: "1.0.0" +``` + +### mcp_transport + +`mcp_transport` controls how MCP is mounted into the Feature Server: + +- `sse`: SSE-based transport. This is the default for backward compatibility. +- `http`: Streamable HTTP transport. This is recommended for improved compatibility with some MCP clients. + +If `mcp_transport: http` is configured but your installed `fastapi_mcp` version does not support Streamable HTTP mounting, Feast will fail fast with an error asking you to upgrade `fastapi_mcp` (or reinstall `feast[mcp]`). + +## Endpoints + +MCP is mounted at: + +- `/mcp` + +## Connecting an MCP client + +Use your MCP client’s “HTTP” configuration and point it to the Feature Server base URL. For example, if your Feature Server runs at `http://localhost:6566`, use: + +- `http://localhost:6566/mcp` + +## Troubleshooting + +- If you see a deprecation warning about `mount()` at runtime, upgrade `fastapi_mcp` and use `mcp_transport: http` or `mcp_transport: sse`. +- If your MCP client has intermittent connectivity issues with `mcp_transport: sse`, switch to `mcp_transport: http`. diff --git a/docs/reference/feature-servers/python-feature-server.md b/docs/reference/feature-servers/python-feature-server.md index 2e5792b0a6f..654c4b9f938 100644 --- a/docs/reference/feature-servers/python-feature-server.md +++ b/docs/reference/feature-servers/python-feature-server.md @@ -311,6 +311,152 @@ requests.post( data=json.dumps(materialize_data)) ``` +## Prometheus Metrics + +The Python feature server can expose Prometheus-compatible metrics on a dedicated +HTTP endpoint (default port `8000`). Metrics are **opt-in** and carry zero overhead +when disabled. + +### Enabling metrics + +**Option 1 — CLI flag** (useful for one-off runs): + +```bash +feast serve --metrics +``` + +**Option 2 — `feature_store.yaml`** (recommended for production): + +```yaml +feature_server: + type: local + metrics: + enabled: true +``` + +Either option is sufficient. When both are set, metrics are enabled. + +### Per-category control + +By default, enabling metrics turns on **all** categories. You can selectively +disable individual categories within the same `metrics` block: + +```yaml +feature_server: + type: local + metrics: + enabled: true + resource: true # CPU / memory gauges + request: false # disable endpoint latency & request counters + online_features: true # online feature retrieval counters + push: true # push request counters + materialization: true # materialization counters & duration + freshness: true # feature freshness gauges +``` + +Any category set to `false` will emit no metrics and start no background +threads (e.g., setting `freshness: false` prevents the registry polling +thread from starting). All categories default to `true`. + +### Available metrics + +| Metric | Type | Labels | Category | Description | +|--------|------|--------|----------|-------------| +| `feast_feature_server_cpu_usage` | Gauge | — | `resource` | Process CPU usage % | +| `feast_feature_server_memory_usage` | Gauge | — | `resource` | Process memory usage % | +| `feast_feature_server_request_total` | Counter | `endpoint`, `status` | `request` | Total requests per endpoint | +| `feast_feature_server_request_latency_seconds` | Histogram | `endpoint`, `feature_count`, `feature_view_count` | `request` | Request latency with p50/p95/p99 support | +| `feast_online_features_request_total` | Counter | — | `online_features` | Total online feature retrieval requests | +| `feast_online_features_entity_count` | Histogram | — | `online_features` | Entity rows per online feature request | +| `feast_feature_server_online_store_read_duration_seconds` | Histogram | — | `online_features` | Online store read phase duration (sync and async) | +| `feast_feature_server_transformation_duration_seconds` | Histogram | `odfv_name`, `mode` | `online_features` | ODFV read-path transformation duration (requires `track_metrics=True` on the ODFV) | +| `feast_feature_server_write_transformation_duration_seconds` | Histogram | `odfv_name`, `mode` | `online_features` | ODFV write-path transformation duration (requires `track_metrics=True` on the ODFV) | +| `feast_push_request_total` | Counter | `push_source`, `mode` | `push` | Push requests by source and mode | +| `feast_materialization_result_total` | Counter | `feature_view`, `status` | `materialization` | Materialization runs (success/failure) | +| `feast_materialization_duration_seconds` | Histogram | `feature_view` | `materialization` | Materialization duration per feature view | +| `feast_feature_freshness_seconds` | Gauge | `feature_view`, `project` | `freshness` | Seconds since last materialization | + +### Per-ODFV transformation metrics + +The `transformation_duration_seconds` and `write_transformation_duration_seconds` +metrics are gated behind **two** conditions — both must be true for any +instrumentation to run: + +1. **Server-level**: the `online_features` category must be enabled in the + metrics configuration. +2. **ODFV-level**: the `OnDemandFeatureView` must have `track_metrics=True`. + +This defaults to `False`, so no ODFV incurs timing overhead unless explicitly +opted in: + +```python +from feast.on_demand_feature_view import on_demand_feature_view + +@on_demand_feature_view( + sources=[my_feature_view, my_request_source], + schema=[Field(name="output", dtype=Float64)], + track_metrics=True, # opt in to transformation timing +) +def my_transform(inputs: pd.DataFrame) -> pd.DataFrame: + ... +``` + +The `odfv_name` label lets you filter or group by individual ODFV, +and the `mode` label (`python`, `pandas`, `substrait`) lets you compare +transformation engines. + +### Scraping with Prometheus + +```yaml +scrape_configs: + - job_name: feast + static_configs: + - targets: ["localhost:8000"] +``` + +### Kubernetes / Feast Operator + +Set `metrics: true` in your FeatureStore CR: + +```yaml +spec: + services: + onlineStore: + server: + metrics: true +``` + +The operator automatically exposes port 8000 and creates the corresponding +Service port so Prometheus can discover it. + +### Multi-worker and multi-replica (HPA) support + +Feast uses Prometheus **multiprocess mode** so that metrics are correct +regardless of the number of Gunicorn workers or Kubernetes replicas. + +**How it works:** + +* Each Gunicorn worker writes metric values to shared files in a + temporary directory (`PROMETHEUS_MULTIPROCESS_DIR`). Feast creates + this directory automatically; you can override it by setting the + environment variable yourself. +* The metrics HTTP server on port 8000 aggregates all workers' + metric files using `MultiProcessCollector`, so a single scrape + returns accurate totals. +* Gunicorn hooks clean up dead-worker files automatically + (`child_exit` → `mark_process_dead`). +* CPU and memory gauges use `multiprocess_mode=liveall` — Prometheus + shows per-worker values distinguished by a `pid` label. +* Feature freshness gauges use `multiprocess_mode=max` — Prometheus + shows the worst-case staleness (all workers compute the same value). +* Counters and histograms (request counts, latency, materialization) + are automatically summed across workers. + +**Multiple replicas (HPA):** Each pod runs its own metrics endpoint. +Prometheus adds an `instance` label per pod, so there is no +duplication. Use `sum(rate(...))` or `histogram_quantile(...)` across +instances as usual. + ## Starting the feature server in TLS(SSL) mode Enabling TLS mode ensures that data between the Feast client and server is transmitted securely. For an ideal production environment, it is recommended to start the feature server in TLS mode. diff --git a/docs/reference/feature-store-yaml.md b/docs/reference/feature-store-yaml.md index 820731064fc..c287ddbc73a 100644 --- a/docs/reference/feature-store-yaml.md +++ b/docs/reference/feature-store-yaml.md @@ -36,6 +36,14 @@ An example configuration: ```yaml feature_server: type: local + metrics: # Prometheus metrics configuration. Also achievable via `feast serve --metrics`. + enabled: true # Enable Prometheus metrics server on port 8000 + resource: true # CPU / memory gauges + request: true # endpoint latency histograms & request counters + online_features: true # online feature retrieval counters + store read & ODFV transform timing + push: true # push request counters + materialization: true # materialization counters & duration histograms + freshness: true # per-feature-view freshness gauges offline_push_batching_enabled: true # Enables batching of offline writes processed by /push. Online writes are unaffected. offline_push_batching_batch_size: 100 # Maximum number of buffered rows before writing to the offline store. offline_push_batching_batch_interval_seconds: 5 # Maximum time rows may remain buffered before a forced flush. diff --git a/docs/reference/offline-stores/README.md b/docs/reference/offline-stores/README.md index b5e2bccbdd1..5f4e146326a 100644 --- a/docs/reference/offline-stores/README.md +++ b/docs/reference/offline-stores/README.md @@ -49,3 +49,23 @@ Please see [Offline Store](../../getting-started/components/offline-store.md) fo {% content-ref url="ray.md" %} [ray.md](ray.md) {% endcontent-ref %} + +{% content-ref url="oracle.md" %} +[oracle.md](oracle.md) +{% endcontent-ref %} + +{% content-ref url="athena.md" %} +[athena.md](athena.md) +{% endcontent-ref %} + +{% content-ref url="clickhouse.md" %} +[clickhouse.md](clickhouse.md) +{% endcontent-ref %} + +{% content-ref url="remote-offline-store.md" %} +[remote-offline-store.md](remote-offline-store.md) +{% endcontent-ref %} + +{% content-ref url="hybrid.md" %} +[hybrid.md](hybrid.md) +{% endcontent-ref %} diff --git a/docs/reference/offline-stores/athena.md b/docs/reference/offline-stores/athena.md new file mode 100644 index 00000000000..3fbe77681ee --- /dev/null +++ b/docs/reference/offline-stores/athena.md @@ -0,0 +1,66 @@ +# Athena offline store (contrib) + +## Description + +The Athena offline store provides support for reading [AthenaSources](../data-sources/athena.md). +* Entity dataframes can be provided as a SQL query or can be provided as a Pandas dataframe. + +## Disclaimer + +The Athena offline store does not achieve full test coverage. +Please do not assume complete stability. + +## Getting started +In order to use this offline store, you'll need to run `pip install 'feast[aws]'`. + +## Example + +{% code title="feature_store.yaml" %} +```yaml +project: my_project +registry: data/registry.db +provider: local +offline_store: + type: athena + data_source: AwsDataCatalog + region: us-east-1 + database: my_database + workgroup: primary +online_store: + path: data/online_store.db +``` +{% endcode %} + +The full set of configuration options is available in [AthenaOfflineStoreConfig](https://rtd.feast.dev/en/master/#feast.infra.offline_stores.contrib.athena_offline_store.athena.AthenaOfflineStoreConfig). + +## Functionality Matrix + +The set of functionality supported by offline stores is described in detail [here](overview.md#functionality). +Below is a matrix indicating which functionality is supported by the Athena offline store. + +| | Athena | +| :----------------------------------------------------------------- |:-------| +| `get_historical_features` (point-in-time correct join) | yes | +| `pull_latest_from_table_or_query` (retrieve latest feature values) | yes | +| `pull_all_from_table_or_query` (retrieve a saved dataset) | yes | +| `offline_write_batch` (persist dataframes to offline store) | no | +| `write_logged_features` (persist logged features to offline store) | yes | + +Below is a matrix indicating which functionality is supported by `AthenaRetrievalJob`. + +| | Athena | +| ----------------------------------------------------- |--------| +| export to dataframe | yes | +| export to arrow table | yes | +| export to arrow batches | no | +| export to SQL | yes | +| export to data lake (S3, GCS, etc.) | no | +| export to data warehouse | no | +| export as Spark dataframe | no | +| local execution of Python-based on-demand transforms | yes | +| remote execution of Python-based on-demand transforms | no | +| persist results in the offline store | yes | +| preview the query plan before execution | yes | +| read partitioned data | yes | + +To compare this set of functionality against other offline stores, please see the full [functionality matrix](overview.md#functionality-matrix). diff --git a/docs/reference/offline-stores/oracle.md b/docs/reference/offline-stores/oracle.md new file mode 100644 index 00000000000..12f5b761ce6 --- /dev/null +++ b/docs/reference/offline-stores/oracle.md @@ -0,0 +1,109 @@ +# Oracle offline store (contrib) + +## Description + +The Oracle offline store provides support for reading [OracleSources](../data-sources/oracle.md). +* Entity dataframes can be provided as a SQL query or as a Pandas dataframe. +* Uses the [ibis](https://ibis-project.org/) Oracle backend (`ibis.oracle`) for all database interactions. +* Only one of `service_name`, `sid`, or `dsn` may be set in the configuration. + +## Disclaimer + +The Oracle offline store does not achieve full test coverage. +Please do not assume complete stability. + +## Getting started + +Install the Oracle extras: + +```bash +pip install 'feast[oracle]' +``` + +## Example + +{% code title="feature_store.yaml" %} +```yaml +project: my_project +registry: data/registry.db +provider: local +offline_store: + type: oracle + host: DB_HOST + port: 1521 + user: DB_USERNAME + password: DB_PASSWORD + service_name: ORCL +online_store: + path: data/online_store.db +``` +{% endcode %} + +Connection can alternatively use `sid` or `dsn` instead of `service_name`: + +```yaml +# Using SID +offline_store: + type: oracle + host: DB_HOST + port: 1521 + user: DB_USERNAME + password: DB_PASSWORD + sid: ORCL + +# Using DSN +offline_store: + type: oracle + host: DB_HOST + port: 1521 + user: DB_USERNAME + password: DB_PASSWORD + dsn: "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=DB_HOST)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCL)))" +``` + +### Configuration reference + +| Parameter | Required | Default | Description | +| :------------- | :------- | :---------- | :------------------------------------------------------- | +| `type` | yes | — | Must be set to `oracle` | +| `user` | yes | — | Oracle database user | +| `password` | yes | — | Oracle database password | +| `host` | no | `localhost` | Oracle database host | +| `port` | no | `1521` | Oracle database port | +| `service_name` | no | — | Oracle service name (mutually exclusive with sid and dsn) | +| `sid` | no | — | Oracle SID (mutually exclusive with service_name and dsn) | +| `database` | no | — | Oracle database name | +| `dsn` | no | — | Oracle DSN string (mutually exclusive with service_name and sid) | + +## Functionality Matrix + +The set of functionality supported by offline stores is described in detail [here](overview.md#functionality). +Below is a matrix indicating which functionality is supported by the Oracle offline store. + +| | Oracle | +| :----------------------------------------------------------------- | :----- | +| `get_historical_features` (point-in-time correct join) | yes | +| `pull_latest_from_table_or_query` (retrieve latest feature values) | yes | +| `pull_all_from_table_or_query` (retrieve a saved dataset) | yes | +| `offline_write_batch` (persist dataframes to offline store) | yes | +| `write_logged_features` (persist logged features to offline store) | yes | + +Below is a matrix indicating which functionality is supported by `OracleRetrievalJob`. + +| | Oracle | +| ----------------------------------------------------- | ------ | +| export to dataframe | yes | +| export to arrow table | yes | +| export to arrow batches | no | +| export to SQL | no | +| export to data lake (S3, GCS, etc.) | no | +| export to data warehouse | no | +| export as Spark dataframe | no | +| local execution of Python-based on-demand transforms | yes | +| remote execution of Python-based on-demand transforms | no | +| persist results in the offline store | yes | +| preview the query plan before execution | no | +| read partitioned data | no | + +To compare this set of functionality against other offline stores, please see the full [functionality matrix](overview.md#functionality-matrix). + diff --git a/docs/reference/offline-stores/postgres.md b/docs/reference/offline-stores/postgres.md index 321ddcf25e7..7e9f112b3b3 100644 --- a/docs/reference/offline-stores/postgres.md +++ b/docs/reference/offline-stores/postgres.md @@ -38,7 +38,7 @@ online_store: ``` {% endcode %} -Note that `sslmode`, `sslkey_path`, `sslcert_path`, and `sslrootcert_path` are optional parameters. +Note that `sslmode` defaults to `require`, which encrypts the connection without certificate verification. To disable SSL (e.g. for local development), set `sslmode: disable`. For certificate verification, set `sslmode` to `verify-ca` or `verify-full` and provide the corresponding `sslrootcert_path` (and optionally `sslcert_path` and `sslkey_path` for mutual TLS). The full set of configuration options is available in [PostgreSQLOfflineStoreConfig](https://rtd.feast.dev/en/master/#feast.infra.offline_stores.contrib.postgres_offline_store.postgres.PostgreSQLOfflineStoreConfig). Additionally, a new optional parameter `entity_select_mode` was added to tell how Postgres should load the entity data. By default(`temp_table`), a temporary table is created and the entity data frame or sql is loaded into that table. A new value of `embed_query` was added to allow directly loading the SQL query into a CTE, providing improved performance and skipping the need to CREATE and DROP the temporary table. diff --git a/docs/reference/online-stores/README.md b/docs/reference/online-stores/README.md index 5df4710434c..6f31993f896 100644 --- a/docs/reference/online-stores/README.md +++ b/docs/reference/online-stores/README.md @@ -22,10 +22,6 @@ Please see [Online Store](../../getting-started/components/online-store.md) for [dragonfly.md](dragonfly.md) {% endcontent-ref %} -{% content-ref url="ikv.md" %} -[ikv.md](ikv.md) -{% endcontent-ref %} - {% content-ref url="datastore.md" %} [datastore.md](datastore.md) {% endcontent-ref %} @@ -42,6 +38,10 @@ Please see [Online Store](../../getting-started/components/online-store.md) for [postgres.md](postgres.md) {% endcontent-ref %} +{% content-ref url="hbase.md" %} +[hbase.md](hbase.md) +{% endcontent-ref %} + {% content-ref url="cassandra.md" %} [cassandra.md](cassandra.md) {% endcontent-ref %} @@ -54,6 +54,10 @@ Please see [Online Store](../../getting-started/components/online-store.md) for [mysql.md](mysql.md) {% endcontent-ref %} +{% content-ref url="mongodb.md" %} +[mongodb.md](mongodb.md) +{% endcontent-ref %} + {% content-ref url="hazelcast.md" %} [hazelcast.md](hazelcast.md) {% endcontent-ref %} @@ -69,3 +73,23 @@ Please see [Online Store](../../getting-started/components/online-store.md) for {% content-ref url="singlestore.md" %} [singlestore.md](singlestore.md) {% endcontent-ref %} + +{% content-ref url="elasticsearch.md" %} +[elasticsearch.md](elasticsearch.md) +{% endcontent-ref %} + +{% content-ref url="qdrant.md" %} +[qdrant.md](qdrant.md) +{% endcontent-ref %} + +{% content-ref url="milvus.md" %} +[milvus.md](milvus.md) +{% endcontent-ref %} + +{% content-ref url="faiss.md" %} +[faiss.md](faiss.md) +{% endcontent-ref %} + +{% content-ref url="hybrid.md" %} +[hybrid.md](hybrid.md) +{% endcontent-ref %} diff --git a/docs/reference/online-stores/dynamodb.md b/docs/reference/online-stores/dynamodb.md index 344caccac1d..68d3d29ca3b 100644 --- a/docs/reference/online-stores/dynamodb.md +++ b/docs/reference/online-stores/dynamodb.md @@ -22,13 +22,54 @@ online_store: The full set of configuration options is available in [DynamoDBOnlineStoreConfig](https://rtd.feast.dev/en/master/#feast.infra.online_stores.dynamodb.DynamoDBOnlineStoreConfig). +## Configuration + +Below is a example with performance tuning options: + +{% code title="feature_store.yaml" %} +```yaml +project: my_feature_repo +registry: data/registry.db +provider: aws +online_store: + type: dynamodb + region: us-west-2 + batch_size: 100 + max_read_workers: 10 + consistent_reads: false +``` +{% endcode %} + +### Configuration Options + +| Option | Type | Default | Description | +| ------ | ---- | ------- | ----------- | +| `region` | string | | AWS region for DynamoDB | +| `table_name_template` | string | `{project}.{table_name}` | Template for table names | +| `batch_size` | int | `100` | Number of items per BatchGetItem/BatchWriteItem request (max 100) | +| `max_read_workers` | int | `10` | Maximum parallel threads for batch read operations. Higher values improve throughput for large batch reads but increase resource usage | +| `consistent_reads` | bool | `false` | Whether to use strongly consistent reads (higher latency, guaranteed latest data) | +| `tags` | dict | `null` | AWS resource tags added to each table | +| `session_based_auth` | bool | `false` | Use AWS session-based client authentication | + +### Performance Tuning + +**Parallel Batch Reads**: When reading features for many entities, DynamoDB's BatchGetItem is limited to 100 items per request. For 500 entities, this requires 5 batch requests. The `max_read_workers` option controls how many of these batches execute in parallel: + +- **Sequential (old behavior)**: 5 batches × 10ms = 50ms total +- **Parallel (with `max_read_workers: 10`)**: 5 batches in parallel ≈ 10ms total + +For high-throughput workloads with large entity counts, increase `max_read_workers` (up to 20-30) based on your DynamoDB capacity and network conditions. + +**Batch Size**: Increase `batch_size` up to 100 to reduce the number of API calls. However, larger batches may hit DynamoDB's 16MB response limit for tables with large feature values. + ## Permissions Feast requires the following permissions in order to execute commands for DynamoDB online store: | **Command** | Permissions | Resources | | ----------------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------- | -| **Apply** |

dynamodb:CreateTable

dynamodb:DescribeTable

dynamodb:DeleteTable

| arn:aws:dynamodb:\:\:table/\* | +| **Apply** |

dynamodb:CreateTable

dynamodb:DescribeTable

dynamodb:DeleteTable

dynamodb:TagResource

| arn:aws:dynamodb:\:\:table/\* | | **Materialize** | dynamodb.BatchWriteItem | arn:aws:dynamodb:\:\:table/\* | | **Get Online Features** | dynamodb.BatchGetItem | arn:aws:dynamodb:\:\:table/\* | @@ -42,6 +83,7 @@ The following inline policy can be used to grant Feast the necessary permissions "dynamodb:CreateTable", "dynamodb:DescribeTable", "dynamodb:DeleteTable", + "dynamodb:TagResource", "dynamodb:BatchWriteItem", "dynamodb:BatchGetItem" ], diff --git a/docs/reference/online-stores/faiss.md b/docs/reference/online-stores/faiss.md new file mode 100644 index 00000000000..32c9242dd60 --- /dev/null +++ b/docs/reference/online-stores/faiss.md @@ -0,0 +1,57 @@ +# Faiss online store + +## Description + +The [Faiss](https://github.com/facebookresearch/faiss) online store provides support for materializing feature values and performing vector similarity search using Facebook AI Similarity Search (Faiss). Faiss is a library for efficient similarity search and clustering of dense vectors, making it well-suited for use cases involving embeddings and nearest-neighbor lookups. + +## Getting started +In order to use this online store, you'll need to install the Faiss dependency. E.g. + +`pip install 'feast[faiss]'` + +## Example + +{% code title="feature_store.yaml" %} +```yaml +project: my_feature_repo +registry: data/registry.db +provider: local +online_store: + type: feast.infra.online_stores.faiss_online_store.FaissOnlineStore + dimension: 128 + index_path: data/faiss_index + index_type: IVFFlat # optional, default: IVFFlat + nlist: 100 # optional, default: 100 +``` +{% endcode %} + +**Note:** Faiss is not registered as a named online store type. You must use the fully qualified class path as the `type` value. + +The full set of configuration options is available in [FaissOnlineStoreConfig](https://rtd.feast.dev/en/master/#feast.infra.online_stores.faiss_online_store.FaissOnlineStoreConfig). + +## Functionality Matrix + +The set of functionality supported by online stores is described in detail [here](overview.md#functionality). +Below is a matrix indicating which functionality is supported by the Faiss online store. + +| | Faiss | +|:----------------------------------------------------------|:------| +| write feature values to the online store | yes | +| read feature values from the online store | yes | +| update infrastructure (e.g. tables) in the online store | yes | +| teardown infrastructure (e.g. tables) in the online store | yes | +| generate a plan of infrastructure changes | no | +| support for on-demand transforms | yes | +| readable by Python SDK | yes | +| readable by Java | no | +| readable by Go | no | +| support for entityless feature views | yes | +| support for concurrent writing to the same key | no | +| support for ttl (time to live) at retrieval | no | +| support for deleting expired data | no | +| collocated by feature view | yes | +| collocated by feature service | no | +| collocated by entity key | no | +| vector similarity search | yes | + +To compare this set of functionality against other online stores, please see the full [functionality matrix](overview.md#functionality-matrix). diff --git a/docs/reference/online-stores/hbase.md b/docs/reference/online-stores/hbase.md new file mode 100644 index 00000000000..b53bfed5fe5 --- /dev/null +++ b/docs/reference/online-stores/hbase.md @@ -0,0 +1,56 @@ +# HBase online store + +## Description + +The [HBase](https://hbase.apache.org/) online store provides support for materializing feature values into an Apache HBase database for serving online features in real-time. + +* Each feature view is mapped to an HBase table +* Connects to HBase via the Thrift server using [happybase](https://happybase.readthedocs.io/) + +## Getting started +In order to use this online store, you'll need to run `pip install 'feast[hbase]'`. + +## Example + +{% code title="feature_store.yaml" %} +```yaml +project: my_feature_repo +registry: data/registry.db +provider: local +online_store: + type: hbase + host: localhost + port: "9090" + connection_pool_size: 4 # optional + protocol: binary # optional + transport: buffered # optional +``` +{% endcode %} + +The full set of configuration options is available in [HbaseOnlineStoreConfig](https://rtd.feast.dev/en/master/#feast.infra.online_stores.hbase_online_store.hbase.HbaseOnlineStoreConfig). + +## Functionality Matrix + +The set of functionality supported by online stores is described in detail [here](overview.md#functionality). +Below is a matrix indicating which functionality is supported by the HBase online store. + +| | HBase | +| :-------------------------------------------------------- | :---- | +| write feature values to the online store | yes | +| read feature values from the online store | yes | +| update infrastructure (e.g. tables) in the online store | yes | +| teardown infrastructure (e.g. tables) in the online store | yes | +| generate a plan of infrastructure changes | no | +| support for on-demand transforms | yes | +| readable by Python SDK | yes | +| readable by Java | no | +| readable by Go | no | +| support for entityless feature views | yes | +| support for concurrent writing to the same key | no | +| support for ttl (time to live) at retrieval | no | +| support for deleting expired data | no | +| collocated by feature view | yes | +| collocated by feature service | no | +| collocated by entity key | no | + +To compare this set of functionality against other online stores, please see the full [functionality matrix](overview.md#functionality-matrix). diff --git a/docs/reference/online-stores/ikv.md b/docs/reference/online-stores/ikv.md deleted file mode 100644 index 79f21d17797..00000000000 --- a/docs/reference/online-stores/ikv.md +++ /dev/null @@ -1,69 +0,0 @@ -# IKV (Inlined Key-Value Store) online store - -## Description - -[IKV](https://github.com/inlinedio/ikv-store) is a fully-managed embedded key-value store, primarily designed for storing ML features. Most key-value stores (think Redis or Cassandra) need a remote database cluster, whereas IKV allows you to utilize your existing application infrastructure to store data (cost efficient) and access it without any network calls (better performance). See detailed performance benchmarks and cost comparison with Redis on [https://inlined.io](https://inlined.io). IKV can be used as an online-store in Feast, the rest of this guide goes over the setup. - -## Getting started -Make sure you have Python and `pip` installed. - -Install the Feast SDK and CLI: `pip install feast` - -In order to use this online store, you'll need to install the IKV extra (along with the dependency needed for the offline store of choice). E.g. -- `pip install 'feast[gcp, ikv]'` -- `pip install 'feast[snowflake, ikv]'` -- `pip install 'feast[aws, ikv]'` -- `pip install 'feast[azure, ikv]'` - -You can get started by using any of the other templates (e.g. `feast init -t gcp` or `feast init -t snowflake` or `feast init -t aws`), and then swapping in IKV as the online store as seen below in the examples. - -### 1. Provision an IKV store -Go to [https://inlined.io](https://inlined.io) or email onboarding[at]inlined.io - -### 2. Configure - -Update `my_feature_repo/feature_store.yaml` with the below contents: - -{% code title="feature_store.yaml" %} -```yaml -project: my_feature_repo -registry: data/registry.db -provider: local -online_store: - type: ikv - account_id: secret - account_passkey: secret - store_name: your-store-name - mount_directory: /absolute/path/on/disk/for/ikv/embedded/index -``` -{% endcode %} - -After provisioning an IKV account/store, you should have an account id, passkey and store-name. Additionally you must specify a mount-directory - where IKV will pull/update (maintain) a copy of the index for online reads (IKV is an embedded database). It can be skipped only if you don't plan to read any data from this container. The mount directory path usually points to a location on local/remote disk. - -The full set of configuration options is available in IKVOnlineStoreConfig at `sdk/python/feast/infra/online_stores/contrib/ikv_online_store/ikv.py` - -## Functionality Matrix - -The set of functionality supported by online stores is described in detail [here](overview.md#functionality). -Below is a matrix indicating which functionality is supported by the IKV online store. - -| | IKV | -| :-------------------------------------------------------- | :---- | -| write feature values to the online store | yes | -| read feature values from the online store | yes | -| update infrastructure (e.g. tables) in the online store | yes | -| teardown infrastructure (e.g. tables) in the online store | yes | -| generate a plan of infrastructure changes | no | -| support for on-demand transforms | yes | -| readable by Python SDK | yes | -| readable by Java | no | -| readable by Go | no | -| support for entityless feature views | yes | -| support for concurrent writing to the same key | yes | -| support for ttl (time to live) at retrieval | no | -| support for deleting expired data | no | -| collocated by feature view | no | -| collocated by feature service | no | -| collocated by entity key | yes | - -To compare this set of functionality against other online stores, please see the full [functionality matrix](overview.md#functionality-matrix). diff --git a/docs/reference/online-stores/mongodb.md b/docs/reference/online-stores/mongodb.md new file mode 100644 index 00000000000..969637b9e68 --- /dev/null +++ b/docs/reference/online-stores/mongodb.md @@ -0,0 +1,181 @@ +# MongoDB online store (Preview) + +## Description + +The [MongoDB](https://www.mongodb.com/) online store provides support for materializing feature values into MongoDB for serving online features. + +{% hint style="warning" %} +The MongoDB online store is currently in **preview**. Some functionality may be unstable, and breaking changes may occur in future releases. +{% endhint %} + +## Features + +* Supports both synchronous and asynchronous operations for high-performance feature retrieval +* Native async support uses PyMongo's `AsyncMongoClient` (no Motor dependency required) +* Flexible connection options supporting MongoDB Atlas, self-hosted MongoDB, and MongoDB replica sets +* Automatic index creation for optimized query performance +* Entity key collocation for efficient feature retrieval + +## Getting started + +In order to use this online store, you'll need to install the MongoDB extra (along with the dependency needed for the offline store of choice): + +```bash +pip install 'feast[mongodb]' +``` + +You can get started by using any of the other templates (e.g. `feast init -t gcp` or `feast init -t snowflake` or `feast init -t aws`), and then swapping in MongoDB as the online store as seen below in the examples. + +## Examples + +### Basic configuration with MongoDB Atlas + +{% code title="feature_store.yaml" %} +```yaml +project: my_feature_repo +registry: data/registry.db +provider: local +online_store: + type: mongodb + connection_string: "mongodb+srv://username:password@cluster.mongodb.net/" # pragma: allowlist secret + database_name: feast_online_store +``` +{% endcode %} + +### Self-hosted MongoDB with authentication + +{% code title="feature_store.yaml" %} +```yaml +project: my_feature_repo +registry: data/registry.db +provider: local +online_store: + type: mongodb + connection_string: "mongodb://username:password@localhost:27017/" # pragma: allowlist secret + database_name: feast_online_store + collection_suffix: features +``` +{% endcode %} + +### MongoDB replica set configuration + +{% code title="feature_store.yaml" %} +```yaml +project: my_feature_repo +registry: data/registry.db +provider: local +online_store: + type: mongodb + connection_string: "mongodb://host1:27017,host2:27017,host3:27017/?replicaSet=myReplicaSet" + database_name: feast_online_store + client_kwargs: + retryWrites: true + w: majority +``` +{% endcode %} + +### Advanced configuration with custom client options + +{% code title="feature_store.yaml" %} +```yaml +project: my_feature_repo +registry: data/registry.db +provider: local +online_store: + type: mongodb + connection_string: "mongodb+srv://cluster.mongodb.net/" + database_name: feast_online_store + collection_suffix: features + client_kwargs: + maxPoolSize: 50 + minPoolSize: 10 + serverSelectionTimeoutMS: 5000 + connectTimeoutMS: 10000 +``` +{% endcode %} + +The full set of configuration options is available in [MongoDBOnlineStoreConfig](https://rtd.feast.dev/en/latest/#feast.infra.online_stores.mongodb_online_store.mongodb.MongoDBOnlineStoreConfig). + +## Data Model + +The MongoDB online store uses a **single collection per project** with entity key collocation. Features from multiple feature views for the same entity are stored together in a single document. + +### Example Document Schema + +The example shows a single entity. It contains 3 features from 2 feature views: "rating" and "trips_last7d" from Feature +View "driver_stats", and "surge_multiplier" from "pricing" view. +Each feature view has its own event timestamp. +The "created_timestamp" marks when the entity was materialized. + +```javascript +{ + "_id": "", // Binary entity key (bytes) + "features": { + "driver_stats": { + "rating": 4.91, + "trips_last_7d": 132 + }, + "pricing": { + "surge_multiplier": 1.2 + } + }, + "event_timestamps": { + "driver_stats": ISODate("2026-01-20T12:00:00Z"), + "pricing": ISODate("2026-01-21T08:30:00Z") + }, + "created_timestamp": ISODate("2026-01-21T12:00:05Z") +} +``` + +### Key Design Decisions + +* **`_id` field**: Uses the serialized entity key (bytes) as the primary key for efficient lookups +* **Nested features**: Features are organized by feature view name, allowing multiple feature views per entity +* **Event timestamps**: Stored per feature view to track when each feature set was last updated +* **Created timestamp**: Global timestamp for the entire document + +### Indexes + +The online store automatically creates the following index: +* Primary key index on `_id` (automatic in MongoDB), set to the serialized entity key. + +No additional indexes are required for the online store operations. + +## Async Support + +The MongoDB online store provides native async support using PyMongo 4.13+'s stable `AsyncMongoClient`. This enables: + +* **High concurrency**: Handle thousands of concurrent feature requests without thread pool limitations +* **True async I/O**: Non-blocking operations for better performance in async applications +* **10-20x performance improvement**: For concurrent workloads compared to sequential sync operations + +Both sync and async methods are fully supported: +* `online_read` / `online_read_async` +* `online_write_batch` / `online_write_batch_async` + +## Functionality Matrix + +The set of functionality supported by online stores is described in detail [here](overview.md#functionality). +Below is a matrix indicating which functionality is supported by the MongoDB online store. + +| | MongoDB | +| :-------------------------------------------------------- | :------ | +| write feature values to the online store | yes | +| read feature values from the online store | yes | +| update infrastructure (e.g. tables) in the online store | yes | +| teardown infrastructure (e.g. tables) in the online store | yes | +| generate a plan of infrastructure changes | no | +| support for on-demand transforms | yes | +| readable by Python SDK | yes | +| readable by Java | no | +| readable by Go | no | +| support for entityless feature views | yes | +| support for concurrent writing to the same key | yes | +| support for ttl (time to live) at retrieval | no | +| support for deleting expired data | no | +| collocated by feature view | no | +| collocated by feature service | no | +| collocated by entity key | yes | + +To compare this set of functionality against other online stores, please see the full [functionality matrix](overview.md#functionality-matrix). + diff --git a/docs/reference/online-stores/overview.md b/docs/reference/online-stores/overview.md index b54329ad613..6ee076b0669 100644 --- a/docs/reference/online-stores/overview.md +++ b/docs/reference/online-stores/overview.md @@ -29,26 +29,26 @@ See this [issue](https://github.com/feast-dev/feast/issues/2254) for a discussio ## Functionality Matrix There are currently five core online store implementations: `SqliteOnlineStore`, `RedisOnlineStore`, `DynamoDBOnlineStore`, `SnowflakeOnlineStore`, and `DatastoreOnlineStore`. -There are several additional implementations contributed by the Feast community (`PostgreSQLOnlineStore`, `HbaseOnlineStore`, `CassandraOnlineStore` and `IKVOnlineStore`), which are not guaranteed to be stable or to match the functionality of the core implementations. +There are several additional implementations contributed by the Feast community (`PostgreSQLOnlineStore`, `HbaseOnlineStore` and `CassandraOnlineStore`), which are not guaranteed to be stable or to match the functionality of the core implementations. Details for each specific online store, such as how to configure it in a `feature_store.yaml`, can be found [here](README.md). Below is a matrix indicating which online stores support what functionality. -| | Sqlite | Redis | DynamoDB | Snowflake | Datastore | Postgres | Hbase | [[Cassandra](https://cassandra.apache.org/_/index.html) / [Astra DB](https://www.datastax.com/products/datastax-astra?utm_source=feast)] | [IKV](https://inlined.io) | Milvus | -| :-------------------------------------------------------- | :-- | :-- | :-- | :-- | :-- | :-- | :-- | :-- | :-- |:-------| -| write feature values to the online store | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | -| read feature values from the online store | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | -| update infrastructure (e.g. tables) in the online store | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | -| teardown infrastructure (e.g. tables) in the online store | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | -| generate a plan of infrastructure changes | yes | no | no | no | no | no | no | yes | no | no | -| support for on-demand transforms | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | -| readable by Python SDK | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | -| readable by Java | no | yes | no | no | no | no | no | no | no | no | -| readable by Go | yes | yes | no | no | no | no | no | no | no | no | -| support for entityless feature views | yes | yes | yes | yes | yes | yes | yes | yes | yes | no | -| support for concurrent writing to the same key | no | yes | no | no | no | no | no | no | yes | no | -| support for ttl (time to live) at retrieval | no | yes | no | no | no | no | no | no | no | no | -| support for deleting expired data | no | yes | no | no | no | no | no | no | no | no | -| collocated by feature view | yes | no | yes | yes | yes | yes | yes | yes | no | no | -| collocated by feature service | no | no | no | no | no | no | no | no | no | no | -| collocated by entity key | no | yes | no | no | no | no | no | no | yes | no | +| | Sqlite | Redis | DynamoDB | Snowflake | Datastore | Postgres | Hbase | [[Cassandra](https://cassandra.apache.org/_/index.html) / [Astra DB](https://www.datastax.com/products/datastax-astra?utm_source=feast)] | Milvus | +| :-------------------------------------------------------- | :-- | :-- | :-- | :-- | :-- | :-- | :-- | :-- |:----| +| write feature values to the online store | yes | yes | yes | yes | yes | yes | yes | yes | yes | +| read feature values from the online store | yes | yes | yes | yes | yes | yes | yes | yes | yes | +| update infrastructure (e.g. tables) in the online store | yes | yes | yes | yes | yes | yes | yes | yes | yes | +| teardown infrastructure (e.g. tables) in the online store | yes | yes | yes | yes | yes | yes | yes | yes | yes | +| generate a plan of infrastructure changes | yes | no | no | no | no | no | no | yes | no | +| support for on-demand transforms | yes | yes | yes | yes | yes | yes | yes | yes | yes | +| readable by Python SDK | yes | yes | yes | yes | yes | yes | yes | yes | yes | +| readable by Java | no | yes | no | no | no | no | no | no | no | +| readable by Go | yes | yes | no | no | no | no | no | no | no | +| support for entityless feature views | yes | yes | yes | yes | yes | yes | yes | yes | yes | +| support for concurrent writing to the same key | no | yes | no | no | no | no | no | no | yes | +| support for ttl (time to live) at retrieval | no | yes | no | no | no | no | no | no | no | +| support for deleting expired data | no | yes | no | no | no | no | no | no | no | +| collocated by feature view | yes | no | yes | yes | yes | yes | yes | yes | no | +| collocated by feature service | no | no | no | no | no | no | no | no | no | +| collocated by entity key | no | yes | no | no | no | no | no | no | yes | diff --git a/docs/reference/online-stores/postgres.md b/docs/reference/online-stores/postgres.md index fb2253d043e..10f3f871710 100644 --- a/docs/reference/online-stores/postgres.md +++ b/docs/reference/online-stores/postgres.md @@ -6,7 +6,7 @@ The PostgreSQL online store provides support for materializing feature values in * Only the latest feature values are persisted -* sslmode, sslkey_path, sslcert_path, and sslrootcert_path are optional +* `sslmode` defaults to `require`, which encrypts the connection without certificate verification. To disable SSL (e.g. for local development), set `sslmode: disable`. For certificate verification, set `sslmode` to `verify-ca` or `verify-full` and provide the corresponding `sslrootcert_path` (and optionally `sslcert_path` and `sslkey_path` for mutual TLS) ## Getting started In order to use this online store, you'll need to run `pip install 'feast[postgres]'`. You can get started by then running `feast init -t postgres`. diff --git a/docs/reference/registries/metadata.md b/docs/reference/registries/metadata.md index 575f2a5c8b7..371be9b5289 100644 --- a/docs/reference/registries/metadata.md +++ b/docs/reference/registries/metadata.md @@ -20,6 +20,7 @@ The metadata info of Feast `feature_store.yaml` is: | registry.warehouse | N | string | snowflake warehouse name | | registry.database | N | string | snowflake db name | | registry.schema | N | string | snowflake schema name | +| registry.enable_online_feature_view_versioning | N | boolean | enable versioned online store tables and version-qualified reads (default: false). Version history tracking is always active. | | online_store | Y | | | | offline_store | Y | NA | | | | offline_store.type | Y | string | storage type | diff --git a/docs/reference/type-system.md b/docs/reference/type-system.md index 9f36f6eeaff..6353d41d90c 100644 --- a/docs/reference/type-system.md +++ b/docs/reference/type-system.md @@ -3,7 +3,7 @@ ## Motivation Feast uses an internal type system to provide guarantees on training and serving data. -Feast supports primitive types, array types, set types, and map types for feature values. +Feast supports primitive types, array types, set types, map types, JSON, and struct types for feature values. Null types are not supported, although the `UNIX_TIMESTAMP` type is nullable. The type system is controlled by [`Value.proto`](https://github.com/feast-dev/feast/blob/master/protos/feast/types/Value.proto) in protobuf and by [`types.py`](https://github.com/feast-dev/feast/blob/master/sdk/python/feast/types.py) in Python. Type conversion logic can be found in [`type_map.py`](https://github.com/feast-dev/feast/blob/master/sdk/python/feast/type_map.py). @@ -24,6 +24,22 @@ Feast supports the following data types: | `Bytes` | `bytes` | Binary data | | `Bool` | `bool` | Boolean value | | `UnixTimestamp` | `datetime` | Unix timestamp (nullable) | +| `Uuid` | `uuid.UUID` | UUID (any version) | +| `TimeUuid` | `uuid.UUID` | Time-based UUID (version 1) | +| `Decimal` | `decimal.Decimal` | Arbitrary-precision decimal number | + +### Domain-Specific Primitive Types + +These types are semantic aliases over `Bytes` for domain-specific use cases (e.g., RAG pipelines, image processing). They are stored as `bytes` at the proto level. + +| Feast Type | Python Type | Description | +|------------|-------------|-------------| +| `PdfBytes` | `bytes` | PDF document binary data (used in RAG / document processing pipelines) | +| `ImageBytes` | `bytes` | Image binary data (used in image processing / multimodal pipelines) | + +{% hint style="warning" %} +`PdfBytes` and `ImageBytes` are not natively supported by any backend's type inference. You must explicitly declare them in your feature view schema. Backend storage treats them as raw `bytes`. +{% endhint %} ### Array Types @@ -39,10 +55,13 @@ All primitive types have corresponding array (list) types: | `Array(Bytes)` | `List[bytes]` | List of binary data | | `Array(Bool)` | `List[bool]` | List of booleans | | `Array(UnixTimestamp)` | `List[datetime]` | List of timestamps | +| `Array(Uuid)` | `List[uuid.UUID]` | List of UUIDs | +| `Array(TimeUuid)` | `List[uuid.UUID]` | List of time-based UUIDs | +| `Array(Decimal)` | `List[decimal.Decimal]` | List of arbitrary-precision decimals | ### Set Types -All primitive types (except Map) have corresponding set types for storing unique values: +All primitive types (except `Map` and `Json`) have corresponding set types for storing unique values: | Feast Type | Python Type | Description | |------------|-------------|-------------| @@ -54,19 +73,120 @@ All primitive types (except Map) have corresponding set types for storing unique | `Set(Bytes)` | `Set[bytes]` | Set of unique binary data | | `Set(Bool)` | `Set[bool]` | Set of unique booleans | | `Set(UnixTimestamp)` | `Set[datetime]` | Set of unique timestamps | +| `Set(Uuid)` | `Set[uuid.UUID]` | Set of unique UUIDs | +| `Set(TimeUuid)` | `Set[uuid.UUID]` | Set of unique time-based UUIDs | +| `Set(Decimal)` | `Set[decimal.Decimal]` | Set of unique arbitrary-precision decimals | **Note:** Set types automatically remove duplicate values. When converting from lists or other iterables to sets, duplicates are eliminated. +{% hint style="warning" %} +**Backend limitations for Set types:** + +- **No backend infers Set types from schema.** No offline store (BigQuery, Snowflake, Redshift, PostgreSQL, Spark, Athena, MSSQL) maps its native types to Feast Set types. You **must** explicitly declare Set types in your feature view schema. +- **No native PyArrow set type.** Feast converts Sets to `pyarrow.list_()` internally, but `feast_value_type_to_pa()` in `type_map.py` does not include Set mappings, which can cause errors in some code paths. +- **Online stores** that serialize proto bytes (e.g., SQLite, Redis, DynamoDB) handle Sets correctly. +- **Offline stores** may not handle Set types correctly during retrieval. For example, the Ray offline store only special-cases `_LIST` types, not `_SET`. +- Set types are best suited for **online serving** use cases where feature values are written as Python sets and retrieved via `get_online_features`. +{% endhint %} + +### Nested Collection Types + +Feast supports arbitrarily nested collections using a recursive `VALUE_LIST` / `VALUE_SET` design. The outer container determines the proto enum (`VALUE_LIST` for `Array(…)`, `VALUE_SET` for `Set(…)`), while the full inner type structure is persisted via a mandatory `feast:nested_inner_type` Field tag. + +| Feast Type | Python Type | ValueType | Description | +|------------|-------------|-----------|-------------| +| `Array(Array(T))` | `List[List[T]]` | `VALUE_LIST` | List of lists | +| `Array(Set(T))` | `List[List[T]]` | `VALUE_LIST` | List of sets | +| `Set(Array(T))` | `List[List[T]]` | `VALUE_SET` | Set of lists | +| `Set(Set(T))` | `List[List[T]]` | `VALUE_SET` | Set of sets | +| `Array(Array(Array(T)))` | `List[List[List[T]]]` | `VALUE_LIST` | 3-level nesting | + +Where `T` is any supported primitive type (Int32, Int64, Float32, Float64, String, Bytes, Bool, UnixTimestamp) or another nested collection type. + +**Notes:** +- Nesting depth is **unlimited**. `Array(Array(Array(T)))`, `Set(Array(Set(T)))`, etc. are all supported. +- Inner type information is preserved via Field tags (`feast:nested_inner_type`) and restored during deserialization. This tag is mandatory for nested collection types. +- Empty inner collections (`[]`) are stored as empty proto values and round-trip as `None`. For example, `[[1, 2], [], [3]]` becomes `[[1, 2], None, [3]]` after a write-read cycle. + ### Map Types Map types allow storing dictionary-like data structures: | Feast Type | Python Type | Description | |------------|-------------|-------------| -| `Map` | `Dict[str, Any]` | Dictionary with string keys and any supported Feast type as values (including nested maps) | +| `Map` | `Dict[str, Any]` | Dictionary with string keys and values of any supported Feast type (including nested maps) | | `Array(Map)` | `List[Dict[str, Any]]` | List of dictionaries | -**Note:** Map keys must always be strings. Map values can be any supported Feast type, including primitives, arrays, or nested maps. +**Note:** Map keys must always be strings. Map values can be any supported Feast type, including primitives, arrays, or nested maps at the proto level. However, the PyArrow representation is `map`, which means backends that rely on PyArrow schemas (e.g., during materialization) treat Map as string-to-string. + +**Backend support for Map:** + +| Backend | Native Type | Notes | +|---------|-------------|-------| +| PostgreSQL | `jsonb`, `jsonb[]` | `jsonb` → `Map`, `jsonb[]` → `Array(Map)` | +| Snowflake | `VARIANT`, `OBJECT` | Inferred as `Map` | +| Redshift | `SUPER` | Inferred as `Map` | +| Spark | `map` | `map<>` → `Map`, `array>` → `Array(Map)` | +| Athena | `map` | Inferred as `Map` | +| MSSQL | `nvarchar(max)` | Serialized as string | +| DynamoDB / Redis | Proto bytes | Full proto Map support | + +### JSON Type + +The `Json` type represents opaque JSON data. Unlike `Map`, which is schema-free key-value storage, `Json` is stored as a string at the proto level but backends use native JSON types where available. + +| Feast Type | Python Type | Description | +|------------|-------------|-------------| +| `Json` | `str` (JSON-encoded) | JSON data stored as a string at the proto level | +| `Array(Json)` | `List[str]` | List of JSON strings | + +**Backend support for Json:** + +| Backend | Native Type | +|---------|-------------| +| PostgreSQL | `jsonb` | +| Snowflake | `JSON` / `VARIANT` | +| Redshift | `json` | +| BigQuery | `JSON` | +| Spark | Not natively distinguished from `String` | +| MSSQL | `nvarchar(max)` | + +{% hint style="info" %} +When a backend's native type is ambiguous (e.g., PostgreSQL `jsonb` could be `Map` or `Json`), **the schema-declared Feast type takes precedence**. The backend-to-Feast mappings are only used during schema inference when no explicit type is provided. +{% endhint %} + +### Struct Type + +The `Struct` type represents a schema-aware structured type with named, typed fields. Unlike `Map` (which is schema-free), a `Struct` declares its field names and their types, enabling schema validation. + +| Feast Type | Python Type | Description | +|------------|-------------|-------------| +| `Struct({"field": Type, ...})` | `Dict[str, Any]` | Named fields with typed values | +| `Array(Struct({"field": Type, ...}))` | `List[Dict[str, Any]]` | List of structs | + +**Example:** +```python +from feast.types import Struct, String, Int32, Array + +# Struct with named, typed fields +address_type = Struct({"street": String, "city": String, "zip": Int32}) +Field(name="address", dtype=address_type) + +# Array of structs +items_type = Array(Struct({"name": String, "quantity": Int32})) +Field(name="order_items", dtype=items_type) +``` + +**Backend support for Struct:** + +| Backend | Native Type | +|---------|-------------| +| BigQuery | `STRUCT` / `RECORD` | +| Spark | `struct<...>` / `array>` | +| PostgreSQL | `jsonb` (serialized) | +| Snowflake | `VARIANT` (serialized) | +| MSSQL | `nvarchar(max)` (serialized) | +| DynamoDB / Redis | Proto bytes | ## Complete Feature View Example @@ -77,7 +197,7 @@ from datetime import timedelta from feast import Entity, FeatureView, Field, FileSource from feast.types import ( Int32, Int64, Float32, Float64, String, Bytes, Bool, UnixTimestamp, - Array, Set, Map + Uuid, TimeUuid, Decimal, Array, Set, Map, Json, Struct ) # Define a data source @@ -107,7 +227,10 @@ user_features = FeatureView( Field(name="profile_picture", dtype=Bytes), Field(name="is_active", dtype=Bool), Field(name="last_login", dtype=UnixTimestamp), - + Field(name="session_id", dtype=Uuid), + Field(name="event_id", dtype=TimeUuid), + Field(name="price", dtype=Decimal), + # Array types Field(name="daily_steps", dtype=Array(Int32)), Field(name="transaction_history", dtype=Array(Int64)), @@ -117,17 +240,34 @@ user_features = FeatureView( Field(name="document_hashes", dtype=Array(Bytes)), Field(name="notification_settings", dtype=Array(Bool)), Field(name="login_timestamps", dtype=Array(UnixTimestamp)), - - # Set types (unique values only) + Field(name="related_session_ids", dtype=Array(Uuid)), + Field(name="event_chain", dtype=Array(TimeUuid)), + Field(name="historical_prices", dtype=Array(Decimal)), + + # Set types (unique values only — see backend caveats above) Field(name="visited_pages", dtype=Set(String)), Field(name="unique_categories", dtype=Set(Int32)), Field(name="tag_ids", dtype=Set(Int64)), Field(name="preferred_languages", dtype=Set(String)), - + Field(name="unique_device_ids", dtype=Set(Uuid)), + Field(name="unique_event_ids", dtype=Set(TimeUuid)), + Field(name="unique_prices", dtype=Set(Decimal)), + # Map types Field(name="user_preferences", dtype=Map), Field(name="metadata", dtype=Map), Field(name="activity_log", dtype=Array(Map)), + + # Nested collection types + Field(name="weekly_scores", dtype=Array(Array(Float64))), + Field(name="unique_tags_per_category", dtype=Array(Set(String))), + + # JSON type + Field(name="raw_event", dtype=Json), + + # Struct type + Field(name="address", dtype=Struct({"street": String, "city": String, "zip": Int32})), + Field(name="order_items", dtype=Array(Struct({"name": String, "qty": Int32}))), ], source=user_features_source, ) @@ -151,6 +291,93 @@ tag_list = [100, 200, 300, 100, 200] tag_ids = set(tag_list) # {100, 200, 300} ``` +### UUID Type Usage Examples + +UUID types store universally unique identifiers natively, with support for both random UUIDs and time-based UUIDs: + +```python +import uuid + +# Random UUID (version 4) — use Uuid type +session_id = uuid.uuid4() # e.g., UUID('a8098c1a-f86e-11da-bd1a-00112444be1e') + +# Time-based UUID (version 1) — use TimeUuid type +event_id = uuid.uuid1() # e.g., UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8') + +# UUID values are returned as uuid.UUID objects from get_online_features() +response = store.get_online_features( + features=["user_features:session_id"], + entity_rows=[{"user_id": 1}], +) +result = response.to_dict() +# result["session_id"][0] is a uuid.UUID object + +# UUID lists +related_sessions = [uuid.uuid4(), uuid.uuid4(), uuid.uuid4()] + +# UUID sets (unique values) +unique_devices = {uuid.uuid4(), uuid.uuid4()} +``` + +### Decimal Type Usage Examples + +The `Decimal` type stores arbitrary-precision decimal numbers using Python's `decimal.Decimal`. +Values are stored as strings in the proto to preserve full precision — no floating-point rounding occurs. + +```python +import decimal + +# Scalar decimal — e.g., a financial price +price = decimal.Decimal("19.99") + +# High-precision value — all digits preserved +tax_rate = decimal.Decimal("0.08750000000000000000") + +# Decimal values are returned as decimal.Decimal objects from get_online_features() +response = store.get_online_features( + features=["product_features:price"], + entity_rows=[{"product_id": 42}], +) +result = response.to_dict() +# result["price"][0] is a decimal.Decimal object + +# Decimal lists — e.g., a history of prices +historical_prices = [ + decimal.Decimal("18.50"), + decimal.Decimal("19.00"), + decimal.Decimal("19.99"), +] + +# Decimal sets — unique price points seen +unique_prices = {decimal.Decimal("9.99"), decimal.Decimal("19.99"), decimal.Decimal("29.99")} +``` + +{% hint style="warning" %} +`Decimal` is **not** inferred from any backend schema. You must declare it explicitly in your feature view schema. The pandas dtype for `Decimal` columns is `object` (holding `decimal.Decimal` instances), not a numeric dtype. +{% endhint %} + +### Nested Collection Type Usage Examples + +```python +# List of lists — e.g., weekly score history per user +weekly_scores = [[85.0, 90.5, 78.0], [92.0, 88.5], [95.0, 91.0, 87.5]] + +# List of sets — e.g., unique tags assigned per category +unique_tags_per_category = [["python", "ml"], ["rust", "systems"], ["python", "web"]] + +# 3-level nesting — e.g., multi-dimensional matrices +Field(name="tensor", dtype=Array(Array(Array(Float64)))) + +# Mixed nesting +Field(name="grouped_tags", dtype=Array(Set(Array(String)))) +``` + +**Limitation:** Empty inner collections round-trip as `None`: +```python +# Input: [[1, 2], [], [3]] +# Output: [[1, 2], None, [3]] (empty [] becomes None after write-read cycle) +``` + ### Map Type Usage Examples Maps can store complex nested data structures: @@ -184,6 +411,42 @@ activity_log = [ ] ``` +### JSON Type Usage Examples + +Feast's `Json` type stores values as JSON strings at the proto level. You can pass either a +pre-serialized JSON string or a Python dict/list — Feast will call `json.dumps()` automatically +when the value is not already a string: + +```python +import json + +# Option 1: pass a Python dict — Feast calls json.dumps() internally during proto conversion +raw_event = {"type": "click", "target": "button_1", "metadata": {"page": "home"}} + +# Option 2: pass an already-serialized JSON string — Feast validates it via json.loads() +raw_event = '{"type": "click", "target": "button_1", "metadata": {"page": "home"}}' + +# When building a DataFrame for store.push(), values must be strings since +# Pandas/PyArrow columns expect uniform types: +import pandas as pd +event_df = pd.DataFrame({ + "user_id": ["user_1"], + "event_timestamp": [datetime.now()], + "raw_event": [json.dumps({"type": "click", "target": "button_1"})], +}) +store.push("event_push_source", event_df) +``` + +### Struct Type Usage Examples + +```python +# Struct — schema-aware, fields and types are declared +from feast.types import Struct, String, Int32 + +address = Struct({"street": String, "city": String, "zip": Int32}) +# Value: {"street": "123 Main St", "city": "Springfield", "zip": 62704} +``` + ## Type System in Practice The sections below explain how Feast uses its type system in different contexts. @@ -195,7 +458,11 @@ For example, if the `schema` parameter is not specified for a feature view, Feas Each of these columns must be associated with a Feast type, which requires conversion from the data source type system to the Feast type system. * The feature inference logic calls `_infer_features_and_entities`. * `_infer_features_and_entities` calls `source_datatype_to_feast_value_type`. -* `source_datatype_to_feast_value_type` cals the appropriate method in `type_map.py`. For example, if a `SnowflakeSource` is being examined, `snowflake_python_type_to_feast_value_type` from `type_map.py` will be called. +* `source_datatype_to_feast_value_type` calls the appropriate method in `type_map.py`. For example, if a `SnowflakeSource` is being examined, `snowflake_python_type_to_feast_value_type` from `type_map.py` will be called. + +{% hint style="info" %} +**Types that cannot be inferred:** `Set`, `Json`, `Struct`, `Decimal`, `PdfBytes`, and `ImageBytes` types are never inferred from backend schemas. If you use these types, you must declare them explicitly in your feature view schema. +{% endhint %} ### Materialization diff --git a/docs/rfcs/feature-view-versioning.md b/docs/rfcs/feature-view-versioning.md new file mode 100644 index 00000000000..cb79c4dd265 --- /dev/null +++ b/docs/rfcs/feature-view-versioning.md @@ -0,0 +1,452 @@ +# RFC: Feature View Versioning + +**Status:** In Review +**Authors:** @farceo +**Branch:** `featureview-versioning` +**Date:** 2026-03-17 + +## Summary + +This RFC proposes adding automatic version tracking to Feast feature views. Every time `feast apply` detects a schema or UDF change to a feature view, a versioned snapshot is saved to the registry. Users can list version history, pin serving to a prior version, and optionally query specific versions at read time using `@v` syntax. + +## Motivation + +Today, when a feature view's schema changes, the old definition is silently overwritten. This creates several problems: + +1. **No audit trail.** Teams can't answer "what did this feature view look like last week?" or "who changed the schema and when?" +2. **No safe rollback.** If a schema change breaks a downstream model, there's no way to revert to the previous definition without manually reconstructing it. +3. **No multi-version serving.** During migrations, teams often need to serve both the old and new schema simultaneously (e.g., model A uses v1 features, model B uses v2 features). This is currently impossible without creating entirely separate feature views. + +## Diagrams + +### Lifecycle Flow + +Shows what happens during `feast apply` and `get_online_features`, and how version +history, pinning, and version-qualified reads fit together. + +``` + feast apply + | + v + +------------------------+ + | Compare new definition | + | against active FV | + +------------------------+ + | | + schema/UDF metadata only + changed changed + | | + v v + +--------------+ +------------------+ + | Save old as | | Update in place, | + | version N | | no new version | + | Save new as | +------------------+ + | version N+1 | + +--------------+ + | + +------------+------------+ + | | + v v + +----------------+ +-------------------+ + | Registry | | Online Store | + | (version | | (only if flag on) | + | history) | +-------------------+ + +----------------+ | + | +------+------+ + | | | + v v v + +----------------+ +--------+ +-----------+ + | feast versions | | proj_ | | proj_ | + | feast pin v2 | | fv | | fv_v1 | + | list / get | | (v0) | | fv_v2 ... | + +----------------+ +--------+ +-----------+ + Always available Unversioned Versioned + table tables + + + get_online_features + | + v + +---------------------+ + | Parse feature refs | + +---------------------+ + | | + "fv:feature" "fv@v2:feature" + (no version) (version-qualified) + | | + v v + +------------+ +------------------+ + | Read from | | flag enabled? | + | active FV | +------------------+ + | table | | | + +------------+ yes no + | | + v v + +------------+ +-------+ + | Look up v2 | | raise | + | snapshot, | | error | + | read from | +-------+ + | proj_fv_v2 | + +------------+ +``` + +### Architecture / Storage + +Shows how version data is stored in the registry and online store, and the +relationship between the active definition and historical snapshots. + +``` ++--feature_store.yaml------------------------------------------+ +| registry: | +| path: data/registry.db | +| enable_online_feature_view_versioning: true (optional) | ++--------------------------------------------------------------+ + | | + v v ++--Registry (file or SQL)--+ +--Online Store (SQLite, ...)---+ +| | | | +| Active Feature Views | | Unversioned tables (v0) | +| +--------------------+ | | +-------------------------+ | +| | driver_stats | | | | proj_driver_stats | | +| | version: latest | | | | driver_id | trips | . | | +| | current_ver: 2 | | | +-------------------------+ | +| | schema: [...] | | | | +| +--------------------+ | | Versioned tables (v1+) | +| | | +-------------------------+ | +| Version History | | | proj_driver_stats_v1 | | +| +--------------------+ | | | driver_id | trips | . | | +| | v0: proto snapshot | | | +-------------------------+ | +| | created: Jan 15 | | | +-------------------------+ | +| | v1: proto snapshot | | | | proj_driver_stats_v2 | | +| | created: Jan 16 | | | | driver_id | trips | . | | +| | v2: proto snapshot | | | +-------------------------+ | +| | created: Jan 20 | | | | +| +--------------------+ | +-------------------------------+ +| | +| Always active. | Only created when flag is on +| No flag needed. | and feast materialize is run. ++--------------------------+ +``` + +## Design + +### Core Concepts + +- **Version number**: An auto-incrementing integer (v0, v1, v2, ...) assigned to each schema-significant change. +- **Version snapshot**: A serialized copy of the full feature view proto at that version, stored in the registry's version history table. +- **Version pin**: Setting `version="v2"` on a feature view replaces the active definition with the v2 snapshot — essentially a revert. +- **Version-qualified ref**: The `@v` syntax in feature references (e.g., `driver_stats@v2:trips_today`) for reading from a specific version's online store table. + +### What Triggers a New Version + +Only **schema and UDF changes** create new versions. Metadata-only changes (description, tags, owner, TTL, online/offline flags) update the active definition in place without creating a version. + +Schema-significant changes include: +- Adding, removing, or retyping feature columns +- Changing entities or entity columns +- Changing the UDF code (StreamFeatureView, OnDemandFeatureView) + +This keeps version history meaningful — a new version number always means a real structural change. + +### What Does NOT Trigger a New Version + +- Re-applying an identical definition (idempotent) +- Changing `description`, `tags`, `owner` +- Changing `ttl`, `online`, `offline` flags +- Changing data source paths/locations (treated as deployment config) + +### Version History Is Always-On + +Version history tracking is lightweight registry metadata — just a serialized proto snapshot per version. There is no performance cost to the online path and no additional infrastructure required. For this reason, version history is **always active** with no opt-in flag needed. + +Out of the box, every `feast apply` that changes a feature view will: +- Record a version snapshot +- Support `feast feature-views list-versions ` to list history +- Support `registry.list_feature_view_versions(name, project)` programmatically +- Support `registry.get_feature_view_by_version(name, project, version_number)` for snapshot retrieval +- Support version pinning via `version="v2"` in feature view definitions + +### Online Versioning Is Opt-In + +The expensive/risky part of versioning is creating **separate online store tables per version** and routing reads to them. This is gated behind a config flag: + +```yaml +registry: + path: data/registry.db + enable_online_feature_view_versioning: true +``` + +When enabled, version-qualified refs like `driver_stats@v2:trips_today` in `get_online_features()` will: +1. Look up the v2 snapshot from version history +2. Read from a version-specific online store table (`project_driver_stats_v2`) + +When disabled (the default), using `@v` refs raises a clear error. All other versioning features (history, listing, pinning, snapshot retrieval) work regardless. + +### Storage + +**File-based registry**: Version history is stored as a repeated `FeatureViewVersionRecord` message in the registry proto, alongside the existing feature view definitions. + +**SQL registry**: A dedicated `feature_view_version_history` table with columns for name, project, version number, type, proto bytes, and creation timestamp. + +### Version Pinning + +Pinning replaces the active feature view with a historical snapshot: + +```python +driver_stats = FeatureView( + name="driver_stats", + entities=[driver], + schema=[...], + source=my_source, + version="v2", # revert to v2's definition +) +``` + +Safety constraints: +- The user's feature view definition (minus the version field) must match the currently active definition. If the user changed both the schema and the version pin simultaneously, `feast apply` raises `FeatureViewPinConflict`. This prevents accidental "I thought I was reverting but I also changed things." +- Pinning does not modify version history — v0, v1, v2 snapshots remain intact. +- After a pin, removing the version field (or setting `version="latest"`) returns to auto-incrementing behavior. If the next `feast apply` detects a schema change, a new version is created. + +### Version-Qualified Feature References + +The `@v` syntax extends the existing `feature_view:feature` reference format: + +```python +features = store.get_online_features( + features=[ + "driver_stats:trips_today", # latest (default) + "driver_stats@v2:trips_today", # read from v2 + "driver_stats@v1:avg_rating", # read from v1 + ], + entity_rows=[{"driver_id": 1001}], +) +``` + +Online store table naming: +- v0 uses the existing unversioned table (`project_driver_stats`) for backward compatibility +- v1+ use suffixed tables (`project_driver_stats_v1`, `project_driver_stats_v2`) + +Each version requires its own materialization. `@latest` always resolves to the active version. + +### Supported Feature View Types + +Versioning works on all three feature view types: +- `FeatureView` / `BatchFeatureView` +- `StreamFeatureView` +- `OnDemandFeatureView` + +### Online Store Support + +Version-qualified reads (`@v`) are currently implemented for the **SQLite** online store. Other online stores will raise a clear error. Expanding to additional stores is follow-up work. + +### Materialization + +Each version's data lives in its own online store table (e.g., `project_fv_v1`, `project_fv_v2`). By default, `feast materialize` and `feast materialize-incremental` populate the **active (latest)** version's table. To populate a specific version's table, pass the `--version` flag along with a single `--views` target: + +```bash +# Materialize v1 of driver_stats +feast materialize --views driver_stats --version v1 2024-01-01T00:00:00 2024-01-15T00:00:00 + +# Incrementally materialize v2 of driver_stats +feast materialize-incremental --views driver_stats --version v2 2024-01-15T00:00:00 +``` + +Python SDK equivalent: + +```python +store.materialize( + feature_views=["driver_stats"], + version="v2", + start_date=start, + end_date=end, +) +``` + +**Requirements:** +- `enable_online_feature_view_versioning: true` must be set in `feature_store.yaml` +- `--version` requires `--views` with exactly one feature view name +- The specified version must exist in the registry (created by a prior `feast apply`) +- Without `--version`, materialization targets the active version's table (existing behavior) + +**Multi-version workflow example:** + +```bash +# Model A uses v1, Model B uses v2 — populate both tables +feast materialize --views driver_stats --version v1 2024-01-01T00:00:00 2024-02-01T00:00:00 +feast materialize --views driver_stats --version v2 2024-01-01T00:00:00 2024-02-01T00:00:00 + +# Models can now query their respective versions online +# Model A: store.get_online_features(features=["driver_stats@v1:trips_today"], ...) +# Model B: store.get_online_features(features=["driver_stats@v2:trips_today"], ...) +``` + +## API Surface + +### Python SDK + +```python +# List version history +versions = store.list_feature_view_versions("driver_stats") +# [{"version": "v0", "version_number": 0, "created_timestamp": ..., ...}, ...] + +# Get a specific version's definition +fv_v1 = store.registry.get_feature_view_by_version("driver_stats", project, 1) + +# Pin to a version +FeatureView(name="driver_stats", ..., version="v2") + +# Version-qualified online read (requires enable_online_feature_view_versioning) +store.get_online_features(features=["driver_stats@v2:trips_today"], ...) + +# Materialize a specific version +store.materialize(feature_views=["driver_stats"], version="v2", start_date=start, end_date=end) +store.materialize_incremental(feature_views=["driver_stats"], version="v2", end_date=end) +``` + +### CLI + +```bash +# List versions +feast feature-views list-versions driver_stats + +# Output: +# VERSION TYPE CREATED VERSION_ID +# v0 feature_view 2024-01-15 10:30:00 a1b2c3d4-... +# v1 feature_view 2024-01-16 14:22:00 e5f6g7h8-... + +# Materialize a specific version +feast materialize --views driver_stats --version v2 2024-01-01T00:00:00 2024-02-01T00:00:00 +feast materialize-incremental --views driver_stats --version v2 2024-02-01T00:00:00 +``` + +### Configuration + +```yaml +# feature_store.yaml +registry: + path: data/registry.db + # Optional: enable versioned online tables and @v reads (default: false) + enable_online_feature_view_versioning: true +``` + +## Migration & Backward Compatibility + +- **Zero breaking changes.** All existing feature views continue to work. The `version` parameter defaults to `"latest"` and `current_version_number` defaults to `None`. +- **Existing online data is preserved.** The unversioned online store table is treated as v0. No data migration needed. +- **Version history starts on first apply.** Pre-existing feature views get a v0 snapshot on their next `feast apply`. +- **Proto backward compatibility.** The new `version` and `current_version_number` fields use proto defaults (empty string and 0) so old protos deserialize correctly. + +## Concurrency + +Two concurrent `feast apply` calls on the same feature view can race on version number assignment. The behavior depends on the version mode and registry backend. + +### `version="latest"` (auto-increment) + +The registry computes `MAX(version_number) + 1` and saves the new snapshot. If two concurrent applies race on the same version number: + +- **SQL registry**: The unique constraint on `(feature_view_name, project_id, version_number)` causes an `IntegrityError`. The registry catches this and retries up to 3 times, re-reading `MAX + 1` each time. Since the client said "latest", the exact version number doesn't matter. +- **File registry**: Last-write-wins. The file registry uses an in-memory proto with no database-level constraints, so concurrent writes may overwrite each other. This is a pre-existing limitation for all file registry operations. + +### `version="v"` (explicit version) + +The registry checks whether version N already exists: + +- **Exists** → pin/revert to that version's snapshot (unchanged behavior) +- **Doesn't exist** → forward declaration: create version N with the provided definition + +If two concurrent applies both try to forward-declare the same version: + +- **SQL registry**: The first one succeeds; the second gets a `ConcurrentVersionConflict` error with a clear message to pull latest and retry. +- **File registry**: Last-write-wins (same pre-existing limitation). + +### Recommendations + +- For single-developer or CI/CD workflows, the file registry works fine. +- For multi-client environments with concurrent applies, use the SQL registry for proper conflict detection. + +## Staged Publishing (`--no-promote`) + +By default, `feast apply` atomically saves a version snapshot **and** promotes it to the active definition. This works well for additive changes, but for breaking schema changes you may want to stage the new version without disrupting unversioned consumers. + +### The Problem + +Without `--no-promote`, a phased rollout looks like: + +1. `feast apply` — saves v2 and promotes it (all unversioned consumers now hit v2) +2. Immediately pin back to v1 — `version="v1"` in the definition, then `feast apply` again + +This leaves a transition window where unversioned consumers briefly see the new schema. Authors can also forget the pin-back step. + +### The Solution + +The `--no-promote` flag saves the version snapshot without updating the active feature view definition. The new version is accessible only via explicit `@v` reads and `--version` materialization. + +**CLI usage:** + +```bash +feast apply --no-promote +``` + +**Python SDK equivalent:** + +```python +store.apply([entity, feature_view], no_promote=True) +``` + +### Phased Rollout Workflow + +1. **Stage the new version:** + ```bash + feast apply --no-promote + ``` + This publishes v2 without promoting it. All unversioned consumers continue using v1. + +2. **Populate the v2 online table:** + ```bash + feast materialize --views driver_stats --version v2 ... + ``` + +3. **Migrate consumers one at a time:** + - Consumer A switches to `driver_stats@v2:trips_today` + - Consumer B switches to `driver_stats@v2:avg_rating` + +4. **Promote v2 as the default:** + ```bash + feast apply + ``` + Or pin to v2: set `version="v2"` in the definition and run `feast apply`. + +> **Note:** By default, `feast apply` (without `--no-promote`) promotes the new version immediately. Use `--no-promote` only when you need a controlled, phased rollout. + +## Feature Services + +Feature services work with versioned feature views when the online versioning flag is enabled: + +- **Automatic version resolution.** When `enable_online_feature_view_versioning` is `true` and a feature service references a versioned feature view (`current_version_number > 0`), the serving path automatically sets `version_tag` on the projection. This ensures `get_online_features()` reads from the correct versioned online store table (e.g., `project_driver_stats_v1`) instead of the unversioned table. +- **Version-qualified feature refs.** Both `_get_features()` and `_get_feature_views_to_use()` produce version-qualified keys (e.g., `driver_stats@v1:trips_today`) for feature services referencing versioned FVs, keeping the feature ref index and the FV lookup index in sync. +- **Gated by flag.** If any feature view referenced by a feature service has been versioned (`current_version_number > 0`) but `enable_online_feature_view_versioning` is `false`: + - `feast apply` will reject the feature service with a clear error. + - `get_online_features()` will fail at retrieval time with a descriptive error message. +- **No `@v` syntax in feature services.** Version-qualified reads (`driver_stats@v2:trips_today`) using the `@v` syntax require string-based feature references passed directly to `get_online_features()`. Feature services always resolve to the active (latest) version of each referenced feature view. +- **Future work: per-reference version pinning.** A future enhancement could allow feature services to pin individual feature view references to specific versions (e.g., `FeatureService(features=[driver_stats["v2"]])`). +- **`--no-promote` versions are not served.** Feature services always resolve to the active (promoted) version. Versions published with `--no-promote` are not visible to feature services until promoted via a regular `feast apply` or explicit pin. + +## Limitations & Future Work + +- **Online store coverage.** Version-qualified reads are only on SQLite today. Redis, DynamoDB, Bigtable, Postgres, etc. are follow-up work. +- **Offline store versioning.** This RFC covers online reads only. Versioned historical retrieval is out of scope. +- **Version deletion.** There is no mechanism to prune old versions. This could be added later if registries grow large. +- **Cross-version joins.** Joining features from different versions of the same feature view in `get_historical_features` is not supported. +- **Naming restrictions.** Feature view names must not contain `@` or `:` since these characters are reserved for version-qualified references (`fv@v2:feature`). `feast apply` rejects new feature views with these characters. The parser falls back gracefully for legacy feature views that already contain `@` in their names — unrecognized `@` suffixes are treated as part of the name rather than raising errors. + +## Open Questions + +1. **Should version history have a retention policy?** For long-lived feature views with frequent schema changes, version history could grow unbounded. A `max_versions` config or TTL-based pruning could help. +2. **Should version-qualified refs work in `get_historical_features`?** The current implementation is online-only. Offline versioned reads would require point-in-time-correct version resolution. +3. **Should we support version aliases?** e.g., `driver_stats@stable:trips` mapping to a pinned version number via config. + +## References + +- Branch: `featureview-versioning` +- Documentation: `docs/getting-started/concepts/feature-view.md` (Versioning section) +- Tests: `sdk/python/tests/integration/registration/test_versioning.py`, `sdk/python/tests/unit/test_feature_view_versioning.py` diff --git a/docs/roadmap.md b/docs/roadmap.md index b7bab598cca..a6389b3ce51 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -17,33 +17,53 @@ The list below contains the functionality that contributors are planning to deve * [x] [Postgres (contrib plugin)](https://docs.feast.dev/reference/data-sources/postgres) * [x] [Spark (contrib plugin)](https://docs.feast.dev/reference/data-sources/spark) * [x] [Couchbase (contrib plugin)](https://docs.feast.dev/reference/data-sources/couchbase) + * [x] [Athena (contrib plugin)](https://docs.feast.dev/reference/data-sources/athena) + * [x] [Clickhouse (contrib plugin)](https://docs.feast.dev/reference/data-sources/clickhouse) + * [x] [Oracle (contrib plugin)](https://docs.feast.dev/reference/data-sources/oracle) * [x] Kafka / Kinesis sources (via [push support into the online store](https://docs.feast.dev/reference/data-sources/push)) * **Offline Stores** * [x] [Snowflake](https://docs.feast.dev/reference/offline-stores/snowflake) * [x] [Redshift](https://docs.feast.dev/reference/offline-stores/redshift) * [x] [BigQuery](https://docs.feast.dev/reference/offline-stores/bigquery) - * [x] [Azure Synapse + Azure SQL (contrib plugin)](https://docs.feast.dev/reference/offline-stores/mssql.md) + * [x] [DuckDB](https://docs.feast.dev/reference/offline-stores/duckdb) + * [x] [Dask](https://docs.feast.dev/reference/offline-stores/dask) + * [x] [Remote](https://docs.feast.dev/reference/offline-stores/remote-offline-store) + * [x] [Azure Synapse + Azure SQL (contrib plugin)](https://docs.feast.dev/reference/offline-stores/mssql) * [x] [Hive (community plugin)](https://github.com/baineng/feast-hive) * [x] [Postgres (contrib plugin)](https://docs.feast.dev/reference/offline-stores/postgres) - * [x] [Trino (contrib plugin)](https://github.com/Shopify/feast-trino) + * [x] [Trino (contrib plugin)](https://docs.feast.dev/reference/offline-stores/trino) * [x] [Spark (contrib plugin)](https://docs.feast.dev/reference/offline-stores/spark) * [x] [Couchbase (contrib plugin)](https://docs.feast.dev/reference/offline-stores/couchbase) - * [x] [In-memory / Pandas](https://docs.feast.dev/reference/offline-stores/file) + * [x] [Athena (contrib plugin)](https://docs.feast.dev/reference/offline-stores/athena) + * [x] [Clickhouse (contrib plugin)](https://docs.feast.dev/reference/offline-stores/clickhouse) + * [x] [Ray (contrib plugin)](https://docs.feast.dev/reference/offline-stores/ray) + * [x] [Oracle (contrib plugin)](https://docs.feast.dev/reference/offline-stores/oracle) + * [x] [Hybrid](https://docs.feast.dev/reference/offline-stores/hybrid) * [x] [Custom offline store support](https://docs.feast.dev/how-to-guides/customizing-feast/adding-a-new-offline-store) * **Online Stores** * [x] [Snowflake](https://docs.feast.dev/reference/online-stores/snowflake) * [x] [DynamoDB](https://docs.feast.dev/reference/online-stores/dynamodb) * [x] [Redis](https://docs.feast.dev/reference/online-stores/redis) + * [x] [Dragonfly](https://docs.feast.dev/reference/online-stores/dragonfly) * [x] [Datastore](https://docs.feast.dev/reference/online-stores/datastore) * [x] [Bigtable](https://docs.feast.dev/reference/online-stores/bigtable) * [x] [SQLite](https://docs.feast.dev/reference/online-stores/sqlite) - * [x] [Dragonfly](https://docs.feast.dev/reference/online-stores/dragonfly) - * [x] [IKV - Inlined Key Value Store](https://docs.feast.dev/reference/online-stores/ikv) + * [x] [Remote](https://docs.feast.dev/reference/online-stores/remote) + * [x] [Postgres](https://docs.feast.dev/reference/online-stores/postgres) + * [x] [HBase](https://docs.feast.dev/reference/online-stores/hbase) + * [x] [Cassandra / AstraDB](https://docs.feast.dev/reference/online-stores/cassandra) + * [x] [ScyllaDB](https://docs.feast.dev/reference/online-stores/scylladb) + * [x] [MySQL](https://docs.feast.dev/reference/online-stores/mysql) + * [x] [Hazelcast](https://docs.feast.dev/reference/online-stores/hazelcast) + * [x] [Elasticsearch](https://docs.feast.dev/reference/online-stores/elasticsearch) + * [x] [SingleStore](https://docs.feast.dev/reference/online-stores/singlestore) + * [x] [Couchbase](https://docs.feast.dev/reference/online-stores/couchbase) + * [x] [MongoDB](https://docs.feast.dev/reference/online-stores/mongodb) + * [x] [Qdrant (vector store)](https://docs.feast.dev/reference/online-stores/qdrant) + * [x] [Milvus (vector store)](https://docs.feast.dev/reference/online-stores/milvus) + * [x] [Faiss (vector store)](https://docs.feast.dev/reference/online-stores/faiss) + * [x] [Hybrid](https://docs.feast.dev/reference/online-stores/hybrid) * [x] [Azure Cache for Redis (community plugin)](https://github.com/Azure/feast-azure) - * [x] [Postgres (contrib plugin)](https://docs.feast.dev/reference/online-stores/postgres) - * [x] [Cassandra / AstraDB (contrib plugin)](https://docs.feast.dev/reference/online-stores/cassandra) - * [x] [ScyllaDB (contrib plugin)](https://docs.feast.dev/reference/online-stores/scylladb) - * [x] [Couchbase (contrib plugin)](https://docs.feast.dev/reference/online-stores/couchbase) * [x] [Custom online store support](https://docs.feast.dev/how-to-guides/customizing-feast/adding-support-for-a-new-online-store) * **Feature Engineering** * [x] On-demand Transformations (On Read) (Beta release. See [RFC](https://docs.google.com/document/d/1lgfIw0Drc65LpaxbUu49RCeJgMew547meSJttnUqz7c/edit#)) diff --git a/docs/specs/offline_store_format.md b/docs/specs/offline_store_format.md index ac829dd52f1..1b440d34c27 100644 --- a/docs/specs/offline_store_format.md +++ b/docs/specs/offline_store_format.md @@ -49,6 +49,12 @@ Here's how Feast types map to Pandas types for Feast APIs that take in or return | DOUBLE\_LIST | `list[float]`| | FLOAT\_LIST | `list[float]`| | BOOL\_LIST | `list[bool]`| +| MAP | `dict` (`Dict[str, Any]`)| +| MAP\_LIST | `list[dict]` (`List[Dict[str, Any]]`)| +| JSON | `object` (parsed Python dict/list/str)| +| JSON\_LIST | `list[object]`| +| STRUCT | `dict` (`Dict[str, Any]`)| +| STRUCT\_LIST | `list[dict]` (`List[Dict[str, Any]]`)| Note that this mapping is non-injective, that is more than one Pandas type may corresponds to one Feast type (but not vice versa). In these cases, when converting Feast values to Pandas, the **first** Pandas type in the table above is used. @@ -78,6 +84,12 @@ Here's how Feast types map to BigQuery types when using BigQuery for offline sto | DOUBLE\_LIST | `ARRAY`| | FLOAT\_LIST | `ARRAY`| | BOOL\_LIST | `ARRAY`| +| MAP | `JSON` / `STRUCT` | +| MAP\_LIST | `ARRAY` / `ARRAY` | +| JSON | `JSON` | +| JSON\_LIST | `ARRAY` | +| STRUCT | `STRUCT` / `RECORD` | +| STRUCT\_LIST | `ARRAY` | Values that are not specified by the table above will cause an error on conversion. @@ -94,3 +106,23 @@ https://docs.snowflake.com/en/user-guide/python-connector-pandas.html#snowflake- | INT32 | `INT8 / UINT8 / INT16 / UINT16 / INT32 / UINT32` | | INT64 | `INT64 / UINT64` | | DOUBLE | `FLOAT64` | +| MAP | `VARIANT` / `OBJECT` | +| JSON | `JSON` / `VARIANT` | + +#### Redshift Types +Here's how Feast types map to Redshift types when using Redshift for offline storage: + +| Feast Type | Redshift Type | +|-------------|--| +| Event Timestamp | `TIMESTAMP` / `TIMESTAMPTZ` | +| BYTES | `VARBYTE` | +| STRING | `VARCHAR` | +| INT32 | `INT4` / `SMALLINT` | +| INT64 | `INT8` / `BIGINT` | +| DOUBLE | `FLOAT8` / `DOUBLE PRECISION` | +| FLOAT | `FLOAT4` / `REAL` | +| BOOL | `BOOL` | +| MAP | `SUPER` | +| JSON | `json` / `SUPER` | + +Note: Redshift's `SUPER` type stores semi-structured JSON data. During materialization, Feast automatically handles `SUPER` columns that are exported as JSON strings by parsing them back into Python dictionaries before converting to `MAP` proto values. diff --git a/docs/tutorials/azure/data/data_generator.py b/docs/tutorials/azure/data/data_generator.py index 77fec082963..20af682c9a3 100644 --- a/docs/tutorials/azure/data/data_generator.py +++ b/docs/tutorials/azure/data/data_generator.py @@ -7,8 +7,7 @@ from pytz import FixedOffset, timezone, utc from random import randint from enum import Enum -from sqlalchemy import create_engine, DateTime -from datetime import datetime +from sqlalchemy import DateTime DEFAULT_ENTITY_DF_EVENT_TIMESTAMP_COL = "event_timestamp" @@ -65,7 +64,8 @@ def create_orders_df( ) ] df.sort_values( - by=["e_ts", "order_id", "driver_id", "customer_id"], inplace=True, + by=["e_ts", "order_id", "driver_id", "customer_id"], + inplace=True, ) else: df[DEFAULT_ENTITY_DF_EVENT_TIMESTAMP_COL] = [ @@ -208,9 +208,7 @@ def create_customer_daily_profile_df(customers, start_date, end_date) -> pd.Data def generate_entities(date, n_customers, n_drivers, order_count): end_date = date - before_start_date = end_date - timedelta(days=365) start_date = end_date - timedelta(days=7) - after_end_date = end_date + timedelta(days=365) customer_entities = [20000 + c_id for c_id in range(n_customers)] driver_entities = [50000 + d_id for d_id in range(n_drivers)] orders_df = create_orders_df( @@ -225,7 +223,7 @@ def generate_entities(date, n_customers, n_drivers, order_count): def save_df_to_csv(df, table_name, dtype): - df.to_csv(table_name+".csv", index=False) + df.to_csv(table_name + ".csv", index=False) if __name__ == "__main__": @@ -247,7 +245,6 @@ def save_df_to_csv(df, table_name, dtype): print(drivers_df.head()) - orders_table = "orders" driver_hourly_table = "driver_hourly" customer_profile_table = "customer_profile" @@ -257,4 +254,4 @@ def save_df_to_csv(df, table_name, dtype): print("uploading drivers") save_df_to_csv(drivers_df, driver_hourly_table, dtype={"datetime": DateTime()}) print("uploading customers") - save_df_to_csv(customer_df, customer_profile_table, dtype={"datetime": DateTime()}) \ No newline at end of file + save_df_to_csv(customer_df, customer_profile_table, dtype={"datetime": DateTime()}) diff --git a/docs/tutorials/azure/notebooks/src/score.py b/docs/tutorials/azure/notebooks/src/score.py index 7def7d2d2ad..f6281c47157 100644 --- a/docs/tutorials/azure/notebooks/src/score.py +++ b/docs/tutorials/azure/notebooks/src/score.py @@ -11,7 +11,7 @@ from feast.infra.offline_stores.contrib.mssql_offline_store.mssql import ( MsSqlServerOfflineStoreConfig, ) -from feast.infra.online_stores.redis import RedisOnlineStoreConfig, RedisOnlineStore +from feast.infra.online_stores.redis import RedisOnlineStoreConfig def init(): diff --git a/examples/java-demo/feature_repo/driver_repo.py b/examples/java-demo/feature_repo/driver_repo.py index f7dd05afff7..edb3e1e9d89 100644 --- a/examples/java-demo/feature_repo/driver_repo.py +++ b/examples/java-demo/feature_repo/driver_repo.py @@ -14,7 +14,10 @@ timestamp_field="event_timestamp", created_timestamp_column="created", ) -driver = Entity(name="driver_id", description="driver id",) +driver = Entity( + name="driver_id", + description="driver id", +) driver_hourly_stats_view = FeatureView( name="driver_hourly_stats", entities=[driver], @@ -58,4 +61,3 @@ def transformed_conv_rate(inputs: pd.DataFrame) -> pd.DataFrame: df["conv_rate_plus_val1"] = inputs["conv_rate"] + inputs["val_to_add"] df["conv_rate_plus_val2"] = inputs["conv_rate"] + inputs["val_to_add_2"] return df - diff --git a/examples/java-demo/feature_repo/test.py b/examples/java-demo/feature_repo/test.py index f73883019d6..9dd0c34a1f6 100644 --- a/examples/java-demo/feature_repo/test.py +++ b/examples/java-demo/feature_repo/test.py @@ -20,9 +20,13 @@ def fetch_java(): print( stub.GetOnlineFeatures( - GetOnlineFeaturesRequest(features=feature_refs, entities=entity_rows,) + GetOnlineFeaturesRequest( + features=feature_refs, + entities=entity_rows, + ) ) ) + if __name__ == "__main__": fetch_java() diff --git a/examples/java-demo/feature_repo/test_python_fetch.py b/examples/java-demo/feature_repo/test_python_fetch.py index 5e2781e1508..0edc05c6603 100644 --- a/examples/java-demo/feature_repo/test_python_fetch.py +++ b/examples/java-demo/feature_repo/test_python_fetch.py @@ -15,7 +15,7 @@ def run_demo(): }, { "driver_id": 1002, - } + }, ], ).to_dict() for key, value in sorted(features.items()): diff --git a/examples/kind-quickstart/src/utils.py b/examples/kind-quickstart/src/utils.py index ea549d7ed8c..34d674a088a 100644 --- a/examples/kind-quickstart/src/utils.py +++ b/examples/kind-quickstart/src/utils.py @@ -1,12 +1,18 @@ import subprocess -def port_forward(service, external_port, local_port=80) : - """ - Run a background process to forward port 80 of the given `service` service to the given `external_port` port. - Returns: the process instance - """ - command = ["kubectl", "port-forward", f"service/{service}", f"{external_port}:{local_port}"] - process = subprocess.Popen(command) - print(f"Port-forwarding {service} with process ID: {process.pid}") - return process +def port_forward(service, external_port, local_port=80): + """ + Run a background process to forward port 80 of the given `service` service to the given `external_port` port. + + Returns: the process instance + """ + command = [ + "kubectl", + "port-forward", + f"service/{service}", + f"{external_port}:{local_port}", + ] + process = subprocess.Popen(command) + print(f"Port-forwarding {service} with process ID: {process.pid}") + return process diff --git a/examples/mcp_feature_store/feature_store.yaml b/examples/mcp_feature_store/feature_store.yaml index 305be159956..82029eb111f 100644 --- a/examples/mcp_feature_store/feature_store.yaml +++ b/examples/mcp_feature_store/feature_store.yaml @@ -14,9 +14,10 @@ feature_server: type: mcp enabled: true mcp_enabled: true # Enable MCP support - defaults to false + mcp_transport: http mcp_server_name: "feast-feature-store" mcp_server_version: "1.0.0" feature_logging: enabled: false -entity_key_serialization_version: 3 \ No newline at end of file +entity_key_serialization_version: 3 diff --git a/examples/online_store/milvus_tutorial/milvus_example.py b/examples/online_store/milvus_tutorial/milvus_example.py index dc5cb646c60..c8889efdf0f 100644 --- a/examples/online_store/milvus_tutorial/milvus_example.py +++ b/examples/online_store/milvus_tutorial/milvus_example.py @@ -32,39 +32,71 @@ def generate_sample_data(): # Sample product data products = [ - {"id": 1, "name": "Smartphone", - "description": "A high-end smartphone with advanced camera features and long battery life."}, - {"id": 2, "name": "Laptop", - "description": "Powerful laptop with fast processor and high-resolution display for professional use."}, - {"id": 3, "name": "Headphones", - "description": "Wireless noise-cancelling headphones with premium sound quality."}, - {"id": 4, "name": "Smartwatch", - "description": "Fitness tracking smartwatch with heart rate monitoring and sleep analysis."}, - {"id": 5, "name": "Tablet", - "description": "Lightweight tablet with vibrant display perfect for reading and browsing."}, - {"id": 6, "name": "Camera", - "description": "Professional digital camera with high-resolution sensor and interchangeable lenses."}, - {"id": 7, "name": "Speaker", - "description": "Bluetooth speaker with rich bass and long battery life for outdoor use."}, - {"id": 8, "name": "Gaming Console", - "description": "Next-generation gaming console with 4K graphics and fast loading times."}, - {"id": 9, "name": "E-reader", - "description": "E-ink display reader with backlight for comfortable reading in any lighting condition."}, - {"id": 10, "name": "Smart TV", - "description": "4K smart television with built-in streaming apps and voice control."} + { + "id": 1, + "name": "Smartphone", + "description": "A high-end smartphone with advanced camera features and long battery life.", + }, + { + "id": 2, + "name": "Laptop", + "description": "Powerful laptop with fast processor and high-resolution display for professional use.", + }, + { + "id": 3, + "name": "Headphones", + "description": "Wireless noise-cancelling headphones with premium sound quality.", + }, + { + "id": 4, + "name": "Smartwatch", + "description": "Fitness tracking smartwatch with heart rate monitoring and sleep analysis.", + }, + { + "id": 5, + "name": "Tablet", + "description": "Lightweight tablet with vibrant display perfect for reading and browsing.", + }, + { + "id": 6, + "name": "Camera", + "description": "Professional digital camera with high-resolution sensor and interchangeable lenses.", + }, + { + "id": 7, + "name": "Speaker", + "description": "Bluetooth speaker with rich bass and long battery life for outdoor use.", + }, + { + "id": 8, + "name": "Gaming Console", + "description": "Next-generation gaming console with 4K graphics and fast loading times.", + }, + { + "id": 9, + "name": "E-reader", + "description": "E-ink display reader with backlight for comfortable reading in any lighting condition.", + }, + { + "id": 10, + "name": "Smart TV", + "description": "4K smart television with built-in streaming apps and voice control.", + }, ] # Create DataFrame df = pd.DataFrame(products) # Generate embeddings using sentence-transformers - model = SentenceTransformer('all-MiniLM-L6-v2') # Small, fast model with 384-dim embeddings - embeddings = model.encode(df['description'].tolist()) + model = SentenceTransformer( + "all-MiniLM-L6-v2" + ) # Small, fast model with 384-dim embeddings + embeddings = model.encode(df["description"].tolist()) # Add embeddings and timestamp to DataFrame - df['embedding'] = embeddings.tolist() - df['event_timestamp'] = datetime.now() - timedelta(days=1) - df['created_timestamp'] = datetime.now() - timedelta(days=1) + df["embedding"] = embeddings.tolist() + df["event_timestamp"] = datetime.now() - timedelta(days=1) + df["created_timestamp"] = datetime.now() - timedelta(days=1) # Save to parquet file parquet_path = "data/sample_data.parquet" @@ -135,16 +167,20 @@ def perform_similarity_search(store, query_text: str, top_k: int = 3): print(f"\nPerforming similarity search for: '{query_text}'") # Generate embedding for query text - model = SentenceTransformer('all-MiniLM-L6-v2') + model = SentenceTransformer("all-MiniLM-L6-v2") query_embedding = model.encode(query_text).tolist() # Perform similarity search using vector embeddings with version 2 API try: results = store.retrieve_online_documents_v2( - features=["product_embeddings:embedding", "product_embeddings:name", "product_embeddings:description"], + features=[ + "product_embeddings:embedding", + "product_embeddings:name", + "product_embeddings:description", + ], query=query_embedding, top_k=top_k, - distance_metric="L2" + distance_metric="L2", ).to_df() # Print results @@ -184,7 +220,9 @@ def main(): perform_similarity_search(store, "portable computing device for work", top_k=3) print("\n=== Tutorial Complete ===") - print("You've successfully set up Milvus with Feast and performed vector similarity searches!") + print( + "You've successfully set up Milvus with Feast and performed vector similarity searches!" + ) if __name__ == "__main__": diff --git a/examples/online_store/pgvector_tutorial/pgvector_example.py b/examples/online_store/pgvector_tutorial/pgvector_example.py index c8236ea4a7b..94c6e079952 100644 --- a/examples/online_store/pgvector_tutorial/pgvector_example.py +++ b/examples/online_store/pgvector_tutorial/pgvector_example.py @@ -4,12 +4,9 @@ # as a vector database backend for Feast. import os -import numpy as np import pandas as pd from datetime import datetime, timedelta -from typing import List, Optional import subprocess -import time # For generating embeddings try: @@ -21,53 +18,97 @@ from feast import FeatureStore, Entity, FeatureView, Field, FileSource from feast.data_format import ParquetFormat -from feast.types import Float32, Array, String, Int64 +from feast.types import Float32, Array, String from feast.value_type import ValueType # Create data directory if it doesn't exist os.makedirs("data", exist_ok=True) + # Step 1: Generate sample data with embeddings def generate_sample_data(): print("Generating sample data with embeddings...") - + # Sample product data products = [ - {"id": 1, "name": "Smartphone", "description": "A high-end smartphone with advanced camera features and long battery life."}, - {"id": 2, "name": "Laptop", "description": "Powerful laptop with fast processor and high-resolution display for professional use."}, - {"id": 3, "name": "Headphones", "description": "Wireless noise-cancelling headphones with premium sound quality."}, - {"id": 4, "name": "Smartwatch", "description": "Fitness tracking smartwatch with heart rate monitoring and sleep analysis."}, - {"id": 5, "name": "Tablet", "description": "Lightweight tablet with vibrant display perfect for reading and browsing."}, - {"id": 6, "name": "Camera", "description": "Professional digital camera with high-resolution sensor and interchangeable lenses."}, - {"id": 7, "name": "Speaker", "description": "Bluetooth speaker with rich bass and long battery life for outdoor use."}, - {"id": 8, "name": "Gaming Console", "description": "Next-generation gaming console with 4K graphics and fast loading times."}, - {"id": 9, "name": "E-reader", "description": "E-ink display reader with backlight for comfortable reading in any lighting condition."}, - {"id": 10, "name": "Smart TV", "description": "4K smart television with built-in streaming apps and voice control."} + { + "id": 1, + "name": "Smartphone", + "description": "A high-end smartphone with advanced camera features and long battery life.", + }, + { + "id": 2, + "name": "Laptop", + "description": "Powerful laptop with fast processor and high-resolution display for professional use.", + }, + { + "id": 3, + "name": "Headphones", + "description": "Wireless noise-cancelling headphones with premium sound quality.", + }, + { + "id": 4, + "name": "Smartwatch", + "description": "Fitness tracking smartwatch with heart rate monitoring and sleep analysis.", + }, + { + "id": 5, + "name": "Tablet", + "description": "Lightweight tablet with vibrant display perfect for reading and browsing.", + }, + { + "id": 6, + "name": "Camera", + "description": "Professional digital camera with high-resolution sensor and interchangeable lenses.", + }, + { + "id": 7, + "name": "Speaker", + "description": "Bluetooth speaker with rich bass and long battery life for outdoor use.", + }, + { + "id": 8, + "name": "Gaming Console", + "description": "Next-generation gaming console with 4K graphics and fast loading times.", + }, + { + "id": 9, + "name": "E-reader", + "description": "E-ink display reader with backlight for comfortable reading in any lighting condition.", + }, + { + "id": 10, + "name": "Smart TV", + "description": "4K smart television with built-in streaming apps and voice control.", + }, ] - + # Create DataFrame df = pd.DataFrame(products) - + # Generate embeddings using sentence-transformers - model = SentenceTransformer('all-MiniLM-L6-v2') # Small, fast model with 384-dim embeddings - embeddings = model.encode(df['description'].tolist()) - + model = SentenceTransformer( + "all-MiniLM-L6-v2" + ) # Small, fast model with 384-dim embeddings + embeddings = model.encode(df["description"].tolist()) + # Add embeddings and timestamp to DataFrame - df['embedding'] = embeddings.tolist() - df['event_timestamp'] = datetime.now() - timedelta(days=1) - df['created_timestamp'] = datetime.now() - timedelta(days=1) - + df["embedding"] = embeddings.tolist() + df["event_timestamp"] = datetime.now() - timedelta(days=1) + df["created_timestamp"] = datetime.now() - timedelta(days=1) + # Save to parquet file parquet_path = "data/sample_data.parquet" df.to_parquet(parquet_path, index=False) - + print(f"Sample data saved to {parquet_path}") return parquet_path + # Step 2: Define feature repository def create_feature_definitions(data_path): print("Creating feature definitions...") - + # Define entity product = Entity( name="product_id", @@ -75,7 +116,7 @@ def create_feature_definitions(data_path): join_keys=["id"], value_type=ValueType.INT64, ) - + # Define data source source = FileSource( file_format=ParquetFormat(), @@ -83,7 +124,7 @@ def create_feature_definitions(data_path): timestamp_field="event_timestamp", created_timestamp_column="created_timestamp", ) - + # Define feature view with vector embeddings product_embeddings = FeatureView( name="product_embeddings", @@ -91,10 +132,10 @@ def create_feature_definitions(data_path): ttl=timedelta(days=30), schema=[ Field( - name="embedding", - dtype=Array(Float32), + name="embedding", + dtype=Array(Float32), vector_index=True, # Mark as vector field - vector_search_metric="L2" # Use L2 distance for similarity + vector_search_metric="L2", # Use L2 distance for similarity ), Field(name="name", dtype=String), Field(name="description", dtype=String), @@ -102,106 +143,152 @@ def create_feature_definitions(data_path): source=source, online=True, ) - + return product, product_embeddings + # Step 3: Initialize and apply feature store def setup_feature_store(product, product_embeddings): print("Setting up feature store...") - + # Initialize feature store store = FeatureStore(repo_path=".") - + # Apply feature definitions store.apply([product, product_embeddings]) - + # Materialize features to online store store.materialize( start_date=datetime.now() - timedelta(days=2), end_date=datetime.now(), ) - + print("Feature store setup complete") return store + # Step 4: Perform vector similarity search def perform_similarity_search(store, query_text: str, top_k: int = 3): print(f"\nPerforming similarity search for: '{query_text}'") - + # Generate embedding for query text - model = SentenceTransformer('all-MiniLM-L6-v2') + model = SentenceTransformer("all-MiniLM-L6-v2") query_embedding = model.encode(query_text).tolist() - + # Perform similarity search using vector embeddings results = store.retrieve_online_documents( query=query_embedding, features=["product_embeddings:embedding"], top_k=top_k, - distance_metric="L2" + distance_metric="L2", ) - + # Extract product IDs from the results by parsing entity keys # (The entities are encoded in a way that's not directly accessible) - + print(f"\nTop {top_k} similar products:") print("Available fields:", list(results.to_dict().keys())) - + # Since we can't access the entity keys directly, let's do a manual search # to show the top similar products based on our search query - + # Get top 5 products sorted by relevance to our query (manual approach) products = [ - {"id": 3, "name": "Headphones", "description": "Wireless noise-cancelling headphones with premium sound quality."}, - {"id": 7, "name": "Speaker", "description": "Bluetooth speaker with rich bass and long battery life for outdoor use."}, - {"id": 2, "name": "Laptop", "description": "Powerful laptop with fast processor and high-resolution display for professional use."}, - {"id": 5, "name": "Tablet", "description": "Lightweight tablet with vibrant display perfect for reading and browsing."}, - {"id": 1, "name": "Smartphone", "description": "A high-end smartphone with advanced camera features and long battery life."}, + { + "id": 3, + "name": "Headphones", + "description": "Wireless noise-cancelling headphones with premium sound quality.", + }, + { + "id": 7, + "name": "Speaker", + "description": "Bluetooth speaker with rich bass and long battery life for outdoor use.", + }, + { + "id": 2, + "name": "Laptop", + "description": "Powerful laptop with fast processor and high-resolution display for professional use.", + }, + { + "id": 5, + "name": "Tablet", + "description": "Lightweight tablet with vibrant display perfect for reading and browsing.", + }, + { + "id": 1, + "name": "Smartphone", + "description": "A high-end smartphone with advanced camera features and long battery life.", + }, ] - + # Filter based on the search query - if "wireless" in query_text.lower() or "audio" in query_text.lower() or "sound" in query_text.lower(): - relevant = [products[0], products[1], products[4]] # Headphones, Speaker, Smartphone - elif "portable" in query_text.lower() or "computing" in query_text.lower() or "work" in query_text.lower(): + if ( + "wireless" in query_text.lower() + or "audio" in query_text.lower() + or "sound" in query_text.lower() + ): + relevant = [ + products[0], + products[1], + products[4], + ] # Headphones, Speaker, Smartphone + elif ( + "portable" in query_text.lower() + or "computing" in query_text.lower() + or "work" in query_text.lower() + ): relevant = [products[2], products[4], products[3]] # Laptop, Smartphone, Tablet else: relevant = products[:3] # Just show first 3 - + # Display results for i, product in enumerate(relevant[:top_k], 1): print(f"\n{i}. Name: {product['name']}") print(f" Description: {product['description']}") - + print("\nNote: Using simulated results for display purposes.") - print("The vector search is working, but the result structure in this Feast version") - print("doesn't allow easy access to the entity keys to retrieve the product details.") + print( + "The vector search is working, but the result structure in this Feast version" + ) + print( + "doesn't allow easy access to the entity keys to retrieve the product details." + ) + # Main function to run the example def main(): print("=== PGVector Tutorial with Feast ===") - + # Check if PostgreSQL with pgvector is running print("\nEnsure PostgreSQL with pgvector is running:") - print("docker run -d \\\n --name postgres-pgvector \\\n -e POSTGRES_USER=feast \\\n -e POSTGRES_PASSWORD=feast \\\n -e POSTGRES_DB=feast \\\n -p 5432:5432 \\\n pgvector/pgvector:pg16") + print( + "docker run -d \\\n --name postgres-pgvector \\\n -e POSTGRES_USER=feast \\\n -e POSTGRES_PASSWORD=feast \\\n -e POSTGRES_DB=feast \\\n -p 5432:5432 \\\n pgvector/pgvector:pg16" + ) print("\nEnsure pgvector extension is created:") - print("docker exec -it postgres-pgvector psql -U feast -c \"CREATE EXTENSION IF NOT EXISTS vector;\"") - + print( + 'docker exec -it postgres-pgvector psql -U feast -c "CREATE EXTENSION IF NOT EXISTS vector;"' + ) + input("\nPress Enter to continue once PostgreSQL with pgvector is ready...") - + # Generate sample data data_path = generate_sample_data() - + # Create feature definitions product, product_embeddings = create_feature_definitions(data_path) - + # Setup feature store store = setup_feature_store(product, product_embeddings) - + # Perform similarity searches perform_similarity_search(store, "wireless audio device with good sound", top_k=3) perform_similarity_search(store, "portable computing device for work", top_k=3) - + print("\n=== Tutorial Complete ===") - print("You've successfully set up pgvector with Feast and performed vector similarity searches!") + print( + "You've successfully set up pgvector with Feast and performed vector similarity searches!" + ) + if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/examples/openlineage-integration/openlineage_demo.py b/examples/openlineage-integration/openlineage_demo.py index 5bcb40fb902..fb02136eeb1 100644 --- a/examples/openlineage-integration/openlineage_demo.py +++ b/examples/openlineage-integration/openlineage_demo.py @@ -33,6 +33,7 @@ from feast import Entity, FeatureService, FeatureView, FileSource, Field from feast.types import Float32, Int64 + def create_feature_store_yaml(url: str) -> str: """Create a feature_store.yaml with OpenLineage configuration.""" return f"""project: openlineage_demo @@ -68,13 +69,13 @@ def run_demo(url: str): (repo_path / "feature_store.yaml").write_text(feature_store_yaml) print(f"Created demo repository at: {repo_path}") - print(f"feature_store.yaml:") + print("feature_store.yaml:") print("-" * 50) print(feature_store_yaml) print("-" * 50) try: - import openlineage.client + import openlineage.client # noqa: F401 except ImportError: print("OpenLineage client not installed.") print("Install with: pip install openlineage-python") @@ -123,7 +124,9 @@ def run_demo(url: str): Field(name="conv_rate", dtype=Float32, description="Conversion rate"), Field(name="acc_rate", dtype=Float32, description="Acceptance rate"), Field( - name="avg_daily_trips", dtype=Int64, description="Average daily trips" + name="avg_daily_trips", + dtype=Int64, + description="Average daily trips", ), ], source=driver_stats_source, @@ -140,12 +143,21 @@ def run_demo(url: str): try: fs.apply( - [driver, driver_stats_source, driver_hourly_stats_view, driver_stats_service] + [ + driver, + driver_stats_source, + driver_hourly_stats_view, + driver_stats_service, + ] ) print("Applied entities, feature views, and feature services") print("OpenLineage events emitted automatically:") - print(" - feast_feature_views_openlineage_demo (DataSources → FeatureViews)") - print(" - feature_service_driver_stats_service (FeatureViews → FeatureService)") + print( + " - feast_feature_views_openlineage_demo (DataSources → FeatureViews)" + ) + print( + " - feature_service_driver_stats_service (FeatureViews → FeatureService)" + ) except Exception as e: print(f"Apply failed: {e}") diff --git a/examples/operator-rbac-openshift-tls/client/feature_repo/test.py b/examples/operator-rbac-openshift-tls/client/feature_repo/test.py index 78732327a62..88f7a0e6484 100644 --- a/examples/operator-rbac-openshift-tls/client/feature_repo/test.py +++ b/examples/operator-rbac-openshift-tls/client/feature_repo/test.py @@ -9,6 +9,7 @@ repo_path = os.getenv("FEAST_REPO_PATH", ".") store = FeatureStore(repo_path=repo_path) + def fetch_historical_features_entity_df(store: FeatureStore, for_batch_scoring: bool): """Fetch historical features for training or batch scoring.""" try: @@ -38,13 +39,17 @@ def fetch_historical_features_entity_df(store: FeatureStore, for_batch_scoring: "transformed_conv_rate:conv_rate_plus_val2", ], ).to_df() - print(f"Successfully fetched {'batch scoring' if for_batch_scoring else 'training'} historical features:\n", training_df.head()) + print( + f"Successfully fetched {'batch scoring' if for_batch_scoring else 'training'} historical features:\n", + training_df.head(), + ) except PermissionError: print("\n*** PERMISSION DENIED *** Cannot fetch historical features.") except Exception as e: print(f"Unexpected error while fetching historical features: {e}") + def fetch_online_features(store: FeatureStore, source: str = ""): """Fetch online features from the feature store.""" try: @@ -76,7 +81,9 @@ def fetch_online_features(store: FeatureStore, source: str = ""): entity_rows=entity_rows, ).to_dict() - print(f"Successfully fetched online features {'via feature service' if source else 'directly'}:\n") + print( + f"Successfully fetched online features {'via feature service' if source else 'directly'}:\n" + ) for key, value in sorted(returned_features.items()): print(f"{key} : {value}") @@ -85,6 +92,7 @@ def fetch_online_features(store: FeatureStore, source: str = ""): except Exception as e: print(f"Unexpected error while fetching online features: {e}") + def check_permissions(): """Check user role, test various Feast operations.""" feature_views = [] @@ -94,7 +102,9 @@ def check_permissions(): try: feature_views = store.list_feature_views() if not feature_views: - print("No feature views found. You might not have access or they haven't been created.") + print( + "No feature views found. You might not have access or they haven't been created." + ) else: print(f"Successfully listed {len(feature_views)} feature views:") for fv in feature_views: @@ -117,7 +127,9 @@ def check_permissions(): store.apply(feature_views) print("User has write access to the feature store.") except PermissionError: - print("\n*** PERMISSION DENIED *** User lacks permission to modify the feature store.") + print( + "\n*** PERMISSION DENIED *** User lacks permission to modify the feature store." + ) except Exception as e: print(f"Unexpected error testing write access: {e}") @@ -151,5 +163,6 @@ def check_permissions(): except Exception as e: print(f"Unexpected error while pushing event: {e}") + if __name__ == "__main__": check_permissions() diff --git a/examples/operator-rbac-openshift-tls/permissions_apply.py b/examples/operator-rbac-openshift-tls/permissions_apply.py index 0d46ad5260a..d628fa88eb8 100644 --- a/examples/operator-rbac-openshift-tls/permissions_apply.py +++ b/examples/operator-rbac-openshift-tls/permissions_apply.py @@ -5,8 +5,10 @@ from feast.permissions.policy import RoleBasedPolicy # Define K8s roles same as created with FeatureStore CR -admin_roles = ["feast-writer"] # Full access (can create, update, delete ) Feast Resources -user_roles = ["feast-reader"] # Read-only access on Feast Resources +admin_roles = [ + "feast-writer" +] # Full access (can create, update, delete ) Feast Resources +user_roles = ["feast-reader"] # Read-only access on Feast Resources # User permissions (feast_user_permission) # - Grants read and describing Feast objects access @@ -14,7 +16,8 @@ name="feast_user_permission", types=ALL_RESOURCE_TYPES, policy=RoleBasedPolicy(roles=user_roles), - actions=[AuthzedAction.DESCRIBE] + READ # Read access (READ_ONLINE, READ_OFFLINE) + describe other Feast Resources. + actions=[AuthzedAction.DESCRIBE] + + READ, # Read access (READ_ONLINE, READ_OFFLINE) + describe other Feast Resources. ) # Admin permissions (feast_admin_permission) @@ -23,5 +26,5 @@ name="feast_admin_permission", types=ALL_RESOURCE_TYPES, policy=RoleBasedPolicy(roles=admin_roles), - actions=ALL_ACTIONS # Full permissions: CREATE, UPDATE, DELETE, READ, WRITE + actions=ALL_ACTIONS, # Full permissions: CREATE, UPDATE, DELETE, READ, WRITE ) diff --git a/examples/operator-rbac-openshift-tls/permissions_with_groups_namespaces.py b/examples/operator-rbac-openshift-tls/permissions_with_groups_namespaces.py index 5565c612902..d5c17fe1c2b 100644 --- a/examples/operator-rbac-openshift-tls/permissions_with_groups_namespaces.py +++ b/examples/operator-rbac-openshift-tls/permissions_with_groups_namespaces.py @@ -5,28 +5,36 @@ from feast.feast_object import ALL_FEATURE_VIEW_TYPES, ALL_RESOURCE_TYPES from feast.project import Project from feast.entity import Entity -from feast.feature_view import FeatureView -from feast.on_demand_feature_view import OnDemandFeatureView -from feast.batch_feature_view import BatchFeatureView -from feast.stream_feature_view import StreamFeatureView from feast.feature_service import FeatureService from feast.data_source import DataSource from feast.saved_dataset import SavedDataset from feast.permissions.permission import Permission from feast.permissions.action import READ, AuthzedAction, ALL_ACTIONS -from feast.permissions.policy import RoleBasedPolicy, GroupBasedPolicy, NamespaceBasedPolicy, CombinedGroupNamespacePolicy +from feast.permissions.policy import ( + RoleBasedPolicy, + GroupBasedPolicy, + NamespaceBasedPolicy, + CombinedGroupNamespacePolicy, +) -# New Testing +# New Testing -WITHOUT_DATA_SOURCE = [Project, Entity, FeatureService, SavedDataset] + ALL_FEATURE_VIEW_TYPES +WITHOUT_DATA_SOURCE = [ + Project, + Entity, + FeatureService, + SavedDataset, +] + ALL_FEATURE_VIEW_TYPES ONLY_ENTITIES = [Entity] ONLY_DS = [DataSource] # Define K8s roles (existing functionality) -admin_roles = ["feast-writer"] # Full access (can create, update, delete) Feast Resources -user_roles = ["feast-reader"] # Read-only access on Feast Resources +admin_roles = [ + "feast-writer" +] # Full access (can create, update, delete) Feast Resources +user_roles = ["feast-reader"] # Read-only access on Feast Resources # Define groups for different teams data_team_groups = ["data-team", "ml-engineers"] @@ -41,9 +49,14 @@ name="pre_Changed", types=ONLY_ENTITIES, policy=NamespaceBasedPolicy(namespaces=prod_namespaces), - actions=[AuthzedAction.DESCRIBE] + READ + actions=[AuthzedAction.DESCRIBE] + READ, +) +only_ds = Permission( + name="entity_reader", + types=ONLY_DS, + policy=NamespaceBasedPolicy(namespaces=prod_namespaces), + actions=[AuthzedAction.DESCRIBE] + READ, ) -only_ds = Permission(name="entity_reader", types=ONLY_DS, policy=NamespaceBasedPolicy(namespaces=[prod_namespaces]), actions=[AuthzedAction.DESCRIBE] + READ) staging_namespaces = ["staging", "dev"] test_namespaces = ["test", "testing"] @@ -53,7 +66,8 @@ name="feast_user_permission", types=ALL_RESOURCE_TYPES, policy=RoleBasedPolicy(roles=user_roles), - actions=[AuthzedAction.DESCRIBE] + READ # Read access (READ_ONLINE, READ_OFFLINE) + describe other Feast Resources. + actions=[AuthzedAction.DESCRIBE] + + READ, # Read access (READ_ONLINE, READ_OFFLINE) + describe other Feast Resources. ) # Admin permissions (existing functionality) @@ -62,7 +76,7 @@ name="feast_admin_permission", types=ALL_RESOURCE_TYPES, policy=RoleBasedPolicy(roles=admin_roles), - actions=ALL_ACTIONS # Full permissions: CREATE, UPDATE, DELETE, READ, WRITE + actions=ALL_ACTIONS, # Full permissions: CREATE, UPDATE, DELETE, READ, WRITE ) # Group-based permissions (new functionality) @@ -71,7 +85,7 @@ name="data_team_read_permission", types=ALL_RESOURCE_TYPES, policy=GroupBasedPolicy(groups=data_team_groups), - actions=[AuthzedAction.DESCRIBE] + READ + actions=[AuthzedAction.DESCRIBE] + READ, ) # - Grants full access to admin groups @@ -79,7 +93,7 @@ name="admin_group_permission", types=ALL_RESOURCE_TYPES, policy=GroupBasedPolicy(groups=admin_groups), - actions=ALL_ACTIONS + actions=ALL_ACTIONS, ) # Namespace-based permissions (new functionality) @@ -88,7 +102,7 @@ name="production_read_permission", types=ALL_RESOURCE_TYPES, policy=NamespaceBasedPolicy(namespaces=prod_namespaces), - actions=[AuthzedAction.DESCRIBE] + READ + actions=[AuthzedAction.DESCRIBE] + READ, ) # # - Grants full access to staging namespace users @@ -96,7 +110,7 @@ name="staging_full_permission", types=ALL_RESOURCE_TYPES, policy=NamespaceBasedPolicy(namespaces=staging_namespaces), - actions=ALL_ACTIONS + actions=ALL_ACTIONS, ) # # Combined permissions (using combined policy type) @@ -104,14 +118,18 @@ dev_test_perm = Permission( name="dev_test_permission", types=ALL_RESOURCE_TYPES, - policy=CombinedGroupNamespacePolicy(groups=dev_team_groups, namespaces=test_namespaces), - actions=[AuthzedAction.DESCRIBE] + READ + policy=CombinedGroupNamespacePolicy( + groups=dev_team_groups, namespaces=test_namespaces + ), + actions=[AuthzedAction.DESCRIBE] + READ, ) # # - Grants full access to data team members in staging namespaces data_staging_perm = Permission( name="data_staging_permission", types=ALL_RESOURCE_TYPES, - policy=CombinedGroupNamespacePolicy(groups=data_team_groups, namespaces=staging_namespaces), - actions=ALL_ACTIONS + policy=CombinedGroupNamespacePolicy( + groups=data_team_groups, namespaces=staging_namespaces + ), + actions=ALL_ACTIONS, ) diff --git a/examples/operator-rbac/client/feature_repo/test.py b/examples/operator-rbac/client/feature_repo/test.py index 78732327a62..88f7a0e6484 100644 --- a/examples/operator-rbac/client/feature_repo/test.py +++ b/examples/operator-rbac/client/feature_repo/test.py @@ -9,6 +9,7 @@ repo_path = os.getenv("FEAST_REPO_PATH", ".") store = FeatureStore(repo_path=repo_path) + def fetch_historical_features_entity_df(store: FeatureStore, for_batch_scoring: bool): """Fetch historical features for training or batch scoring.""" try: @@ -38,13 +39,17 @@ def fetch_historical_features_entity_df(store: FeatureStore, for_batch_scoring: "transformed_conv_rate:conv_rate_plus_val2", ], ).to_df() - print(f"Successfully fetched {'batch scoring' if for_batch_scoring else 'training'} historical features:\n", training_df.head()) + print( + f"Successfully fetched {'batch scoring' if for_batch_scoring else 'training'} historical features:\n", + training_df.head(), + ) except PermissionError: print("\n*** PERMISSION DENIED *** Cannot fetch historical features.") except Exception as e: print(f"Unexpected error while fetching historical features: {e}") + def fetch_online_features(store: FeatureStore, source: str = ""): """Fetch online features from the feature store.""" try: @@ -76,7 +81,9 @@ def fetch_online_features(store: FeatureStore, source: str = ""): entity_rows=entity_rows, ).to_dict() - print(f"Successfully fetched online features {'via feature service' if source else 'directly'}:\n") + print( + f"Successfully fetched online features {'via feature service' if source else 'directly'}:\n" + ) for key, value in sorted(returned_features.items()): print(f"{key} : {value}") @@ -85,6 +92,7 @@ def fetch_online_features(store: FeatureStore, source: str = ""): except Exception as e: print(f"Unexpected error while fetching online features: {e}") + def check_permissions(): """Check user role, test various Feast operations.""" feature_views = [] @@ -94,7 +102,9 @@ def check_permissions(): try: feature_views = store.list_feature_views() if not feature_views: - print("No feature views found. You might not have access or they haven't been created.") + print( + "No feature views found. You might not have access or they haven't been created." + ) else: print(f"Successfully listed {len(feature_views)} feature views:") for fv in feature_views: @@ -117,7 +127,9 @@ def check_permissions(): store.apply(feature_views) print("User has write access to the feature store.") except PermissionError: - print("\n*** PERMISSION DENIED *** User lacks permission to modify the feature store.") + print( + "\n*** PERMISSION DENIED *** User lacks permission to modify the feature store." + ) except Exception as e: print(f"Unexpected error testing write access: {e}") @@ -151,5 +163,6 @@ def check_permissions(): except Exception as e: print(f"Unexpected error while pushing event: {e}") + if __name__ == "__main__": check_permissions() diff --git a/examples/operator-rbac/permissions_apply.py b/examples/operator-rbac/permissions_apply.py index 0d46ad5260a..d628fa88eb8 100644 --- a/examples/operator-rbac/permissions_apply.py +++ b/examples/operator-rbac/permissions_apply.py @@ -5,8 +5,10 @@ from feast.permissions.policy import RoleBasedPolicy # Define K8s roles same as created with FeatureStore CR -admin_roles = ["feast-writer"] # Full access (can create, update, delete ) Feast Resources -user_roles = ["feast-reader"] # Read-only access on Feast Resources +admin_roles = [ + "feast-writer" +] # Full access (can create, update, delete ) Feast Resources +user_roles = ["feast-reader"] # Read-only access on Feast Resources # User permissions (feast_user_permission) # - Grants read and describing Feast objects access @@ -14,7 +16,8 @@ name="feast_user_permission", types=ALL_RESOURCE_TYPES, policy=RoleBasedPolicy(roles=user_roles), - actions=[AuthzedAction.DESCRIBE] + READ # Read access (READ_ONLINE, READ_OFFLINE) + describe other Feast Resources. + actions=[AuthzedAction.DESCRIBE] + + READ, # Read access (READ_ONLINE, READ_OFFLINE) + describe other Feast Resources. ) # Admin permissions (feast_admin_permission) @@ -23,5 +26,5 @@ name="feast_admin_permission", types=ALL_RESOURCE_TYPES, policy=RoleBasedPolicy(roles=admin_roles), - actions=ALL_ACTIONS # Full permissions: CREATE, UPDATE, DELETE, READ, WRITE + actions=ALL_ACTIONS, # Full permissions: CREATE, UPDATE, DELETE, READ, WRITE ) diff --git a/examples/podman_local/client/feature_repo/test.py b/examples/podman_local/client/feature_repo/test.py index 13ab2444aab..1e3b741a1b3 100644 --- a/examples/podman_local/client/feature_repo/test.py +++ b/examples/podman_local/client/feature_repo/test.py @@ -1,9 +1,9 @@ -import subprocess from datetime import datetime import pandas as pd from feast import FeatureStore from feast.data_source import PushMode + def run_demo(): try: store = FeatureStore(repo_path=".") @@ -51,6 +51,7 @@ def run_demo(): except Exception as e: print(f"An error occurred in run_demo: {e}") + def fetch_historical_features_entity_df(store: FeatureStore, for_batch_scoring: bool): try: entity_df = pd.DataFrame.from_dict( @@ -83,6 +84,7 @@ def fetch_historical_features_entity_df(store: FeatureStore, for_batch_scoring: except Exception as e: print(f"An error occurred in fetch_historical_features_entity_df: {e}") + def fetch_online_features(store, source: str = ""): try: entity_rows = [ @@ -116,6 +118,7 @@ def fetch_online_features(store, source: str = ""): except Exception as e: print(f"An error occurred in fetch_online_features: {e}") + if __name__ == "__main__": try: run_demo() diff --git a/examples/python-helm-demo/feature_repo/driver_repo.py b/examples/python-helm-demo/feature_repo/driver_repo.py index f7dd05afff7..edb3e1e9d89 100644 --- a/examples/python-helm-demo/feature_repo/driver_repo.py +++ b/examples/python-helm-demo/feature_repo/driver_repo.py @@ -14,7 +14,10 @@ timestamp_field="event_timestamp", created_timestamp_column="created", ) -driver = Entity(name="driver_id", description="driver id",) +driver = Entity( + name="driver_id", + description="driver id", +) driver_hourly_stats_view = FeatureView( name="driver_hourly_stats", entities=[driver], @@ -58,4 +61,3 @@ def transformed_conv_rate(inputs: pd.DataFrame) -> pd.DataFrame: df["conv_rate_plus_val1"] = inputs["conv_rate"] + inputs["val_to_add"] df["conv_rate_plus_val2"] = inputs["conv_rate"] + inputs["val_to_add_2"] return df - diff --git a/examples/python-helm-demo/test/test_python_fetch.py b/examples/python-helm-demo/test/test_python_fetch.py index 715912422f3..3412f7d4de0 100644 --- a/examples/python-helm-demo/test/test_python_fetch.py +++ b/examples/python-helm-demo/test/test_python_fetch.py @@ -18,8 +18,11 @@ def run_demo_http(): resp_data = json.loads(r.text) records = pd.DataFrame.from_records( - columns=resp_data["metadata"]["feature_names"], - data=[[r["values"][i] for r in resp_data["results"]] for i in range(len(resp_data["results"]))] + columns=resp_data["metadata"]["feature_names"], + data=[ + [r["values"][i] for r in resp_data["results"]] + for i in range(len(resp_data["results"])) + ], ) for col in sorted(records.columns): print(col, " : ", records[col].values) diff --git a/examples/rag-docling/feature_repo/example_repo.py b/examples/rag-docling/feature_repo/example_repo.py index 6ce2adab8a5..1169b1c830a 100644 --- a/examples/rag-docling/feature_repo/example_repo.py +++ b/examples/rag-docling/feature_repo/example_repo.py @@ -1,6 +1,5 @@ from datetime import timedelta -import pandas as pd from feast import ( FeatureView, Field, @@ -12,7 +11,7 @@ from feast.types import Float64, Array, String, ValueType, PdfBytes from feast.on_demand_feature_view import on_demand_feature_view from sentence_transformers import SentenceTransformer -from typing import Dict, Any, List +from typing import Any import hashlib from docling.datamodel.base_models import DocumentStream @@ -20,7 +19,6 @@ import io from docling.document_converter import DocumentConverter from transformers import AutoTokenizer -from sentence_transformers import SentenceTransformer from docling.chunking import HybridChunker # Load tokenizer and embedding model @@ -31,13 +29,19 @@ embedding_model = SentenceTransformer(EMBED_MODEL_ID) chunker = HybridChunker(tokenizer=tokenizer, max_tokens=MAX_TOKENS, merge_peers=True) + def embed_text(text: str) -> list[float]: """Generate an embedding for a given text.""" return embedding_model.encode([text], normalize_embeddings=True).tolist()[0] -def generate_chunk_id(file_name: str, raw_chunk_markdown: str="") -> str: + +def generate_chunk_id(file_name: str, raw_chunk_markdown: str = "") -> str: """Generate a unique chunk ID based on file_name and raw_chunk_markdown.""" - unique_string = f"{file_name}-{raw_chunk_markdown}" if raw_chunk_markdown != "" else f"{file_name}" + unique_string = ( + f"{file_name}-{raw_chunk_markdown}" + if raw_chunk_markdown != "" + else f"{file_name}" + ) return hashlib.sha256(unique_string.encode()).hexdigest() @@ -64,7 +68,7 @@ def generate_chunk_id(file_name: str, raw_chunk_markdown: str="") -> str: input_request_pdf = RequestSource( name="pdf_request_source", schema=[ - Field(name="document_id", dtype=String), + Field(name="document_id", dtype=String), Field(name="pdf_bytes", dtype=PdfBytes), Field(name="file_name", dtype=String), ], @@ -88,6 +92,7 @@ def generate_chunk_id(file_name: str, raw_chunk_markdown: str="") -> str: ttl=timedelta(hours=2), ) + @on_demand_feature_view( entities=[chunk, document], sources=[input_request_pdf], diff --git a/examples/rag-retriever/rag_feast_docembedder.ipynb b/examples/rag-retriever/rag_feast_docembedder.ipynb new file mode 100644 index 00000000000..47728fef556 --- /dev/null +++ b/examples/rag-retriever/rag_feast_docembedder.ipynb @@ -0,0 +1,648 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "2855fd1a", + "metadata": {}, + "outputs": [], + "source": [ + "# %pip install --quiet feast[milvus] sentence-transformers datasets\n", + "# %pip install bigtree==0.19.2\n", + "# %pip install marshmallow==3.10.0 " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "3bb14cf1", + "metadata": {}, + "outputs": [], + "source": [ + "from datasets import load_dataset\n", + "# load wikipedia dataset - 1% of the training split\n", + "dataset = load_dataset(\n", + " \"facebook/wiki_dpr\",\n", + " \"psgs_w100.nq.exact\",\n", + " split=\"train[:1%]\",\n", + " with_index=False,\n", + " trust_remote_code=True,\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "92a5e18c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
idtexttitleembeddings
01Aaron Aaron ( or ; \"Ahärôn\") is a prophet, hig...Aaron[0.013342111, 0.58217376, -0.31309745, -0.6991...
12God at Sinai granted Aaron the priesthood for ...Aaron[-0.19236332, 0.539003, -0.5652932, -0.5195250...
23his rod turn into a snake. Then he stretched o...Aaron[-0.23045847, 0.28877887, -0.3449004, -0.14077...
34however, Aaron and Hur remained below to look ...Aaron[0.107315615, 0.5992388, -0.37498242, -0.53419...
45Aaron and his sons to the priesthood, and arra...Aaron[0.32623303, 0.51600194, -0.5568064, -0.494033...
\n", + "
" + ], + "text/plain": [ + " id text title \\\n", + "0 1 Aaron Aaron ( or ; \"Ahärôn\") is a prophet, hig... Aaron \n", + "1 2 God at Sinai granted Aaron the priesthood for ... Aaron \n", + "2 3 his rod turn into a snake. Then he stretched o... Aaron \n", + "3 4 however, Aaron and Hur remained below to look ... Aaron \n", + "4 5 Aaron and his sons to the priesthood, and arra... Aaron \n", + "\n", + " embeddings \n", + "0 [0.013342111, 0.58217376, -0.31309745, -0.6991... \n", + "1 [-0.19236332, 0.539003, -0.5652932, -0.5195250... \n", + "2 [-0.23045847, 0.28877887, -0.3449004, -0.14077... \n", + "3 [0.107315615, 0.5992388, -0.37498242, -0.53419... \n", + "4 [0.32623303, 0.51600194, -0.5568064, -0.494033... " + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dataset.column_names\n", + "df = dataset.select(range(100)).to_pandas()\n", + "df.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "088eaf84", + "metadata": {}, + "outputs": [], + "source": [ + "import yaml\n", + "import os\n", + "\n", + "\n", + "def write_feature_store_yaml(file_path: str, project_name: str) -> str:\n", + " \"\"\"\n", + " Write a feature_store.yaml file to the specified path.\n", + "\n", + " Args:\n", + " file_path: Full path where the YAML file should be written\n", + " (e.g. \"feature_repo/feature_store.yaml\").\n", + " project_name: The project name to use in the YAML.\n", + "\n", + " Returns:\n", + " The absolute path of the written file.\n", + " \"\"\"\n", + " config = {\n", + " \"project\": project_name,\n", + " \"provider\": \"local\",\n", + " \"registry\": \"data/registry.db\",\n", + " \"online_store\": {\n", + " \"type\": \"milvus\",\n", + " \"host\": \"http://localhost\",\n", + " \"port\": 19530,\n", + " \"vector_enabled\": True,\n", + " \"embedding_dim\": 384,\n", + " \"index_type\": \"FLAT\",\n", + " \"metric_type\": \"COSINE\",\n", + " },\n", + " \"offline_store\": {\n", + " \"type\": \"file\",\n", + " },\n", + " \"entity_key_serialization_version\": 3,\n", + " \"auth\": {\n", + " \"type\": \"no_auth\",\n", + " },\n", + " }\n", + "\n", + " os.makedirs(os.path.dirname(os.path.abspath(file_path)), exist_ok=True)\n", + "\n", + " with open(file_path, \"w\") as f:\n", + " yaml.dump(config, f, default_flow_style=False, sort_keys=False)\n", + "\n", + " return os.path.abspath(file_path)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "f951c804", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "mkdir: feature_repo_docebedder: File exists\n", + "/Users/chpatel/projects/feast/examples/rag-retriever\n" + ] + } + ], + "source": [ + "%mkdir feature_repo_docebedder\n", + "!pwd" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "27be0f7e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "YAML written to: /Users/chpatel/projects/feast/examples/rag-retriever/feature_repo_docebedder/feature_store.yaml\n" + ] + } + ], + "source": [ + "path = write_feature_store_yaml(\"feature_repo_docebedder/feature_store.yaml\", \"my_project\")\n", + "print(f\"YAML written to: {path}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "a19428c3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "No project found in the repository. Using project name my_project defined in feature_store.yaml\n", + "Applying changes for project my_project\n", + "Connecting to Milvus remotely at http://localhost:19530\n", + "Deploying infrastructure for \u001b[1m\u001b[32mtext_feature_view\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/chpatel/projects/feast/sdk/python/feast/infra/online_stores/milvus_online_store/milvus.py:86: UserWarning: Field name \"vector_enabled\" in \"MilvusOnlineStoreConfig\" shadows an attribute in parent \"VectorStoreConfig\"\n", + " class MilvusOnlineStoreConfig(FeastConfigBaseModel, VectorStoreConfig):\n" + ] + } + ], + "source": [ + "from feast import DocEmbedder\n", + "\n", + "de = DocEmbedder(repo_path=\"feature_repo_docebedder\", feature_view_name=\"text_feature_view\",yaml_file=\"feature_store.yaml\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "ed217e95", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b19b54476308402eaa251a88fc098300", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Batches: 0%| | 0/4 [00:00\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
passage_idtextembeddingevent_timestampsource_id
01_0Aaron Aaron ( or ; \"Ahärôn\") is a prophet, hig...[0.002557202707976103, 0.12003513425588608, -0...2026-02-11 12:26:29.098091+00:001
11_1Israelites, Aaron served as his brother's spok...[-0.01853535883128643, 0.13290095329284668, -0...2026-02-11 12:26:29.098091+00:001
22_0God at Sinai granted Aaron the priesthood for ...[0.014343681745231152, 0.10290483385324478, -0...2026-02-11 12:26:29.098091+00:002
32_1could not speak well, God appointed Aaron as M...[0.0504433810710907, 0.1175316572189331, -0.00...2026-02-11 12:26:29.098091+00:002
43_0his rod turn into a snake. Then he stretched o...[-0.06228446215391159, 0.10652626305818558, 0....2026-02-11 12:26:29.098091+00:003
..................
19598_1State College before entering Columbia Univers...[0.03597380220890045, 0.04296444356441498, 0.0...2026-02-11 12:26:29.098091+00:0098
19699_0joined the Merchant Marine to earn money to co...[0.05798682942986488, -0.007653537206351757, -...2026-02-11 12:26:29.098091+00:0099
19799_1spent several months in a mental institution a...[0.05905637890100479, 0.030195411294698715, -0...2026-02-11 12:26:29.098091+00:0099
198100_0harboring stolen goods in his dorm room. It wa...[-0.005938616115599871, 0.02653227001428604, -...2026-02-11 12:26:29.098091+00:00100
199100_1Eugene to party meetings. Ginsberg later said ...[0.007752032019197941, 0.06832979619503021, 0....2026-02-11 12:26:29.098091+00:00100
\n", + "

200 rows × 5 columns

\n", + "" + ], + "text/plain": [ + " passage_id text \\\n", + "0 1_0 Aaron Aaron ( or ; \"Ahärôn\") is a prophet, hig... \n", + "1 1_1 Israelites, Aaron served as his brother's spok... \n", + "2 2_0 God at Sinai granted Aaron the priesthood for ... \n", + "3 2_1 could not speak well, God appointed Aaron as M... \n", + "4 3_0 his rod turn into a snake. Then he stretched o... \n", + ".. ... ... \n", + "195 98_1 State College before entering Columbia Univers... \n", + "196 99_0 joined the Merchant Marine to earn money to co... \n", + "197 99_1 spent several months in a mental institution a... \n", + "198 100_0 harboring stolen goods in his dorm room. It wa... \n", + "199 100_1 Eugene to party meetings. Ginsberg later said ... \n", + "\n", + " embedding \\\n", + "0 [0.002557202707976103, 0.12003513425588608, -0... \n", + "1 [-0.01853535883128643, 0.13290095329284668, -0... \n", + "2 [0.014343681745231152, 0.10290483385324478, -0... \n", + "3 [0.0504433810710907, 0.1175316572189331, -0.00... \n", + "4 [-0.06228446215391159, 0.10652626305818558, 0.... \n", + ".. ... \n", + "195 [0.03597380220890045, 0.04296444356441498, 0.0... \n", + "196 [0.05798682942986488, -0.007653537206351757, -... \n", + "197 [0.05905637890100479, 0.030195411294698715, -0... \n", + "198 [-0.005938616115599871, 0.02653227001428604, -... \n", + "199 [0.007752032019197941, 0.06832979619503021, 0.... \n", + "\n", + " event_timestamp source_id \n", + "0 2026-02-11 12:26:29.098091+00:00 1 \n", + "1 2026-02-11 12:26:29.098091+00:00 1 \n", + "2 2026-02-11 12:26:29.098091+00:00 2 \n", + "3 2026-02-11 12:26:29.098091+00:00 2 \n", + "4 2026-02-11 12:26:29.098091+00:00 3 \n", + ".. ... ... \n", + "195 2026-02-11 12:26:29.098091+00:00 98 \n", + "196 2026-02-11 12:26:29.098091+00:00 99 \n", + "197 2026-02-11 12:26:29.098091+00:00 99 \n", + "198 2026-02-11 12:26:29.098091+00:00 100 \n", + "199 2026-02-11 12:26:29.098091+00:00 100 \n", + "\n", + "[200 rows x 5 columns]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "de.embed_documents(documents=df, id_column=\"id\", source_column=\"text\", column_mapping= (\"text\", \"text_embedding\"))" + + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "b25b69df", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/Users/chpatel/projects/feast/examples/rag-retriever/feature_repo_docebedder\n" + ] + } + ], + "source": [ + "%cd feature_repo_docebedder" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "5bf57671", + "metadata": {}, + "outputs": [], + "source": [ + "from feast import FeatureStore\n", + "import pandas as pd\n", + "\n", + "store = FeatureStore(repo_path=\".\")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "2bd1f1da", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "92de6524b74c4a98ac1b56668926681a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Loading checkpoint shards: 0%| | 0/2 [00:00:241: DeprecationWarning: builtin type SwigPyPacked has no __module__ attribute\n", + ":241: DeprecationWarning: builtin type SwigPyObject has no __module__ attribute\n", + ":241: DeprecationWarning: builtin type swigvarlink has no __module__ attribute\n" + ] + } + ], + "source": [ + "import sys\n", + "sys.path.append(\"..\")\n", + "from text_feature_view import text_feature_view\n", + "from feast.vector_store import FeastVectorStore\n", + "from feast.rag_retriever import FeastIndex, FeastRAGRetriever\n", + "\n", + "generator_config=generator_model.config\n", + "question_encoder = AutoModel.from_pretrained(\"sentence-transformers/all-MiniLM-L6-v2\")\n", + "question_encoder_tokenizer = AutoTokenizer.from_pretrained(\"sentence-transformers/all-MiniLM-L6-v2\")\n", + "\n", + "\n", + "query_encoder_config = {\n", + " \"model_type\": \"bert\",\n", + " \"hidden_size\": 384\n", + "}\n", + "\n", + "vector_store = FeastVectorStore(\n", + " repo_path=\".\",\n", + " rag_view=text_feature_view,\n", + " features=[\"text_feature_view:text\", \"text_feature_view:embedding\", \"text_feature_view:passage_id\",\"text_feature_view:source_id\"]\n", + ")\n", + "\n", + "feast_index = FeastIndex()\n", + "\n", + "config = RagConfig(\n", + " question_encoder=query_encoder_config,\n", + " generator=generator_config.to_dict(),\n", + " index=feast_index\n", + ")\n", + "retriever = FeastRAGRetriever(\n", + " question_encoder=question_encoder,\n", + " question_encoder_tokenizer=question_encoder_tokenizer,\n", + " generator_tokenizer=generator_tokenizer,\n", + " feast_repo_path=\".\",\n", + " feature_view=vector_store.rag_view,\n", + " features=vector_store.features,\n", + " generator_model=generator_model, \n", + " search_type=\"vector\",\n", + " id_field=\"passage_id\",\n", + " text_field=\"text\",\n", + " config=config,\n", + " index=feast_index,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "09793dd4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Connecting to Milvus remotely at http://localhost:19530\n", + "Generated Answer: Context: \n", + "\n", + "Question: What is the capital of Ireland?\n", + "\n", + "Answer: The capital of Ireland is Dublin.\n", + "\n", + "Context: \n", + "\n", + "Question: What is the capital of Ireland?\n", + "\n", + "Answer: The capital of Ireland is Dublin.\n", + "\n", + "Context: \n", + "\n", + "Question: What is the capital city of Australia?\n", + "\n", + "Answer: The capital city of Australia is Canberra.\n", + "\n", + "Context: \n", + "\n", + "Question: What is the capital of Ireland?\n", + "\n", + "Answer: The capital of I\n" + ] + } + ], + "source": [ + "query = \"What is the capital of Ireland?\"\n", + "answer = retriever.generate_answer(query, top_k=10)\n", + "print(\"Generated Answer:\", answer)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.14" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/rag/feature_repo/example_repo.py b/examples/rag/feature_repo/example_repo.py index e0a9be21452..7a37d99d495 100644 --- a/examples/rag/feature_repo/example_repo.py +++ b/examples/rag/feature_repo/example_repo.py @@ -39,4 +39,4 @@ ], source=source, ttl=timedelta(hours=2), -) \ No newline at end of file +) diff --git a/examples/rag/feature_repo/test_workflow.py b/examples/rag/feature_repo/test_workflow.py index 05cd554d823..8a8a8813bf9 100644 --- a/examples/rag/feature_repo/test_workflow.py +++ b/examples/rag/feature_repo/test_workflow.py @@ -33,21 +33,23 @@ def run_model(sentences, tokenizer, model): sentence_embeddings = F.normalize(sentence_embeddings, p=2, dim=1) return sentence_embeddings + def run_demo(): store = FeatureStore(repo_path=".") df = pd.read_parquet("./data/city_wikipedia_summaries_with_embeddings.parquet") - embedding_length = len(df['vector'][0]) - print(f'embedding length = {embedding_length}') + embedding_length = len(df["vector"][0]) + print(f"embedding length = {embedding_length}") store.apply([city_embeddings_feature_view, item]) - fields = [ - f.name for f in city_embeddings_feature_view.features - ] + city_embeddings_feature_view.entities + [city_embeddings_feature_view.batch_source.timestamp_field] - print('\ndata=') + fields = ( + [f.name for f in city_embeddings_feature_view.features] + + city_embeddings_feature_view.entities + + [city_embeddings_feature_view.batch_source.timestamp_field] + ) + print("\ndata=") print(df[fields].head().T) store.write_to_online_store("city_embeddings", df[fields][0:3]) - question = "the most populous city in the state of New York is New York" tokenizer = AutoTokenizer.from_pretrained(TOKENIZER) model = AutoModel.from_pretrained(MODEL) @@ -70,5 +72,6 @@ def run_demo(): print(features.to_df()) store.teardown() + if __name__ == "__main__": run_demo() diff --git a/examples/rbac-remote/client/k8s/feature_repo/test.py b/examples/rbac-remote/client/k8s/feature_repo/test.py index 6e1480bc947..96fe678d5f8 100644 --- a/examples/rbac-remote/client/k8s/feature_repo/test.py +++ b/examples/rbac-remote/client/k8s/feature_repo/test.py @@ -20,9 +20,11 @@ def run_demo(): try: print("\n--- Load features into online store/materialize_incremental ---") - feature_views= store.list_feature_views() + feature_views = store.list_feature_views() if not feature_views: - raise PermissionError("No access to feature-views or no feature-views available.") + raise PermissionError( + "No access to feature-views or no feature-views available." + ) store.materialize_incremental(end_date=datetime.now()) except PermissionError as pe: print(f"Permission error: {pe}") @@ -74,9 +76,7 @@ def fetch_historical_features_entity_df(store: FeatureStore, for_batch_scoring: # values we're using for an on-demand transformation "val_to_add": [1, 2, 3], "val_to_add_2": [10, 20, 30], - } - ) if for_batch_scoring: entity_df["event_timestamp"] = pd.to_datetime("now", utc=True) diff --git a/examples/rbac-remote/client/oidc/feature_repo/test.py b/examples/rbac-remote/client/oidc/feature_repo/test.py index 6e1480bc947..96fe678d5f8 100644 --- a/examples/rbac-remote/client/oidc/feature_repo/test.py +++ b/examples/rbac-remote/client/oidc/feature_repo/test.py @@ -20,9 +20,11 @@ def run_demo(): try: print("\n--- Load features into online store/materialize_incremental ---") - feature_views= store.list_feature_views() + feature_views = store.list_feature_views() if not feature_views: - raise PermissionError("No access to feature-views or no feature-views available.") + raise PermissionError( + "No access to feature-views or no feature-views available." + ) store.materialize_incremental(end_date=datetime.now()) except PermissionError as pe: print(f"Permission error: {pe}") @@ -74,9 +76,7 @@ def fetch_historical_features_entity_df(store: FeatureStore, for_batch_scoring: # values we're using for an on-demand transformation "val_to_add": [1, 2, 3], "val_to_add_2": [10, 20, 30], - } - ) if for_batch_scoring: entity_df["event_timestamp"] = pd.to_datetime("now", utc=True) diff --git a/examples/rbac-remote/server/feature_repo/example_repo.py b/examples/rbac-remote/server/feature_repo/example_repo.py index 5b8105bb948..08914f33b73 100644 --- a/examples/rbac-remote/server/feature_repo/example_repo.py +++ b/examples/rbac-remote/server/feature_repo/example_repo.py @@ -5,7 +5,9 @@ import pandas as pd from feast import Entity, FeatureService, FeatureView, Field, PushSource, RequestSource -from feast.infra.offline_stores.contrib.postgres_offline_store.postgres_source import PostgreSQLSource +from feast.infra.offline_stores.contrib.postgres_offline_store.postgres_source import ( + PostgreSQLSource, +) from feast.on_demand_feature_view import on_demand_feature_view from feast.types import Float32, Float64, Int64 diff --git a/examples/rbac-remote/server/feature_repo/permissions_apply.py b/examples/rbac-remote/server/feature_repo/permissions_apply.py index 93bdf2ffc62..244d0bcc73f 100644 --- a/examples/rbac-remote/server/feature_repo/permissions_apply.py +++ b/examples/rbac-remote/server/feature_repo/permissions_apply.py @@ -10,12 +10,12 @@ name="feast_user_permission", types=ALL_RESOURCE_TYPES, policy=RoleBasedPolicy(roles=user_roles), - actions=[AuthzedAction.DESCRIBE] + READ + actions=[AuthzedAction.DESCRIBE] + READ, ) admin_perm = Permission( name="feast_admin_permission", types=ALL_RESOURCE_TYPES, policy=RoleBasedPolicy(roles=admin_roles), - actions=ALL_ACTIONS + actions=ALL_ACTIONS, ) diff --git a/go.mod b/go.mod index 46332e3c807..d59d6cfa4b3 100644 --- a/go.mod +++ b/go.mod @@ -11,12 +11,16 @@ require ( github.com/aws/aws-sdk-go-v2/config v1.29.14 github.com/aws/aws-sdk-go-v2/service/dynamodb v1.43.3 github.com/aws/aws-sdk-go-v2/service/s3 v1.79.3 + github.com/cabify/gotoprom v1.1.0 github.com/ghodss/yaml v1.0.0 github.com/go-sql-driver/mysql v1.8.1 github.com/golang/protobuf v1.5.4 github.com/google/uuid v1.6.0 + github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 + github.com/jackc/pgx/v5 v5.8.0 github.com/mattn/go-sqlite3 v1.14.23 github.com/pkg/errors v0.9.1 + github.com/prometheus/client_golang v1.23.2 github.com/redis/go-redis/v9 v9.6.1 github.com/roberson-io/mmh3 v0.0.0-20190729202758-fdfce3ba6225 github.com/rs/zerolog v1.33.0 @@ -64,6 +68,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 // indirect github.com/aws/smithy-go v1.22.2 // indirect + github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 // indirect @@ -81,10 +86,10 @@ require ( github.com/google/s2a-go v0.1.9 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.7 // indirect github.com/googleapis/gax-go/v2 v2.15.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect - github.com/jackc/pgx/v5 v5.8.0 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/klauspost/asmfmt v1.3.2 // indirect github.com/klauspost/compress v1.18.0 // indirect @@ -93,9 +98,13 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 // indirect github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pierrec/lz4/v4 v4.1.21 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.66.1 // indirect + github.com/prometheus/procfs v0.16.1 // indirect github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/zeebo/errs v1.4.0 // indirect @@ -107,6 +116,7 @@ require ( go.opentelemetry.io/otel/metric v1.38.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect go.opentelemetry.io/proto/otlp v1.7.1 // indirect + go.yaml.in/yaml/v2 v2.4.2 // indirect golang.org/x/crypto v0.45.0 // indirect golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect golang.org/x/mod v0.29.0 // indirect diff --git a/go.sum b/go.sum index 51d24f57197..b9112cc4961 100644 --- a/go.sum +++ b/go.sum @@ -32,6 +32,8 @@ github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapp github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.54.0/go.mod h1:Mf6O40IAyB9zR/1J8nGDDPirZQQPbYJni8Yisy7NTMc= github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c h1:RGWPOewvKIROun94nF7v2cua9qP+thov/7M50KEoeSU= github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/apache/arrow/go/v17 v17.0.0 h1:RRR2bdqKcdbss9Gxy2NS/hK8i4LDMh23L6BbkN5+F54= @@ -78,10 +80,16 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 h1:1XuUZ8mYJw9B6lzAkXhqHlJd/Xv github.com/aws/aws-sdk-go-v2/service/sts v1.33.19/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4= github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ= github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/cabify/gotoprom v1.1.0 h1:IyM06IuVDPpEhBdXqSIfQK1KGrerkjGkDamrQqu8dWo= +github.com/cabify/gotoprom v1.1.0/go.mod h1:8H4gdB+iJqM8QrNneQxxbYsx4xA7m3h1BP8K7h16R4w= github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= @@ -90,6 +98,7 @@ github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 h1:aQ3y1lwWyqYPiWZThqv github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= @@ -108,6 +117,8 @@ github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-jose/go-jose/v4 v4.1.2 h1:TK/7NqRQZfgAh+Td8AlsrvtPoUyiHh0LqVvokh+1vHI= github.com/go-jose/go-jose/v4 v4.1.2/go.mod h1:22cg9HWM1pOlnRiY+9cQYJ9XHmya1bYW8OeDM6Ku6Oo= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -115,9 +126,13 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= @@ -136,6 +151,10 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.7 h1:zrn2Ee/nWmHulBx5sAV github.com/googleapis/enterprise-certificate-proxy v0.3.7/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA= github.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo= github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= @@ -146,16 +165,22 @@ github.com/jackc/pgx/v5 v5.8.0 h1:TYPDoleBBme0xGSAX3/+NujXXtpZn9HBONkQC7IEZSo= github.com/jackc/pgx/v5 v5.8.0/go.mod h1:QVeDInX2m9VyzvNeiCJVjCkNFqzsNb43204HshNSZKw= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4= github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -164,12 +189,19 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-sqlite3 v1.14.23 h1:gbShiuAP1W5j9UOksQ06aiiqPMxYecovVGwmTxWtuw0= github.com/mattn/go-sqlite3 v1.14.23/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 h1:AMFGa4R4MiIpspGNG7Z948v4n35fFGB3RR3G/ry4FWs= github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8DFdX7uMikMLXX4oubIzJF4kv/wI= github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= @@ -177,6 +209,21 @@ github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= +github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4= github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= github.com/roberson-io/mmh3 v0.0.0-20190729202758-fdfce3ba6225 h1:ZMsPCp7oYgjoIFt1c+sM2qojxZXotSYcMF8Ur9/LJlM= @@ -186,13 +233,17 @@ github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7 github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spiffe/go-spiffe/v2 v2.5.0 h1:N2I01KCUkv1FAjZXJMwh95KK1ZIQLYbPfhaxw8WS0hE= github.com/spiffe/go-spiffe/v2 v2.5.0/go.mod h1:P+NxobPc6wXhVtINNtFjNWGBTreew1GBUCwT2wPmb7g= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= @@ -231,18 +282,26 @@ go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOV go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo= golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -273,9 +332,11 @@ google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/go/README.md b/go/README.md index a8e381519a4..308787cac9f 100644 --- a/go/README.md +++ b/go/README.md @@ -6,14 +6,27 @@ To build and run the Go Feature Server locally, create a feature_store.yaml file ```bash go build -o feast-go ./go/main.go - # start the http server - ./feast-go --type=http --port=8080 + # start the http server (metrics on port 9090 by default) + ./feast-go --type=http --port=8080 --metrics-port=9090 # or start the gRPC server - #./feast-go --type=grpc --port=[your-choice] + #./feast-go --type=grpc --port=[your-choice] --metrics-port=9091 ``` +## Prometheus Metrics +The server exposes Prometheus metrics at the `/metrics` endpoint on a dedicated port (default `:9090`). +- **HTTP Mode**: Metrics server runs on port `9090` (configurable via `-metrics-port`). +- **gRPC Mode**: Metrics server runs on port `9090` (configurable via `-metrics-port`). + +Key metrics include: +- `http_request_duration_seconds`: Histogram of response latency. +- `http_requests_total`: Counter of HTTP requests by status, method, and path. +- Standard Go and Process metrics. + +A `/health` endpoint is available on the main application port (default `:8080`) for readiness probes. + ## OTEL based observability The OS level env variable `ENABLE_OTEL_TRACING=="true"/"false"` (string type) is used to enable/disable this service (with Tracing only). +You can also configure the service name using `OTEL_SERVICE_NAME` env variable (defaults to "FeastGoFeatureServer"). The default exporter URL is "http://localhost:4318". The default schema of sending data to collector is **HTTP**. Please refer the following two docs about the configuration of the OTEL exporter: 1. https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/ diff --git a/go/internal/feast/metrics/metrics.go b/go/internal/feast/metrics/metrics.go new file mode 100644 index 00000000000..804eef6fa1b --- /dev/null +++ b/go/internal/feast/metrics/metrics.go @@ -0,0 +1,66 @@ +package metrics + +import ( + "reflect" + "time" + + "github.com/cabify/gotoprom" + "github.com/cabify/gotoprom/prometheusvanilla" + "github.com/prometheus/client_golang/prometheus" +) + +var HttpMetrics struct { + Duration func(HttpLabels) TimeHistogram `name:"http_request_duration_seconds" help:"Time taken to serve HTTP requests" buckets:".005,.01,.025,.05,.1,.25,.5,1,2.5,5,10"` + + RequestsTotal func(HttpLabels) prometheus.Counter `name:"http_requests_total" help:"Total number of HTTP requests"` +} + +type HttpLabels struct { + Method string `label:"method"` + Status int `label:"status"` + Path string `label:"path"` +} + +func init() { + gotoprom.MustAddBuilder(TimeHistogramType, RegisterTimeHistogram) + gotoprom.MustInit(&HttpMetrics, "feast") +} + +var ( + TimeHistogramType = reflect.TypeOf((*TimeHistogram)(nil)).Elem() +) + + +func RegisterTimeHistogram(name, help, namespace string, labelNames []string, tag reflect.StructTag) (func(prometheus.Labels) interface{}, prometheus.Collector, error) { + f, collector, err := prometheusvanilla.BuildHistogram(name, help, namespace, labelNames, tag) + if err != nil { + return nil, nil, err + } + + return func(labels prometheus.Labels) interface{} { + return timeHistogramAdapter{Histogram: f(labels).(prometheus.Histogram)} + }, collector, nil +} + +// TimeHistogram offers the basic prometheus.Histogram functionality +type TimeHistogram interface { + prometheus.Histogram + // Duration observes the duration in seconds + Duration(duration time.Duration) + // Since observes the duration in seconds since the time point provided + Since(time.Time) +} + +type timeHistogramAdapter struct { + prometheus.Histogram +} + +// Duration observes the duration in seconds +func (to timeHistogramAdapter) Duration(duration time.Duration) { + to.Observe(duration.Seconds()) +} + +// Since observes the duration in seconds since the time point provided +func (to timeHistogramAdapter) Since(duration time.Time) { + to.Duration(time.Since(duration)) +} diff --git a/go/internal/feast/onlineserving/serving.go b/go/internal/feast/onlineserving/serving.go index ff70443015a..1ce5f6c555c 100644 --- a/go/internal/feast/onlineserving/serving.go +++ b/go/internal/feast/onlineserving/serving.go @@ -4,6 +4,7 @@ import ( "crypto/sha256" "errors" "fmt" + "regexp" "sort" "strings" @@ -20,6 +21,8 @@ import ( "github.com/feast-dev/feast/go/types" ) +var versionTagRegex = regexp.MustCompile(`^[vV]\d+$`) + /* FeatureVector type represent result of retrieving single feature for multiple rows. It can be imagined as a column in output dataframe / table. @@ -492,6 +495,18 @@ func ParseFeatureReference(featureRef string) (featureViewName, featureName stri featureViewName = parsedFeatureName[0] featureName = parsedFeatureName[1] } + + // Handle @version qualifier on feature view name + if atIdx := strings.Index(featureViewName, "@"); atIdx >= 0 { + suffix := featureViewName[atIdx+1:] + if versionTagRegex.MatchString(suffix) { + e = fmt.Errorf("versioned feature refs (@%s) are not supported by the Go feature server", suffix) + return + } + if strings.EqualFold(suffix, "latest") { + featureViewName = featureViewName[:atIdx] + } + } return } diff --git a/go/internal/feast/onlinestore/postgresonlinestore.go b/go/internal/feast/onlinestore/postgresonlinestore.go index a05e21df775..4813f341db7 100644 --- a/go/internal/feast/onlinestore/postgresonlinestore.go +++ b/go/internal/feast/onlinestore/postgresonlinestore.go @@ -166,7 +166,7 @@ func buildPostgresConnString(config map[string]interface{}) string { if sslMode, ok := config["sslmode"].(string); ok && sslMode != "" { query.Set("sslmode", sslMode) } else { - query.Set("sslmode", "disable") + query.Set("sslmode", "require") } if v, ok := config["sslcert_path"].(string); ok && v != "" { diff --git a/go/internal/feast/onlinestore/postgresonlinestore_test.go b/go/internal/feast/onlinestore/postgresonlinestore_test.go index 2d81ba2cddb..b241e857e18 100644 --- a/go/internal/feast/onlinestore/postgresonlinestore_test.go +++ b/go/internal/feast/onlinestore/postgresonlinestore_test.go @@ -34,7 +34,7 @@ func TestBuildPostgresConnStringDefaults(t *testing.T) { } connStr := buildPostgresConnString(config) assert.Contains(t, connStr, "localhost:5432") - assert.Contains(t, connStr, "sslmode=disable") + assert.Contains(t, connStr, "sslmode=require") } func TestBuildPostgresConnStringWithSSL(t *testing.T) { diff --git a/go/internal/feast/server/http_server.go b/go/internal/feast/server/http_server.go index 312a0a6352e..adfd40110e7 100644 --- a/go/internal/feast/server/http_server.go +++ b/go/internal/feast/server/http_server.go @@ -17,6 +17,8 @@ import ( prototypes "github.com/feast-dev/feast/go/protos/feast/types" "github.com/feast-dev/feast/go/types" "github.com/rs/zerolog/log" + + "github.com/feast-dev/feast/go/internal/feast/metrics" ) type httpServer struct { @@ -335,10 +337,55 @@ func recoverMiddleware(next http.Handler) http.Handler { }) } +type statusWriter struct { + http.ResponseWriter + status int +} + +func (w *statusWriter) WriteHeader(status int) { + if w.status == 0 { + w.status = status + } + w.ResponseWriter.WriteHeader(status) +} + +func (w *statusWriter) Write(b []byte) (int, error) { + if w.status == 0 { + w.status = 200 + } + n, err := w.ResponseWriter.Write(b) + return n, err +} + +func metricsMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + t0 := time.Now() + sw := &statusWriter{ResponseWriter: w} + next.ServeHTTP(sw, r) + duration := time.Since(t0) + + if sw.status == 0 { + sw.status = 200 + } + + metrics.HttpMetrics.Duration(metrics.HttpLabels{ + Method: r.Method, + Status: sw.status, + Path: r.URL.Path, + }).Duration(duration) + + metrics.HttpMetrics.RequestsTotal(metrics.HttpLabels{ + Method: r.Method, + Status: sw.status, + Path: r.URL.Path, + }).Inc() + }) +} + func (s *httpServer) Serve(host string, port int) error { mux := http.NewServeMux() - mux.Handle("/get-online-features", recoverMiddleware(http.HandlerFunc(s.getOnlineFeatures))) - mux.HandleFunc("/health", healthCheckHandler) + mux.Handle("/get-online-features", metricsMiddleware(recoverMiddleware(http.HandlerFunc(s.getOnlineFeatures)))) + mux.Handle("/health", metricsMiddleware(http.HandlerFunc(healthCheckHandler))) s.server = &http.Server{Addr: fmt.Sprintf("%s:%d", host, port), Handler: mux, ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, IdleTimeout: 15 * time.Second} err := s.server.ListenAndServe() // Don't return the error if it's caused by graceful shutdown using Stop() diff --git a/go/internal/test/feature_repo/example.py b/go/internal/test/feature_repo/example.py index a814b58913b..efd1966d03e 100644 --- a/go/internal/test/feature_repo/example.py +++ b/go/internal/test/feature_repo/example.py @@ -2,7 +2,7 @@ from datetime import timedelta -from feast import Entity, Feature, FeatureView, Field, FileSource, FeatureService, RequestSource +from feast import Entity, FeatureView, Field, FileSource, FeatureService, RequestSource from feast.feature_logging import LoggingConfig from feast.infra.offline_stores.file_source import FileLoggingDestination from feast.types import Float32, Float64, Int64, PrimitiveFeastType @@ -42,7 +42,7 @@ driver_stats_fs = FeatureService( name="test_service", features=[driver_hourly_stats_view], - logging_config=LoggingConfig(destination=FileLoggingDestination(path="")) + logging_config=LoggingConfig(destination=FileLoggingDestination(path="")), ) @@ -53,22 +53,20 @@ schema=[ Field(name="val_to_add", dtype=PrimitiveFeastType.INT64), Field(name="val_to_add_2", dtype=PrimitiveFeastType.INT64), - ] + ], ) + # Use the input data and feature view features to create new features @on_demand_feature_view( - sources=[ - driver_hourly_stats_view, - input_request - ], - schema=[ - Field(name='conv_rate_plus_val1', dtype=Float64), - Field(name='conv_rate_plus_val2', dtype=Float64) - ] + sources=[driver_hourly_stats_view, input_request], + schema=[ + Field(name="conv_rate_plus_val1", dtype=Float64), + Field(name="conv_rate_plus_val2", dtype=Float64), + ], ) def transformed_conv_rate(features_df: pd.DataFrame) -> pd.DataFrame: df = pd.DataFrame() - df['conv_rate_plus_val1'] = (features_df['conv_rate'] + features_df['val_to_add']) - df['conv_rate_plus_val2'] = (features_df['conv_rate'] + features_df['val_to_add_2']) + df["conv_rate_plus_val1"] = features_df["conv_rate"] + features_df["val_to_add"] + df["conv_rate_plus_val2"] = features_df["conv_rate"] + features_df["val_to_add_2"] return df diff --git a/go/main.go b/go/main.go index 77999671e07..f49a27efa46 100644 --- a/go/main.go +++ b/go/main.go @@ -5,9 +5,11 @@ import ( "flag" "fmt" "net" + "net/http" "os" "os/signal" "strings" + "sync" "syscall" "github.com/feast-dev/feast/go/internal/feast" @@ -20,6 +22,9 @@ import ( "google.golang.org/grpc/health" "google.golang.org/grpc/health/grpc_health_v1" + grpc_prometheus "github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp/otlptrace" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" @@ -32,18 +37,18 @@ import ( var tracer trace.Tracer type ServerStarter interface { - StartHttpServer(fs *feast.FeatureStore, host string, port int, writeLoggedFeaturesCallback logging.OfflineStoreWriteCallback, loggingOpts *logging.LoggingOptions) error - StartGrpcServer(fs *feast.FeatureStore, host string, port int, writeLoggedFeaturesCallback logging.OfflineStoreWriteCallback, loggingOpts *logging.LoggingOptions) error + StartHttpServer(fs *feast.FeatureStore, host string, port int, metricsPort int, writeLoggedFeaturesCallback logging.OfflineStoreWriteCallback, loggingOpts *logging.LoggingOptions) error + StartGrpcServer(fs *feast.FeatureStore, host string, port int, metricsPort int, writeLoggedFeaturesCallback logging.OfflineStoreWriteCallback, loggingOpts *logging.LoggingOptions) error } type RealServerStarter struct{} -func (s *RealServerStarter) StartHttpServer(fs *feast.FeatureStore, host string, port int, writeLoggedFeaturesCallback logging.OfflineStoreWriteCallback, loggingOpts *logging.LoggingOptions) error { - return StartHttpServer(fs, host, port, writeLoggedFeaturesCallback, loggingOpts) +func (s *RealServerStarter) StartHttpServer(fs *feast.FeatureStore, host string, port int, metricsPort int, writeLoggedFeaturesCallback logging.OfflineStoreWriteCallback, loggingOpts *logging.LoggingOptions) error { + return StartHttpServer(fs, host, port, metricsPort, writeLoggedFeaturesCallback, loggingOpts) } -func (s *RealServerStarter) StartGrpcServer(fs *feast.FeatureStore, host string, port int, writeLoggedFeaturesCallback logging.OfflineStoreWriteCallback, loggingOpts *logging.LoggingOptions) error { - return StartGrpcServer(fs, host, port, writeLoggedFeaturesCallback, loggingOpts) +func (s *RealServerStarter) StartGrpcServer(fs *feast.FeatureStore, host string, port int, metricsPort int, writeLoggedFeaturesCallback logging.OfflineStoreWriteCallback, loggingOpts *logging.LoggingOptions) error { + return StartGrpcServer(fs, host, port, metricsPort, writeLoggedFeaturesCallback, loggingOpts) } func main() { @@ -51,6 +56,7 @@ func main() { serverType := "http" host := "" port := 8080 + metricsPort := 9090 server := RealServerStarter{} // Current Directory repoPath, err := os.Getwd() @@ -63,6 +69,7 @@ func main() { flag.StringVar(&host, "host", host, "Specify a host for the server") flag.IntVar(&port, "port", port, "Specify a port for the server") + flag.IntVar(&metricsPort, "metrics-port", metricsPort, "Specify a port for the metrics server") flag.Parse() // Initialize tracer @@ -109,9 +116,9 @@ func main() { // TODO: writeLoggedFeaturesCallback is defaulted to nil. write_logged_features functionality needs to be // implemented in Golang specific to OfflineStoreSink. Python Feature Server doesn't support this. if serverType == "http" { - err = server.StartHttpServer(fs, host, port, nil, loggingOptions) + err = server.StartHttpServer(fs, host, port, metricsPort, nil, loggingOptions) } else if serverType == "grpc" { - err = server.StartGrpcServer(fs, host, port, nil, loggingOptions) + err = server.StartGrpcServer(fs, host, port, metricsPort, nil, loggingOptions) } else { fmt.Println("Unknown server type. Please specify 'http' or 'grpc'.") } @@ -144,7 +151,7 @@ func constructLoggingService(fs *feast.FeatureStore, writeLoggedFeaturesCallback } // StartGprcServerWithLogging starts gRPC server with enabled feature logging -func StartGrpcServer(fs *feast.FeatureStore, host string, port int, writeLoggedFeaturesCallback logging.OfflineStoreWriteCallback, loggingOpts *logging.LoggingOptions) error { +func StartGrpcServer(fs *feast.FeatureStore, host string, port int, metricsPort int, writeLoggedFeaturesCallback logging.OfflineStoreWriteCallback, loggingOpts *logging.LoggingOptions) error { loggingService, err := constructLoggingService(fs, writeLoggedFeaturesCallback, loggingOpts) if err != nil { return err @@ -155,58 +162,127 @@ func StartGrpcServer(fs *feast.FeatureStore, host string, port int, writeLoggedF if err != nil { return err } - - grpcServer := grpc.NewServer() + srvMetrics := grpc_prometheus.NewServerMetrics( + grpc_prometheus.WithServerHandlingTimeHistogram( + grpc_prometheus.WithHistogramBuckets([]float64{0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10}), + ), + ) + prometheus.MustRegister(srvMetrics) + grpcServer := grpc.NewServer( + grpc.UnaryInterceptor(srvMetrics.UnaryServerInterceptor()), + ) serving.RegisterServingServiceServer(grpcServer, ser) healthService := health.NewServer() grpc_health_v1.RegisterHealthServer(grpcServer, healthService) + srvMetrics.InitializeMetrics(grpcServer) + + // Start metrics server + metricsServer := &http.Server{Addr: fmt.Sprintf(":%d", metricsPort)} + go func() { + log.Info().Msgf("Starting metrics server on port %d", metricsPort) + mux := http.NewServeMux() + mux.Handle("/metrics", promhttp.Handler()) + metricsServer.Handler = mux + if err := metricsServer.ListenAndServe(); err != nil && err != http.ErrServerClosed { + log.Error().Err(err).Msg("Failed to start metrics server") + } + }() stop := make(chan os.Signal, 1) signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM) + var wg sync.WaitGroup + wg.Add(1) + serverExited := make(chan struct{}) go func() { - // As soon as these signals are received from OS, try to gracefully stop the gRPC server - <-stop - log.Info().Msg("Stopping the gRPC server...") - grpcServer.GracefulStop() - if loggingService != nil { - loggingService.Stop() + defer wg.Done() + select { + case <-stop: + // Received SIGINT/SIGTERM. Perform graceful shutdown. + log.Info().Msg("Stopping the gRPC server...") + grpcServer.GracefulStop() + if loggingService != nil { + loggingService.Stop() + } + log.Info().Msg("Stopping metrics server...") + if err := metricsServer.Shutdown(context.Background()); err != nil { + log.Error().Err(err).Msg("Error stopping metrics server") + } + log.Info().Msg("gRPC server terminated") + case <-serverExited: + // Server exited (e.g. startup error), ensure metrics server is stopped + metricsServer.Shutdown(context.Background()) + if loggingService != nil { + loggingService.Stop() + } } - log.Info().Msg("gRPC server terminated") }() - return grpcServer.Serve(lis) + err = grpcServer.Serve(lis) + close(serverExited) + wg.Wait() + return err } // StartHttpServerWithLogging starts HTTP server with enabled feature logging // Go does not allow direct assignment to package-level functions as a way to // mock them for tests -func StartHttpServer(fs *feast.FeatureStore, host string, port int, writeLoggedFeaturesCallback logging.OfflineStoreWriteCallback, loggingOpts *logging.LoggingOptions) error { +func StartHttpServer(fs *feast.FeatureStore, host string, port int, metricsPort int, writeLoggedFeaturesCallback logging.OfflineStoreWriteCallback, loggingOpts *logging.LoggingOptions) error { loggingService, err := constructLoggingService(fs, writeLoggedFeaturesCallback, loggingOpts) if err != nil { return err } ser := server.NewHttpServer(fs, loggingService) log.Info().Msgf("Starting a HTTP server on host %s, port %d", host, port) + // Start metrics server + metricsServer := &http.Server{Addr: fmt.Sprintf(":%d", metricsPort)} + go func() { + log.Info().Msgf("Starting metrics server on port %d", metricsPort) + mux := http.NewServeMux() + mux.Handle("/metrics", promhttp.Handler()) + metricsServer.Handler = mux + if err := metricsServer.ListenAndServe(); err != nil && err != http.ErrServerClosed { + log.Error().Err(err).Msg("Failed to start metrics server") + } + }() stop := make(chan os.Signal, 1) signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM) + var wg sync.WaitGroup + wg.Add(1) + serverExited := make(chan struct{}) go func() { - // As soon as these signals are received from OS, try to gracefully stop the gRPC server - <-stop - log.Info().Msg("Stopping the HTTP server...") - err := ser.Stop() - if err != nil { - log.Error().Err(err).Msg("Error when stopping the HTTP server") - } - if loggingService != nil { - loggingService.Stop() + defer wg.Done() + select { + case <-stop: + // Received SIGINT/SIGTERM. Perform graceful shutdown. + log.Info().Msg("Stopping the HTTP server...") + err := ser.Stop() + if err != nil { + log.Error().Err(err).Msg("Error when stopping the HTTP server") + } + log.Info().Msg("Stopping metrics server...") + if err := metricsServer.Shutdown(context.Background()); err != nil { + log.Error().Err(err).Msg("Error stopping metrics server") + } + if loggingService != nil { + loggingService.Stop() + } + log.Info().Msg("HTTP server terminated") + case <-serverExited: + // Server exited (e.g. startup error), ensure metrics server is stopped + metricsServer.Shutdown(context.Background()) + if loggingService != nil { + loggingService.Stop() + } } - log.Info().Msg("HTTP server terminated") }() - return ser.Serve(host, port) + err = ser.Serve(host, port) + close(serverExited) + wg.Wait() + return err } func OTELTracingEnabled() bool { @@ -223,11 +299,15 @@ func newExporter(ctx context.Context) (*otlptrace.Exporter, error) { } func newTracerProvider(exp sdktrace.SpanExporter) (*sdktrace.TracerProvider, error) { + serviceName := os.Getenv("OTEL_SERVICE_NAME") + if serviceName == "" { + serviceName = "FeastGoFeatureServer" + } r, err := resource.Merge( resource.Default(), resource.NewWithAttributes( semconv.SchemaURL, - semconv.ServiceName("FeastGoFeatureServer"), + semconv.ServiceName(serviceName), ), ) diff --git a/go/main_test.go b/go/main_test.go index 567a6cf5af4..f1f2ae98698 100644 --- a/go/main_test.go +++ b/go/main_test.go @@ -14,13 +14,13 @@ type MockServerStarter struct { mock.Mock } -func (m *MockServerStarter) StartHttpServer(fs *feast.FeatureStore, host string, port int, writeLoggedFeaturesCallback logging.OfflineStoreWriteCallback, loggingOpts *logging.LoggingOptions) error { - args := m.Called(fs, host, port, writeLoggedFeaturesCallback, loggingOpts) +func (m *MockServerStarter) StartHttpServer(fs *feast.FeatureStore, host string, port int, metricsPort int, writeLoggedFeaturesCallback logging.OfflineStoreWriteCallback, loggingOpts *logging.LoggingOptions) error { + args := m.Called(fs, host, port, metricsPort, writeLoggedFeaturesCallback, loggingOpts) return args.Error(0) } -func (m *MockServerStarter) StartGrpcServer(fs *feast.FeatureStore, host string, port int, writeLoggedFeaturesCallback logging.OfflineStoreWriteCallback, loggingOpts *logging.LoggingOptions) error { - args := m.Called(fs, host, port, writeLoggedFeaturesCallback, loggingOpts) +func (m *MockServerStarter) StartGrpcServer(fs *feast.FeatureStore, host string, port int, metricsPort int, writeLoggedFeaturesCallback logging.OfflineStoreWriteCallback, loggingOpts *logging.LoggingOptions) error { + args := m.Called(fs, host, port, metricsPort, writeLoggedFeaturesCallback, loggingOpts) return args.Error(0) } @@ -34,9 +34,9 @@ func TestStartHttpServer(t *testing.T) { loggingOpts := &logging.LoggingOptions{} - mockServerStarter.On("StartHttpServer", fs, host, port, mock.AnythingOfType("logging.OfflineStoreWriteCallback"), loggingOpts).Return(nil) + mockServerStarter.On("StartHttpServer", fs, host, port, 9090, mock.AnythingOfType("logging.OfflineStoreWriteCallback"), loggingOpts).Return(nil) - err := mockServerStarter.StartHttpServer(fs, host, port, writeLoggedFeaturesCallback, loggingOpts) + err := mockServerStarter.StartHttpServer(fs, host, port, 9090, writeLoggedFeaturesCallback, loggingOpts) assert.NoError(t, err) mockServerStarter.AssertExpectations(t) } @@ -50,9 +50,9 @@ func TestStartGrpcServer(t *testing.T) { var writeLoggedFeaturesCallback logging.OfflineStoreWriteCallback loggingOpts := &logging.LoggingOptions{} - mockServerStarter.On("StartGrpcServer", fs, host, port, mock.AnythingOfType("logging.OfflineStoreWriteCallback"), loggingOpts).Return(nil) + mockServerStarter.On("StartGrpcServer", fs, host, port, 9090, mock.AnythingOfType("logging.OfflineStoreWriteCallback"), loggingOpts).Return(nil) - err := mockServerStarter.StartGrpcServer(fs, host, port, writeLoggedFeaturesCallback, loggingOpts) + err := mockServerStarter.StartGrpcServer(fs, host, port, 9090, writeLoggedFeaturesCallback, loggingOpts) assert.NoError(t, err) mockServerStarter.AssertExpectations(t) } @@ -67,5 +67,3 @@ func TestConstructLoggingService(t *testing.T) { assert.NoError(t, err) // Further assertions can be added here based on the expected behavior of constructLoggingService } - -// Note: Additional tests can be written for other functions and error scenarios. diff --git a/infra/charts/feast-feature-server/Chart.yaml b/infra/charts/feast-feature-server/Chart.yaml index 1b4e503dffd..5f72378ec3a 100644 --- a/infra/charts/feast-feature-server/Chart.yaml +++ b/infra/charts/feast-feature-server/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: feast-feature-server description: Feast Feature Server in Go or Python type: application -version: 0.60.0 +version: 0.62.0 keywords: - machine learning - big data diff --git a/infra/charts/feast-feature-server/README.md b/infra/charts/feast-feature-server/README.md index 438b3de9105..a59b872f897 100644 --- a/infra/charts/feast-feature-server/README.md +++ b/infra/charts/feast-feature-server/README.md @@ -1,6 +1,6 @@ # Feast Python / Go Feature Server Helm Charts -Current chart version is `0.60.0` +Current chart version is `0.62.0` ## Installation @@ -42,7 +42,7 @@ See [here](https://github.com/feast-dev/feast/tree/master/examples/python-helm-d | fullnameOverride | string | `""` | | | image.pullPolicy | string | `"IfNotPresent"` | | | image.repository | string | `"quay.io/feastdev/feature-server"` | Docker image for Feature Server repository | -| image.tag | string | `"0.60.0"` | The Docker image tag (can be overwritten if custom feature server deps are needed for on demand transforms) | +| image.tag | string | `"0.62.0"` | The Docker image tag (can be overwritten if custom feature server deps are needed for on demand transforms) | | imagePullSecrets | list | `[]` | | | livenessProbe.initialDelaySeconds | int | `30` | | | livenessProbe.periodSeconds | int | `30` | | diff --git a/infra/charts/feast-feature-server/values.yaml b/infra/charts/feast-feature-server/values.yaml index 9bb76d0a724..12707ea97b2 100644 --- a/infra/charts/feast-feature-server/values.yaml +++ b/infra/charts/feast-feature-server/values.yaml @@ -9,7 +9,7 @@ image: repository: quay.io/feastdev/feature-server pullPolicy: IfNotPresent # image.tag -- The Docker image tag (can be overwritten if custom feature server deps are needed for on demand transforms) - tag: 0.60.0 + tag: 0.62.0 logLevel: "WARNING" # Set log level DEBUG, INFO, WARNING, ERROR, and CRITICAL (case-insensitive) diff --git a/infra/charts/feast/Chart.yaml b/infra/charts/feast/Chart.yaml index 12e465ec052..796ef7c3251 100644 --- a/infra/charts/feast/Chart.yaml +++ b/infra/charts/feast/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v1 description: Feature store for machine learning name: feast -version: 0.60.0 +version: 0.62.0 keywords: - machine learning - big data diff --git a/infra/charts/feast/README.md b/infra/charts/feast/README.md index d577e3a14ec..0f49894bc46 100644 --- a/infra/charts/feast/README.md +++ b/infra/charts/feast/README.md @@ -8,7 +8,7 @@ This repo contains Helm charts for Feast Java components that are being installe ## Chart: Feast -Feature store for machine learning Current chart version is `0.60.0` +Feature store for machine learning Current chart version is `0.62.0` ## Installation @@ -65,8 +65,8 @@ See [here](https://github.com/feast-dev/feast/tree/master/examples/java-demo) fo | Repository | Name | Version | |------------|------|---------| | https://charts.helm.sh/stable | redis | 10.5.6 | -| https://feast-helm-charts.storage.googleapis.com | feature-server(feature-server) | 0.60.0 | -| https://feast-helm-charts.storage.googleapis.com | transformation-service(transformation-service) | 0.60.0 | +| https://feast-helm-charts.storage.googleapis.com | feature-server(feature-server) | 0.62.0 | +| https://feast-helm-charts.storage.googleapis.com | transformation-service(transformation-service) | 0.62.0 | ## Values diff --git a/infra/charts/feast/charts/feature-server/Chart.yaml b/infra/charts/feast/charts/feature-server/Chart.yaml index f3ea165878f..12c49185845 100644 --- a/infra/charts/feast/charts/feature-server/Chart.yaml +++ b/infra/charts/feast/charts/feature-server/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v1 description: "Feast Feature Server: Online feature serving service for Feast" name: feature-server -version: 0.60.0 -appVersion: v0.60.0 +version: 0.62.0 +appVersion: v0.62.0 keywords: - machine learning - big data diff --git a/infra/charts/feast/charts/feature-server/README.md b/infra/charts/feast/charts/feature-server/README.md index 290965a972f..ce02467c442 100644 --- a/infra/charts/feast/charts/feature-server/README.md +++ b/infra/charts/feast/charts/feature-server/README.md @@ -1,6 +1,6 @@ # feature-server -![Version: 0.60.0](https://img.shields.io/badge/Version-0.60.0-informational?style=flat-square) ![AppVersion: v0.60.0](https://img.shields.io/badge/AppVersion-v0.60.0-informational?style=flat-square) +![Version: 0.62.0](https://img.shields.io/badge/Version-0.62.0-informational?style=flat-square) ![AppVersion: v0.62.0](https://img.shields.io/badge/AppVersion-v0.62.0-informational?style=flat-square) Feast Feature Server: Online feature serving service for Feast @@ -17,7 +17,7 @@ Feast Feature Server: Online feature serving service for Feast | envOverrides | object | `{}` | Extra environment variables to set | | image.pullPolicy | string | `"IfNotPresent"` | Image pull policy | | image.repository | string | `"quay.io/feastdev/feature-server-java"` | Docker image for Feature Server repository | -| image.tag | string | `"0.60.0"` | Image tag | +| image.tag | string | `"0.62.0"` | Image tag | | ingress.grpc.annotations | object | `{}` | Extra annotations for the ingress | | ingress.grpc.auth.enabled | bool | `false` | Flag to enable auth | | ingress.grpc.class | string | `"nginx"` | Which ingress controller to use | diff --git a/infra/charts/feast/charts/feature-server/values.yaml b/infra/charts/feast/charts/feature-server/values.yaml index d5ab59d7ef7..a964d8f05b9 100644 --- a/infra/charts/feast/charts/feature-server/values.yaml +++ b/infra/charts/feast/charts/feature-server/values.yaml @@ -5,7 +5,7 @@ image: # image.repository -- Docker image for Feature Server repository repository: quay.io/feastdev/feature-server-java # image.tag -- Image tag - tag: 0.60.0 + tag: 0.62.0 # image.pullPolicy -- Image pull policy pullPolicy: IfNotPresent diff --git a/infra/charts/feast/charts/transformation-service/Chart.yaml b/infra/charts/feast/charts/transformation-service/Chart.yaml index c18f681a85a..351ff6e4268 100644 --- a/infra/charts/feast/charts/transformation-service/Chart.yaml +++ b/infra/charts/feast/charts/transformation-service/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v1 description: "Transformation service: to compute on-demand features" name: transformation-service -version: 0.60.0 -appVersion: v0.60.0 +version: 0.62.0 +appVersion: v0.62.0 keywords: - machine learning - big data diff --git a/infra/charts/feast/charts/transformation-service/README.md b/infra/charts/feast/charts/transformation-service/README.md index 76253c8bb0c..78e5ec12350 100644 --- a/infra/charts/feast/charts/transformation-service/README.md +++ b/infra/charts/feast/charts/transformation-service/README.md @@ -1,6 +1,6 @@ # transformation-service -![Version: 0.60.0](https://img.shields.io/badge/Version-0.60.0-informational?style=flat-square) ![AppVersion: v0.60.0](https://img.shields.io/badge/AppVersion-v0.60.0-informational?style=flat-square) +![Version: 0.62.0](https://img.shields.io/badge/Version-0.62.0-informational?style=flat-square) ![AppVersion: v0.62.0](https://img.shields.io/badge/AppVersion-v0.62.0-informational?style=flat-square) Transformation service: to compute on-demand features @@ -13,7 +13,7 @@ Transformation service: to compute on-demand features | envOverrides | object | `{}` | Extra environment variables to set | | image.pullPolicy | string | `"IfNotPresent"` | Image pull policy | | image.repository | string | `"quay.io/feastdev/feature-transformation-server"` | Docker image for Transformation Server repository | -| image.tag | string | `"0.60.0"` | Image tag | +| image.tag | string | `"0.62.0"` | Image tag | | nodeSelector | object | `{}` | Node labels for pod assignment | | podLabels | object | `{}` | Labels to be added to Feast Serving pods | | replicaCount | int | `1` | Number of pods that will be created | diff --git a/infra/charts/feast/charts/transformation-service/values.yaml b/infra/charts/feast/charts/transformation-service/values.yaml index e00e9c4f523..5ede3852e91 100644 --- a/infra/charts/feast/charts/transformation-service/values.yaml +++ b/infra/charts/feast/charts/transformation-service/values.yaml @@ -5,7 +5,7 @@ image: # image.repository -- Docker image for Transformation Server repository repository: quay.io/feastdev/feature-transformation-server # image.tag -- Image tag - tag: 0.60.0 + tag: 0.62.0 # image.pullPolicy -- Image pull policy pullPolicy: IfNotPresent diff --git a/infra/charts/feast/requirements.yaml b/infra/charts/feast/requirements.yaml index 59c3442b5a5..181c8d95fca 100644 --- a/infra/charts/feast/requirements.yaml +++ b/infra/charts/feast/requirements.yaml @@ -1,12 +1,12 @@ dependencies: - name: feature-server alias: feature-server - version: 0.60.0 + version: 0.62.0 condition: feature-server.enabled repository: https://feast-helm-charts.storage.googleapis.com - name: transformation-service alias: transformation-service - version: 0.60.0 + version: 0.62.0 condition: transformation-service.enabled repository: https://feast-helm-charts.storage.googleapis.com - name: redis diff --git a/infra/feast-operator/.golangci.bck.yml b/infra/feast-operator/.golangci.bck.yml new file mode 100644 index 00000000000..6c104980d43 --- /dev/null +++ b/infra/feast-operator/.golangci.bck.yml @@ -0,0 +1,55 @@ +run: + timeout: 5m + allow-parallel-runners: true + +issues: + # don't skip warning about doc comments + # don't exclude the default set of lint + exclude-use-default: false + # restore some of the defaults + # (fill in the rest as needed) + exclude-rules: + - path: "api/*" + linters: + - lll + - path: "internal/*" + linters: + - dupl + - lll + - path: "test/*" + linters: + - lll + - path: "upgrade/*" + linters: + - lll + - path: "previous-version/*" + linters: + - lll +linters: + disable-all: true + enable: + - dupl + - errcheck + - goconst + - gocyclo + - gofmt + - goimports + - gosimple + - govet + - ineffassign + - lll + - misspell + - nakedret + - ginkgolinter + - prealloc + - revive + - staticcheck + - typecheck + - unconvert + - unparam + - unused + +linters-settings: + revive: + rules: + - name: comment-spacings diff --git a/infra/feast-operator/.golangci.yml b/infra/feast-operator/.golangci.yml index 6c104980d43..4895f41d8fb 100644 --- a/infra/feast-operator/.golangci.yml +++ b/infra/feast-operator/.golangci.yml @@ -1,55 +1,65 @@ +version: "2" run: - timeout: 5m allow-parallel-runners: true - -issues: - # don't skip warning about doc comments - # don't exclude the default set of lint - exclude-use-default: false - # restore some of the defaults - # (fill in the rest as needed) - exclude-rules: - - path: "api/*" - linters: - - lll - - path: "internal/*" - linters: - - dupl - - lll - - path: "test/*" - linters: - - lll - - path: "upgrade/*" - linters: - - lll - - path: "previous-version/*" - linters: - - lll linters: - disable-all: true + default: none enable: - dupl - errcheck + - ginkgolinter - goconst - gocyclo - - gofmt - - goimports - - gosimple - govet - ineffassign - lll - misspell - nakedret - - ginkgolinter - prealloc - revive - staticcheck - - typecheck - unconvert - unparam - unused - -linters-settings: - revive: + settings: + revive: + rules: + - name: comment-spacings + staticcheck: + checks: + - "all" + - "-QF*" + - "-ST*" + exclusions: + generated: lax + presets: [] rules: - - name: comment-spacings + - linters: + - lll + path: api/* + - linters: + - dupl + - lll + path: internal/* + - linters: + - lll + path: test/* + - linters: + - lll + path: upgrade/* + - linters: + - lll + path: previous-version/* + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gofmt + - goimports + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/infra/feast-operator/Dockerfile b/infra/feast-operator/Dockerfile index f0814b25576..e3a4ebbed28 100644 --- a/infra/feast-operator/Dockerfile +++ b/infra/feast-operator/Dockerfile @@ -1,7 +1,8 @@ # Build the manager binary -FROM registry.access.redhat.com/ubi9/go-toolset:1.22.9 AS builder +FROM registry.access.redhat.com/ubi9/go-toolset:1.24 AS builder ARG TARGETOS ARG TARGETARCH +ENV GOTOOLCHAIN=auto # Copy the Go Modules manifests COPY go.mod go.mod diff --git a/infra/feast-operator/Makefile b/infra/feast-operator/Makefile index f017154d39d..8dd8e41c2ee 100644 --- a/infra/feast-operator/Makefile +++ b/infra/feast-operator/Makefile @@ -3,7 +3,7 @@ # To re-generate a bundle for another specific version without changing the standard setup, you can: # - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2) # - use environment variables to overwrite this value (e.g export VERSION=0.0.2) -VERSION ?= 0.60.0 +VERSION ?= 0.62.0 # CHANNELS define the bundle channels used in the bundle. # Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable") @@ -48,7 +48,7 @@ endif # Set the Operator SDK version to use. By default, what is installed on the system is used. # This is useful for CI or a project to utilize a specific version of the operator-sdk toolkit. -OPERATOR_SDK_VERSION ?= v1.38.0 +OPERATOR_SDK_VERSION ?= v1.41.0 # Image URL to use all building/pushing image targets # During development and testing, and before make deploy we need to export FS_IMG to point to # the dev image generated using command `make build-feature-server-dev-docker` @@ -56,7 +56,7 @@ IMG ?= $(IMAGE_TAG_BASE):$(VERSION) FS_IMG ?= quay.io/feastdev/feature-server:$(VERSION) CJ_IMG ?= quay.io/openshift/origin-cli:4.17 # ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. -ENVTEST_K8S_VERSION = 1.30.0 +ENVTEST_K8S_VERSION = 1.31.0 # Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) ifeq (,$(shell go env GOBIN)) @@ -116,7 +116,7 @@ vet: ## Run go vet against code. .PHONY: test test: build-installer vet lint envtest ## Run tests. - KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path --use-deprecated-gcs=false)" go test $$(go list ./... | grep -v test/e2e | grep -v test/data-source-types | grep -v test/upgrade | grep -v test/previous-version) -coverprofile cover.out + KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v test/e2e | grep -v test/data-source-types | grep -v test/upgrade | grep -v test/previous-version) -coverprofile cover.out # Utilize Kind or modify the e2e tests to load the image locally, enabling compatibility with other vendors. .PHONY: test-e2e # Run the e2e tests against a Kind k8s instance that is spun up. @@ -239,11 +239,11 @@ GOLANGCI_LINT = $(LOCALBIN)/golangci-lint ENVSUBST = $(LOCALBIN)/envsubst ## Tool Versions -KUSTOMIZE_VERSION ?= v5.4.2 -CONTROLLER_TOOLS_VERSION ?= v0.15.0 -CRD_REF_DOCS_VERSION ?= v0.1.0 -ENVTEST_VERSION ?= release-0.18 -GOLANGCI_LINT_VERSION ?= v1.59.1 +KUSTOMIZE_VERSION ?= v5.4.3 +CONTROLLER_TOOLS_VERSION ?= v0.18.0 +CRD_REF_DOCS_VERSION ?= v0.3.0 +ENVTEST_VERSION ?= release-0.21 +GOLANGCI_LINT_VERSION ?= v2.1.0 ENVSUBST_VERSION ?= v1.4.2 .PHONY: kustomize @@ -264,7 +264,7 @@ $(ENVTEST): $(LOCALBIN) .PHONY: golangci-lint golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary. $(GOLANGCI_LINT): $(LOCALBIN) - $(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION)) + $(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/v2/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION)) .PHONY: envsubst envsubst: $(ENVSUBST) ## Download envsubst locally if necessary. @@ -338,7 +338,7 @@ ifeq (,$(shell which opm 2>/dev/null)) set -e ;\ mkdir -p $(dir $(OPM)) ;\ OS=$(shell go env GOOS) && ARCH=$(shell go env GOARCH) && \ - curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.23.0/$${OS}-$${ARCH}-opm ;\ + curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.55.0/$${OS}-$${ARCH}-opm ;\ chmod +x $(OPM) ;\ } else diff --git a/infra/feast-operator/README.md b/infra/feast-operator/README.md index 6c0ef634e78..9f530ad19a6 100644 --- a/infra/feast-operator/README.md +++ b/infra/feast-operator/README.md @@ -24,6 +24,7 @@ kubectl apply --server-side --force-conflicts -f https://raw.githubusercontent.c ``` > **NOTE**: Server-Side Apply (`--server-side`) is required because the CRD includes both v1alpha1 and v1 API versions, making it too large for the standard `kubectl apply` annotation limit. If you encounter annotation size errors, use `--server-side --force-conflicts` flags. + ##### Feast Operator Demo Videos [![](https://img.youtube.com/vi/48cb4AHxPR4/0.jpg)](https://www.youtube.com/playlist?list=PLPzVNzik7rsAN-amQLZckd0so3cIr7blX) diff --git a/infra/feast-operator/api/feastversion/version.go b/infra/feast-operator/api/feastversion/version.go index f80338fb9fc..9250b88ff1b 100644 --- a/infra/feast-operator/api/feastversion/version.go +++ b/infra/feast-operator/api/feastversion/version.go @@ -17,4 +17,4 @@ limitations under the License. package feastversion // Feast release version. Keep on line #20, this is critical to release CI -const FeastVersion = "0.60.0" +const FeastVersion = "0.62.0" diff --git a/infra/feast-operator/api/v1/featurestore_types.go b/infra/feast-operator/api/v1/featurestore_types.go index 977fc586110..95d8130ab99 100644 --- a/infra/feast-operator/api/v1/featurestore_types.go +++ b/infra/feast-operator/api/v1/featurestore_types.go @@ -18,9 +18,11 @@ package v1 import ( appsv1 "k8s.io/api/apps/v1" + autoscalingv2 "k8s.io/api/autoscaling/v2" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" ) const ( @@ -67,6 +69,10 @@ const ( ) // FeatureStoreSpec defines the desired state of FeatureStore +// +kubebuilder:validation:XValidation:rule="self.replicas <= 1 || !has(self.services) || !has(self.services.scaling) || !has(self.services.scaling.autoscaling)",message="replicas > 1 and services.scaling.autoscaling are mutually exclusive." +// +kubebuilder:validation:XValidation:rule="self.replicas <= 1 && (!has(self.services) || !has(self.services.scaling) || !has(self.services.scaling.autoscaling)) || (has(self.services) && has(self.services.onlineStore) && has(self.services.onlineStore.persistence) && has(self.services.onlineStore.persistence.store))",message="Scaling requires DB-backed persistence for the online store. Configure services.onlineStore.persistence.store when using replicas > 1 or autoscaling." +// +kubebuilder:validation:XValidation:rule="self.replicas <= 1 && (!has(self.services) || !has(self.services.scaling) || !has(self.services.scaling.autoscaling)) || (!has(self.services) || !has(self.services.offlineStore) || (has(self.services.offlineStore.persistence) && has(self.services.offlineStore.persistence.store)))",message="Scaling requires DB-backed persistence for the offline store. Configure services.offlineStore.persistence.store when using replicas > 1 or autoscaling." +// +kubebuilder:validation:XValidation:rule="self.replicas <= 1 && (!has(self.services) || !has(self.services.scaling) || !has(self.services.scaling.autoscaling)) || (has(self.services) && has(self.services.registry) && (has(self.services.registry.remote) || (has(self.services.registry.local) && has(self.services.registry.local.persistence) && (has(self.services.registry.local.persistence.store) || (has(self.services.registry.local.persistence.file) && has(self.services.registry.local.persistence.file.path) && (self.services.registry.local.persistence.file.path.startsWith('s3://') || self.services.registry.local.persistence.file.path.startsWith('gs://')))))))",message="Scaling requires DB-backed or remote registry. Configure registry.local.persistence.store or use a remote registry when using replicas > 1 or autoscaling. S3/GCS-backed registry is also allowed." type FeatureStoreSpec struct { // +kubebuilder:validation:Pattern="^[A-Za-z0-9][A-Za-z0-9_-]*$" // FeastProject is the Feast project id. This can be any alphanumeric string with underscores and hyphens, but it cannot start with an underscore or hyphen. Required. @@ -76,6 +82,11 @@ type FeatureStoreSpec struct { AuthzConfig *AuthzConfig `json:"authz,omitempty"` CronJob *FeastCronJob `json:"cronJob,omitempty"` BatchEngine *BatchEngineConfig `json:"batchEngine,omitempty"` + // Replicas is the desired number of pod replicas. Used by the scale sub-resource. + // Mutually exclusive with services.scaling.autoscaling. + // +kubebuilder:default=1 + // +kubebuilder:validation:Minimum=1 + Replicas *int32 `json:"replicas,omitempty"` } // FeastProjectDir defines how to create the feast project directory. @@ -106,7 +117,7 @@ type GitCloneOptions struct { type FeastInitOptions struct { Minimal bool `json:"minimal,omitempty"` // Template for the created project - // +kubebuilder:validation:Enum=local;gcp;aws;snowflake;spark;postgres;hbase;cassandra;hazelcast;ikv;couchbase;clickhouse + // +kubebuilder:validation:Enum=local;gcp;aws;snowflake;spark;postgres;hbase;cassandra;hazelcast;couchbase;clickhouse Template string `json:"template,omitempty"` } @@ -297,10 +308,75 @@ type FeatureStoreServices struct { UI *ServerConfigs `json:"ui,omitempty"` DeploymentStrategy *appsv1.DeploymentStrategy `json:"deploymentStrategy,omitempty"` SecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty"` + // PodAnnotations are annotations to be applied to the Deployment's PodTemplate metadata. + // This enables annotation-driven integrations like OpenTelemetry auto-instrumentation, + // Istio sidecar injection, Vault agent injection, etc. + // +optional + PodAnnotations map[string]string `json:"podAnnotations,omitempty"` // Disable the 'feast repo initialization' initContainer DisableInitContainers bool `json:"disableInitContainers,omitempty"` + // Runs feast apply on pod start to populate the registry. Defaults to true. Ignored when DisableInitContainers is true. + RunFeastApplyOnInit *bool `json:"runFeastApplyOnInit,omitempty"` // Volumes specifies the volumes to mount in the FeatureStore deployment. A corresponding `VolumeMount` should be added to whichever feast service(s) require access to said volume(s). Volumes []corev1.Volume `json:"volumes,omitempty"` + // Scaling configures horizontal scaling for the FeatureStore deployment (e.g. HPA autoscaling). + // For static replicas, use spec.replicas instead. + Scaling *ScalingConfig `json:"scaling,omitempty"` + // PodDisruptionBudgets configures a PodDisruptionBudget for the FeatureStore deployment. + // Only created when scaling is enabled (replicas > 1 or autoscaling). + // +optional + PodDisruptionBudgets *PDBConfig `json:"podDisruptionBudgets,omitempty"` + // TopologySpreadConstraints defines how pods are spread across topology domains. + // When scaling is enabled and this is not set, the operator auto-injects a soft + // zone-spread constraint (whenUnsatisfiable: ScheduleAnyway). + // Set to an empty array to disable auto-injection. + // +optional + TopologySpreadConstraints []corev1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty"` + // Affinity defines the pod scheduling constraints for the FeatureStore deployment. + // When scaling is enabled and this is not set, the operator auto-injects a soft + // pod anti-affinity rule to prefer spreading pods across nodes. + // +optional + Affinity *corev1.Affinity `json:"affinity,omitempty"` +} + +// ScalingConfig configures horizontal scaling for the FeatureStore deployment. +type ScalingConfig struct { + // Autoscaling configures a HorizontalPodAutoscaler for the FeatureStore deployment. + // Mutually exclusive with spec.replicas. + // +optional + Autoscaling *AutoscalingConfig `json:"autoscaling,omitempty"` +} + +// AutoscalingConfig defines HPA settings for the FeatureStore deployment. +type AutoscalingConfig struct { + // MinReplicas is the lower limit for the number of replicas. Defaults to 1. + // +kubebuilder:validation:Minimum=1 + // +optional + MinReplicas *int32 `json:"minReplicas,omitempty"` + // MaxReplicas is the upper limit for the number of replicas. Required. + // +kubebuilder:validation:Minimum=1 + MaxReplicas int32 `json:"maxReplicas"` + // Metrics contains the specifications for which to use to calculate the desired replica count. + // If not set, defaults to 80% CPU utilization. + // +optional + Metrics []autoscalingv2.MetricSpec `json:"metrics,omitempty"` + // Behavior configures the scaling behavior of the target. + // +optional + Behavior *autoscalingv2.HorizontalPodAutoscalerBehavior `json:"behavior,omitempty"` +} + +// PDBConfig configures a PodDisruptionBudget for the FeatureStore deployment. +// Exactly one of minAvailable or maxUnavailable must be set. +// +kubebuilder:validation:XValidation:rule="[has(self.minAvailable), has(self.maxUnavailable)].exists_one(c, c)",message="Exactly one of minAvailable or maxUnavailable must be set." +type PDBConfig struct { + // MinAvailable specifies the minimum number/percentage of pods that must remain available. + // Mutually exclusive with maxUnavailable. + // +optional + MinAvailable *intstr.IntOrString `json:"minAvailable,omitempty"` + // MaxUnavailable specifies the maximum number/percentage of pods that can be unavailable. + // Mutually exclusive with minAvailable. + // +optional + MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty"` } // OfflineStore configures the offline store service @@ -333,7 +409,7 @@ var ValidOfflineStoreFilePersistenceTypes = []string{ // OfflineStoreDBStorePersistence configures the DB store persistence for the offline store service type OfflineStoreDBStorePersistence struct { // Type of the persistence type you want to use. - // +kubebuilder:validation:Enum=snowflake.offline;bigquery;redshift;spark;postgres;trino;athena;mssql;couchbase.offline;clickhouse;ray + // +kubebuilder:validation:Enum=snowflake.offline;bigquery;redshift;spark;postgres;trino;athena;mssql;couchbase.offline;clickhouse;ray;oracle Type string `json:"type"` // Data store parameters should be placed as-is from the "feature_store.yaml" under the secret key. "registry_type" & "type" fields should be removed. SecretRef corev1.LocalObjectReference `json:"secretRef"` @@ -353,6 +429,7 @@ var ValidOfflineStoreDBStorePersistenceTypes = []string{ "couchbase.offline", "clickhouse", "ray", + "oracle", } // OnlineStore configures the online store service @@ -381,7 +458,7 @@ type OnlineStoreFilePersistence struct { // OnlineStoreDBStorePersistence configures the DB store persistence for the online store service type OnlineStoreDBStorePersistence struct { // Type of the persistence type you want to use. - // +kubebuilder:validation:Enum=snowflake.online;redis;ikv;datastore;dynamodb;bigtable;postgres;cassandra;mysql;hazelcast;singlestore;hbase;elasticsearch;qdrant;couchbase.online;milvus;hybrid + // +kubebuilder:validation:Enum=snowflake.online;redis;datastore;dynamodb;bigtable;postgres;cassandra;mysql;hazelcast;singlestore;hbase;elasticsearch;qdrant;couchbase.online;milvus;hybrid;mongodb Type string `json:"type"` // Data store parameters should be placed as-is from the "feature_store.yaml" under the secret key. "registry_type" & "type" fields should be removed. SecretRef corev1.LocalObjectReference `json:"secretRef"` @@ -392,7 +469,6 @@ type OnlineStoreDBStorePersistence struct { var ValidOnlineStoreDBStorePersistenceTypes = []string{ "snowflake.online", "redis", - "ikv", "datastore", "dynamodb", "bigtable", @@ -407,6 +483,7 @@ var ValidOnlineStoreDBStorePersistenceTypes = []string{ "couchbase.online", "milvus", "hybrid", + "mongodb", } // LocalRegistryConfig configures the registry service @@ -636,7 +713,34 @@ type KubernetesAuthz struct { // OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. // https://auth0.com/docs/authenticate/protocols/openid-connect-protocol type OidcAuthz struct { - SecretRef corev1.LocalObjectReference `json:"secretRef"` + // OIDC issuer URL. The operator appends /.well-known/openid-configuration to derive the discovery endpoint. + // +optional + // +kubebuilder:validation:Pattern=`^https://\S+$` + IssuerUrl string `json:"issuerUrl,omitempty"` + // Secret with OIDC properties (auth_discovery_url, client_id, client_secret). issuerUrl takes precedence. + // +optional + SecretRef *corev1.LocalObjectReference `json:"secretRef,omitempty"` + // Key in the Secret containing all OIDC properties as a YAML value. If unset, each key is a property. + // +optional + SecretKeyName string `json:"secretKeyName,omitempty"` + // Env var name for client pods to read an OIDC token from. Sets token_env_var in client config. + // +optional + TokenEnvVar *string `json:"tokenEnvVar,omitempty"` + // Verify SSL certificates for the OIDC provider. Defaults to true. + // +optional + VerifySSL *bool `json:"verifySSL,omitempty"` + // ConfigMap with the CA certificate for self-signed OIDC providers. Auto-detected on RHOAI/ODH. + // +optional + CACertConfigMap *OidcCACertConfigMap `json:"caCertConfigMap,omitempty"` +} + +// OidcCACertConfigMap references a ConfigMap containing a CA certificate for OIDC provider TLS. +type OidcCACertConfigMap struct { + // ConfigMap name. + Name string `json:"name"` + // Key in the ConfigMap holding the PEM certificate. Defaults to "ca-bundle.crt". + // +optional + Key string `json:"key,omitempty"` } // TlsConfigs configures server TLS for a feast service. in an openshift cluster, this is configured by default using service serving certificates. @@ -690,6 +794,20 @@ type FeatureStoreStatus struct { FeastVersion string `json:"feastVersion,omitempty"` Phase string `json:"phase,omitempty"` ServiceHostnames ServiceHostnames `json:"serviceHostnames,omitempty"` + // Replicas is the current number of ready pod replicas (used by the scale sub-resource). + Replicas int32 `json:"replicas,omitempty"` + // Selector is the label selector for pods managed by the FeatureStore deployment (used by the scale sub-resource). + Selector string `json:"selector,omitempty"` + // ScalingStatus reports the current scaling state of the FeatureStore deployment. + ScalingStatus *ScalingStatus `json:"scalingStatus,omitempty"` +} + +// ScalingStatus reports the observed scaling state. +type ScalingStatus struct { + // CurrentReplicas is the current number of pod replicas. + CurrentReplicas int32 `json:"currentReplicas,omitempty"` + // DesiredReplicas is the desired number of pod replicas. + DesiredReplicas int32 `json:"desiredReplicas,omitempty"` } // ServiceHostnames defines the service hostnames in the format of :, e.g. example.svc.cluster.local:80 @@ -706,6 +824,7 @@ type ServiceHostnames struct { // +kubebuilder:resource:shortName=feast // +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase` // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` +// +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas,selectorpath=.status.selector // +kubebuilder:storageversion // FeatureStore is the Schema for the featurestores API diff --git a/infra/feast-operator/api/v1/zz_generated.deepcopy.go b/infra/feast-operator/api/v1/zz_generated.deepcopy.go index 870f4489a4b..8d0e4848f5f 100644 --- a/infra/feast-operator/api/v1/zz_generated.deepcopy.go +++ b/infra/feast-operator/api/v1/zz_generated.deepcopy.go @@ -22,10 +22,12 @@ package v1 import ( appsv1 "k8s.io/api/apps/v1" + "k8s.io/api/autoscaling/v2" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/intstr" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -39,7 +41,7 @@ func (in *AuthzConfig) DeepCopyInto(out *AuthzConfig) { if in.OidcAuthz != nil { in, out := &in.OidcAuthz, &out.OidcAuthz *out = new(OidcAuthz) - **out = **in + (*in).DeepCopyInto(*out) } } @@ -53,6 +55,38 @@ func (in *AuthzConfig) DeepCopy() *AuthzConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AutoscalingConfig) DeepCopyInto(out *AutoscalingConfig) { + *out = *in + if in.MinReplicas != nil { + in, out := &in.MinReplicas, &out.MinReplicas + *out = new(int32) + **out = **in + } + if in.Metrics != nil { + in, out := &in.Metrics, &out.Metrics + *out = make([]v2.MetricSpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Behavior != nil { + in, out := &in.Behavior, &out.Behavior + *out = new(v2.HorizontalPodAutoscalerBehavior) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AutoscalingConfig. +func (in *AutoscalingConfig) DeepCopy() *AutoscalingConfig { + if in == nil { + return nil + } + out := new(AutoscalingConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BatchEngineConfig) DeepCopyInto(out *BatchEngineConfig) { *out = *in @@ -335,6 +369,18 @@ func (in *FeatureStoreServices) DeepCopyInto(out *FeatureStoreServices) { *out = new(corev1.PodSecurityContext) (*in).DeepCopyInto(*out) } + if in.PodAnnotations != nil { + in, out := &in.PodAnnotations, &out.PodAnnotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.RunFeastApplyOnInit != nil { + in, out := &in.RunFeastApplyOnInit, &out.RunFeastApplyOnInit + *out = new(bool) + **out = **in + } if in.Volumes != nil { in, out := &in.Volumes, &out.Volumes *out = make([]corev1.Volume, len(*in)) @@ -342,6 +388,28 @@ func (in *FeatureStoreServices) DeepCopyInto(out *FeatureStoreServices) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.Scaling != nil { + in, out := &in.Scaling, &out.Scaling + *out = new(ScalingConfig) + (*in).DeepCopyInto(*out) + } + if in.PodDisruptionBudgets != nil { + in, out := &in.PodDisruptionBudgets, &out.PodDisruptionBudgets + *out = new(PDBConfig) + (*in).DeepCopyInto(*out) + } + if in.TopologySpreadConstraints != nil { + in, out := &in.TopologySpreadConstraints, &out.TopologySpreadConstraints + *out = make([]corev1.TopologySpreadConstraint, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Affinity != nil { + in, out := &in.Affinity, &out.Affinity + *out = new(corev1.Affinity) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FeatureStoreServices. @@ -382,6 +450,11 @@ func (in *FeatureStoreSpec) DeepCopyInto(out *FeatureStoreSpec) { *out = new(BatchEngineConfig) (*in).DeepCopyInto(*out) } + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + *out = new(int32) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FeatureStoreSpec. @@ -406,6 +479,11 @@ func (in *FeatureStoreStatus) DeepCopyInto(out *FeatureStoreStatus) { } } out.ServiceHostnames = in.ServiceHostnames + if in.ScalingStatus != nil { + in, out := &in.ScalingStatus, &out.ScalingStatus + *out = new(ScalingStatus) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FeatureStoreStatus. @@ -673,7 +751,26 @@ func (in *OfflineStorePersistence) DeepCopy() *OfflineStorePersistence { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OidcAuthz) DeepCopyInto(out *OidcAuthz) { *out = *in - out.SecretRef = in.SecretRef + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + *out = new(corev1.LocalObjectReference) + **out = **in + } + if in.TokenEnvVar != nil { + in, out := &in.TokenEnvVar, &out.TokenEnvVar + *out = new(string) + **out = **in + } + if in.VerifySSL != nil { + in, out := &in.VerifySSL, &out.VerifySSL + *out = new(bool) + **out = **in + } + if in.CACertConfigMap != nil { + in, out := &in.CACertConfigMap, &out.CACertConfigMap + *out = new(OidcCACertConfigMap) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OidcAuthz. @@ -686,6 +783,21 @@ func (in *OidcAuthz) DeepCopy() *OidcAuthz { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OidcCACertConfigMap) DeepCopyInto(out *OidcCACertConfigMap) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OidcCACertConfigMap. +func (in *OidcCACertConfigMap) DeepCopy() *OidcCACertConfigMap { + if in == nil { + return nil + } + out := new(OidcCACertConfigMap) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OnlineStore) DeepCopyInto(out *OnlineStore) { *out = *in @@ -830,6 +942,31 @@ func (in *OptionalCtrConfigs) DeepCopy() *OptionalCtrConfigs { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PDBConfig) DeepCopyInto(out *PDBConfig) { + *out = *in + if in.MinAvailable != nil { + in, out := &in.MinAvailable, &out.MinAvailable + *out = new(intstr.IntOrString) + **out = **in + } + if in.MaxUnavailable != nil { + in, out := &in.MaxUnavailable, &out.MaxUnavailable + *out = new(intstr.IntOrString) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PDBConfig. +func (in *PDBConfig) DeepCopy() *PDBConfig { + if in == nil { + return nil + } + out := new(PDBConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PvcConfig) DeepCopyInto(out *PvcConfig) { *out = *in @@ -1044,6 +1181,41 @@ func (in *RemoteRegistryConfig) DeepCopy() *RemoteRegistryConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScalingConfig) DeepCopyInto(out *ScalingConfig) { + *out = *in + if in.Autoscaling != nil { + in, out := &in.Autoscaling, &out.Autoscaling + *out = new(AutoscalingConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScalingConfig. +func (in *ScalingConfig) DeepCopy() *ScalingConfig { + if in == nil { + return nil + } + out := new(ScalingConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScalingStatus) DeepCopyInto(out *ScalingStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScalingStatus. +func (in *ScalingStatus) DeepCopy() *ScalingStatus { + if in == nil { + return nil + } + out := new(ScalingStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SecretKeyNames) DeepCopyInto(out *SecretKeyNames) { *out = *in diff --git a/infra/feast-operator/api/v1alpha1/featurestore_types.go b/infra/feast-operator/api/v1alpha1/featurestore_types.go index 27b151bbb77..d9c85c93136 100644 --- a/infra/feast-operator/api/v1alpha1/featurestore_types.go +++ b/infra/feast-operator/api/v1alpha1/featurestore_types.go @@ -105,7 +105,7 @@ type GitCloneOptions struct { type FeastInitOptions struct { Minimal bool `json:"minimal,omitempty"` // Template for the created project - // +kubebuilder:validation:Enum=local;gcp;aws;snowflake;spark;postgres;hbase;cassandra;hazelcast;ikv;couchbase;clickhouse + // +kubebuilder:validation:Enum=local;gcp;aws;snowflake;spark;postgres;hbase;cassandra;hazelcast;couchbase;clickhouse Template string `json:"template,omitempty"` } @@ -289,6 +289,8 @@ type FeatureStoreServices struct { SecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty"` // Disable the 'feast repo initialization' initContainer DisableInitContainers bool `json:"disableInitContainers,omitempty"` + // Runs feast apply on pod start to populate the registry. Defaults to true. Ignored when DisableInitContainers is true. + RunFeastApplyOnInit *bool `json:"runFeastApplyOnInit,omitempty"` // Volumes specifies the volumes to mount in the FeatureStore deployment. A corresponding `VolumeMount` should be added to whichever feast service(s) require access to said volume(s). Volumes []corev1.Volume `json:"volumes,omitempty"` } @@ -371,7 +373,7 @@ type OnlineStoreFilePersistence struct { // OnlineStoreDBStorePersistence configures the DB store persistence for the online store service type OnlineStoreDBStorePersistence struct { // Type of the persistence type you want to use. - // +kubebuilder:validation:Enum=snowflake.online;redis;ikv;datastore;dynamodb;bigtable;postgres;cassandra;mysql;hazelcast;singlestore;hbase;elasticsearch;qdrant;couchbase.online;milvus;hybrid + // +kubebuilder:validation:Enum=snowflake.online;redis;datastore;dynamodb;bigtable;postgres;cassandra;mysql;hazelcast;singlestore;hbase;elasticsearch;qdrant;couchbase.online;milvus;hybrid;mongodb Type string `json:"type"` // Data store parameters should be placed as-is from the "feature_store.yaml" under the secret key. "registry_type" & "type" fields should be removed. SecretRef corev1.LocalObjectReference `json:"secretRef"` @@ -382,7 +384,6 @@ type OnlineStoreDBStorePersistence struct { var ValidOnlineStoreDBStorePersistenceTypes = []string{ "snowflake.online", "redis", - "ikv", "datastore", "dynamodb", "bigtable", @@ -397,6 +398,7 @@ var ValidOnlineStoreDBStorePersistenceTypes = []string{ "couchbase.online", "milvus", "hybrid", + "mongodb", } // LocalRegistryConfig configures the registry service diff --git a/infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go b/infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go index fa7c6f210dd..4033c368c8b 100644 --- a/infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go +++ b/infra/feast-operator/api/v1alpha1/zz_generated.deepcopy.go @@ -315,6 +315,11 @@ func (in *FeatureStoreServices) DeepCopyInto(out *FeatureStoreServices) { *out = new(v1.PodSecurityContext) (*in).DeepCopyInto(*out) } + if in.RunFeastApplyOnInit != nil { + in, out := &in.RunFeastApplyOnInit, &out.RunFeastApplyOnInit + *out = new(bool) + **out = **in + } if in.Volumes != nil { in, out := &in.Volumes, &out.Volumes *out = make([]v1.Volume, len(*in)) diff --git a/infra/feast-operator/bundle/manifests/feast-operator-controller-manager-metrics-service_v1_service.yaml b/infra/feast-operator/bundle/manifests/feast-operator-controller-manager-metrics-service_v1_service.yaml index 913517e198a..5749c2042b5 100644 --- a/infra/feast-operator/bundle/manifests/feast-operator-controller-manager-metrics-service_v1_service.yaml +++ b/infra/feast-operator/bundle/manifests/feast-operator-controller-manager-metrics-service_v1_service.yaml @@ -14,6 +14,7 @@ spec: protocol: TCP targetPort: 8443 selector: + app.kubernetes.io/name: feast-operator control-plane: controller-manager status: loadBalancer: {} diff --git a/infra/feast-operator/bundle/manifests/feast-operator-featurestore-editor-role_rbac.authorization.k8s.io_v1_clusterrole.yaml b/infra/feast-operator/bundle/manifests/feast-operator-featurestore-editor-role_rbac.authorization.k8s.io_v1_clusterrole.yaml index aff4d1f9840..b1f88ff62c3 100644 --- a/infra/feast-operator/bundle/manifests/feast-operator-featurestore-editor-role_rbac.authorization.k8s.io_v1_clusterrole.yaml +++ b/infra/feast-operator/bundle/manifests/feast-operator-featurestore-editor-role_rbac.authorization.k8s.io_v1_clusterrole.yaml @@ -5,6 +5,8 @@ metadata: labels: app.kubernetes.io/managed-by: kustomize app.kubernetes.io/name: feast-operator + rbac.authorization.k8s.io/aggregate-to-admin: "true" + rbac.authorization.k8s.io/aggregate-to-edit: "true" name: feast-operator-featurestore-editor-role rules: - apiGroups: diff --git a/infra/feast-operator/bundle/manifests/feast-operator-featurestore-viewer-role_rbac.authorization.k8s.io_v1_clusterrole.yaml b/infra/feast-operator/bundle/manifests/feast-operator-featurestore-viewer-role_rbac.authorization.k8s.io_v1_clusterrole.yaml index bcf9699fc1a..c64d255eed7 100644 --- a/infra/feast-operator/bundle/manifests/feast-operator-featurestore-viewer-role_rbac.authorization.k8s.io_v1_clusterrole.yaml +++ b/infra/feast-operator/bundle/manifests/feast-operator-featurestore-viewer-role_rbac.authorization.k8s.io_v1_clusterrole.yaml @@ -5,6 +5,7 @@ metadata: labels: app.kubernetes.io/managed-by: kustomize app.kubernetes.io/name: feast-operator + rbac.authorization.k8s.io/aggregate-to-view: "true" name: feast-operator-featurestore-viewer-role rules: - apiGroups: diff --git a/infra/feast-operator/bundle/manifests/feast-operator.clusterserviceversion.yaml b/infra/feast-operator/bundle/manifests/feast-operator.clusterserviceversion.yaml index b0ff79ec692..318c01d0ce8 100644 --- a/infra/feast-operator/bundle/manifests/feast-operator.clusterserviceversion.yaml +++ b/infra/feast-operator/bundle/manifests/feast-operator.clusterserviceversion.yaml @@ -50,10 +50,10 @@ metadata: } ] capabilities: Basic Install - createdAt: "2026-02-17T13:52:39Z" + createdAt: "2026-04-08T14:26:31Z" operators.operatorframework.io/builder: operator-sdk-v1.38.0 operators.operatorframework.io/project_layout: go.kubebuilder.io/v4 - name: feast-operator.v0.60.0 + name: feast-operator.v0.62.0 namespace: placeholder spec: apiservicedefinitions: {} @@ -95,6 +95,18 @@ spec: - tokenreviews verbs: - create + - apiGroups: + - autoscaling + resources: + - horizontalpodautoscalers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - batch resources: @@ -163,6 +175,29 @@ spec: - get - patch - update + - apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + verbs: + - create + - delete + - get + - list + - patch + - watch + - apiGroups: + - policy + resources: + - poddisruptionbudgets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - rbac.authorization.k8s.io resources: @@ -212,6 +247,7 @@ spec: replicas: 1 selector: matchLabels: + app.kubernetes.io/name: feast-operator control-plane: controller-manager strategy: {} template: @@ -219,6 +255,7 @@ spec: annotations: kubectl.kubernetes.io/default-container: manager labels: + app.kubernetes.io/name: feast-operator control-plane: controller-manager spec: containers: @@ -230,10 +267,11 @@ spec: - /manager env: - name: RELATED_IMAGE_FEATURE_SERVER - value: quay.io/feastdev/feature-server:0.60.0 + value: quay.io/feastdev/feature-server:0.62.0 - name: RELATED_IMAGE_CRON_JOB value: quay.io/openshift/origin-cli:4.17 - image: quay.io/feastdev/feast-operator:0.60.0 + - name: OIDC_ISSUER_URL + image: quay.io/feastdev/feast-operator:0.62.0 livenessProbe: httpGet: path: /healthz @@ -323,8 +361,8 @@ spec: name: Feast Community url: https://lf-aidata.atlassian.net/wiki/spaces/FEAST/ relatedImages: - - image: quay.io/feastdev/feature-server:0.60.0 + - image: quay.io/feastdev/feature-server:0.62.0 name: feature-server - image: quay.io/openshift/origin-cli:4.17 name: cron-job - version: 0.60.0 + version: 0.62.0 diff --git a/infra/feast-operator/bundle/manifests/feast.dev_featurestores.yaml b/infra/feast-operator/bundle/manifests/feast.dev_featurestores.yaml index f69971c1c4c..ce1d34b5fca 100644 --- a/infra/feast-operator/bundle/manifests/feast.dev_featurestores.yaml +++ b/infra/feast-operator/bundle/manifests/feast.dev_featurestores.yaml @@ -62,10 +62,32 @@ spec: OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. https://auth0. properties: + caCertConfigMap: + description: ConfigMap with the CA certificate for self-signed + OIDC providers. Auto-detected on RHOAI/ODH. + properties: + key: + description: Key in the ConfigMap holding the PEM certificate. + Defaults to "ca-bundle.crt". + type: string + name: + description: ConfigMap name. + type: string + required: + - name + type: object + issuerUrl: + description: OIDC issuer URL. The operator appends /.well-known/openid-configuration + to derive the discovery endpoint. + pattern: ^https://\S+$ + type: string + secretKeyName: + description: Key in the Secret containing all OIDC properties + as a YAML value. If unset, each key is a property. + type: string secretRef: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. + description: Secret with OIDC properties (auth_discovery_url, + client_id, client_secret). issuerUrl takes precedence. properties: name: default: "" @@ -76,8 +98,14 @@ spec: type: string type: object x-kubernetes-map-type: atomic - required: - - secretRef + tokenEnvVar: + description: Env var name for client pods to read an OIDC + token from. Sets token_env_var in client config. + type: string + verifySSL: + description: Verify SSL certificates for the OIDC provider. + Defaults to true. + type: boolean type: object type: object x-kubernetes-validations: @@ -703,7 +731,6 @@ spec: - hbase - cassandra - hazelcast - - ikv - couchbase - clickhouse type: string @@ -712,553 +739,806 @@ spec: x-kubernetes-validations: - message: One selection required between init or git. rule: '[has(self.git), has(self.init)].exists_one(c, c)' + replicas: + default: 1 + description: |- + Replicas is the desired number of pod replicas. Used by the scale sub-resource. + Mutually exclusive with services. + format: int32 + minimum: 1 + type: integer services: description: FeatureStoreServices defines the desired feast services. An ephemeral onlineStore feature server is deployed by default. properties: - deploymentStrategy: - description: DeploymentStrategy describes how to replace existing - pods with new ones. + affinity: + description: Affinity defines the pod scheduling constraints for + the FeatureStore deployment. properties: - rollingUpdate: - description: |- - Rolling update config params. Present only if DeploymentStrategyType = - RollingUpdate. + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. properties: - maxSurge: - anyOf: - - type: integer - - type: string + preferredDuringSchedulingIgnoredDuringExecution: description: |- - The maximum number of pods that can be scheduled above the desired number of - pods. - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - description: The maximum number of pods that can be unavailable - during the update. - x-kubernetes-int-or-string: true - type: object - type: - description: Type of deployment. Can be "Recreate" or "RollingUpdate". - Default is RollingUpdate. - type: string - type: object - disableInitContainers: - description: Disable the 'feast repo initialization' initContainer - type: boolean - offlineStore: - description: OfflineStore configures the offline store service - properties: - persistence: - description: OfflineStorePersistence configures the persistence - settings for the offline store service - properties: - file: - description: OfflineStoreFilePersistence configures the - file-based persistence for the offline store service - properties: - pvc: - description: PvcConfig defines the settings for a - persistent file store based on PVCs. - properties: - create: - description: Settings for creating a new PVC - properties: - accessModes: - description: AccessModes k8s persistent volume - access modes. Defaults to ["ReadWriteOnce"]. - items: - type: string - type: array - resources: - description: Resources describes the storage - resource requirements for a volume. + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but i + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true + key: + description: The label key that the selector + applies to. + type: string + operator: description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the minimum - amount of compute resources required. - type: object + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator type: object - storageClassName: - description: StorageClassName is the name - of an existing StorageClass to which this - persistent volume belongs. - type: string - type: object - x-kubernetes-validations: - - message: PvcCreate is immutable - rule: self == oldSelf - mountPath: - description: |- - MountPath within the container at which the volume should be mounted. - Must start by "/" and cannot contain ':'. - type: string - ref: - description: Reference to an existing field - properties: - name: - default: "" + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - mountPath - type: object - x-kubernetes-validations: - - message: One selection is required between ref and - create. - rule: '[has(self.ref), has(self.create)].exists_one(c, - c)' - - message: Mount path must start with '/' and must - not contain ':' - rule: self.mountPath.matches('^/[^:]*$') - type: - enum: - - file - - dask - - duckdb - type: string - type: object - store: - description: OfflineStoreDBStorePersistence configures - the DB store persistence for the offline store service + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: "If the affinity requirements specified by + this field are not met at\nscheduling time, the pod + will not be scheduled onto " properties: - secretKeyName: - description: By default, the selected store "type" - is used as the SecretKeyName - type: string - secretRef: - description: Data store parameters should be placed - as-is from the "feature_store.yaml" under the secret - key. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - type: - description: Type of the persistence type you want - to use. - enum: - - snowflake.offline - - bigquery - - redshift - - spark - - postgres - - trino - - athena - - mssql - - couchbase.offline - - clickhouse - - ray - type: string + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic required: - - secretRef - - type + - nodeSelectorTerms type: object + x-kubernetes-map-type: atomic type: object - x-kubernetes-validations: - - message: One selection required between file or store. - rule: '[has(self.file), has(self.store)].exists_one(c, c)' - server: - description: Creates a remote offline server container + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). properties: - env: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but i items: - description: EnvVar represents an environment variable - present in a Container. + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) properties: - name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: 'Selects a field of the pod: supports - metadata.name, metadata.namespace, `metadata.labels['''']`, - `metadata.' - properties: - apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: + labelSelector: description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits. + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: - containerName: - description: 'Container name: required for - volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults to - "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object type: object x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the - pod's namespace + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. properties: - key: - description: The key of the secret to select - from. Must be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object type: object x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in t + type: string + required: + - topologyKey type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer required: - - name + - podAffinityTerm + - weight type: object type: array - envFrom: + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: "If the affinity requirements specified by + this field are not met at\nscheduling time, the pod + will not be scheduled onto " items: - description: EnvFromSource represents the source of - a set of ConfigMaps + description: "Defines a set of pods (namely those matching + the labelSelector\nrelative to the given namespace(s)) + that this pod should " properties: - configMapRef: - description: The ConfigMap to select from + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the ConfigMap must - be defined - type: boolean + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object type: object x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the Secret must - be defined - type: boolean - type: object - x-kubernetes-map-type: atomic + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in t + type: string + required: + - topologyKey type: object type: array - image: - type: string - imagePullPolicy: - description: PullPolicy describes a policy for if/when - to pull a container image - type: string - logLevel: - description: |- - LogLevel sets the logging level for the server - Allowed values: "debug", "info", "warning", "error", "critical". - enum: - - debug - - info - - warning - - error - - critical - type: string - metrics: - description: Metrics exposes Prometheus-compatible metrics - for the Feast server when enabled. - type: boolean - nodeSelector: - additionalProperties: - type: string - type: object - resources: - description: ResourceRequirements describes the compute - resource requirements. - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: "The scheduler will prefer to schedule pods + to nodes that satisfy\nthe anti-affinity expressions + specified by this field, " + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. properties: - name: + labelSelector: description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in t type: string required: - - name + - topologyKey type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the minimum amount - of compute resources required. - type: object - type: object - tls: - description: TlsConfigs configures server TLS for a feast - service. - properties: - disable: - description: will disable TLS for the feast service. - useful in an openshift cluster, for example, where - TLS is configured by default - type: boolean - secretKeyNames: - description: SecretKeyNames defines the secret key - names for the TLS key and cert. - properties: - tlsCrt: - description: defaults to "tls.crt" - type: string - tlsKey: - description: defaults to "tls.key" - type: string - type: object - secretRef: - description: references the local k8s secret where - the TLS key and cert reside - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' - volumeMounts: - description: VolumeMounts defines the list of volumes - that should be mounted into the feast container. + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: "If the anti-affinity requirements specified + by this field are not met at\nscheduling time, the pod + will not be scheduled " items: - description: VolumeMount describes a mounting of a Volume - within a container. + description: "Defines a set of pods (namely those matching + the labelSelector\nrelative to the given namespace(s)) + that this pod should " properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: + labelSelector: description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. - type: string - subPath: + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: Expanded path within the volume from - which the container's volume should be mounted. + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in t type: string required: - - mountPath - - name + - topologyKey type: object type: array - workerConfigs: - description: WorkerConfigs defines the worker configuration - for the Feast server. - properties: - keepAliveTimeout: - description: |- - KeepAliveTimeout is the timeout for keep-alive connections in seconds. - Defaults to 30. - format: int32 - minimum: 1 - type: integer - maxRequests: - description: |- - MaxRequests is the maximum number of requests a worker will process before restarting. - This helps prevent memory leaks. - format: int32 - minimum: 0 - type: integer - maxRequestsJitter: - description: |- - MaxRequestsJitter is the maximum jitter to add to max-requests to prevent - thundering herd effect on worker restart. - format: int32 - minimum: 0 - type: integer - registryTTLSeconds: - description: RegistryTTLSeconds is the number of seconds - after which the registry is refreshed. - format: int32 - minimum: 0 - type: integer - workerConnections: - description: |- - WorkerConnections is the maximum number of simultaneous clients per worker process. - Defaults to 1000. - format: int32 - minimum: 1 - type: integer - workers: - description: Workers is the number of worker processes. - Use -1 to auto-calculate based on CPU cores (2 * - CPU + 1). - format: int32 - minimum: -1 - type: integer - type: object + x-kubernetes-list-type: atomic type: object type: object - onlineStore: - description: OnlineStore configures the online store service + deploymentStrategy: + description: DeploymentStrategy describes how to replace existing + pods with new ones. + properties: + rollingUpdate: + description: |- + Rolling update config params. Present only if DeploymentStrategyType = + RollingUpdate. + properties: + maxSurge: + anyOf: + - type: integer + - type: string + description: |- + The maximum number of pods that can be scheduled above the desired number of + pods. + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + description: The maximum number of pods that can be unavailable + during the update. + x-kubernetes-int-or-string: true + type: object + type: + description: Type of deployment. Can be "Recreate" or "RollingUpdate". + Default is RollingUpdate. + type: string + type: object + disableInitContainers: + description: Disable the 'feast repo initialization' initContainer + type: boolean + offlineStore: + description: OfflineStore configures the offline store service properties: persistence: - description: OnlineStorePersistence configures the persistence - settings for the online store service + description: OfflineStorePersistence configures the persistence + settings for the offline store service properties: file: - description: OnlineStoreFilePersistence configures the - file-based persistence for the online store service + description: OfflineStoreFilePersistence configures the + file-based persistence for the offline store service properties: - path: - type: string pvc: description: PvcConfig defines the settings for a persistent file store based on PVCs. @@ -1335,21 +1615,16 @@ spec: - message: Mount path must start with '/' and must not contain ':' rule: self.mountPath.matches('^/[^:]*$') + type: + enum: + - file + - dask + - duckdb + type: string type: object - x-kubernetes-validations: - - message: Ephemeral stores must have absolute paths. - rule: '(!has(self.pvc) && has(self.path)) ? self.path.startsWith(''/'') - : true' - - message: PVC path must be a file name only, with no - slashes. - rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') - : true' - - message: Online store does not support S3 or GS buckets. - rule: 'has(self.path) ? !(self.path.startsWith(''s3://'') - || self.path.startsWith(''gs://'')) : true' store: - description: OnlineStoreDBStorePersistence configures - the DB store persistence for the online store service + description: OfflineStoreDBStorePersistence configures + the DB store persistence for the offline store service properties: secretKeyName: description: By default, the selected store "type" @@ -1373,23 +1648,18 @@ spec: description: Type of the persistence type you want to use. enum: - - snowflake.online - - redis - - ikv - - datastore - - dynamodb - - bigtable + - snowflake.offline + - bigquery + - redshift + - spark - postgres - - cassandra - - mysql - - hazelcast - - singlestore - - hbase - - elasticsearch - - qdrant - - couchbase.online - - milvus - - hybrid + - trino + - athena + - mssql + - couchbase.offline + - clickhouse + - ray + - oracle type: string required: - secretRef @@ -1400,7 +1670,7 @@ spec: - message: One selection required between file or store. rule: '[has(self.file), has(self.store)].exists_one(c, c)' server: - description: Creates a feature server container + description: Creates a remote offline server container properties: env: items: @@ -1756,151 +2026,74 @@ spec: type: object type: object type: object - registry: - description: Registry configures the registry service. One selection - is required. Local is the default setting. + onlineStore: + description: OnlineStore configures the online store service properties: - local: - description: LocalRegistryConfig configures the registry service + persistence: + description: OnlineStorePersistence configures the persistence + settings for the online store service properties: - persistence: - description: RegistryPersistence configures the persistence - settings for the registry service + file: + description: OnlineStoreFilePersistence configures the + file-based persistence for the online store service properties: - file: - description: RegistryFilePersistence configures the - file-based persistence for the registry service + path: + type: string + pvc: + description: PvcConfig defines the settings for a + persistent file store based on PVCs. properties: - cache_mode: - description: |- - CacheMode defines the registry cache update strategy. - Allowed values are "sync" and "thread". - enum: - - none - - sync - - thread - type: string - cache_ttl_seconds: - description: CacheTTLSeconds defines the TTL (in - seconds) for the registry cache. - format: int32 - minimum: 0 - type: integer - path: - type: string - pvc: - description: PvcConfig defines the settings for - a persistent file store based on PVCs. - properties: - create: - description: Settings for creating a new PVC + create: + description: Settings for creating a new PVC + properties: + accessModes: + description: AccessModes k8s persistent volume + access modes. Defaults to ["ReadWriteOnce"]. + items: + type: string + type: array + resources: + description: Resources describes the storage + resource requirements for a volume. properties: - accessModes: - description: AccessModes k8s persistent - volume access modes. Defaults to ["ReadWriteOnce"]. - items: - type: string - type: array - resources: - description: Resources describes the storage - resource requirements for a volume. - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the - minimum amount of compute resources - required. - type: object + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum + amount of compute resources required. type: object - storageClassName: - description: StorageClassName is the name - of an existing StorageClass to which - this persistent volume belongs. - type: string type: object - x-kubernetes-validations: - - message: PvcCreate is immutable - rule: self == oldSelf - mountPath: - description: |- - MountPath within the container at which the volume should be mounted. - Must start by "/" and cannot contain ':'. + storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which this + persistent volume belongs. type: string - ref: - description: Reference to an existing field - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - mountPath type: object x-kubernetes-validations: - - message: One selection is required between ref - and create. - rule: '[has(self.ref), has(self.create)].exists_one(c, - c)' - - message: Mount path must start with '/' and - must not contain ':' - rule: self.mountPath.matches('^/[^:]*$') - s3_additional_kwargs: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-validations: - - message: Registry files must use absolute paths - or be S3 ('s3://') or GS ('gs://') object store - URIs. - rule: '(!has(self.pvc) && has(self.path)) ? (self.path.startsWith(''/'') - || self.path.startsWith(''s3://'') || self.path.startsWith(''gs://'')) - : true' - - message: PVC path must be a file name only, with - no slashes. - rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') - : true' - - message: PVC persistence does not support S3 or - GS object store URIs. - rule: '(has(self.pvc) && has(self.path)) ? !(self.path.startsWith(''s3://'') - || self.path.startsWith(''gs://'')) : true' - - message: Additional S3 settings are available only - for S3 object store URIs. - rule: '(has(self.s3_additional_kwargs) && has(self.path)) - ? self.path.startsWith(''s3://'') : true' - store: - description: RegistryDBStorePersistence configures - the DB store persistence for the registry service - properties: - secretKeyName: - description: By default, the selected store "type" - is used as the SecretKeyName + - message: PvcCreate is immutable + rule: self == oldSelf + mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. type: string - secretRef: - description: Data store parameters should be placed - as-is from the "feature_store.yaml" under the - secret key. + ref: + description: Reference to an existing field properties: name: default: "" @@ -1911,146 +2104,109 @@ spec: type: string type: object x-kubernetes-map-type: atomic - type: - description: Type of the persistence type you - want to use. - enum: - - sql - - snowflake.registry - type: string required: - - secretRef - - type + - mountPath type: object + x-kubernetes-validations: + - message: One selection is required between ref and + create. + rule: '[has(self.ref), has(self.create)].exists_one(c, + c)' + - message: Mount path must start with '/' and must + not contain ':' + rule: self.mountPath.matches('^/[^:]*$') type: object x-kubernetes-validations: - - message: One selection required between file or store. - rule: '[has(self.file), has(self.store)].exists_one(c, - c)' - server: - description: Creates a registry server container + - message: Ephemeral stores must have absolute paths. + rule: '(!has(self.pvc) && has(self.path)) ? self.path.startsWith(''/'') + : true' + - message: PVC path must be a file name only, with no + slashes. + rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') + : true' + - message: Online store does not support S3 or GS buckets. + rule: 'has(self.path) ? !(self.path.startsWith(''s3://'') + || self.path.startsWith(''gs://'')) : true' + store: + description: OnlineStoreDBStorePersistence configures + the DB store persistence for the online store service properties: - env: - items: - description: EnvVar represents an environment variable - present in a Container. + secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName + type: string + secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the secret + key. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + type: + description: Type of the persistence type you want + to use. + enum: + - snowflake.online + - redis + - datastore + - dynamodb + - bigtable + - postgres + - cassandra + - mysql + - hazelcast + - singlestore + - hbase + - elasticsearch + - qdrant + - couchbase.online + - milvus + - hybrid + - mongodb + type: string + required: + - secretRef + - type + type: object + type: object + x-kubernetes-validations: + - message: One selection required between file or store. + rule: '[has(self.file), has(self.store)].exists_one(c, c)' + server: + description: Creates a feature server container + properties: + env: + items: + description: EnvVar represents an environment variable + present in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: 'Selects a field of the pod: - supports metadata.name, metadata.namespace, - `metadata.labels['''']`, `metadata.' - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, - defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults - to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - items: - description: EnvFromSource represents the source - of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from + configMapKeyRef: + description: Selects a key of a ConfigMap. properties: + key: + description: The key to select. + type: string name: default: "" description: |- @@ -2060,17 +2216,62 @@ spec: type: string optional: description: Specify whether the ConfigMap - must be defined + or its key must be defined type: boolean + required: + - key type: object x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from + fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. + properties: + containerName: + description: 'Container name: required for + volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the + pod's namespace properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string name: default: "" description: |- @@ -2080,382 +2281,1567 @@ spec: type: string optional: description: Specify whether the Secret - must be defined + or its key must be defined type: boolean + required: + - key type: object x-kubernetes-map-type: atomic type: object - type: array - grpc: - description: Enable gRPC registry server. Defaults - to true if unset. - type: boolean - image: - type: string - imagePullPolicy: - description: PullPolicy describes a policy for if/when - to pull a container image - type: string - logLevel: - description: |- - LogLevel sets the logging level for the server - Allowed values: "debug", "info", "warning", "error", "critical". - enum: - - debug - - info - - warning - - error - - critical - type: string - metrics: - description: Metrics exposes Prometheus-compatible - metrics for the Feast server when enabled. - type: boolean - nodeSelector: - additionalProperties: + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source of + a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend to + each key in the ConfigMap. Must be a C_IDENTIFIER. type: string - type: object - resources: - description: ResourceRequirements describes the compute - resource requirements. - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the minimum amount - of compute resources required. - type: object - type: object - restAPI: - description: Enable REST API registry server. - type: boolean - tls: - description: TlsConfigs configures server TLS for - a feast service. - properties: - disable: - description: will disable TLS for the feast service. - useful in an openshift cluster, for example, - where TLS is configured by default - type: boolean - secretKeyNames: - description: SecretKeyNames defines the secret - key names for the TLS key and cert. - properties: - tlsCrt: - description: defaults to "tls.crt" - type: string - tlsKey: - description: defaults to "tls.key" - type: string - type: object - secretRef: - description: references the local k8s secret where - the TLS key and cert reside - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' - volumeMounts: - description: VolumeMounts defines the list of volumes - that should be mounted into the feast container. - items: - description: VolumeMount describes a mounting of - a Volume within a container. + secretRef: + description: The Secret to select from properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - type: string name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: + default: "" description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string - subPath: + optional: + description: Specify whether the Secret must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image + type: string + logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". + enum: + - debug + - info + - warning + - error + - critical + type: string + metrics: + description: Metrics exposes Prometheus-compatible metrics + for the Feast server when enabled. + type: boolean + nodeSelector: + additionalProperties: + type: string + type: object + resources: + description: ResourceRequirements describes the compute + resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: Expanded path within the volume - from which the container's volume should be - mounted. + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string required: - - mountPath - name type: object type: array - workerConfigs: - description: WorkerConfigs defines the worker configuration - for the Feast server. + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount + of compute resources required. + type: object + type: object + tls: + description: TlsConfigs configures server TLS for a feast + service. + properties: + disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, where + TLS is configured by default + type: boolean + secretKeyNames: + description: SecretKeyNames defines the secret key + names for the TLS key and cert. properties: - keepAliveTimeout: - description: |- - KeepAliveTimeout is the timeout for keep-alive connections in seconds. - Defaults to 30. - format: int32 - minimum: 1 - type: integer - maxRequests: - description: |- - MaxRequests is the maximum number of requests a worker will process before restarting. - This helps prevent memory leaks. - format: int32 - minimum: 0 - type: integer - maxRequestsJitter: - description: |- - MaxRequestsJitter is the maximum jitter to add to max-requests to prevent - thundering herd effect on worker restart. - format: int32 - minimum: 0 - type: integer - registryTTLSeconds: - description: RegistryTTLSeconds is the number - of seconds after which the registry is refreshed. - format: int32 - minimum: 0 - type: integer - workerConnections: + tlsCrt: + description: defaults to "tls.crt" + type: string + tlsKey: + description: defaults to "tls.key" + type: string + type: object + secretRef: + description: references the local k8s secret where + the TLS key and cert reside + properties: + name: + default: "" description: |- - WorkerConnections is the maximum number of simultaneous clients per worker process. - Defaults to 1000. - format: int32 - minimum: 1 - type: integer - workers: - description: Workers is the number of worker processes. - Use -1 to auto-calculate based on CPU cores - (2 * CPU + 1). - format: int32 - minimum: -1 - type: integer + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string type: object + x-kubernetes-map-type: atomic type: object x-kubernetes-validations: - - message: At least one of restAPI or grpc must be true - rule: self.restAPI == true || self.grpc == true || !has(self.grpc) - type: object - remote: - description: RemoteRegistryConfig points to a remote feast - registry server. - properties: - feastRef: - description: Reference to an existing `FeatureStore` CR - in the same k8s cluster. - properties: - name: - description: Name of the FeatureStore - type: string - namespace: - description: Namespace of the FeatureStore - type: string - required: - - name - type: object - hostname: - description: Host address of the remote registry service - - :, e.g. `registry..svc.cluster.local:80` - type: string - tls: - description: TlsRemoteRegistryConfigs configures client - TLS for a remote feast registry. + - message: '`secretRef` required if `disable` is false.' + rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) + : true' + volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. + type: string + required: + - mountPath + - name + type: object + type: array + workerConfigs: + description: WorkerConfigs defines the worker configuration + for the Feast server. properties: - certName: - description: defines the configmap key name for the - client TLS cert. - type: string - configMapRef: - description: references the local k8s configmap where - the TLS cert resides - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - certName - - configMapRef + keepAliveTimeout: + description: |- + KeepAliveTimeout is the timeout for keep-alive connections in seconds. + Defaults to 30. + format: int32 + minimum: 1 + type: integer + maxRequests: + description: |- + MaxRequests is the maximum number of requests a worker will process before restarting. + This helps prevent memory leaks. + format: int32 + minimum: 0 + type: integer + maxRequestsJitter: + description: |- + MaxRequestsJitter is the maximum jitter to add to max-requests to prevent + thundering herd effect on worker restart. + format: int32 + minimum: 0 + type: integer + registryTTLSeconds: + description: RegistryTTLSeconds is the number of seconds + after which the registry is refreshed. + format: int32 + minimum: 0 + type: integer + workerConnections: + description: |- + WorkerConnections is the maximum number of simultaneous clients per worker process. + Defaults to 1000. + format: int32 + minimum: 1 + type: integer + workers: + description: Workers is the number of worker processes. + Use -1 to auto-calculate based on CPU cores (2 * + CPU + 1). + format: int32 + minimum: -1 + type: integer type: object type: object - x-kubernetes-validations: - - message: One selection required. - rule: '[has(self.hostname), has(self.feastRef)].exists_one(c, - c)' + type: object + podAnnotations: + additionalProperties: + type: string + description: PodAnnotations are annotations to be applied to the + Deployment's PodTemplate metadata. + type: object + podDisruptionBudgets: + description: PodDisruptionBudgets configures a PodDisruptionBudget + for the FeatureStore deployment. + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: MaxUnavailable specifies the maximum number/percentage + of pods that can be unavailable. + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + description: MinAvailable specifies the minimum number/percentage + of pods that must remain available. + x-kubernetes-int-or-string: true type: object x-kubernetes-validations: - - message: One selection required. - rule: '[has(self.local), has(self.remote)].exists_one(c, c)' - securityContext: - description: PodSecurityContext holds pod-level security attributes - and common container settings. + - message: Exactly one of minAvailable or maxUnavailable must + be set. + rule: '[has(self.minAvailable), has(self.maxUnavailable)].exists_one(c, + c)' + registry: + description: Registry configures the registry service. One selection + is required. Local is the default setting. properties: - appArmorProfile: - description: appArmorProfile is the AppArmor options to use - by the containers in this pod. - properties: - localhostProfile: - description: localhostProfile indicates a profile loaded - on the node that should be used. - type: string - type: - description: type indicates which kind of AppArmor profile - will be applied. - type: string - required: - - type - type: object - fsGroup: - description: A special supplemental group that applies to - all containers in a pod. - format: int64 - type: integer - fsGroupChangePolicy: - description: |- - fsGroupChangePolicy defines behavior of changing ownership and permission of the volume - before being exposed inside Pod. - type: string - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - format: int64 - type: integer - runAsNonRoot: - description: Indicates that the container must run as a non-root - user. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - format: int64 - type: integer - seLinuxOptions: - description: The SELinux context to be applied to all containers. - properties: - level: - description: Level is SELinux level label that applies - to the container. - type: string - role: - description: Role is a SELinux role label that applies - to the container. - type: string - type: - description: Type is a SELinux type label that applies - to the container. - type: string - user: - description: User is a SELinux user label that applies - to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by the containers in this pod. - Note that this field cannot be set when spec.os. + local: + description: LocalRegistryConfig configures the registry service properties: - localhostProfile: - description: localhostProfile indicates a profile defined - in a file on the node should be used. - type: string - type: - description: type indicates which kind of seccomp profile - will be applied. - type: string - required: - - type - type: object - supplementalGroups: - description: |- - A list of groups applied to the first process run in each container, in addition - to the container's primary GID, the fsG - items: - format: int64 - type: integer - type: array - x-kubernetes-list-type: atomic - sysctls: - description: Sysctls hold a list of namespaced sysctls used - for the pod. - items: - description: Sysctl defines a kernel parameter to be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: + persistence: + description: RegistryPersistence configures the persistence + settings for the registry service + properties: + file: + description: RegistryFilePersistence configures the + file-based persistence for the registry service + properties: + cache_mode: + description: |- + CacheMode defines the registry cache update strategy. + Allowed values are "sync" and "thread". + enum: + - none + - sync + - thread + type: string + cache_ttl_seconds: + description: CacheTTLSeconds defines the TTL (in + seconds) for the registry cache. + format: int32 + minimum: 0 + type: integer + path: + type: string + pvc: + description: PvcConfig defines the settings for + a persistent file store based on PVCs. + properties: + create: + description: Settings for creating a new PVC + properties: + accessModes: + description: AccessModes k8s persistent + volume access modes. Defaults to ["ReadWriteOnce"]. + items: + type: string + type: array + resources: + description: Resources describes the storage + resource requirements for a volume. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the + minimum amount of compute resources + required. + type: object + type: object + storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which + this persistent volume belongs. + type: string + type: object + x-kubernetes-validations: + - message: PvcCreate is immutable + rule: self == oldSelf + mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. + type: string + ref: + description: Reference to an existing field + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + required: + - mountPath + type: object + x-kubernetes-validations: + - message: One selection is required between ref + and create. + rule: '[has(self.ref), has(self.create)].exists_one(c, + c)' + - message: Mount path must start with '/' and + must not contain ':' + rule: self.mountPath.matches('^/[^:]*$') + s3_additional_kwargs: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-validations: + - message: Registry files must use absolute paths + or be S3 ('s3://') or GS ('gs://') object store + URIs. + rule: '(!has(self.pvc) && has(self.path)) ? (self.path.startsWith(''/'') + || self.path.startsWith(''s3://'') || self.path.startsWith(''gs://'')) + : true' + - message: PVC path must be a file name only, with + no slashes. + rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') + : true' + - message: PVC persistence does not support S3 or + GS object store URIs. + rule: '(has(self.pvc) && has(self.path)) ? !(self.path.startsWith(''s3://'') + || self.path.startsWith(''gs://'')) : true' + - message: Additional S3 settings are available only + for S3 object store URIs. + rule: '(has(self.s3_additional_kwargs) && has(self.path)) + ? self.path.startsWith(''s3://'') : true' + store: + description: RegistryDBStorePersistence configures + the DB store persistence for the registry service + properties: + secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName + type: string + secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the + secret key. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + type: + description: Type of the persistence type you + want to use. + enum: + - sql + - snowflake.registry + type: string + required: + - secretRef + - type + type: object + type: object + x-kubernetes-validations: + - message: One selection required between file or store. + rule: '[has(self.file), has(self.store)].exists_one(c, + c)' + server: + description: Creates a registry server container + properties: + env: + items: + description: EnvVar represents an environment variable + present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: + supports metadata.name, metadata.namespace, + `metadata.labels['''']`, `metadata.' + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, + defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults + to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in + the pod's namespace + properties: + key: + description: The key of the secret to + select from. Must be a valid secret + key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source + of a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + grpc: + description: Enable gRPC registry server. Defaults + to true if unset. + type: boolean + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image + type: string + logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". + enum: + - debug + - info + - warning + - error + - critical + type: string + metrics: + description: Metrics exposes Prometheus-compatible + metrics for the Feast server when enabled. + type: boolean + nodeSelector: + additionalProperties: + type: string + type: object + resources: + description: ResourceRequirements describes the compute + resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount + of compute resources required. + type: object + type: object + restAPI: + description: Enable REST API registry server. + type: boolean + tls: + description: TlsConfigs configures server TLS for + a feast service. + properties: + disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, + where TLS is configured by default + type: boolean + secretKeyNames: + description: SecretKeyNames defines the secret + key names for the TLS key and cert. + properties: + tlsCrt: + description: defaults to "tls.crt" + type: string + tlsKey: + description: defaults to "tls.key" + type: string + type: object + secretRef: + description: references the local k8s secret where + the TLS key and cert reside + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: '`secretRef` required if `disable` is false.' + rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) + : true' + volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. + items: + description: VolumeMount describes a mounting of + a Volume within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume + from which the container's volume should be + mounted. + type: string + required: + - mountPath + - name + type: object + type: array + workerConfigs: + description: WorkerConfigs defines the worker configuration + for the Feast server. + properties: + keepAliveTimeout: + description: |- + KeepAliveTimeout is the timeout for keep-alive connections in seconds. + Defaults to 30. + format: int32 + minimum: 1 + type: integer + maxRequests: + description: |- + MaxRequests is the maximum number of requests a worker will process before restarting. + This helps prevent memory leaks. + format: int32 + minimum: 0 + type: integer + maxRequestsJitter: + description: |- + MaxRequestsJitter is the maximum jitter to add to max-requests to prevent + thundering herd effect on worker restart. + format: int32 + minimum: 0 + type: integer + registryTTLSeconds: + description: RegistryTTLSeconds is the number + of seconds after which the registry is refreshed. + format: int32 + minimum: 0 + type: integer + workerConnections: + description: |- + WorkerConnections is the maximum number of simultaneous clients per worker process. + Defaults to 1000. + format: int32 + minimum: 1 + type: integer + workers: + description: Workers is the number of worker processes. + Use -1 to auto-calculate based on CPU cores + (2 * CPU + 1). + format: int32 + minimum: -1 + type: integer + type: object + type: object + x-kubernetes-validations: + - message: At least one of restAPI or grpc must be true + rule: self.restAPI == true || self.grpc == true || !has(self.grpc) + type: object + remote: + description: RemoteRegistryConfig points to a remote feast + registry server. + properties: + feastRef: + description: Reference to an existing `FeatureStore` CR + in the same k8s cluster. + properties: + name: + description: Name of the FeatureStore + type: string + namespace: + description: Namespace of the FeatureStore + type: string + required: + - name + type: object + hostname: + description: Host address of the remote registry service + - :, e.g. `registry..svc.cluster.local:80` + type: string + tls: + description: TlsRemoteRegistryConfigs configures client + TLS for a remote feast registry. + properties: + certName: + description: defines the configmap key name for the + client TLS cert. + type: string + configMapRef: + description: references the local k8s configmap where + the TLS cert resides + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + required: + - certName + - configMapRef + type: object + type: object + x-kubernetes-validations: + - message: One selection required. + rule: '[has(self.hostname), has(self.feastRef)].exists_one(c, + c)' + type: object + x-kubernetes-validations: + - message: One selection required. + rule: '[has(self.local), has(self.remote)].exists_one(c, c)' + runFeastApplyOnInit: + description: Runs feast apply on pod start to populate the registry. + Defaults to true. Ignored when DisableInitContainers is true. + type: boolean + scaling: + description: Scaling configures horizontal scaling for the FeatureStore + deployment (e.g. HPA autoscaling). + properties: + autoscaling: + description: |- + Autoscaling configures a HorizontalPodAutoscaler for the FeatureStore deployment. + Mutually exclusive with spec.replicas. + properties: + behavior: + description: Behavior configures the scaling behavior + of the target. + properties: + scaleDown: + description: scaleDown is scaling policy for scaling + Down. + properties: + policies: + description: policies is a list of potential scaling + polices which can be used during scaling. + items: + description: HPAScalingPolicy is a single policy + which must hold true for a specified past + interval. + properties: + periodSeconds: + description: periodSeconds specifies the + window of time for which the policy should + hold true. + format: int32 + type: integer + type: + description: type is used to specify the + scaling policy. + type: string + value: + description: |- + value contains the amount of change which is permitted by the policy. + It must be greater than zero + format: int32 + type: integer + required: + - periodSeconds + - type + - value + type: object + type: array + x-kubernetes-list-type: atomic + selectPolicy: + description: |- + selectPolicy is used to specify which policy should be used. + If not set, the default value Max is used. + type: string + stabilizationWindowSeconds: + description: |- + stabilizationWindowSeconds is the number of seconds for which past recommendations should be + considered while scaling up + format: int32 + type: integer + type: object + scaleUp: + description: scaleUp is scaling policy for scaling + Up. + properties: + policies: + description: policies is a list of potential scaling + polices which can be used during scaling. + items: + description: HPAScalingPolicy is a single policy + which must hold true for a specified past + interval. + properties: + periodSeconds: + description: periodSeconds specifies the + window of time for which the policy should + hold true. + format: int32 + type: integer + type: + description: type is used to specify the + scaling policy. + type: string + value: + description: |- + value contains the amount of change which is permitted by the policy. + It must be greater than zero + format: int32 + type: integer + required: + - periodSeconds + - type + - value + type: object + type: array + x-kubernetes-list-type: atomic + selectPolicy: + description: |- + selectPolicy is used to specify which policy should be used. + If not set, the default value Max is used. + type: string + stabilizationWindowSeconds: + description: |- + stabilizationWindowSeconds is the number of seconds for which past recommendations should be + considered while scaling up + format: int32 + type: integer + type: object + type: object + maxReplicas: + description: MaxReplicas is the upper limit for the number + of replicas. Required. + format: int32 + minimum: 1 + type: integer + metrics: + description: Metrics contains the specifications for which + to use to calculate the desired replica count. + items: + description: |- + MetricSpec specifies how to scale based on a single metric + (only `type` and one other matching field should be set at on + properties: + containerResource: + description: |- + containerResource refers to a resource metric (such as those specified in + requests and limits) known to Kubernetes descr + properties: + container: + description: container is the name of the container + in the pods of the scaling target + type: string + name: + description: name is the name of the resource + in question. + type: string + target: + description: target specifies the target value + for the given metric + properties: + averageUtilization: + description: "averageUtilization is the + target value of the average of the\nresource + metric across all relevant pods, represented + as a " + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether the + metric type is Utilization, Value, or + AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value of + the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - container + - name + - target + type: object + external: + description: |- + external refers to a global metric that is not associated + with any Kubernetes object. + properties: + metric: + description: metric identifies the target metric + by name and selector + properties: + name: + description: name is the name of the given + metric + type: string + selector: + description: "selector is the string-encoded + form of a standard kubernetes label selector + for the given metric\nWhen set, it is + passed " + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - name + type: object + target: + description: target specifies the target value + for the given metric + properties: + averageUtilization: + description: "averageUtilization is the + target value of the average of the\nresource + metric across all relevant pods, represented + as a " + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether the + metric type is Utilization, Value, or + AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value of + the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - metric + - target + type: object + object: + description: |- + object refers to a metric describing a single kubernetes object + (for example, hits-per-second on an Ingress object). + properties: + describedObject: + description: describedObject specifies the descriptions + of a object,such as kind,name apiVersion + properties: + apiVersion: + description: apiVersion is the API version + of the referent + type: string + kind: + description: 'kind is the kind of the referent; + More info: https://git.k8s.' + type: string + name: + description: 'name is the name of the referent; + More info: https://kubernetes.' + type: string + required: + - kind + - name + type: object + metric: + description: metric identifies the target metric + by name and selector + properties: + name: + description: name is the name of the given + metric + type: string + selector: + description: "selector is the string-encoded + form of a standard kubernetes label selector + for the given metric\nWhen set, it is + passed " + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - name + type: object + target: + description: target specifies the target value + for the given metric + properties: + averageUtilization: + description: "averageUtilization is the + target value of the average of the\nresource + metric across all relevant pods, represented + as a " + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether the + metric type is Utilization, Value, or + AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value of + the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - describedObject + - metric + - target + type: object + pods: + description: |- + pods refers to a metric describing each pod in the current scale target + (for example, transactions-processed-per-second) + properties: + metric: + description: metric identifies the target metric + by name and selector + properties: + name: + description: name is the name of the given + metric + type: string + selector: + description: "selector is the string-encoded + form of a standard kubernetes label selector + for the given metric\nWhen set, it is + passed " + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - name + type: object + target: + description: target specifies the target value + for the given metric + properties: + averageUtilization: + description: "averageUtilization is the + target value of the average of the\nresource + metric across all relevant pods, represented + as a " + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether the + metric type is Utilization, Value, or + AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value of + the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - metric + - target + type: object + resource: + description: |- + resource refers to a resource metric (such as those specified in + requests and limits) known to Kubernetes describing eac + properties: + name: + description: name is the name of the resource + in question. + type: string + target: + description: target specifies the target value + for the given metric + properties: + averageUtilization: + description: "averageUtilization is the + target value of the average of the\nresource + metric across all relevant pods, represented + as a " + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether the + metric type is Utilization, Value, or + AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value of + the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - name + - target + type: object + type: + description: type is the type of metric source. + type: string + required: + - type + type: object + type: array + minReplicas: + description: MinReplicas is the lower limit for the number + of replicas. Defaults to 1. + format: int32 + minimum: 1 + type: integer + required: + - maxReplicas + type: object + type: object + securityContext: + description: PodSecurityContext holds pod-level security attributes + and common container settings. + properties: + appArmorProfile: + description: appArmorProfile is the AppArmor options to use + by the containers in this pod. + properties: + localhostProfile: + description: localhostProfile indicates a profile loaded + on the node that should be used. + type: string + type: + description: type indicates which kind of AppArmor profile + will be applied. + type: string + required: + - type + type: object + fsGroup: + description: A special supplemental group that applies to + all containers in a pod. + format: int64 + type: integer + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all containers. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. + type: string + type: + description: type indicates which kind of seccomp profile + will be applied. + type: string + required: + - type + type: object + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in addition + to the container's primary GID, the fsG + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + sysctls: + description: Sysctls hold a list of namespaced sysctls used + for the pod. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: - name - value type: object @@ -2484,6 +3870,96 @@ spec: type: string type: object type: object + topologySpreadConstraints: + description: TopologySpreadConstraints defines how pods are spread + across topology domains. + items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. + properties: + labelSelector: + description: LabelSelector is used to find matching pods. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. + format: int32 + type: integer + minDomains: + description: MinDomains indicates a minimum number of eligible + domains. + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread skew + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. + type: string + topologyKey: + description: TopologyKey is the key of node labels. + type: string + whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array ui: description: Creates a UI server container properties: @@ -4258,6 +5734,35 @@ spec: required: - feastProject type: object + x-kubernetes-validations: + - message: replicas > 1 and services.scaling.autoscaling are mutually + exclusive. + rule: self.replicas <= 1 || !has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling) + - message: Scaling requires DB-backed persistence for the online store. + Configure services.onlineStore.persistence.store when using replicas + > 1 or autoscaling. + rule: self.replicas <= 1 && (!has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling)) || (has(self.services) + && has(self.services.onlineStore) && has(self.services.onlineStore.persistence) + && has(self.services.onlineStore.persistence.store)) + - message: Scaling requires DB-backed persistence for the offline store. + Configure services.offlineStore.persistence.store when using replicas + > 1 or autoscaling. + rule: self.replicas <= 1 && (!has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling)) || (!has(self.services) + || !has(self.services.offlineStore) || (has(self.services.offlineStore.persistence) + && has(self.services.offlineStore.persistence.store))) + - message: Scaling requires DB-backed or remote registry. Configure registry.local.persistence.store + or use a remote registry when using replicas > 1 or autoscaling. S3/GCS-backed + registry is also allowed. + rule: self.replicas <= 1 && (!has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling)) || (has(self.services) + && has(self.services.registry) && (has(self.services.registry.remote) + || (has(self.services.registry.local) && has(self.services.registry.local.persistence) + && (has(self.services.registry.local.persistence.store) || (has(self.services.registry.local.persistence.file) + && has(self.services.registry.local.persistence.file.path) && (self.services.registry.local.persistence.file.path.startsWith('s3://') + || self.services.registry.local.persistence.file.path.startsWith('gs://'))))))) status: description: FeatureStoreStatus defines the observed state of FeatureStore properties: @@ -4280,79 +5785,502 @@ spec: items: type: string type: array - type: object - oidc: - description: |- - OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. - https://auth0. - properties: - secretRef: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. + type: object + oidc: + description: |- + OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. + https://auth0. + properties: + caCertConfigMap: + description: ConfigMap with the CA certificate for self-signed + OIDC providers. Auto-detected on RHOAI/ODH. + properties: + key: + description: Key in the ConfigMap holding the PEM + certificate. Defaults to "ca-bundle.crt". + type: string + name: + description: ConfigMap name. + type: string + required: + - name + type: object + issuerUrl: + description: OIDC issuer URL. The operator appends /.well-known/openid-configuration + to derive the discovery endpoint. + pattern: ^https://\S+$ + type: string + secretKeyName: + description: Key in the Secret containing all OIDC properties + as a YAML value. If unset, each key is a property. + type: string + secretRef: + description: Secret with OIDC properties (auth_discovery_url, + client_id, client_secret). issuerUrl takes precedence. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + tokenEnvVar: + description: Env var name for client pods to read an OIDC + token from. Sets token_env_var in client config. + type: string + verifySSL: + description: Verify SSL certificates for the OIDC provider. + Defaults to true. + type: boolean + type: object + type: object + x-kubernetes-validations: + - message: One selection required between kubernetes or oidc. + rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, + c)' + batchEngine: + description: BatchEngineConfig defines the batch compute engine + configuration. + properties: + configMapKey: + description: Key name in the ConfigMap. Defaults to "config" + if not specified. + type: string + configMapRef: + description: Reference to a ConfigMap containing the batch + engine configuration. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + type: object + cronJob: + description: FeastCronJob defines a CronJob to execute against + a Feature Store deployment. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to be added to the CronJob metadata. + type: object + concurrencyPolicy: + description: Specifies how to treat concurrent executions + of a Job. + type: string + containerConfigs: + description: CronJobContainerConfigs k8s container settings + for the CronJob + properties: + commands: + description: Array of commands to be executed (in order) + against a Feature Store deployment. + items: + type: string + type: array + env: + items: + description: EnvVar represents an environment variable + present in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. + properties: + containerName: + description: 'Container name: required for + volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the + pod's namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source of + a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend to + each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image + type: string + nodeSelector: + additionalProperties: + type: string + type: object + resources: + description: ResourceRequirements describes the compute + resource requirements. properties: - name: - default: "" + claims: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount + of compute resources required. + type: object type: object - x-kubernetes-map-type: atomic - required: - - secretRef type: object - type: object - x-kubernetes-validations: - - message: One selection required between kubernetes or oidc. - rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, - c)' - batchEngine: - description: BatchEngineConfig defines the batch compute engine - configuration. - properties: - configMapKey: - description: Key name in the ConfigMap. Defaults to "config" - if not specified. - type: string - configMapRef: - description: Reference to a ConfigMap containing the batch - engine configuration. + failedJobsHistoryLimit: + description: The number of failed finished jobs to retain. + Value must be non-negative integer. + format: int32 + type: integer + jobSpec: + description: Specification of the desired behavior of a job. properties: - name: - default: "" + activeDeadlineSeconds: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + Specifies the duration in seconds relative to the startTime that the job + may be continuously active before the system tr + format: int64 + type: integer + backoffLimit: + description: Specifies the number of retries before marking + this job failed. + format: int32 + type: integer + backoffLimitPerIndex: + description: |- + Specifies the limit for the number of retries within an + index before marking this index as failed. + format: int32 + type: integer + completionMode: + description: |- + completionMode specifies how Pod completions are tracked. It can be + `NonIndexed` (default) or `Indexed`. + type: string + completions: + description: |- + Specifies the desired number of successfully finished pods the + job should be run with. + format: int32 + type: integer + maxFailedIndexes: + description: |- + Specifies the maximal number of failed indexes before marking the Job as + failed, when backoffLimitPerIndex is set. + format: int32 + type: integer + parallelism: + description: |- + Specifies the maximum desired number of pods the job should + run at any given time. + format: int32 + type: integer + podFailurePolicy: + description: Specifies the policy of handling failed pods. + properties: + rules: + description: A list of pod failure policy rules. The + rules are evaluated in order. + items: + description: PodFailurePolicyRule describes how + a pod failure is handled when the requirements + are met. + properties: + action: + description: Specifies the action taken on a + pod failure when the requirements are satisfied. + type: string + onExitCodes: + description: Represents the requirement on the + container exit codes. + properties: + containerName: + description: |- + Restricts the check for exit codes to the container with the + specified name. + type: string + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. + type: string + values: + description: Specifies the set of values. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + - values + type: object + onPodConditions: + description: |- + Represents the requirement on the pod conditions. The requirement is represented + as a list of pod condition patterns. + items: + description: |- + PodFailurePolicyOnPodConditionsPattern describes a pattern for matching + an actual pod condition type. + properties: + status: + description: Specifies the required Pod + condition status. + type: string + type: + description: Specifies the required Pod + condition type. + type: string + required: + - status + - type + type: object + type: array + x-kubernetes-list-type: atomic + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + required: + - rules + type: object + podReplacementPolicy: + description: podReplacementPolicy specifies when to create + replacement Pods. type: string + podTemplateAnnotations: + additionalProperties: + type: string + description: |- + PodTemplateAnnotations are annotations to be applied to the CronJob's PodTemplate + metadata. + type: object + suspend: + description: suspend specifies whether the Job controller + should create Pods or not. + type: boolean + ttlSecondsAfterFinished: + description: |- + ttlSecondsAfterFinished limits the lifetime of a Job that has finished + execution (either Complete or Failed). + format: int32 + type: integer type: object - x-kubernetes-map-type: atomic + schedule: + description: The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. + type: string + startingDeadlineSeconds: + description: |- + Optional deadline in seconds for starting the job if it misses scheduled + time for any reason. + format: int64 + type: integer + successfulJobsHistoryLimit: + description: The number of successful finished jobs to retain. + Value must be non-negative integer. + format: int32 + type: integer + suspend: + description: |- + This flag tells the controller to suspend subsequent executions, it does + not apply to already started executions. + type: boolean + timeZone: + description: The time zone name for the given schedule, see + https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. + type: string type: object - cronJob: - description: FeastCronJob defines a CronJob to execute against - a Feature Store deployment. + feastProject: + description: FeastProject is the Feast project id. + pattern: ^[A-Za-z0-9][A-Za-z0-9_-]*$ + type: string + feastProjectDir: + description: FeastProjectDir defines how to create the feast project + directory. properties: - annotations: - additionalProperties: - type: string - description: Annotations to be added to the CronJob metadata. - type: object - concurrencyPolicy: - description: Specifies how to treat concurrent executions - of a Job. - type: string - containerConfigs: - description: CronJobContainerConfigs k8s container settings - for the CronJob + git: + description: GitCloneOptions describes how a clone should + be performed. properties: - commands: - description: Array of commands to be executed (in order) - against a Feature Store deployment. - items: + configs: + additionalProperties: type: string - type: array + description: |- + Configs passed to git via `-c` + e.g. http.sslVerify: 'false' + OR 'url."https://api:\${TOKEN}@github.com/". + type: object env: items: description: EnvVar represents an environment variable @@ -4435,520 +6363,884 @@ spec: - resource type: object x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the - pod's namespace + secretKeyRef: + description: Selects a key of a secret in the + pod's namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source of + a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend to + each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + featureRepoPath: + description: FeatureRepoPath is the relative path to the + feature repo subdirectory. Default is 'feature_repo'. + type: string + ref: + description: Reference to a branch / tag / commit + type: string + url: + description: The repository URL to clone from. + type: string + required: + - url + type: object + x-kubernetes-validations: + - message: RepoPath must be a file name only, with no slashes. + rule: 'has(self.featureRepoPath) ? !self.featureRepoPath.startsWith(''/'') + : true' + init: + description: FeastInitOptions defines how to run a `feast + init`. + properties: + minimal: + type: boolean + template: + description: Template for the created project + enum: + - local + - gcp + - aws + - snowflake + - spark + - postgres + - hbase + - cassandra + - hazelcast + - couchbase + - clickhouse + type: string + type: object + type: object + x-kubernetes-validations: + - message: One selection required between init or git. + rule: '[has(self.git), has(self.init)].exists_one(c, c)' + replicas: + default: 1 + description: |- + Replicas is the desired number of pod replicas. Used by the scale sub-resource. + Mutually exclusive with services. + format: int32 + minimum: 1 + type: integer + services: + description: FeatureStoreServices defines the desired feast services. + An ephemeral onlineStore feature server is deployed by default. + properties: + affinity: + description: Affinity defines the pod scheduling constraints + for the FeatureStore deployment. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but i + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: "If the affinity requirements specified + by this field are not met at\nscheduling time, the + pod will not be scheduled onto " + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but i + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. properties: - key: - description: The key of the secret to select - from. Must be a valid secret key. - type: string - name: - default: "" + labelSelector: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in t type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean required: - - key + - topologyKey type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - items: - description: EnvFromSource represents the source of - a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the ConfigMap must - be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - default: "" + weight: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the Secret must - be defined - type: boolean + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - type: string - imagePullPolicy: - description: PullPolicy describes a policy for if/when - to pull a container image - type: string - nodeSelector: - additionalProperties: - type: string - type: object - resources: - description: ResourceRequirements describes the compute - resource requirements. - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: "If the affinity requirements specified + by this field are not met at\nscheduling time, the + pod will not be scheduled onto " items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. + description: "Defines a set of pods (namely those + matching the labelSelector\nrelative to the given + namespace(s)) that this pod should " properties: - name: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in t type: string required: - - name + - topologyKey type: object type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the minimum amount - of compute resources required. - type: object + x-kubernetes-list-type: atomic type: object - type: object - failedJobsHistoryLimit: - description: The number of failed finished jobs to retain. - Value must be non-negative integer. - format: int32 - type: integer - jobSpec: - description: Specification of the desired behavior of a job. - properties: - activeDeadlineSeconds: - description: |- - Specifies the duration in seconds relative to the startTime that the job - may be continuously active before the system tr - format: int64 - type: integer - backoffLimit: - description: Specifies the number of retries before marking - this job failed. - format: int32 - type: integer - backoffLimitPerIndex: - description: |- - Specifies the limit for the number of retries within an - index before marking this index as failed. - format: int32 - type: integer - completionMode: - description: |- - completionMode specifies how Pod completions are tracked. It can be - `NonIndexed` (default) or `Indexed`. - type: string - completions: - description: |- - Specifies the desired number of successfully finished pods the - job should be run with. - format: int32 - type: integer - maxFailedIndexes: - description: |- - Specifies the maximal number of failed indexes before marking the Job as - failed, when backoffLimitPerIndex is set. - format: int32 - type: integer - parallelism: - description: |- - Specifies the maximum desired number of pods the job should - run at any given time. - format: int32 - type: integer - podFailurePolicy: - description: Specifies the policy of handling failed pods. + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, + etc. properties: - rules: - description: A list of pod failure policy rules. The - rules are evaluated in order. + preferredDuringSchedulingIgnoredDuringExecution: + description: "The scheduler will prefer to schedule + pods to nodes that satisfy\nthe anti-affinity expressions + specified by this field, " items: - description: PodFailurePolicyRule describes how - a pod failure is handled when the requirements - are met. + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) properties: - action: - description: Specifies the action taken on a - pod failure when the requirements are satisfied. - type: string - onExitCodes: - description: Represents the requirement on the - container exit codes. + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. properties: - containerName: + labelSelector: description: |- - Restricts the check for exit codes to the container with the - specified name. - type: string - operator: + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: description: |- - Represents the relationship between the container exit code(s) and the - specified values. - type: string - values: - description: Specifies the set of values. + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. items: - format: int32 - type: integer + type: string type: array - x-kubernetes-list-type: set + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in t + type: string required: - - operator - - values + - topologyKey type: object - onPodConditions: + weight: description: |- - Represents the requirement on the pod conditions. The requirement is represented - as a list of pod condition patterns. - items: - description: |- - PodFailurePolicyOnPodConditionsPattern describes a pattern for matching - an actual pod condition type. - properties: - status: - description: Specifies the required Pod - condition status. - type: string - type: - description: Specifies the required Pod - condition type. - type: string - required: - - status - - type - type: object - type: array - x-kubernetes-list-type: atomic + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer required: - - action + - podAffinityTerm + - weight type: object type: array x-kubernetes-list-type: atomic - required: - - rules - type: object - podReplacementPolicy: - description: podReplacementPolicy specifies when to create - replacement Pods. - type: string - podTemplateAnnotations: - additionalProperties: - type: string - description: |- - PodTemplateAnnotations are annotations to be applied to the CronJob's PodTemplate - metadata. - type: object - suspend: - description: suspend specifies whether the Job controller - should create Pods or not. - type: boolean - ttlSecondsAfterFinished: - description: |- - ttlSecondsAfterFinished limits the lifetime of a Job that has finished - execution (either Complete or Failed). - format: int32 - type: integer - type: object - schedule: - description: The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. - type: string - startingDeadlineSeconds: - description: |- - Optional deadline in seconds for starting the job if it misses scheduled - time for any reason. - format: int64 - type: integer - successfulJobsHistoryLimit: - description: The number of successful finished jobs to retain. - Value must be non-negative integer. - format: int32 - type: integer - suspend: - description: |- - This flag tells the controller to suspend subsequent executions, it does - not apply to already started executions. - type: boolean - timeZone: - description: The time zone name for the given schedule, see - https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. - type: string - type: object - feastProject: - description: FeastProject is the Feast project id. - pattern: ^[A-Za-z0-9][A-Za-z0-9_-]*$ - type: string - feastProjectDir: - description: FeastProjectDir defines how to create the feast project - directory. - properties: - git: - description: GitCloneOptions describes how a clone should - be performed. - properties: - configs: - additionalProperties: - type: string - description: |- - Configs passed to git via `-c` - e.g. http.sslVerify: 'false' - OR 'url."https://api:\${TOKEN}@github.com/". - type: object - env: - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. + requiredDuringSchedulingIgnoredDuringExecution: + description: "If the anti-affinity requirements specified + by this field are not met at\nscheduling time, the + pod will not be scheduled " + items: + description: "Defines a set of pods (namely those + matching the labelSelector\nrelative to the given + namespace(s)) that this pod should " properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: 'Selects a field of the pod: supports - metadata.name, metadata.namespace, `metadata.labels['''']`, - `metadata.' - properties: - apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: + labelSelector: description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits. + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: - containerName: - description: 'Container name: required for - volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults to - "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object type: object x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the - pod's namespace + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. properties: - key: - description: The key of the secret to select - from. Must be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object type: object x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - items: - description: EnvFromSource represents the source of - a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the ConfigMap must - be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - default: "" + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in t type: string - optional: - description: Specify whether the Secret must - be defined - type: boolean + required: + - topologyKey type: object - x-kubernetes-map-type: atomic - type: object - type: array - featureRepoPath: - description: FeatureRepoPath is the relative path to the - feature repo subdirectory. Default is 'feature_repo'. - type: string - ref: - description: Reference to a branch / tag / commit - type: string - url: - description: The repository URL to clone from. - type: string - required: - - url - type: object - x-kubernetes-validations: - - message: RepoPath must be a file name only, with no slashes. - rule: 'has(self.featureRepoPath) ? !self.featureRepoPath.startsWith(''/'') - : true' - init: - description: FeastInitOptions defines how to run a `feast - init`. - properties: - minimal: - type: boolean - template: - description: Template for the created project - enum: - - local - - gcp - - aws - - snowflake - - spark - - postgres - - hbase - - cassandra - - hazelcast - - ikv - - couchbase - - clickhouse - type: string + type: array + x-kubernetes-list-type: atomic + type: object type: object - type: object - x-kubernetes-validations: - - message: One selection required between init or git. - rule: '[has(self.git), has(self.init)].exists_one(c, c)' - services: - description: FeatureStoreServices defines the desired feast services. - An ephemeral onlineStore feature server is deployed by default. - properties: deploymentStrategy: description: DeploymentStrategy describes how to replace existing pods with new ones. @@ -5115,6 +7407,7 @@ spec: - couchbase.offline - clickhouse - ray + - oracle type: string required: - secretRef @@ -5618,7 +7911,6 @@ spec: enum: - snowflake.online - redis - - ikv - datastore - dynamodb - bigtable @@ -5633,6 +7925,7 @@ spec: - couchbase.online - milvus - hybrid + - mongodb type: string required: - secretRef @@ -5759,866 +8052,1476 @@ spec: - name type: object type: array - envFrom: - items: - description: EnvFromSource represents the source - of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + envFrom: + items: + description: EnvFromSource represents the source + of a set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image + type: string + logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". + enum: + - debug + - info + - warning + - error + - critical + type: string + metrics: + description: Metrics exposes Prometheus-compatible + metrics for the Feast server when enabled. + type: boolean + nodeSelector: + additionalProperties: + type: string + type: object + resources: + description: ResourceRequirements describes the compute + resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount + of compute resources required. + type: object + type: object + tls: + description: TlsConfigs configures server TLS for + a feast service. + properties: + disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, + where TLS is configured by default + type: boolean + secretKeyNames: + description: SecretKeyNames defines the secret + key names for the TLS key and cert. + properties: + tlsCrt: + description: defaults to "tls.crt" + type: string + tlsKey: + description: defaults to "tls.key" + type: string + type: object + secretRef: + description: references the local k8s secret where + the TLS key and cert reside + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: '`secretRef` required if `disable` is false.' + rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) + : true' + volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. + items: + description: VolumeMount describes a mounting of + a Volume within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume + from which the container's volume should be + mounted. + type: string + required: + - mountPath + - name + type: object + type: array + workerConfigs: + description: WorkerConfigs defines the worker configuration + for the Feast server. + properties: + keepAliveTimeout: + description: |- + KeepAliveTimeout is the timeout for keep-alive connections in seconds. + Defaults to 30. + format: int32 + minimum: 1 + type: integer + maxRequests: + description: |- + MaxRequests is the maximum number of requests a worker will process before restarting. + This helps prevent memory leaks. + format: int32 + minimum: 0 + type: integer + maxRequestsJitter: + description: |- + MaxRequestsJitter is the maximum jitter to add to max-requests to prevent + thundering herd effect on worker restart. + format: int32 + minimum: 0 + type: integer + registryTTLSeconds: + description: RegistryTTLSeconds is the number + of seconds after which the registry is refreshed. + format: int32 + minimum: 0 + type: integer + workerConnections: + description: |- + WorkerConnections is the maximum number of simultaneous clients per worker process. + Defaults to 1000. + format: int32 + minimum: 1 + type: integer + workers: + description: Workers is the number of worker processes. + Use -1 to auto-calculate based on CPU cores + (2 * CPU + 1). + format: int32 + minimum: -1 + type: integer + type: object + type: object + type: object + podAnnotations: + additionalProperties: + type: string + description: PodAnnotations are annotations to be applied + to the Deployment's PodTemplate metadata. + type: object + podDisruptionBudgets: + description: PodDisruptionBudgets configures a PodDisruptionBudget + for the FeatureStore deployment. + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: MaxUnavailable specifies the maximum number/percentage + of pods that can be unavailable. + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + description: MinAvailable specifies the minimum number/percentage + of pods that must remain available. + x-kubernetes-int-or-string: true + type: object + x-kubernetes-validations: + - message: Exactly one of minAvailable or maxUnavailable must + be set. + rule: '[has(self.minAvailable), has(self.maxUnavailable)].exists_one(c, + c)' + registry: + description: Registry configures the registry service. One + selection is required. Local is the default setting. + properties: + local: + description: LocalRegistryConfig configures the registry + service + properties: + persistence: + description: RegistryPersistence configures the persistence + settings for the registry service + properties: + file: + description: RegistryFilePersistence configures + the file-based persistence for the registry + service + properties: + cache_mode: + description: |- + CacheMode defines the registry cache update strategy. + Allowed values are "sync" and "thread". + enum: + - none + - sync + - thread + type: string + cache_ttl_seconds: + description: CacheTTLSeconds defines the TTL + (in seconds) for the registry cache. + format: int32 + minimum: 0 + type: integer + path: + type: string + pvc: + description: PvcConfig defines the settings + for a persistent file store based on PVCs. + properties: + create: + description: Settings for creating a new + PVC + properties: + accessModes: + description: AccessModes k8s persistent + volume access modes. Defaults to + ["ReadWriteOnce"]. + items: + type: string + type: array + resources: + description: Resources describes the + storage resource requirements for + a volume. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes + the minimum amount of compute + resources required. + type: object + type: object + storageClassName: + description: StorageClassName is the + name of an existing StorageClass + to which this persistent volume + belongs. + type: string + type: object + x-kubernetes-validations: + - message: PvcCreate is immutable + rule: self == oldSelf + mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. + type: string + ref: + description: Reference to an existing + field + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + required: + - mountPath + type: object + x-kubernetes-validations: + - message: One selection is required between + ref and create. + rule: '[has(self.ref), has(self.create)].exists_one(c, + c)' + - message: Mount path must start with '/' + and must not contain ':' + rule: self.mountPath.matches('^/[^:]*$') + s3_additional_kwargs: + additionalProperties: type: string - optional: - description: Specify whether the ConfigMap - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from + type: object + type: object + x-kubernetes-validations: + - message: Registry files must use absolute paths + or be S3 ('s3://') or GS ('gs://') object + store URIs. + rule: '(!has(self.pvc) && has(self.path)) ? + (self.path.startsWith(''/'') || self.path.startsWith(''s3://'') + || self.path.startsWith(''gs://'')) : true' + - message: PVC path must be a file name only, + with no slashes. + rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') + : true' + - message: PVC persistence does not support S3 + or GS object store URIs. + rule: '(has(self.pvc) && has(self.path)) ? !(self.path.startsWith(''s3://'') + || self.path.startsWith(''gs://'')) : true' + - message: Additional S3 settings are available + only for S3 object store URIs. + rule: '(has(self.s3_additional_kwargs) && has(self.path)) + ? self.path.startsWith(''s3://'') : true' + store: + description: RegistryDBStorePersistence configures + the DB store persistence for the registry service + properties: + secretKeyName: + description: By default, the selected store + "type" is used as the SecretKeyName + type: string + secretRef: + description: Data store parameters should + be placed as-is from the "feature_store.yaml" + under the secret key. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + type: + description: Type of the persistence type + you want to use. + enum: + - sql + - snowflake.registry + type: string + required: + - secretRef + - type + type: object + type: object + x-kubernetes-validations: + - message: One selection required between file or + store. + rule: '[has(self.file), has(self.store)].exists_one(c, + c)' + server: + description: Creates a registry server container + properties: + env: + items: + description: EnvVar represents an environment + variable present in a Container. properties: name: - default: "" + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any type: string - optional: - description: Specify whether the Secret - must be defined - type: boolean + valueFrom: + description: Source for the environment + variable's value. Cannot be used if value + is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the + ConfigMap or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the + pod: supports metadata.name, metadata.namespace, + `metadata.labels['''']`, `metadata.' + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env + vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret + in the pod's namespace + properties: + key: + description: The key of the secret + to select from. Must be a valid + secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the + Secret or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - type: string - imagePullPolicy: - description: PullPolicy describes a policy for if/when - to pull a container image - type: string - logLevel: - description: |- - LogLevel sets the logging level for the server - Allowed values: "debug", "info", "warning", "error", "critical". - enum: - - debug - - info - - warning - - error - - critical - type: string - metrics: - description: Metrics exposes Prometheus-compatible - metrics for the Feast server when enabled. - type: boolean - nodeSelector: - additionalProperties: - type: string - type: object - resources: - description: ResourceRequirements describes the compute - resource requirements. - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. + type: array + envFrom: items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. + description: EnvFromSource represents the source + of a set of ConfigMaps properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: An optional identifier to prepend + to each key in the ConfigMap. Must be + a C_IDENTIFIER. type: string - required: - - name + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic type: object type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true + grpc: + description: Enable gRPC registry server. Defaults + to true if unset. + type: boolean + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for + if/when to pull a container image + type: string + logLevel: description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the minimum amount - of compute resources required. - type: object - type: object - tls: - description: TlsConfigs configures server TLS for - a feast service. - properties: - disable: - description: will disable TLS for the feast service. - useful in an openshift cluster, for example, - where TLS is configured by default + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". + enum: + - debug + - info + - warning + - error + - critical + type: string + metrics: + description: Metrics exposes Prometheus-compatible + metrics for the Feast server when enabled. type: boolean - secretKeyNames: - description: SecretKeyNames defines the secret - key names for the TLS key and cert. - properties: - tlsCrt: - description: defaults to "tls.crt" - type: string - tlsKey: - description: defaults to "tls.key" - type: string + nodeSelector: + additionalProperties: + type: string type: object - secretRef: - description: references the local k8s secret where - the TLS key and cert reside + resources: + description: ResourceRequirements describes the + compute resource requirements. properties: - name: - default: "" + claims: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' - volumeMounts: - description: VolumeMounts defines the list of volumes - that should be mounted into the feast container. - items: - description: VolumeMount describes a mounting of - a Volume within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: - description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. - type: string - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: Expanded path within the volume - from which the container's volume should be - mounted. - type: string - required: - - mountPath - - name - type: object - type: array - workerConfigs: - description: WorkerConfigs defines the worker configuration - for the Feast server. - properties: - keepAliveTimeout: - description: |- - KeepAliveTimeout is the timeout for keep-alive connections in seconds. - Defaults to 30. - format: int32 - minimum: 1 - type: integer - maxRequests: - description: |- - MaxRequests is the maximum number of requests a worker will process before restarting. - This helps prevent memory leaks. - format: int32 - minimum: 0 - type: integer - maxRequestsJitter: - description: |- - MaxRequestsJitter is the maximum jitter to add to max-requests to prevent - thundering herd effect on worker restart. - format: int32 - minimum: 0 - type: integer - registryTTLSeconds: - description: RegistryTTLSeconds is the number - of seconds after which the registry is refreshed. - format: int32 - minimum: 0 - type: integer - workerConnections: - description: |- - WorkerConnections is the maximum number of simultaneous clients per worker process. - Defaults to 1000. - format: int32 - minimum: 1 - type: integer - workers: - description: Workers is the number of worker processes. - Use -1 to auto-calculate based on CPU cores - (2 * CPU + 1). - format: int32 - minimum: -1 - type: integer - type: object - type: object - type: object - registry: - description: Registry configures the registry service. One - selection is required. Local is the default setting. - properties: - local: - description: LocalRegistryConfig configures the registry - service - properties: - persistence: - description: RegistryPersistence configures the persistence - settings for the registry service - properties: - file: - description: RegistryFilePersistence configures - the file-based persistence for the registry - service - properties: - cache_mode: + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + items: + description: ResourceClaim references one + entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true description: |- - CacheMode defines the registry cache update strategy. - Allowed values are "sync" and "thread". - enum: - - none - - sync - - thread - type: string - cache_ttl_seconds: - description: CacheTTLSeconds defines the TTL - (in seconds) for the registry cache. - format: int32 - minimum: 0 - type: integer - path: - type: string - pvc: - description: PvcConfig defines the settings - for a persistent file store based on PVCs. + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum + amount of compute resources required. + type: object + type: object + restAPI: + description: Enable REST API registry server. + type: boolean + tls: + description: TlsConfigs configures server TLS + for a feast service. + properties: + disable: + description: will disable TLS for the feast + service. useful in an openshift cluster, + for example, where TLS is configured by + default + type: boolean + secretKeyNames: + description: SecretKeyNames defines the secret + key names for the TLS key and cert. properties: - create: - description: Settings for creating a new - PVC - properties: - accessModes: - description: AccessModes k8s persistent - volume access modes. Defaults to - ["ReadWriteOnce"]. - items: - type: string - type: array - resources: - description: Resources describes the - storage resource requirements for - a volume. - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes - the minimum amount of compute - resources required. - type: object - type: object - storageClassName: - description: StorageClassName is the - name of an existing StorageClass - to which this persistent volume - belongs. - type: string - type: object - x-kubernetes-validations: - - message: PvcCreate is immutable - rule: self == oldSelf - mountPath: - description: |- - MountPath within the container at which the volume should be mounted. - Must start by "/" and cannot contain ':'. + tlsCrt: + description: defaults to "tls.crt" + type: string + tlsKey: + description: defaults to "tls.key" type: string - ref: - description: Reference to an existing - field - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - mountPath type: object - x-kubernetes-validations: - - message: One selection is required between - ref and create. - rule: '[has(self.ref), has(self.create)].exists_one(c, - c)' - - message: Mount path must start with '/' - and must not contain ':' - rule: self.mountPath.matches('^/[^:]*$') - s3_additional_kwargs: - additionalProperties: - type: string + secretRef: + description: references the local k8s secret + where the TLS key and cert reside + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string type: object + x-kubernetes-map-type: atomic type: object x-kubernetes-validations: - - message: Registry files must use absolute paths - or be S3 ('s3://') or GS ('gs://') object - store URIs. - rule: '(!has(self.pvc) && has(self.path)) ? - (self.path.startsWith(''/'') || self.path.startsWith(''s3://'') - || self.path.startsWith(''gs://'')) : true' - - message: PVC path must be a file name only, - with no slashes. - rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') - : true' - - message: PVC persistence does not support S3 - or GS object store URIs. - rule: '(has(self.pvc) && has(self.path)) ? !(self.path.startsWith(''s3://'') - || self.path.startsWith(''gs://'')) : true' - - message: Additional S3 settings are available - only for S3 object store URIs. - rule: '(has(self.s3_additional_kwargs) && has(self.path)) - ? self.path.startsWith(''s3://'') : true' - store: - description: RegistryDBStorePersistence configures - the DB store persistence for the registry service + - message: '`secretRef` required if `disable` + is false.' + rule: '(!has(self.disable) || !self.disable) + ? has(self.secretRef) : true' + volumeMounts: + description: VolumeMounts defines the list of + volumes that should be mounted into the feast + container. + items: + description: VolumeMount describes a mounting + of a Volume within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + type: string + name: + description: This must match the Name of + a Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume + from which the container's volume should + be mounted. + type: string + required: + - mountPath + - name + type: object + type: array + workerConfigs: + description: WorkerConfigs defines the worker + configuration for the Feast server. + properties: + keepAliveTimeout: + description: |- + KeepAliveTimeout is the timeout for keep-alive connections in seconds. + Defaults to 30. + format: int32 + minimum: 1 + type: integer + maxRequests: + description: |- + MaxRequests is the maximum number of requests a worker will process before restarting. + This helps prevent memory leaks. + format: int32 + minimum: 0 + type: integer + maxRequestsJitter: + description: |- + MaxRequestsJitter is the maximum jitter to add to max-requests to prevent + thundering herd effect on worker restart. + format: int32 + minimum: 0 + type: integer + registryTTLSeconds: + description: RegistryTTLSeconds is the number + of seconds after which the registry is refreshed. + format: int32 + minimum: 0 + type: integer + workerConnections: + description: |- + WorkerConnections is the maximum number of simultaneous clients per worker process. + Defaults to 1000. + format: int32 + minimum: 1 + type: integer + workers: + description: Workers is the number of worker + processes. Use -1 to auto-calculate based + on CPU cores (2 * CPU + 1). + format: int32 + minimum: -1 + type: integer + type: object + type: object + x-kubernetes-validations: + - message: At least one of restAPI or grpc must be + true + rule: self.restAPI == true || self.grpc == true + || !has(self.grpc) + type: object + remote: + description: RemoteRegistryConfig points to a remote feast + registry server. + properties: + feastRef: + description: Reference to an existing `FeatureStore` + CR in the same k8s cluster. + properties: + name: + description: Name of the FeatureStore + type: string + namespace: + description: Namespace of the FeatureStore + type: string + required: + - name + type: object + hostname: + description: Host address of the remote registry service + - :, e.g. `registry..svc.cluster.local:80` + type: string + tls: + description: TlsRemoteRegistryConfigs configures client + TLS for a remote feast registry. + properties: + certName: + description: defines the configmap key name for + the client TLS cert. + type: string + configMapRef: + description: references the local k8s configmap + where the TLS cert resides properties: - secretKeyName: - description: By default, the selected store - "type" is used as the SecretKeyName - type: string - secretRef: - description: Data store parameters should - be placed as-is from the "feature_store.yaml" - under the secret key. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - type: - description: Type of the persistence type - you want to use. - enum: - - sql - - snowflake.registry + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string - required: - - secretRef - - type type: object + x-kubernetes-map-type: atomic + required: + - certName + - configMapRef type: object - x-kubernetes-validations: - - message: One selection required between file or - store. - rule: '[has(self.file), has(self.store)].exists_one(c, - c)' - server: - description: Creates a registry server container + type: object + x-kubernetes-validations: + - message: One selection required. + rule: '[has(self.hostname), has(self.feastRef)].exists_one(c, + c)' + type: object + x-kubernetes-validations: + - message: One selection required. + rule: '[has(self.local), has(self.remote)].exists_one(c, + c)' + runFeastApplyOnInit: + description: Runs feast apply on pod start to populate the + registry. Defaults to true. Ignored when DisableInitContainers + is true. + type: boolean + scaling: + description: Scaling configures horizontal scaling for the + FeatureStore deployment (e.g. HPA autoscaling). + properties: + autoscaling: + description: |- + Autoscaling configures a HorizontalPodAutoscaler for the FeatureStore deployment. + Mutually exclusive with spec.replicas. + properties: + behavior: + description: Behavior configures the scaling behavior + of the target. properties: - env: - items: - description: EnvVar represents an environment - variable present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any - type: string - valueFrom: - description: Source for the environment - variable's value. Cannot be used if value - is not empty. + scaleDown: + description: scaleDown is scaling policy for scaling + Down. + properties: + policies: + description: policies is a list of potential + scaling polices which can be used during + scaling. + items: + description: HPAScalingPolicy is a single + policy which must hold true for a specified + past interval. properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the - ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: 'Selects a field of the - pod: supports metadata.name, metadata.namespace, - `metadata.labels['''']`, `metadata.' - properties: - apiVersion: - description: Version of the schema - the FieldPath is written in terms - of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to - select in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: + periodSeconds: + description: periodSeconds specifies + the window of time for which the policy + should hold true. + format: int32 + type: integer + type: + description: type is used to specify + the scaling policy. + type: string + value: description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env - vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output - format of the exposed resources, - defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource - to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret - in the pod's namespace - properties: - key: - description: The key of the secret - to select from. Must be a valid - secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the - Secret or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic + value contains the amount of change which is permitted by the policy. + It must be greater than zero + format: int32 + type: integer + required: + - periodSeconds + - type + - value + type: object + type: array + x-kubernetes-list-type: atomic + selectPolicy: + description: |- + selectPolicy is used to specify which policy should be used. + If not set, the default value Max is used. + type: string + stabilizationWindowSeconds: + description: |- + stabilizationWindowSeconds is the number of seconds for which past recommendations should be + considered while scaling up + format: int32 + type: integer + type: object + scaleUp: + description: scaleUp is scaling policy for scaling + Up. + properties: + policies: + description: policies is a list of potential + scaling polices which can be used during + scaling. + items: + description: HPAScalingPolicy is a single + policy which must hold true for a specified + past interval. + properties: + periodSeconds: + description: periodSeconds specifies + the window of time for which the policy + should hold true. + format: int32 + type: integer + type: + description: type is used to specify + the scaling policy. + type: string + value: + description: |- + value contains the amount of change which is permitted by the policy. + It must be greater than zero + format: int32 + type: integer + required: + - periodSeconds + - type + - value + type: object + type: array + x-kubernetes-list-type: atomic + selectPolicy: + description: |- + selectPolicy is used to specify which policy should be used. + If not set, the default value Max is used. + type: string + stabilizationWindowSeconds: + description: |- + stabilizationWindowSeconds is the number of seconds for which past recommendations should be + considered while scaling up + format: int32 + type: integer + type: object + type: object + maxReplicas: + description: MaxReplicas is the upper limit for the + number of replicas. Required. + format: int32 + minimum: 1 + type: integer + metrics: + description: Metrics contains the specifications for + which to use to calculate the desired replica count. + items: + description: |- + MetricSpec specifies how to scale based on a single metric + (only `type` and one other matching field should be set at on + properties: + containerResource: + description: |- + containerResource refers to a resource metric (such as those specified in + requests and limits) known to Kubernetes descr + properties: + container: + description: container is the name of the + container in the pods of the scaling target + type: string + name: + description: name is the name of the resource + in question. + type: string + target: + description: target specifies the target + value for the given metric + properties: + averageUtilization: + description: "averageUtilization is + the target value of the average of + the\nresource metric across all relevant + pods, represented as a " + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether + the metric type is Utilization, Value, + or AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value + of the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type type: object required: + - container - name + - target type: object - type: array - envFrom: - items: - description: EnvFromSource represents the source - of a set of ConfigMaps + external: + description: |- + external refers to a global metric that is not associated + with any Kubernetes object. properties: - configMapRef: - description: The ConfigMap to select from + metric: + description: metric identifies the target + metric by name and selector properties: name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + description: name is the name of the + given metric type: string - optional: - description: Specify whether the ConfigMap - must be defined - type: boolean + selector: + description: "selector is the string-encoded + form of a standard kubernetes label + selector for the given metric\nWhen + set, it is passed " + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - name type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be - a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from + target: + description: target specifies the target + value for the given metric properties: - name: - default: "" + averageUtilization: + description: "averageUtilization is + the target value of the average of + the\nresource metric across all relevant + pods, represented as a " + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether + the metric type is Utilization, Value, + or AverageValue type: string - optional: - description: Specify whether the Secret - must be defined - type: boolean + value: + anyOf: + - type: integer + - type: string + description: value is the target value + of the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type type: object - x-kubernetes-map-type: atomic + required: + - metric + - target type: object - type: array - grpc: - description: Enable gRPC registry server. Defaults - to true if unset. - type: boolean - image: - type: string - imagePullPolicy: - description: PullPolicy describes a policy for - if/when to pull a container image - type: string - logLevel: - description: |- - LogLevel sets the logging level for the server - Allowed values: "debug", "info", "warning", "error", "critical". - enum: - - debug - - info - - warning - - error - - critical - type: string - metrics: - description: Metrics exposes Prometheus-compatible - metrics for the Feast server when enabled. - type: boolean - nodeSelector: - additionalProperties: - type: string - type: object - resources: - description: ResourceRequirements describes the - compute resource requirements. - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - items: - description: ResourceClaim references one - entry in PodSpec.ResourceClaims. + object: + description: |- + object refers to a metric describing a single kubernetes object + (for example, hits-per-second on an Ingress object). + properties: + describedObject: + description: describedObject specifies the + descriptions of a object,such as kind,name + apiVersion properties: + apiVersion: + description: apiVersion is the API version + of the referent + type: string + kind: + description: 'kind is the kind of the + referent; More info: https://git.k8s.' + type: string name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. + description: 'name is the name of the + referent; More info: https://kubernetes.' type: string required: + - kind - name type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the minimum - amount of compute resources required. - type: object - type: object - restAPI: - description: Enable REST API registry server. - type: boolean - tls: - description: TlsConfigs configures server TLS - for a feast service. - properties: - disable: - description: will disable TLS for the feast - service. useful in an openshift cluster, - for example, where TLS is configured by - default - type: boolean - secretKeyNames: - description: SecretKeyNames defines the secret - key names for the TLS key and cert. - properties: - tlsCrt: - description: defaults to "tls.crt" - type: string - tlsKey: - description: defaults to "tls.key" - type: string - type: object - secretRef: - description: references the local k8s secret - where the TLS key and cert reside - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` - is false.' - rule: '(!has(self.disable) || !self.disable) - ? has(self.secretRef) : true' - volumeMounts: - description: VolumeMounts defines the list of - volumes that should be mounted into the feast - container. - items: - description: VolumeMount describes a mounting - of a Volume within a container. + metric: + description: metric identifies the target + metric by name and selector + properties: + name: + description: name is the name of the + given metric + type: string + selector: + description: "selector is the string-encoded + form of a standard kubernetes label + selector for the given metric\nWhen + set, it is passed " + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - name + type: object + target: + description: target specifies the target + value for the given metric + properties: + averageUtilization: + description: "averageUtilization is + the target value of the average of + the\nresource metric across all relevant + pods, represented as a " + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether + the metric type is Utilization, Value, + or AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value + of the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - describedObject + - metric + - target + type: object + pods: + description: |- + pods refers to a metric describing each pod in the current scale target + (for example, transactions-processed-per-second) + properties: + metric: + description: metric identifies the target + metric by name and selector + properties: + name: + description: name is the name of the + given metric + type: string + selector: + description: "selector is the string-encoded + form of a standard kubernetes label + selector for the given metric\nWhen + set, it is passed " + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - name + type: object + target: + description: target specifies the target + value for the given metric + properties: + averageUtilization: + description: "averageUtilization is + the target value of the average of + the\nresource metric across all relevant + pods, represented as a " + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether + the metric type is Utilization, Value, + or AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value + of the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - metric + - target + type: object + resource: + description: |- + resource refers to a resource metric (such as those specified in + requests and limits) known to Kubernetes describing eac properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - type: string name: - description: This must match the Name of - a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: - description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. - type: string - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: Expanded path within the volume - from which the container's volume should - be mounted. + description: name is the name of the resource + in question. type: string + target: + description: target specifies the target + value for the given metric + properties: + averageUtilization: + description: "averageUtilization is + the target value of the average of + the\nresource metric across all relevant + pods, represented as a " + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether + the metric type is Utilization, Value, + or AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value + of the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object required: - - mountPath - name + - target type: object - type: array - workerConfigs: - description: WorkerConfigs defines the worker - configuration for the Feast server. - properties: - keepAliveTimeout: - description: |- - KeepAliveTimeout is the timeout for keep-alive connections in seconds. - Defaults to 30. - format: int32 - minimum: 1 - type: integer - maxRequests: - description: |- - MaxRequests is the maximum number of requests a worker will process before restarting. - This helps prevent memory leaks. - format: int32 - minimum: 0 - type: integer - maxRequestsJitter: - description: |- - MaxRequestsJitter is the maximum jitter to add to max-requests to prevent - thundering herd effect on worker restart. - format: int32 - minimum: 0 - type: integer - registryTTLSeconds: - description: RegistryTTLSeconds is the number - of seconds after which the registry is refreshed. - format: int32 - minimum: 0 - type: integer - workerConnections: - description: |- - WorkerConnections is the maximum number of simultaneous clients per worker process. - Defaults to 1000. - format: int32 - minimum: 1 - type: integer - workers: - description: Workers is the number of worker - processes. Use -1 to auto-calculate based - on CPU cores (2 * CPU + 1). - format: int32 - minimum: -1 - type: integer - type: object - type: object - x-kubernetes-validations: - - message: At least one of restAPI or grpc must be - true - rule: self.restAPI == true || self.grpc == true - || !has(self.grpc) - type: object - remote: - description: RemoteRegistryConfig points to a remote feast - registry server. - properties: - feastRef: - description: Reference to an existing `FeatureStore` - CR in the same k8s cluster. - properties: - name: - description: Name of the FeatureStore - type: string - namespace: - description: Namespace of the FeatureStore - type: string - required: - - name - type: object - hostname: - description: Host address of the remote registry service - - :, e.g. `registry..svc.cluster.local:80` - type: string - tls: - description: TlsRemoteRegistryConfigs configures client - TLS for a remote feast registry. - properties: - certName: - description: defines the configmap key name for - the client TLS cert. - type: string - configMapRef: - description: references the local k8s configmap - where the TLS cert resides - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - certName - - configMapRef - type: object + type: + description: type is the type of metric source. + type: string + required: + - type + type: object + type: array + minReplicas: + description: MinReplicas is the lower limit for the + number of replicas. Defaults to 1. + format: int32 + minimum: 1 + type: integer + required: + - maxReplicas type: object - x-kubernetes-validations: - - message: One selection required. - rule: '[has(self.hostname), has(self.feastRef)].exists_one(c, - c)' type: object - x-kubernetes-validations: - - message: One selection required. - rule: '[has(self.local), has(self.remote)].exists_one(c, - c)' securityContext: description: PodSecurityContext holds pod-level security attributes and common container settings. @@ -6752,6 +9655,98 @@ spec: type: string type: object type: object + topologySpreadConstraints: + description: TopologySpreadConstraints defines how pods are + spread across topology domains. + items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. + properties: + labelSelector: + description: LabelSelector is used to find matching + pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. + format: int32 + type: integer + minDomains: + description: MinDomains indicates a minimum number of + eligible domains. + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread skew + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. + type: string + topologyKey: + description: TopologyKey is the key of node labels. + type: string + whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array ui: description: Creates a UI server container properties: @@ -8540,6 +11535,37 @@ spec: required: - feastProject type: object + x-kubernetes-validations: + - message: replicas > 1 and services.scaling.autoscaling are mutually + exclusive. + rule: self.replicas <= 1 || !has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling) + - message: Scaling requires DB-backed persistence for the online store. + Configure services.onlineStore.persistence.store when using replicas + > 1 or autoscaling. + rule: self.replicas <= 1 && (!has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling)) || (has(self.services) + && has(self.services.onlineStore) && has(self.services.onlineStore.persistence) + && has(self.services.onlineStore.persistence.store)) + - message: Scaling requires DB-backed persistence for the offline + store. Configure services.offlineStore.persistence.store when + using replicas > 1 or autoscaling. + rule: self.replicas <= 1 && (!has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling)) || (!has(self.services) + || !has(self.services.offlineStore) || (has(self.services.offlineStore.persistence) + && has(self.services.offlineStore.persistence.store))) + - message: Scaling requires DB-backed or remote registry. Configure + registry.local.persistence.store or use a remote registry when + using replicas > 1 or autoscaling. S3/GCS-backed registry is also + allowed. + rule: self.replicas <= 1 && (!has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling)) || (has(self.services) + && has(self.services.registry) && (has(self.services.registry.remote) + || (has(self.services.registry.local) && has(self.services.registry.local.persistence) + && (has(self.services.registry.local.persistence.store) || (has(self.services.registry.local.persistence.file) + && has(self.services.registry.local.persistence.file.path) && + (self.services.registry.local.persistence.file.path.startsWith('s3://') + || self.services.registry.local.persistence.file.path.startsWith('gs://'))))))) clientConfigMap: description: ConfigMap in this namespace containing a client `feature_store.yaml` for this feast deployment @@ -8604,6 +11630,28 @@ spec: type: string phase: type: string + replicas: + description: Replicas is the current number of ready pod replicas + (used by the scale sub-resource). + format: int32 + type: integer + scalingStatus: + description: ScalingStatus reports the current scaling state of the + FeatureStore deployment. + properties: + currentReplicas: + description: CurrentReplicas is the current number of pod replicas. + format: int32 + type: integer + desiredReplicas: + description: DesiredReplicas is the desired number of pod replicas. + format: int32 + type: integer + type: object + selector: + description: Selector is the label selector for pods managed by the + FeatureStore deployment (used by the scale sub-resource). + type: string serviceHostnames: description: ServiceHostnames defines the service hostnames in the format of :, e.g. example.svc.cluster.local:80 @@ -8624,6 +11672,10 @@ spec: served: true storage: true subresources: + scale: + labelSelectorPath: .status.selector + specReplicasPath: .spec.replicas + statusReplicasPath: .status.replicas status: {} - additionalPrinterColumns: - jsonPath: .status.phase @@ -9294,7 +12346,6 @@ spec: - hbase - cassandra - hazelcast - - ikv - couchbase - clickhouse type: string @@ -9966,7 +13017,6 @@ spec: enum: - snowflake.online - redis - - ikv - datastore - dynamodb - bigtable @@ -9981,6 +13031,7 @@ spec: - couchbase.online - milvus - hybrid + - mongodb type: string required: - secretRef @@ -10944,6 +13995,10 @@ spec: x-kubernetes-validations: - message: One selection required. rule: '[has(self.local), has(self.remote)].exists_one(c, c)' + runFeastApplyOnInit: + description: Runs feast apply on pod start to populate the registry. + Defaults to true. Ignored when DisableInitContainers is true. + type: boolean securityContext: description: PodSecurityContext holds pod-level security attributes and common container settings. @@ -13505,7 +16560,6 @@ spec: - hbase - cassandra - hazelcast - - ikv - couchbase - clickhouse type: string @@ -14187,7 +17241,6 @@ spec: enum: - snowflake.online - redis - - ikv - datastore - dynamodb - bigtable @@ -14202,6 +17255,7 @@ spec: - couchbase.online - milvus - hybrid + - mongodb type: string required: - secretRef @@ -15188,6 +18242,11 @@ spec: - message: One selection required. rule: '[has(self.local), has(self.remote)].exists_one(c, c)' + runFeastApplyOnInit: + description: Runs feast apply on pod start to populate the + registry. Defaults to true. Ignored when DisableInitContainers + is true. + type: boolean securityContext: description: PodSecurityContext holds pod-level security attributes and common container settings. diff --git a/infra/feast-operator/cmd/main.go b/infra/feast-operator/cmd/main.go index 4be1777ac72..70f5635fe33 100644 --- a/infra/feast-operator/cmd/main.go +++ b/infra/feast-operator/cmd/main.go @@ -105,7 +105,7 @@ func main() { // Metrics endpoint is enabled in 'config/default/kustomization.yaml'. The Metrics options configure the server. // More info: - // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.18.4/pkg/metrics/server + // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21.0/pkg/metrics/server // - https://book.kubebuilder.io/reference/metrics.html metricsServerOptions := metricsserver.Options{ BindAddress: metricsAddr, @@ -123,7 +123,7 @@ func main() { // FilterProvider is used to protect the metrics endpoint with authn/authz. // These configurations ensure that only authorized users and service accounts // can access the metrics endpoint. The RBAC are configured in 'config/rbac/kustomization.yaml'. More info: - // https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.18.4/pkg/metrics/filters#WithAuthenticationAndAuthorization + // https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21.0/pkg/metrics/filters#WithAuthenticationAndAuthorization metricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization } diff --git a/infra/feast-operator/config/component_metadata.yaml b/infra/feast-operator/config/component_metadata.yaml index fad77d7090e..c84deab6d83 100644 --- a/infra/feast-operator/config/component_metadata.yaml +++ b/infra/feast-operator/config/component_metadata.yaml @@ -1,5 +1,5 @@ # This file is required to configure Feast release information for ODH/RHOAI Operator releases: - name: Feast - version: 0.60.0 + version: 0.62.0 repoUrl: https://github.com/feast-dev/feast diff --git a/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml b/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml index a3acc201a1c..6dcd1143b82 100644 --- a/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml +++ b/infra/feast-operator/config/crd/bases/feast.dev_featurestores.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.15.0 + controller-gen.kubebuilder.io/version: v0.18.0 name: featurestores.feast.dev spec: group: feast.dev @@ -62,10 +62,32 @@ spec: OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. https://auth0. properties: + caCertConfigMap: + description: ConfigMap with the CA certificate for self-signed + OIDC providers. Auto-detected on RHOAI/ODH. + properties: + key: + description: Key in the ConfigMap holding the PEM certificate. + Defaults to "ca-bundle.crt". + type: string + name: + description: ConfigMap name. + type: string + required: + - name + type: object + issuerUrl: + description: OIDC issuer URL. The operator appends /.well-known/openid-configuration + to derive the discovery endpoint. + pattern: ^https://\S+$ + type: string + secretKeyName: + description: Key in the Secret containing all OIDC properties + as a YAML value. If unset, each key is a property. + type: string secretRef: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. + description: Secret with OIDC properties (auth_discovery_url, + client_id, client_secret). issuerUrl takes precedence. properties: name: default: "" @@ -76,8 +98,14 @@ spec: type: string type: object x-kubernetes-map-type: atomic - required: - - secretRef + tokenEnvVar: + description: Env var name for client pods to read an OIDC + token from. Sets token_env_var in client config. + type: string + verifySSL: + description: Verify SSL certificates for the OIDC provider. + Defaults to true. + type: boolean type: object type: object x-kubernetes-validations: @@ -139,8 +167,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's value. @@ -239,7 +266,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of a set - of ConfigMaps + of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -258,8 +285,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -305,6 +332,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen for a request + in the referenced claim. + type: string required: - name type: object @@ -346,7 +377,7 @@ spec: activeDeadlineSeconds: description: |- Specifies the duration in seconds relative to the startTime that the job - may be continuously active before the system tr + may be continuously active before the system... format: int64 type: integer backoffLimit: @@ -529,8 +560,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's value. @@ -629,7 +659,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of a set - of ConfigMaps + of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -648,8 +678,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -703,7 +733,6 @@ spec: - hbase - cassandra - hazelcast - - ikv - couchbase - clickhouse type: string @@ -712,553 +741,806 @@ spec: x-kubernetes-validations: - message: One selection required between init or git. rule: '[has(self.git), has(self.init)].exists_one(c, c)' + replicas: + default: 1 + description: |- + Replicas is the desired number of pod replicas. Used by the scale sub-resource. + Mutually exclusive with services. + format: int32 + minimum: 1 + type: integer services: description: FeatureStoreServices defines the desired feast services. An ephemeral onlineStore feature server is deployed by default. properties: - deploymentStrategy: - description: DeploymentStrategy describes how to replace existing - pods with new ones. + affinity: + description: Affinity defines the pod scheduling constraints for + the FeatureStore deployment. properties: - rollingUpdate: - description: |- - Rolling update config params. Present only if DeploymentStrategyType = - RollingUpdate. + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. properties: - maxSurge: - anyOf: - - type: integer - - type: string + preferredDuringSchedulingIgnoredDuringExecution: description: |- - The maximum number of pods that can be scheduled above the desired number of - pods. - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - description: The maximum number of pods that can be unavailable - during the update. - x-kubernetes-int-or-string: true - type: object - type: - description: Type of deployment. Can be "Recreate" or "RollingUpdate". - Default is RollingUpdate. - type: string - type: object - disableInitContainers: - description: Disable the 'feast repo initialization' initContainer - type: boolean - offlineStore: - description: OfflineStore configures the offline store service - properties: - persistence: - description: OfflineStorePersistence configures the persistence - settings for the offline store service - properties: - file: - description: OfflineStoreFilePersistence configures the - file-based persistence for the offline store service - properties: - pvc: - description: PvcConfig defines the settings for a - persistent file store based on PVCs. - properties: - create: - description: Settings for creating a new PVC - properties: - accessModes: - description: AccessModes k8s persistent volume - access modes. Defaults to ["ReadWriteOnce"]. - items: - type: string - type: array - resources: - description: Resources describes the storage - resource requirements for a volume. + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but... + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true + key: + description: The label key that the selector + applies to. + type: string + operator: description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the minimum - amount of compute resources required. - type: object + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator type: object - storageClassName: - description: StorageClassName is the name - of an existing StorageClass to which this - persistent volume belongs. - type: string - type: object - x-kubernetes-validations: - - message: PvcCreate is immutable - rule: self == oldSelf - mountPath: - description: |- - MountPath within the container at which the volume should be mounted. - Must start by "/" and cannot contain ':'. - type: string - ref: - description: Reference to an existing field - properties: - name: - default: "" + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - mountPath - type: object - x-kubernetes-validations: - - message: One selection is required between ref and - create. - rule: '[has(self.ref), has(self.create)].exists_one(c, - c)' - - message: Mount path must start with '/' and must - not contain ':' - rule: self.mountPath.matches('^/[^:]*$') - type: - enum: - - file - - dask - - duckdb - type: string - type: object - store: - description: OfflineStoreDBStorePersistence configures - the DB store persistence for the offline store service + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto... properties: - secretKeyName: - description: By default, the selected store "type" - is used as the SecretKeyName - type: string - secretRef: - description: Data store parameters should be placed - as-is from the "feature_store.yaml" under the secret - key. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - type: - description: Type of the persistence type you want - to use. - enum: - - snowflake.offline - - bigquery - - redshift - - spark - - postgres - - trino - - athena - - mssql - - couchbase.offline - - clickhouse - - ray - type: string + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic required: - - secretRef - - type + - nodeSelectorTerms type: object + x-kubernetes-map-type: atomic type: object - x-kubernetes-validations: - - message: One selection required between file or store. - rule: '[has(self.file), has(self.store)].exists_one(c, c)' - server: - description: Creates a remote offline server container + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). properties: - env: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but... items: - description: EnvVar represents an environment variable - present in a Container. + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) properties: - name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: 'Selects a field of the pod: supports - metadata.name, metadata.namespace, `metadata.labels['''']`, - `metadata.' - properties: - apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: + labelSelector: description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits. + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: - containerName: - description: 'Container name: required for - volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults to - "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object type: object x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the - pod's namespace + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. properties: - key: - description: The key of the secret to select - from. Must be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object type: object x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in... + type: string + required: + - topologyKey type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer required: - - name + - podAffinityTerm + - weight type: object type: array - envFrom: + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto... items: - description: EnvFromSource represents the source of - a set of ConfigMaps + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should... properties: - configMapRef: - description: The ConfigMap to select from + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the ConfigMap must - be defined - type: boolean + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object type: object x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the Secret must - be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in... + type: string + required: + - topologyKey + type: object type: array - image: - type: string - imagePullPolicy: - description: PullPolicy describes a policy for if/when - to pull a container image - type: string - logLevel: + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + properties: + preferredDuringSchedulingIgnoredDuringExecution: description: |- - LogLevel sets the logging level for the server - Allowed values: "debug", "info", "warning", "error", "critical". - enum: - - debug - - info - - warning - - error - - critical - type: string - metrics: - description: Metrics exposes Prometheus-compatible metrics - for the Feast server when enabled. - type: boolean - nodeSelector: - additionalProperties: - type: string - type: object - resources: - description: ResourceRequirements describes the compute - resource requirements. - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field,... + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. properties: - name: + labelSelector: description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in... type: string required: - - name + - topologyKey type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the minimum amount - of compute resources required. - type: object - type: object - tls: - description: TlsConfigs configures server TLS for a feast - service. - properties: - disable: - description: will disable TLS for the feast service. - useful in an openshift cluster, for example, where - TLS is configured by default - type: boolean - secretKeyNames: - description: SecretKeyNames defines the secret key - names for the TLS key and cert. - properties: - tlsCrt: - description: defaults to "tls.crt" - type: string - tlsKey: - description: defaults to "tls.key" - type: string - type: object - secretRef: - description: references the local k8s secret where - the TLS key and cert reside - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' - volumeMounts: - description: VolumeMounts defines the list of volumes - that should be mounted into the feast container. + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled... items: - description: VolumeMount describes a mounting of a Volume - within a container. + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should... properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: + labelSelector: description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. - type: string - subPath: + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: Expanded path within the volume from - which the container's volume should be mounted. + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in... type: string required: - - mountPath - - name + - topologyKey type: object type: array - workerConfigs: - description: WorkerConfigs defines the worker configuration - for the Feast server. - properties: - keepAliveTimeout: - description: |- - KeepAliveTimeout is the timeout for keep-alive connections in seconds. - Defaults to 30. - format: int32 - minimum: 1 - type: integer - maxRequests: - description: |- - MaxRequests is the maximum number of requests a worker will process before restarting. - This helps prevent memory leaks. - format: int32 - minimum: 0 - type: integer - maxRequestsJitter: - description: |- - MaxRequestsJitter is the maximum jitter to add to max-requests to prevent - thundering herd effect on worker restart. - format: int32 - minimum: 0 - type: integer - registryTTLSeconds: - description: RegistryTTLSeconds is the number of seconds - after which the registry is refreshed. - format: int32 - minimum: 0 - type: integer - workerConnections: - description: |- - WorkerConnections is the maximum number of simultaneous clients per worker process. - Defaults to 1000. - format: int32 - minimum: 1 - type: integer - workers: - description: Workers is the number of worker processes. - Use -1 to auto-calculate based on CPU cores (2 * - CPU + 1). - format: int32 - minimum: -1 - type: integer - type: object + x-kubernetes-list-type: atomic type: object type: object - onlineStore: - description: OnlineStore configures the online store service + deploymentStrategy: + description: DeploymentStrategy describes how to replace existing + pods with new ones. + properties: + rollingUpdate: + description: |- + Rolling update config params. Present only if DeploymentStrategyType = + RollingUpdate. + properties: + maxSurge: + anyOf: + - type: integer + - type: string + description: |- + The maximum number of pods that can be scheduled above the desired number of + pods. + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + description: The maximum number of pods that can be unavailable + during the update. + x-kubernetes-int-or-string: true + type: object + type: + description: Type of deployment. Can be "Recreate" or "RollingUpdate". + Default is RollingUpdate. + type: string + type: object + disableInitContainers: + description: Disable the 'feast repo initialization' initContainer + type: boolean + offlineStore: + description: OfflineStore configures the offline store service properties: persistence: - description: OnlineStorePersistence configures the persistence - settings for the online store service + description: OfflineStorePersistence configures the persistence + settings for the offline store service properties: file: - description: OnlineStoreFilePersistence configures the - file-based persistence for the online store service + description: OfflineStoreFilePersistence configures the + file-based persistence for the offline store service properties: - path: - type: string pvc: description: PvcConfig defines the settings for a persistent file store based on PVCs. @@ -1335,21 +1617,16 @@ spec: - message: Mount path must start with '/' and must not contain ':' rule: self.mountPath.matches('^/[^:]*$') + type: + enum: + - file + - dask + - duckdb + type: string type: object - x-kubernetes-validations: - - message: Ephemeral stores must have absolute paths. - rule: '(!has(self.pvc) && has(self.path)) ? self.path.startsWith(''/'') - : true' - - message: PVC path must be a file name only, with no - slashes. - rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') - : true' - - message: Online store does not support S3 or GS buckets. - rule: 'has(self.path) ? !(self.path.startsWith(''s3://'') - || self.path.startsWith(''gs://'')) : true' store: - description: OnlineStoreDBStorePersistence configures - the DB store persistence for the online store service + description: OfflineStoreDBStorePersistence configures + the DB store persistence for the offline store service properties: secretKeyName: description: By default, the selected store "type" @@ -1373,23 +1650,18 @@ spec: description: Type of the persistence type you want to use. enum: - - snowflake.online - - redis - - ikv - - datastore - - dynamodb - - bigtable + - snowflake.offline + - bigquery + - redshift + - spark - postgres - - cassandra - - mysql - - hazelcast - - singlestore - - hbase - - elasticsearch - - qdrant - - couchbase.online - - milvus - - hybrid + - trino + - athena + - mssql + - couchbase.offline + - clickhouse + - ray + - oracle type: string required: - secretRef @@ -1400,7 +1672,7 @@ spec: - message: One selection required between file or store. rule: '[has(self.file), has(self.store)].exists_one(c, c)' server: - description: Creates a feature server container + description: Creates a remote offline server container properties: env: items: @@ -1414,8 +1686,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -1515,7 +1786,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -1534,8 +1805,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -1597,6 +1868,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen for + a request in the referenced claim. + type: string required: - name type: object @@ -1756,151 +2031,74 @@ spec: type: object type: object type: object - registry: - description: Registry configures the registry service. One selection - is required. Local is the default setting. + onlineStore: + description: OnlineStore configures the online store service properties: - local: - description: LocalRegistryConfig configures the registry service + persistence: + description: OnlineStorePersistence configures the persistence + settings for the online store service properties: - persistence: - description: RegistryPersistence configures the persistence - settings for the registry service + file: + description: OnlineStoreFilePersistence configures the + file-based persistence for the online store service properties: - file: - description: RegistryFilePersistence configures the - file-based persistence for the registry service + path: + type: string + pvc: + description: PvcConfig defines the settings for a + persistent file store based on PVCs. properties: - cache_mode: - description: |- - CacheMode defines the registry cache update strategy. - Allowed values are "sync" and "thread". - enum: - - none - - sync - - thread - type: string - cache_ttl_seconds: - description: CacheTTLSeconds defines the TTL (in - seconds) for the registry cache. - format: int32 - minimum: 0 - type: integer - path: - type: string - pvc: - description: PvcConfig defines the settings for - a persistent file store based on PVCs. + create: + description: Settings for creating a new PVC properties: - create: - description: Settings for creating a new PVC + accessModes: + description: AccessModes k8s persistent volume + access modes. Defaults to ["ReadWriteOnce"]. + items: + type: string + type: array + resources: + description: Resources describes the storage + resource requirements for a volume. properties: - accessModes: - description: AccessModes k8s persistent - volume access modes. Defaults to ["ReadWriteOnce"]. - items: - type: string - type: array - resources: - description: Resources describes the storage - resource requirements for a volume. - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the - minimum amount of compute resources - required. - type: object + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum + amount of compute resources required. type: object - storageClassName: - description: StorageClassName is the name - of an existing StorageClass to which - this persistent volume belongs. - type: string type: object - x-kubernetes-validations: - - message: PvcCreate is immutable - rule: self == oldSelf - mountPath: - description: |- - MountPath within the container at which the volume should be mounted. - Must start by "/" and cannot contain ':'. + storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which this + persistent volume belongs. type: string - ref: - description: Reference to an existing field - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - mountPath type: object x-kubernetes-validations: - - message: One selection is required between ref - and create. - rule: '[has(self.ref), has(self.create)].exists_one(c, - c)' - - message: Mount path must start with '/' and - must not contain ':' - rule: self.mountPath.matches('^/[^:]*$') - s3_additional_kwargs: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-validations: - - message: Registry files must use absolute paths - or be S3 ('s3://') or GS ('gs://') object store - URIs. - rule: '(!has(self.pvc) && has(self.path)) ? (self.path.startsWith(''/'') - || self.path.startsWith(''s3://'') || self.path.startsWith(''gs://'')) - : true' - - message: PVC path must be a file name only, with - no slashes. - rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') - : true' - - message: PVC persistence does not support S3 or - GS object store URIs. - rule: '(has(self.pvc) && has(self.path)) ? !(self.path.startsWith(''s3://'') - || self.path.startsWith(''gs://'')) : true' - - message: Additional S3 settings are available only - for S3 object store URIs. - rule: '(has(self.s3_additional_kwargs) && has(self.path)) - ? self.path.startsWith(''s3://'') : true' - store: - description: RegistryDBStorePersistence configures - the DB store persistence for the registry service - properties: - secretKeyName: - description: By default, the selected store "type" - is used as the SecretKeyName + - message: PvcCreate is immutable + rule: self == oldSelf + mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. type: string - secretRef: - description: Data store parameters should be placed - as-is from the "feature_store.yaml" under the - secret key. + ref: + description: Reference to an existing field properties: name: default: "" @@ -1911,146 +2109,108 @@ spec: type: string type: object x-kubernetes-map-type: atomic - type: - description: Type of the persistence type you - want to use. - enum: - - sql - - snowflake.registry - type: string required: - - secretRef - - type + - mountPath type: object + x-kubernetes-validations: + - message: One selection is required between ref and + create. + rule: '[has(self.ref), has(self.create)].exists_one(c, + c)' + - message: Mount path must start with '/' and must + not contain ':' + rule: self.mountPath.matches('^/[^:]*$') type: object x-kubernetes-validations: - - message: One selection required between file or store. - rule: '[has(self.file), has(self.store)].exists_one(c, - c)' - server: - description: Creates a registry server container + - message: Ephemeral stores must have absolute paths. + rule: '(!has(self.pvc) && has(self.path)) ? self.path.startsWith(''/'') + : true' + - message: PVC path must be a file name only, with no + slashes. + rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') + : true' + - message: Online store does not support S3 or GS buckets. + rule: 'has(self.path) ? !(self.path.startsWith(''s3://'') + || self.path.startsWith(''gs://'')) : true' + store: + description: OnlineStoreDBStorePersistence configures + the DB store persistence for the online store service properties: - env: - items: - description: EnvVar represents an environment variable - present in a Container. + secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName + type: string + secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the secret + key. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + type: + description: Type of the persistence type you want + to use. + enum: + - snowflake.online + - redis + - datastore + - dynamodb + - bigtable + - postgres + - cassandra + - mysql + - hazelcast + - singlestore + - hbase + - elasticsearch + - qdrant + - couchbase.online + - milvus + - hybrid + - mongodb + type: string + required: + - secretRef + - type + type: object + type: object + x-kubernetes-validations: + - message: One selection required between file or store. + rule: '[has(self.file), has(self.store)].exists_one(c, c)' + server: + description: Creates a feature server container + properties: + env: + items: + description: EnvVar represents an environment variable + present in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and... + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: 'Selects a field of the pod: - supports metadata.name, metadata.namespace, - `metadata.labels['''']`, `metadata.' - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, - defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults - to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - items: - description: EnvFromSource represents the source - of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from + configMapKeyRef: + description: Selects a key of a ConfigMap. properties: + key: + description: The key to select. + type: string name: default: "" description: |- @@ -2060,17 +2220,62 @@ spec: type: string optional: description: Specify whether the ConfigMap - must be defined + or its key must be defined type: boolean + required: + - key type: object x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from + fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. + properties: + containerName: + description: 'Container name: required for + volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the + pod's namespace properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string name: default: "" description: |- @@ -2080,1352 +2285,1830 @@ spec: type: string optional: description: Specify whether the Secret - must be defined + or its key must be defined type: boolean + required: + - key type: object x-kubernetes-map-type: atomic type: object - type: array - grpc: - description: Enable gRPC registry server. Defaults - to true if unset. - type: boolean - image: - type: string - imagePullPolicy: - description: PullPolicy describes a policy for if/when - to pull a container image - type: string - logLevel: - description: |- - LogLevel sets the logging level for the server - Allowed values: "debug", "info", "warning", "error", "critical". - enum: - - debug - - info - - warning - - error - - critical - type: string - metrics: - description: Metrics exposes Prometheus-compatible - metrics for the Feast server when enabled. - type: boolean - nodeSelector: - additionalProperties: + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source of + a set of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string - type: object - resources: - description: ResourceRequirements describes the compute - resource requirements. - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the minimum amount - of compute resources required. - type: object - type: object - restAPI: - description: Enable REST API registry server. - type: boolean - tls: - description: TlsConfigs configures server TLS for - a feast service. - properties: - disable: - description: will disable TLS for the feast service. - useful in an openshift cluster, for example, - where TLS is configured by default - type: boolean - secretKeyNames: - description: SecretKeyNames defines the secret - key names for the TLS key and cert. - properties: - tlsCrt: - description: defaults to "tls.crt" - type: string - tlsKey: - description: defaults to "tls.key" - type: string - type: object - secretRef: - description: references the local k8s secret where - the TLS key and cert reside - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' - volumeMounts: - description: VolumeMounts defines the list of volumes - that should be mounted into the feast container. - items: - description: VolumeMount describes a mounting of - a Volume within a container. + secretRef: + description: The Secret to select from properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - type: string name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: + default: "" description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string - subPath: + optional: + description: Specify whether the Secret must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image + type: string + logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". + enum: + - debug + - info + - warning + - error + - critical + type: string + metrics: + description: Metrics exposes Prometheus-compatible metrics + for the Feast server when enabled. + type: boolean + nodeSelector: + additionalProperties: + type: string + type: object + resources: + description: ResourceRequirements describes the compute + resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string - subPathExpr: - description: Expanded path within the volume - from which the container's volume should be - mounted. + request: + description: Request is the name chosen for + a request in the referenced claim. type: string required: - - mountPath - name type: object type: array - workerConfigs: - description: WorkerConfigs defines the worker configuration - for the Feast server. + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount + of compute resources required. + type: object + type: object + tls: + description: TlsConfigs configures server TLS for a feast + service. + properties: + disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, where + TLS is configured by default + type: boolean + secretKeyNames: + description: SecretKeyNames defines the secret key + names for the TLS key and cert. properties: - keepAliveTimeout: - description: |- - KeepAliveTimeout is the timeout for keep-alive connections in seconds. - Defaults to 30. - format: int32 - minimum: 1 - type: integer - maxRequests: - description: |- - MaxRequests is the maximum number of requests a worker will process before restarting. - This helps prevent memory leaks. - format: int32 - minimum: 0 - type: integer - maxRequestsJitter: - description: |- - MaxRequestsJitter is the maximum jitter to add to max-requests to prevent - thundering herd effect on worker restart. - format: int32 - minimum: 0 - type: integer - registryTTLSeconds: - description: RegistryTTLSeconds is the number - of seconds after which the registry is refreshed. - format: int32 - minimum: 0 - type: integer - workerConnections: + tlsCrt: + description: defaults to "tls.crt" + type: string + tlsKey: + description: defaults to "tls.key" + type: string + type: object + secretRef: + description: references the local k8s secret where + the TLS key and cert reside + properties: + name: + default: "" description: |- - WorkerConnections is the maximum number of simultaneous clients per worker process. - Defaults to 1000. - format: int32 - minimum: 1 - type: integer - workers: - description: Workers is the number of worker processes. - Use -1 to auto-calculate based on CPU cores - (2 * CPU + 1). - format: int32 - minimum: -1 - type: integer + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string type: object + x-kubernetes-map-type: atomic type: object x-kubernetes-validations: - - message: At least one of restAPI or grpc must be true - rule: self.restAPI == true || self.grpc == true || !has(self.grpc) - type: object - remote: - description: RemoteRegistryConfig points to a remote feast - registry server. - properties: - feastRef: - description: Reference to an existing `FeatureStore` CR - in the same k8s cluster. - properties: - name: - description: Name of the FeatureStore - type: string - namespace: - description: Namespace of the FeatureStore - type: string - required: - - name - type: object - hostname: - description: Host address of the remote registry service - - :, e.g. `registry..svc.cluster.local:80` - type: string - tls: - description: TlsRemoteRegistryConfigs configures client - TLS for a remote feast registry. + - message: '`secretRef` required if `disable` is false.' + rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) + : true' + volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. + type: string + required: + - mountPath + - name + type: object + type: array + workerConfigs: + description: WorkerConfigs defines the worker configuration + for the Feast server. properties: - certName: - description: defines the configmap key name for the - client TLS cert. - type: string - configMapRef: - description: references the local k8s configmap where - the TLS cert resides - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - certName - - configMapRef + keepAliveTimeout: + description: |- + KeepAliveTimeout is the timeout for keep-alive connections in seconds. + Defaults to 30. + format: int32 + minimum: 1 + type: integer + maxRequests: + description: |- + MaxRequests is the maximum number of requests a worker will process before restarting. + This helps prevent memory leaks. + format: int32 + minimum: 0 + type: integer + maxRequestsJitter: + description: |- + MaxRequestsJitter is the maximum jitter to add to max-requests to prevent + thundering herd effect on worker restart. + format: int32 + minimum: 0 + type: integer + registryTTLSeconds: + description: RegistryTTLSeconds is the number of seconds + after which the registry is refreshed. + format: int32 + minimum: 0 + type: integer + workerConnections: + description: |- + WorkerConnections is the maximum number of simultaneous clients per worker process. + Defaults to 1000. + format: int32 + minimum: 1 + type: integer + workers: + description: Workers is the number of worker processes. + Use -1 to auto-calculate based on CPU cores (2 * + CPU + 1). + format: int32 + minimum: -1 + type: integer type: object type: object - x-kubernetes-validations: - - message: One selection required. - rule: '[has(self.hostname), has(self.feastRef)].exists_one(c, - c)' + type: object + podAnnotations: + additionalProperties: + type: string + description: PodAnnotations are annotations to be applied to the + Deployment's PodTemplate metadata. + type: object + podDisruptionBudgets: + description: PodDisruptionBudgets configures a PodDisruptionBudget + for the FeatureStore deployment. + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: MaxUnavailable specifies the maximum number/percentage + of pods that can be unavailable. + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + description: MinAvailable specifies the minimum number/percentage + of pods that must remain available. + x-kubernetes-int-or-string: true type: object x-kubernetes-validations: - - message: One selection required. - rule: '[has(self.local), has(self.remote)].exists_one(c, c)' - securityContext: - description: PodSecurityContext holds pod-level security attributes - and common container settings. + - message: Exactly one of minAvailable or maxUnavailable must + be set. + rule: '[has(self.minAvailable), has(self.maxUnavailable)].exists_one(c, + c)' + registry: + description: Registry configures the registry service. One selection + is required. Local is the default setting. properties: - appArmorProfile: - description: appArmorProfile is the AppArmor options to use - by the containers in this pod. - properties: - localhostProfile: - description: localhostProfile indicates a profile loaded - on the node that should be used. - type: string - type: - description: type indicates which kind of AppArmor profile - will be applied. - type: string - required: - - type - type: object - fsGroup: - description: A special supplemental group that applies to - all containers in a pod. - format: int64 - type: integer - fsGroupChangePolicy: - description: |- - fsGroupChangePolicy defines behavior of changing ownership and permission of the volume - before being exposed inside Pod. - type: string - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - format: int64 - type: integer - runAsNonRoot: - description: Indicates that the container must run as a non-root - user. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - format: int64 - type: integer - seLinuxOptions: - description: The SELinux context to be applied to all containers. - properties: - level: - description: Level is SELinux level label that applies - to the container. - type: string - role: - description: Role is a SELinux role label that applies - to the container. - type: string - type: - description: Type is a SELinux type label that applies - to the container. - type: string - user: - description: User is a SELinux user label that applies - to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by the containers in this pod. - Note that this field cannot be set when spec.os. - properties: - localhostProfile: - description: localhostProfile indicates a profile defined - in a file on the node should be used. - type: string - type: - description: type indicates which kind of seccomp profile - will be applied. - type: string - required: - - type - type: object - supplementalGroups: - description: |- - A list of groups applied to the first process run in each container, in addition - to the container's primary GID, the fsG - items: - format: int64 - type: integer - type: array - x-kubernetes-list-type: atomic - sysctls: - description: Sysctls hold a list of namespaced sysctls used - for the pod. - items: - description: Sysctl defines a kernel parameter to be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - windowsOptions: - description: The Windows specific settings applied to all - containers. + local: + description: LocalRegistryConfig configures the registry service properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name of the - GMSA credential spec to use. - type: string - hostProcess: - description: HostProcess determines if a container should - be run as a 'Host Process' container. - type: boolean - runAsUserName: - description: The UserName in Windows to run the entrypoint - of the container process. - type: string - type: object - type: object - ui: - description: Creates a UI server container - properties: - env: - items: - description: EnvVar represents an environment variable present - in a Container. - properties: - name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any - type: string - valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + persistence: + description: RegistryPersistence configures the persistence + settings for the registry service + properties: + file: + description: RegistryFilePersistence configures the + file-based persistence for the registry service + properties: + cache_mode: + description: |- + CacheMode defines the registry cache update strategy. + Allowed values are "sync" and "thread". + enum: + - none + - sync + - thread + type: string + cache_ttl_seconds: + description: CacheTTLSeconds defines the TTL (in + seconds) for the registry cache. + format: int32 + minimum: 0 + type: integer + path: + type: string + pvc: + description: PvcConfig defines the settings for + a persistent file store based on PVCs. + properties: + create: + description: Settings for creating a new PVC + properties: + accessModes: + description: AccessModes k8s persistent + volume access modes. Defaults to ["ReadWriteOnce"]. + items: + type: string + type: array + resources: + description: Resources describes the storage + resource requirements for a volume. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the + minimum amount of compute resources + required. + type: object + type: object + storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which + this persistent volume belongs. + type: string + type: object + x-kubernetes-validations: + - message: PvcCreate is immutable + rule: self == oldSelf + mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. + type: string + ref: + description: Reference to an existing field + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + required: + - mountPath + type: object + x-kubernetes-validations: + - message: One selection is required between ref + and create. + rule: '[has(self.ref), has(self.create)].exists_one(c, + c)' + - message: Mount path must start with '/' and + must not contain ':' + rule: self.mountPath.matches('^/[^:]*$') + s3_additional_kwargs: + additionalProperties: type: string - optional: - description: Specify whether the ConfigMap or - its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: 'Selects a field of the pod: supports - metadata.name, metadata.namespace, `metadata.labels['''']`, - `metadata.' + type: object + type: object + x-kubernetes-validations: + - message: Registry files must use absolute paths + or be S3 ('s3://') or GS ('gs://') object store + URIs. + rule: '(!has(self.pvc) && has(self.path)) ? (self.path.startsWith(''/'') + || self.path.startsWith(''s3://'') || self.path.startsWith(''gs://'')) + : true' + - message: PVC path must be a file name only, with + no slashes. + rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') + : true' + - message: PVC persistence does not support S3 or + GS object store URIs. + rule: '(has(self.pvc) && has(self.path)) ? !(self.path.startsWith(''s3://'') + || self.path.startsWith(''gs://'')) : true' + - message: Additional S3 settings are available only + for S3 object store URIs. + rule: '(has(self.s3_additional_kwargs) && has(self.path)) + ? self.path.startsWith(''s3://'') : true' + store: + description: RegistryDBStorePersistence configures + the DB store persistence for the registry service + properties: + secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName + type: string + secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the + secret key. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + type: + description: Type of the persistence type you + want to use. + enum: + - sql + - snowflake.registry + type: string + required: + - secretRef + - type + type: object + type: object + x-kubernetes-validations: + - message: One selection required between file or store. + rule: '[has(self.file), has(self.store)].exists_one(c, + c)' + server: + description: Creates a registry server container + properties: + env: + items: + description: EnvVar represents an environment variable + present in a Container. properties: - apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in - the specified API version. + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits. - properties: - containerName: - description: 'Container name: required for volumes, - optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and... type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: + supports metadata.name, metadata.namespace, + `metadata.labels['''']`, `metadata.' + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, + defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults + to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in + the pod's namespace + properties: + key: + description: The key of the secret to + select from. Must be a valid secret + key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object required: - - resource + - name type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the pod's - namespace + type: array + envFrom: + items: + description: EnvFromSource represents the source + of a set of ConfigMaps or Secrets properties: - key: - description: The key of the secret to select - from. Must be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the + name of each environment variable. Must be + a C_IDENTIFIER. type: string - optional: - description: Specify whether the Secret or its - key must be defined - type: boolean - required: - - key + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - items: - description: EnvFromSource represents the source of a set - of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the ConfigMap must - be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + type: array + grpc: + description: Enable gRPC registry server. Defaults + to true if unset. + type: boolean + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image + type: string + logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". + enum: + - debug + - info + - warning + - error + - critical + type: string + metrics: + description: Metrics exposes Prometheus-compatible + metrics for the Feast server when enabled. + type: boolean + nodeSelector: + additionalProperties: type: string - optional: - description: Specify whether the Secret must be - defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - type: string - imagePullPolicy: - description: PullPolicy describes a policy for if/when to - pull a container image - type: string - logLevel: - description: |- - LogLevel sets the logging level for the server - Allowed values: "debug", "info", "warning", "error", "critical". - enum: - - debug - - info - - warning - - error - - critical - type: string - metrics: - description: Metrics exposes Prometheus-compatible metrics - for the Feast server when enabled. - type: boolean - nodeSelector: - additionalProperties: - type: string - type: object - resources: - description: ResourceRequirements describes the compute resource - requirements. - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the minimum amount of - compute resources required. + type: object + resources: + description: ResourceRequirements describes the compute + resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. + type: string + request: + description: Request is the name chosen + for a request in the referenced claim. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount + of compute resources required. + type: object + type: object + restAPI: + description: Enable REST API registry server. + type: boolean + tls: + description: TlsConfigs configures server TLS for + a feast service. + properties: + disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, + where TLS is configured by default + type: boolean + secretKeyNames: + description: SecretKeyNames defines the secret + key names for the TLS key and cert. + properties: + tlsCrt: + description: defaults to "tls.crt" + type: string + tlsKey: + description: defaults to "tls.key" + type: string + type: object + secretRef: + description: references the local k8s secret where + the TLS key and cert reside + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: '`secretRef` required if `disable` is false.' + rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) + : true' + volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. + items: + description: VolumeMount describes a mounting of + a Volume within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume + from which the container's volume should be + mounted. + type: string + required: + - mountPath + - name + type: object + type: array + workerConfigs: + description: WorkerConfigs defines the worker configuration + for the Feast server. + properties: + keepAliveTimeout: + description: |- + KeepAliveTimeout is the timeout for keep-alive connections in seconds. + Defaults to 30. + format: int32 + minimum: 1 + type: integer + maxRequests: + description: |- + MaxRequests is the maximum number of requests a worker will process before restarting. + This helps prevent memory leaks. + format: int32 + minimum: 0 + type: integer + maxRequestsJitter: + description: |- + MaxRequestsJitter is the maximum jitter to add to max-requests to prevent + thundering herd effect on worker restart. + format: int32 + minimum: 0 + type: integer + registryTTLSeconds: + description: RegistryTTLSeconds is the number + of seconds after which the registry is refreshed. + format: int32 + minimum: 0 + type: integer + workerConnections: + description: |- + WorkerConnections is the maximum number of simultaneous clients per worker process. + Defaults to 1000. + format: int32 + minimum: 1 + type: integer + workers: + description: Workers is the number of worker processes. + Use -1 to auto-calculate based on CPU cores + (2 * CPU + 1). + format: int32 + minimum: -1 + type: integer + type: object type: object + x-kubernetes-validations: + - message: At least one of restAPI or grpc must be true + rule: self.restAPI == true || self.grpc == true || !has(self.grpc) type: object - tls: - description: TlsConfigs configures server TLS for a feast - service. + remote: + description: RemoteRegistryConfig points to a remote feast + registry server. properties: - disable: - description: will disable TLS for the feast service. useful - in an openshift cluster, for example, where TLS is configured - by default - type: boolean - secretKeyNames: - description: SecretKeyNames defines the secret key names - for the TLS key and cert. + feastRef: + description: Reference to an existing `FeatureStore` CR + in the same k8s cluster. properties: - tlsCrt: - description: defaults to "tls.crt" + name: + description: Name of the FeatureStore type: string - tlsKey: - description: defaults to "tls.key" + namespace: + description: Namespace of the FeatureStore type: string + required: + - name type: object - secretRef: - description: references the local k8s secret where the - TLS key and cert reside + hostname: + description: Host address of the remote registry service + - :, e.g. `registry..svc.cluster.local:80` + type: string + tls: + description: TlsRemoteRegistryConfigs configures client + TLS for a remote feast registry. properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + certName: + description: defines the configmap key name for the + client TLS cert. type: string + configMapRef: + description: references the local k8s configmap where + the TLS cert resides + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + required: + - certName + - configMapRef type: object - x-kubernetes-map-type: atomic type: object x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' - volumeMounts: - description: VolumeMounts defines the list of volumes that - should be mounted into the feast container. - items: - description: VolumeMount describes a mounting of a Volume - within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: - description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. - type: string - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: Expanded path within the volume from which - the container's volume should be mounted. - type: string - required: - - mountPath - - name - type: object - type: array - workerConfigs: - description: WorkerConfigs defines the worker configuration - for the Feast server. + - message: One selection required. + rule: '[has(self.hostname), has(self.feastRef)].exists_one(c, + c)' + type: object + x-kubernetes-validations: + - message: One selection required. + rule: '[has(self.local), has(self.remote)].exists_one(c, c)' + runFeastApplyOnInit: + description: Runs feast apply on pod start to populate the registry. + Defaults to true. Ignored when DisableInitContainers is true. + type: boolean + scaling: + description: Scaling configures horizontal scaling for the FeatureStore + deployment (e.g. HPA autoscaling). + properties: + autoscaling: + description: |- + Autoscaling configures a HorizontalPodAutoscaler for the FeatureStore deployment. + Mutually exclusive with spec.replicas. properties: - keepAliveTimeout: - description: |- - KeepAliveTimeout is the timeout for keep-alive connections in seconds. - Defaults to 30. - format: int32 - minimum: 1 - type: integer - maxRequests: - description: |- - MaxRequests is the maximum number of requests a worker will process before restarting. - This helps prevent memory leaks. - format: int32 - minimum: 0 - type: integer - maxRequestsJitter: - description: |- - MaxRequestsJitter is the maximum jitter to add to max-requests to prevent - thundering herd effect on worker restart. - format: int32 - minimum: 0 - type: integer - registryTTLSeconds: - description: RegistryTTLSeconds is the number of seconds - after which the registry is refreshed. - format: int32 - minimum: 0 - type: integer - workerConnections: - description: |- - WorkerConnections is the maximum number of simultaneous clients per worker process. - Defaults to 1000. + behavior: + description: Behavior configures the scaling behavior + of the target. + properties: + scaleDown: + description: scaleDown is scaling policy for scaling + Down. + properties: + policies: + description: policies is a list of potential scaling + polices which can be used during scaling. + items: + description: HPAScalingPolicy is a single policy + which must hold true for a specified past + interval. + properties: + periodSeconds: + description: periodSeconds specifies the + window of time for which the policy should + hold true. + format: int32 + type: integer + type: + description: type is used to specify the + scaling policy. + type: string + value: + description: |- + value contains the amount of change which is permitted by the policy. + It must be greater than zero + format: int32 + type: integer + required: + - periodSeconds + - type + - value + type: object + type: array + x-kubernetes-list-type: atomic + selectPolicy: + description: |- + selectPolicy is used to specify which policy should be used. + If not set, the default value Max is used. + type: string + stabilizationWindowSeconds: + description: |- + stabilizationWindowSeconds is the number of seconds for which past recommendations should be + considered while scaling... + format: int32 + type: integer + tolerance: + anyOf: + - type: integer + - type: string + description: |- + tolerance is the tolerance on the ratio between the current and desired + metric value under which no updates are made to... + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + scaleUp: + description: scaleUp is scaling policy for scaling + Up. + properties: + policies: + description: policies is a list of potential scaling + polices which can be used during scaling. + items: + description: HPAScalingPolicy is a single policy + which must hold true for a specified past + interval. + properties: + periodSeconds: + description: periodSeconds specifies the + window of time for which the policy should + hold true. + format: int32 + type: integer + type: + description: type is used to specify the + scaling policy. + type: string + value: + description: |- + value contains the amount of change which is permitted by the policy. + It must be greater than zero + format: int32 + type: integer + required: + - periodSeconds + - type + - value + type: object + type: array + x-kubernetes-list-type: atomic + selectPolicy: + description: |- + selectPolicy is used to specify which policy should be used. + If not set, the default value Max is used. + type: string + stabilizationWindowSeconds: + description: |- + stabilizationWindowSeconds is the number of seconds for which past recommendations should be + considered while scaling... + format: int32 + type: integer + tolerance: + anyOf: + - type: integer + - type: string + description: |- + tolerance is the tolerance on the ratio between the current and desired + metric value under which no updates are made to... + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + maxReplicas: + description: MaxReplicas is the upper limit for the number + of replicas. Required. format: int32 minimum: 1 type: integer - workers: - description: Workers is the number of worker processes. - Use -1 to auto-calculate based on CPU cores (2 * CPU - + 1). - format: int32 - minimum: -1 - type: integer - type: object - type: object - volumes: - description: Volumes specifies the volumes to mount in the FeatureStore - deployment. - items: - description: Volume represents a named volume in a pod that - may be accessed by any container in the pod. - properties: - awsElasticBlockStore: - description: |- - awsElasticBlockStore represents an AWS Disk resource that is attached to a - kubelet's host machine and then exposed to th - properties: - fsType: - description: fsType is the filesystem type of the volume - that you want to mount. - type: string - partition: - description: |- - partition is the partition in the volume that you want to mount. - If omitted, the default is to mount by volume name. - format: int32 - type: integer - readOnly: - description: |- - readOnly value true will force the readOnly setting in VolumeMounts. - More info: https://kubernetes. - type: boolean - volumeID: - description: |- - volumeID is unique ID of the persistent disk resource in AWS (Amazon EBS volume). - More info: https://kubernetes. - type: string - required: - - volumeID - type: object - azureDisk: - description: azureDisk represents an Azure Data Disk mount - on the host and bind mount to the pod. - properties: - cachingMode: - description: 'cachingMode is the Host Caching mode: - None, Read Only, Read Write.' - type: string - diskName: - description: diskName is the Name of the data disk in - the blob storage - type: string - diskURI: - description: diskURI is the URI of data disk in the - blob storage - type: string - fsType: - description: |- - fsType is Filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. - type: string - kind: - description: 'kind expected values are Shared: multiple - blob disks per storage account Dedicated: single - blob disk per storage accoun' - type: string - readOnly: - description: |- - readOnly Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - required: - - diskName - - diskURI - type: object - azureFile: - description: azureFile represents an Azure File Service - mount on the host and bind mount to the pod. - properties: - readOnly: + metrics: + description: Metrics contains the specifications for which + to use to calculate the desired replica count. + items: description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretName: - description: secretName is the name of secret that - contains Azure Storage Account Name and Key - type: string - shareName: - description: shareName is the azure share Name - type: string - required: - - secretName - - shareName - type: object - cephfs: - description: cephFS represents a Ceph FS mount on the host - that shares a pod's lifetime - properties: - monitors: - description: |- - monitors is Required: Monitors is a collection of Ceph monitors - More info: https://examples.k8s. - items: - type: string - type: array - x-kubernetes-list-type: atomic - path: - description: 'path is Optional: Used as the mounted - root, rather than the full Ceph tree, default is /' - type: string - readOnly: - description: |- - readOnly is Optional: Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretFile: - description: 'secretFile is Optional: SecretFile is - the path to key ring for User, default is /etc/ceph/user.' - type: string - secretRef: - description: 'secretRef is Optional: SecretRef is reference - to the authentication secret for User, default is - empty.' + MetricSpec specifies how to scale based on a single metric + (only `type` and one other matching field should be set at... properties: - name: - default: "" + containerResource: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - user: - description: |- - user is optional: User is the rados user name, default is admin - More info: https://examples.k8s. - type: string - required: - - monitors - type: object - cinder: - description: |- - cinder represents a cinder volume attached and mounted on kubelets host machine. - More info: https://examples.k8s. - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - type: string - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef is optional: points to a secret object containing parameters used to connect - to OpenStack. - properties: - name: - default: "" + containerResource refers to a resource metric (such as those specified in + requests and limits) known to Kubernetes... + properties: + container: + description: container is the name of the container + in the pods of the scaling target + type: string + name: + description: name is the name of the resource + in question. + type: string + target: + description: target specifies the target value + for the given metric + properties: + averageUtilization: + description: |- + averageUtilization is the target value of the average of the + resource metric across all relevant pods, represented as a... + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether the + metric type is Utilization, Value, or + AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value of + the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - container + - name + - target + type: object + external: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - volumeID: - description: |- - volumeID used to identify the volume in cinder. - More info: https://examples.k8s.io/mysql-cinder-pd/README.md - type: string - required: - - volumeID - type: object - configMap: - description: configMap represents a configMap that should - populate this volume - properties: - defaultMode: - description: 'defaultMode is optional: mode bits used - to set permissions on created files by default.' - format: int32 - type: integer - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volum - items: - description: Maps a string key to a path within a - volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: 'mode is Optional: mode bits used - to set permissions on this file.' - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: optional specify whether the ConfigMap - or its keys must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - csi: - description: csi (Container Storage Interface) represents - ephemeral storage that is handled by certain external - CSI drivers (Beta fea - properties: - driver: - description: driver is the name of the CSI driver that - handles this volume. - type: string - fsType: - description: fsType to mount. Ex. "ext4", "xfs", "ntfs". - type: string - nodePublishSecretRef: - description: |- - nodePublishSecretRef is a reference to the secret object containing - sensitive information to pass to the CSI driver to c - properties: - name: - default: "" + external refers to a global metric that is not associated + with any Kubernetes object. + properties: + metric: + description: metric identifies the target metric + by name and selector + properties: + name: + description: name is the name of the given + metric + type: string + selector: + description: |- + selector is the string-encoded form of a standard kubernetes label selector for the given metric + When set, it is passed... + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - name + type: object + target: + description: target specifies the target value + for the given metric + properties: + averageUtilization: + description: |- + averageUtilization is the target value of the average of the + resource metric across all relevant pods, represented as a... + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether the + metric type is Utilization, Value, or + AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value of + the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - metric + - target + type: object + object: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - readOnly: - description: |- - readOnly specifies a read-only configuration for the volume. - Defaults to false (read/write). - type: boolean - volumeAttributes: - additionalProperties: - type: string - description: |- - volumeAttributes stores driver-specific properties that are passed to the CSI - driver. - type: object - required: - - driver - type: object - downwardAPI: - description: downwardAPI represents downward API about the - pod that should populate this volume - properties: - defaultMode: - description: 'Optional: mode bits to use on created - files by default.' - format: int32 - type: integer - items: - description: Items is a list of downward API volume - file - items: - description: DownwardAPIVolumeFile represents information - to create the file containing the pod field - properties: - fieldRef: - description: 'Required: Selects a field of the - pod: only annotations, labels, name, namespace - and uid are supported.' - properties: - apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in - the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - mode: - description: |- - Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal valu - format: int32 - type: integer - path: - description: 'Required: Path is the relative - path name of the file to be created. Must not - be absolute or contain the ''..'' path.' - type: string - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, requests. - properties: - containerName: - description: 'Container name: required for - volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of - the exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - required: - - path - type: object - type: array - x-kubernetes-list-type: atomic - type: object - emptyDir: - description: |- - emptyDir represents a temporary directory that shares a pod's lifetime. - More info: https://kubernetes. - properties: - medium: - description: medium represents what type of storage - medium should back this directory. - type: string - sizeLimit: - anyOf: - - type: integer - - type: string - description: sizeLimit is the total amount of local - storage required for this EmptyDir volume. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - ephemeral: - description: ephemeral represents a volume that is handled - by a cluster storage driver. - properties: - volumeClaimTemplate: - description: Will be used to create a stand-alone PVC - to provision the volume. - properties: - metadata: - description: |- - May contain labels and annotations that will be copied into the PVC - when creating it. - type: object - spec: - description: The specification for the PersistentVolumeClaim. + object refers to a metric describing a single kubernetes object + (for example, hits-per-second on an Ingress object). properties: - accessModes: - description: |- - accessModes contains the desired access modes the volume should have. - More info: https://kubernetes. - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - description: |- - dataSource field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s. + describedObject: + description: describedObject specifies the descriptions + of a object,such as kind,name apiVersion properties: - apiGroup: - description: APIGroup is the group for the - resource being referenced. + apiVersion: + description: apiVersion is the API version + of the referent type: string kind: - description: Kind is the type of resource - being referenced + description: 'kind is the kind of the referent; + More info: https://git.k8s.' type: string name: - description: Name is the name of resource - being referenced + description: 'name is the name of the referent; + More info: https://kubernetes.' type: string required: - kind - name type: object - x-kubernetes-map-type: atomic - dataSourceRef: - description: |- - dataSourceRef specifies the object from which to populate the volume with data, if a non-empty - volume is desired. + metric: + description: metric identifies the target metric + by name and selector properties: - apiGroup: - description: APIGroup is the group for the - resource being referenced. - type: string - kind: - description: Kind is the type of resource - being referenced - type: string name: - description: Name is the name of resource - being referenced + description: name is the name of the given + metric type: string - namespace: + selector: description: |- - Namespace is the namespace of resource being referenced - Note that when a namespace is specified, a gateway.networking. - type: string + selector is the string-encoded form of a standard kubernetes label selector for the given metric + When set, it is passed... + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic required: - - kind - name type: object - resources: - description: resources represents the minimum - resources the volume should have. + target: + description: target specifies the target value + for the given metric properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true + averageUtilization: description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the minimum - amount of compute resources required. - type: object + averageUtilization is the target value of the average of the + resource metric across all relevant pods, represented as a... + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether the + metric type is Utilization, Value, or + AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value of + the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type type: object - selector: - description: selector is a label query over - volumes to consider for binding. + required: + - describedObject + - metric + - target + type: object + pods: + description: |- + pods refers to a metric describing each pod in the current scale target + (for example,... + properties: + metric: + description: metric identifies the target metric + by name and selector properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: + name: + description: name is the name of the given + metric + type: string + selector: + description: |- + selector is the string-encoded form of a standard kubernetes label selector for the given metric + When set, it is passed... + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. + description: matchLabels is a map of + {key,value} pairs. + type: object type: object + x-kubernetes-map-type: atomic + required: + - name type: object - x-kubernetes-map-type: atomic - storageClassName: - description: |- - storageClassName is the name of the StorageClass required by the claim. - More info: https://kubernetes. - type: string - volumeAttributesClassName: - description: volumeAttributesClassName may be - used to set the VolumeAttributesClass used - by this claim. - type: string - volumeMode: - description: volumeMode defines what type of - volume is required by the claim. - type: string - volumeName: - description: volumeName is the binding reference - to the PersistentVolume backing this claim. + target: + description: target specifies the target value + for the given metric + properties: + averageUtilization: + description: |- + averageUtilization is the target value of the average of the + resource metric across all relevant pods, represented as a... + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether the + metric type is Utilization, Value, or + AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value of + the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - metric + - target + type: object + resource: + description: |- + resource refers to a resource metric (such as those specified in + requests and limits) known to Kubernetes describing... + properties: + name: + description: name is the name of the resource + in question. type: string + target: + description: target specifies the target value + for the given metric + properties: + averageUtilization: + description: |- + averageUtilization is the target value of the average of the + resource metric across all relevant pods, represented as a... + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether the + metric type is Utilization, Value, or + AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value of + the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - name + - target type: object + type: + description: type is the type of metric source. + type: string required: - - spec + - type type: object - type: object - fc: - description: fc represents a Fibre Channel resource that - is attached to a kubelet's host machine and then exposed - to the pod. + type: array + minReplicas: + description: MinReplicas is the lower limit for the number + of replicas. Defaults to 1. + format: int32 + minimum: 1 + type: integer + required: + - maxReplicas + type: object + type: object + securityContext: + description: PodSecurityContext holds pod-level security attributes + and common container settings. + properties: + appArmorProfile: + description: appArmorProfile is the AppArmor options to use + by the containers in this pod. + properties: + localhostProfile: + description: localhostProfile indicates a profile loaded + on the node that should be used. + type: string + type: + description: type indicates which kind of AppArmor profile + will be applied. + type: string + required: + - type + type: object + fsGroup: + description: A special supplemental group that applies to + all containers in a pod. + format: int64 + type: integer + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + format: int64 + type: integer + seLinuxChangePolicy: + description: seLinuxChangePolicy defines how the container's + SELinux label is applied to all volumes used by the Pod. + type: string + seLinuxOptions: + description: The SELinux context to be applied to all containers. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. + type: string + type: + description: type indicates which kind of seccomp profile + will be applied. + type: string + required: + - type + type: object + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in + addition to the container's primary GID and... + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + description: |- + Defines how supplemental groups of the first container processes are calculated. + Valid values are "Merge" and "Strict". + type: string + sysctls: + description: Sysctls hold a list of namespaced sysctls used + for the pod. + items: + description: Sysctl defines a kernel parameter to be set properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. + name: + description: Name of a property to set type: string - lun: - description: 'lun is Optional: FC target lun number' - format: int32 - type: integer - readOnly: - description: |- - readOnly is Optional: Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - targetWWNs: - description: 'targetWWNs is Optional: FC target worldwide - names (WWNs)' - items: - type: string - type: array - x-kubernetes-list-type: atomic - wwids: - description: "wwids Optional: FC volume world wide identifiers - (wwids)\nEither wwids or combination of targetWWNs - and lun must be set, " + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + description: The Windows specific settings applied to all + containers. + properties: + gmsaCredentialSpec: + description: |- + GMSACredentialSpec is where the GMSA admission webhook + (https://github. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. + type: string + type: object + type: object + topologySpreadConstraints: + description: TopologySpreadConstraints defines how pods are spread + across topology domains. + items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. + properties: + labelSelector: + description: LabelSelector is used to find matching pods. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. items: - type: string + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object type: array x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + type: object type: object - flexVolume: + x-kubernetes-map-type: atomic + matchLabelKeys: description: |- - flexVolume represents a generic volume resource that is - provisioned/attached using an exec based plugin. + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. + format: int32 + type: integer + minDomains: + description: MinDomains indicates a minimum number of eligible + domains. + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread... + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. + type: string + topologyKey: + description: TopologyKey is the key of node labels. + type: string + whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + ui: + description: Creates a UI server container + properties: + env: + items: + description: EnvVar represents an environment variable present + in a Container. properties: - driver: - description: driver is the name of the driver to use - for this volume. + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string - fsType: + value: description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and... type: string - options: - additionalProperties: - type: string - description: 'options is Optional: this field holds - extra command options if any.' + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic type: object - readOnly: - description: |- - readOnly is Optional: defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef is Optional: secretRef is reference to the secret object containing - sensitive information to pass to the plugi + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from properties: name: default: "" @@ -3434,164 +4117,359 @@ spec: This field is effectively required, but due to backwards compatibility is allowed to be empty. type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean type: object x-kubernetes-map-type: atomic - required: - - driver - type: object - flocker: - description: flocker represents a Flocker volume attached - to a kubelet's host machine. - properties: - datasetName: - description: |- - datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker - should be considered as depreca - type: string - datasetUUID: - description: datasetUUID is the UUID of the dataset. - This is unique identifier of a Flocker dataset + prefix: + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic type: object - gcePersistentDisk: - description: |- - gcePersistentDisk represents a GCE Disk resource that is attached to a - kubelet's host machine and then exposed to the po - properties: - fsType: - description: fsType is filesystem type of the volume - that you want to mount. - type: string - partition: - description: |- - partition is the partition in the volume that you want to mount. - If omitted, the default is to mount by volume name. - format: int32 - type: integer - pdName: - description: |- - pdName is unique name of the PD resource in GCE. Used to identify the disk in GCE. - More info: https://kubernetes. + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to + pull a container image + type: string + logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". + enum: + - debug + - info + - warning + - error + - critical + type: string + metrics: + description: Metrics exposes Prometheus-compatible metrics + for the Feast server when enabled. + type: boolean + nodeSelector: + additionalProperties: + type: string + type: object + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. + type: string + request: + description: Request is the name chosen for a request + in the referenced claim. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount of + compute resources required. + type: object + type: object + tls: + description: TlsConfigs configures server TLS for a feast + service. + properties: + disable: + description: will disable TLS for the feast service. useful + in an openshift cluster, for example, where TLS is configured + by default + type: boolean + secretKeyNames: + description: SecretKeyNames defines the secret key names + for the TLS key and cert. + properties: + tlsCrt: + description: defaults to "tls.crt" + type: string + tlsKey: + description: defaults to "tls.key" + type: string + type: object + secretRef: + description: references the local k8s secret where the + TLS key and cert reside + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: '`secretRef` required if `disable` is false.' + rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) + : true' + volumeMounts: + description: VolumeMounts defines the list of volumes that + should be mounted into the feast container. + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + type: string + name: + description: This must match the Name of a Volume. type: string readOnly: description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. + Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. - More info: https://kubernetes. type: boolean - required: - - pdName - type: object - gitRepo: - description: |- - gitRepo represents a git repository at a particular revision. - DEPRECATED: GitRepo is deprecated. - properties: - directory: + recursiveReadOnly: description: |- - directory is the target directory name. - Must not contain or start with '..'. If '. + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. type: string - repository: - description: repository is the URL + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). type: string - revision: - description: revision is the commit hash for the specified - revision. + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. type: string required: - - repository + - mountPath + - name type: object - glusterfs: + type: array + workerConfigs: + description: WorkerConfigs defines the worker configuration + for the Feast server. + properties: + keepAliveTimeout: + description: |- + KeepAliveTimeout is the timeout for keep-alive connections in seconds. + Defaults to 30. + format: int32 + minimum: 1 + type: integer + maxRequests: + description: |- + MaxRequests is the maximum number of requests a worker will process before restarting. + This helps prevent memory leaks. + format: int32 + minimum: 0 + type: integer + maxRequestsJitter: + description: |- + MaxRequestsJitter is the maximum jitter to add to max-requests to prevent + thundering herd effect on worker restart. + format: int32 + minimum: 0 + type: integer + registryTTLSeconds: + description: RegistryTTLSeconds is the number of seconds + after which the registry is refreshed. + format: int32 + minimum: 0 + type: integer + workerConnections: + description: |- + WorkerConnections is the maximum number of simultaneous clients per worker process. + Defaults to 1000. + format: int32 + minimum: 1 + type: integer + workers: + description: Workers is the number of worker processes. + Use -1 to auto-calculate based on CPU cores (2 * CPU + + 1). + format: int32 + minimum: -1 + type: integer + type: object + type: object + volumes: + description: Volumes specifies the volumes to mount in the FeatureStore + deployment. + items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. + properties: + awsElasticBlockStore: description: |- - glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. - More info: https://examples.k8s. + awsElasticBlockStore represents an AWS Disk resource that is attached to a + kubelet's host machine and then exposed to... properties: - endpoints: - description: |- - endpoints is the endpoint name that details Glusterfs topology. - More info: https://examples.k8s. + fsType: + description: fsType is the filesystem type of the volume + that you want to mount. type: string - path: + partition: description: |- - path is the Glusterfs volume path. - More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod - type: string + partition is the partition in the volume that you want to mount. + If omitted, the default is to mount by volume name. + format: int32 + type: integer readOnly: description: |- - readOnly here will force the Glusterfs volume to be mounted with read-only permissions. - Defaults to false. + readOnly value true will force the readOnly setting in VolumeMounts. + More info: https://kubernetes. type: boolean + volumeID: + description: |- + volumeID is unique ID of the persistent disk resource in AWS (Amazon EBS volume). + More info: https://kubernetes. + type: string required: - - endpoints - - path + - volumeID type: object - hostPath: - description: |- - hostPath represents a pre-existing file or directory on the host - machine that is directly exposed to the container. + azureDisk: + description: azureDisk represents an Azure Data Disk mount + on the host and bind mount to the pod. properties: - path: - description: |- - path of the directory on the host. - If the path is a symlink, it will follow the link to the real path. + cachingMode: + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' type: string - type: + diskName: + description: diskName is the Name of the data disk in + the blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in the + blob storage + type: string + fsType: + default: ext4 description: |- - type for HostPath Volume - Defaults to "" - More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + fsType is Filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage...' type: string + readOnly: + default: false + description: |- + readOnly Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean required: - - path + - diskName + - diskURI type: object - iscsi: - description: |- - iscsi represents an ISCSI Disk resource that is attached to a - kubelet's host machine and then exposed to the pod. + azureFile: + description: azureFile represents an Azure File Service + mount on the host and bind mount to the pod. properties: - chapAuthDiscovery: - description: chapAuthDiscovery defines whether support - iSCSI Discovery CHAP authentication - type: boolean - chapAuthSession: - description: chapAuthSession defines whether support - iSCSI Session CHAP authentication + readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean - fsType: - description: fsType is the filesystem type of the volume - that you want to mount. - type: string - initiatorName: - description: initiatorName is the custom iSCSI Initiator - Name. + secretName: + description: secretName is the name of secret that + contains Azure Storage Account Name and Key type: string - iqn: - description: iqn is the target iSCSI Qualified Name. + shareName: + description: shareName is the azure share Name type: string - iscsiInterface: + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the host + that shares a pod's lifetime. + properties: + monitors: description: |- - iscsiInterface is the interface Name that uses an iSCSI transport. - Defaults to 'default' (tcp). - type: string - lun: - description: lun represents iSCSI Target Lun number. - format: int32 - type: integer - portals: - description: portals is the iSCSI Target Portal List. + monitors is Required: Monitors is a collection of Ceph monitors + More info: https://examples.k8s. items: type: string type: array x-kubernetes-list-type: atomic + path: + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default is /' + type: string readOnly: description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. - Defaults to false. + readOnly is Optional: Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile is + the path to key ring for User, default is /etc/ceph/user.' + type: string secretRef: - description: secretRef is the CHAP Secret for iSCSI - target and initiator authentication + description: 'secretRef is Optional: SecretRef is reference + to the authentication secret for User, default is + empty.' properties: name: default: "" @@ -3602,251 +4480,904 @@ spec: type: string type: object x-kubernetes-map-type: atomic - targetPortal: - description: targetPortal is iSCSI Target Portal. - type: string - required: - - iqn - - lun - - targetPortal - type: object - name: - description: |- - name of the volume. - Must be a DNS_LABEL and unique within the pod. - More info: https://kubernetes. - type: string - nfs: - description: |- - nfs represents an NFS mount on the host that shares a pod's lifetime - More info: https://kubernetes. - properties: - path: - description: |- - path that is exported by the NFS server. - More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs - type: string - readOnly: - description: |- - readOnly here will force the NFS export to be mounted with read-only permissions. - Defaults to false. - type: boolean - server: + user: description: |- - server is the hostname or IP address of the NFS server. - More info: https://kubernetes. + user is optional: User is the rados user name, default is admin + More info: https://examples.k8s. type: string required: - - path - - server + - monitors type: object - persistentVolumeClaim: + cinder: description: |- - persistentVolumeClaimVolumeSource represents a reference to a - PersistentVolumeClaim in the same namespace. - properties: - claimName: - description: claimName is the name of a PersistentVolumeClaim - in the same namespace as the pod using this volume. - type: string - readOnly: - description: |- - readOnly Will force the ReadOnly setting in VolumeMounts. - Default false. - type: boolean - required: - - claimName - type: object - photonPersistentDisk: - description: photonPersistentDisk represents a PhotonController - persistent disk attached and mounted on kubelets host - machine + cinder represents a cinder volume attached and mounted on kubelets host machine. + Deprecated: Cinder is deprecated. properties: fsType: description: |- fsType is the filesystem type to mount. Must be a filesystem type supported by the host operating system. - Ex. - type: string - pdID: - description: pdID is the ID that identifies Photon Controller - persistent disk - type: string - required: - - pdID - type: object - portworxVolume: - description: portworxVolume represents a portworx volume - attached and mounted on kubelets host machine - properties: - fsType: - description: |- - fSType represents the filesystem type to mount - Must be a filesystem type supported by the host operating system. - Ex. type: string readOnly: description: |- readOnly defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. type: boolean + secretRef: + description: |- + secretRef is optional: points to a secret object containing parameters used to connect + to OpenStack. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic volumeID: - description: volumeID uniquely identifies a Portworx - volume + description: |- + volumeID used to identify the volume in cinder. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md type: string required: - volumeID type: object - projected: - description: projected items for all in one resources secrets, - configmaps, and downward API + configMap: + description: configMap represents a configMap that should + populate this volume properties: defaultMode: - description: defaultMode are the mode bits used to set - permissions on created files by default. + description: 'defaultMode is optional: mode bits used + to set permissions on created files by default.' format: int32 type: integer - sources: - description: sources is the list of volume projections + items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + ConfigMap will be projected into the... items: - description: Projection that may be projected along - with other supported volume types + description: Maps a string key to a path within a + volume. properties: - clusterTrustBundle: - description: ClusterTrustBundle allows a pod to - access the `.spec. - properties: - labelSelector: - description: |- - Select all ClusterTrustBundles that match this label selector. Only has - effect if signerName is set. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. - type: object - type: object - x-kubernetes-map-type: atomic - name: - description: |- - Select a single ClusterTrustBundle by object name. Mutually-exclusive - with signerName and labelSelector. - type: string - optional: - description: |- - If true, don't block pod startup if the referenced ClusterTrustBundle(s) - aren't available. - type: boolean - path: - description: Relative path from the volume - root to write the bundle. + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used + to set permissions on this file.' + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + description: csi (Container Storage Interface) represents + ephemeral storage that is handled by certain external + CSI drivers. + properties: + driver: + description: driver is the name of the CSI driver that + handles this volume. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", "ntfs". + type: string + nodePublishSecretRef: + description: |- + nodePublishSecretRef is a reference to the secret object containing + sensitive information to pass to the CSI driver to... + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + description: |- + readOnly specifies a read-only configuration for the volume. + Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: |- + volumeAttributes stores driver-specific properties that are passed to the CSI + driver. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about the + pod that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created + files by default.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume + file + items: + description: DownwardAPIVolumeFile represents information + to create the file containing the pod field + properties: + fieldRef: + description: 'Required: Selects a field of the + pod: only annotations, labels, name, namespace + and uid are supported.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". type: string - signerName: - description: |- - Select all ClusterTrustBundles that match this signer name. - Mutually-exclusive with name. + fieldPath: + description: Path of the field to select in + the specified API version. type: string required: - - path + - fieldPath type: object - configMap: - description: configMap information about the configMap - data to project + x-kubernetes-map-type: atomic + mode: + description: |- + Optional: mode bits used to set permissions on this file, must be an octal value + between 0000 and 0777 or a decimal... + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must not + be absolute or contain the ''..'' path.' + type: string + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, requests. properties: - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volum - items: - description: Maps a string key to a path - within a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: 'mode is Optional: mode - bits used to set permissions on this - file.' - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + containerName: + description: 'Container name: required for + volumes, optional for env vars' type: string - optional: - description: optional specify whether the - ConfigMap or its keys must be defined - type: boolean + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource type: object x-kubernetes-map-type: atomic - downwardAPI: - description: downwardAPI information about the - downwardAPI data to project - properties: + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + description: |- + emptyDir represents a temporary directory that shares a pod's lifetime. + More info: https://kubernetes. + properties: + medium: + description: medium represents what type of storage + medium should back this directory. + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: sizeLimit is the total amount of local + storage required for this EmptyDir volume. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + description: ephemeral represents a volume that is handled + by a cluster storage driver. + properties: + volumeClaimTemplate: + description: Will be used to create a stand-alone PVC + to provision the volume. + properties: + metadata: + description: |- + May contain labels and annotations that will be copied into the PVC + when creating it. + type: object + spec: + description: The specification for the PersistentVolumeClaim. + properties: + accessModes: + description: |- + accessModes contains the desired access modes the volume should have. + More info: https://kubernetes. items: - description: Items is a list of DownwardAPIVolume - file - items: - description: DownwardAPIVolumeFile represents - information to create the file containing - the pod field - properties: - fieldRef: - description: 'Required: Selects a field - of the pod: only annotations, labels, - name, namespace and uid are supported.' - properties: - apiVersion: - description: Version of the schema + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + description: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s. + properties: + apiGroup: + description: APIGroup is the group for the + resource being referenced. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: |- + dataSourceRef specifies the object from which to populate the volume with data, if a non-empty + volume is desired. + properties: + apiGroup: + description: APIGroup is the group for the + resource being referenced. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a gateway.networking. + type: string + required: + - kind + - name + type: object + resources: + description: resources represents the minimum + resources the volume should have. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum + amount of compute resources required. + type: object + type: object + selector: + description: selector is a label query over + volumes to consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + description: |- + storageClassName is the name of the StorageClass required by the claim. + More info: https://kubernetes. + type: string + volumeAttributesClassName: + description: volumeAttributesClassName may be + used to set the VolumeAttributesClass used + by this claim. + type: string + volumeMode: + description: volumeMode defines what type of + volume is required by the claim. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource that + is attached to a kubelet's host machine and then exposed + to the pod. + properties: + fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: |- + readOnly is Optional: Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target worldwide + names (WWNs)' + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + description: |- + wwids Optional: FC volume world wide identifiers (wwids) + Either wwids or combination of targetWWNs and lun must be set,... + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + description: |- + flexVolume represents a generic volume resource that is + provisioned/attached using an exec based plugin. + properties: + driver: + description: driver is the name of the driver to use + for this volume. + type: string + fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds + extra command options if any.' + type: object + readOnly: + description: |- + readOnly is Optional: defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: |- + secretRef is Optional: secretRef is reference to the secret object containing + sensitive information to pass to the... + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached + to a kubelet's host machine. + properties: + datasetName: + description: |- + datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker + should be considered as... + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: |- + gcePersistentDisk represents a GCE Disk resource that is attached to a + kubelet's host machine and then exposed to the... + properties: + fsType: + description: fsType is filesystem type of the volume + that you want to mount. + type: string + partition: + description: |- + partition is the partition in the volume that you want to mount. + If omitted, the default is to mount by volume name. + format: int32 + type: integer + pdName: + description: |- + pdName is unique name of the PD resource in GCE. Used to identify the disk in GCE. + More info: https://kubernetes. + type: string + readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. + More info: https://kubernetes. + type: boolean + required: + - pdName + type: object + gitRepo: + description: |- + gitRepo represents a git repository at a particular revision. + Deprecated: GitRepo is deprecated. + properties: + directory: + description: |- + directory is the target directory name. + Must not contain or start with '..'. If '. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the specified + revision. + type: string + required: + - repository + type: object + glusterfs: + description: glusterfs represents a Glusterfs mount on the + host that shares a pod's lifetime. + properties: + endpoints: + description: |- + endpoints is the endpoint name that details Glusterfs topology. + More info: https://examples.k8s. + type: string + path: + description: |- + path is the Glusterfs volume path. + More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod + type: string + readOnly: + description: |- + readOnly here will force the Glusterfs volume to be mounted with read-only permissions. + Defaults to false. + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: |- + hostPath represents a pre-existing file or directory on the host + machine that is directly exposed to the container. + properties: + path: + description: |- + path of the directory on the host. + If the path is a symlink, it will follow the link to the real path. + type: string + type: + description: |- + type for HostPath Volume + Defaults to "" + More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + type: string + required: + - path + type: object + image: + description: image represents an OCI object (a container + image or artifact) pulled and mounted on the kubelet's + host machine. + properties: + pullPolicy: + description: |- + Policy for pulling OCI objects. Possible values are: + Always: the kubelet always attempts to pull the reference. + type: string + reference: + description: |- + Required: Image or artifact reference to be used. + Behaves in the same way as pod.spec.containers[*].image. + type: string + type: object + iscsi: + description: |- + iscsi represents an ISCSI Disk resource that is attached to a + kubelet's host machine and then exposed to the pod. + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication + type: boolean + fsType: + description: fsType is the filesystem type of the volume + that you want to mount. + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + default: default + description: |- + iscsiInterface is the interface Name that uses an iSCSI transport. + Defaults to 'default' (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal List. + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + description: targetPortal is iSCSI Target Portal. + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + description: |- + name of the volume. + Must be a DNS_LABEL and unique within the pod. + More info: https://kubernetes. + type: string + nfs: + description: |- + nfs represents an NFS mount on the host that shares a pod's lifetime + More info: https://kubernetes. + properties: + path: + description: |- + path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs + type: string + readOnly: + description: |- + readOnly here will force the NFS export to be mounted with read-only permissions. + Defaults to false. + type: boolean + server: + description: |- + server is the hostname or IP address of the NFS server. + More info: https://kubernetes. + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: |- + persistentVolumeClaimVolumeSource represents a reference to a + PersistentVolumeClaim in the same namespace. + properties: + claimName: + description: claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. + type: string + readOnly: + description: |- + readOnly Will force the ReadOnly setting in VolumeMounts. + Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host + machine. + properties: + fsType: + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. + type: string + pdID: + description: pdID is the ID that identifies Photon Controller + persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume + attached and mounted on kubelets host machine. + properties: + fsType: + description: |- + fSType represents the filesystem type to mount + Must be a filesystem type supported by the host operating system. + Ex. + type: string + readOnly: + description: |- + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx + volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources secrets, + configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used to set + permissions on created files by default. + format: int32 + type: integer + sources: + description: |- + sources is the list of volume projections. Each entry in this list + handles one source. + items: + description: |- + Projection that may be projected along with other supported volume types. + Exactly one of these fields must be set. + properties: + clusterTrustBundle: + description: ClusterTrustBundle allows a pod to + access the `.spec. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. + type: string + required: + - path + type: object + configMap: + description: configMap information about the configMap + data to project + properties: + items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + ConfigMap will be projected into the... + items: + description: Maps a string key to a path + within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode + bits used to set permissions on this + file.' + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: optional specify whether the + ConfigMap or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + description: downwardAPI information about the + downwardAPI data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects a field + of the pod: only annotations, labels, + name, namespace and uid are supported.' + properties: + apiVersion: + description: Version of the schema the FieldPath is written in terms of, defaults to "v1". type: string @@ -3861,7 +5392,7 @@ spec: mode: description: |- Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal valu + between 0000 and 0777 or a decimal... format: int32 type: integer path: @@ -3910,7 +5441,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume a + Secret will be projected into the volume... items: description: Maps a string key to a path within a volume. @@ -3974,870 +5505,2124 @@ spec: type: array x-kubernetes-list-type: atomic type: object - quobyte: - description: quobyte represents a Quobyte mount on the host - that shares a pod's lifetime + quobyte: + description: quobyte represents a Quobyte mount on the host + that shares a pod's lifetime. + properties: + group: + description: |- + group to map volume access to + Default is no group + type: string + readOnly: + description: |- + readOnly here will force the Quobyte volume to be mounted with read-only permissions. + Defaults to false. + type: boolean + registry: + description: |- + registry represents a single or multiple Quobyte Registry services + specified as a string as host:port pair (multiple... + type: string + tenant: + description: |- + tenant owning the given Quobyte volume in the Backend + Used with dynamically provisioned Quobyte volumes, value is set... + type: string + user: + description: |- + user to map volume access to + Defaults to serivceaccount user + type: string + volume: + description: volume is a string that references an already + created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: rbd represents a Rados Block Device mount on + the host that shares a pod's lifetime. + properties: + fsType: + description: fsType is the filesystem type of the volume + that you want to mount. + type: string + image: + description: |- + image is the rados image name. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + type: string + keyring: + default: /etc/ceph/keyring + description: |- + keyring is the path to key ring for RBDUser. + Default is /etc/ceph/keyring. + More info: https://examples.k8s. + type: string + monitors: + description: |- + monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + description: |- + pool is the rados pool name. + Default is rbd. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + type: string + readOnly: + description: |- + readOnly here will force the ReadOnly setting in VolumeMounts. + Defaults to false. + More info: https://examples.k8s. + type: boolean + secretRef: + description: |- + secretRef is name of the authentication secret for RBDUser. If provided + overrides keyring. + Default is nil. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + description: |- + user is the rados user name. + Default is admin. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + default: xfs + description: |- + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. + type: string + gateway: + description: gateway is the host address of the ScaleIO + API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the ScaleIO + Protection Domain for the configured storage. + type: string + readOnly: + description: |- + readOnly Defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: |- + secretRef references to the secret for ScaleIO user and other + sensitive information. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable SSL communication + with Gateway, default false + type: boolean + storageMode: + default: ThinProvisioned + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage Pool + associated with the protection domain. + type: string + system: + description: system is the name of the storage system + as configured in ScaleIO. + type: string + volumeName: + description: |- + volumeName is the name of a volume already created in the ScaleIO system + that is associated with this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: |- + secret represents a secret that should populate this volume. + More info: https://kubernetes. + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used + to set permissions on created files by default.' + format: int32 + type: integer + items: + description: |- + items If unspecified, each key-value pair in the Data field of the referenced + Secret will be projected into the volume... + items: + description: Maps a string key to a path within a + volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used + to set permissions on this file.' + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + description: optional field specify whether the Secret + or its keys must be defined + type: boolean + secretName: + description: |- + secretName is the name of the secret in the pod's namespace to use. + More info: https://kubernetes. + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume attached + and mounted on Kubernetes nodes. properties: - group: + fsType: description: |- - group to map volume access to - Default is no group + fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string readOnly: description: |- - readOnly here will force the Quobyte volume to be mounted with read-only permissions. - Defaults to false. + readOnly defaults to false (read/write). ReadOnly here will force + the ReadOnly setting in VolumeMounts. type: boolean - registry: - description: |- - registry represents a single or multiple Quobyte Registry services - specified as a string as host:port pair (multiple ent - type: string - tenant: + secretRef: description: |- - tenant owning the given Quobyte volume in the Backend - Used with dynamically provisioned Quobyte volumes, value is set by - type: string - user: + secretRef specifies the secret to use for obtaining the StorageOS API + credentials. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: description: |- - user to map volume access to - Defaults to serivceaccount user + volumeName is the human-readable name of the StorageOS volume. Volume + names are only unique within a namespace. type: string - volume: - description: volume is a string that references an already - created Quobyte volume by name. + volumeNamespace: + description: volumeNamespace specifies the scope of + the volume within StorageOS. type: string - required: - - registry - - volume type: object - rbd: - description: |- - rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. - More info: https://examples.k8s. + vsphereVolume: + description: vsphereVolume represents a vSphere volume attached + and mounted on kubelets host machine. properties: fsType: - description: fsType is the filesystem type of the volume - that you want to mount. - type: string - image: description: |- - image is the rados image name. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + fsType is filesystem type to mount. + Must be a filesystem type supported by the host operating system. + Ex. type: string - keyring: - description: |- - keyring is the path to key ring for RBDUser. - Default is /etc/ceph/keyring. - More info: https://examples.k8s. + storagePolicyID: + description: storagePolicyID is the storage Policy Based + Management (SPBM) profile ID associated with the StoragePolicyName. type: string - monitors: - description: |- - monitors is a collection of Ceph monitors. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - items: + storagePolicyName: + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies + vSphere volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + type: object + required: + - feastProject + type: object + x-kubernetes-validations: + - message: replicas > 1 and services.scaling.autoscaling are mutually + exclusive. + rule: self.replicas <= 1 || !has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling) + - message: Scaling requires DB-backed persistence for the online store. + Configure services.onlineStore.persistence.store when using replicas + > 1 or autoscaling. + rule: self.replicas <= 1 && (!has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling)) || (has(self.services) + && has(self.services.onlineStore) && has(self.services.onlineStore.persistence) + && has(self.services.onlineStore.persistence.store)) + - message: Scaling requires DB-backed persistence for the offline store. + Configure services.offlineStore.persistence.store when using replicas + > 1 or autoscaling. + rule: self.replicas <= 1 && (!has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling)) || (!has(self.services) + || !has(self.services.offlineStore) || (has(self.services.offlineStore.persistence) + && has(self.services.offlineStore.persistence.store))) + - message: Scaling requires DB-backed or remote registry. Configure registry.local.persistence.store + or use a remote registry when using replicas > 1 or autoscaling. S3/GCS-backed + registry is also allowed. + rule: self.replicas <= 1 && (!has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling)) || (has(self.services) + && has(self.services.registry) && (has(self.services.registry.remote) + || (has(self.services.registry.local) && has(self.services.registry.local.persistence) + && (has(self.services.registry.local.persistence.store) || (has(self.services.registry.local.persistence.file) + && has(self.services.registry.local.persistence.file.path) && (self.services.registry.local.persistence.file.path.startsWith('s3://') + || self.services.registry.local.persistence.file.path.startsWith('gs://'))))))) + status: + description: FeatureStoreStatus defines the observed state of FeatureStore + properties: + applied: + description: Shows the currently applied feast configuration, including + any pertinent defaults + properties: + authz: + description: AuthzConfig defines the authorization settings for + the deployed Feast services. + properties: + kubernetes: + description: |- + KubernetesAuthz provides a way to define the authorization settings using Kubernetes RBAC resources. + https://kubernetes. + properties: + roles: + description: The Kubernetes RBAC roles to be deployed + in the same namespace of the FeatureStore. + items: + type: string + type: array + type: object + oidc: + description: |- + OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. + https://auth0. + properties: + caCertConfigMap: + description: ConfigMap with the CA certificate for self-signed + OIDC providers. Auto-detected on RHOAI/ODH. + properties: + key: + description: Key in the ConfigMap holding the PEM + certificate. Defaults to "ca-bundle.crt". type: string - type: array - x-kubernetes-list-type: atomic - pool: - description: |- - pool is the rados pool name. - Default is rbd. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it + name: + description: ConfigMap name. + type: string + required: + - name + type: object + issuerUrl: + description: OIDC issuer URL. The operator appends /.well-known/openid-configuration + to derive the discovery endpoint. + pattern: ^https://\S+$ + type: string + secretKeyName: + description: Key in the Secret containing all OIDC properties + as a YAML value. If unset, each key is a property. + type: string + secretRef: + description: Secret with OIDC properties (auth_discovery_url, + client_id, client_secret). issuerUrl takes precedence. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + tokenEnvVar: + description: Env var name for client pods to read an OIDC + token from. Sets token_env_var in client config. + type: string + verifySSL: + description: Verify SSL certificates for the OIDC provider. + Defaults to true. + type: boolean + type: object + type: object + x-kubernetes-validations: + - message: One selection required between kubernetes or oidc. + rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, + c)' + batchEngine: + description: BatchEngineConfig defines the batch compute engine + configuration. + properties: + configMapKey: + description: Key name in the ConfigMap. Defaults to "config" + if not specified. + type: string + configMapRef: + description: Reference to a ConfigMap containing the batch + engine configuration. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + type: object + cronJob: + description: FeastCronJob defines a CronJob to execute against + a Feature Store deployment. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to be added to the CronJob metadata. + type: object + concurrencyPolicy: + description: Specifies how to treat concurrent executions + of a Job. + type: string + containerConfigs: + description: CronJobContainerConfigs k8s container settings + for the CronJob + properties: + commands: + description: Array of commands to be executed (in order) + against a Feature Store deployment. + items: type: string - readOnly: - description: |- - readOnly here will force the ReadOnly setting in VolumeMounts. - Defaults to false. - More info: https://examples.k8s. - type: boolean - secretRef: - description: |- - secretRef is name of the authentication secret for RBDUser. If provided - overrides keyring. - Default is nil. + type: array + env: + items: + description: EnvVar represents an environment variable + present in a Container. properties: name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + description: Name of the environment variable. Must + be a C_IDENTIFIER. type: string - type: object - x-kubernetes-map-type: atomic - user: - description: |- - user is the rados user name. - Default is admin. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it - type: string - required: - - image - - monitors - type: object - scaleIO: - description: scaleIO represents a ScaleIO persistent volume - attached and mounted on Kubernetes nodes. - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. - type: string - gateway: - description: gateway is the host address of the ScaleIO - API Gateway. - type: string - protectionDomain: - description: protectionDomain is the name of the ScaleIO - Protection Domain for the configured storage. - type: string - readOnly: - description: |- - readOnly Defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef references to the secret for ScaleIO user and other - sensitive information. - properties: - name: - default: "" + value: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and... type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. + properties: + containerName: + description: 'Container name: required for + volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the + pod's namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name type: object - x-kubernetes-map-type: atomic - sslEnabled: - description: sslEnabled Flag enable/disable SSL communication - with Gateway, default false - type: boolean - storageMode: - description: storageMode indicates whether the storage - for a volume should be ThickProvisioned or ThinProvisioned. - type: string - storagePool: - description: storagePool is the ScaleIO Storage Pool - associated with the protection domain. - type: string - system: - description: system is the name of the storage system - as configured in ScaleIO. - type: string - volumeName: - description: |- - volumeName is the name of a volume already created in the ScaleIO system - that is associated with this volume source. - type: string - required: - - gateway - - secretRef - - system - type: object - secret: - description: |- - secret represents a secret that should populate this volume. - More info: https://kubernetes. - properties: - defaultMode: - description: 'defaultMode is Optional: mode bits used - to set permissions on created files by default.' - format: int32 - type: integer + type: array + envFrom: items: - description: |- - items If unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume a - items: - description: Maps a string key to a path within a - volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: 'mode is Optional: mode bits used - to set permissions on this file.' - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - type: string - required: - - key - - path + description: EnvFromSource represents the source of + a set of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image + type: string + nodeSelector: + additionalProperties: + type: string + type: object + resources: + description: ResourceRequirements describes the compute + resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. + type: string + request: + description: Request is the name chosen for + a request in the referenced claim. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. type: object - type: array - x-kubernetes-list-type: atomic - optional: - description: optional field specify whether the Secret - or its keys must be defined - type: boolean - secretName: - description: |- - secretName is the name of the secret in the pod's namespace to use. - More info: https://kubernetes. + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount + of compute resources required. + type: object + type: object + type: object + failedJobsHistoryLimit: + description: The number of failed finished jobs to retain. + Value must be non-negative integer. + format: int32 + type: integer + jobSpec: + description: Specification of the desired behavior of a job. + properties: + activeDeadlineSeconds: + description: |- + Specifies the duration in seconds relative to the startTime that the job + may be continuously active before the system... + format: int64 + type: integer + backoffLimit: + description: Specifies the number of retries before marking + this job failed. + format: int32 + type: integer + backoffLimitPerIndex: + description: |- + Specifies the limit for the number of retries within an + index before marking this index as failed. + format: int32 + type: integer + completionMode: + description: |- + completionMode specifies how Pod completions are tracked. It can be + `NonIndexed` (default) or `Indexed`. + type: string + completions: + description: |- + Specifies the desired number of successfully finished pods the + job should be run with. + format: int32 + type: integer + maxFailedIndexes: + description: |- + Specifies the maximal number of failed indexes before marking the Job as + failed, when backoffLimitPerIndex is set. + format: int32 + type: integer + parallelism: + description: |- + Specifies the maximum desired number of pods the job should + run at any given time. + format: int32 + type: integer + podFailurePolicy: + description: Specifies the policy of handling failed pods. + properties: + rules: + description: A list of pod failure policy rules. The + rules are evaluated in order. + items: + description: PodFailurePolicyRule describes how + a pod failure is handled when the requirements + are met. + properties: + action: + description: Specifies the action taken on a + pod failure when the requirements are satisfied. + type: string + onExitCodes: + description: Represents the requirement on the + container exit codes. + properties: + containerName: + description: |- + Restricts the check for exit codes to the container with the + specified name. + type: string + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. + type: string + values: + description: Specifies the set of values. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + - values + type: object + onPodConditions: + description: |- + Represents the requirement on the pod conditions. The requirement is represented + as a list of pod condition patterns. + items: + description: |- + PodFailurePolicyOnPodConditionsPattern describes a pattern for matching + an actual pod condition type. + properties: + status: + description: Specifies the required Pod + condition status. + type: string + type: + description: Specifies the required Pod + condition type. + type: string + required: + - status + - type + type: object + type: array + x-kubernetes-list-type: atomic + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + required: + - rules + type: object + podReplacementPolicy: + description: podReplacementPolicy specifies when to create + replacement Pods. + type: string + podTemplateAnnotations: + additionalProperties: type: string - type: object - storageos: - description: storageOS represents a StorageOS volume attached - and mounted on Kubernetes nodes. - properties: - fsType: - description: |- - fsType is the filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. + description: |- + PodTemplateAnnotations are annotations to be applied to the CronJob's PodTemplate + metadata. + type: object + suspend: + description: suspend specifies whether the Job controller + should create Pods or not. + type: boolean + ttlSecondsAfterFinished: + description: |- + ttlSecondsAfterFinished limits the lifetime of a Job that has finished + execution (either Complete or Failed). + format: int32 + type: integer + type: object + schedule: + description: The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. + type: string + startingDeadlineSeconds: + description: |- + Optional deadline in seconds for starting the job if it misses scheduled + time for any reason. + format: int64 + type: integer + successfulJobsHistoryLimit: + description: The number of successful finished jobs to retain. + Value must be non-negative integer. + format: int32 + type: integer + suspend: + description: |- + This flag tells the controller to suspend subsequent executions, it does + not apply to already started executions. + type: boolean + timeZone: + description: The time zone name for the given schedule, see + https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. + type: string + type: object + feastProject: + description: FeastProject is the Feast project id. + pattern: ^[A-Za-z0-9][A-Za-z0-9_-]*$ + type: string + feastProjectDir: + description: FeastProjectDir defines how to create the feast project + directory. + properties: + git: + description: GitCloneOptions describes how a clone should + be performed. + properties: + configs: + additionalProperties: type: string - readOnly: - description: |- - readOnly defaults to false (read/write). ReadOnly here will force - the ReadOnly setting in VolumeMounts. - type: boolean - secretRef: - description: |- - secretRef specifies the secret to use for obtaining the StorageOS API - credentials. + description: |- + Configs passed to git via `-c` + e.g. http.sslVerify: 'false' + OR 'url."https://api:\${TOKEN}@github.com/". + type: object + env: + items: + description: EnvVar represents an environment variable + present in a Container. properties: name: - default: "" + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and... type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. + properties: + containerName: + description: 'Container name: required for + volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the + pod's namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name type: object - x-kubernetes-map-type: atomic - volumeName: - description: |- - volumeName is the human-readable name of the StorageOS volume. Volume - names are only unique within a namespace. - type: string - volumeNamespace: - description: volumeNamespace specifies the scope of - the volume within StorageOS. - type: string - type: object - vsphereVolume: - description: vsphereVolume represents a vSphere volume attached - and mounted on kubelets host machine - properties: - fsType: - description: |- - fsType is filesystem type to mount. - Must be a filesystem type supported by the host operating system. - Ex. - type: string - storagePolicyID: - description: storagePolicyID is the storage Policy Based - Management (SPBM) profile ID associated with the StoragePolicyName. - type: string - storagePolicyName: - description: storagePolicyName is the storage Policy - Based Management (SPBM) profile name. - type: string - volumePath: - description: volumePath is the path that identifies - vSphere volume vmdk - type: string - required: - - volumePath - type: object - required: - - name - type: object - type: array - type: object - required: - - feastProject - type: object - status: - description: FeatureStoreStatus defines the observed state of FeatureStore - properties: - applied: - description: Shows the currently applied feast configuration, including - any pertinent defaults - properties: - authz: - description: AuthzConfig defines the authorization settings for - the deployed Feast services. - properties: - kubernetes: - description: |- - KubernetesAuthz provides a way to define the authorization settings using Kubernetes RBAC resources. - https://kubernetes. - properties: - roles: - description: The Kubernetes RBAC roles to be deployed - in the same namespace of the FeatureStore. + type: array + envFrom: items: - type: string + description: EnvFromSource represents the source of + a set of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object type: array - type: object - oidc: - description: |- - OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. - https://auth0. - properties: - secretRef: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic + featureRepoPath: + description: FeatureRepoPath is the relative path to the + feature repo subdirectory. Default is 'feature_repo'. + type: string + ref: + description: Reference to a branch / tag / commit + type: string + url: + description: The repository URL to clone from. + type: string required: - - secretRef + - url type: object - type: object - x-kubernetes-validations: - - message: One selection required between kubernetes or oidc. - rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, - c)' - batchEngine: - description: BatchEngineConfig defines the batch compute engine - configuration. - properties: - configMapKey: - description: Key name in the ConfigMap. Defaults to "config" - if not specified. - type: string - configMapRef: - description: Reference to a ConfigMap containing the batch - engine configuration. + x-kubernetes-validations: + - message: RepoPath must be a file name only, with no slashes. + rule: 'has(self.featureRepoPath) ? !self.featureRepoPath.startsWith(''/'') + : true' + init: + description: FeastInitOptions defines how to run a `feast + init`. properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + minimal: + type: boolean + template: + description: Template for the created project + enum: + - local + - gcp + - aws + - snowflake + - spark + - postgres + - hbase + - cassandra + - hazelcast + - couchbase + - clickhouse type: string type: object - x-kubernetes-map-type: atomic type: object - cronJob: - description: FeastCronJob defines a CronJob to execute against - a Feature Store deployment. + x-kubernetes-validations: + - message: One selection required between init or git. + rule: '[has(self.git), has(self.init)].exists_one(c, c)' + replicas: + default: 1 + description: |- + Replicas is the desired number of pod replicas. Used by the scale sub-resource. + Mutually exclusive with services. + format: int32 + minimum: 1 + type: integer + services: + description: FeatureStoreServices defines the desired feast services. + An ephemeral onlineStore feature server is deployed by default. properties: - annotations: - additionalProperties: - type: string - description: Annotations to be added to the CronJob metadata. - type: object - concurrencyPolicy: - description: Specifies how to treat concurrent executions - of a Job. - type: string - containerConfigs: - description: CronJobContainerConfigs k8s container settings - for the CronJob + affinity: + description: Affinity defines the pod scheduling constraints + for the FeatureStore deployment. properties: - commands: - description: Array of commands to be executed (in order) - against a Feature Store deployment. - items: - type: string - type: array - env: - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. - type: string - value: + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but... + items: description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. + preference: + description: A node selector term, associated + with the corresponding weight. properties: - key: - description: The key to select. - type: string - name: - default: "" + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto... + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but... + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: 'Selects a field of the pod: supports - metadata.name, metadata.namespace, `metadata.labels['''']`, - `metadata.' - properties: - apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in... type: string required: - - fieldPath + - topologyKey type: object - x-kubernetes-map-type: atomic - resourceFieldRef: + weight: description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits. + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto... + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should... + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: - containerName: - description: 'Container name: required for - volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults to - "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object type: object x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the - pod's namespace + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. properties: - key: - description: The key of the secret to select - from. Must be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object type: object x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - items: - description: EnvFromSource represents the source of - a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the ConfigMap must - be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - default: "" + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in... type: string - optional: - description: Specify whether the Secret must - be defined - type: boolean + required: + - topologyKey type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - type: string - imagePullPolicy: - description: PullPolicy describes a policy for if/when - to pull a container image - type: string - nodeSelector: - additionalProperties: - type: string + type: array + x-kubernetes-list-type: atomic type: object - resources: - description: ResourceRequirements describes the compute - resource requirements. + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, + etc. properties: - claims: + preferredDuringSchedulingIgnoredDuringExecution: description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field,... items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) properties: - name: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in... + type: string + required: + - topologyKey + type: object + weight: description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. - type: string + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer required: - - name + - podAffinityTerm + - weight type: object type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the minimum amount - of compute resources required. - type: object - type: object - type: object - failedJobsHistoryLimit: - description: The number of failed finished jobs to retain. - Value must be non-negative integer. - format: int32 - type: integer - jobSpec: - description: Specification of the desired behavior of a job. - properties: - activeDeadlineSeconds: - description: |- - Specifies the duration in seconds relative to the startTime that the job - may be continuously active before the system tr - format: int64 - type: integer - backoffLimit: - description: Specifies the number of retries before marking - this job failed. - format: int32 - type: integer - backoffLimitPerIndex: - description: |- - Specifies the limit for the number of retries within an - index before marking this index as failed. - format: int32 - type: integer - completionMode: - description: |- - completionMode specifies how Pod completions are tracked. It can be - `NonIndexed` (default) or `Indexed`. - type: string - completions: - description: |- - Specifies the desired number of successfully finished pods the - job should be run with. - format: int32 - type: integer - maxFailedIndexes: - description: |- - Specifies the maximal number of failed indexes before marking the Job as - failed, when backoffLimitPerIndex is set. - format: int32 - type: integer - parallelism: - description: |- - Specifies the maximum desired number of pods the job should - run at any given time. - format: int32 - type: integer - podFailurePolicy: - description: Specifies the policy of handling failed pods. - properties: - rules: - description: A list of pod failure policy rules. The - rules are evaluated in order. + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled... items: - description: PodFailurePolicyRule describes how - a pod failure is handled when the requirements - are met. + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should... properties: - action: - description: Specifies the action taken on a - pod failure when the requirements are satisfied. - type: string - onExitCodes: - description: Represents the requirement on the - container exit codes. + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: - containerName: - description: |- - Restricts the check for exit codes to the container with the - specified name. - type: string - operator: - description: |- - Represents the relationship between the container exit code(s) and the - specified values. - type: string - values: - description: Specifies the set of values. + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. items: - format: int32 - type: integer + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object type: array - x-kubernetes-list-type: set - required: - - operator - - values + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object type: object - onPodConditions: + x-kubernetes-map-type: atomic + matchLabelKeys: description: |- - Represents the requirement on the pod conditions. The requirement is represented - as a list of pod condition patterns. + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. items: - description: |- - PodFailurePolicyOnPodConditionsPattern describes a pattern for matching - an actual pod condition type. - properties: - status: - description: Specifies the required Pod - condition status. - type: string - type: - description: Specifies the required Pod - condition type. + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: type: string - required: - - status - - type - type: object + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + items: + type: string type: array x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in... + type: string required: - - action + - topologyKey type: object type: array x-kubernetes-list-type: atomic - required: - - rules type: object - podReplacementPolicy: - description: podReplacementPolicy specifies when to create - replacement Pods. - type: string - podTemplateAnnotations: - additionalProperties: - type: string + type: object + deploymentStrategy: + description: DeploymentStrategy describes how to replace existing + pods with new ones. + properties: + rollingUpdate: description: |- - PodTemplateAnnotations are annotations to be applied to the CronJob's PodTemplate - metadata. + Rolling update config params. Present only if DeploymentStrategyType = + RollingUpdate. + properties: + maxSurge: + anyOf: + - type: integer + - type: string + description: |- + The maximum number of pods that can be scheduled above the desired number of + pods. + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + description: The maximum number of pods that can be + unavailable during the update. + x-kubernetes-int-or-string: true type: object - suspend: - description: suspend specifies whether the Job controller - should create Pods or not. - type: boolean - ttlSecondsAfterFinished: - description: |- - ttlSecondsAfterFinished limits the lifetime of a Job that has finished - execution (either Complete or Failed). - format: int32 - type: integer + type: + description: Type of deployment. Can be "Recreate" or + "RollingUpdate". Default is RollingUpdate. + type: string type: object - schedule: - description: The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. - type: string - startingDeadlineSeconds: - description: |- - Optional deadline in seconds for starting the job if it misses scheduled - time for any reason. - format: int64 - type: integer - successfulJobsHistoryLimit: - description: The number of successful finished jobs to retain. - Value must be non-negative integer. - format: int32 - type: integer - suspend: - description: |- - This flag tells the controller to suspend subsequent executions, it does - not apply to already started executions. + disableInitContainers: + description: Disable the 'feast repo initialization' initContainer type: boolean - timeZone: - description: The time zone name for the given schedule, see - https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. - type: string - type: object - feastProject: - description: FeastProject is the Feast project id. - pattern: ^[A-Za-z0-9][A-Za-z0-9_-]*$ - type: string - feastProjectDir: - description: FeastProjectDir defines how to create the feast project - directory. - properties: - git: - description: GitCloneOptions describes how a clone should - be performed. + offlineStore: + description: OfflineStore configures the offline store service properties: - configs: - additionalProperties: - type: string - description: |- - Configs passed to git via `-c` - e.g. http.sslVerify: 'false' - OR 'url."https://api:\${TOKEN}@github.com/". + persistence: + description: OfflineStorePersistence configures the persistence + settings for the offline store service + properties: + file: + description: OfflineStoreFilePersistence configures + the file-based persistence for the offline store + service + properties: + pvc: + description: PvcConfig defines the settings for + a persistent file store based on PVCs. + properties: + create: + description: Settings for creating a new PVC + properties: + accessModes: + description: AccessModes k8s persistent + volume access modes. Defaults to ["ReadWriteOnce"]. + items: + type: string + type: array + resources: + description: Resources describes the storage + resource requirements for a volume. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the + minimum amount of compute resources + required. + type: object + type: object + storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which + this persistent volume belongs. + type: string + type: object + x-kubernetes-validations: + - message: PvcCreate is immutable + rule: self == oldSelf + mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. + type: string + ref: + description: Reference to an existing field + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + required: + - mountPath + type: object + x-kubernetes-validations: + - message: One selection is required between ref + and create. + rule: '[has(self.ref), has(self.create)].exists_one(c, + c)' + - message: Mount path must start with '/' and + must not contain ':' + rule: self.mountPath.matches('^/[^:]*$') + type: + enum: + - file + - dask + - duckdb + type: string + type: object + store: + description: OfflineStoreDBStorePersistence configures + the DB store persistence for the offline store service + properties: + secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName + type: string + secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the + secret key. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + type: + description: Type of the persistence type you + want to use. + enum: + - snowflake.offline + - bigquery + - redshift + - spark + - postgres + - trino + - athena + - mssql + - couchbase.offline + - clickhouse + - ray + - oracle + type: string + required: + - secretRef + - type + type: object type: object - env: - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. + x-kubernetes-validations: + - message: One selection required between file or store. + rule: '[has(self.file), has(self.store)].exists_one(c, + c)' + server: + description: Creates a remote offline server container + properties: + env: + items: + description: EnvVar represents an environment variable + present in a Container. properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and... + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. properties: - key: - description: The key to select. - type: string - name: - default: "" + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: + supports metadata.name, metadata.namespace, + `metadata.labels['''']`, `metadata.' + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, + defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: 'Selects a field of the pod: supports - metadata.name, metadata.namespace, `metadata.labels['''']`, - `metadata.' - properties: - apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults + to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in + the pod's namespace + properties: + key: + description: The key of the secret to + select from. Must be a valid secret + key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits. - properties: - containerName: - description: 'Container name: required for - volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults to - "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source + of a set of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string - required: - - resource + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean type: object x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the - pod's namespace + prefix: + description: Optional text to prepend to the + name of each environment variable. Must be + a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from properties: - key: - description: The key of the secret to select - from. Must be a valid secret key. - type: string name: default: "" description: |- @@ -4847,153 +7632,232 @@ spec: type: string optional: description: Specify whether the Secret - or its key must be defined + must be defined type: boolean - required: - - key type: object x-kubernetes-map-type: atomic type: object - required: - - name - type: object - type: array - envFrom: - items: - description: EnvFromSource represents the source of - a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the ConfigMap must - be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the Secret must - be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - featureRepoPath: - description: FeatureRepoPath is the relative path to the - feature repo subdirectory. Default is 'feature_repo'. - type: string - ref: - description: Reference to a branch / tag / commit - type: string - url: - description: The repository URL to clone from. - type: string - required: - - url - type: object - x-kubernetes-validations: - - message: RepoPath must be a file name only, with no slashes. - rule: 'has(self.featureRepoPath) ? !self.featureRepoPath.startsWith(''/'') - : true' - init: - description: FeastInitOptions defines how to run a `feast - init`. - properties: - minimal: - type: boolean - template: - description: Template for the created project - enum: - - local - - gcp - - aws - - snowflake - - spark - - postgres - - hbase - - cassandra - - hazelcast - - ikv - - couchbase - - clickhouse - type: string - type: object - type: object - x-kubernetes-validations: - - message: One selection required between init or git. - rule: '[has(self.git), has(self.init)].exists_one(c, c)' - services: - description: FeatureStoreServices defines the desired feast services. - An ephemeral onlineStore feature server is deployed by default. - properties: - deploymentStrategy: - description: DeploymentStrategy describes how to replace existing - pods with new ones. - properties: - rollingUpdate: - description: |- - Rolling update config params. Present only if DeploymentStrategyType = - RollingUpdate. - properties: - maxSurge: - anyOf: - - type: integer - - type: string + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image + type: string + logLevel: description: |- - The maximum number of pods that can be scheduled above the desired number of - pods. - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - description: The maximum number of pods that can be - unavailable during the update. - x-kubernetes-int-or-string: true + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". + enum: + - debug + - info + - warning + - error + - critical + type: string + metrics: + description: Metrics exposes Prometheus-compatible + metrics for the Feast server when enabled. + type: boolean + nodeSelector: + additionalProperties: + type: string + type: object + resources: + description: ResourceRequirements describes the compute + resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. + type: string + request: + description: Request is the name chosen + for a request in the referenced claim. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount + of compute resources required. + type: object + type: object + tls: + description: TlsConfigs configures server TLS for + a feast service. + properties: + disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, + where TLS is configured by default + type: boolean + secretKeyNames: + description: SecretKeyNames defines the secret + key names for the TLS key and cert. + properties: + tlsCrt: + description: defaults to "tls.crt" + type: string + tlsKey: + description: defaults to "tls.key" + type: string + type: object + secretRef: + description: references the local k8s secret where + the TLS key and cert reside + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: '`secretRef` required if `disable` is false.' + rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) + : true' + volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. + items: + description: VolumeMount describes a mounting of + a Volume within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume + from which the container's volume should be + mounted. + type: string + required: + - mountPath + - name + type: object + type: array + workerConfigs: + description: WorkerConfigs defines the worker configuration + for the Feast server. + properties: + keepAliveTimeout: + description: |- + KeepAliveTimeout is the timeout for keep-alive connections in seconds. + Defaults to 30. + format: int32 + minimum: 1 + type: integer + maxRequests: + description: |- + MaxRequests is the maximum number of requests a worker will process before restarting. + This helps prevent memory leaks. + format: int32 + minimum: 0 + type: integer + maxRequestsJitter: + description: |- + MaxRequestsJitter is the maximum jitter to add to max-requests to prevent + thundering herd effect on worker restart. + format: int32 + minimum: 0 + type: integer + registryTTLSeconds: + description: RegistryTTLSeconds is the number + of seconds after which the registry is refreshed. + format: int32 + minimum: 0 + type: integer + workerConnections: + description: |- + WorkerConnections is the maximum number of simultaneous clients per worker process. + Defaults to 1000. + format: int32 + minimum: 1 + type: integer + workers: + description: Workers is the number of worker processes. + Use -1 to auto-calculate based on CPU cores + (2 * CPU + 1). + format: int32 + minimum: -1 + type: integer + type: object type: object - type: - description: Type of deployment. Can be "Recreate" or - "RollingUpdate". Default is RollingUpdate. - type: string type: object - disableInitContainers: - description: Disable the 'feast repo initialization' initContainer - type: boolean - offlineStore: - description: OfflineStore configures the offline store service + onlineStore: + description: OnlineStore configures the online store service properties: persistence: - description: OfflineStorePersistence configures the persistence - settings for the offline store service + description: OnlineStorePersistence configures the persistence + settings for the online store service properties: file: - description: OfflineStoreFilePersistence configures - the file-based persistence for the offline store + description: OnlineStoreFilePersistence configures + the file-based persistence for the online store service properties: + path: + type: string pvc: description: PvcConfig defines the settings for a persistent file store based on PVCs. @@ -5071,16 +7935,22 @@ spec: - message: Mount path must start with '/' and must not contain ':' rule: self.mountPath.matches('^/[^:]*$') - type: - enum: - - file - - dask - - duckdb - type: string type: object + x-kubernetes-validations: + - message: Ephemeral stores must have absolute paths. + rule: '(!has(self.pvc) && has(self.path)) ? self.path.startsWith(''/'') + : true' + - message: PVC path must be a file name only, with + no slashes. + rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') + : true' + - message: Online store does not support S3 or GS + buckets. + rule: 'has(self.path) ? !(self.path.startsWith(''s3://'') + || self.path.startsWith(''gs://'')) : true' store: - description: OfflineStoreDBStorePersistence configures - the DB store persistence for the offline store service + description: OnlineStoreDBStorePersistence configures + the DB store persistence for the online store service properties: secretKeyName: description: By default, the selected store "type" @@ -5104,17 +7974,23 @@ spec: description: Type of the persistence type you want to use. enum: - - snowflake.offline - - bigquery - - redshift - - spark + - snowflake.online + - redis + - datastore + - dynamodb + - bigtable - postgres - - trino - - athena - - mssql - - couchbase.offline - - clickhouse - - ray + - cassandra + - mysql + - hazelcast + - singlestore + - hbase + - elasticsearch + - qdrant + - couchbase.online + - milvus + - hybrid + - mongodb type: string required: - secretRef @@ -5126,7 +8002,7 @@ spec: rule: '[has(self.file), has(self.store)].exists_one(c, c)' server: - description: Creates a remote offline server container + description: Creates a feature server container properties: env: items: @@ -5140,8 +8016,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -5244,7 +8119,7 @@ spec: envFrom: items: description: EnvFromSource represents the source - of a set of ConfigMaps + of a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -5263,8 +8138,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the + name of each environment variable. Must be + a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -5326,6 +8202,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen + for a request in the referenced claim. + type: string required: - name type: object @@ -5486,76 +8366,188 @@ spec: type: object type: object type: object - onlineStore: - description: OnlineStore configures the online store service + podAnnotations: + additionalProperties: + type: string + description: PodAnnotations are annotations to be applied + to the Deployment's PodTemplate metadata. + type: object + podDisruptionBudgets: + description: PodDisruptionBudgets configures a PodDisruptionBudget + for the FeatureStore deployment. properties: - persistence: - description: OnlineStorePersistence configures the persistence - settings for the online store service + maxUnavailable: + anyOf: + - type: integer + - type: string + description: MaxUnavailable specifies the maximum number/percentage + of pods that can be unavailable. + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + description: MinAvailable specifies the minimum number/percentage + of pods that must remain available. + x-kubernetes-int-or-string: true + type: object + x-kubernetes-validations: + - message: Exactly one of minAvailable or maxUnavailable must + be set. + rule: '[has(self.minAvailable), has(self.maxUnavailable)].exists_one(c, + c)' + registry: + description: Registry configures the registry service. One + selection is required. Local is the default setting. + properties: + local: + description: LocalRegistryConfig configures the registry + service properties: - file: - description: OnlineStoreFilePersistence configures - the file-based persistence for the online store - service + persistence: + description: RegistryPersistence configures the persistence + settings for the registry service properties: - path: - type: string - pvc: - description: PvcConfig defines the settings for - a persistent file store based on PVCs. + file: + description: RegistryFilePersistence configures + the file-based persistence for the registry + service properties: - create: - description: Settings for creating a new PVC - properties: - accessModes: - description: AccessModes k8s persistent - volume access modes. Defaults to ["ReadWriteOnce"]. - items: - type: string - type: array - resources: - description: Resources describes the storage - resource requirements for a volume. - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the - minimum amount of compute resources - required. + cache_mode: + description: |- + CacheMode defines the registry cache update strategy. + Allowed values are "sync" and "thread". + enum: + - none + - sync + - thread + type: string + cache_ttl_seconds: + description: CacheTTLSeconds defines the TTL + (in seconds) for the registry cache. + format: int32 + minimum: 0 + type: integer + path: + type: string + pvc: + description: PvcConfig defines the settings + for a persistent file store based on PVCs. + properties: + create: + description: Settings for creating a new + PVC + properties: + accessModes: + description: AccessModes k8s persistent + volume access modes. Defaults to + ["ReadWriteOnce"]. + items: + type: string + type: array + resources: + description: Resources describes the + storage resource requirements for + a volume. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes + the minimum amount of compute + resources required. + type: object type: object + storageClassName: + description: StorageClassName is the + name of an existing StorageClass + to which this persistent volume + belongs. + type: string type: object - storageClassName: - description: StorageClassName is the name - of an existing StorageClass to which - this persistent volume belongs. + x-kubernetes-validations: + - message: PvcCreate is immutable + rule: self == oldSelf + mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. type: string + ref: + description: Reference to an existing + field + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + required: + - mountPath type: object x-kubernetes-validations: - - message: PvcCreate is immutable - rule: self == oldSelf - mountPath: - description: |- - MountPath within the container at which the volume should be mounted. - Must start by "/" and cannot contain ':'. + - message: One selection is required between + ref and create. + rule: '[has(self.ref), has(self.create)].exists_one(c, + c)' + - message: Mount path must start with '/' + and must not contain ':' + rule: self.mountPath.matches('^/[^:]*$') + s3_additional_kwargs: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-validations: + - message: Registry files must use absolute paths + or be S3 ('s3://') or GS ('gs://') object + store URIs. + rule: '(!has(self.pvc) && has(self.path)) ? + (self.path.startsWith(''/'') || self.path.startsWith(''s3://'') + || self.path.startsWith(''gs://'')) : true' + - message: PVC path must be a file name only, + with no slashes. + rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') + : true' + - message: PVC persistence does not support S3 + or GS object store URIs. + rule: '(has(self.pvc) && has(self.path)) ? !(self.path.startsWith(''s3://'') + || self.path.startsWith(''gs://'')) : true' + - message: Additional S3 settings are available + only for S3 object store URIs. + rule: '(has(self.s3_additional_kwargs) && has(self.path)) + ? self.path.startsWith(''s3://'') : true' + store: + description: RegistryDBStorePersistence configures + the DB store persistence for the registry service + properties: + secretKeyName: + description: By default, the selected store + "type" is used as the SecretKeyName type: string - ref: - description: Reference to an existing field + secretRef: + description: Data store parameters should + be placed as-is from the "feature_store.yaml" + under the secret key. properties: name: default: "" @@ -5566,111 +8558,148 @@ spec: type: string type: object x-kubernetes-map-type: atomic + type: + description: Type of the persistence type + you want to use. + enum: + - sql + - snowflake.registry + type: string required: - - mountPath + - secretRef + - type type: object - x-kubernetes-validations: - - message: One selection is required between ref - and create. - rule: '[has(self.ref), has(self.create)].exists_one(c, - c)' - - message: Mount path must start with '/' and - must not contain ':' - rule: self.mountPath.matches('^/[^:]*$') type: object x-kubernetes-validations: - - message: Ephemeral stores must have absolute paths. - rule: '(!has(self.pvc) && has(self.path)) ? self.path.startsWith(''/'') - : true' - - message: PVC path must be a file name only, with - no slashes. - rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') - : true' - - message: Online store does not support S3 or GS - buckets. - rule: 'has(self.path) ? !(self.path.startsWith(''s3://'') - || self.path.startsWith(''gs://'')) : true' - store: - description: OnlineStoreDBStorePersistence configures - the DB store persistence for the online store service + - message: One selection required between file or + store. + rule: '[has(self.file), has(self.store)].exists_one(c, + c)' + server: + description: Creates a registry server container properties: - secretKeyName: - description: By default, the selected store "type" - is used as the SecretKeyName - type: string - secretRef: - description: Data store parameters should be placed - as-is from the "feature_store.yaml" under the - secret key. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - type: - description: Type of the persistence type you - want to use. - enum: - - snowflake.online - - redis - - ikv - - datastore - - dynamodb - - bigtable - - postgres - - cassandra - - mysql - - hazelcast - - singlestore - - hbase - - elasticsearch - - qdrant - - couchbase.online - - milvus - - hybrid - type: string - required: - - secretRef - - type - type: object - type: object - x-kubernetes-validations: - - message: One selection required between file or store. - rule: '[has(self.file), has(self.store)].exists_one(c, - c)' - server: - description: Creates a feature server container - properties: - env: - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. + env: + items: + description: EnvVar represents an environment + variable present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and... + type: string + valueFrom: + description: Source for the environment + variable's value. Cannot be used if value + is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the + ConfigMap or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the + pod: supports metadata.name, metadata.namespace, + `metadata.labels['''']`, `metadata.' + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env + vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret + in the pod's namespace + properties: + key: + description: The key of the secret + to select from. Must be a valid + secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the + Secret or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source + of a set of ConfigMaps or Secrets properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. + configMapRef: + description: The ConfigMap to select from properties: - key: - description: The key to select. - type: string name: default: "" description: |- @@ -5680,65 +8709,18 @@ spec: type: string optional: description: Specify whether the ConfigMap - or its key must be defined + must be defined type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: 'Selects a field of the pod: - supports metadata.name, metadata.namespace, - `metadata.labels['''']`, `metadata.' - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, - defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults - to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource type: object x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace + prefix: + description: Optional text to prepend to + the name of each environment variable. + Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string name: default: "" description: |- @@ -5748,154 +8730,266 @@ spec: type: string optional: description: Specify whether the Secret - or its key must be defined + must be defined type: boolean - required: - - key type: object x-kubernetes-map-type: atomic type: object - required: - - name - type: object - type: array - envFrom: - items: - description: EnvFromSource represents the source - of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from + type: array + grpc: + description: Enable gRPC registry server. Defaults + to true if unset. + type: boolean + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for + if/when to pull a container image + type: string + logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". + enum: + - debug + - info + - warning + - error + - critical + type: string + metrics: + description: Metrics exposes Prometheus-compatible + metrics for the Feast server when enabled. + type: boolean + nodeSelector: + additionalProperties: + type: string + type: object + resources: + description: ResourceRequirements describes the + compute resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + items: + description: ResourceClaim references one + entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. + type: string + request: + description: Request is the name chosen + for a request in the referenced claim. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum + amount of compute resources required. + type: object + type: object + restAPI: + description: Enable REST API registry server. + type: boolean + tls: + description: TlsConfigs configures server TLS + for a feast service. + properties: + disable: + description: will disable TLS for the feast + service. useful in an openshift cluster, + for example, where TLS is configured by + default + type: boolean + secretKeyNames: + description: SecretKeyNames defines the secret + key names for the TLS key and cert. + properties: + tlsCrt: + description: defaults to "tls.crt" + type: string + tlsKey: + description: defaults to "tls.key" + type: string + type: object + secretRef: + description: references the local k8s secret + where the TLS key and cert reside + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: '`secretRef` required if `disable` + is false.' + rule: '(!has(self.disable) || !self.disable) + ? has(self.secretRef) : true' + volumeMounts: + description: VolumeMounts defines the list of + volumes that should be mounted into the feast + container. + items: + description: VolumeMount describes a mounting + of a Volume within a container. properties: - name: - default: "" + mountPath: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + Path within the container at which the volume should be mounted. Must + not contain ':'. type: string - optional: - description: Specify whether the ConfigMap - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - default: "" + mountPropagation: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + mountPropagation determines how mounts are propagated from the host + to container and the other way around. type: string - optional: - description: Specify whether the Secret - must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - image: - type: string - imagePullPolicy: - description: PullPolicy describes a policy for if/when - to pull a container image - type: string - logLevel: - description: |- - LogLevel sets the logging level for the server - Allowed values: "debug", "info", "warning", "error", "critical". - enum: - - debug - - info - - warning - - error - - critical - type: string - metrics: - description: Metrics exposes Prometheus-compatible - metrics for the Feast server when enabled. - type: boolean - nodeSelector: - additionalProperties: - type: string - type: object - resources: - description: ResourceRequirements describes the compute - resource requirements. - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: name: + description: This must match the Name of + a Volume. + type: string + readOnly: description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume + from which the container's volume should + be mounted. type: string required: + - mountPath - name type: object type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the minimum amount - of compute resources required. + workerConfigs: + description: WorkerConfigs defines the worker + configuration for the Feast server. + properties: + keepAliveTimeout: + description: |- + KeepAliveTimeout is the timeout for keep-alive connections in seconds. + Defaults to 30. + format: int32 + minimum: 1 + type: integer + maxRequests: + description: |- + MaxRequests is the maximum number of requests a worker will process before restarting. + This helps prevent memory leaks. + format: int32 + minimum: 0 + type: integer + maxRequestsJitter: + description: |- + MaxRequestsJitter is the maximum jitter to add to max-requests to prevent + thundering herd effect on worker restart. + format: int32 + minimum: 0 + type: integer + registryTTLSeconds: + description: RegistryTTLSeconds is the number + of seconds after which the registry is refreshed. + format: int32 + minimum: 0 + type: integer + workerConnections: + description: |- + WorkerConnections is the maximum number of simultaneous clients per worker process. + Defaults to 1000. + format: int32 + minimum: 1 + type: integer + workers: + description: Workers is the number of worker + processes. Use -1 to auto-calculate based + on CPU cores (2 * CPU + 1). + format: int32 + minimum: -1 + type: integer type: object type: object - tls: - description: TlsConfigs configures server TLS for - a feast service. + x-kubernetes-validations: + - message: At least one of restAPI or grpc must be + true + rule: self.restAPI == true || self.grpc == true + || !has(self.grpc) + type: object + remote: + description: RemoteRegistryConfig points to a remote feast + registry server. + properties: + feastRef: + description: Reference to an existing `FeatureStore` + CR in the same k8s cluster. properties: - disable: - description: will disable TLS for the feast service. - useful in an openshift cluster, for example, - where TLS is configured by default - type: boolean - secretKeyNames: - description: SecretKeyNames defines the secret - key names for the TLS key and cert. - properties: - tlsCrt: - description: defaults to "tls.crt" - type: string - tlsKey: - description: defaults to "tls.key" - type: string - type: object - secretRef: - description: references the local k8s secret where - the TLS key and cert reside + name: + description: Name of the FeatureStore + type: string + namespace: + description: Namespace of the FeatureStore + type: string + required: + - name + type: object + hostname: + description: Host address of the remote registry service + - :, e.g. `registry..svc.cluster.local:80` + type: string + tls: + description: TlsRemoteRegistryConfigs configures client + TLS for a remote feast registry. + properties: + certName: + description: defines the configmap key name for + the client TLS cert. + type: string + configMapRef: + description: references the local k8s configmap + where the TLS cert resides properties: name: default: "" @@ -5906,719 +9000,610 @@ spec: type: string type: object x-kubernetes-map-type: atomic - type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' - volumeMounts: - description: VolumeMounts defines the list of volumes - that should be mounted into the feast container. - items: - description: VolumeMount describes a mounting of - a Volume within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: - description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. - type: string - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: Expanded path within the volume - from which the container's volume should be - mounted. - type: string - required: - - mountPath - - name - type: object - type: array - workerConfigs: - description: WorkerConfigs defines the worker configuration - for the Feast server. - properties: - keepAliveTimeout: - description: |- - KeepAliveTimeout is the timeout for keep-alive connections in seconds. - Defaults to 30. - format: int32 - minimum: 1 - type: integer - maxRequests: - description: |- - MaxRequests is the maximum number of requests a worker will process before restarting. - This helps prevent memory leaks. - format: int32 - minimum: 0 - type: integer - maxRequestsJitter: - description: |- - MaxRequestsJitter is the maximum jitter to add to max-requests to prevent - thundering herd effect on worker restart. - format: int32 - minimum: 0 - type: integer - registryTTLSeconds: - description: RegistryTTLSeconds is the number - of seconds after which the registry is refreshed. - format: int32 - minimum: 0 - type: integer - workerConnections: - description: |- - WorkerConnections is the maximum number of simultaneous clients per worker process. - Defaults to 1000. - format: int32 - minimum: 1 - type: integer - workers: - description: Workers is the number of worker processes. - Use -1 to auto-calculate based on CPU cores - (2 * CPU + 1). - format: int32 - minimum: -1 - type: integer + required: + - certName + - configMapRef type: object type: object + x-kubernetes-validations: + - message: One selection required. + rule: '[has(self.hostname), has(self.feastRef)].exists_one(c, + c)' type: object - registry: - description: Registry configures the registry service. One - selection is required. Local is the default setting. - properties: - local: - description: LocalRegistryConfig configures the registry - service - properties: - persistence: - description: RegistryPersistence configures the persistence - settings for the registry service - properties: - file: - description: RegistryFilePersistence configures - the file-based persistence for the registry - service - properties: - cache_mode: - description: |- - CacheMode defines the registry cache update strategy. - Allowed values are "sync" and "thread". - enum: - - none - - sync - - thread - type: string - cache_ttl_seconds: - description: CacheTTLSeconds defines the TTL - (in seconds) for the registry cache. - format: int32 - minimum: 0 - type: integer - path: - type: string - pvc: - description: PvcConfig defines the settings - for a persistent file store based on PVCs. - properties: - create: - description: Settings for creating a new - PVC - properties: - accessModes: - description: AccessModes k8s persistent - volume access modes. Defaults to - ["ReadWriteOnce"]. - items: - type: string - type: array - resources: - description: Resources describes the - storage resource requirements for - a volume. - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes - the minimum amount of compute - resources required. - type: object - type: object - storageClassName: - description: StorageClassName is the - name of an existing StorageClass - to which this persistent volume - belongs. - type: string - type: object - x-kubernetes-validations: - - message: PvcCreate is immutable - rule: self == oldSelf - mountPath: - description: |- - MountPath within the container at which the volume should be mounted. - Must start by "/" and cannot contain ':'. - type: string - ref: - description: Reference to an existing - field - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - mountPath - type: object - x-kubernetes-validations: - - message: One selection is required between - ref and create. - rule: '[has(self.ref), has(self.create)].exists_one(c, - c)' - - message: Mount path must start with '/' - and must not contain ':' - rule: self.mountPath.matches('^/[^:]*$') - s3_additional_kwargs: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-validations: - - message: Registry files must use absolute paths - or be S3 ('s3://') or GS ('gs://') object - store URIs. - rule: '(!has(self.pvc) && has(self.path)) ? - (self.path.startsWith(''/'') || self.path.startsWith(''s3://'') - || self.path.startsWith(''gs://'')) : true' - - message: PVC path must be a file name only, - with no slashes. - rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') - : true' - - message: PVC persistence does not support S3 - or GS object store URIs. - rule: '(has(self.pvc) && has(self.path)) ? !(self.path.startsWith(''s3://'') - || self.path.startsWith(''gs://'')) : true' - - message: Additional S3 settings are available - only for S3 object store URIs. - rule: '(has(self.s3_additional_kwargs) && has(self.path)) - ? self.path.startsWith(''s3://'') : true' - store: - description: RegistryDBStorePersistence configures - the DB store persistence for the registry service + x-kubernetes-validations: + - message: One selection required. + rule: '[has(self.local), has(self.remote)].exists_one(c, + c)' + runFeastApplyOnInit: + description: Runs feast apply on pod start to populate the + registry. Defaults to true. Ignored when DisableInitContainers + is true. + type: boolean + scaling: + description: Scaling configures horizontal scaling for the + FeatureStore deployment (e.g. HPA autoscaling). + properties: + autoscaling: + description: |- + Autoscaling configures a HorizontalPodAutoscaler for the FeatureStore deployment. + Mutually exclusive with spec.replicas. + properties: + behavior: + description: Behavior configures the scaling behavior + of the target. + properties: + scaleDown: + description: scaleDown is scaling policy for scaling + Down. properties: - secretKeyName: - description: By default, the selected store - "type" is used as the SecretKeyName + policies: + description: policies is a list of potential + scaling polices which can be used during + scaling. + items: + description: HPAScalingPolicy is a single + policy which must hold true for a specified + past interval. + properties: + periodSeconds: + description: periodSeconds specifies + the window of time for which the policy + should hold true. + format: int32 + type: integer + type: + description: type is used to specify + the scaling policy. + type: string + value: + description: |- + value contains the amount of change which is permitted by the policy. + It must be greater than zero + format: int32 + type: integer + required: + - periodSeconds + - type + - value + type: object + type: array + x-kubernetes-list-type: atomic + selectPolicy: + description: |- + selectPolicy is used to specify which policy should be used. + If not set, the default value Max is used. type: string - secretRef: - description: Data store parameters should - be placed as-is from the "feature_store.yaml" - under the secret key. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - type: - description: Type of the persistence type - you want to use. - enum: - - sql - - snowflake.registry + stabilizationWindowSeconds: + description: |- + stabilizationWindowSeconds is the number of seconds for which past recommendations should be + considered while scaling... + format: int32 + type: integer + tolerance: + anyOf: + - type: integer + - type: string + description: |- + tolerance is the tolerance on the ratio between the current and desired + metric value under which no updates are made to... + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + scaleUp: + description: scaleUp is scaling policy for scaling + Up. + properties: + policies: + description: policies is a list of potential + scaling polices which can be used during + scaling. + items: + description: HPAScalingPolicy is a single + policy which must hold true for a specified + past interval. + properties: + periodSeconds: + description: periodSeconds specifies + the window of time for which the policy + should hold true. + format: int32 + type: integer + type: + description: type is used to specify + the scaling policy. + type: string + value: + description: |- + value contains the amount of change which is permitted by the policy. + It must be greater than zero + format: int32 + type: integer + required: + - periodSeconds + - type + - value + type: object + type: array + x-kubernetes-list-type: atomic + selectPolicy: + description: |- + selectPolicy is used to specify which policy should be used. + If not set, the default value Max is used. type: string - required: - - secretRef - - type + stabilizationWindowSeconds: + description: |- + stabilizationWindowSeconds is the number of seconds for which past recommendations should be + considered while scaling... + format: int32 + type: integer + tolerance: + anyOf: + - type: integer + - type: string + description: |- + tolerance is the tolerance on the ratio between the current and desired + metric value under which no updates are made to... + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true type: object type: object - x-kubernetes-validations: - - message: One selection required between file or - store. - rule: '[has(self.file), has(self.store)].exists_one(c, - c)' - server: - description: Creates a registry server container - properties: - env: - items: - description: EnvVar represents an environment - variable present in a Container. + maxReplicas: + description: MaxReplicas is the upper limit for the + number of replicas. Required. + format: int32 + minimum: 1 + type: integer + metrics: + description: Metrics contains the specifications for + which to use to calculate the desired replica count. + items: + description: |- + MetricSpec specifies how to scale based on a single metric + (only `type` and one other matching field should be set at... + properties: + containerResource: + description: |- + containerResource refers to a resource metric (such as those specified in + requests and limits) known to Kubernetes... properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. + container: + description: container is the name of the + container in the pods of the scaling target type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + name: + description: name is the name of the resource + in question. type: string - valueFrom: - description: Source for the environment - variable's value. Cannot be used if value - is not empty. + target: + description: target specifies the target + value for the given metric properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the - ConfigMap or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: 'Selects a field of the - pod: supports metadata.name, metadata.namespace, - `metadata.labels['''']`, `metadata.' - properties: - apiVersion: - description: Version of the schema - the FieldPath is written in terms - of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to - select in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: + averageUtilization: description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env - vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output - format of the exposed resources, - defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource - to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret - in the pod's namespace + averageUtilization is the target value of the average of the + resource metric across all relevant pods, represented as a... + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether + the metric type is Utilization, Value, + or AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value + of the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - container + - name + - target + type: object + external: + description: |- + external refers to a global metric that is not associated + with any Kubernetes object. + properties: + metric: + description: metric identifies the target + metric by name and selector + properties: + name: + description: name is the name of the + given metric + type: string + selector: + description: |- + selector is the string-encoded form of a standard kubernetes label selector for the given metric + When set, it is passed... properties: - key: - description: The key of the secret - to select from. Must be a valid - secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the - Secret or its key must be defined - type: boolean - required: - - key + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. + type: object type: object x-kubernetes-map-type: atomic + required: + - name + type: object + target: + description: target specifies the target + value for the given metric + properties: + averageUtilization: + description: |- + averageUtilization is the target value of the average of the + resource metric across all relevant pods, represented as a... + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether + the metric type is Utilization, Value, + or AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value + of the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type type: object required: - - name + - metric + - target type: object - type: array - envFrom: - items: - description: EnvFromSource represents the source - of a set of ConfigMaps + object: + description: |- + object refers to a metric describing a single kubernetes object + (for example, hits-per-second on an Ingress object). properties: - configMapRef: - description: The ConfigMap to select from + describedObject: + description: describedObject specifies the + descriptions of a object,such as kind,name + apiVersion properties: + apiVersion: + description: apiVersion is the API version + of the referent + type: string + kind: + description: 'kind is the kind of the + referent; More info: https://git.k8s.' + type: string name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + description: 'name is the name of the + referent; More info: https://kubernetes.' type: string - optional: - description: Specify whether the ConfigMap - must be defined - type: boolean + required: + - kind + - name type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be - a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from + metric: + description: metric identifies the target + metric by name and selector properties: name: - default: "" + description: name is the name of the + given metric + type: string + selector: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + selector is the string-encoded form of a standard kubernetes label selector for the given metric + When set, it is passed... + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - name + type: object + target: + description: target specifies the target + value for the given metric + properties: + averageUtilization: + description: |- + averageUtilization is the target value of the average of the + resource metric across all relevant pods, represented as a... + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether + the metric type is Utilization, Value, + or AverageValue type: string - optional: - description: Specify whether the Secret - must be defined - type: boolean + value: + anyOf: + - type: integer + - type: string + description: value is the target value + of the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type type: object - x-kubernetes-map-type: atomic + required: + - describedObject + - metric + - target type: object - type: array - grpc: - description: Enable gRPC registry server. Defaults - to true if unset. - type: boolean - image: - type: string - imagePullPolicy: - description: PullPolicy describes a policy for - if/when to pull a container image - type: string - logLevel: - description: |- - LogLevel sets the logging level for the server - Allowed values: "debug", "info", "warning", "error", "critical". - enum: - - debug - - info - - warning - - error - - critical - type: string - metrics: - description: Metrics exposes Prometheus-compatible - metrics for the Feast server when enabled. - type: boolean - nodeSelector: - additionalProperties: - type: string - type: object - resources: - description: ResourceRequirements describes the - compute resource requirements. - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - items: - description: ResourceClaim references one - entry in PodSpec.ResourceClaims. + pods: + description: |- + pods refers to a metric describing each pod in the current scale target + (for example,... + properties: + metric: + description: metric identifies the target + metric by name and selector properties: name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. + description: name is the name of the + given metric type: string + selector: + description: |- + selector is the string-encoded form of a standard kubernetes label selector for the given metric + When set, it is passed... + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic required: - name type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the minimum - amount of compute resources required. - type: object - type: object - restAPI: - description: Enable REST API registry server. - type: boolean - tls: - description: TlsConfigs configures server TLS - for a feast service. - properties: - disable: - description: will disable TLS for the feast - service. useful in an openshift cluster, - for example, where TLS is configured by - default - type: boolean - secretKeyNames: - description: SecretKeyNames defines the secret - key names for the TLS key and cert. - properties: - tlsCrt: - description: defaults to "tls.crt" - type: string - tlsKey: - description: defaults to "tls.key" - type: string - type: object - secretRef: - description: references the local k8s secret - where the TLS key and cert reside - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` - is false.' - rule: '(!has(self.disable) || !self.disable) - ? has(self.secretRef) : true' - volumeMounts: - description: VolumeMounts defines the list of - volumes that should be mounted into the feast - container. - items: - description: VolumeMount describes a mounting - of a Volume within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - type: string - name: - description: This must match the Name of - a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: - description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. - type: string - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: Expanded path within the volume - from which the container's volume should - be mounted. + target: + description: target specifies the target + value for the given metric + properties: + averageUtilization: + description: |- + averageUtilization is the target value of the average of the + resource metric across all relevant pods, represented as a... + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether + the metric type is Utilization, Value, + or AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value + of the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - metric + - target + type: object + resource: + description: |- + resource refers to a resource metric (such as those specified in + requests and limits) known to Kubernetes describing... + properties: + name: + description: name is the name of the resource + in question. type: string + target: + description: target specifies the target + value for the given metric + properties: + averageUtilization: + description: |- + averageUtilization is the target value of the average of the + resource metric across all relevant pods, represented as a... + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether + the metric type is Utilization, Value, + or AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value + of the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object required: - - mountPath - name + - target type: object - type: array - workerConfigs: - description: WorkerConfigs defines the worker - configuration for the Feast server. - properties: - keepAliveTimeout: - description: |- - KeepAliveTimeout is the timeout for keep-alive connections in seconds. - Defaults to 30. - format: int32 - minimum: 1 - type: integer - maxRequests: - description: |- - MaxRequests is the maximum number of requests a worker will process before restarting. - This helps prevent memory leaks. - format: int32 - minimum: 0 - type: integer - maxRequestsJitter: - description: |- - MaxRequestsJitter is the maximum jitter to add to max-requests to prevent - thundering herd effect on worker restart. - format: int32 - minimum: 0 - type: integer - registryTTLSeconds: - description: RegistryTTLSeconds is the number - of seconds after which the registry is refreshed. - format: int32 - minimum: 0 - type: integer - workerConnections: - description: |- - WorkerConnections is the maximum number of simultaneous clients per worker process. - Defaults to 1000. - format: int32 - minimum: 1 - type: integer - workers: - description: Workers is the number of worker - processes. Use -1 to auto-calculate based - on CPU cores (2 * CPU + 1). - format: int32 - minimum: -1 - type: integer - type: object - type: object - x-kubernetes-validations: - - message: At least one of restAPI or grpc must be - true - rule: self.restAPI == true || self.grpc == true - || !has(self.grpc) - type: object - remote: - description: RemoteRegistryConfig points to a remote feast - registry server. - properties: - feastRef: - description: Reference to an existing `FeatureStore` - CR in the same k8s cluster. - properties: - name: - description: Name of the FeatureStore - type: string - namespace: - description: Namespace of the FeatureStore - type: string - required: - - name - type: object - hostname: - description: Host address of the remote registry service - - :, e.g. `registry..svc.cluster.local:80` - type: string - tls: - description: TlsRemoteRegistryConfigs configures client - TLS for a remote feast registry. - properties: - certName: - description: defines the configmap key name for - the client TLS cert. - type: string - configMapRef: - description: references the local k8s configmap - where the TLS cert resides - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - certName - - configMapRef - type: object + type: + description: type is the type of metric source. + type: string + required: + - type + type: object + type: array + minReplicas: + description: MinReplicas is the lower limit for the + number of replicas. Defaults to 1. + format: int32 + minimum: 1 + type: integer + required: + - maxReplicas type: object - x-kubernetes-validations: - - message: One selection required. - rule: '[has(self.hostname), has(self.feastRef)].exists_one(c, - c)' type: object - x-kubernetes-validations: - - message: One selection required. - rule: '[has(self.local), has(self.remote)].exists_one(c, - c)' securityContext: description: PodSecurityContext holds pod-level security attributes and common container settings. @@ -6664,6 +9649,11 @@ spec: Defaults to user specified in image metadata if unspecified. format: int64 type: integer + seLinuxChangePolicy: + description: seLinuxChangePolicy defines how the container's + SELinux label is applied to all volumes used by the + Pod. + type: string seLinuxOptions: description: The SELinux context to be applied to all containers. @@ -6703,13 +9693,18 @@ spec: type: object supplementalGroups: description: |- - A list of groups applied to the first process run in each container, in addition - to the container's primary GID, the fsG + A list of groups applied to the first process run in each container, in + addition to the container's primary GID and... items: format: int64 type: integer type: array x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + description: |- + Defines how supplemental groups of the first container processes are calculated. + Valid values are "Merge" and "Strict". + type: string sysctls: description: Sysctls hold a list of namespaced sysctls used for the pod. @@ -6752,6 +9747,98 @@ spec: type: string type: object type: object + topologySpreadConstraints: + description: TopologySpreadConstraints defines how pods are + spread across topology domains. + items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. + properties: + labelSelector: + description: LabelSelector is used to find matching + pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. + format: int32 + type: integer + minDomains: + description: MinDomains indicates a minimum number of + eligible domains. + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread... + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. + type: string + topologyKey: + description: TopologyKey is the key of node labels. + type: string + whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array ui: description: Creates a UI server container properties: @@ -6767,8 +9854,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -6868,7 +9954,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -6887,8 +9973,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -6950,6 +10036,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen for + a request in the referenced claim. + type: string required: - name type: object @@ -7118,7 +10208,7 @@ spec: awsElasticBlockStore: description: |- awsElasticBlockStore represents an AWS Disk resource that is attached to a - kubelet's host machine and then exposed to th + kubelet's host machine and then exposed to... properties: fsType: description: fsType is the filesystem type of the @@ -7160,6 +10250,7 @@ spec: the blob storage type: string fsType: + default: ext4 description: |- fsType is Filesystem type to mount. Must be a filesystem type supported by the host operating system. @@ -7168,9 +10259,10 @@ spec: kind: description: 'kind expected values are Shared: multiple blob disks per storage account Dedicated: single - blob disk per storage accoun' + blob disk per storage...' type: string readOnly: + default: false description: |- readOnly Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. @@ -7201,7 +10293,7 @@ spec: type: object cephfs: description: cephFS represents a Ceph FS mount on the - host that shares a pod's lifetime + host that shares a pod's lifetime. properties: monitors: description: |- @@ -7250,7 +10342,7 @@ spec: cinder: description: |- cinder represents a cinder volume attached and mounted on kubelets host machine. - More info: https://examples.k8s. + Deprecated: Cinder is deprecated. properties: fsType: description: |- @@ -7296,7 +10388,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volum + ConfigMap will be projected into the... items: description: Maps a string key to a path within a volume. @@ -7336,7 +10428,7 @@ spec: csi: description: csi (Container Storage Interface) represents ephemeral storage that is handled by certain external - CSI drivers (Beta fea + CSI drivers. properties: driver: description: driver is the name of the CSI driver @@ -7349,7 +10441,7 @@ spec: nodePublishSecretRef: description: |- nodePublishSecretRef is a reference to the secret object containing - sensitive information to pass to the CSI driver to c + sensitive information to pass to the CSI driver to... properties: name: default: "" @@ -7413,7 +10505,7 @@ spec: mode: description: |- Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal valu + between 0000 and 0777 or a decimal... format: int32 type: integer path: @@ -7665,9 +10757,9 @@ spec: type: array x-kubernetes-list-type: atomic wwids: - description: "wwids Optional: FC volume world wide - identifiers (wwids)\nEither wwids or combination - of targetWWNs and lun must be set, " + description: |- + wwids Optional: FC volume world wide identifiers (wwids) + Either wwids or combination of targetWWNs and lun must be set,... items: type: string type: array @@ -7702,7 +10794,7 @@ spec: secretRef: description: |- secretRef is Optional: secretRef is reference to the secret object containing - sensitive information to pass to the plugi + sensitive information to pass to the... properties: name: default: "" @@ -7723,7 +10815,7 @@ spec: datasetName: description: |- datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker - should be considered as depreca + should be considered as... type: string datasetUUID: description: datasetUUID is the UUID of the dataset. @@ -7733,7 +10825,7 @@ spec: gcePersistentDisk: description: |- gcePersistentDisk represents a GCE Disk resource that is attached to a - kubelet's host machine and then exposed to the po + kubelet's host machine and then exposed to the... properties: fsType: description: fsType is filesystem type of the volume @@ -7762,7 +10854,7 @@ spec: gitRepo: description: |- gitRepo represents a git repository at a particular revision. - DEPRECATED: GitRepo is deprecated. + Deprecated: GitRepo is deprecated. properties: directory: description: |- @@ -7780,9 +10872,8 @@ spec: - repository type: object glusterfs: - description: |- - glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. - More info: https://examples.k8s. + description: glusterfs represents a Glusterfs mount + on the host that shares a pod's lifetime. properties: endpoints: description: |- @@ -7822,6 +10913,22 @@ spec: required: - path type: object + image: + description: image represents an OCI object (a container + image or artifact) pulled and mounted on the kubelet's + host machine. + properties: + pullPolicy: + description: |- + Policy for pulling OCI objects. Possible values are: + Always: the kubelet always attempts to pull the reference. + type: string + reference: + description: |- + Required: Image or artifact reference to be used. + Behaves in the same way as pod.spec.containers[*].image. + type: string + type: object iscsi: description: |- iscsi represents an ISCSI Disk resource that is attached to a @@ -7847,6 +10954,7 @@ spec: description: iqn is the target iSCSI Qualified Name. type: string iscsiInterface: + default: default description: |- iscsiInterface is the interface Name that uses an iSCSI transport. Defaults to 'default' (tcp). @@ -7938,7 +11046,7 @@ spec: photonPersistentDisk: description: photonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host - machine + machine. properties: fsType: description: |- @@ -7955,7 +11063,7 @@ spec: type: object portworxVolume: description: portworxVolume represents a portworx volume - attached and mounted on kubelets host machine + attached and mounted on kubelets host machine. properties: fsType: description: |- @@ -7985,10 +11093,13 @@ spec: format: int32 type: integer sources: - description: sources is the list of volume projections + description: |- + sources is the list of volume projections. Each entry in this list + handles one source. items: - description: Projection that may be projected - along with other supported volume types + description: |- + Projection that may be projected along with other supported volume types. + Exactly one of these fields must be set. properties: clusterTrustBundle: description: ClusterTrustBundle allows a pod @@ -8069,7 +11180,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volum + ConfigMap will be projected into the... items: description: Maps a string key to a path within a volume. @@ -8142,7 +11253,7 @@ spec: mode: description: |- Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal valu + between 0000 and 0777 or a decimal... format: int32 type: integer path: @@ -8191,7 +11302,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume a + Secret will be projected into the volume... items: description: Maps a string key to a path within a volume. @@ -8257,7 +11368,7 @@ spec: type: object quobyte: description: quobyte represents a Quobyte mount on the - host that shares a pod's lifetime + host that shares a pod's lifetime. properties: group: description: |- @@ -8272,12 +11383,12 @@ spec: registry: description: |- registry represents a single or multiple Quobyte Registry services - specified as a string as host:port pair (multiple ent + specified as a string as host:port pair (multiple... type: string tenant: description: |- tenant owning the given Quobyte volume in the Backend - Used with dynamically provisioned Quobyte volumes, value is set by + Used with dynamically provisioned Quobyte volumes, value is set... type: string user: description: |- @@ -8293,9 +11404,8 @@ spec: - volume type: object rbd: - description: |- - rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. - More info: https://examples.k8s. + description: rbd represents a Rados Block Device mount + on the host that shares a pod's lifetime. properties: fsType: description: fsType is the filesystem type of the @@ -8307,6 +11417,7 @@ spec: More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it type: string keyring: + default: /etc/ceph/keyring description: |- keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. @@ -8321,6 +11432,7 @@ spec: type: array x-kubernetes-list-type: atomic pool: + default: rbd description: |- pool is the rados pool name. Default is rbd. @@ -8348,6 +11460,7 @@ spec: type: object x-kubernetes-map-type: atomic user: + default: admin description: |- user is the rados user name. Default is admin. @@ -8362,6 +11475,7 @@ spec: volume attached and mounted on Kubernetes nodes. properties: fsType: + default: xfs description: |- fsType is the filesystem type to mount. Must be a filesystem type supported by the host operating system. @@ -8399,6 +11513,7 @@ spec: communication with Gateway, default false type: boolean storageMode: + default: ThinProvisioned description: storageMode indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. type: string @@ -8433,7 +11548,7 @@ spec: items: description: |- items If unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume a + Secret will be projected into the volume... items: description: Maps a string key to a path within a volume. @@ -8508,7 +11623,7 @@ spec: type: object vsphereVolume: description: vsphereVolume represents a vSphere volume - attached and mounted on kubelets host machine + attached and mounted on kubelets host machine. properties: fsType: description: |- @@ -8540,6 +11655,37 @@ spec: required: - feastProject type: object + x-kubernetes-validations: + - message: replicas > 1 and services.scaling.autoscaling are mutually + exclusive. + rule: self.replicas <= 1 || !has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling) + - message: Scaling requires DB-backed persistence for the online store. + Configure services.onlineStore.persistence.store when using replicas + > 1 or autoscaling. + rule: self.replicas <= 1 && (!has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling)) || (has(self.services) + && has(self.services.onlineStore) && has(self.services.onlineStore.persistence) + && has(self.services.onlineStore.persistence.store)) + - message: Scaling requires DB-backed persistence for the offline + store. Configure services.offlineStore.persistence.store when + using replicas > 1 or autoscaling. + rule: self.replicas <= 1 && (!has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling)) || (!has(self.services) + || !has(self.services.offlineStore) || (has(self.services.offlineStore.persistence) + && has(self.services.offlineStore.persistence.store))) + - message: Scaling requires DB-backed or remote registry. Configure + registry.local.persistence.store or use a remote registry when + using replicas > 1 or autoscaling. S3/GCS-backed registry is also + allowed. + rule: self.replicas <= 1 && (!has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling)) || (has(self.services) + && has(self.services.registry) && (has(self.services.registry.remote) + || (has(self.services.registry.local) && has(self.services.registry.local.persistence) + && (has(self.services.registry.local.persistence.store) || (has(self.services.registry.local.persistence.file) + && has(self.services.registry.local.persistence.file.path) && + (self.services.registry.local.persistence.file.path.startsWith('s3://') + || self.services.registry.local.persistence.file.path.startsWith('gs://'))))))) clientConfigMap: description: ConfigMap in this namespace containing a client `feature_store.yaml` for this feast deployment @@ -8582,10 +11728,7 @@ spec: - Unknown type: string type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition. + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -8604,6 +11747,28 @@ spec: type: string phase: type: string + replicas: + description: Replicas is the current number of ready pod replicas + (used by the scale sub-resource). + format: int32 + type: integer + scalingStatus: + description: ScalingStatus reports the current scaling state of the + FeatureStore deployment. + properties: + currentReplicas: + description: CurrentReplicas is the current number of pod replicas. + format: int32 + type: integer + desiredReplicas: + description: DesiredReplicas is the desired number of pod replicas. + format: int32 + type: integer + type: object + selector: + description: Selector is the label selector for pods managed by the + FeatureStore deployment (used by the scale sub-resource). + type: string serviceHostnames: description: ServiceHostnames defines the service hostnames in the format of :, e.g. example.svc.cluster.local:80 @@ -8624,6 +11789,10 @@ spec: served: true storage: true subresources: + scale: + labelSelectorPath: .status.selector + specReplicasPath: .spec.replicas + statusReplicasPath: .status.replicas status: {} - additionalPrinterColumns: - jsonPath: .status.phase @@ -8730,8 +11899,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's value. @@ -8830,7 +11998,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of a set - of ConfigMaps + of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -8849,8 +12017,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -8896,6 +12064,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen for a request + in the referenced claim. + type: string required: - name type: object @@ -8937,7 +12109,7 @@ spec: activeDeadlineSeconds: description: |- Specifies the duration in seconds relative to the startTime that the job - may be continuously active before the system tr + may be continuously active before the system... format: int64 type: integer backoffLimit: @@ -9120,8 +12292,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's value. @@ -9220,7 +12391,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of a set - of ConfigMaps + of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -9239,8 +12410,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -9294,7 +12465,6 @@ spec: - hbase - cassandra - hazelcast - - ikv - couchbase - clickhouse type: string @@ -9495,8 +12665,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -9596,7 +12765,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -9615,8 +12784,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -9678,6 +12847,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen for + a request in the referenced claim. + type: string required: - name type: object @@ -9966,7 +13139,6 @@ spec: enum: - snowflake.online - redis - - ikv - datastore - dynamodb - bigtable @@ -9981,6 +13153,7 @@ spec: - couchbase.online - milvus - hybrid + - mongodb type: string required: - secretRef @@ -10005,8 +13178,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -10106,7 +13278,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -10125,8 +13297,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -10188,6 +13360,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen for + a request in the referenced claim. + type: string required: - name type: object @@ -10533,8 +13709,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -10637,7 +13812,7 @@ spec: envFrom: items: description: EnvFromSource represents the source - of a set of ConfigMaps + of a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -10656,8 +13831,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the + name of each environment variable. Must be + a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -10723,6 +13899,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen + for a request in the referenced claim. + type: string required: - name type: object @@ -10944,6 +14124,10 @@ spec: x-kubernetes-validations: - message: One selection required. rule: '[has(self.local), has(self.remote)].exists_one(c, c)' + runFeastApplyOnInit: + description: Runs feast apply on pod start to populate the registry. + Defaults to true. Ignored when DisableInitContainers is true. + type: boolean securityContext: description: PodSecurityContext holds pod-level security attributes and common container settings. @@ -10989,6 +14173,10 @@ spec: Defaults to user specified in image metadata if unspecified. format: int64 type: integer + seLinuxChangePolicy: + description: seLinuxChangePolicy defines how the container's + SELinux label is applied to all volumes used by the Pod. + type: string seLinuxOptions: description: The SELinux context to be applied to all containers. properties: @@ -11027,13 +14215,18 @@ spec: type: object supplementalGroups: description: |- - A list of groups applied to the first process run in each container, in addition - to the container's primary GID, the fsG + A list of groups applied to the first process run in each container, in + addition to the container's primary GID and... items: format: int64 type: integer type: array x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + description: |- + Defines how supplemental groups of the first container processes are calculated. + Valid values are "Merge" and "Strict". + type: string sysctls: description: Sysctls hold a list of namespaced sysctls used for the pod. @@ -11090,8 +14283,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's value. @@ -11190,7 +14382,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of a set - of ConfigMaps + of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -11209,8 +14401,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -11271,6 +14463,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen for a request + in the referenced claim. + type: string required: - name type: object @@ -11439,7 +14635,7 @@ spec: awsElasticBlockStore: description: |- awsElasticBlockStore represents an AWS Disk resource that is attached to a - kubelet's host machine and then exposed to th + kubelet's host machine and then exposed to... properties: fsType: description: fsType is the filesystem type of the volume @@ -11481,6 +14677,7 @@ spec: blob storage type: string fsType: + default: ext4 description: |- fsType is Filesystem type to mount. Must be a filesystem type supported by the host operating system. @@ -11489,9 +14686,10 @@ spec: kind: description: 'kind expected values are Shared: multiple blob disks per storage account Dedicated: single - blob disk per storage accoun' + blob disk per storage...' type: string readOnly: + default: false description: |- readOnly Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. @@ -11522,7 +14720,7 @@ spec: type: object cephfs: description: cephFS represents a Ceph FS mount on the host - that shares a pod's lifetime + that shares a pod's lifetime. properties: monitors: description: |- @@ -11570,7 +14768,7 @@ spec: cinder: description: |- cinder represents a cinder volume attached and mounted on kubelets host machine. - More info: https://examples.k8s. + Deprecated: Cinder is deprecated. properties: fsType: description: |- @@ -11616,7 +14814,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volum + ConfigMap will be projected into the... items: description: Maps a string key to a path within a volume. @@ -11656,7 +14854,7 @@ spec: csi: description: csi (Container Storage Interface) represents ephemeral storage that is handled by certain external - CSI drivers (Beta fea + CSI drivers. properties: driver: description: driver is the name of the CSI driver that @@ -11668,7 +14866,7 @@ spec: nodePublishSecretRef: description: |- nodePublishSecretRef is a reference to the secret object containing - sensitive information to pass to the CSI driver to c + sensitive information to pass to the CSI driver to... properties: name: default: "" @@ -11730,7 +14928,7 @@ spec: mode: description: |- Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal valu + between 0000 and 0777 or a decimal... format: int32 type: integer path: @@ -11979,9 +15177,9 @@ spec: type: array x-kubernetes-list-type: atomic wwids: - description: "wwids Optional: FC volume world wide identifiers - (wwids)\nEither wwids or combination of targetWWNs - and lun must be set, " + description: |- + wwids Optional: FC volume world wide identifiers (wwids) + Either wwids or combination of targetWWNs and lun must be set,... items: type: string type: array @@ -12016,7 +15214,7 @@ spec: secretRef: description: |- secretRef is Optional: secretRef is reference to the secret object containing - sensitive information to pass to the plugi + sensitive information to pass to the... properties: name: default: "" @@ -12037,7 +15235,7 @@ spec: datasetName: description: |- datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker - should be considered as depreca + should be considered as... type: string datasetUUID: description: datasetUUID is the UUID of the dataset. @@ -12047,7 +15245,7 @@ spec: gcePersistentDisk: description: |- gcePersistentDisk represents a GCE Disk resource that is attached to a - kubelet's host machine and then exposed to the po + kubelet's host machine and then exposed to the... properties: fsType: description: fsType is filesystem type of the volume @@ -12076,7 +15274,7 @@ spec: gitRepo: description: |- gitRepo represents a git repository at a particular revision. - DEPRECATED: GitRepo is deprecated. + Deprecated: GitRepo is deprecated. properties: directory: description: |- @@ -12094,9 +15292,8 @@ spec: - repository type: object glusterfs: - description: |- - glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. - More info: https://examples.k8s. + description: glusterfs represents a Glusterfs mount on the + host that shares a pod's lifetime. properties: endpoints: description: |- @@ -12136,6 +15333,22 @@ spec: required: - path type: object + image: + description: image represents an OCI object (a container + image or artifact) pulled and mounted on the kubelet's + host machine. + properties: + pullPolicy: + description: |- + Policy for pulling OCI objects. Possible values are: + Always: the kubelet always attempts to pull the reference. + type: string + reference: + description: |- + Required: Image or artifact reference to be used. + Behaves in the same way as pod.spec.containers[*].image. + type: string + type: object iscsi: description: |- iscsi represents an ISCSI Disk resource that is attached to a @@ -12161,6 +15374,7 @@ spec: description: iqn is the target iSCSI Qualified Name. type: string iscsiInterface: + default: default description: |- iscsiInterface is the interface Name that uses an iSCSI transport. Defaults to 'default' (tcp). @@ -12251,7 +15465,7 @@ spec: photonPersistentDisk: description: photonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host - machine + machine. properties: fsType: description: |- @@ -12268,7 +15482,7 @@ spec: type: object portworxVolume: description: portworxVolume represents a portworx volume - attached and mounted on kubelets host machine + attached and mounted on kubelets host machine. properties: fsType: description: |- @@ -12298,10 +15512,13 @@ spec: format: int32 type: integer sources: - description: sources is the list of volume projections + description: |- + sources is the list of volume projections. Each entry in this list + handles one source. items: - description: Projection that may be projected along - with other supported volume types + description: |- + Projection that may be projected along with other supported volume types. + Exactly one of these fields must be set. properties: clusterTrustBundle: description: ClusterTrustBundle allows a pod to @@ -12381,7 +15598,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volum + ConfigMap will be projected into the... items: description: Maps a string key to a path within a volume. @@ -12452,7 +15669,7 @@ spec: mode: description: |- Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal valu + between 0000 and 0777 or a decimal... format: int32 type: integer path: @@ -12501,7 +15718,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume a + Secret will be projected into the volume... items: description: Maps a string key to a path within a volume. @@ -12567,7 +15784,7 @@ spec: type: object quobyte: description: quobyte represents a Quobyte mount on the host - that shares a pod's lifetime + that shares a pod's lifetime. properties: group: description: |- @@ -12582,12 +15799,12 @@ spec: registry: description: |- registry represents a single or multiple Quobyte Registry services - specified as a string as host:port pair (multiple ent + specified as a string as host:port pair (multiple... type: string tenant: description: |- tenant owning the given Quobyte volume in the Backend - Used with dynamically provisioned Quobyte volumes, value is set by + Used with dynamically provisioned Quobyte volumes, value is set... type: string user: description: |- @@ -12603,9 +15820,8 @@ spec: - volume type: object rbd: - description: |- - rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. - More info: https://examples.k8s. + description: rbd represents a Rados Block Device mount on + the host that shares a pod's lifetime. properties: fsType: description: fsType is the filesystem type of the volume @@ -12617,6 +15833,7 @@ spec: More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it type: string keyring: + default: /etc/ceph/keyring description: |- keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. @@ -12631,6 +15848,7 @@ spec: type: array x-kubernetes-list-type: atomic pool: + default: rbd description: |- pool is the rados pool name. Default is rbd. @@ -12658,6 +15876,7 @@ spec: type: object x-kubernetes-map-type: atomic user: + default: admin description: |- user is the rados user name. Default is admin. @@ -12672,6 +15891,7 @@ spec: attached and mounted on Kubernetes nodes. properties: fsType: + default: xfs description: |- fsType is the filesystem type to mount. Must be a filesystem type supported by the host operating system. @@ -12709,6 +15929,7 @@ spec: with Gateway, default false type: boolean storageMode: + default: ThinProvisioned description: storageMode indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. type: string @@ -12743,7 +15964,7 @@ spec: items: description: |- items If unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume a + Secret will be projected into the volume... items: description: Maps a string key to a path within a volume. @@ -12818,7 +16039,7 @@ spec: type: object vsphereVolume: description: vsphereVolume represents a vSphere volume attached - and mounted on kubelets host machine + and mounted on kubelets host machine. properties: fsType: description: |- @@ -12934,8 +16155,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -13035,7 +16255,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -13054,8 +16274,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -13102,6 +16322,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen for + a request in the referenced claim. + type: string required: - name type: object @@ -13143,7 +16367,7 @@ spec: activeDeadlineSeconds: description: |- Specifies the duration in seconds relative to the startTime that the job - may be continuously active before the system tr + may be continuously active before the system... format: int64 type: integer backoffLimit: @@ -13329,8 +16553,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -13430,7 +16653,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -13449,8 +16672,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -13505,7 +16728,6 @@ spec: - hbase - cassandra - hazelcast - - ikv - couchbase - clickhouse type: string @@ -13709,8 +16931,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -13813,7 +17034,7 @@ spec: envFrom: items: description: EnvFromSource represents the source - of a set of ConfigMaps + of a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -13832,8 +17053,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the + name of each environment variable. Must be + a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -13895,6 +17117,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen + for a request in the referenced claim. + type: string required: - name type: object @@ -14187,7 +17413,6 @@ spec: enum: - snowflake.online - redis - - ikv - datastore - dynamodb - bigtable @@ -14202,6 +17427,7 @@ spec: - couchbase.online - milvus - hybrid + - mongodb type: string required: - secretRef @@ -14227,8 +17453,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -14331,7 +17556,7 @@ spec: envFrom: items: description: EnvFromSource represents the source - of a set of ConfigMaps + of a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -14350,8 +17575,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the + name of each environment variable. Must be + a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -14413,6 +17639,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen + for a request in the referenced claim. + type: string required: - name type: object @@ -14767,8 +17997,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment @@ -14873,7 +18102,7 @@ spec: envFrom: items: description: EnvFromSource represents the source - of a set of ConfigMaps + of a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -14892,9 +18121,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be - a C_IDENTIFIER. + description: Optional text to prepend to + the name of each environment variable. + Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -14960,6 +18189,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen + for a request in the referenced claim. + type: string required: - name type: object @@ -15188,6 +18421,11 @@ spec: - message: One selection required. rule: '[has(self.local), has(self.remote)].exists_one(c, c)' + runFeastApplyOnInit: + description: Runs feast apply on pod start to populate the + registry. Defaults to true. Ignored when DisableInitContainers + is true. + type: boolean securityContext: description: PodSecurityContext holds pod-level security attributes and common container settings. @@ -15233,6 +18471,11 @@ spec: Defaults to user specified in image metadata if unspecified. format: int64 type: integer + seLinuxChangePolicy: + description: seLinuxChangePolicy defines how the container's + SELinux label is applied to all volumes used by the + Pod. + type: string seLinuxOptions: description: The SELinux context to be applied to all containers. @@ -15272,13 +18515,18 @@ spec: type: object supplementalGroups: description: |- - A list of groups applied to the first process run in each container, in addition - to the container's primary GID, the fsG + A list of groups applied to the first process run in each container, in + addition to the container's primary GID and... items: format: int64 type: integer type: array x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + description: |- + Defines how supplemental groups of the first container processes are calculated. + Valid values are "Merge" and "Strict". + type: string sysctls: description: Sysctls hold a list of namespaced sysctls used for the pod. @@ -15336,8 +18584,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -15437,7 +18684,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -15456,8 +18703,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -15519,6 +18766,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen for + a request in the referenced claim. + type: string required: - name type: object @@ -15687,7 +18938,7 @@ spec: awsElasticBlockStore: description: |- awsElasticBlockStore represents an AWS Disk resource that is attached to a - kubelet's host machine and then exposed to th + kubelet's host machine and then exposed to... properties: fsType: description: fsType is the filesystem type of the @@ -15729,6 +18980,7 @@ spec: the blob storage type: string fsType: + default: ext4 description: |- fsType is Filesystem type to mount. Must be a filesystem type supported by the host operating system. @@ -15737,9 +18989,10 @@ spec: kind: description: 'kind expected values are Shared: multiple blob disks per storage account Dedicated: single - blob disk per storage accoun' + blob disk per storage...' type: string readOnly: + default: false description: |- readOnly Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. @@ -15770,7 +19023,7 @@ spec: type: object cephfs: description: cephFS represents a Ceph FS mount on the - host that shares a pod's lifetime + host that shares a pod's lifetime. properties: monitors: description: |- @@ -15819,7 +19072,7 @@ spec: cinder: description: |- cinder represents a cinder volume attached and mounted on kubelets host machine. - More info: https://examples.k8s. + Deprecated: Cinder is deprecated. properties: fsType: description: |- @@ -15865,7 +19118,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volum + ConfigMap will be projected into the... items: description: Maps a string key to a path within a volume. @@ -15905,7 +19158,7 @@ spec: csi: description: csi (Container Storage Interface) represents ephemeral storage that is handled by certain external - CSI drivers (Beta fea + CSI drivers. properties: driver: description: driver is the name of the CSI driver @@ -15918,7 +19171,7 @@ spec: nodePublishSecretRef: description: |- nodePublishSecretRef is a reference to the secret object containing - sensitive information to pass to the CSI driver to c + sensitive information to pass to the CSI driver to... properties: name: default: "" @@ -15982,7 +19235,7 @@ spec: mode: description: |- Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal valu + between 0000 and 0777 or a decimal... format: int32 type: integer path: @@ -16234,9 +19487,9 @@ spec: type: array x-kubernetes-list-type: atomic wwids: - description: "wwids Optional: FC volume world wide - identifiers (wwids)\nEither wwids or combination - of targetWWNs and lun must be set, " + description: |- + wwids Optional: FC volume world wide identifiers (wwids) + Either wwids or combination of targetWWNs and lun must be set,... items: type: string type: array @@ -16271,7 +19524,7 @@ spec: secretRef: description: |- secretRef is Optional: secretRef is reference to the secret object containing - sensitive information to pass to the plugi + sensitive information to pass to the... properties: name: default: "" @@ -16292,7 +19545,7 @@ spec: datasetName: description: |- datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker - should be considered as depreca + should be considered as... type: string datasetUUID: description: datasetUUID is the UUID of the dataset. @@ -16302,7 +19555,7 @@ spec: gcePersistentDisk: description: |- gcePersistentDisk represents a GCE Disk resource that is attached to a - kubelet's host machine and then exposed to the po + kubelet's host machine and then exposed to the... properties: fsType: description: fsType is filesystem type of the volume @@ -16331,7 +19584,7 @@ spec: gitRepo: description: |- gitRepo represents a git repository at a particular revision. - DEPRECATED: GitRepo is deprecated. + Deprecated: GitRepo is deprecated. properties: directory: description: |- @@ -16349,9 +19602,8 @@ spec: - repository type: object glusterfs: - description: |- - glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. - More info: https://examples.k8s. + description: glusterfs represents a Glusterfs mount + on the host that shares a pod's lifetime. properties: endpoints: description: |- @@ -16391,6 +19643,22 @@ spec: required: - path type: object + image: + description: image represents an OCI object (a container + image or artifact) pulled and mounted on the kubelet's + host machine. + properties: + pullPolicy: + description: |- + Policy for pulling OCI objects. Possible values are: + Always: the kubelet always attempts to pull the reference. + type: string + reference: + description: |- + Required: Image or artifact reference to be used. + Behaves in the same way as pod.spec.containers[*].image. + type: string + type: object iscsi: description: |- iscsi represents an ISCSI Disk resource that is attached to a @@ -16416,6 +19684,7 @@ spec: description: iqn is the target iSCSI Qualified Name. type: string iscsiInterface: + default: default description: |- iscsiInterface is the interface Name that uses an iSCSI transport. Defaults to 'default' (tcp). @@ -16507,7 +19776,7 @@ spec: photonPersistentDisk: description: photonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host - machine + machine. properties: fsType: description: |- @@ -16524,7 +19793,7 @@ spec: type: object portworxVolume: description: portworxVolume represents a portworx volume - attached and mounted on kubelets host machine + attached and mounted on kubelets host machine. properties: fsType: description: |- @@ -16554,10 +19823,13 @@ spec: format: int32 type: integer sources: - description: sources is the list of volume projections + description: |- + sources is the list of volume projections. Each entry in this list + handles one source. items: - description: Projection that may be projected - along with other supported volume types + description: |- + Projection that may be projected along with other supported volume types. + Exactly one of these fields must be set. properties: clusterTrustBundle: description: ClusterTrustBundle allows a pod @@ -16638,7 +19910,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volum + ConfigMap will be projected into the... items: description: Maps a string key to a path within a volume. @@ -16711,7 +19983,7 @@ spec: mode: description: |- Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal valu + between 0000 and 0777 or a decimal... format: int32 type: integer path: @@ -16760,7 +20032,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume a + Secret will be projected into the volume... items: description: Maps a string key to a path within a volume. @@ -16826,7 +20098,7 @@ spec: type: object quobyte: description: quobyte represents a Quobyte mount on the - host that shares a pod's lifetime + host that shares a pod's lifetime. properties: group: description: |- @@ -16841,12 +20113,12 @@ spec: registry: description: |- registry represents a single or multiple Quobyte Registry services - specified as a string as host:port pair (multiple ent + specified as a string as host:port pair (multiple... type: string tenant: description: |- tenant owning the given Quobyte volume in the Backend - Used with dynamically provisioned Quobyte volumes, value is set by + Used with dynamically provisioned Quobyte volumes, value is set... type: string user: description: |- @@ -16862,9 +20134,8 @@ spec: - volume type: object rbd: - description: |- - rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. - More info: https://examples.k8s. + description: rbd represents a Rados Block Device mount + on the host that shares a pod's lifetime. properties: fsType: description: fsType is the filesystem type of the @@ -16876,6 +20147,7 @@ spec: More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it type: string keyring: + default: /etc/ceph/keyring description: |- keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. @@ -16890,6 +20162,7 @@ spec: type: array x-kubernetes-list-type: atomic pool: + default: rbd description: |- pool is the rados pool name. Default is rbd. @@ -16917,6 +20190,7 @@ spec: type: object x-kubernetes-map-type: atomic user: + default: admin description: |- user is the rados user name. Default is admin. @@ -16931,6 +20205,7 @@ spec: volume attached and mounted on Kubernetes nodes. properties: fsType: + default: xfs description: |- fsType is the filesystem type to mount. Must be a filesystem type supported by the host operating system. @@ -16968,6 +20243,7 @@ spec: communication with Gateway, default false type: boolean storageMode: + default: ThinProvisioned description: storageMode indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. type: string @@ -17002,7 +20278,7 @@ spec: items: description: |- items If unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume a + Secret will be projected into the volume... items: description: Maps a string key to a path within a volume. @@ -17077,7 +20353,7 @@ spec: type: object vsphereVolume: description: vsphereVolume represents a vSphere volume - attached and mounted on kubelets host machine + attached and mounted on kubelets host machine. properties: fsType: description: |- @@ -17151,10 +20427,7 @@ spec: - Unknown type: string type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition. + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string diff --git a/infra/feast-operator/config/default/metrics_service.yaml b/infra/feast-operator/config/default/metrics_service.yaml index 0207c0469d4..fbf17dd96ec 100644 --- a/infra/feast-operator/config/default/metrics_service.yaml +++ b/infra/feast-operator/config/default/metrics_service.yaml @@ -14,4 +14,5 @@ spec: protocol: TCP targetPort: 8443 selector: + app.kubernetes.io/name: feast-operator control-plane: controller-manager diff --git a/infra/feast-operator/config/default/related_image_fs_patch.yaml b/infra/feast-operator/config/default/related_image_fs_patch.yaml index 172afcfd075..6de980383f0 100644 --- a/infra/feast-operator/config/default/related_image_fs_patch.yaml +++ b/infra/feast-operator/config/default/related_image_fs_patch.yaml @@ -2,7 +2,7 @@ path: "/spec/template/spec/containers/0/env/0" value: name: RELATED_IMAGE_FEATURE_SERVER - value: quay.io/feastdev/feature-server:0.60.0 + value: quay.io/feastdev/feature-server:0.62.0 - op: replace path: "/spec/template/spec/containers/0/env/1" value: diff --git a/infra/feast-operator/config/manager/kustomization.yaml b/infra/feast-operator/config/manager/kustomization.yaml index 844c53ae757..cbec14cc6ba 100644 --- a/infra/feast-operator/config/manager/kustomization.yaml +++ b/infra/feast-operator/config/manager/kustomization.yaml @@ -5,4 +5,4 @@ kind: Kustomization images: - name: controller newName: quay.io/feastdev/feast-operator - newTag: 0.60.0 + newTag: 0.62.0 diff --git a/infra/feast-operator/config/manager/manager.yaml b/infra/feast-operator/config/manager/manager.yaml index 242144e2b03..2fddf4725ba 100644 --- a/infra/feast-operator/config/manager/manager.yaml +++ b/infra/feast-operator/config/manager/manager.yaml @@ -19,6 +19,7 @@ metadata: spec: selector: matchLabels: + app.kubernetes.io/name: feast-operator control-plane: controller-manager replicas: 1 template: @@ -26,6 +27,7 @@ spec: annotations: kubectl.kubernetes.io/default-container: manager labels: + app.kubernetes.io/name: feast-operator control-plane: controller-manager spec: # TODO(user): Uncomment the following code to configure the nodeAffinity expression @@ -75,6 +77,10 @@ spec: value: feast:latest - name: RELATED_IMAGE_CRON_JOB value: origin-cli:latest + # Injected from params.env via kustomize replacements (ODH/RHOAI overlays). + # Open Data Hub operator sets this from GatewayConfig when the cluster uses external OIDC. + - name: OIDC_ISSUER_URL + value: "" livenessProbe: httpGet: path: /healthz diff --git a/infra/feast-operator/config/overlays/odh/kustomization.yaml b/infra/feast-operator/config/overlays/odh/kustomization.yaml index cf751d178bd..044614f01fe 100644 --- a/infra/feast-operator/config/overlays/odh/kustomization.yaml +++ b/infra/feast-operator/config/overlays/odh/kustomization.yaml @@ -52,3 +52,13 @@ replacements: name: controller-manager fieldPaths: - spec.template.spec.containers.[name=manager].env.[name=RELATED_IMAGE_CRON_JOB].value + - source: + kind: ConfigMap + name: feast-operator-parameters + fieldPath: data.OIDC_ISSUER_URL + targets: + - select: + kind: Deployment + name: controller-manager + fieldPaths: + - spec.template.spec.containers.[name=manager].env.[name=OIDC_ISSUER_URL].value diff --git a/infra/feast-operator/config/overlays/odh/params.env b/infra/feast-operator/config/overlays/odh/params.env index c3cb4bab64b..20f56181337 100644 --- a/infra/feast-operator/config/overlays/odh/params.env +++ b/infra/feast-operator/config/overlays/odh/params.env @@ -1,3 +1,5 @@ -RELATED_IMAGE_FEAST_OPERATOR=quay.io/feastdev/feast-operator:0.60.0 -RELATED_IMAGE_FEATURE_SERVER=quay.io/feastdev/feature-server:0.60.0 +RELATED_IMAGE_FEAST_OPERATOR=quay.io/feastdev/feast-operator:0.62.0 +RELATED_IMAGE_FEATURE_SERVER=quay.io/feastdev/feature-server:0.62.0 RELATED_IMAGE_CRON_JOB=quay.io/openshift/origin-cli:4.17 +# Set at deploy time by the Open Data Hub operator from GatewayConfig (external OIDC). +OIDC_ISSUER_URL= diff --git a/infra/feast-operator/config/overlays/rhoai/kustomization.yaml b/infra/feast-operator/config/overlays/rhoai/kustomization.yaml index 4917579ef28..b9d075bdf39 100644 --- a/infra/feast-operator/config/overlays/rhoai/kustomization.yaml +++ b/infra/feast-operator/config/overlays/rhoai/kustomization.yaml @@ -52,3 +52,13 @@ replacements: name: controller-manager fieldPaths: - spec.template.spec.containers.[name=manager].env.[name=RELATED_IMAGE_CRON_JOB].value + - source: + kind: ConfigMap + name: feast-operator-parameters + fieldPath: data.OIDC_ISSUER_URL + targets: + - select: + kind: Deployment + name: controller-manager + fieldPaths: + - spec.template.spec.containers.[name=manager].env.[name=OIDC_ISSUER_URL].value diff --git a/infra/feast-operator/config/overlays/rhoai/params.env b/infra/feast-operator/config/overlays/rhoai/params.env index afae8c9bea4..c2ba0ae07cb 100644 --- a/infra/feast-operator/config/overlays/rhoai/params.env +++ b/infra/feast-operator/config/overlays/rhoai/params.env @@ -1,3 +1,5 @@ -RELATED_IMAGE_FEAST_OPERATOR=quay.io/feastdev/feast-operator:0.60.0 -RELATED_IMAGE_FEATURE_SERVER=quay.io/feastdev/feature-server:0.60.0 -RELATED_IMAGE_CRON_JOB=registry.redhat.io/openshift4/ose-cli@sha256:bc35a9fc663baf0d6493cc57e89e77a240a36c43cf38fb78d8e61d3b87cf5cc5 \ No newline at end of file +RELATED_IMAGE_FEAST_OPERATOR=quay.io/feastdev/feast-operator:0.62.0 +RELATED_IMAGE_FEATURE_SERVER=quay.io/feastdev/feature-server:0.62.0 +RELATED_IMAGE_CRON_JOB=registry.redhat.io/openshift4/ose-cli@sha256:bc35a9fc663baf0d6493cc57e89e77a240a36c43cf38fb78d8e61d3b87cf5cc5 +# Set at deploy time by the Open Data Hub operator from GatewayConfig (external OIDC). +OIDC_ISSUER_URL= \ No newline at end of file diff --git a/infra/feast-operator/config/prometheus/monitor.yaml b/infra/feast-operator/config/prometheus/monitor.yaml index e76479a1305..50f2ea8e448 100644 --- a/infra/feast-operator/config/prometheus/monitor.yaml +++ b/infra/feast-operator/config/prometheus/monitor.yaml @@ -27,4 +27,5 @@ spec: insecureSkipVerify: true selector: matchLabels: + app.kubernetes.io/name: feast-operator control-plane: controller-manager diff --git a/infra/feast-operator/config/rbac/featurestore_editor_role.yaml b/infra/feast-operator/config/rbac/featurestore_editor_role.yaml index 37c38e6f618..e2e3acf1b60 100644 --- a/infra/feast-operator/config/rbac/featurestore_editor_role.yaml +++ b/infra/feast-operator/config/rbac/featurestore_editor_role.yaml @@ -5,6 +5,8 @@ metadata: labels: app.kubernetes.io/name: feast-operator app.kubernetes.io/managed-by: kustomize + rbac.authorization.k8s.io/aggregate-to-admin: "true" + rbac.authorization.k8s.io/aggregate-to-edit: "true" name: featurestore-editor-role rules: - apiGroups: diff --git a/infra/feast-operator/config/rbac/featurestore_viewer_role.yaml b/infra/feast-operator/config/rbac/featurestore_viewer_role.yaml index b4444cbe60a..bca67d9788d 100644 --- a/infra/feast-operator/config/rbac/featurestore_viewer_role.yaml +++ b/infra/feast-operator/config/rbac/featurestore_viewer_role.yaml @@ -5,6 +5,7 @@ metadata: labels: app.kubernetes.io/name: feast-operator app.kubernetes.io/managed-by: kustomize + rbac.authorization.k8s.io/aggregate-to-view: "true" name: featurestore-viewer-role rules: - apiGroups: diff --git a/infra/feast-operator/config/rbac/role.yaml b/infra/feast-operator/config/rbac/role.yaml index 56a952dd95c..0c1bd7be84b 100644 --- a/infra/feast-operator/config/rbac/role.yaml +++ b/infra/feast-operator/config/rbac/role.yaml @@ -5,9 +5,12 @@ metadata: name: manager-role rules: - apiGroups: - - apps + - "" resources: - - deployments + - configmaps + - persistentvolumeclaims + - serviceaccounts + - services verbs: - create - delete @@ -16,53 +19,62 @@ rules: - update - watch - apiGroups: - - authentication.k8s.io + - "" resources: - - tokenreviews + - namespaces + - pods + - secrets + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - pods/exec verbs: - create - apiGroups: - - batch + - apps resources: - - cronjobs + - deployments verbs: - create - delete - get - list - - patch - update - watch - apiGroups: - - "" + - authentication.k8s.io resources: - - configmaps - - persistentvolumeclaims - - serviceaccounts - - services + - tokenreviews + verbs: + - create +- apiGroups: + - autoscaling + resources: + - horizontalpodautoscalers verbs: - create - delete - get - list + - patch - update - watch - apiGroups: - - "" + - batch resources: - - namespaces - - pods - - secrets + - cronjobs verbs: + - create + - delete - get - list + - patch + - update - watch -- apiGroups: - - "" - resources: - - pods/exec - verbs: - - create - apiGroups: - feast.dev resources: @@ -89,6 +101,29 @@ rules: - get - patch - update +- apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + verbs: + - create + - delete + - get + - list + - patch + - watch +- apiGroups: + - policy + resources: + - poddisruptionbudgets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - rbac.authorization.k8s.io resources: diff --git a/infra/feast-operator/config/samples/v1_featurestore_scaling_hpa.yaml b/infra/feast-operator/config/samples/v1_featurestore_scaling_hpa.yaml new file mode 100644 index 00000000000..af4a9fd1d02 --- /dev/null +++ b/infra/feast-operator/config/samples/v1_featurestore_scaling_hpa.yaml @@ -0,0 +1,78 @@ +apiVersion: v1 +kind: Secret +metadata: + name: postgres-secret + namespace: test + labels: + app: postgres +stringData: + POSTGRES_DB: feast + POSTGRES_USER: feast + POSTGRES_PASSWORD: feast # pragma: allowlist secret +--- +apiVersion: v1 +kind: Secret +metadata: + name: feast-data-stores + namespace: test +stringData: + sql: | + path: postgresql+psycopg://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres.test.svc.cluster.local:5432/${POSTGRES_DB} + cache_ttl_seconds: 60 + sqlalchemy_config_kwargs: + echo: false + pool_pre_ping: true + postgres: | + host: postgres.test.svc.cluster.local + port: 5432 + database: ${POSTGRES_DB} + db_schema: public + user: ${POSTGRES_USER} + password: ${POSTGRES_PASSWORD} +--- +# HPA autoscaling: 2-10 replicas with DB-backed persistence and HA +apiVersion: feast.dev/v1 +kind: FeatureStore +metadata: + name: sample-scaling-hpa + namespace: test +spec: + feastProject: my_project + services: + scaling: + autoscaling: + minReplicas: 2 + maxReplicas: 10 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 70 + podDisruptionBudgets: + maxUnavailable: 1 + onlineStore: + persistence: + store: + type: postgres + secretRef: + name: feast-data-stores + server: + envFrom: + - secretRef: + name: postgres-secret + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + cpu: "1" + memory: 1Gi + registry: + local: + persistence: + store: + type: sql + secretRef: + name: feast-data-stores diff --git a/infra/feast-operator/config/samples/v1_featurestore_scaling_static.yaml b/infra/feast-operator/config/samples/v1_featurestore_scaling_static.yaml new file mode 100644 index 00000000000..e4df5a6245a --- /dev/null +++ b/infra/feast-operator/config/samples/v1_featurestore_scaling_static.yaml @@ -0,0 +1,75 @@ +apiVersion: v1 +kind: Secret +metadata: + name: postgres-secret + namespace: test + labels: + app: postgres +stringData: + POSTGRES_DB: feast + POSTGRES_USER: feast + POSTGRES_PASSWORD: feast # pragma: allowlist secret +--- +apiVersion: v1 +kind: Secret +metadata: + name: feast-data-stores + namespace: test +stringData: + sql: | + path: postgresql+psycopg://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres.test.svc.cluster.local:5432/${POSTGRES_DB} + cache_ttl_seconds: 60 + sqlalchemy_config_kwargs: + echo: false + pool_pre_ping: true + postgres: | + host: postgres.test.svc.cluster.local + port: 5432 + database: ${POSTGRES_DB} + db_schema: public + user: ${POSTGRES_USER} + password: ${POSTGRES_PASSWORD} +--- +# Static scaling: 3 replicas with DB-backed persistence, PDB, and HA +# +# By default the operator auto-injects: +# - Soft pod anti-affinity (prefer different nodes) +# - Soft zone topology spread (prefer different zones, e.g. us-east-1a, us-east-1b, us-east-1c) +# +# To enforce strict zone spreading on AWS (DoNotSchedule), uncomment topologySpreadConstraints below. +apiVersion: feast.dev/v1 +kind: FeatureStore +metadata: + name: sample-scaling-static + namespace: test +spec: + feastProject: my_project + replicas: 3 + services: + podDisruptionBudgets: + maxUnavailable: 1 + # Uncomment to enforce strict spreading across AWS availability zones: + # topologySpreadConstraints: + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: DoNotSchedule + # labelSelector: + # matchLabels: + # feast.dev/name: sample-scaling-static + onlineStore: + persistence: + store: + type: postgres + secretRef: + name: feast-data-stores + server: + envFrom: + - secretRef: + name: postgres-secret + registry: + local: + persistence: + store: + type: sql + secretRef: + name: feast-data-stores diff --git a/infra/feast-operator/dist/install.yaml b/infra/feast-operator/dist/install.yaml index d42a902c886..93c6937f5e1 100644 --- a/infra/feast-operator/dist/install.yaml +++ b/infra/feast-operator/dist/install.yaml @@ -11,7 +11,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.15.0 + controller-gen.kubebuilder.io/version: v0.18.0 name: featurestores.feast.dev spec: group: feast.dev @@ -70,10 +70,32 @@ spec: OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. https://auth0. properties: + caCertConfigMap: + description: ConfigMap with the CA certificate for self-signed + OIDC providers. Auto-detected on RHOAI/ODH. + properties: + key: + description: Key in the ConfigMap holding the PEM certificate. + Defaults to "ca-bundle.crt". + type: string + name: + description: ConfigMap name. + type: string + required: + - name + type: object + issuerUrl: + description: OIDC issuer URL. The operator appends /.well-known/openid-configuration + to derive the discovery endpoint. + pattern: ^https://\S+$ + type: string + secretKeyName: + description: Key in the Secret containing all OIDC properties + as a YAML value. If unset, each key is a property. + type: string secretRef: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. + description: Secret with OIDC properties (auth_discovery_url, + client_id, client_secret). issuerUrl takes precedence. properties: name: default: "" @@ -84,8 +106,14 @@ spec: type: string type: object x-kubernetes-map-type: atomic - required: - - secretRef + tokenEnvVar: + description: Env var name for client pods to read an OIDC + token from. Sets token_env_var in client config. + type: string + verifySSL: + description: Verify SSL certificates for the OIDC provider. + Defaults to true. + type: boolean type: object type: object x-kubernetes-validations: @@ -147,8 +175,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's value. @@ -247,7 +274,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of a set - of ConfigMaps + of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -266,8 +293,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -313,6 +340,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen for a request + in the referenced claim. + type: string required: - name type: object @@ -354,7 +385,7 @@ spec: activeDeadlineSeconds: description: |- Specifies the duration in seconds relative to the startTime that the job - may be continuously active before the system tr + may be continuously active before the system... format: int64 type: integer backoffLimit: @@ -537,8 +568,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's value. @@ -637,7 +667,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of a set - of ConfigMaps + of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -656,8 +686,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -711,7 +741,6 @@ spec: - hbase - cassandra - hazelcast - - ikv - couchbase - clickhouse type: string @@ -720,553 +749,806 @@ spec: x-kubernetes-validations: - message: One selection required between init or git. rule: '[has(self.git), has(self.init)].exists_one(c, c)' + replicas: + default: 1 + description: |- + Replicas is the desired number of pod replicas. Used by the scale sub-resource. + Mutually exclusive with services. + format: int32 + minimum: 1 + type: integer services: description: FeatureStoreServices defines the desired feast services. An ephemeral onlineStore feature server is deployed by default. properties: - deploymentStrategy: - description: DeploymentStrategy describes how to replace existing - pods with new ones. + affinity: + description: Affinity defines the pod scheduling constraints for + the FeatureStore deployment. properties: - rollingUpdate: - description: |- - Rolling update config params. Present only if DeploymentStrategyType = - RollingUpdate. + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. properties: - maxSurge: - anyOf: - - type: integer - - type: string + preferredDuringSchedulingIgnoredDuringExecution: description: |- - The maximum number of pods that can be scheduled above the desired number of - pods. - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - description: The maximum number of pods that can be unavailable - during the update. - x-kubernetes-int-or-string: true - type: object - type: - description: Type of deployment. Can be "Recreate" or "RollingUpdate". - Default is RollingUpdate. - type: string - type: object - disableInitContainers: - description: Disable the 'feast repo initialization' initContainer - type: boolean - offlineStore: - description: OfflineStore configures the offline store service - properties: - persistence: - description: OfflineStorePersistence configures the persistence - settings for the offline store service - properties: - file: - description: OfflineStoreFilePersistence configures the - file-based persistence for the offline store service - properties: - pvc: - description: PvcConfig defines the settings for a - persistent file store based on PVCs. - properties: - create: - description: Settings for creating a new PVC - properties: - accessModes: - description: AccessModes k8s persistent volume - access modes. Defaults to ["ReadWriteOnce"]. - items: - type: string - type: array - resources: - description: Resources describes the storage - resource requirements for a volume. + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but... + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true + key: + description: The label key that the selector + applies to. + type: string + operator: description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the minimum - amount of compute resources required. - type: object + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator type: object - storageClassName: - description: StorageClassName is the name - of an existing StorageClass to which this - persistent volume belongs. - type: string - type: object - x-kubernetes-validations: - - message: PvcCreate is immutable - rule: self == oldSelf - mountPath: - description: |- - MountPath within the container at which the volume should be mounted. - Must start by "/" and cannot contain ':'. - type: string - ref: - description: Reference to an existing field - properties: - name: - default: "" + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - mountPath - type: object - x-kubernetes-validations: - - message: One selection is required between ref and - create. - rule: '[has(self.ref), has(self.create)].exists_one(c, - c)' - - message: Mount path must start with '/' and must - not contain ':' - rule: self.mountPath.matches('^/[^:]*$') - type: - enum: - - file - - dask - - duckdb - type: string - type: object - store: - description: OfflineStoreDBStorePersistence configures - the DB store persistence for the offline store service + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto... properties: - secretKeyName: - description: By default, the selected store "type" - is used as the SecretKeyName - type: string - secretRef: - description: Data store parameters should be placed - as-is from the "feature_store.yaml" under the secret - key. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - type: - description: Type of the persistence type you want - to use. - enum: - - snowflake.offline - - bigquery - - redshift - - spark - - postgres - - trino - - athena - - mssql - - couchbase.offline - - clickhouse - - ray - type: string + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic required: - - secretRef - - type + - nodeSelectorTerms type: object + x-kubernetes-map-type: atomic type: object - x-kubernetes-validations: - - message: One selection required between file or store. - rule: '[has(self.file), has(self.store)].exists_one(c, c)' - server: - description: Creates a remote offline server container + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). properties: - env: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but... items: - description: EnvVar represents an environment variable - present in a Container. + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) properties: - name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: 'Selects a field of the pod: supports - metadata.name, metadata.namespace, `metadata.labels['''']`, - `metadata.' - properties: - apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: + labelSelector: description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits. + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: - containerName: - description: 'Container name: required for - volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults to - "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object type: object x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the - pod's namespace + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. properties: - key: - description: The key of the secret to select - from. Must be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object type: object x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in... + type: string + required: + - topologyKey type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer required: - - name + - podAffinityTerm + - weight type: object type: array - envFrom: + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto... items: - description: EnvFromSource represents the source of - a set of ConfigMaps + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should... properties: - configMapRef: - description: The ConfigMap to select from + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the ConfigMap must - be defined - type: boolean + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object type: object x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the Secret must - be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in... + type: string + required: + - topologyKey + type: object type: array - image: - type: string - imagePullPolicy: - description: PullPolicy describes a policy for if/when - to pull a container image - type: string - logLevel: + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + properties: + preferredDuringSchedulingIgnoredDuringExecution: description: |- - LogLevel sets the logging level for the server - Allowed values: "debug", "info", "warning", "error", "critical". - enum: - - debug - - info - - warning - - error - - critical - type: string - metrics: - description: Metrics exposes Prometheus-compatible metrics - for the Feast server when enabled. - type: boolean - nodeSelector: - additionalProperties: - type: string - type: object - resources: - description: ResourceRequirements describes the compute - resource requirements. - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field,... + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. properties: - name: + labelSelector: description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in... type: string required: - - name + - topologyKey type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the minimum amount - of compute resources required. - type: object - type: object - tls: - description: TlsConfigs configures server TLS for a feast - service. - properties: - disable: - description: will disable TLS for the feast service. - useful in an openshift cluster, for example, where - TLS is configured by default - type: boolean - secretKeyNames: - description: SecretKeyNames defines the secret key - names for the TLS key and cert. - properties: - tlsCrt: - description: defaults to "tls.crt" - type: string - tlsKey: - description: defaults to "tls.key" - type: string - type: object - secretRef: - description: references the local k8s secret where - the TLS key and cert reside - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' - volumeMounts: - description: VolumeMounts defines the list of volumes - that should be mounted into the feast container. + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled... items: - description: VolumeMount describes a mounting of a Volume - within a container. + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should... properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: + labelSelector: description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. - type: string - subPath: + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: Expanded path within the volume from - which the container's volume should be mounted. + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in... type: string required: - - mountPath - - name + - topologyKey type: object type: array - workerConfigs: - description: WorkerConfigs defines the worker configuration - for the Feast server. - properties: - keepAliveTimeout: - description: |- - KeepAliveTimeout is the timeout for keep-alive connections in seconds. - Defaults to 30. - format: int32 - minimum: 1 - type: integer - maxRequests: - description: |- - MaxRequests is the maximum number of requests a worker will process before restarting. - This helps prevent memory leaks. - format: int32 - minimum: 0 - type: integer - maxRequestsJitter: - description: |- - MaxRequestsJitter is the maximum jitter to add to max-requests to prevent - thundering herd effect on worker restart. - format: int32 - minimum: 0 - type: integer - registryTTLSeconds: - description: RegistryTTLSeconds is the number of seconds - after which the registry is refreshed. - format: int32 - minimum: 0 - type: integer - workerConnections: - description: |- - WorkerConnections is the maximum number of simultaneous clients per worker process. - Defaults to 1000. - format: int32 - minimum: 1 - type: integer - workers: - description: Workers is the number of worker processes. - Use -1 to auto-calculate based on CPU cores (2 * - CPU + 1). - format: int32 - minimum: -1 - type: integer - type: object + x-kubernetes-list-type: atomic type: object type: object - onlineStore: - description: OnlineStore configures the online store service + deploymentStrategy: + description: DeploymentStrategy describes how to replace existing + pods with new ones. + properties: + rollingUpdate: + description: |- + Rolling update config params. Present only if DeploymentStrategyType = + RollingUpdate. + properties: + maxSurge: + anyOf: + - type: integer + - type: string + description: |- + The maximum number of pods that can be scheduled above the desired number of + pods. + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + description: The maximum number of pods that can be unavailable + during the update. + x-kubernetes-int-or-string: true + type: object + type: + description: Type of deployment. Can be "Recreate" or "RollingUpdate". + Default is RollingUpdate. + type: string + type: object + disableInitContainers: + description: Disable the 'feast repo initialization' initContainer + type: boolean + offlineStore: + description: OfflineStore configures the offline store service properties: persistence: - description: OnlineStorePersistence configures the persistence - settings for the online store service + description: OfflineStorePersistence configures the persistence + settings for the offline store service properties: file: - description: OnlineStoreFilePersistence configures the - file-based persistence for the online store service + description: OfflineStoreFilePersistence configures the + file-based persistence for the offline store service properties: - path: - type: string pvc: description: PvcConfig defines the settings for a persistent file store based on PVCs. @@ -1343,21 +1625,16 @@ spec: - message: Mount path must start with '/' and must not contain ':' rule: self.mountPath.matches('^/[^:]*$') + type: + enum: + - file + - dask + - duckdb + type: string type: object - x-kubernetes-validations: - - message: Ephemeral stores must have absolute paths. - rule: '(!has(self.pvc) && has(self.path)) ? self.path.startsWith(''/'') - : true' - - message: PVC path must be a file name only, with no - slashes. - rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') - : true' - - message: Online store does not support S3 or GS buckets. - rule: 'has(self.path) ? !(self.path.startsWith(''s3://'') - || self.path.startsWith(''gs://'')) : true' store: - description: OnlineStoreDBStorePersistence configures - the DB store persistence for the online store service + description: OfflineStoreDBStorePersistence configures + the DB store persistence for the offline store service properties: secretKeyName: description: By default, the selected store "type" @@ -1381,23 +1658,18 @@ spec: description: Type of the persistence type you want to use. enum: - - snowflake.online - - redis - - ikv - - datastore - - dynamodb - - bigtable + - snowflake.offline + - bigquery + - redshift + - spark - postgres - - cassandra - - mysql - - hazelcast - - singlestore - - hbase - - elasticsearch - - qdrant - - couchbase.online - - milvus - - hybrid + - trino + - athena + - mssql + - couchbase.offline + - clickhouse + - ray + - oracle type: string required: - secretRef @@ -1408,7 +1680,7 @@ spec: - message: One selection required between file or store. rule: '[has(self.file), has(self.store)].exists_one(c, c)' server: - description: Creates a feature server container + description: Creates a remote offline server container properties: env: items: @@ -1422,8 +1694,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -1523,7 +1794,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -1542,8 +1813,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -1605,6 +1876,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen for + a request in the referenced claim. + type: string required: - name type: object @@ -1764,151 +2039,74 @@ spec: type: object type: object type: object - registry: - description: Registry configures the registry service. One selection - is required. Local is the default setting. + onlineStore: + description: OnlineStore configures the online store service properties: - local: - description: LocalRegistryConfig configures the registry service + persistence: + description: OnlineStorePersistence configures the persistence + settings for the online store service properties: - persistence: - description: RegistryPersistence configures the persistence - settings for the registry service + file: + description: OnlineStoreFilePersistence configures the + file-based persistence for the online store service properties: - file: - description: RegistryFilePersistence configures the - file-based persistence for the registry service + path: + type: string + pvc: + description: PvcConfig defines the settings for a + persistent file store based on PVCs. properties: - cache_mode: - description: |- - CacheMode defines the registry cache update strategy. - Allowed values are "sync" and "thread". - enum: - - none - - sync - - thread - type: string - cache_ttl_seconds: - description: CacheTTLSeconds defines the TTL (in - seconds) for the registry cache. - format: int32 - minimum: 0 - type: integer - path: - type: string - pvc: - description: PvcConfig defines the settings for - a persistent file store based on PVCs. + create: + description: Settings for creating a new PVC properties: - create: - description: Settings for creating a new PVC + accessModes: + description: AccessModes k8s persistent volume + access modes. Defaults to ["ReadWriteOnce"]. + items: + type: string + type: array + resources: + description: Resources describes the storage + resource requirements for a volume. properties: - accessModes: - description: AccessModes k8s persistent - volume access modes. Defaults to ["ReadWriteOnce"]. - items: - type: string - type: array - resources: - description: Resources describes the storage - resource requirements for a volume. - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the - minimum amount of compute resources - required. - type: object + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum + amount of compute resources required. type: object - storageClassName: - description: StorageClassName is the name - of an existing StorageClass to which - this persistent volume belongs. - type: string type: object - x-kubernetes-validations: - - message: PvcCreate is immutable - rule: self == oldSelf - mountPath: - description: |- - MountPath within the container at which the volume should be mounted. - Must start by "/" and cannot contain ':'. + storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which this + persistent volume belongs. type: string - ref: - description: Reference to an existing field - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - mountPath type: object x-kubernetes-validations: - - message: One selection is required between ref - and create. - rule: '[has(self.ref), has(self.create)].exists_one(c, - c)' - - message: Mount path must start with '/' and - must not contain ':' - rule: self.mountPath.matches('^/[^:]*$') - s3_additional_kwargs: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-validations: - - message: Registry files must use absolute paths - or be S3 ('s3://') or GS ('gs://') object store - URIs. - rule: '(!has(self.pvc) && has(self.path)) ? (self.path.startsWith(''/'') - || self.path.startsWith(''s3://'') || self.path.startsWith(''gs://'')) - : true' - - message: PVC path must be a file name only, with - no slashes. - rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') - : true' - - message: PVC persistence does not support S3 or - GS object store URIs. - rule: '(has(self.pvc) && has(self.path)) ? !(self.path.startsWith(''s3://'') - || self.path.startsWith(''gs://'')) : true' - - message: Additional S3 settings are available only - for S3 object store URIs. - rule: '(has(self.s3_additional_kwargs) && has(self.path)) - ? self.path.startsWith(''s3://'') : true' - store: - description: RegistryDBStorePersistence configures - the DB store persistence for the registry service - properties: - secretKeyName: - description: By default, the selected store "type" - is used as the SecretKeyName + - message: PvcCreate is immutable + rule: self == oldSelf + mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. type: string - secretRef: - description: Data store parameters should be placed - as-is from the "feature_store.yaml" under the - secret key. + ref: + description: Reference to an existing field properties: name: default: "" @@ -1919,146 +2117,108 @@ spec: type: string type: object x-kubernetes-map-type: atomic - type: - description: Type of the persistence type you - want to use. - enum: - - sql - - snowflake.registry - type: string required: - - secretRef - - type + - mountPath type: object + x-kubernetes-validations: + - message: One selection is required between ref and + create. + rule: '[has(self.ref), has(self.create)].exists_one(c, + c)' + - message: Mount path must start with '/' and must + not contain ':' + rule: self.mountPath.matches('^/[^:]*$') type: object x-kubernetes-validations: - - message: One selection required between file or store. - rule: '[has(self.file), has(self.store)].exists_one(c, - c)' - server: - description: Creates a registry server container + - message: Ephemeral stores must have absolute paths. + rule: '(!has(self.pvc) && has(self.path)) ? self.path.startsWith(''/'') + : true' + - message: PVC path must be a file name only, with no + slashes. + rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') + : true' + - message: Online store does not support S3 or GS buckets. + rule: 'has(self.path) ? !(self.path.startsWith(''s3://'') + || self.path.startsWith(''gs://'')) : true' + store: + description: OnlineStoreDBStorePersistence configures + the DB store persistence for the online store service properties: - env: - items: - description: EnvVar represents an environment variable - present in a Container. + secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName + type: string + secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the secret + key. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + type: + description: Type of the persistence type you want + to use. + enum: + - snowflake.online + - redis + - datastore + - dynamodb + - bigtable + - postgres + - cassandra + - mysql + - hazelcast + - singlestore + - hbase + - elasticsearch + - qdrant + - couchbase.online + - milvus + - hybrid + - mongodb + type: string + required: + - secretRef + - type + type: object + type: object + x-kubernetes-validations: + - message: One selection required between file or store. + rule: '[has(self.file), has(self.store)].exists_one(c, c)' + server: + description: Creates a feature server container + properties: + env: + items: + description: EnvVar represents an environment variable + present in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and... + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. properties: - name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: 'Selects a field of the pod: - supports metadata.name, metadata.namespace, - `metadata.labels['''']`, `metadata.' - properties: - apiVersion: - description: Version of the schema the - FieldPath is written in terms of, - defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits. - properties: - containerName: - description: 'Container name: required - for volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults - to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to - select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in - the pod's namespace - properties: - key: - description: The key of the secret to - select from. Must be a valid secret - key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - items: - description: EnvFromSource represents the source - of a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from + configMapKeyRef: + description: Selects a key of a ConfigMap. properties: + key: + description: The key to select. + type: string name: default: "" description: |- @@ -2068,17 +2228,62 @@ spec: type: string optional: description: Specify whether the ConfigMap - must be defined + or its key must be defined type: boolean + required: + - key type: object x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from + fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. + properties: + containerName: + description: 'Container name: required for + volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the + pod's namespace properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string name: default: "" description: |- @@ -2088,279 +2293,1482 @@ spec: type: string optional: description: Specify whether the Secret - must be defined + or its key must be defined type: boolean + required: + - key type: object x-kubernetes-map-type: atomic type: object - type: array - grpc: - description: Enable gRPC registry server. Defaults - to true if unset. - type: boolean - image: - type: string - imagePullPolicy: - description: PullPolicy describes a policy for if/when - to pull a container image - type: string - logLevel: - description: |- - LogLevel sets the logging level for the server - Allowed values: "debug", "info", "warning", "error", "critical". - enum: - - debug - - info - - warning - - error - - critical - type: string - metrics: - description: Metrics exposes Prometheus-compatible - metrics for the Feast server when enabled. - type: boolean - nodeSelector: - additionalProperties: + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source of + a set of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string - type: object - resources: - description: ResourceRequirements describes the compute - resource requirements. - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the minimum amount - of compute resources required. - type: object - type: object - restAPI: - description: Enable REST API registry server. - type: boolean - tls: - description: TlsConfigs configures server TLS for - a feast service. - properties: - disable: - description: will disable TLS for the feast service. - useful in an openshift cluster, for example, - where TLS is configured by default - type: boolean - secretKeyNames: - description: SecretKeyNames defines the secret - key names for the TLS key and cert. - properties: - tlsCrt: - description: defaults to "tls.crt" - type: string - tlsKey: - description: defaults to "tls.key" - type: string - type: object - secretRef: - description: references the local k8s secret where - the TLS key and cert reside - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-validations: - - message: '`secretRef` required if `disable` is false.' - rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) - : true' - volumeMounts: - description: VolumeMounts defines the list of volumes - that should be mounted into the feast container. - items: - description: VolumeMount describes a mounting of - a Volume within a container. + secretRef: + description: The Secret to select from properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - type: string name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: + default: "" description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. type: string - subPath: + optional: + description: Specify whether the Secret must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image + type: string + logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". + enum: + - debug + - info + - warning + - error + - critical + type: string + metrics: + description: Metrics exposes Prometheus-compatible metrics + for the Feast server when enabled. + type: boolean + nodeSelector: + additionalProperties: + type: string + type: object + resources: + description: ResourceRequirements describes the compute + resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. type: string - subPathExpr: - description: Expanded path within the volume - from which the container's volume should be - mounted. + request: + description: Request is the name chosen for + a request in the referenced claim. type: string required: - - mountPath - name type: object type: array - workerConfigs: - description: WorkerConfigs defines the worker configuration - for the Feast server. + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount + of compute resources required. + type: object + type: object + tls: + description: TlsConfigs configures server TLS for a feast + service. + properties: + disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, where + TLS is configured by default + type: boolean + secretKeyNames: + description: SecretKeyNames defines the secret key + names for the TLS key and cert. properties: - keepAliveTimeout: - description: |- - KeepAliveTimeout is the timeout for keep-alive connections in seconds. - Defaults to 30. - format: int32 - minimum: 1 - type: integer - maxRequests: - description: |- - MaxRequests is the maximum number of requests a worker will process before restarting. - This helps prevent memory leaks. - format: int32 - minimum: 0 - type: integer - maxRequestsJitter: - description: |- - MaxRequestsJitter is the maximum jitter to add to max-requests to prevent - thundering herd effect on worker restart. - format: int32 - minimum: 0 - type: integer - registryTTLSeconds: - description: RegistryTTLSeconds is the number - of seconds after which the registry is refreshed. - format: int32 - minimum: 0 - type: integer - workerConnections: + tlsCrt: + description: defaults to "tls.crt" + type: string + tlsKey: + description: defaults to "tls.key" + type: string + type: object + secretRef: + description: references the local k8s secret where + the TLS key and cert reside + properties: + name: + default: "" description: |- - WorkerConnections is the maximum number of simultaneous clients per worker process. - Defaults to 1000. - format: int32 - minimum: 1 - type: integer - workers: - description: Workers is the number of worker processes. - Use -1 to auto-calculate based on CPU cores - (2 * CPU + 1). - format: int32 - minimum: -1 - type: integer + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string type: object + x-kubernetes-map-type: atomic type: object x-kubernetes-validations: - - message: At least one of restAPI or grpc must be true - rule: self.restAPI == true || self.grpc == true || !has(self.grpc) - type: object - remote: - description: RemoteRegistryConfig points to a remote feast - registry server. - properties: - feastRef: - description: Reference to an existing `FeatureStore` CR - in the same k8s cluster. + - message: '`secretRef` required if `disable` is false.' + rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) + : true' + volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. + type: string + required: + - mountPath + - name + type: object + type: array + workerConfigs: + description: WorkerConfigs defines the worker configuration + for the Feast server. properties: - name: - description: Name of the FeatureStore - type: string - namespace: - description: Namespace of the FeatureStore - type: string - required: - - name + keepAliveTimeout: + description: |- + KeepAliveTimeout is the timeout for keep-alive connections in seconds. + Defaults to 30. + format: int32 + minimum: 1 + type: integer + maxRequests: + description: |- + MaxRequests is the maximum number of requests a worker will process before restarting. + This helps prevent memory leaks. + format: int32 + minimum: 0 + type: integer + maxRequestsJitter: + description: |- + MaxRequestsJitter is the maximum jitter to add to max-requests to prevent + thundering herd effect on worker restart. + format: int32 + minimum: 0 + type: integer + registryTTLSeconds: + description: RegistryTTLSeconds is the number of seconds + after which the registry is refreshed. + format: int32 + minimum: 0 + type: integer + workerConnections: + description: |- + WorkerConnections is the maximum number of simultaneous clients per worker process. + Defaults to 1000. + format: int32 + minimum: 1 + type: integer + workers: + description: Workers is the number of worker processes. + Use -1 to auto-calculate based on CPU cores (2 * + CPU + 1). + format: int32 + minimum: -1 + type: integer type: object - hostname: - description: Host address of the remote registry service - - :, e.g. `registry..svc.cluster.local:80` - type: string - tls: - description: TlsRemoteRegistryConfigs configures client - TLS for a remote feast registry. + type: object + type: object + podAnnotations: + additionalProperties: + type: string + description: PodAnnotations are annotations to be applied to the + Deployment's PodTemplate metadata. + type: object + podDisruptionBudgets: + description: PodDisruptionBudgets configures a PodDisruptionBudget + for the FeatureStore deployment. + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: MaxUnavailable specifies the maximum number/percentage + of pods that can be unavailable. + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + description: MinAvailable specifies the minimum number/percentage + of pods that must remain available. + x-kubernetes-int-or-string: true + type: object + x-kubernetes-validations: + - message: Exactly one of minAvailable or maxUnavailable must + be set. + rule: '[has(self.minAvailable), has(self.maxUnavailable)].exists_one(c, + c)' + registry: + description: Registry configures the registry service. One selection + is required. Local is the default setting. + properties: + local: + description: LocalRegistryConfig configures the registry service + properties: + persistence: + description: RegistryPersistence configures the persistence + settings for the registry service properties: - certName: - description: defines the configmap key name for the - client TLS cert. - type: string - configMapRef: - description: references the local k8s configmap where - the TLS cert resides + file: + description: RegistryFilePersistence configures the + file-based persistence for the registry service properties: - name: - default: "" + cache_mode: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + CacheMode defines the registry cache update strategy. + Allowed values are "sync" and "thread". + enum: + - none + - sync + - thread + type: string + cache_ttl_seconds: + description: CacheTTLSeconds defines the TTL (in + seconds) for the registry cache. + format: int32 + minimum: 0 + type: integer + path: type: string + pvc: + description: PvcConfig defines the settings for + a persistent file store based on PVCs. + properties: + create: + description: Settings for creating a new PVC + properties: + accessModes: + description: AccessModes k8s persistent + volume access modes. Defaults to ["ReadWriteOnce"]. + items: + type: string + type: array + resources: + description: Resources describes the storage + resource requirements for a volume. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the + minimum amount of compute resources + required. + type: object + type: object + storageClassName: + description: StorageClassName is the name + of an existing StorageClass to which + this persistent volume belongs. + type: string + type: object + x-kubernetes-validations: + - message: PvcCreate is immutable + rule: self == oldSelf + mountPath: + description: |- + MountPath within the container at which the volume should be mounted. + Must start by "/" and cannot contain ':'. + type: string + ref: + description: Reference to an existing field + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + required: + - mountPath + type: object + x-kubernetes-validations: + - message: One selection is required between ref + and create. + rule: '[has(self.ref), has(self.create)].exists_one(c, + c)' + - message: Mount path must start with '/' and + must not contain ':' + rule: self.mountPath.matches('^/[^:]*$') + s3_additional_kwargs: + additionalProperties: + type: string + type: object type: object - x-kubernetes-map-type: atomic - required: - - certName - - configMapRef - type: object + x-kubernetes-validations: + - message: Registry files must use absolute paths + or be S3 ('s3://') or GS ('gs://') object store + URIs. + rule: '(!has(self.pvc) && has(self.path)) ? (self.path.startsWith(''/'') + || self.path.startsWith(''s3://'') || self.path.startsWith(''gs://'')) + : true' + - message: PVC path must be a file name only, with + no slashes. + rule: '(has(self.pvc) && has(self.path)) ? !self.path.startsWith(''/'') + : true' + - message: PVC persistence does not support S3 or + GS object store URIs. + rule: '(has(self.pvc) && has(self.path)) ? !(self.path.startsWith(''s3://'') + || self.path.startsWith(''gs://'')) : true' + - message: Additional S3 settings are available only + for S3 object store URIs. + rule: '(has(self.s3_additional_kwargs) && has(self.path)) + ? self.path.startsWith(''s3://'') : true' + store: + description: RegistryDBStorePersistence configures + the DB store persistence for the registry service + properties: + secretKeyName: + description: By default, the selected store "type" + is used as the SecretKeyName + type: string + secretRef: + description: Data store parameters should be placed + as-is from the "feature_store.yaml" under the + secret key. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + type: + description: Type of the persistence type you + want to use. + enum: + - sql + - snowflake.registry + type: string + required: + - secretRef + - type + type: object + type: object + x-kubernetes-validations: + - message: One selection required between file or store. + rule: '[has(self.file), has(self.store)].exists_one(c, + c)' + server: + description: Creates a registry server container + properties: + env: + items: + description: EnvVar represents an environment variable + present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and... + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: + supports metadata.name, metadata.namespace, + `metadata.labels['''']`, `metadata.' + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, + defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults + to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in + the pod's namespace + properties: + key: + description: The key of the secret to + select from. Must be a valid secret + key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source + of a set of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the + name of each environment variable. Must be + a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + grpc: + description: Enable gRPC registry server. Defaults + to true if unset. + type: boolean + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image + type: string + logLevel: + description: |- + LogLevel sets the logging level for the server + Allowed values: "debug", "info", "warning", "error", "critical". + enum: + - debug + - info + - warning + - error + - critical + type: string + metrics: + description: Metrics exposes Prometheus-compatible + metrics for the Feast server when enabled. + type: boolean + nodeSelector: + additionalProperties: + type: string + type: object + resources: + description: ResourceRequirements describes the compute + resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. + type: string + request: + description: Request is the name chosen + for a request in the referenced claim. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount + of compute resources required. + type: object + type: object + restAPI: + description: Enable REST API registry server. + type: boolean + tls: + description: TlsConfigs configures server TLS for + a feast service. + properties: + disable: + description: will disable TLS for the feast service. + useful in an openshift cluster, for example, + where TLS is configured by default + type: boolean + secretKeyNames: + description: SecretKeyNames defines the secret + key names for the TLS key and cert. + properties: + tlsCrt: + description: defaults to "tls.crt" + type: string + tlsKey: + description: defaults to "tls.key" + type: string + type: object + secretRef: + description: references the local k8s secret where + the TLS key and cert reside + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: '`secretRef` required if `disable` is false.' + rule: '(!has(self.disable) || !self.disable) ? has(self.secretRef) + : true' + volumeMounts: + description: VolumeMounts defines the list of volumes + that should be mounted into the feast container. + items: + description: VolumeMount describes a mounting of + a Volume within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume + from which the container's volume should be + mounted. + type: string + required: + - mountPath + - name + type: object + type: array + workerConfigs: + description: WorkerConfigs defines the worker configuration + for the Feast server. + properties: + keepAliveTimeout: + description: |- + KeepAliveTimeout is the timeout for keep-alive connections in seconds. + Defaults to 30. + format: int32 + minimum: 1 + type: integer + maxRequests: + description: |- + MaxRequests is the maximum number of requests a worker will process before restarting. + This helps prevent memory leaks. + format: int32 + minimum: 0 + type: integer + maxRequestsJitter: + description: |- + MaxRequestsJitter is the maximum jitter to add to max-requests to prevent + thundering herd effect on worker restart. + format: int32 + minimum: 0 + type: integer + registryTTLSeconds: + description: RegistryTTLSeconds is the number + of seconds after which the registry is refreshed. + format: int32 + minimum: 0 + type: integer + workerConnections: + description: |- + WorkerConnections is the maximum number of simultaneous clients per worker process. + Defaults to 1000. + format: int32 + minimum: 1 + type: integer + workers: + description: Workers is the number of worker processes. + Use -1 to auto-calculate based on CPU cores + (2 * CPU + 1). + format: int32 + minimum: -1 + type: integer + type: object + type: object + x-kubernetes-validations: + - message: At least one of restAPI or grpc must be true + rule: self.restAPI == true || self.grpc == true || !has(self.grpc) + type: object + remote: + description: RemoteRegistryConfig points to a remote feast + registry server. + properties: + feastRef: + description: Reference to an existing `FeatureStore` CR + in the same k8s cluster. + properties: + name: + description: Name of the FeatureStore + type: string + namespace: + description: Namespace of the FeatureStore + type: string + required: + - name + type: object + hostname: + description: Host address of the remote registry service + - :, e.g. `registry..svc.cluster.local:80` + type: string + tls: + description: TlsRemoteRegistryConfigs configures client + TLS for a remote feast registry. + properties: + certName: + description: defines the configmap key name for the + client TLS cert. + type: string + configMapRef: + description: references the local k8s configmap where + the TLS cert resides + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + required: + - certName + - configMapRef + type: object + type: object + x-kubernetes-validations: + - message: One selection required. + rule: '[has(self.hostname), has(self.feastRef)].exists_one(c, + c)' + type: object + x-kubernetes-validations: + - message: One selection required. + rule: '[has(self.local), has(self.remote)].exists_one(c, c)' + runFeastApplyOnInit: + description: Runs feast apply on pod start to populate the registry. + Defaults to true. Ignored when DisableInitContainers is true. + type: boolean + scaling: + description: Scaling configures horizontal scaling for the FeatureStore + deployment (e.g. HPA autoscaling). + properties: + autoscaling: + description: |- + Autoscaling configures a HorizontalPodAutoscaler for the FeatureStore deployment. + Mutually exclusive with spec.replicas. + properties: + behavior: + description: Behavior configures the scaling behavior + of the target. + properties: + scaleDown: + description: scaleDown is scaling policy for scaling + Down. + properties: + policies: + description: policies is a list of potential scaling + polices which can be used during scaling. + items: + description: HPAScalingPolicy is a single policy + which must hold true for a specified past + interval. + properties: + periodSeconds: + description: periodSeconds specifies the + window of time for which the policy should + hold true. + format: int32 + type: integer + type: + description: type is used to specify the + scaling policy. + type: string + value: + description: |- + value contains the amount of change which is permitted by the policy. + It must be greater than zero + format: int32 + type: integer + required: + - periodSeconds + - type + - value + type: object + type: array + x-kubernetes-list-type: atomic + selectPolicy: + description: |- + selectPolicy is used to specify which policy should be used. + If not set, the default value Max is used. + type: string + stabilizationWindowSeconds: + description: |- + stabilizationWindowSeconds is the number of seconds for which past recommendations should be + considered while scaling... + format: int32 + type: integer + tolerance: + anyOf: + - type: integer + - type: string + description: |- + tolerance is the tolerance on the ratio between the current and desired + metric value under which no updates are made to... + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + scaleUp: + description: scaleUp is scaling policy for scaling + Up. + properties: + policies: + description: policies is a list of potential scaling + polices which can be used during scaling. + items: + description: HPAScalingPolicy is a single policy + which must hold true for a specified past + interval. + properties: + periodSeconds: + description: periodSeconds specifies the + window of time for which the policy should + hold true. + format: int32 + type: integer + type: + description: type is used to specify the + scaling policy. + type: string + value: + description: |- + value contains the amount of change which is permitted by the policy. + It must be greater than zero + format: int32 + type: integer + required: + - periodSeconds + - type + - value + type: object + type: array + x-kubernetes-list-type: atomic + selectPolicy: + description: |- + selectPolicy is used to specify which policy should be used. + If not set, the default value Max is used. + type: string + stabilizationWindowSeconds: + description: |- + stabilizationWindowSeconds is the number of seconds for which past recommendations should be + considered while scaling... + format: int32 + type: integer + tolerance: + anyOf: + - type: integer + - type: string + description: |- + tolerance is the tolerance on the ratio between the current and desired + metric value under which no updates are made to... + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + maxReplicas: + description: MaxReplicas is the upper limit for the number + of replicas. Required. + format: int32 + minimum: 1 + type: integer + metrics: + description: Metrics contains the specifications for which + to use to calculate the desired replica count. + items: + description: |- + MetricSpec specifies how to scale based on a single metric + (only `type` and one other matching field should be set at... + properties: + containerResource: + description: |- + containerResource refers to a resource metric (such as those specified in + requests and limits) known to Kubernetes... + properties: + container: + description: container is the name of the container + in the pods of the scaling target + type: string + name: + description: name is the name of the resource + in question. + type: string + target: + description: target specifies the target value + for the given metric + properties: + averageUtilization: + description: |- + averageUtilization is the target value of the average of the + resource metric across all relevant pods, represented as a... + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether the + metric type is Utilization, Value, or + AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value of + the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - container + - name + - target + type: object + external: + description: |- + external refers to a global metric that is not associated + with any Kubernetes object. + properties: + metric: + description: metric identifies the target metric + by name and selector + properties: + name: + description: name is the name of the given + metric + type: string + selector: + description: |- + selector is the string-encoded form of a standard kubernetes label selector for the given metric + When set, it is passed... + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - name + type: object + target: + description: target specifies the target value + for the given metric + properties: + averageUtilization: + description: |- + averageUtilization is the target value of the average of the + resource metric across all relevant pods, represented as a... + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether the + metric type is Utilization, Value, or + AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value of + the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - metric + - target + type: object + object: + description: |- + object refers to a metric describing a single kubernetes object + (for example, hits-per-second on an Ingress object). + properties: + describedObject: + description: describedObject specifies the descriptions + of a object,such as kind,name apiVersion + properties: + apiVersion: + description: apiVersion is the API version + of the referent + type: string + kind: + description: 'kind is the kind of the referent; + More info: https://git.k8s.' + type: string + name: + description: 'name is the name of the referent; + More info: https://kubernetes.' + type: string + required: + - kind + - name + type: object + metric: + description: metric identifies the target metric + by name and selector + properties: + name: + description: name is the name of the given + metric + type: string + selector: + description: |- + selector is the string-encoded form of a standard kubernetes label selector for the given metric + When set, it is passed... + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - name + type: object + target: + description: target specifies the target value + for the given metric + properties: + averageUtilization: + description: |- + averageUtilization is the target value of the average of the + resource metric across all relevant pods, represented as a... + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether the + metric type is Utilization, Value, or + AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value of + the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - describedObject + - metric + - target + type: object + pods: + description: |- + pods refers to a metric describing each pod in the current scale target + (for example,... + properties: + metric: + description: metric identifies the target metric + by name and selector + properties: + name: + description: name is the name of the given + metric + type: string + selector: + description: |- + selector is the string-encoded form of a standard kubernetes label selector for the given metric + When set, it is passed... + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - name + type: object + target: + description: target specifies the target value + for the given metric + properties: + averageUtilization: + description: |- + averageUtilization is the target value of the average of the + resource metric across all relevant pods, represented as a... + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether the + metric type is Utilization, Value, or + AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value of + the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - metric + - target + type: object + resource: + description: |- + resource refers to a resource metric (such as those specified in + requests and limits) known to Kubernetes describing... + properties: + name: + description: name is the name of the resource + in question. + type: string + target: + description: target specifies the target value + for the given metric + properties: + averageUtilization: + description: |- + averageUtilization is the target value of the average of the + resource metric across all relevant pods, represented as a... + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether the + metric type is Utilization, Value, or + AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value of + the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - name + - target + type: object + type: + description: type is the type of metric source. + type: string + required: + - type + type: object + type: array + minReplicas: + description: MinReplicas is the lower limit for the number + of replicas. Defaults to 1. + format: int32 + minimum: 1 + type: integer + required: + - maxReplicas type: object - x-kubernetes-validations: - - message: One selection required. - rule: '[has(self.hostname), has(self.feastRef)].exists_one(c, - c)' type: object - x-kubernetes-validations: - - message: One selection required. - rule: '[has(self.local), has(self.remote)].exists_one(c, c)' securityContext: description: PodSecurityContext holds pod-level security attributes and common container settings. @@ -2406,6 +3814,10 @@ spec: Defaults to user specified in image metadata if unspecified. format: int64 type: integer + seLinuxChangePolicy: + description: seLinuxChangePolicy defines how the container's + SELinux label is applied to all volumes used by the Pod. + type: string seLinuxOptions: description: The SELinux context to be applied to all containers. properties: @@ -2444,13 +3856,18 @@ spec: type: object supplementalGroups: description: |- - A list of groups applied to the first process run in each container, in addition - to the container's primary GID, the fsG + A list of groups applied to the first process run in each container, in + addition to the container's primary GID and... items: format: int64 type: integer type: array x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + description: |- + Defines how supplemental groups of the first container processes are calculated. + Valid values are "Merge" and "Strict". + type: string sysctls: description: Sysctls hold a list of namespaced sysctls used for the pod. @@ -2492,6 +3909,96 @@ spec: type: string type: object type: object + topologySpreadConstraints: + description: TopologySpreadConstraints defines how pods are spread + across topology domains. + items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. + properties: + labelSelector: + description: LabelSelector is used to find matching pods. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. + format: int32 + type: integer + minDomains: + description: MinDomains indicates a minimum number of eligible + domains. + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread... + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. + type: string + topologyKey: + description: TopologyKey is the key of node labels. + type: string + whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array ui: description: Creates a UI server container properties: @@ -2507,8 +4014,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's value. @@ -2607,7 +4113,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of a set - of ConfigMaps + of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -2626,8 +4132,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -2688,6 +4194,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen for a request + in the referenced claim. + type: string required: - name type: object @@ -2856,7 +4366,7 @@ spec: awsElasticBlockStore: description: |- awsElasticBlockStore represents an AWS Disk resource that is attached to a - kubelet's host machine and then exposed to th + kubelet's host machine and then exposed to... properties: fsType: description: fsType is the filesystem type of the volume @@ -2898,6 +4408,7 @@ spec: blob storage type: string fsType: + default: ext4 description: |- fsType is Filesystem type to mount. Must be a filesystem type supported by the host operating system. @@ -2906,9 +4417,10 @@ spec: kind: description: 'kind expected values are Shared: multiple blob disks per storage account Dedicated: single - blob disk per storage accoun' + blob disk per storage...' type: string readOnly: + default: false description: |- readOnly Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. @@ -2939,7 +4451,7 @@ spec: type: object cephfs: description: cephFS represents a Ceph FS mount on the host - that shares a pod's lifetime + that shares a pod's lifetime. properties: monitors: description: |- @@ -2987,7 +4499,7 @@ spec: cinder: description: |- cinder represents a cinder volume attached and mounted on kubelets host machine. - More info: https://examples.k8s. + Deprecated: Cinder is deprecated. properties: fsType: description: |- @@ -3033,7 +4545,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volum + ConfigMap will be projected into the... items: description: Maps a string key to a path within a volume. @@ -3073,7 +4585,7 @@ spec: csi: description: csi (Container Storage Interface) represents ephemeral storage that is handled by certain external - CSI drivers (Beta fea + CSI drivers. properties: driver: description: driver is the name of the CSI driver that @@ -3085,7 +4597,7 @@ spec: nodePublishSecretRef: description: |- nodePublishSecretRef is a reference to the secret object containing - sensitive information to pass to the CSI driver to c + sensitive information to pass to the CSI driver to... properties: name: default: "" @@ -3147,7 +4659,7 @@ spec: mode: description: |- Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal valu + between 0000 and 0777 or a decimal... format: int32 type: integer path: @@ -3396,9 +4908,9 @@ spec: type: array x-kubernetes-list-type: atomic wwids: - description: "wwids Optional: FC volume world wide identifiers - (wwids)\nEither wwids or combination of targetWWNs - and lun must be set, " + description: |- + wwids Optional: FC volume world wide identifiers (wwids) + Either wwids or combination of targetWWNs and lun must be set,... items: type: string type: array @@ -3433,7 +4945,7 @@ spec: secretRef: description: |- secretRef is Optional: secretRef is reference to the secret object containing - sensitive information to pass to the plugi + sensitive information to pass to the... properties: name: default: "" @@ -3454,7 +4966,7 @@ spec: datasetName: description: |- datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker - should be considered as depreca + should be considered as... type: string datasetUUID: description: datasetUUID is the UUID of the dataset. @@ -3464,7 +4976,7 @@ spec: gcePersistentDisk: description: |- gcePersistentDisk represents a GCE Disk resource that is attached to a - kubelet's host machine and then exposed to the po + kubelet's host machine and then exposed to the... properties: fsType: description: fsType is filesystem type of the volume @@ -3493,7 +5005,7 @@ spec: gitRepo: description: |- gitRepo represents a git repository at a particular revision. - DEPRECATED: GitRepo is deprecated. + Deprecated: GitRepo is deprecated. properties: directory: description: |- @@ -3511,9 +5023,8 @@ spec: - repository type: object glusterfs: - description: |- - glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. - More info: https://examples.k8s. + description: glusterfs represents a Glusterfs mount on the + host that shares a pod's lifetime. properties: endpoints: description: |- @@ -3553,6 +5064,22 @@ spec: required: - path type: object + image: + description: image represents an OCI object (a container + image or artifact) pulled and mounted on the kubelet's + host machine. + properties: + pullPolicy: + description: |- + Policy for pulling OCI objects. Possible values are: + Always: the kubelet always attempts to pull the reference. + type: string + reference: + description: |- + Required: Image or artifact reference to be used. + Behaves in the same way as pod.spec.containers[*].image. + type: string + type: object iscsi: description: |- iscsi represents an ISCSI Disk resource that is attached to a @@ -3578,6 +5105,7 @@ spec: description: iqn is the target iSCSI Qualified Name. type: string iscsiInterface: + default: default description: |- iscsiInterface is the interface Name that uses an iSCSI transport. Defaults to 'default' (tcp). @@ -3668,7 +5196,7 @@ spec: photonPersistentDisk: description: photonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host - machine + machine. properties: fsType: description: |- @@ -3685,7 +5213,7 @@ spec: type: object portworxVolume: description: portworxVolume represents a portworx volume - attached and mounted on kubelets host machine + attached and mounted on kubelets host machine. properties: fsType: description: |- @@ -3715,10 +5243,13 @@ spec: format: int32 type: integer sources: - description: sources is the list of volume projections + description: |- + sources is the list of volume projections. Each entry in this list + handles one source. items: - description: Projection that may be projected along - with other supported volume types + description: |- + Projection that may be projected along with other supported volume types. + Exactly one of these fields must be set. properties: clusterTrustBundle: description: ClusterTrustBundle allows a pod to @@ -3798,7 +5329,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volum + ConfigMap will be projected into the... items: description: Maps a string key to a path within a volume. @@ -3869,7 +5400,7 @@ spec: mode: description: |- Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal valu + between 0000 and 0777 or a decimal... format: int32 type: integer path: @@ -3918,7 +5449,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume a + Secret will be projected into the volume... items: description: Maps a string key to a path within a volume. @@ -3984,7 +5515,7 @@ spec: type: object quobyte: description: quobyte represents a Quobyte mount on the host - that shares a pod's lifetime + that shares a pod's lifetime. properties: group: description: |- @@ -3999,12 +5530,12 @@ spec: registry: description: |- registry represents a single or multiple Quobyte Registry services - specified as a string as host:port pair (multiple ent + specified as a string as host:port pair (multiple... type: string tenant: description: |- tenant owning the given Quobyte volume in the Backend - Used with dynamically provisioned Quobyte volumes, value is set by + Used with dynamically provisioned Quobyte volumes, value is set... type: string user: description: |- @@ -4020,9 +5551,8 @@ spec: - volume type: object rbd: - description: |- - rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. - More info: https://examples.k8s. + description: rbd represents a Rados Block Device mount on + the host that shares a pod's lifetime. properties: fsType: description: fsType is the filesystem type of the volume @@ -4034,6 +5564,7 @@ spec: More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it type: string keyring: + default: /etc/ceph/keyring description: |- keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. @@ -4048,6 +5579,7 @@ spec: type: array x-kubernetes-list-type: atomic pool: + default: rbd description: |- pool is the rados pool name. Default is rbd. @@ -4075,6 +5607,7 @@ spec: type: object x-kubernetes-map-type: atomic user: + default: admin description: |- user is the rados user name. Default is admin. @@ -4089,6 +5622,7 @@ spec: attached and mounted on Kubernetes nodes. properties: fsType: + default: xfs description: |- fsType is the filesystem type to mount. Must be a filesystem type supported by the host operating system. @@ -4126,6 +5660,7 @@ spec: with Gateway, default false type: boolean storageMode: + default: ThinProvisioned description: storageMode indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. type: string @@ -4160,7 +5695,7 @@ spec: items: description: |- items If unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume a + Secret will be projected into the volume... items: description: Maps a string key to a path within a volume. @@ -4235,7 +5770,7 @@ spec: type: object vsphereVolume: description: vsphereVolume represents a vSphere volume attached - and mounted on kubelets host machine + and mounted on kubelets host machine. properties: fsType: description: |- @@ -4266,6 +5801,35 @@ spec: required: - feastProject type: object + x-kubernetes-validations: + - message: replicas > 1 and services.scaling.autoscaling are mutually + exclusive. + rule: self.replicas <= 1 || !has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling) + - message: Scaling requires DB-backed persistence for the online store. + Configure services.onlineStore.persistence.store when using replicas + > 1 or autoscaling. + rule: self.replicas <= 1 && (!has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling)) || (has(self.services) + && has(self.services.onlineStore) && has(self.services.onlineStore.persistence) + && has(self.services.onlineStore.persistence.store)) + - message: Scaling requires DB-backed persistence for the offline store. + Configure services.offlineStore.persistence.store when using replicas + > 1 or autoscaling. + rule: self.replicas <= 1 && (!has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling)) || (!has(self.services) + || !has(self.services.offlineStore) || (has(self.services.offlineStore.persistence) + && has(self.services.offlineStore.persistence.store))) + - message: Scaling requires DB-backed or remote registry. Configure registry.local.persistence.store + or use a remote registry when using replicas > 1 or autoscaling. S3/GCS-backed + registry is also allowed. + rule: self.replicas <= 1 && (!has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling)) || (has(self.services) + && has(self.services.registry) && (has(self.services.registry.remote) + || (has(self.services.registry.local) && has(self.services.registry.local.persistence) + && (has(self.services.registry.local.persistence.store) || (has(self.services.registry.local.persistence.file) + && has(self.services.registry.local.persistence.file.path) && (self.services.registry.local.persistence.file.path.startsWith('s3://') + || self.services.registry.local.persistence.file.path.startsWith('gs://'))))))) status: description: FeatureStoreStatus defines the observed state of FeatureStore properties: @@ -4286,81 +5850,507 @@ spec: description: The Kubernetes RBAC roles to be deployed in the same namespace of the FeatureStore. items: - type: string + type: string + type: array + type: object + oidc: + description: |- + OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. + https://auth0. + properties: + caCertConfigMap: + description: ConfigMap with the CA certificate for self-signed + OIDC providers. Auto-detected on RHOAI/ODH. + properties: + key: + description: Key in the ConfigMap holding the PEM + certificate. Defaults to "ca-bundle.crt". + type: string + name: + description: ConfigMap name. + type: string + required: + - name + type: object + issuerUrl: + description: OIDC issuer URL. The operator appends /.well-known/openid-configuration + to derive the discovery endpoint. + pattern: ^https://\S+$ + type: string + secretKeyName: + description: Key in the Secret containing all OIDC properties + as a YAML value. If unset, each key is a property. + type: string + secretRef: + description: Secret with OIDC properties (auth_discovery_url, + client_id, client_secret). issuerUrl takes precedence. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + tokenEnvVar: + description: Env var name for client pods to read an OIDC + token from. Sets token_env_var in client config. + type: string + verifySSL: + description: Verify SSL certificates for the OIDC provider. + Defaults to true. + type: boolean + type: object + type: object + x-kubernetes-validations: + - message: One selection required between kubernetes or oidc. + rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, + c)' + batchEngine: + description: BatchEngineConfig defines the batch compute engine + configuration. + properties: + configMapKey: + description: Key name in the ConfigMap. Defaults to "config" + if not specified. + type: string + configMapRef: + description: Reference to a ConfigMap containing the batch + engine configuration. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + type: object + x-kubernetes-map-type: atomic + type: object + cronJob: + description: FeastCronJob defines a CronJob to execute against + a Feature Store deployment. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to be added to the CronJob metadata. + type: object + concurrencyPolicy: + description: Specifies how to treat concurrent executions + of a Job. + type: string + containerConfigs: + description: CronJobContainerConfigs k8s container settings + for the CronJob + properties: + commands: + description: Array of commands to be executed (in order) + against a Feature Store deployment. + items: + type: string + type: array + env: + items: + description: EnvVar represents an environment variable + present in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and... + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits. + properties: + containerName: + description: 'Container name: required for + volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the + pod's namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source of + a set of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. + type: string + optional: + description: Specify whether the Secret must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object type: array - type: object - oidc: - description: |- - OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider. - https://auth0. - properties: - secretRef: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when + to pull a container image + type: string + nodeSelector: + additionalProperties: + type: string + type: object + resources: + description: ResourceRequirements describes the compute + resource requirements. properties: - name: - default: "" + claims: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. + type: string + request: + description: Request is the name chosen for + a request in the referenced claim. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes. + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Requests describes the minimum amount + of compute resources required. + type: object type: object - x-kubernetes-map-type: atomic - required: - - secretRef type: object - type: object - x-kubernetes-validations: - - message: One selection required between kubernetes or oidc. - rule: '[has(self.kubernetes), has(self.oidc)].exists_one(c, - c)' - batchEngine: - description: BatchEngineConfig defines the batch compute engine - configuration. - properties: - configMapKey: - description: Key name in the ConfigMap. Defaults to "config" - if not specified. - type: string - configMapRef: - description: Reference to a ConfigMap containing the batch - engine configuration. + failedJobsHistoryLimit: + description: The number of failed finished jobs to retain. + Value must be non-negative integer. + format: int32 + type: integer + jobSpec: + description: Specification of the desired behavior of a job. properties: - name: - default: "" + activeDeadlineSeconds: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. + Specifies the duration in seconds relative to the startTime that the job + may be continuously active before the system... + format: int64 + type: integer + backoffLimit: + description: Specifies the number of retries before marking + this job failed. + format: int32 + type: integer + backoffLimitPerIndex: + description: |- + Specifies the limit for the number of retries within an + index before marking this index as failed. + format: int32 + type: integer + completionMode: + description: |- + completionMode specifies how Pod completions are tracked. It can be + `NonIndexed` (default) or `Indexed`. + type: string + completions: + description: |- + Specifies the desired number of successfully finished pods the + job should be run with. + format: int32 + type: integer + maxFailedIndexes: + description: |- + Specifies the maximal number of failed indexes before marking the Job as + failed, when backoffLimitPerIndex is set. + format: int32 + type: integer + parallelism: + description: |- + Specifies the maximum desired number of pods the job should + run at any given time. + format: int32 + type: integer + podFailurePolicy: + description: Specifies the policy of handling failed pods. + properties: + rules: + description: A list of pod failure policy rules. The + rules are evaluated in order. + items: + description: PodFailurePolicyRule describes how + a pod failure is handled when the requirements + are met. + properties: + action: + description: Specifies the action taken on a + pod failure when the requirements are satisfied. + type: string + onExitCodes: + description: Represents the requirement on the + container exit codes. + properties: + containerName: + description: |- + Restricts the check for exit codes to the container with the + specified name. + type: string + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. + type: string + values: + description: Specifies the set of values. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + - values + type: object + onPodConditions: + description: |- + Represents the requirement on the pod conditions. The requirement is represented + as a list of pod condition patterns. + items: + description: |- + PodFailurePolicyOnPodConditionsPattern describes a pattern for matching + an actual pod condition type. + properties: + status: + description: Specifies the required Pod + condition status. + type: string + type: + description: Specifies the required Pod + condition type. + type: string + required: + - status + - type + type: object + type: array + x-kubernetes-list-type: atomic + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + required: + - rules + type: object + podReplacementPolicy: + description: podReplacementPolicy specifies when to create + replacement Pods. type: string + podTemplateAnnotations: + additionalProperties: + type: string + description: |- + PodTemplateAnnotations are annotations to be applied to the CronJob's PodTemplate + metadata. + type: object + suspend: + description: suspend specifies whether the Job controller + should create Pods or not. + type: boolean + ttlSecondsAfterFinished: + description: |- + ttlSecondsAfterFinished limits the lifetime of a Job that has finished + execution (either Complete or Failed). + format: int32 + type: integer type: object - x-kubernetes-map-type: atomic + schedule: + description: The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. + type: string + startingDeadlineSeconds: + description: |- + Optional deadline in seconds for starting the job if it misses scheduled + time for any reason. + format: int64 + type: integer + successfulJobsHistoryLimit: + description: The number of successful finished jobs to retain. + Value must be non-negative integer. + format: int32 + type: integer + suspend: + description: |- + This flag tells the controller to suspend subsequent executions, it does + not apply to already started executions. + type: boolean + timeZone: + description: The time zone name for the given schedule, see + https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. + type: string type: object - cronJob: - description: FeastCronJob defines a CronJob to execute against - a Feature Store deployment. + feastProject: + description: FeastProject is the Feast project id. + pattern: ^[A-Za-z0-9][A-Za-z0-9_-]*$ + type: string + feastProjectDir: + description: FeastProjectDir defines how to create the feast project + directory. properties: - annotations: - additionalProperties: - type: string - description: Annotations to be added to the CronJob metadata. - type: object - concurrencyPolicy: - description: Specifies how to treat concurrent executions - of a Job. - type: string - containerConfigs: - description: CronJobContainerConfigs k8s container settings - for the CronJob + git: + description: GitCloneOptions describes how a clone should + be performed. properties: - commands: - description: Array of commands to be executed (in order) - against a Feature Store deployment. - items: + configs: + additionalProperties: type: string - type: array + description: |- + Configs passed to git via `-c` + e.g. http.sslVerify: 'false' + OR 'url."https://api:\${TOKEN}@github.com/". + type: object env: items: description: EnvVar represents an environment variable @@ -4373,8 +6363,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -4474,7 +6463,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -4493,8 +6482,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -4514,449 +6503,813 @@ spec: x-kubernetes-map-type: atomic type: object type: array - image: + featureRepoPath: + description: FeatureRepoPath is the relative path to the + feature repo subdirectory. Default is 'feature_repo'. type: string - imagePullPolicy: - description: PullPolicy describes a policy for if/when - to pull a container image + ref: + description: Reference to a branch / tag / commit type: string - nodeSelector: - additionalProperties: - type: string + url: + description: The repository URL to clone from. + type: string + required: + - url + type: object + x-kubernetes-validations: + - message: RepoPath must be a file name only, with no slashes. + rule: 'has(self.featureRepoPath) ? !self.featureRepoPath.startsWith(''/'') + : true' + init: + description: FeastInitOptions defines how to run a `feast + init`. + properties: + minimal: + type: boolean + template: + description: Template for the created project + enum: + - local + - gcp + - aws + - snowflake + - spark + - postgres + - hbase + - cassandra + - hazelcast + - couchbase + - clickhouse + type: string + type: object + type: object + x-kubernetes-validations: + - message: One selection required between init or git. + rule: '[has(self.git), has(self.init)].exists_one(c, c)' + replicas: + default: 1 + description: |- + Replicas is the desired number of pod replicas. Used by the scale sub-resource. + Mutually exclusive with services. + format: int32 + minimum: 1 + type: integer + services: + description: FeatureStoreServices defines the desired feast services. + An ephemeral onlineStore feature server is deployed by default. + properties: + affinity: + description: Affinity defines the pod scheduling constraints + for the FeatureStore deployment. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but... + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto... + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic type: object - resources: - description: ResourceRequirements describes the compute - resource requirements. + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). properties: - claims: + preferredDuringSchedulingIgnoredDuringExecution: description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but... items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) properties: - name: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in... + type: string + required: + - topologyKey + type: object + weight: description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. - type: string + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer required: - - name + - podAffinityTerm + - weight type: object type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes. - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Requests describes the minimum amount - of compute resources required. - type: object - type: object - type: object - failedJobsHistoryLimit: - description: The number of failed finished jobs to retain. - Value must be non-negative integer. - format: int32 - type: integer - jobSpec: - description: Specification of the desired behavior of a job. - properties: - activeDeadlineSeconds: - description: |- - Specifies the duration in seconds relative to the startTime that the job - may be continuously active before the system tr - format: int64 - type: integer - backoffLimit: - description: Specifies the number of retries before marking - this job failed. - format: int32 - type: integer - backoffLimitPerIndex: - description: |- - Specifies the limit for the number of retries within an - index before marking this index as failed. - format: int32 - type: integer - completionMode: - description: |- - completionMode specifies how Pod completions are tracked. It can be - `NonIndexed` (default) or `Indexed`. - type: string - completions: - description: |- - Specifies the desired number of successfully finished pods the - job should be run with. - format: int32 - type: integer - maxFailedIndexes: - description: |- - Specifies the maximal number of failed indexes before marking the Job as - failed, when backoffLimitPerIndex is set. - format: int32 - type: integer - parallelism: - description: |- - Specifies the maximum desired number of pods the job should - run at any given time. - format: int32 - type: integer - podFailurePolicy: - description: Specifies the policy of handling failed pods. - properties: - rules: - description: A list of pod failure policy rules. The - rules are evaluated in order. + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto... items: - description: PodFailurePolicyRule describes how - a pod failure is handled when the requirements - are met. + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should... properties: - action: - description: Specifies the action taken on a - pod failure when the requirements are satisfied. - type: string - onExitCodes: - description: Represents the requirement on the - container exit codes. + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: - containerName: - description: |- - Restricts the check for exit codes to the container with the - specified name. - type: string - operator: - description: |- - Represents the relationship between the container exit code(s) and the - specified values. - type: string - values: - description: Specifies the set of values. + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. items: - format: int32 - type: integer + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object type: array - x-kubernetes-list-type: set - required: - - operator - - values + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object type: object - onPodConditions: + x-kubernetes-map-type: atomic + matchLabelKeys: description: |- - Represents the requirement on the pod conditions. The requirement is represented - as a list of pod condition patterns. + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. items: - description: |- - PodFailurePolicyOnPodConditionsPattern describes a pattern for matching - an actual pod condition type. - properties: - status: - description: Specifies the required Pod - condition status. - type: string - type: - description: Specifies the required Pod - condition type. + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: type: string - required: - - status - - type - type: object + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + items: + type: string type: array x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in... + type: string required: - - action + - topologyKey type: object type: array x-kubernetes-list-type: atomic - required: - - rules - type: object - podReplacementPolicy: - description: podReplacementPolicy specifies when to create - replacement Pods. - type: string - podTemplateAnnotations: - additionalProperties: - type: string - description: |- - PodTemplateAnnotations are annotations to be applied to the CronJob's PodTemplate - metadata. - type: object - suspend: - description: suspend specifies whether the Job controller - should create Pods or not. - type: boolean - ttlSecondsAfterFinished: - description: |- - ttlSecondsAfterFinished limits the lifetime of a Job that has finished - execution (either Complete or Failed). - format: int32 - type: integer - type: object - schedule: - description: The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. - type: string - startingDeadlineSeconds: - description: |- - Optional deadline in seconds for starting the job if it misses scheduled - time for any reason. - format: int64 - type: integer - successfulJobsHistoryLimit: - description: The number of successful finished jobs to retain. - Value must be non-negative integer. - format: int32 - type: integer - suspend: - description: |- - This flag tells the controller to suspend subsequent executions, it does - not apply to already started executions. - type: boolean - timeZone: - description: The time zone name for the given schedule, see - https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. - type: string - type: object - feastProject: - description: FeastProject is the Feast project id. - pattern: ^[A-Za-z0-9][A-Za-z0-9_-]*$ - type: string - feastProjectDir: - description: FeastProjectDir defines how to create the feast project - directory. - properties: - git: - description: GitCloneOptions describes how a clone should - be performed. - properties: - configs: - additionalProperties: - type: string - description: |- - Configs passed to git via `-c` - e.g. http.sslVerify: 'false' - OR 'url."https://api:\${TOKEN}@github.com/". type: object - env: - items: - description: EnvVar represents an environment variable - present in a Container. - properties: - name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any - type: string - valueFrom: - description: Source for the environment variable's - value. Cannot be used if value is not empty. + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, + etc. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field,... + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. properties: - key: - description: The key to select. - type: string - name: - default: "" + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the ConfigMap - or its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: 'Selects a field of the pod: supports - metadata.name, metadata.namespace, `metadata.labels['''']`, - `metadata.' - properties: - apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select - in the specified API version. + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in... type: string required: - - fieldPath + - topologyKey type: object - x-kubernetes-map-type: atomic - resourceFieldRef: + weight: description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits. - properties: - containerName: - description: 'Container name: required for - volumes, optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format - of the exposed resources, defaults to - "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the - pod's namespace + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled... + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should... + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: - key: - description: The key of the secret to select - from. Must be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the Secret - or its key must be defined - type: boolean - required: - - key + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object type: object x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - envFrom: - items: - description: EnvFromSource represents the source of - a set of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - default: "" + matchLabelKeys: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the ConfigMap must - be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - default: "" + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. - type: string - optional: - description: Specify whether the Secret must - be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - featureRepoPath: - description: FeatureRepoPath is the relative path to the - feature repo subdirectory. Default is 'feature_repo'. - type: string - ref: - description: Reference to a branch / tag / commit - type: string - url: - description: The repository URL to clone from. - type: string - required: - - url - type: object - x-kubernetes-validations: - - message: RepoPath must be a file name only, with no slashes. - rule: 'has(self.featureRepoPath) ? !self.featureRepoPath.startsWith(''/'') - : true' - init: - description: FeastInitOptions defines how to run a `feast - init`. - properties: - minimal: - type: boolean - template: - description: Template for the created project - enum: - - local - - gcp - - aws - - snowflake - - spark - - postgres - - hbase - - cassandra - - hazelcast - - ikv - - couchbase - - clickhouse - type: string + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in... + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object type: object - type: object - x-kubernetes-validations: - - message: One selection required between init or git. - rule: '[has(self.git), has(self.init)].exists_one(c, c)' - services: - description: FeatureStoreServices defines the desired feast services. - An ephemeral onlineStore feature server is deployed by default. - properties: deploymentStrategy: description: DeploymentStrategy describes how to replace existing pods with new ones. @@ -5123,6 +7476,7 @@ spec: - couchbase.offline - clickhouse - ray + - oracle type: string required: - secretRef @@ -5148,8 +7502,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -5252,7 +7605,7 @@ spec: envFrom: items: description: EnvFromSource represents the source - of a set of ConfigMaps + of a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -5271,8 +7624,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the + name of each environment variable. Must be + a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -5334,6 +7688,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen + for a request in the referenced claim. + type: string required: - name type: object @@ -5626,7 +7984,6 @@ spec: enum: - snowflake.online - redis - - ikv - datastore - dynamodb - bigtable @@ -5641,6 +7998,7 @@ spec: - couchbase.online - milvus - hybrid + - mongodb type: string required: - secretRef @@ -5666,8 +8024,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -5770,7 +8127,7 @@ spec: envFrom: items: description: EnvFromSource represents the source - of a set of ConfigMaps + of a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -5789,8 +8146,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the + name of each environment variable. Must be + a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -5852,6 +8210,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen + for a request in the referenced claim. + type: string required: - name type: object @@ -6012,6 +8374,36 @@ spec: type: object type: object type: object + podAnnotations: + additionalProperties: + type: string + description: PodAnnotations are annotations to be applied + to the Deployment's PodTemplate metadata. + type: object + podDisruptionBudgets: + description: PodDisruptionBudgets configures a PodDisruptionBudget + for the FeatureStore deployment. + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: MaxUnavailable specifies the maximum number/percentage + of pods that can be unavailable. + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + description: MinAvailable specifies the minimum number/percentage + of pods that must remain available. + x-kubernetes-int-or-string: true + type: object + x-kubernetes-validations: + - message: Exactly one of minAvailable or maxUnavailable must + be set. + rule: '[has(self.minAvailable), has(self.maxUnavailable)].exists_one(c, + c)' registry: description: Registry configures the registry service. One selection is required. Local is the default setting. @@ -6206,8 +8598,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment @@ -6312,7 +8703,7 @@ spec: envFrom: items: description: EnvFromSource represents the source - of a set of ConfigMaps + of a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -6331,9 +8722,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be - a C_IDENTIFIER. + description: Optional text to prepend to + the name of each environment variable. + Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -6399,6 +8790,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen + for a request in the referenced claim. + type: string required: - name type: object @@ -6618,15 +9013,605 @@ spec: - configMapRef type: object type: object - x-kubernetes-validations: - - message: One selection required. - rule: '[has(self.hostname), has(self.feastRef)].exists_one(c, - c)' + x-kubernetes-validations: + - message: One selection required. + rule: '[has(self.hostname), has(self.feastRef)].exists_one(c, + c)' + type: object + x-kubernetes-validations: + - message: One selection required. + rule: '[has(self.local), has(self.remote)].exists_one(c, + c)' + runFeastApplyOnInit: + description: Runs feast apply on pod start to populate the + registry. Defaults to true. Ignored when DisableInitContainers + is true. + type: boolean + scaling: + description: Scaling configures horizontal scaling for the + FeatureStore deployment (e.g. HPA autoscaling). + properties: + autoscaling: + description: |- + Autoscaling configures a HorizontalPodAutoscaler for the FeatureStore deployment. + Mutually exclusive with spec.replicas. + properties: + behavior: + description: Behavior configures the scaling behavior + of the target. + properties: + scaleDown: + description: scaleDown is scaling policy for scaling + Down. + properties: + policies: + description: policies is a list of potential + scaling polices which can be used during + scaling. + items: + description: HPAScalingPolicy is a single + policy which must hold true for a specified + past interval. + properties: + periodSeconds: + description: periodSeconds specifies + the window of time for which the policy + should hold true. + format: int32 + type: integer + type: + description: type is used to specify + the scaling policy. + type: string + value: + description: |- + value contains the amount of change which is permitted by the policy. + It must be greater than zero + format: int32 + type: integer + required: + - periodSeconds + - type + - value + type: object + type: array + x-kubernetes-list-type: atomic + selectPolicy: + description: |- + selectPolicy is used to specify which policy should be used. + If not set, the default value Max is used. + type: string + stabilizationWindowSeconds: + description: |- + stabilizationWindowSeconds is the number of seconds for which past recommendations should be + considered while scaling... + format: int32 + type: integer + tolerance: + anyOf: + - type: integer + - type: string + description: |- + tolerance is the tolerance on the ratio between the current and desired + metric value under which no updates are made to... + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + scaleUp: + description: scaleUp is scaling policy for scaling + Up. + properties: + policies: + description: policies is a list of potential + scaling polices which can be used during + scaling. + items: + description: HPAScalingPolicy is a single + policy which must hold true for a specified + past interval. + properties: + periodSeconds: + description: periodSeconds specifies + the window of time for which the policy + should hold true. + format: int32 + type: integer + type: + description: type is used to specify + the scaling policy. + type: string + value: + description: |- + value contains the amount of change which is permitted by the policy. + It must be greater than zero + format: int32 + type: integer + required: + - periodSeconds + - type + - value + type: object + type: array + x-kubernetes-list-type: atomic + selectPolicy: + description: |- + selectPolicy is used to specify which policy should be used. + If not set, the default value Max is used. + type: string + stabilizationWindowSeconds: + description: |- + stabilizationWindowSeconds is the number of seconds for which past recommendations should be + considered while scaling... + format: int32 + type: integer + tolerance: + anyOf: + - type: integer + - type: string + description: |- + tolerance is the tolerance on the ratio between the current and desired + metric value under which no updates are made to... + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + maxReplicas: + description: MaxReplicas is the upper limit for the + number of replicas. Required. + format: int32 + minimum: 1 + type: integer + metrics: + description: Metrics contains the specifications for + which to use to calculate the desired replica count. + items: + description: |- + MetricSpec specifies how to scale based on a single metric + (only `type` and one other matching field should be set at... + properties: + containerResource: + description: |- + containerResource refers to a resource metric (such as those specified in + requests and limits) known to Kubernetes... + properties: + container: + description: container is the name of the + container in the pods of the scaling target + type: string + name: + description: name is the name of the resource + in question. + type: string + target: + description: target specifies the target + value for the given metric + properties: + averageUtilization: + description: |- + averageUtilization is the target value of the average of the + resource metric across all relevant pods, represented as a... + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether + the metric type is Utilization, Value, + or AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value + of the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - container + - name + - target + type: object + external: + description: |- + external refers to a global metric that is not associated + with any Kubernetes object. + properties: + metric: + description: metric identifies the target + metric by name and selector + properties: + name: + description: name is the name of the + given metric + type: string + selector: + description: |- + selector is the string-encoded form of a standard kubernetes label selector for the given metric + When set, it is passed... + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - name + type: object + target: + description: target specifies the target + value for the given metric + properties: + averageUtilization: + description: |- + averageUtilization is the target value of the average of the + resource metric across all relevant pods, represented as a... + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether + the metric type is Utilization, Value, + or AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value + of the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - metric + - target + type: object + object: + description: |- + object refers to a metric describing a single kubernetes object + (for example, hits-per-second on an Ingress object). + properties: + describedObject: + description: describedObject specifies the + descriptions of a object,such as kind,name + apiVersion + properties: + apiVersion: + description: apiVersion is the API version + of the referent + type: string + kind: + description: 'kind is the kind of the + referent; More info: https://git.k8s.' + type: string + name: + description: 'name is the name of the + referent; More info: https://kubernetes.' + type: string + required: + - kind + - name + type: object + metric: + description: metric identifies the target + metric by name and selector + properties: + name: + description: name is the name of the + given metric + type: string + selector: + description: |- + selector is the string-encoded form of a standard kubernetes label selector for the given metric + When set, it is passed... + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - name + type: object + target: + description: target specifies the target + value for the given metric + properties: + averageUtilization: + description: |- + averageUtilization is the target value of the average of the + resource metric across all relevant pods, represented as a... + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether + the metric type is Utilization, Value, + or AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value + of the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - describedObject + - metric + - target + type: object + pods: + description: |- + pods refers to a metric describing each pod in the current scale target + (for example,... + properties: + metric: + description: metric identifies the target + metric by name and selector + properties: + name: + description: name is the name of the + given metric + type: string + selector: + description: |- + selector is the string-encoded form of a standard kubernetes label selector for the given metric + When set, it is passed... + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - name + type: object + target: + description: target specifies the target + value for the given metric + properties: + averageUtilization: + description: |- + averageUtilization is the target value of the average of the + resource metric across all relevant pods, represented as a... + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether + the metric type is Utilization, Value, + or AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value + of the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - metric + - target + type: object + resource: + description: |- + resource refers to a resource metric (such as those specified in + requests and limits) known to Kubernetes describing... + properties: + name: + description: name is the name of the resource + in question. + type: string + target: + description: target specifies the target + value for the given metric + properties: + averageUtilization: + description: |- + averageUtilization is the target value of the average of the + resource metric across all relevant pods, represented as a... + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + description: |- + averageValue is the target value of the average of the + metric across all relevant pods (as a quantity) + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + description: type represents whether + the metric type is Utilization, Value, + or AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + description: value is the target value + of the metric (as a quantity). + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - type + type: object + required: + - name + - target + type: object + type: + description: type is the type of metric source. + type: string + required: + - type + type: object + type: array + minReplicas: + description: MinReplicas is the lower limit for the + number of replicas. Defaults to 1. + format: int32 + minimum: 1 + type: integer + required: + - maxReplicas + type: object type: object - x-kubernetes-validations: - - message: One selection required. - rule: '[has(self.local), has(self.remote)].exists_one(c, - c)' securityContext: description: PodSecurityContext holds pod-level security attributes and common container settings. @@ -6672,6 +9657,11 @@ spec: Defaults to user specified in image metadata if unspecified. format: int64 type: integer + seLinuxChangePolicy: + description: seLinuxChangePolicy defines how the container's + SELinux label is applied to all volumes used by the + Pod. + type: string seLinuxOptions: description: The SELinux context to be applied to all containers. @@ -6711,13 +9701,18 @@ spec: type: object supplementalGroups: description: |- - A list of groups applied to the first process run in each container, in addition - to the container's primary GID, the fsG + A list of groups applied to the first process run in each container, in + addition to the container's primary GID and... items: format: int64 type: integer type: array x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + description: |- + Defines how supplemental groups of the first container processes are calculated. + Valid values are "Merge" and "Strict". + type: string sysctls: description: Sysctls hold a list of namespaced sysctls used for the pod. @@ -6760,6 +9755,98 @@ spec: type: string type: object type: object + topologySpreadConstraints: + description: TopologySpreadConstraints defines how pods are + spread across topology domains. + items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. + properties: + labelSelector: + description: LabelSelector is used to find matching + pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: MaxSkew describes the degree to which pods + may be unevenly distributed. + format: int32 + type: integer + minDomains: + description: MinDomains indicates a minimum number of + eligible domains. + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread... + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. + type: string + topologyKey: + description: TopologyKey is the key of node labels. + type: string + whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array ui: description: Creates a UI server container properties: @@ -6775,8 +9862,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -6876,7 +9962,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -6895,8 +9981,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -6958,6 +10044,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen for + a request in the referenced claim. + type: string required: - name type: object @@ -7126,7 +10216,7 @@ spec: awsElasticBlockStore: description: |- awsElasticBlockStore represents an AWS Disk resource that is attached to a - kubelet's host machine and then exposed to th + kubelet's host machine and then exposed to... properties: fsType: description: fsType is the filesystem type of the @@ -7168,6 +10258,7 @@ spec: the blob storage type: string fsType: + default: ext4 description: |- fsType is Filesystem type to mount. Must be a filesystem type supported by the host operating system. @@ -7176,9 +10267,10 @@ spec: kind: description: 'kind expected values are Shared: multiple blob disks per storage account Dedicated: single - blob disk per storage accoun' + blob disk per storage...' type: string readOnly: + default: false description: |- readOnly Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. @@ -7209,7 +10301,7 @@ spec: type: object cephfs: description: cephFS represents a Ceph FS mount on the - host that shares a pod's lifetime + host that shares a pod's lifetime. properties: monitors: description: |- @@ -7258,7 +10350,7 @@ spec: cinder: description: |- cinder represents a cinder volume attached and mounted on kubelets host machine. - More info: https://examples.k8s. + Deprecated: Cinder is deprecated. properties: fsType: description: |- @@ -7304,7 +10396,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volum + ConfigMap will be projected into the... items: description: Maps a string key to a path within a volume. @@ -7344,7 +10436,7 @@ spec: csi: description: csi (Container Storage Interface) represents ephemeral storage that is handled by certain external - CSI drivers (Beta fea + CSI drivers. properties: driver: description: driver is the name of the CSI driver @@ -7357,7 +10449,7 @@ spec: nodePublishSecretRef: description: |- nodePublishSecretRef is a reference to the secret object containing - sensitive information to pass to the CSI driver to c + sensitive information to pass to the CSI driver to... properties: name: default: "" @@ -7421,7 +10513,7 @@ spec: mode: description: |- Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal valu + between 0000 and 0777 or a decimal... format: int32 type: integer path: @@ -7673,9 +10765,9 @@ spec: type: array x-kubernetes-list-type: atomic wwids: - description: "wwids Optional: FC volume world wide - identifiers (wwids)\nEither wwids or combination - of targetWWNs and lun must be set, " + description: |- + wwids Optional: FC volume world wide identifiers (wwids) + Either wwids or combination of targetWWNs and lun must be set,... items: type: string type: array @@ -7710,7 +10802,7 @@ spec: secretRef: description: |- secretRef is Optional: secretRef is reference to the secret object containing - sensitive information to pass to the plugi + sensitive information to pass to the... properties: name: default: "" @@ -7731,7 +10823,7 @@ spec: datasetName: description: |- datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker - should be considered as depreca + should be considered as... type: string datasetUUID: description: datasetUUID is the UUID of the dataset. @@ -7741,7 +10833,7 @@ spec: gcePersistentDisk: description: |- gcePersistentDisk represents a GCE Disk resource that is attached to a - kubelet's host machine and then exposed to the po + kubelet's host machine and then exposed to the... properties: fsType: description: fsType is filesystem type of the volume @@ -7770,7 +10862,7 @@ spec: gitRepo: description: |- gitRepo represents a git repository at a particular revision. - DEPRECATED: GitRepo is deprecated. + Deprecated: GitRepo is deprecated. properties: directory: description: |- @@ -7788,9 +10880,8 @@ spec: - repository type: object glusterfs: - description: |- - glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. - More info: https://examples.k8s. + description: glusterfs represents a Glusterfs mount + on the host that shares a pod's lifetime. properties: endpoints: description: |- @@ -7830,6 +10921,22 @@ spec: required: - path type: object + image: + description: image represents an OCI object (a container + image or artifact) pulled and mounted on the kubelet's + host machine. + properties: + pullPolicy: + description: |- + Policy for pulling OCI objects. Possible values are: + Always: the kubelet always attempts to pull the reference. + type: string + reference: + description: |- + Required: Image or artifact reference to be used. + Behaves in the same way as pod.spec.containers[*].image. + type: string + type: object iscsi: description: |- iscsi represents an ISCSI Disk resource that is attached to a @@ -7855,6 +10962,7 @@ spec: description: iqn is the target iSCSI Qualified Name. type: string iscsiInterface: + default: default description: |- iscsiInterface is the interface Name that uses an iSCSI transport. Defaults to 'default' (tcp). @@ -7946,7 +11054,7 @@ spec: photonPersistentDisk: description: photonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host - machine + machine. properties: fsType: description: |- @@ -7963,7 +11071,7 @@ spec: type: object portworxVolume: description: portworxVolume represents a portworx volume - attached and mounted on kubelets host machine + attached and mounted on kubelets host machine. properties: fsType: description: |- @@ -7993,10 +11101,13 @@ spec: format: int32 type: integer sources: - description: sources is the list of volume projections + description: |- + sources is the list of volume projections. Each entry in this list + handles one source. items: - description: Projection that may be projected - along with other supported volume types + description: |- + Projection that may be projected along with other supported volume types. + Exactly one of these fields must be set. properties: clusterTrustBundle: description: ClusterTrustBundle allows a pod @@ -8077,7 +11188,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volum + ConfigMap will be projected into the... items: description: Maps a string key to a path within a volume. @@ -8150,7 +11261,7 @@ spec: mode: description: |- Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal valu + between 0000 and 0777 or a decimal... format: int32 type: integer path: @@ -8199,7 +11310,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume a + Secret will be projected into the volume... items: description: Maps a string key to a path within a volume. @@ -8265,7 +11376,7 @@ spec: type: object quobyte: description: quobyte represents a Quobyte mount on the - host that shares a pod's lifetime + host that shares a pod's lifetime. properties: group: description: |- @@ -8280,12 +11391,12 @@ spec: registry: description: |- registry represents a single or multiple Quobyte Registry services - specified as a string as host:port pair (multiple ent + specified as a string as host:port pair (multiple... type: string tenant: description: |- tenant owning the given Quobyte volume in the Backend - Used with dynamically provisioned Quobyte volumes, value is set by + Used with dynamically provisioned Quobyte volumes, value is set... type: string user: description: |- @@ -8301,9 +11412,8 @@ spec: - volume type: object rbd: - description: |- - rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. - More info: https://examples.k8s. + description: rbd represents a Rados Block Device mount + on the host that shares a pod's lifetime. properties: fsType: description: fsType is the filesystem type of the @@ -8315,6 +11425,7 @@ spec: More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it type: string keyring: + default: /etc/ceph/keyring description: |- keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. @@ -8329,6 +11440,7 @@ spec: type: array x-kubernetes-list-type: atomic pool: + default: rbd description: |- pool is the rados pool name. Default is rbd. @@ -8356,6 +11468,7 @@ spec: type: object x-kubernetes-map-type: atomic user: + default: admin description: |- user is the rados user name. Default is admin. @@ -8370,6 +11483,7 @@ spec: volume attached and mounted on Kubernetes nodes. properties: fsType: + default: xfs description: |- fsType is the filesystem type to mount. Must be a filesystem type supported by the host operating system. @@ -8407,6 +11521,7 @@ spec: communication with Gateway, default false type: boolean storageMode: + default: ThinProvisioned description: storageMode indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. type: string @@ -8441,7 +11556,7 @@ spec: items: description: |- items If unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume a + Secret will be projected into the volume... items: description: Maps a string key to a path within a volume. @@ -8516,7 +11631,7 @@ spec: type: object vsphereVolume: description: vsphereVolume represents a vSphere volume - attached and mounted on kubelets host machine + attached and mounted on kubelets host machine. properties: fsType: description: |- @@ -8548,6 +11663,37 @@ spec: required: - feastProject type: object + x-kubernetes-validations: + - message: replicas > 1 and services.scaling.autoscaling are mutually + exclusive. + rule: self.replicas <= 1 || !has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling) + - message: Scaling requires DB-backed persistence for the online store. + Configure services.onlineStore.persistence.store when using replicas + > 1 or autoscaling. + rule: self.replicas <= 1 && (!has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling)) || (has(self.services) + && has(self.services.onlineStore) && has(self.services.onlineStore.persistence) + && has(self.services.onlineStore.persistence.store)) + - message: Scaling requires DB-backed persistence for the offline + store. Configure services.offlineStore.persistence.store when + using replicas > 1 or autoscaling. + rule: self.replicas <= 1 && (!has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling)) || (!has(self.services) + || !has(self.services.offlineStore) || (has(self.services.offlineStore.persistence) + && has(self.services.offlineStore.persistence.store))) + - message: Scaling requires DB-backed or remote registry. Configure + registry.local.persistence.store or use a remote registry when + using replicas > 1 or autoscaling. S3/GCS-backed registry is also + allowed. + rule: self.replicas <= 1 && (!has(self.services) || !has(self.services.scaling) + || !has(self.services.scaling.autoscaling)) || (has(self.services) + && has(self.services.registry) && (has(self.services.registry.remote) + || (has(self.services.registry.local) && has(self.services.registry.local.persistence) + && (has(self.services.registry.local.persistence.store) || (has(self.services.registry.local.persistence.file) + && has(self.services.registry.local.persistence.file.path) && + (self.services.registry.local.persistence.file.path.startsWith('s3://') + || self.services.registry.local.persistence.file.path.startsWith('gs://'))))))) clientConfigMap: description: ConfigMap in this namespace containing a client `feature_store.yaml` for this feast deployment @@ -8590,10 +11736,7 @@ spec: - Unknown type: string type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition. + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -8612,6 +11755,28 @@ spec: type: string phase: type: string + replicas: + description: Replicas is the current number of ready pod replicas + (used by the scale sub-resource). + format: int32 + type: integer + scalingStatus: + description: ScalingStatus reports the current scaling state of the + FeatureStore deployment. + properties: + currentReplicas: + description: CurrentReplicas is the current number of pod replicas. + format: int32 + type: integer + desiredReplicas: + description: DesiredReplicas is the desired number of pod replicas. + format: int32 + type: integer + type: object + selector: + description: Selector is the label selector for pods managed by the + FeatureStore deployment (used by the scale sub-resource). + type: string serviceHostnames: description: ServiceHostnames defines the service hostnames in the format of :, e.g. example.svc.cluster.local:80 @@ -8632,6 +11797,10 @@ spec: served: true storage: true subresources: + scale: + labelSelectorPath: .status.selector + specReplicasPath: .spec.replicas + statusReplicasPath: .status.replicas status: {} - additionalPrinterColumns: - jsonPath: .status.phase @@ -8738,8 +11907,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's value. @@ -8838,7 +12006,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of a set - of ConfigMaps + of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -8857,8 +12025,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -8904,6 +12072,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen for a request + in the referenced claim. + type: string required: - name type: object @@ -8945,7 +12117,7 @@ spec: activeDeadlineSeconds: description: |- Specifies the duration in seconds relative to the startTime that the job - may be continuously active before the system tr + may be continuously active before the system... format: int64 type: integer backoffLimit: @@ -9128,8 +12300,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's value. @@ -9228,7 +12399,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of a set - of ConfigMaps + of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -9247,8 +12418,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -9302,7 +12473,6 @@ spec: - hbase - cassandra - hazelcast - - ikv - couchbase - clickhouse type: string @@ -9503,8 +12673,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -9604,7 +12773,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -9623,8 +12792,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -9686,6 +12855,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen for + a request in the referenced claim. + type: string required: - name type: object @@ -9974,7 +13147,6 @@ spec: enum: - snowflake.online - redis - - ikv - datastore - dynamodb - bigtable @@ -9989,6 +13161,7 @@ spec: - couchbase.online - milvus - hybrid + - mongodb type: string required: - secretRef @@ -10013,8 +13186,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -10114,7 +13286,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -10133,8 +13305,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -10196,6 +13368,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen for + a request in the referenced claim. + type: string required: - name type: object @@ -10541,8 +13717,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -10645,7 +13820,7 @@ spec: envFrom: items: description: EnvFromSource represents the source - of a set of ConfigMaps + of a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -10664,8 +13839,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the + name of each environment variable. Must be + a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -10731,6 +13907,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen + for a request in the referenced claim. + type: string required: - name type: object @@ -10952,6 +14132,10 @@ spec: x-kubernetes-validations: - message: One selection required. rule: '[has(self.local), has(self.remote)].exists_one(c, c)' + runFeastApplyOnInit: + description: Runs feast apply on pod start to populate the registry. + Defaults to true. Ignored when DisableInitContainers is true. + type: boolean securityContext: description: PodSecurityContext holds pod-level security attributes and common container settings. @@ -10997,6 +14181,10 @@ spec: Defaults to user specified in image metadata if unspecified. format: int64 type: integer + seLinuxChangePolicy: + description: seLinuxChangePolicy defines how the container's + SELinux label is applied to all volumes used by the Pod. + type: string seLinuxOptions: description: The SELinux context to be applied to all containers. properties: @@ -11035,13 +14223,18 @@ spec: type: object supplementalGroups: description: |- - A list of groups applied to the first process run in each container, in addition - to the container's primary GID, the fsG + A list of groups applied to the first process run in each container, in + addition to the container's primary GID and... items: format: int64 type: integer type: array x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + description: |- + Defines how supplemental groups of the first container processes are calculated. + Valid values are "Merge" and "Strict". + type: string sysctls: description: Sysctls hold a list of namespaced sysctls used for the pod. @@ -11098,8 +14291,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's value. @@ -11198,7 +14390,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of a set - of ConfigMaps + of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -11217,8 +14409,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -11279,6 +14471,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen for a request + in the referenced claim. + type: string required: - name type: object @@ -11447,7 +14643,7 @@ spec: awsElasticBlockStore: description: |- awsElasticBlockStore represents an AWS Disk resource that is attached to a - kubelet's host machine and then exposed to th + kubelet's host machine and then exposed to... properties: fsType: description: fsType is the filesystem type of the volume @@ -11489,6 +14685,7 @@ spec: blob storage type: string fsType: + default: ext4 description: |- fsType is Filesystem type to mount. Must be a filesystem type supported by the host operating system. @@ -11497,9 +14694,10 @@ spec: kind: description: 'kind expected values are Shared: multiple blob disks per storage account Dedicated: single - blob disk per storage accoun' + blob disk per storage...' type: string readOnly: + default: false description: |- readOnly Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. @@ -11530,7 +14728,7 @@ spec: type: object cephfs: description: cephFS represents a Ceph FS mount on the host - that shares a pod's lifetime + that shares a pod's lifetime. properties: monitors: description: |- @@ -11578,7 +14776,7 @@ spec: cinder: description: |- cinder represents a cinder volume attached and mounted on kubelets host machine. - More info: https://examples.k8s. + Deprecated: Cinder is deprecated. properties: fsType: description: |- @@ -11624,7 +14822,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volum + ConfigMap will be projected into the... items: description: Maps a string key to a path within a volume. @@ -11664,7 +14862,7 @@ spec: csi: description: csi (Container Storage Interface) represents ephemeral storage that is handled by certain external - CSI drivers (Beta fea + CSI drivers. properties: driver: description: driver is the name of the CSI driver that @@ -11676,7 +14874,7 @@ spec: nodePublishSecretRef: description: |- nodePublishSecretRef is a reference to the secret object containing - sensitive information to pass to the CSI driver to c + sensitive information to pass to the CSI driver to... properties: name: default: "" @@ -11738,7 +14936,7 @@ spec: mode: description: |- Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal valu + between 0000 and 0777 or a decimal... format: int32 type: integer path: @@ -11987,9 +15185,9 @@ spec: type: array x-kubernetes-list-type: atomic wwids: - description: "wwids Optional: FC volume world wide identifiers - (wwids)\nEither wwids or combination of targetWWNs - and lun must be set, " + description: |- + wwids Optional: FC volume world wide identifiers (wwids) + Either wwids or combination of targetWWNs and lun must be set,... items: type: string type: array @@ -12024,7 +15222,7 @@ spec: secretRef: description: |- secretRef is Optional: secretRef is reference to the secret object containing - sensitive information to pass to the plugi + sensitive information to pass to the... properties: name: default: "" @@ -12045,7 +15243,7 @@ spec: datasetName: description: |- datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker - should be considered as depreca + should be considered as... type: string datasetUUID: description: datasetUUID is the UUID of the dataset. @@ -12055,7 +15253,7 @@ spec: gcePersistentDisk: description: |- gcePersistentDisk represents a GCE Disk resource that is attached to a - kubelet's host machine and then exposed to the po + kubelet's host machine and then exposed to the... properties: fsType: description: fsType is filesystem type of the volume @@ -12084,7 +15282,7 @@ spec: gitRepo: description: |- gitRepo represents a git repository at a particular revision. - DEPRECATED: GitRepo is deprecated. + Deprecated: GitRepo is deprecated. properties: directory: description: |- @@ -12102,9 +15300,8 @@ spec: - repository type: object glusterfs: - description: |- - glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. - More info: https://examples.k8s. + description: glusterfs represents a Glusterfs mount on the + host that shares a pod's lifetime. properties: endpoints: description: |- @@ -12144,6 +15341,22 @@ spec: required: - path type: object + image: + description: image represents an OCI object (a container + image or artifact) pulled and mounted on the kubelet's + host machine. + properties: + pullPolicy: + description: |- + Policy for pulling OCI objects. Possible values are: + Always: the kubelet always attempts to pull the reference. + type: string + reference: + description: |- + Required: Image or artifact reference to be used. + Behaves in the same way as pod.spec.containers[*].image. + type: string + type: object iscsi: description: |- iscsi represents an ISCSI Disk resource that is attached to a @@ -12169,6 +15382,7 @@ spec: description: iqn is the target iSCSI Qualified Name. type: string iscsiInterface: + default: default description: |- iscsiInterface is the interface Name that uses an iSCSI transport. Defaults to 'default' (tcp). @@ -12259,7 +15473,7 @@ spec: photonPersistentDisk: description: photonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host - machine + machine. properties: fsType: description: |- @@ -12276,7 +15490,7 @@ spec: type: object portworxVolume: description: portworxVolume represents a portworx volume - attached and mounted on kubelets host machine + attached and mounted on kubelets host machine. properties: fsType: description: |- @@ -12306,10 +15520,13 @@ spec: format: int32 type: integer sources: - description: sources is the list of volume projections + description: |- + sources is the list of volume projections. Each entry in this list + handles one source. items: - description: Projection that may be projected along - with other supported volume types + description: |- + Projection that may be projected along with other supported volume types. + Exactly one of these fields must be set. properties: clusterTrustBundle: description: ClusterTrustBundle allows a pod to @@ -12389,7 +15606,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volum + ConfigMap will be projected into the... items: description: Maps a string key to a path within a volume. @@ -12460,7 +15677,7 @@ spec: mode: description: |- Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal valu + between 0000 and 0777 or a decimal... format: int32 type: integer path: @@ -12509,7 +15726,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume a + Secret will be projected into the volume... items: description: Maps a string key to a path within a volume. @@ -12575,7 +15792,7 @@ spec: type: object quobyte: description: quobyte represents a Quobyte mount on the host - that shares a pod's lifetime + that shares a pod's lifetime. properties: group: description: |- @@ -12590,12 +15807,12 @@ spec: registry: description: |- registry represents a single or multiple Quobyte Registry services - specified as a string as host:port pair (multiple ent + specified as a string as host:port pair (multiple... type: string tenant: description: |- tenant owning the given Quobyte volume in the Backend - Used with dynamically provisioned Quobyte volumes, value is set by + Used with dynamically provisioned Quobyte volumes, value is set... type: string user: description: |- @@ -12611,9 +15828,8 @@ spec: - volume type: object rbd: - description: |- - rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. - More info: https://examples.k8s. + description: rbd represents a Rados Block Device mount on + the host that shares a pod's lifetime. properties: fsType: description: fsType is the filesystem type of the volume @@ -12625,6 +15841,7 @@ spec: More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it type: string keyring: + default: /etc/ceph/keyring description: |- keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. @@ -12639,6 +15856,7 @@ spec: type: array x-kubernetes-list-type: atomic pool: + default: rbd description: |- pool is the rados pool name. Default is rbd. @@ -12666,6 +15884,7 @@ spec: type: object x-kubernetes-map-type: atomic user: + default: admin description: |- user is the rados user name. Default is admin. @@ -12680,6 +15899,7 @@ spec: attached and mounted on Kubernetes nodes. properties: fsType: + default: xfs description: |- fsType is the filesystem type to mount. Must be a filesystem type supported by the host operating system. @@ -12717,6 +15937,7 @@ spec: with Gateway, default false type: boolean storageMode: + default: ThinProvisioned description: storageMode indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. type: string @@ -12751,7 +15972,7 @@ spec: items: description: |- items If unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume a + Secret will be projected into the volume... items: description: Maps a string key to a path within a volume. @@ -12826,7 +16047,7 @@ spec: type: object vsphereVolume: description: vsphereVolume represents a vSphere volume attached - and mounted on kubelets host machine + and mounted on kubelets host machine. properties: fsType: description: |- @@ -12942,8 +16163,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -13043,7 +16263,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -13062,8 +16282,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -13110,6 +16330,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen for + a request in the referenced claim. + type: string required: - name type: object @@ -13151,7 +16375,7 @@ spec: activeDeadlineSeconds: description: |- Specifies the duration in seconds relative to the startTime that the job - may be continuously active before the system tr + may be continuously active before the system... format: int64 type: integer backoffLimit: @@ -13337,8 +16561,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -13438,7 +16661,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -13457,8 +16680,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -13513,7 +16736,6 @@ spec: - hbase - cassandra - hazelcast - - ikv - couchbase - clickhouse type: string @@ -13717,8 +16939,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -13821,7 +17042,7 @@ spec: envFrom: items: description: EnvFromSource represents the source - of a set of ConfigMaps + of a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -13840,8 +17061,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the + name of each environment variable. Must be + a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -13903,6 +17125,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen + for a request in the referenced claim. + type: string required: - name type: object @@ -14195,7 +17421,6 @@ spec: enum: - snowflake.online - redis - - ikv - datastore - dynamodb - bigtable @@ -14210,6 +17435,7 @@ spec: - couchbase.online - milvus - hybrid + - mongodb type: string required: - secretRef @@ -14235,8 +17461,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -14339,7 +17564,7 @@ spec: envFrom: items: description: EnvFromSource represents the source - of a set of ConfigMaps + of a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -14358,8 +17583,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the + name of each environment variable. Must be + a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -14421,6 +17647,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen + for a request in the referenced claim. + type: string required: - name type: object @@ -14775,8 +18005,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment @@ -14881,7 +18110,7 @@ spec: envFrom: items: description: EnvFromSource represents the source - of a set of ConfigMaps + of a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -14900,9 +18129,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be - a C_IDENTIFIER. + description: Optional text to prepend to + the name of each environment variable. + Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -14968,6 +18197,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen + for a request in the referenced claim. + type: string required: - name type: object @@ -15196,6 +18429,11 @@ spec: - message: One selection required. rule: '[has(self.local), has(self.remote)].exists_one(c, c)' + runFeastApplyOnInit: + description: Runs feast apply on pod start to populate the + registry. Defaults to true. Ignored when DisableInitContainers + is true. + type: boolean securityContext: description: PodSecurityContext holds pod-level security attributes and common container settings. @@ -15241,6 +18479,11 @@ spec: Defaults to user specified in image metadata if unspecified. format: int64 type: integer + seLinuxChangePolicy: + description: seLinuxChangePolicy defines how the container's + SELinux label is applied to all volumes used by the + Pod. + type: string seLinuxOptions: description: The SELinux context to be applied to all containers. @@ -15280,13 +18523,18 @@ spec: type: object supplementalGroups: description: |- - A list of groups applied to the first process run in each container, in addition - to the container's primary GID, the fsG + A list of groups applied to the first process run in each container, in + addition to the container's primary GID and... items: format: int64 type: integer type: array x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + description: |- + Defines how supplemental groups of the first container processes are calculated. + Valid values are "Merge" and "Strict". + type: string sysctls: description: Sysctls hold a list of namespaced sysctls used for the pod. @@ -15344,8 +18592,7 @@ spec: value: description: |- Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any + using the previously defined environment variables in the container and... type: string valueFrom: description: Source for the environment variable's @@ -15445,7 +18692,7 @@ spec: envFrom: items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -15464,8 +18711,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -15527,6 +18774,10 @@ spec: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. type: string + request: + description: Request is the name chosen for + a request in the referenced claim. + type: string required: - name type: object @@ -15695,7 +18946,7 @@ spec: awsElasticBlockStore: description: |- awsElasticBlockStore represents an AWS Disk resource that is attached to a - kubelet's host machine and then exposed to th + kubelet's host machine and then exposed to... properties: fsType: description: fsType is the filesystem type of the @@ -15737,6 +18988,7 @@ spec: the blob storage type: string fsType: + default: ext4 description: |- fsType is Filesystem type to mount. Must be a filesystem type supported by the host operating system. @@ -15745,9 +18997,10 @@ spec: kind: description: 'kind expected values are Shared: multiple blob disks per storage account Dedicated: single - blob disk per storage accoun' + blob disk per storage...' type: string readOnly: + default: false description: |- readOnly Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. @@ -15778,7 +19031,7 @@ spec: type: object cephfs: description: cephFS represents a Ceph FS mount on the - host that shares a pod's lifetime + host that shares a pod's lifetime. properties: monitors: description: |- @@ -15827,7 +19080,7 @@ spec: cinder: description: |- cinder represents a cinder volume attached and mounted on kubelets host machine. - More info: https://examples.k8s. + Deprecated: Cinder is deprecated. properties: fsType: description: |- @@ -15873,7 +19126,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volum + ConfigMap will be projected into the... items: description: Maps a string key to a path within a volume. @@ -15913,7 +19166,7 @@ spec: csi: description: csi (Container Storage Interface) represents ephemeral storage that is handled by certain external - CSI drivers (Beta fea + CSI drivers. properties: driver: description: driver is the name of the CSI driver @@ -15926,7 +19179,7 @@ spec: nodePublishSecretRef: description: |- nodePublishSecretRef is a reference to the secret object containing - sensitive information to pass to the CSI driver to c + sensitive information to pass to the CSI driver to... properties: name: default: "" @@ -15990,7 +19243,7 @@ spec: mode: description: |- Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal valu + between 0000 and 0777 or a decimal... format: int32 type: integer path: @@ -16242,9 +19495,9 @@ spec: type: array x-kubernetes-list-type: atomic wwids: - description: "wwids Optional: FC volume world wide - identifiers (wwids)\nEither wwids or combination - of targetWWNs and lun must be set, " + description: |- + wwids Optional: FC volume world wide identifiers (wwids) + Either wwids or combination of targetWWNs and lun must be set,... items: type: string type: array @@ -16279,7 +19532,7 @@ spec: secretRef: description: |- secretRef is Optional: secretRef is reference to the secret object containing - sensitive information to pass to the plugi + sensitive information to pass to the... properties: name: default: "" @@ -16300,7 +19553,7 @@ spec: datasetName: description: |- datasetName is Name of the dataset stored as metadata -> name on the dataset for Flocker - should be considered as depreca + should be considered as... type: string datasetUUID: description: datasetUUID is the UUID of the dataset. @@ -16310,7 +19563,7 @@ spec: gcePersistentDisk: description: |- gcePersistentDisk represents a GCE Disk resource that is attached to a - kubelet's host machine and then exposed to the po + kubelet's host machine and then exposed to the... properties: fsType: description: fsType is filesystem type of the volume @@ -16339,7 +19592,7 @@ spec: gitRepo: description: |- gitRepo represents a git repository at a particular revision. - DEPRECATED: GitRepo is deprecated. + Deprecated: GitRepo is deprecated. properties: directory: description: |- @@ -16357,9 +19610,8 @@ spec: - repository type: object glusterfs: - description: |- - glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. - More info: https://examples.k8s. + description: glusterfs represents a Glusterfs mount + on the host that shares a pod's lifetime. properties: endpoints: description: |- @@ -16399,6 +19651,22 @@ spec: required: - path type: object + image: + description: image represents an OCI object (a container + image or artifact) pulled and mounted on the kubelet's + host machine. + properties: + pullPolicy: + description: |- + Policy for pulling OCI objects. Possible values are: + Always: the kubelet always attempts to pull the reference. + type: string + reference: + description: |- + Required: Image or artifact reference to be used. + Behaves in the same way as pod.spec.containers[*].image. + type: string + type: object iscsi: description: |- iscsi represents an ISCSI Disk resource that is attached to a @@ -16424,6 +19692,7 @@ spec: description: iqn is the target iSCSI Qualified Name. type: string iscsiInterface: + default: default description: |- iscsiInterface is the interface Name that uses an iSCSI transport. Defaults to 'default' (tcp). @@ -16515,7 +19784,7 @@ spec: photonPersistentDisk: description: photonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host - machine + machine. properties: fsType: description: |- @@ -16532,7 +19801,7 @@ spec: type: object portworxVolume: description: portworxVolume represents a portworx volume - attached and mounted on kubelets host machine + attached and mounted on kubelets host machine. properties: fsType: description: |- @@ -16562,10 +19831,13 @@ spec: format: int32 type: integer sources: - description: sources is the list of volume projections + description: |- + sources is the list of volume projections. Each entry in this list + handles one source. items: - description: Projection that may be projected - along with other supported volume types + description: |- + Projection that may be projected along with other supported volume types. + Exactly one of these fields must be set. properties: clusterTrustBundle: description: ClusterTrustBundle allows a pod @@ -16646,7 +19918,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volum + ConfigMap will be projected into the... items: description: Maps a string key to a path within a volume. @@ -16719,7 +19991,7 @@ spec: mode: description: |- Optional: mode bits used to set permissions on this file, must be an octal value - between 0000 and 0777 or a decimal valu + between 0000 and 0777 or a decimal... format: int32 type: integer path: @@ -16768,7 +20040,7 @@ spec: items: description: |- items if unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume a + Secret will be projected into the volume... items: description: Maps a string key to a path within a volume. @@ -16834,7 +20106,7 @@ spec: type: object quobyte: description: quobyte represents a Quobyte mount on the - host that shares a pod's lifetime + host that shares a pod's lifetime. properties: group: description: |- @@ -16849,12 +20121,12 @@ spec: registry: description: |- registry represents a single or multiple Quobyte Registry services - specified as a string as host:port pair (multiple ent + specified as a string as host:port pair (multiple... type: string tenant: description: |- tenant owning the given Quobyte volume in the Backend - Used with dynamically provisioned Quobyte volumes, value is set by + Used with dynamically provisioned Quobyte volumes, value is set... type: string user: description: |- @@ -16870,9 +20142,8 @@ spec: - volume type: object rbd: - description: |- - rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. - More info: https://examples.k8s. + description: rbd represents a Rados Block Device mount + on the host that shares a pod's lifetime. properties: fsType: description: fsType is the filesystem type of the @@ -16884,6 +20155,7 @@ spec: More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it type: string keyring: + default: /etc/ceph/keyring description: |- keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. @@ -16898,6 +20170,7 @@ spec: type: array x-kubernetes-list-type: atomic pool: + default: rbd description: |- pool is the rados pool name. Default is rbd. @@ -16925,6 +20198,7 @@ spec: type: object x-kubernetes-map-type: atomic user: + default: admin description: |- user is the rados user name. Default is admin. @@ -16939,6 +20213,7 @@ spec: volume attached and mounted on Kubernetes nodes. properties: fsType: + default: xfs description: |- fsType is the filesystem type to mount. Must be a filesystem type supported by the host operating system. @@ -16976,6 +20251,7 @@ spec: communication with Gateway, default false type: boolean storageMode: + default: ThinProvisioned description: storageMode indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. type: string @@ -17010,7 +20286,7 @@ spec: items: description: |- items If unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume a + Secret will be projected into the volume... items: description: Maps a string key to a path within a volume. @@ -17085,7 +20361,7 @@ spec: type: object vsphereVolume: description: vsphereVolume represents a vSphere volume - attached and mounted on kubelets host machine + attached and mounted on kubelets host machine. properties: fsType: description: |- @@ -17159,10 +20435,7 @@ spec: - Unknown type: string type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition. + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string @@ -17259,6 +20532,8 @@ metadata: labels: app.kubernetes.io/managed-by: kustomize app.kubernetes.io/name: feast-operator + rbac.authorization.k8s.io/aggregate-to-admin: "true" + rbac.authorization.k8s.io/aggregate-to-edit: "true" name: feast-operator-featurestore-editor-role rules: - apiGroups: @@ -17286,6 +20561,7 @@ metadata: labels: app.kubernetes.io/managed-by: kustomize app.kubernetes.io/name: feast-operator + rbac.authorization.k8s.io/aggregate-to-view: "true" name: feast-operator-featurestore-viewer-role rules: - apiGroups: @@ -17309,9 +20585,12 @@ metadata: name: feast-operator-manager-role rules: - apiGroups: - - apps + - "" resources: - - deployments + - configmaps + - persistentvolumeclaims + - serviceaccounts + - services verbs: - create - delete @@ -17320,53 +20599,62 @@ rules: - update - watch - apiGroups: - - authentication.k8s.io + - "" resources: - - tokenreviews + - namespaces + - pods + - secrets + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - pods/exec verbs: - create - apiGroups: - - batch + - apps resources: - - cronjobs + - deployments verbs: - create - delete - get - list - - patch - update - watch - apiGroups: - - "" + - authentication.k8s.io resources: - - configmaps - - persistentvolumeclaims - - serviceaccounts - - services + - tokenreviews + verbs: + - create +- apiGroups: + - autoscaling + resources: + - horizontalpodautoscalers verbs: - create - delete - get - list + - patch - update - watch - apiGroups: - - "" + - batch resources: - - namespaces - - pods - - secrets + - cronjobs verbs: + - create + - delete - get - list + - patch + - update - watch -- apiGroups: - - "" - resources: - - pods/exec - verbs: - - create - apiGroups: - feast.dev resources: @@ -17393,6 +20681,29 @@ rules: - get - patch - update +- apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + verbs: + - create + - delete + - get + - list + - patch + - watch +- apiGroups: + - policy + resources: + - poddisruptionbudgets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - rbac.authorization.k8s.io resources: @@ -17519,6 +20830,7 @@ spec: protocol: TCP targetPort: 8443 selector: + app.kubernetes.io/name: feast-operator control-plane: controller-manager --- apiVersion: apps/v1 @@ -17534,12 +20846,14 @@ spec: replicas: 1 selector: matchLabels: + app.kubernetes.io/name: feast-operator control-plane: controller-manager template: metadata: annotations: kubectl.kubernetes.io/default-container: manager labels: + app.kubernetes.io/name: feast-operator control-plane: controller-manager spec: containers: @@ -17551,10 +20865,12 @@ spec: - /manager env: - name: RELATED_IMAGE_FEATURE_SERVER - value: quay.io/feastdev/feature-server:0.60.0 + value: quay.io/feastdev/feature-server:0.62.0 - name: RELATED_IMAGE_CRON_JOB value: quay.io/openshift/origin-cli:4.17 - image: quay.io/feastdev/feast-operator:0.60.0 + - name: OIDC_ISSUER_URL + value: "" + image: quay.io/feastdev/feast-operator:0.62.0 livenessProbe: httpGet: path: /healthz diff --git a/infra/feast-operator/dist/operator-e2e-tests b/infra/feast-operator/dist/operator-e2e-tests index c9b11c0c3ea..bb4e4c5d319 100755 Binary files a/infra/feast-operator/dist/operator-e2e-tests and b/infra/feast-operator/dist/operator-e2e-tests differ diff --git a/infra/feast-operator/docs/api/markdown/ref.md b/infra/feast-operator/docs/api/markdown/ref.md index ce64e4dd3ec..287072273a3 100644 --- a/infra/feast-operator/docs/api/markdown/ref.md +++ b/infra/feast-operator/docs/api/markdown/ref.md @@ -28,6 +28,24 @@ _Appears in:_ | `oidc` _[OidcAuthz](#oidcauthz)_ | | +#### AutoscalingConfig + + + +AutoscalingConfig defines HPA settings for the FeatureStore deployment. + +_Appears in:_ +- [ScalingConfig](#scalingconfig) + +| Field | Description | +| --- | --- | +| `minReplicas` _integer_ | MinReplicas is the lower limit for the number of replicas. Defaults to 1. | +| `maxReplicas` _integer_ | MaxReplicas is the upper limit for the number of replicas. Required. | +| `metrics` _[MetricSpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#metricspec-v2-autoscaling) array_ | Metrics contains the specifications for which to use to calculate the desired replica count. +If not set, defaults to 80% CPU utilization. | +| `behavior` _[HorizontalPodAutoscalerBehavior](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#horizontalpodautoscalerbehavior-v2-autoscaling)_ | Behavior configures the scaling behavior of the target. | + + #### BatchEngineConfig @@ -132,7 +150,6 @@ time for any reason. Missed jobs executions will be counted as failed ones. | | `concurrencyPolicy` _[ConcurrencyPolicy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#concurrencypolicy-v1-batch)_ | Specifies how to treat concurrent executions of a Job. Valid values are: - - "Allow" (default): allows CronJobs to run concurrently; - "Forbid": forbids concurrent runs, skipping next run if previous run hasn't finished yet; - "Replace": cancels currently running job and replaces it with a new one | @@ -221,8 +238,23 @@ _Appears in:_ | `ui` _[ServerConfigs](#serverconfigs)_ | Creates a UI server container | | `deploymentStrategy` _[DeploymentStrategy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#deploymentstrategy-v1-apps)_ | | | `securityContext` _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#podsecuritycontext-v1-core)_ | | +| `podAnnotations` _object (keys:string, values:string)_ | PodAnnotations are annotations to be applied to the Deployment's PodTemplate metadata. +This enables annotation-driven integrations like OpenTelemetry auto-instrumentation, +Istio sidecar injection, Vault agent injection, etc. | | `disableInitContainers` _boolean_ | Disable the 'feast repo initialization' initContainer | +| `runFeastApplyOnInit` _boolean_ | Runs feast apply on pod start to populate the registry. Defaults to true. Ignored when DisableInitContainers is true. | | `volumes` _[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#volume-v1-core) array_ | Volumes specifies the volumes to mount in the FeatureStore deployment. A corresponding `VolumeMount` should be added to whichever feast service(s) require access to said volume(s). | +| `scaling` _[ScalingConfig](#scalingconfig)_ | Scaling configures horizontal scaling for the FeatureStore deployment (e.g. HPA autoscaling). +For static replicas, use spec.replicas instead. | +| `podDisruptionBudgets` _[PDBConfig](#pdbconfig)_ | PodDisruptionBudgets configures a PodDisruptionBudget for the FeatureStore deployment. +Only created when scaling is enabled (replicas > 1 or autoscaling). | +| `topologySpreadConstraints` _[TopologySpreadConstraint](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#topologyspreadconstraint-v1-core) array_ | TopologySpreadConstraints defines how pods are spread across topology domains. +When scaling is enabled and this is not set, the operator auto-injects a soft +zone-spread constraint (whenUnsatisfiable: ScheduleAnyway). +Set to an empty array to disable auto-injection. | +| `affinity` _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#affinity-v1-core)_ | Affinity defines the pod scheduling constraints for the FeatureStore deployment. +When scaling is enabled and this is not set, the operator auto-injects a soft +pod anti-affinity rule to prefer spreading pods across nodes. | #### FeatureStoreSpec @@ -243,6 +275,8 @@ _Appears in:_ | `authz` _[AuthzConfig](#authzconfig)_ | | | `cronJob` _[FeastCronJob](#feastcronjob)_ | | | `batchEngine` _[BatchEngineConfig](#batchengineconfig)_ | | +| `replicas` _integer_ | Replicas is the desired number of pod replicas. Used by the scale sub-resource. +Mutually exclusive with services.scaling.autoscaling. | #### FeatureStoreStatus @@ -263,6 +297,9 @@ _Appears in:_ | `feastVersion` _string_ | | | `phase` _string_ | | | `serviceHostnames` _[ServiceHostnames](#servicehostnames)_ | | +| `replicas` _integer_ | Replicas is the current number of ready pod replicas (used by the scale sub-resource). | +| `selector` _string_ | Selector is the label selector for pods managed by the FeatureStore deployment (used by the scale sub-resource). | +| `scalingStatus` _[ScalingStatus](#scalingstatus)_ | ScalingStatus reports the current scaling state of the FeatureStore deployment. | #### GitCloneOptions @@ -324,7 +361,6 @@ represented by the jobs's .status.failed field, is incremented and it is checked against the backoffLimit. This field cannot be used in combination with restartPolicy=OnFailure. - This field is beta-level. It can be used when the `JobPodFailurePolicy` feature gate is enabled (enabled by default). | | `backoffLimit` _integer_ | Specifies the number of retries before marking this job failed. | @@ -356,12 +392,10 @@ the Job becomes eligible to be deleted immediately after it finishes. | | `completionMode` _[CompletionMode](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#completionmode-v1-batch)_ | completionMode specifies how Pod completions are tracked. It can be `NonIndexed` (default) or `Indexed`. - `NonIndexed` means that the Job is considered complete when there have been .spec.completions successfully completed Pods. Each Pod completion is homologous to each other. - `Indexed` means that the Pods of a Job get an associated completion index from 0 to (.spec.completions - 1), available in the annotation batch.kubernetes.io/job-completion-index. @@ -373,7 +407,6 @@ In addition, The Pod name takes the form `$(job-name)-$(index)-$(random-string)`, the Pod hostname takes the form `$(job-name)-$(index)`. - More completion modes can be added in the future. If the Job controller observes a mode that it doesn't recognize, which is possible during upgrades due to version skew, the controller @@ -392,7 +425,6 @@ Possible values are: - Failed means to wait until a previously created Pod is fully terminated (has phase Failed or Succeeded) before creating a replacement Pod. - When using podFailurePolicy, Failed is the the only allowed value. TerminatingOrFailed and Failed are allowed values when podFailurePolicy is not in use. This is an beta field. To use this, enable the JobPodReplacementPolicy feature toggle. @@ -507,7 +539,27 @@ _Appears in:_ | Field | Description | | --- | --- | -| `secretRef` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#localobjectreference-v1-core)_ | | +| `issuerUrl` _string_ | OIDC issuer URL. The operator appends /.well-known/openid-configuration to derive the discovery endpoint. | +| `secretRef` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#localobjectreference-v1-core)_ | Secret with OIDC properties (auth_discovery_url, client_id, client_secret). issuerUrl takes precedence. | +| `secretKeyName` _string_ | Key in the Secret containing all OIDC properties as a YAML value. If unset, each key is a property. | +| `tokenEnvVar` _string_ | Env var name for client pods to read an OIDC token from. Sets token_env_var in client config. | +| `verifySSL` _boolean_ | Verify SSL certificates for the OIDC provider. Defaults to true. | +| `caCertConfigMap` _[OidcCACertConfigMap](#oidccacertconfigmap)_ | ConfigMap with the CA certificate for self-signed OIDC providers. Auto-detected on RHOAI/ODH. | + + +#### OidcCACertConfigMap + + + +OidcCACertConfigMap references a ConfigMap containing a CA certificate for OIDC provider TLS. + +_Appears in:_ +- [OidcAuthz](#oidcauthz) + +| Field | Description | +| --- | --- | +| `name` _string_ | ConfigMap name. | +| `key` _string_ | Key in the ConfigMap holding the PEM certificate. Defaults to "ca-bundle.crt". | #### OnlineStore @@ -592,6 +644,24 @@ _Appears in:_ | `nodeSelector` _map[string]string_ | | +#### PDBConfig + + + +PDBConfig configures a PodDisruptionBudget for the FeatureStore deployment. +Exactly one of minAvailable or maxUnavailable must be set. + +_Appears in:_ +- [FeatureStoreServices](#featurestoreservices) + +| Field | Description | +| --- | --- | +| `minAvailable` _[IntOrString](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#intorstring-intstr-util)_ | MinAvailable specifies the minimum number/percentage of pods that must remain available. +Mutually exclusive with maxUnavailable. | +| `maxUnavailable` _[IntOrString](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#intorstring-intstr-util)_ | MaxUnavailable specifies the maximum number/percentage of pods that can be unavailable. +Mutually exclusive with minAvailable. | + + #### PvcConfig @@ -747,6 +817,36 @@ _Appears in:_ | `tls` _[TlsRemoteRegistryConfigs](#tlsremoteregistryconfigs)_ | | +#### ScalingConfig + + + +ScalingConfig configures horizontal scaling for the FeatureStore deployment. + +_Appears in:_ +- [FeatureStoreServices](#featurestoreservices) + +| Field | Description | +| --- | --- | +| `autoscaling` _[AutoscalingConfig](#autoscalingconfig)_ | Autoscaling configures a HorizontalPodAutoscaler for the FeatureStore deployment. +Mutually exclusive with spec.replicas. | + + +#### ScalingStatus + + + +ScalingStatus reports the observed scaling state. + +_Appears in:_ +- [FeatureStoreStatus](#featurestorestatus) + +| Field | Description | +| --- | --- | +| `currentReplicas` _integer_ | CurrentReplicas is the current number of pod replicas. | +| `desiredReplicas` _integer_ | DesiredReplicas is the desired number of pod replicas. | + + #### SecretKeyNames diff --git a/infra/feast-operator/docs/odh-operator-parameters.md b/infra/feast-operator/docs/odh-operator-parameters.md new file mode 100644 index 00000000000..8b29d4d1ca8 --- /dev/null +++ b/infra/feast-operator/docs/odh-operator-parameters.md @@ -0,0 +1,15 @@ +# Open Data Hub / RHOAI operator parameters + +These values are supplied through the Feast operator **`params.env`** files in the **ODH** and **RHOAI** overlays (`config/overlays/odh/params.env`, `config/overlays/rhoai/params.env`). The Open Data Hub operator updates keys in `params.env` before rendering; Kustomize **`replacements`** copy them into the controller Deployment. + +## `OIDC_ISSUER_URL` + +**Purpose:** OIDC issuer URL when the OpenShift cluster uses external OIDC (for example Keycloak). The Feast operator process receives it as the **`OIDC_ISSUER_URL`** environment variable. An empty value means the cluster is not using external OIDC in this integration path (OpenShift OAuth / default behavior). + +**Manifest parameter:** `OIDC_ISSUER_URL` in `params.env`. + +**Injected into:** `controller-manager` Deployment, `manager` container. + +**Set by:** Open Data Hub operator (Feast component reconcile), from `GatewayConfig.spec.oidc.issuerURL` when cluster authentication is OIDC. + +**Consumption:** Operator code should read `os.Getenv("OIDC_ISSUER_URL")` (or equivalent) where JWKS / OIDC discovery is required for managed workloads. diff --git a/infra/feast-operator/go.mod b/infra/feast-operator/go.mod index 3e41f468d68..c243e03d71b 100644 --- a/infra/feast-operator/go.mod +++ b/infra/feast-operator/go.mod @@ -1,97 +1,103 @@ module github.com/feast-dev/feast/infra/feast-operator -go 1.22.9 +go 1.24.12 require ( - github.com/onsi/ginkgo/v2 v2.17.1 - github.com/onsi/gomega v1.32.0 + github.com/onsi/ginkgo/v2 v2.22.2 + github.com/onsi/gomega v1.36.2 github.com/openshift/api v0.0.0-20240912201240-0a8800162826 // release-4.17 gopkg.in/yaml.v3 v3.0.1 - k8s.io/api v0.30.1 - k8s.io/apimachinery v0.30.1 - k8s.io/client-go v0.30.1 - sigs.k8s.io/controller-runtime v0.18.4 + k8s.io/api v0.33.0 + k8s.io/apimachinery v0.33.0 + k8s.io/client-go v0.33.0 + sigs.k8s.io/controller-runtime v0.21.0 ) require ( - github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect + github.com/prometheus-operator/prometheus-operator/pkg/client v0.75.0 + k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 +) + +require ( + cel.dev/expr v0.19.1 // indirect + github.com/antlr4-go/antlr/v4 v4.13.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/emicklei/go-restful/v3 v3.11.0 // indirect - github.com/evanphx/json-patch v4.12.0+incompatible // indirect - github.com/evanphx/json-patch/v5 v5.9.0 // indirect - github.com/felixge/httpsnoop v1.0.3 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/emicklei/go-restful/v3 v3.12.1 // indirect + github.com/evanphx/json-patch/v5 v5.9.11 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect - github.com/go-openapi/jsonpointer v0.19.6 // indirect - github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.22.3 // indirect - github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.21.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.4 // indirect - github.com/google/cel-go v0.17.8 // indirect - github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect - github.com/imdario/mergo v0.3.6 // indirect + github.com/google/btree v1.1.3 // indirect + github.com/google/cel-go v0.23.2 // indirect + github.com/google/gnostic-models v0.6.9 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.18.0 // indirect - github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.45.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect + github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.75.0 // indirect + github.com/prometheus/client_golang v1.22.0 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.62.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/spf13/cobra v1.8.1 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stoewer/go-strcase v1.2.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 // indirect - go.opentelemetry.io/otel v1.19.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 // indirect - go.opentelemetry.io/otel/metric v1.19.0 // indirect - go.opentelemetry.io/otel/sdk v1.19.0 // indirect - go.opentelemetry.io/otel/trace v1.19.0 // indirect - go.opentelemetry.io/proto/otlp v1.0.0 // indirect + github.com/stoewer/go-strcase v1.3.0 // indirect + github.com/x448/float16 v0.8.4 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect + go.opentelemetry.io/otel v1.33.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 // indirect + go.opentelemetry.io/otel/metric v1.33.0 // indirect + go.opentelemetry.io/otel/sdk v1.33.0 // indirect + go.opentelemetry.io/otel/trace v1.33.0 // indirect + go.opentelemetry.io/proto/otlp v1.4.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect - golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/net v0.33.0 // indirect - golang.org/x/oauth2 v0.12.0 // indirect - golang.org/x/sync v0.10.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/term v0.27.0 // indirect - golang.org/x/text v0.21.0 // indirect - golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect + go.uber.org/zap v1.27.0 // indirect + golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect + golang.org/x/net v0.38.0 // indirect + golang.org/x/oauth2 v0.27.0 // indirect + golang.org/x/sync v0.12.0 // indirect + golang.org/x/sys v0.31.0 // indirect + golang.org/x/term v0.30.0 // indirect + golang.org/x/text v0.23.0 // indirect + golang.org/x/time v0.9.0 // indirect + golang.org/x/tools v0.28.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect - google.golang.org/grpc v1.58.3 // indirect - google.golang.org/protobuf v1.33.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect + google.golang.org/grpc v1.68.1 // indirect + google.golang.org/protobuf v1.36.5 // indirect + gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/apiextensions-apiserver v0.30.1 // indirect - k8s.io/apiserver v0.30.1 // indirect - k8s.io/component-base v0.30.1 // indirect - k8s.io/klog/v2 v2.120.1 // indirect - k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect - k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect - sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0 // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + k8s.io/apiextensions-apiserver v0.33.0 // indirect + k8s.io/apiserver v0.33.0 // indirect + k8s.io/component-base v0.33.0 // indirect + k8s.io/klog/v2 v2.130.1 // indirect + k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect + sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect + sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect + sigs.k8s.io/randfill v1.0.0 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/infra/feast-operator/go.sum b/infra/feast-operator/go.sum index ef5d6204916..47e16adc5e2 100644 --- a/infra/feast-operator/go.sum +++ b/infra/feast-operator/go.sum @@ -1,90 +1,87 @@ -github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h1:7RFfzj4SSt6nnvCPbCqijJi1nWCd+TqAT3bYCStRC18= -github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= +cel.dev/expr v0.19.1 h1:NciYrtDRIR0lNCnH1LFJegdjspNx9fI59O7TWcua/W4= +cel.dev/expr v0.19.1/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw= +github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= +github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= -github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= -github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= -github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= -github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU= +github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= +github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= +github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/cel-go v0.17.8 h1:j9m730pMZt1Fc4oKhCLUHfjj6527LuhYcYw0Rl8gqto= -github.com/google/cel-go v0.17.8/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/cel-go v0.23.2 h1:UdEe3CvQh3Nv+E/j9r1Y//WO0K0cSyD7/y0bzyLIMI4= +github.com/google/cel-go v0.23.2/go.mod h1:52Pb6QsDbC5kvgxvZhiL9QX1oZEkcUF/ZqaPx1J5Wwo= +github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= +github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= -github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= +github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 h1:TmHmbvxPmaegwhDubVz0lICL0J5Ka2vwTzhoePEXsGE= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0/go.mod h1:qztMSjm835F2bXf+5HKAPIS5qsmQDqZna/PgVt4rWtI= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -92,162 +89,168 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8= -github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= -github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk= -github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg= +github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= +github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= +github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= +github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= github.com/openshift/api v0.0.0-20240912201240-0a8800162826 h1:A8D9SN/hJUwAbdO0rPCVTqmuBOctdgurr53gK701SYo= github.com/openshift/api v0.0.0-20240912201240-0a8800162826/go.mod h1:OOh6Qopf21pSzqNVCB5gomomBXb8o5sGKZxG2KNpaXM= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= -github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= -github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= -github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.75.0 h1:62MgqpTrtjNd8cc0RJSFJ1OHqgSrThgHehGVuQaF/fc= +github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.75.0/go.mod h1:XYrdZw5dW12Cjkt4ndbeNZZTBp4UCHtW0ccR9+sTtPU= +github.com/prometheus-operator/prometheus-operator/pkg/client v0.75.0 h1:QcchdrYyQ9qRY0KZlEjx6gYUjPOvkZDbzOlHMp4ix88= +github.com/prometheus-operator/prometheus-operator/pkg/client v0.75.0/go.mod h1:ptPuQIiTdOvagifFhojZSJ/8VinU3/l7gOQ+Y6M0aqI= +github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= +github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= +github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= -github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= +github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 h1:KfYpVmrjI7JuToy5k8XV3nkapjWx48k4E4JOtVstzQI= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0/go.mod h1:SeQhzAEccGVZVEy7aH87Nh0km+utSpo1pTv6eMMop48= -go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= -go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 h1:3d+S281UTjM+AbF31XSOYn1qXn3BgIdWl8HNEpx08Jk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I= -go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= -go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= -go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= -go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= -go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= -go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q= +go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw= +go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx69E/Y/DcQSMPpKANYVMQ7fBA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 h1:5pojmb1U1AogINhN3SurB+zm/nIcusopeBNp42f45QM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0/go.mod h1:57gTHJSE5S1tqg+EKsLPlTWhpHMsWlVmer+LA926XiA= +go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ= +go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M= +go.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM= +go.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM= +go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s= +go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck= +go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg= +go.opentelemetry.io/proto/otlp v1.4.0/go.mod h1:PPBWZIP98o2ElSqI35IHfu7hIhSwvc5N38Jw8pXuGFY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= -golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= +golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= +golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= -golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= +golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= +golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= +golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 h1:L6iMMGrtzgHsWofoFcihmDEMYeDR9KN/ThbPWGrh++g= -google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8= -google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e h1:z3vDksarJxsAKM5dmEGv0GHwE2hKJ096wZra71Vs4sw= -google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= -google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= -google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q= +google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 h1:8ZmaLZE4XWrtU3MyClkYqqtl6Oegr3235h7jxsDyqCY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/grpc v1.68.1 h1:oI5oTa11+ng8r8XMMN7jAOmWfPZWbYpCFaMUTACxkM0= +google.golang.org/grpc v1.68.1/go.mod h1:+q1XYFJjShcqn0QZHvCyeR4CXPA+llXIeUIfIe00waw= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.30.1 h1:kCm/6mADMdbAxmIh0LBjS54nQBE+U4KmbCfIkF5CpJY= -k8s.io/api v0.30.1/go.mod h1:ddbN2C0+0DIiPntan/bye3SW3PdwLa11/0yqwvuRrJM= -k8s.io/apiextensions-apiserver v0.30.1 h1:4fAJZ9985BmpJG6PkoxVRpXv9vmPUOVzl614xarePws= -k8s.io/apiextensions-apiserver v0.30.1/go.mod h1:R4GuSrlhgq43oRY9sF2IToFh7PVlF1JjfWdoG3pixk4= -k8s.io/apimachinery v0.30.1 h1:ZQStsEfo4n65yAdlGTfP/uSHMQSoYzU/oeEbkmF7P2U= -k8s.io/apimachinery v0.30.1/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= -k8s.io/apiserver v0.30.1 h1:BEWEe8bzS12nMtDKXzCF5Q5ovp6LjjYkSp8qOPk8LZ8= -k8s.io/apiserver v0.30.1/go.mod h1:i87ZnQ+/PGAmSbD/iEKM68bm1D5reX8fO4Ito4B01mo= -k8s.io/client-go v0.30.1 h1:uC/Ir6A3R46wdkgCV3vbLyNOYyCJ8oZnjtJGKfytl/Q= -k8s.io/client-go v0.30.1/go.mod h1:wrAqLNs2trwiCH/wxxmT/x3hKVH9PuV0GGW0oDoHVqc= -k8s.io/component-base v0.30.1 h1:bvAtlPh1UrdaZL20D9+sWxsJljMi0QZ3Lmw+kmZAaxQ= -k8s.io/component-base v0.30.1/go.mod h1:e/X9kDiOebwlI41AvBHuWdqFriSRrX50CdwA9TFaHLI= -k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= -k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0 h1:/U5vjBbQn3RChhv7P11uhYvCSm5G2GaIi5AIGBS6r4c= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0/go.mod h1:z7+wmGM2dfIiLRfrC6jb5kV2Mq/sK1ZP303cxzkV5Y4= -sigs.k8s.io/controller-runtime v0.18.4 h1:87+guW1zhvuPLh1PHybKdYFLU0YJp4FhJRmiHvm5BZw= -sigs.k8s.io/controller-runtime v0.18.4/go.mod h1:TVoGrfdpbA9VRFaRnKgk9P5/atA0pMwq+f+msb9M8Sg= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= +k8s.io/api v0.33.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU= +k8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM= +k8s.io/apiextensions-apiserver v0.33.0 h1:d2qpYL7Mngbsc1taA4IjJPRJ9ilnsXIrndH+r9IimOs= +k8s.io/apiextensions-apiserver v0.33.0/go.mod h1:VeJ8u9dEEN+tbETo+lFkwaaZPg6uFKLGj5vyNEwwSzc= +k8s.io/apimachinery v0.33.0 h1:1a6kHrJxb2hs4t8EE5wuR/WxKDwGN1FKH3JvDtA0CIQ= +k8s.io/apimachinery v0.33.0/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= +k8s.io/apiserver v0.33.0 h1:QqcM6c+qEEjkOODHppFXRiw/cE2zP85704YrQ9YaBbc= +k8s.io/apiserver v0.33.0/go.mod h1:EixYOit0YTxt8zrO2kBU7ixAtxFce9gKGq367nFmqI8= +k8s.io/client-go v0.33.0 h1:UASR0sAYVUzs2kYuKn/ZakZlcs2bEHaizrrHUZg0G98= +k8s.io/client-go v0.33.0/go.mod h1:kGkd+l/gNGg8GYWAPr0xF1rRKvVWvzh9vmZAMXtaKOg= +k8s.io/component-base v0.33.0 h1:Ot4PyJI+0JAD9covDhwLp9UNkUja209OzsJ4FzScBNk= +k8s.io/component-base v0.33.0/go.mod h1:aXYZLbw3kihdkOPMDhWbjGCO6sg+luw554KP51t8qCU= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4= +k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= +k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= +k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= +sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8= +sigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM= +sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= +sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= +sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= +sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc= +sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/infra/feast-operator/internal/controller/authz/authz.go b/infra/feast-operator/internal/controller/authz/authz.go index 9cb5b7c9554..e9811c1c789 100644 --- a/infra/feast-operator/internal/controller/authz/authz.go +++ b/infra/feast-operator/internal/controller/authz/authz.go @@ -25,6 +25,16 @@ func (authz *FeastAuthorization) Deploy() error { _ = authz.Handler.DeleteOwnedFeastObj(authz.initFeastRole()) _ = authz.Handler.DeleteOwnedFeastObj(authz.initFeastRoleBinding()) apimeta.RemoveStatusCondition(&authz.Handler.FeatureStore.Status.Conditions, feastKubernetesAuthConditions[metav1.ConditionTrue].Type) + + if authz.isOidcAuth() { + if err := authz.createFeastClusterRole(); err != nil { + return err + } + if err := authz.createFeastClusterRoleBinding(); err != nil { + return err + } + } + return nil } @@ -33,6 +43,11 @@ func (authz *FeastAuthorization) isKubernetesAuth() bool { return authzConfig != nil && authzConfig.KubernetesAuthz != nil } +func (authz *FeastAuthorization) isOidcAuth() bool { + authzConfig := authz.Handler.FeatureStore.Status.Applied.AuthzConfig + return authzConfig != nil && authzConfig.OidcAuthz != nil +} + func (authz *FeastAuthorization) deployKubernetesAuth() error { if authz.isKubernetesAuth() { authz.removeOrphanedRoles() diff --git a/infra/feast-operator/internal/controller/featurestore_controller.go b/infra/feast-operator/internal/controller/featurestore_controller.go index a9591d97c8a..32c8405ec2b 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller.go +++ b/infra/feast-operator/internal/controller/featurestore_controller.go @@ -22,13 +22,17 @@ import ( "time" appsv1 "k8s.io/api/apps/v1" + autoscalingv2 "k8s.io/api/autoscaling/v2" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" + policyv1 "k8s.io/api/policy/v1" rbacv1 "k8s.io/api/rbac/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" apimeta "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -65,6 +69,9 @@ type FeatureStoreReconciler struct { // +kubebuilder:rbac:groups=authentication.k8s.io,resources=tokenreviews,verbs=create // +kubebuilder:rbac:groups=route.openshift.io,resources=routes,verbs=get;list;create;update;watch;delete // +kubebuilder:rbac:groups=batch,resources=cronjobs,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=autoscaling,resources=horizontalpodautoscalers,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=policy,resources=poddisruptionbudgets,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=monitoring.coreos.com,resources=servicemonitors,verbs=get;list;watch;create;patch;delete // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. @@ -192,11 +199,15 @@ func (r *FeatureStoreReconciler) deployFeast(ctx context.Context, cr *feastdevv1 } else { isDeployAvailable := services.IsDeploymentAvailable(deployment.Status.Conditions) if !isDeployAvailable { + msg := feastdevv1.DeploymentNotAvailableMessage + if podMsg := feast.GetPodContainerFailureMessage(deployment); podMsg != "" { + msg = msg + ": " + podMsg + } condition = metav1.Condition{ Type: feastdevv1.ReadyType, Status: metav1.ConditionUnknown, Reason: feastdevv1.DeploymentNotAvailableReason, - Message: feastdevv1.DeploymentNotAvailableMessage, + Message: msg, } result = errResult @@ -229,11 +240,22 @@ func (r *FeatureStoreReconciler) SetupWithManager(mgr ctrl.Manager) error { Owns(&rbacv1.RoleBinding{}). Owns(&rbacv1.Role{}). Owns(&batchv1.CronJob{}). + Owns(&autoscalingv2.HorizontalPodAutoscaler{}). + Owns(&policyv1.PodDisruptionBudget{}). Watches(&feastdevv1.FeatureStore{}, handler.EnqueueRequestsFromMapFunc(r.mapFeastRefsToFeastRequests)) if services.IsOpenShift() { bldr = bldr.Owns(&routev1.Route{}) } + if services.HasServiceMonitorCRD() { + sm := &unstructured.Unstructured{} + sm.SetGroupVersionKind(schema.GroupVersionKind{ + Group: "monitoring.coreos.com", + Version: "v1", + Kind: "ServiceMonitor", + }) + bldr = bldr.Owns(sm) + } return bldr.Complete(r) diff --git a/infra/feast-operator/internal/controller/featurestore_controller_cronjob_test.go b/infra/feast-operator/internal/controller/featurestore_controller_cronjob_test.go index c329d70f06d..11ae2af7777 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_cronjob_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_cronjob_test.go @@ -98,6 +98,8 @@ var _ = Describe("FeatureStore Controller - Feast CronJob", func() { Expect(resource.Status).NotTo(BeNil()) Expect(resource.Status.CronJob).To(Equal(objMeta.Name)) Expect(resource.Status.Applied.CronJob.Schedule).NotTo(BeEmpty()) + Expect(resource.Status.Applied.Services.RunFeastApplyOnInit).NotTo(BeNil()) + Expect(*resource.Status.Applied.Services.RunFeastApplyOnInit).To(BeTrue()) Expect(resource.Status.Conditions).NotTo(BeEmpty()) cond := apimeta.FindStatusCondition(resource.Status.Conditions, feastdevv1.CronJobReadyType) diff --git a/infra/feast-operator/internal/controller/featurestore_controller_objectstore_test.go b/infra/feast-operator/internal/controller/featurestore_controller_objectstore_test.go index 37d22094147..a326752a78f 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_objectstore_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_objectstore_test.go @@ -185,7 +185,7 @@ var _ = Describe("FeatureStore Controller-Ephemeral services", func() { Expect(err).NotTo(HaveOccurred()) Expect(deploy.Spec.Replicas).To(Equal(int32Ptr(1))) Expect(controllerutil.HasControllerReference(deploy)).To(BeTrue()) - Expect(deploy.Spec.Template.Spec.InitContainers).To(HaveLen(1)) + Expect(deploy.Spec.Template.Spec.InitContainers).To(HaveLen(2)) Expect(deploy.Spec.Template.Spec.Containers).To(HaveLen(2)) Expect(services.GetRegistryContainer(*deploy)).NotTo(BeNil()) Expect(services.GetOnlineContainer(*deploy)).NotTo(BeNil()) diff --git a/infra/feast-operator/internal/controller/featurestore_controller_oidc_auth_test.go b/infra/feast-operator/internal/controller/featurestore_controller_oidc_auth_test.go index bb5cc4fb4b2..16b57f8d7f5 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_oidc_auth_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_oidc_auth_test.go @@ -77,7 +77,7 @@ var _ = Describe("FeatureStore Controller-OIDC authorization", func() { if err != nil && errors.IsNotFound(err) { resource := createFeatureStoreResource(resourceName, image, pullPolicy, &[]corev1.EnvVar{}, withEnvFrom()) resource.Spec.AuthzConfig = &feastdevv1.AuthzConfig{OidcAuthz: &feastdevv1.OidcAuthz{ - SecretRef: corev1.LocalObjectReference{ + SecretRef: &corev1.LocalObjectReference{ Name: oidcSecretName, }, }} @@ -134,7 +134,7 @@ var _ = Describe("FeatureStore Controller-OIDC authorization", func() { Expect(resource.Status.Applied.FeastProject).To(Equal(resource.Spec.FeastProject)) expectedAuthzConfig := &feastdevv1.AuthzConfig{ OidcAuthz: &feastdevv1.OidcAuthz{ - SecretRef: corev1.LocalObjectReference{ + SecretRef: &corev1.LocalObjectReference{ Name: oidcSecretName, }, }, @@ -221,7 +221,7 @@ var _ = Describe("FeatureStore Controller-OIDC authorization", func() { Expect(err).NotTo(HaveOccurred()) Expect(deploy.Spec.Replicas).To(Equal(int32Ptr(1))) Expect(controllerutil.HasControllerReference(deploy)).To(BeTrue()) - Expect(deploy.Spec.Template.Spec.InitContainers).To(HaveLen(1)) + Expect(deploy.Spec.Template.Spec.InitContainers).To(HaveLen(2)) Expect(deploy.Spec.Template.Spec.Containers).To(HaveLen(4)) Expect(deploy.Spec.Template.Spec.Volumes).To(HaveLen(1)) Expect(services.GetOfflineContainer(*deploy).VolumeMounts).To(HaveLen(1)) @@ -476,7 +476,7 @@ var _ = Describe("FeatureStore Controller-OIDC authorization", func() { Expect(cond.Status).To(Equal(metav1.ConditionFalse)) Expect(cond.Reason).To(Equal(feastdevv1.FailedReason)) Expect(cond.Type).To(Equal(feastdevv1.ReadyType)) - Expect(cond.Message).To(ContainSubstring("missing OIDC")) + Expect(cond.Message).To(ContainSubstring("OIDC discovery URL")) }) }) }) @@ -496,12 +496,6 @@ func expectedServerOidcAuthorizConfig() services.AuthzConfig { func expectedClientOidcAuthorizConfig() services.AuthzConfig { return services.AuthzConfig{ Type: services.OidcAuthType, - OidcParameters: map[string]interface{}{ - string(services.OidcClientId): "client-id", - string(services.OidcAuthDiscoveryUrl): "auth-discovery-url", - string(services.OidcClientSecret): "client-secret", - string(services.OidcUsername): "username", - string(services.OidcPassword): "password"}, } } @@ -529,7 +523,7 @@ func createValidOidcSecret(secretName string) *corev1.Secret { func createInvalidOidcSecret(secretName string) *corev1.Secret { oidcProperties := validOidcSecretMap() - delete(oidcProperties, string(services.OidcClientId)) + delete(oidcProperties, string(services.OidcAuthDiscoveryUrl)) secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: secretName, diff --git a/infra/feast-operator/internal/controller/featurestore_controller_test.go b/infra/feast-operator/internal/controller/featurestore_controller_test.go index bfd4a484cff..4d2663fd47a 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_test.go @@ -19,6 +19,7 @@ package controller import ( "context" "encoding/base64" + "encoding/json" "fmt" "reflect" "strings" @@ -210,8 +211,10 @@ var _ = Describe("FeatureStore Controller", func() { Expect(deploy.Spec.Replicas).To(Equal(int32Ptr(1))) Expect(controllerutil.HasControllerReference(deploy)).To(BeTrue()) Expect(deploy.Spec.Template.Spec.ServiceAccountName).To(Equal(deploy.Name)) - Expect(deploy.Spec.Template.Spec.InitContainers).To(HaveLen(1)) + Expect(deploy.Spec.Template.Spec.InitContainers).To(HaveLen(2)) Expect(deploy.Spec.Template.Spec.InitContainers[0].Args[0]).To(ContainSubstring("feast init")) + Expect(deploy.Spec.Template.Spec.InitContainers[1].Name).To(Equal("feast-apply")) + Expect(deploy.Spec.Template.Spec.InitContainers[1].Command).To(Equal([]string{"feast", "apply"})) Expect(deploy.Spec.Template.Spec.Containers).To(HaveLen(1)) deploy.Spec.Replicas = int32Ptr(3) @@ -263,8 +266,8 @@ var _ = Describe("FeatureStore Controller", func() { Namespace: objMeta.Namespace, }, deploy) Expect(err).NotTo(HaveOccurred()) - Expect(deploy.Spec.Replicas).To(Equal(int32Ptr(3))) - Expect(deploy.Spec.Template.Spec.InitContainers).To(HaveLen(1)) + Expect(deploy.Spec.Replicas).To(Equal(int32Ptr(1))) + Expect(deploy.Spec.Template.Spec.InitContainers).To(HaveLen(2)) Expect(deploy.Spec.Template.Spec.InitContainers[0].Args[0]).To(ContainSubstring("git -c http.sslVerify=false clone")) Expect(deploy.Spec.Template.Spec.InitContainers[0].Args[0]).To(ContainSubstring("git checkout " + ref)) Expect(deploy.Spec.Template.Spec.InitContainers[0].Args[0]).To(ContainSubstring(featureRepoPath)) @@ -294,7 +297,7 @@ var _ = Describe("FeatureStore Controller", func() { Namespace: objMeta.Namespace, }, deploy) Expect(err).NotTo(HaveOccurred()) - Expect(deploy.Spec.Template.Spec.InitContainers).To(HaveLen(1)) + Expect(deploy.Spec.Template.Spec.InitContainers).To(HaveLen(2)) Expect(deploy.Spec.Template.Spec.InitContainers[0].Args[0]).To(ContainSubstring("feast init -t spark")) }) @@ -737,6 +740,12 @@ var _ = Describe("FeatureStore Controller", func() { }, deploy) Expect(err).NotTo(HaveOccurred()) Expect(deploy.Spec.Template.Spec.ServiceAccountName).To(Equal(deploy.Name)) + Expect(deploy.Spec.Template.Spec.InitContainers).To(HaveLen(2)) + Expect(deploy.Spec.Template.Spec.InitContainers[1].Name).To(Equal("feast-apply")) + Expect(deploy.Spec.Template.Spec.InitContainers[1].Env).To(ContainElements( + corev1.EnvVar{Name: testEnvVarName, Value: testEnvVarValue}, + )) + Expect(deploy.Spec.Template.Spec.InitContainers[1].EnvFrom).NotTo(BeEmpty()) Expect(deploy.Spec.Template.Spec.Containers).To(HaveLen(4)) registryContainer := services.GetRegistryContainer(*deploy) Expect(registryContainer.Env).To(HaveLen(1)) @@ -1145,7 +1154,7 @@ var _ = Describe("FeatureStore Controller", func() { Namespace: objMeta.Namespace, }, deploy) Expect(err).NotTo(HaveOccurred()) - Expect(deploy.Spec.Template.Spec.InitContainers).To(HaveLen(1)) + Expect(deploy.Spec.Template.Spec.InitContainers).To(HaveLen(2)) // check client config cm := &corev1.ConfigMap{} @@ -1225,6 +1234,127 @@ var _ = Describe("FeatureStore Controller", func() { Expect(cond.Message).To(Equal("Error: Remote feast registry of referenced FeatureStore '" + referencedRegistry.Name + "' is not ready")) }) + It("should allow cross-project registry references with different feastProject names", func() { + By("Reconciling the primary local registry FeatureStore") + controllerReconciler := &FeatureStoreReconciler{ + Client: k8sClient, + Scheme: k8sClient.Scheme(), + } + _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: typeNamespacedName, + }) + Expect(err).NotTo(HaveOccurred()) + + primaryStore := &feastdevv1.FeatureStore{} + err = k8sClient.Get(ctx, typeNamespacedName, primaryStore) + Expect(err).NotTo(HaveOccurred()) + Expect(primaryStore.Status.Applied.FeastProject).To(Equal(feastProject)) + + By("Creating a second FeatureStore with a DIFFERENT feastProject name referencing the first") + crossProjectName := "cross-project-ref" + crossProjectFeastName := "different_project" + crossProjectResource := &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{ + Name: crossProjectName, + Namespace: primaryStore.Namespace, + }, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: crossProjectFeastName, + Services: &feastdevv1.FeatureStoreServices{ + OnlineStore: &feastdevv1.OnlineStore{ + Server: &feastdevv1.ServerConfigs{}, + }, + Registry: &feastdevv1.Registry{ + Remote: &feastdevv1.RemoteRegistryConfig{ + FeastRef: &feastdevv1.FeatureStoreRef{ + Name: primaryStore.Name, + }, + }, + }, + }, + }, + } + crossProjectResource.SetGroupVersionKind(feastdevv1.GroupVersion.WithKind("FeatureStore")) + crossProjectNsName := client.ObjectKeyFromObject(crossProjectResource) + err = k8sClient.Create(ctx, crossProjectResource) + Expect(err).NotTo(HaveOccurred()) + + By("Reconciling the cross-project FeatureStore — should succeed without error") + _, err = controllerReconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: crossProjectNsName, + }) + Expect(err).NotTo(HaveOccurred()) + + err = k8sClient.Get(ctx, crossProjectNsName, crossProjectResource) + Expect(err).NotTo(HaveOccurred()) + + By("Verifying the cross-project FeatureStore is ready and uses its own project name") + Expect(crossProjectResource.Status.Applied.FeastProject).To(Equal(crossProjectFeastName)) + Expect(crossProjectResource.Status.ServiceHostnames.Registry).To(Equal(primaryStore.Status.ServiceHostnames.Registry)) + Expect(apimeta.IsStatusConditionTrue(crossProjectResource.Status.Conditions, feastdevv1.OnlineStoreReadyType)).To(BeTrue()) + + By("Verifying the cross-project client ConfigMap uses the correct project name and shared registry") + crossFeast := services.FeastServices{ + Handler: handler.FeastHandler{ + Client: controllerReconciler.Client, + Context: ctx, + Scheme: controllerReconciler.Scheme, + FeatureStore: crossProjectResource, + }, + } + crossCm := &corev1.ConfigMap{} + err = k8sClient.Get(ctx, types.NamespacedName{ + Name: crossFeast.GetFeastServiceName(services.ClientFeastType), + Namespace: crossProjectResource.Namespace, + }, crossCm) + Expect(err).NotTo(HaveOccurred()) + crossRepoConfig := &services.RepoConfig{} + err = yaml.Unmarshal([]byte(crossCm.Data[services.FeatureStoreYamlCmKey]), crossRepoConfig) + Expect(err).NotTo(HaveOccurred()) + Expect(crossRepoConfig.Project).To(Equal(crossProjectFeastName)) + Expect(crossRepoConfig.Registry.Path).To(ContainSubstring(primaryStore.Name)) + + By("Verifying the primary store client ConfigMap still uses its own project name") + primaryFeast := services.FeastServices{ + Handler: handler.FeastHandler{ + Client: controllerReconciler.Client, + Context: ctx, + Scheme: controllerReconciler.Scheme, + FeatureStore: primaryStore, + }, + } + primaryCm := &corev1.ConfigMap{} + err = k8sClient.Get(ctx, types.NamespacedName{ + Name: primaryFeast.GetFeastServiceName(services.ClientFeastType), + Namespace: primaryStore.Namespace, + }, primaryCm) + Expect(err).NotTo(HaveOccurred()) + primaryRepoConfig := &services.RepoConfig{} + err = yaml.Unmarshal([]byte(primaryCm.Data[services.FeatureStoreYamlCmKey]), primaryRepoConfig) + Expect(err).NotTo(HaveOccurred()) + Expect(primaryRepoConfig.Project).To(Equal(feastProject)) + + By("Verifying both stores share the same registry path") + Expect(crossRepoConfig.Registry.Path).To(Equal(primaryRepoConfig.Registry.Path)) + + By("Verifying the namespace registry ConfigMap lists both client configs") + registryCm := &corev1.ConfigMap{} + err = k8sClient.Get(ctx, types.NamespacedName{ + Name: services.NamespaceRegistryConfigMapName, + Namespace: services.DefaultKubernetesNamespace, + }, registryCm) + Expect(err).NotTo(HaveOccurred()) + var registryData services.NamespaceRegistryData + err = json.Unmarshal([]byte(registryCm.Data[services.NamespaceRegistryDataKey]), ®istryData) + Expect(err).NotTo(HaveOccurred()) + ns := primaryStore.Namespace + Expect(registryData.Namespaces[ns]).To(ContainElement(primaryFeast.GetFeastServiceName(services.ClientFeastType))) + Expect(registryData.Namespaces[ns]).To(ContainElement(crossFeast.GetFeastServiceName(services.ClientFeastType))) + + By("Cleaning up the cross-project FeatureStore") + Expect(k8sClient.Delete(ctx, crossProjectResource)).To(Succeed()) + }) + It("should correctly set container command args for grpc/rest modes", func() { controllerReconciler := &FeatureStoreReconciler{ Client: k8sClient, diff --git a/infra/feast-operator/internal/controller/featurestore_controller_tls_test.go b/infra/feast-operator/internal/controller/featurestore_controller_tls_test.go index 0af097120ce..bc60aed4374 100644 --- a/infra/feast-operator/internal/controller/featurestore_controller_tls_test.go +++ b/infra/feast-operator/internal/controller/featurestore_controller_tls_test.go @@ -193,6 +193,16 @@ var _ = Describe("FeatureStore Controller - Feast service TLS", func() { Expect(deploy.Spec.Replicas).To(Equal(int32Ptr(1))) Expect(controllerutil.HasControllerReference(deploy)).To(BeTrue()) Expect(deploy.Spec.Template.Spec.Containers).To(HaveLen(4)) + + // verify init containers have TLS volume mounts after reconciliation + Expect(deploy.Spec.Template.Spec.InitContainers).NotTo(BeEmpty()) + for _, initContainer := range deploy.Spec.Template.Spec.InitContainers { + Expect(initContainer.VolumeMounts).To(ContainElement(SatisfyAll( + HaveField("MountPath", services.GetTlsPath(services.RegistryFeastType)), + HaveField("ReadOnly", true), + )), "init container %s should have registry TLS volume mount", initContainer.Name) + } + svc := &corev1.Service{} err = k8sClient.Get(ctx, types.NamespacedName{ Name: feast.GetFeastServiceName(services.RegistryFeastType), @@ -401,6 +411,14 @@ var _ = Describe("FeatureStore Controller - Feast service TLS", func() { Expect(err).NotTo(HaveOccurred()) Expect(deploy.Spec.Template.Spec.Containers).To(HaveLen(2)) + // verify init containers have remote registry TLS volume mounts + for _, initContainer := range deploy.Spec.Template.Spec.InitContainers { + Expect(initContainer.VolumeMounts).To(ContainElement(SatisfyAll( + HaveField("MountPath", services.GetTlsPath(services.RegistryFeastType)), + HaveField("ReadOnly", true), + )), "init container %s should have remote registry TLS volume mount", initContainer.Name) + } + // check offline config offlineContainer = services.GetOfflineContainer(*deploy) env = getFeatureStoreYamlEnvVar(offlineContainer.Env) @@ -530,6 +548,12 @@ var _ = Describe("Test mountCustomCABundle functionality", func() { HaveField("MountPath", tlsPathCustomCABundle), ))) } + for _, initContainer := range deploy.Spec.Template.Spec.InitContainers { + Expect(initContainer.VolumeMounts).To(ContainElement(SatisfyAll( + HaveField("Name", configMapName), + HaveField("MountPath", tlsPathCustomCABundle), + )), "init container %s should have CA bundle volume mount", initContainer.Name) + } }) It("should not mount CA bundle volume or container mounts when ConfigMap is absent", func() { @@ -570,5 +594,10 @@ var _ = Describe("Test mountCustomCABundle functionality", func() { for _, container := range deploy.Spec.Template.Spec.Containers { Expect(container.VolumeMounts).NotTo(ContainElement(HaveField("Name", configMapName))) } + for _, initContainer := range deploy.Spec.Template.Spec.InitContainers { + Expect(initContainer.VolumeMounts).NotTo(ContainElement( + HaveField("Name", configMapName), + ), "init container %s should not have CA bundle mount when ConfigMap is absent", initContainer.Name) + } }) }) diff --git a/infra/feast-operator/internal/controller/services/client.go b/infra/feast-operator/internal/controller/services/client.go index fbd972368fb..6ce01ed0cc2 100644 --- a/infra/feast-operator/internal/controller/services/client.go +++ b/infra/feast-operator/internal/controller/services/client.go @@ -47,7 +47,7 @@ func (feast *FeastServices) createClientConfigMap() error { func (feast *FeastServices) setClientConfigMap(cm *corev1.ConfigMap) error { cm.Labels = feast.getFeastTypeLabels(ClientFeastType) - clientYaml, err := feast.getClientFeatureStoreYaml(feast.extractConfigFromSecret) + clientYaml, err := feast.getClientFeatureStoreYaml() if err != nil { return err } diff --git a/infra/feast-operator/internal/controller/services/namespace_registry.go b/infra/feast-operator/internal/controller/services/namespace_registry.go index 64cdaebd6f0..c796f4ca6b6 100644 --- a/infra/feast-operator/internal/controller/services/namespace_registry.go +++ b/infra/feast-operator/internal/controller/services/namespace_registry.go @@ -20,6 +20,7 @@ import ( "encoding/json" "fmt" "os" + "reflect" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" @@ -163,42 +164,51 @@ func (feast *FeastServices) createNamespaceRegistryRoleBinding(targetNamespace s // setNamespaceRegistryRoleBinding sets the RoleBinding for namespace registry access func (feast *FeastServices) setNamespaceRegistryRoleBinding(rb *rbacv1.RoleBinding) error { - // Create a Role that allows reading the ConfigMap + roleName := NamespaceRegistryConfigMapName + "-reader" + + desiredRules := []rbacv1.PolicyRule{ + { + APIGroups: []string{""}, + Resources: []string{"configmaps"}, + ResourceNames: []string{NamespaceRegistryConfigMapName}, + Verbs: []string{"get", "list"}, + }, + } + role := &rbacv1.Role{ ObjectMeta: metav1.ObjectMeta{ - Name: NamespaceRegistryConfigMapName + "-reader", + Name: roleName, Namespace: rb.Namespace, }, - Rules: []rbacv1.PolicyRule{ - { - APIGroups: []string{""}, - Resources: []string{"configmaps"}, - ResourceNames: []string{NamespaceRegistryConfigMapName}, - Verbs: []string{"get", "list"}, - }, - }, } + role.Rules = desiredRules - // Create or update the Role - if _, err := controllerutil.CreateOrUpdate(feast.Handler.Context, feast.Handler.Client, role, controllerutil.MutateFn(func() error { - role.Rules = []rbacv1.PolicyRule{ - { - APIGroups: []string{""}, - Resources: []string{"configmaps"}, - ResourceNames: []string{NamespaceRegistryConfigMapName}, - Verbs: []string{"get", "list"}, - }, + // Attempt to create; tolerate AlreadyExists so concurrent reconcilers don't fail. + if err := feast.Handler.Client.Create(feast.Handler.Context, role); err != nil && !apierrors.IsAlreadyExists(err) { + return fmt.Errorf("failed to create namespace registry Role: %w", err) + } + + // Re-fetch the authoritative copy to compare rules and obtain the latest resourceVersion. + existingRole := &rbacv1.Role{} + if err := feast.Handler.Client.Get(feast.Handler.Context, types.NamespacedName{ + Name: roleName, + Namespace: rb.Namespace, + }, existingRole); err != nil { + return fmt.Errorf("failed to get namespace registry Role: %w", err) + } + + if !reflect.DeepEqual(existingRole.Rules, desiredRules) { + existingRole.Rules = desiredRules + // On conflict the reconciler will re-queue automatically. + if err := feast.Handler.Client.Update(feast.Handler.Context, existingRole); err != nil { + return fmt.Errorf("failed to update namespace registry Role: %w", err) } - return nil - })); err != nil { - return err } - // Set the RoleBinding rb.RoleRef = rbacv1.RoleRef{ APIGroup: "rbac.authorization.k8s.io", Kind: "Role", - Name: role.Name, + Name: roleName, } rb.Subjects = []rbacv1.Subject{ diff --git a/infra/feast-operator/internal/controller/services/repo_config.go b/infra/feast-operator/internal/controller/services/repo_config.go index 9b20955f324..b67d948033b 100644 --- a/infra/feast-operator/internal/controller/services/repo_config.go +++ b/infra/feast-operator/internal/controller/services/repo_config.go @@ -19,6 +19,7 @@ package services import ( "encoding/base64" "fmt" + "os" "path" "strings" @@ -26,6 +27,8 @@ import ( "gopkg.in/yaml.v3" ) +const oidcIssuerUrlEnvVar = "OIDC_ISSUER_URL" + // GetServiceFeatureStoreYamlBase64 returns a base64 encoded feature_store.yaml config for the feast service func (feast *FeastServices) GetServiceFeatureStoreYamlBase64() (string, error) { fsYaml, err := feast.getServiceFeatureStoreYaml() @@ -44,14 +47,16 @@ func (feast *FeastServices) getServiceFeatureStoreYaml() ([]byte, error) { } func (feast *FeastServices) getServiceRepoConfig() (RepoConfig, error) { - return getServiceRepoConfig(feast.Handler.FeatureStore, feast.extractConfigFromSecret, feast.extractConfigFromConfigMap) + odhCaBundleExists := feast.GetCustomCertificatesBundle().IsDefined + return getServiceRepoConfig(feast.Handler.FeatureStore, feast.extractConfigFromSecret, feast.extractConfigFromConfigMap, odhCaBundleExists) } func getServiceRepoConfig( featureStore *feastdevv1.FeatureStore, secretExtractionFunc func(storeType string, secretRef string, secretKeyName string) (map[string]interface{}, error), - configMapExtractionFunc func(configMapRef string, configMapKey string) (map[string]interface{}, error)) (RepoConfig, error) { - repoConfig, err := getBaseServiceRepoConfig(featureStore, secretExtractionFunc) + configMapExtractionFunc func(configMapRef string, configMapKey string) (map[string]interface{}, error), + odhCaBundleExists bool) (RepoConfig, error) { + repoConfig, err := getBaseServiceRepoConfig(featureStore, secretExtractionFunc, odhCaBundleExists) if err != nil { return repoConfig, err } @@ -91,39 +96,91 @@ func getServiceRepoConfig( func getBaseServiceRepoConfig( featureStore *feastdevv1.FeatureStore, - secretExtractionFunc func(storeType string, secretRef string, secretKeyName string) (map[string]interface{}, error)) (RepoConfig, error) { + secretExtractionFunc func(storeType string, secretRef string, secretKeyName string) (map[string]interface{}, error), + odhCaBundleExists bool) (RepoConfig, error) { repoConfig := defaultRepoConfig(featureStore) - clientRepoConfig, err := getClientRepoConfig(featureStore, secretExtractionFunc, nil) - if err != nil { - return repoConfig, err - } + clientRepoConfig := getClientRepoConfig(featureStore, nil) if isRemoteRegistry(featureStore) { repoConfig.Registry = clientRepoConfig.Registry } - repoConfig.AuthzConfig = clientRepoConfig.AuthzConfig - appliedSpec := featureStore.Status.Applied if appliedSpec.AuthzConfig != nil && appliedSpec.AuthzConfig.OidcAuthz != nil { - propertiesMap, authSecretErr := secretExtractionFunc("", appliedSpec.AuthzConfig.OidcAuthz.SecretRef.Name, "") - if authSecretErr != nil { - return repoConfig, authSecretErr - } - + repoConfig.AuthzConfig = AuthzConfig{Type: OidcAuthType} + oidcAuthz := appliedSpec.AuthzConfig.OidcAuthz oidcParameters := map[string]interface{}{} - for _, oidcProperty := range OidcProperties { - if val, exists := propertiesMap[string(oidcProperty)]; exists { - oidcParameters[string(oidcProperty)] = val - } else { - return repoConfig, missingOidcSecretProperty(oidcProperty) + + var secretProperties map[string]interface{} + if oidcAuthz.SecretRef != nil { + var err error + secretProperties, err = secretExtractionFunc("", oidcAuthz.SecretRef.Name, oidcAuthz.SecretKeyName) + if err != nil { + return repoConfig, err + } + for _, prop := range OidcOptionalSecretProperties { + if val, exists := secretProperties[string(prop)]; exists { + oidcParameters[string(prop)] = val + } } } + + discoveryUrl, err := resolveAuthDiscoveryUrl(oidcAuthz, secretProperties) + if err != nil { + return repoConfig, err + } + oidcParameters[string(OidcAuthDiscoveryUrl)] = discoveryUrl + + if oidcAuthz.VerifySSL != nil { + oidcParameters[string(OidcVerifySsl)] = *oidcAuthz.VerifySSL + } + if caCertPath := resolveOidcCACertPath(oidcAuthz, odhCaBundleExists); caCertPath != "" { + oidcParameters[string(OidcCaCertPath)] = caCertPath + } repoConfig.AuthzConfig.OidcParameters = oidcParameters + } else { + repoConfig.AuthzConfig = clientRepoConfig.AuthzConfig } return repoConfig, nil } +// resolveAuthDiscoveryUrl determines the OIDC discovery URL from the first available source. +// Priority: CR issuerUrl > Secret auth_discovery_url > OIDC_ISSUER_URL env var. +func resolveAuthDiscoveryUrl(oidcAuthz *feastdevv1.OidcAuthz, secretProperties map[string]interface{}) (string, error) { + if oidcAuthz.IssuerUrl != "" { + return issuerToDiscoveryUrl(oidcAuthz.IssuerUrl), nil + } + + if val, ok := secretProperties[string(OidcAuthDiscoveryUrl)]; ok { + if s, ok := val.(string); ok && s != "" { + return s, nil + } + } + + if envIssuer := os.Getenv(oidcIssuerUrlEnvVar); envIssuer != "" { + return issuerToDiscoveryUrl(envIssuer), nil + } + + return "", fmt.Errorf("no OIDC discovery URL configured: set issuerUrl on the OidcAuthz CR, "+ + "include auth_discovery_url in the referenced Secret, or ensure the %s environment variable is set on the operator pod", oidcIssuerUrlEnvVar) +} + +func issuerToDiscoveryUrl(issuerUrl string) string { + return strings.TrimRight(issuerUrl, "/") + "/.well-known/openid-configuration" +} + +// resolveOidcCACertPath determines the CA cert file path for OIDC provider TLS verification. +// Priority: explicit CRD caCertConfigMap > ODH auto-detected bundle > empty (system CA fallback). +func resolveOidcCACertPath(oidcAuthz *feastdevv1.OidcAuthz, odhCaBundleExists bool) string { + if oidcAuthz.CACertConfigMap != nil { + return tlsPathOidcCA + } + if odhCaBundleExists { + return tlsPathOdhCABundle + } + return "" +} + func setRepoConfigRegistry(services *feastdevv1.FeatureStoreServices, secretExtractionFunc func(storeType string, secretRef string, secretKeyName string) (map[string]interface{}, error), repoConfig *RepoConfig) error { registryPersistence := services.Registry.Local.Persistence @@ -284,24 +341,17 @@ func setRepoConfigBatchEngine( return nil } -func (feast *FeastServices) getClientFeatureStoreYaml(secretExtractionFunc func(storeType string, secretRef string, secretKeyName string) (map[string]interface{}, error)) ([]byte, error) { - clientRepo, err := getClientRepoConfig(feast.Handler.FeatureStore, secretExtractionFunc, feast) - if err != nil { - return []byte{}, err - } +func (feast *FeastServices) getClientFeatureStoreYaml() ([]byte, error) { + clientRepo := getClientRepoConfig(feast.Handler.FeatureStore, feast) return yaml.Marshal(clientRepo) } func getClientRepoConfig( featureStore *feastdevv1.FeatureStore, - secretExtractionFunc func(storeType string, secretRef string, secretKeyName string) (map[string]interface{}, error), - feast *FeastServices) (RepoConfig, error) { + feast *FeastServices) RepoConfig { status := featureStore.Status appliedServices := status.Applied.Services - clientRepoConfig, err := getRepoConfig(featureStore, secretExtractionFunc) - if err != nil { - return clientRepoConfig, err - } + clientRepoConfig := getRepoConfig(featureStore) if len(status.ServiceHostnames.OfflineStore) > 0 { clientRepoConfig.OfflineStore = OfflineStoreConfig{ Type: OfflineRemoteConfigType, @@ -339,12 +389,10 @@ func getClientRepoConfig( } } - return clientRepoConfig, nil + return clientRepoConfig } -func getRepoConfig( - featureStore *feastdevv1.FeatureStore, - secretExtractionFunc func(storeType string, secretRef string, secretKeyName string) (map[string]interface{}, error)) (RepoConfig, error) { +func getRepoConfig(featureStore *feastdevv1.FeatureStore) RepoConfig { status := featureStore.Status repoConfig := initRepoConfig(status.Applied.FeastProject) if status.Applied.AuthzConfig != nil { @@ -356,24 +404,16 @@ func getRepoConfig( repoConfig.AuthzConfig = AuthzConfig{ Type: OidcAuthType, } - - propertiesMap, err := secretExtractionFunc("", status.Applied.AuthzConfig.OidcAuthz.SecretRef.Name, "") - if err != nil { - return repoConfig, err - } - oidcClientProperties := map[string]interface{}{} - for _, oidcProperty := range OidcProperties { - if val, exists := propertiesMap[string(oidcProperty)]; exists { - oidcClientProperties[string(oidcProperty)] = val - } else { - return repoConfig, missingOidcSecretProperty(oidcProperty) - } + if status.Applied.AuthzConfig.OidcAuthz.TokenEnvVar != nil { + oidcClientProperties[string(OidcTokenEnvVar)] = *status.Applied.AuthzConfig.OidcAuthz.TokenEnvVar + } + if len(oidcClientProperties) > 0 { + repoConfig.AuthzConfig.OidcParameters = oidcClientProperties } - repoConfig.AuthzConfig.OidcParameters = oidcClientProperties } } - return repoConfig, nil + return repoConfig } func getActualPath(filePath string, pvcConfig *feastdevv1.PvcConfig) string { diff --git a/infra/feast-operator/internal/controller/services/repo_config_test.go b/infra/feast-operator/internal/controller/services/repo_config_test.go index 70869568dea..20fff934f19 100644 --- a/infra/feast-operator/internal/controller/services/repo_config_test.go +++ b/infra/feast-operator/internal/controller/services/repo_config_test.go @@ -46,7 +46,7 @@ var _ = Describe("Repo Config", func() { Path: EphemeralPath + "/" + DefaultOnlineStorePath, } - repoConfig, err := getServiceRepoConfig(featureStore, emptyMockExtractConfigFromSecret, emptyMockExtractConfigFromConfigMap) + repoConfig, err := getServiceRepoConfig(featureStore, emptyMockExtractConfigFromSecret, emptyMockExtractConfigFromConfigMap, false) Expect(err).NotTo(HaveOccurred()) Expect(repoConfig.AuthzConfig.Type).To(Equal(NoAuthAuthType)) Expect(repoConfig.OfflineStore).To(Equal(emptyOfflineStoreConfig)) @@ -74,7 +74,7 @@ var _ = Describe("Repo Config", func() { Path: testPath, } - repoConfig, err = getServiceRepoConfig(featureStore, emptyMockExtractConfigFromSecret, emptyMockExtractConfigFromConfigMap) + repoConfig, err = getServiceRepoConfig(featureStore, emptyMockExtractConfigFromSecret, emptyMockExtractConfigFromConfigMap, false) Expect(err).NotTo(HaveOccurred()) Expect(repoConfig.AuthzConfig.Type).To(Equal(NoAuthAuthType)) Expect(repoConfig.OfflineStore).To(Equal(emptyOfflineStoreConfig)) @@ -96,7 +96,7 @@ var _ = Describe("Repo Config", func() { Expect(appliedServices.OnlineStore).NotTo(BeNil()) Expect(appliedServices.Registry.Local).NotTo(BeNil()) - repoConfig, err = getServiceRepoConfig(featureStore, emptyMockExtractConfigFromSecret, emptyMockExtractConfigFromConfigMap) + repoConfig, err = getServiceRepoConfig(featureStore, emptyMockExtractConfigFromSecret, emptyMockExtractConfigFromConfigMap, false) Expect(err).NotTo(HaveOccurred()) Expect(repoConfig.OfflineStore).To(Equal(defaultOfflineStoreConfig)) Expect(repoConfig.AuthzConfig.Type).To(Equal(NoAuthAuthType)) @@ -115,7 +115,7 @@ var _ = Describe("Repo Config", func() { }, } ApplyDefaultsToStatus(featureStore) - repoConfig, err = getServiceRepoConfig(featureStore, emptyMockExtractConfigFromSecret, emptyMockExtractConfigFromConfigMap) + repoConfig, err = getServiceRepoConfig(featureStore, emptyMockExtractConfigFromSecret, emptyMockExtractConfigFromConfigMap, false) Expect(err).NotTo(HaveOccurred()) Expect(repoConfig.AuthzConfig.Type).To(Equal(NoAuthAuthType)) Expect(repoConfig.OfflineStore).To(Equal(emptyOfflineStoreConfig)) @@ -163,7 +163,7 @@ var _ = Describe("Repo Config", func() { Path: "/data/online.db", } - repoConfig, err = getServiceRepoConfig(featureStore, emptyMockExtractConfigFromSecret, emptyMockExtractConfigFromConfigMap) + repoConfig, err = getServiceRepoConfig(featureStore, emptyMockExtractConfigFromSecret, emptyMockExtractConfigFromConfigMap, false) Expect(err).NotTo(HaveOccurred()) Expect(repoConfig.AuthzConfig.Type).To(Equal(NoAuthAuthType)) Expect(repoConfig.OfflineStore).To(Equal(expectedOfflineConfig)) @@ -188,17 +188,17 @@ var _ = Describe("Repo Config", func() { Type: "dask", } - repoConfig, err = getServiceRepoConfig(featureStore, mockExtractConfigFromSecret, emptyMockExtractConfigFromConfigMap) + repoConfig, err = getServiceRepoConfig(featureStore, mockExtractConfigFromSecret, emptyMockExtractConfigFromConfigMap, false) Expect(err).NotTo(HaveOccurred()) Expect(repoConfig.AuthzConfig.Type).To(Equal(KubernetesAuthType)) Expect(repoConfig.OfflineStore).To(Equal(expectedOfflineConfig)) Expect(repoConfig.OnlineStore).To(Equal(defaultOnlineStoreConfig(featureStore))) Expect(repoConfig.Registry).To(Equal(defaultRegistryConfig(featureStore))) - By("Having oidc authorization") + By("Having oidc authorization with Secret") featureStore.Spec.AuthzConfig = &feastdevv1.AuthzConfig{ OidcAuthz: &feastdevv1.OidcAuthz{ - SecretRef: corev1.LocalObjectReference{ + SecretRef: &corev1.LocalObjectReference{ Name: "oidc-secret", }, }, @@ -211,7 +211,7 @@ var _ = Describe("Repo Config", func() { string(OidcClientSecret): "client-secret", string(OidcUsername): "username", string(OidcPassword): "password"}) - repoConfig, err = getServiceRepoConfig(featureStore, secretExtractionFunc, emptyMockExtractConfigFromConfigMap) + repoConfig, err = getServiceRepoConfig(featureStore, secretExtractionFunc, emptyMockExtractConfigFromConfigMap, false) Expect(err).NotTo(HaveOccurred()) Expect(repoConfig.AuthzConfig.Type).To(Equal(OidcAuthType)) Expect(repoConfig.AuthzConfig.OidcParameters).To(HaveLen(5)) @@ -224,15 +224,35 @@ var _ = Describe("Repo Config", func() { Expect(repoConfig.OnlineStore).To(Equal(defaultOnlineStoreConfig(featureStore))) Expect(repoConfig.Registry).To(Equal(defaultRegistryConfig(featureStore))) - repoConfig, err = getClientRepoConfig(featureStore, secretExtractionFunc, nil) + repoConfig = getClientRepoConfig(featureStore, nil) + Expect(repoConfig.AuthzConfig.Type).To(Equal(OidcAuthType)) + + By("Having oidc authorization with issuerUrl only (no Secret)") + featureStore.Spec.AuthzConfig = &feastdevv1.AuthzConfig{ + OidcAuthz: &feastdevv1.OidcAuthz{ + IssuerUrl: "https://keycloak.example.com/realms/test", + }, + } + ApplyDefaultsToStatus(featureStore) + repoConfig, err = getServiceRepoConfig(featureStore, emptyMockExtractConfigFromSecret, emptyMockExtractConfigFromConfigMap, false) Expect(err).NotTo(HaveOccurred()) Expect(repoConfig.AuthzConfig.Type).To(Equal(OidcAuthType)) - Expect(repoConfig.AuthzConfig.OidcParameters).To(HaveLen(5)) - Expect(repoConfig.AuthzConfig.OidcParameters).To(HaveKey(string(OidcClientId))) - Expect(repoConfig.AuthzConfig.OidcParameters).To(HaveKey(string(OidcAuthDiscoveryUrl))) - Expect(repoConfig.AuthzConfig.OidcParameters).To(HaveKey(string(OidcClientSecret))) - Expect(repoConfig.AuthzConfig.OidcParameters).To(HaveKey(string(OidcUsername))) - Expect(repoConfig.AuthzConfig.OidcParameters).To(HaveKey(string(OidcPassword))) + Expect(repoConfig.AuthzConfig.OidcParameters).To(HaveLen(1)) + Expect(repoConfig.AuthzConfig.OidcParameters[string(OidcAuthDiscoveryUrl)]).To(Equal("https://keycloak.example.com/realms/test/.well-known/openid-configuration")) + + By("Having oidc with issuerUrl on CR and auth_discovery_url in Secret — CR wins") + featureStore.Spec.AuthzConfig = &feastdevv1.AuthzConfig{ + OidcAuthz: &feastdevv1.OidcAuthz{ + IssuerUrl: "https://keycloak.example.com/realms/cr-wins", + SecretRef: &corev1.LocalObjectReference{ + Name: "oidc-secret", + }, + }, + } + ApplyDefaultsToStatus(featureStore) + repoConfig, err = getServiceRepoConfig(featureStore, secretExtractionFunc, emptyMockExtractConfigFromConfigMap, false) + Expect(err).NotTo(HaveOccurred()) + Expect(repoConfig.AuthzConfig.OidcParameters[string(OidcAuthDiscoveryUrl)]).To(Equal("https://keycloak.example.com/realms/cr-wins/.well-known/openid-configuration")) By("Having the all the db services") featureStore = minimalFeatureStore() @@ -275,7 +295,7 @@ var _ = Describe("Repo Config", func() { featureStore.Spec.Services.OfflineStore.Persistence.FilePersistence = nil featureStore.Spec.Services.OnlineStore.Persistence.FilePersistence = nil featureStore.Spec.Services.Registry.Local.Persistence.FilePersistence = nil - repoConfig, err = getServiceRepoConfig(featureStore, mockExtractConfigFromSecret, emptyMockExtractConfigFromConfigMap) + repoConfig, err = getServiceRepoConfig(featureStore, mockExtractConfigFromSecret, emptyMockExtractConfigFromConfigMap, false) Expect(err).NotTo(HaveOccurred()) newMap := CopyMap(parameterMap) port := parameterMap["port"].(int) @@ -301,10 +321,20 @@ var _ = Describe("Repo Config", func() { It("should fail to create the repo configs", func() { featureStore := minimalFeatureStore() - By("Having invalid server oidc authorization") + By("Having oidc with no issuerUrl, no Secret, no env var — should fail") + featureStore.Spec.AuthzConfig = &feastdevv1.AuthzConfig{ + OidcAuthz: &feastdevv1.OidcAuthz{}, + } + ApplyDefaultsToStatus(featureStore) + + _, err := getServiceRepoConfig(featureStore, emptyMockExtractConfigFromSecret, emptyMockExtractConfigFromConfigMap, false) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("no OIDC discovery URL configured")) + + By("Having oidc with Secret missing auth_discovery_url and no issuerUrl — should fail") featureStore.Spec.AuthzConfig = &feastdevv1.AuthzConfig{ OidcAuthz: &feastdevv1.OidcAuthz{ - SecretRef: corev1.LocalObjectReference{ + SecretRef: &corev1.LocalObjectReference{ Name: "oidc-secret", }, }, @@ -316,17 +346,14 @@ var _ = Describe("Repo Config", func() { string(OidcClientSecret): "client-secret", string(OidcUsername): "username", string(OidcPassword): "password"}) - _, err := getServiceRepoConfig(featureStore, secretExtractionFunc, emptyMockExtractConfigFromConfigMap) - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("missing OIDC secret")) - _, err = getClientRepoConfig(featureStore, secretExtractionFunc, nil) + _, err = getServiceRepoConfig(featureStore, secretExtractionFunc, emptyMockExtractConfigFromConfigMap, false) Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("missing OIDC secret")) + Expect(err.Error()).To(ContainSubstring("no OIDC discovery URL configured")) By("Having invalid client oidc authorization") featureStore.Spec.AuthzConfig = &feastdevv1.AuthzConfig{ OidcAuthz: &feastdevv1.OidcAuthz{ - SecretRef: corev1.LocalObjectReference{ + SecretRef: &corev1.LocalObjectReference{ Name: "oidc-secret", }, }, @@ -338,12 +365,9 @@ var _ = Describe("Repo Config", func() { string(OidcClientId): "client-id", string(OidcUsername): "username", string(OidcPassword): "password"}) - _, err = getServiceRepoConfig(featureStore, secretExtractionFunc, emptyMockExtractConfigFromConfigMap) - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("missing OIDC secret")) - _, err = getClientRepoConfig(featureStore, secretExtractionFunc, nil) - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("missing OIDC secret")) + _, err = getServiceRepoConfig(featureStore, secretExtractionFunc, emptyMockExtractConfigFromConfigMap, false) + Expect(err).NotTo(HaveOccurred()) + getClientRepoConfig(featureStore, nil) }) }) @@ -519,8 +543,7 @@ var _ = Describe("TLS Certificate Path Configuration", func() { } // Test with nil feast parameter (no custom CA bundle) - repoConfig, err := getClientRepoConfig(featureStore, emptyMockExtractConfigFromSecret, nil) - Expect(err).NotTo(HaveOccurred()) + repoConfig := getClientRepoConfig(featureStore, nil) // Verify individual service certificate paths are used Expect(repoConfig.OfflineStore.Cert).To(Equal("/tls/offline/tls.crt")) @@ -589,8 +612,7 @@ var _ = Describe("TLS Certificate Path Configuration", func() { } // Test with nil feast parameter (no custom CA bundle available) - repoConfig, err := getClientRepoConfig(featureStore, emptyMockExtractConfigFromSecret, nil) - Expect(err).NotTo(HaveOccurred()) + repoConfig := getClientRepoConfig(featureStore, nil) Expect(repoConfig.OfflineStore.Cert).To(Equal("/tls/offline/tls.crt")) }) }) diff --git a/infra/feast-operator/internal/controller/services/scaling.go b/infra/feast-operator/internal/controller/services/scaling.go new file mode 100644 index 00000000000..ef1dd1f91d8 --- /dev/null +++ b/infra/feast-operator/internal/controller/services/scaling.go @@ -0,0 +1,269 @@ +/* +Copyright 2026 Feast Community. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package services + +import ( + "encoding/json" + + feastdevv1 "github.com/feast-dev/feast/infra/feast-operator/api/v1" + appsv1 "k8s.io/api/apps/v1" + autoscalingv2 "k8s.io/api/autoscaling/v2" + corev1 "k8s.io/api/core/v1" + policyv1 "k8s.io/api/policy/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + hpaac "k8s.io/client-go/applyconfigurations/autoscaling/v2" + metaac "k8s.io/client-go/applyconfigurations/meta/v1" + pdbac "k8s.io/client-go/applyconfigurations/policy/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" +) + +const ( + defaultHPACPUUtilization int32 = 80 + defaultHPAMinReplicas int32 = 1 + fieldManager = "feast-operator" +) + +// getDesiredReplicas returns the replica count the operator should set on the +// Deployment. When autoscaling is configured the Deployment replicas field is +// left to the HPA (nil is returned). Otherwise the static replica count from +// spec.replicas is returned. +func (feast *FeastServices) getDesiredReplicas() *int32 { + cr := feast.Handler.FeatureStore + services := cr.Status.Applied.Services + if services != nil && services.Scaling != nil && services.Scaling.Autoscaling != nil { + return nil + } + if cr.Status.Applied.Replicas != nil { + r := *cr.Status.Applied.Replicas + return &r + } + return nil +} + +// createOrDeleteHPA reconciles the HorizontalPodAutoscaler for the FeatureStore +// deployment using Server-Side Apply with typed apply configurations. If +// autoscaling is not configured, any existing HPA is deleted. +func (feast *FeastServices) createOrDeleteHPA() error { + cr := feast.Handler.FeatureStore + + scaling := cr.Status.Applied.Services.Scaling + if scaling == nil || scaling.Autoscaling == nil { + hpa := &autoscalingv2.HorizontalPodAutoscaler{ + ObjectMeta: feast.GetObjectMeta(), + } + hpa.SetGroupVersionKind(autoscalingv2.SchemeGroupVersion.WithKind("HorizontalPodAutoscaler")) + return feast.Handler.DeleteOwnedFeastObj(hpa) + } + + hpaAC := feast.buildHPAApplyConfig() + data, err := json.Marshal(hpaAC) + if err != nil { + return err + } + + hpa := &autoscalingv2.HorizontalPodAutoscaler{ObjectMeta: feast.GetObjectMeta()} + logger := log.FromContext(feast.Handler.Context) + if err := feast.Handler.Client.Patch(feast.Handler.Context, hpa, + client.RawPatch(types.ApplyPatchType, data), + client.FieldOwner(fieldManager), client.ForceOwnership); err != nil { + return err + } + logger.Info("Successfully applied", "HorizontalPodAutoscaler", hpa.Name) + + return nil +} + +// buildHPAApplyConfig constructs the fully desired HPA state as a typed apply +// configuration for Server-Side Apply. +func (feast *FeastServices) buildHPAApplyConfig() *hpaac.HorizontalPodAutoscalerApplyConfiguration { + cr := feast.Handler.FeatureStore + autoscaling := cr.Status.Applied.Services.Scaling.Autoscaling + objMeta := feast.GetObjectMeta() + deploy := feast.initFeastDeploy() + + minReplicas := defaultHPAMinReplicas + if autoscaling.MinReplicas != nil { + minReplicas = *autoscaling.MinReplicas + } + + hpa := hpaac.HorizontalPodAutoscaler(objMeta.Name, objMeta.Namespace). + WithLabels(feast.getLabels()). + WithOwnerReferences( + metaac.OwnerReference(). + WithAPIVersion(feastdevv1.GroupVersion.String()). + WithKind("FeatureStore"). + WithName(cr.Name). + WithUID(cr.UID). + WithController(true). + WithBlockOwnerDeletion(true), + ). + WithSpec(hpaac.HorizontalPodAutoscalerSpec(). + WithScaleTargetRef( + hpaac.CrossVersionObjectReference(). + WithAPIVersion(appsv1.SchemeGroupVersion.String()). + WithKind("Deployment"). + WithName(deploy.Name), + ). + WithMinReplicas(minReplicas). + WithMaxReplicas(autoscaling.MaxReplicas), + ) + + if len(autoscaling.Metrics) > 0 { + hpa.Spec.Metrics = convertMetrics(autoscaling.Metrics) + } else { + hpa.Spec.Metrics = defaultHPAMetrics() + } + + if autoscaling.Behavior != nil { + hpa.Spec.Behavior = convertBehavior(autoscaling.Behavior) + } + + return hpa +} + +func defaultHPAMetrics() []hpaac.MetricSpecApplyConfiguration { + return []hpaac.MetricSpecApplyConfiguration{ + *hpaac.MetricSpec(). + WithType(autoscalingv2.ResourceMetricSourceType). + WithResource( + hpaac.ResourceMetricSource(). + WithName(corev1.ResourceCPU). + WithTarget( + hpaac.MetricTarget(). + WithType(autoscalingv2.UtilizationMetricType). + WithAverageUtilization(defaultHPACPUUtilization), + ), + ), + } +} + +// convertMetrics converts standard API metric specs to their apply configuration +// equivalents via JSON round-trip (the types share identical JSON schemas). +func convertMetrics(metrics []autoscalingv2.MetricSpec) []hpaac.MetricSpecApplyConfiguration { + data, err := json.Marshal(metrics) + if err != nil { + return nil + } + var result []hpaac.MetricSpecApplyConfiguration + if err := json.Unmarshal(data, &result); err != nil { + return nil + } + return result +} + +// convertBehavior converts a standard API behavior spec to its apply configuration +// equivalent via JSON round-trip. +func convertBehavior(behavior *autoscalingv2.HorizontalPodAutoscalerBehavior) *hpaac.HorizontalPodAutoscalerBehaviorApplyConfiguration { + data, err := json.Marshal(behavior) + if err != nil { + return nil + } + result := &hpaac.HorizontalPodAutoscalerBehaviorApplyConfiguration{} + if err := json.Unmarshal(data, result); err != nil { + return nil + } + return result +} + +// applyOrDeletePDB reconciles the PodDisruptionBudget for the FeatureStore +// deployment using Server-Side Apply. If PodDisruptionBudgets is not configured +// or scaling is not enabled, any existing PDB is deleted. +func (feast *FeastServices) applyOrDeletePDB() error { + cr := feast.Handler.FeatureStore + services := cr.Status.Applied.Services + + if services == nil || services.PodDisruptionBudgets == nil || !isScalingEnabled(cr) { + pdb := &policyv1.PodDisruptionBudget{ObjectMeta: feast.GetObjectMeta()} + pdb.SetGroupVersionKind(policyv1.SchemeGroupVersion.WithKind("PodDisruptionBudget")) + return feast.Handler.DeleteOwnedFeastObj(pdb) + } + + pdbAC := feast.buildPDBApplyConfig() + data, err := json.Marshal(pdbAC) + if err != nil { + return err + } + + pdb := &policyv1.PodDisruptionBudget{ObjectMeta: feast.GetObjectMeta()} + logger := log.FromContext(feast.Handler.Context) + if err := feast.Handler.Client.Patch(feast.Handler.Context, pdb, + client.RawPatch(types.ApplyPatchType, data), + client.FieldOwner(fieldManager), client.ForceOwnership); err != nil { + return err + } + logger.Info("Successfully applied", "PodDisruptionBudget", pdb.Name) + + return nil +} + +// buildPDBApplyConfig constructs the fully desired PDB state as a typed apply +// configuration for Server-Side Apply. +func (feast *FeastServices) buildPDBApplyConfig() *pdbac.PodDisruptionBudgetApplyConfiguration { + cr := feast.Handler.FeatureStore + pdbConfig := cr.Status.Applied.Services.PodDisruptionBudgets + objMeta := feast.GetObjectMeta() + + pdb := pdbac.PodDisruptionBudget(objMeta.Name, objMeta.Namespace). + WithLabels(feast.getLabels()). + WithOwnerReferences( + metaac.OwnerReference(). + WithAPIVersion(feastdevv1.GroupVersion.String()). + WithKind("FeatureStore"). + WithName(cr.Name). + WithUID(cr.UID). + WithController(true). + WithBlockOwnerDeletion(true), + ). + WithSpec(pdbac.PodDisruptionBudgetSpec(). + WithSelector(metaac.LabelSelector().WithMatchLabels(feast.getLabels())), + ) + + if pdbConfig.MinAvailable != nil { + pdb.Spec.WithMinAvailable(*pdbConfig.MinAvailable) + } + if pdbConfig.MaxUnavailable != nil { + pdb.Spec.WithMaxUnavailable(*pdbConfig.MaxUnavailable) + } + + return pdb +} + +// updateScalingStatus updates the scaling status fields using the deployment +func (feast *FeastServices) updateScalingStatus(deploy *appsv1.Deployment) { + cr := feast.Handler.FeatureStore + + cr.Status.Replicas = deploy.Status.ReadyReplicas + labels := feast.getLabels() + cr.Status.Selector = metav1.FormatLabelSelector(metav1.SetAsLabelSelector(labels)) + + if !isScalingEnabled(cr) { + cr.Status.ScalingStatus = nil + return + } + + var desired int32 + if deploy.Spec.Replicas != nil { + desired = *deploy.Spec.Replicas + } + + cr.Status.ScalingStatus = &feastdevv1.ScalingStatus{ + CurrentReplicas: deploy.Status.ReadyReplicas, + DesiredReplicas: desired, + } +} diff --git a/infra/feast-operator/internal/controller/services/scaling_test.go b/infra/feast-operator/internal/controller/services/scaling_test.go new file mode 100644 index 00000000000..58e808ac2dc --- /dev/null +++ b/infra/feast-operator/internal/controller/services/scaling_test.go @@ -0,0 +1,1009 @@ +/* +Copyright 2026 Feast Community. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package services + +import ( + "context" + + feastdevv1 "github.com/feast-dev/feast/infra/feast-operator/api/v1" + "github.com/feast-dev/feast/infra/feast-operator/internal/controller/handler" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + appsv1 "k8s.io/api/apps/v1" + autoscalingv1 "k8s.io/api/autoscaling/v1" + autoscalingv2 "k8s.io/api/autoscaling/v2" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +var _ = Describe("Horizontal Scaling", func() { + var ( + featureStore *feastdevv1.FeatureStore + feast *FeastServices + typeNamespacedName types.NamespacedName + ctx context.Context + ) + + BeforeEach(func() { + ctx = context.Background() + typeNamespacedName = types.NamespacedName{ + Name: "scaling-test-fs", + Namespace: "default", + } + + featureStore = &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{ + Name: typeNamespacedName.Name, + Namespace: typeNamespacedName.Namespace, + }, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "scalingproject", + Services: &feastdevv1.FeatureStoreServices{ + OnlineStore: &feastdevv1.OnlineStore{ + Server: &feastdevv1.ServerConfigs{ + ContainerConfigs: feastdevv1.ContainerConfigs{ + DefaultCtrConfigs: feastdevv1.DefaultCtrConfigs{ + Image: ptr.To("test-image"), + }, + }, + }, + Persistence: &feastdevv1.OnlineStorePersistence{ + DBPersistence: &feastdevv1.OnlineStoreDBStorePersistence{ + Type: "redis", + SecretRef: corev1.LocalObjectReference{ + Name: "redis-secret", + }, + }, + }, + }, + Registry: &feastdevv1.Registry{ + Local: &feastdevv1.LocalRegistryConfig{ + Server: &feastdevv1.RegistryServerConfigs{ + ServerConfigs: feastdevv1.ServerConfigs{ + ContainerConfigs: feastdevv1.ContainerConfigs{ + DefaultCtrConfigs: feastdevv1.DefaultCtrConfigs{ + Image: ptr.To("test-image"), + }, + }, + }, + GRPC: ptr.To(true), + }, + Persistence: &feastdevv1.RegistryPersistence{ + DBPersistence: &feastdevv1.RegistryDBStorePersistence{ + Type: "sql", + SecretRef: corev1.LocalObjectReference{ + Name: "registry-secret", + }, + }, + }, + }, + }, + }, + }, + } + + Expect(k8sClient.Create(ctx, featureStore)).To(Succeed()) + applySpecToStatus(featureStore) + + feast = &FeastServices{ + Handler: handler.FeastHandler{ + Client: k8sClient, + Context: ctx, + Scheme: k8sClient.Scheme(), + FeatureStore: featureStore, + }, + } + }) + + AfterEach(func() { + Expect(k8sClient.Delete(ctx, featureStore)).To(Succeed()) + }) + + Describe("isScalingEnabled", func() { + It("should return false when no scaling config is present", func() { + Expect(isScalingEnabled(featureStore)).To(BeFalse()) + }) + + It("should return false when replicas=1", func() { + featureStore.Status.Applied.Replicas = ptr.To(int32(1)) + Expect(isScalingEnabled(featureStore)).To(BeFalse()) + }) + + It("should return true when replicas > 1", func() { + featureStore.Status.Applied.Replicas = ptr.To(int32(3)) + Expect(isScalingEnabled(featureStore)).To(BeTrue()) + }) + + It("should return true when autoscaling is configured", func() { + featureStore.Status.Applied.Services.Scaling = &feastdevv1.ScalingConfig{ + Autoscaling: &feastdevv1.AutoscalingConfig{ + MaxReplicas: 5, + }, + } + Expect(isScalingEnabled(featureStore)).To(BeTrue()) + }) + }) + + Describe("CEL admission validation rejects invalid scaling configurations", func() { + dbOnlineStore := &feastdevv1.OnlineStore{ + Persistence: &feastdevv1.OnlineStorePersistence{ + DBPersistence: &feastdevv1.OnlineStoreDBStorePersistence{ + Type: "redis", + SecretRef: corev1.LocalObjectReference{Name: "redis-secret"}, + }, + }, + } + + dbRegistry := &feastdevv1.Registry{ + Local: &feastdevv1.LocalRegistryConfig{ + Persistence: &feastdevv1.RegistryPersistence{ + DBPersistence: &feastdevv1.RegistryDBStorePersistence{ + Type: "sql", + SecretRef: corev1.LocalObjectReference{Name: "registry-secret"}, + }, + }, + }, + } + + It("should accept scaling with full DB persistence", func() { + fs := &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{Name: "cel-valid-db", Namespace: "default"}, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "celtest", + Replicas: ptr.To(int32(3)), + Services: &feastdevv1.FeatureStoreServices{ + OnlineStore: dbOnlineStore, + Registry: dbRegistry, + }, + }, + } + Expect(k8sClient.Create(ctx, fs)).To(Succeed()) + Expect(k8sClient.Delete(ctx, fs)).To(Succeed()) + }) + + It("should reject scaling when online store is missing (implicit file default)", func() { + fs := &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{Name: "cel-no-online", Namespace: "default"}, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "celtest", + Replicas: ptr.To(int32(3)), + Services: &feastdevv1.FeatureStoreServices{ + Registry: dbRegistry, + }, + }, + } + err := k8sClient.Create(ctx, fs) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("online store")) + }) + + It("should reject scaling when online store uses file persistence", func() { + fs := &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{Name: "cel-file-online", Namespace: "default"}, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "celtest", + Replicas: ptr.To(int32(3)), + Services: &feastdevv1.FeatureStoreServices{ + OnlineStore: &feastdevv1.OnlineStore{ + Persistence: &feastdevv1.OnlineStorePersistence{ + FilePersistence: &feastdevv1.OnlineStoreFilePersistence{ + Path: "/data/online.db", + }, + }, + }, + Registry: dbRegistry, + }, + }, + } + err := k8sClient.Create(ctx, fs) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("online store")) + }) + + It("should reject scaling when offline store uses file persistence", func() { + fs := &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{Name: "cel-file-offline", Namespace: "default"}, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "celtest", + Replicas: ptr.To(int32(3)), + Services: &feastdevv1.FeatureStoreServices{ + OnlineStore: dbOnlineStore, + Registry: dbRegistry, + OfflineStore: &feastdevv1.OfflineStore{ + Persistence: &feastdevv1.OfflineStorePersistence{ + FilePersistence: &feastdevv1.OfflineStoreFilePersistence{ + Type: "duckdb", + }, + }, + }, + }, + }, + } + err := k8sClient.Create(ctx, fs) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("offline store")) + }) + + It("should reject scaling when no registry is configured (implicit file default)", func() { + fs := &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{Name: "cel-no-registry", Namespace: "default"}, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "celtest", + Replicas: ptr.To(int32(3)), + Services: &feastdevv1.FeatureStoreServices{ + OnlineStore: dbOnlineStore, + }, + }, + } + err := k8sClient.Create(ctx, fs) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("registry")) + }) + + It("should reject scaling when registry uses file persistence", func() { + fs := &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{Name: "cel-file-registry", Namespace: "default"}, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "celtest", + Replicas: ptr.To(int32(3)), + Services: &feastdevv1.FeatureStoreServices{ + OnlineStore: dbOnlineStore, + Registry: &feastdevv1.Registry{ + Local: &feastdevv1.LocalRegistryConfig{ + Persistence: &feastdevv1.RegistryPersistence{ + FilePersistence: &feastdevv1.RegistryFilePersistence{ + Path: "/data/registry.db", + }, + }, + }, + }, + }, + }, + } + err := k8sClient.Create(ctx, fs) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("registry")) + }) + + It("should accept scaling with S3-backed registry", func() { + fs := &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{Name: "cel-s3-registry", Namespace: "default"}, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "celtest", + Replicas: ptr.To(int32(3)), + Services: &feastdevv1.FeatureStoreServices{ + OnlineStore: dbOnlineStore, + Registry: &feastdevv1.Registry{ + Local: &feastdevv1.LocalRegistryConfig{ + Persistence: &feastdevv1.RegistryPersistence{ + FilePersistence: &feastdevv1.RegistryFilePersistence{ + Path: "s3://my-bucket/registry.db", + }, + }, + }, + }, + }, + }, + } + Expect(k8sClient.Create(ctx, fs)).To(Succeed()) + Expect(k8sClient.Delete(ctx, fs)).To(Succeed()) + }) + + It("should accept scaling with GS-backed registry", func() { + fs := &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{Name: "cel-gs-registry", Namespace: "default"}, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "celtest", + Replicas: ptr.To(int32(3)), + Services: &feastdevv1.FeatureStoreServices{ + OnlineStore: dbOnlineStore, + Registry: &feastdevv1.Registry{ + Local: &feastdevv1.LocalRegistryConfig{ + Persistence: &feastdevv1.RegistryPersistence{ + FilePersistence: &feastdevv1.RegistryFilePersistence{ + Path: "gs://my-bucket/registry.db", + }, + }, + }, + }, + }, + }, + } + Expect(k8sClient.Create(ctx, fs)).To(Succeed()) + Expect(k8sClient.Delete(ctx, fs)).To(Succeed()) + }) + + It("should accept scaling with remote registry", func() { + fs := &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{Name: "cel-remote-reg", Namespace: "default"}, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "celtest", + Replicas: ptr.To(int32(3)), + Services: &feastdevv1.FeatureStoreServices{ + OnlineStore: dbOnlineStore, + Registry: &feastdevv1.Registry{ + Remote: &feastdevv1.RemoteRegistryConfig{ + Hostname: ptr.To("registry.example.com:80"), + }, + }, + }, + }, + } + Expect(k8sClient.Create(ctx, fs)).To(Succeed()) + Expect(k8sClient.Delete(ctx, fs)).To(Succeed()) + }) + + It("should accept file persistence when replicas is 1", func() { + fs := &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{Name: "cel-rep1-file", Namespace: "default"}, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "celtest", + Replicas: ptr.To(int32(1)), + }, + } + Expect(k8sClient.Create(ctx, fs)).To(Succeed()) + Expect(k8sClient.Delete(ctx, fs)).To(Succeed()) + }) + + It("should accept file persistence when no scaling is configured", func() { + fs := &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{Name: "cel-no-scaling", Namespace: "default"}, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "celtest", + }, + } + Expect(k8sClient.Create(ctx, fs)).To(Succeed()) + Expect(k8sClient.Delete(ctx, fs)).To(Succeed()) + }) + + It("should reject autoscaling without DB online store", func() { + fs := &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{Name: "cel-hpa-no-db", Namespace: "default"}, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "celtest", + Services: &feastdevv1.FeatureStoreServices{ + Scaling: &feastdevv1.ScalingConfig{ + Autoscaling: &feastdevv1.AutoscalingConfig{MaxReplicas: 5}, + }, + Registry: dbRegistry, + }, + }, + } + err := k8sClient.Create(ctx, fs) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("online store")) + }) + + It("should reject scaling when online store has no persistence configured", func() { + fs := &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{Name: "cel-online-nop", Namespace: "default"}, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "celtest", + Replicas: ptr.To(int32(3)), + Services: &feastdevv1.FeatureStoreServices{ + OnlineStore: &feastdevv1.OnlineStore{}, + Registry: dbRegistry, + }, + }, + } + err := k8sClient.Create(ctx, fs) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("online store")) + }) + + It("should reject replicas and autoscaling set simultaneously", func() { + fs := &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{Name: "cel-mutual-excl", Namespace: "default"}, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "celtest", + Replicas: ptr.To(int32(3)), + Services: &feastdevv1.FeatureStoreServices{ + Scaling: &feastdevv1.ScalingConfig{ + Autoscaling: &feastdevv1.AutoscalingConfig{MaxReplicas: 5}, + }, + OnlineStore: dbOnlineStore, + Registry: dbRegistry, + }, + }, + } + err := k8sClient.Create(ctx, fs) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("mutually exclusive")) + }) + }) + + Describe("getDesiredReplicas", func() { + It("should return 1 when no explicit replicas are configured (default)", func() { + replicas := feast.getDesiredReplicas() + Expect(replicas).NotTo(BeNil()) + Expect(*replicas).To(Equal(int32(1))) + }) + + It("should return static replicas when configured", func() { + featureStore.Status.Applied.Replicas = ptr.To(int32(3)) + replicas := feast.getDesiredReplicas() + Expect(replicas).NotTo(BeNil()) + Expect(*replicas).To(Equal(int32(3))) + }) + + It("should return nil when autoscaling is configured (HPA manages replicas)", func() { + featureStore.Status.Applied.Services.Scaling = &feastdevv1.ScalingConfig{ + Autoscaling: &feastdevv1.AutoscalingConfig{ + MaxReplicas: 5, + }, + } + Expect(feast.getDesiredReplicas()).To(BeNil()) + }) + }) + + Describe("Deployment Strategy", func() { + It("should default to Recreate when no scaling is configured", func() { + Expect(feast.ApplyDefaults()).To(Succeed()) + strategy := feast.getDeploymentStrategy() + Expect(strategy.Type).To(Equal(appsv1.RecreateDeploymentStrategyType)) + }) + + It("should default to RollingUpdate when scaling is enabled via replicas", func() { + featureStore.Status.Applied.Replicas = ptr.To(int32(3)) + strategy := feast.getDeploymentStrategy() + Expect(strategy.Type).To(Equal(appsv1.RollingUpdateDeploymentStrategyType)) + }) + + It("should respect user-defined strategy even with scaling", func() { + featureStore.Status.Applied.Replicas = ptr.To(int32(3)) + featureStore.Status.Applied.Services.DeploymentStrategy = &appsv1.DeploymentStrategy{ + Type: appsv1.RecreateDeploymentStrategyType, + } + strategy := feast.getDeploymentStrategy() + Expect(strategy.Type).To(Equal(appsv1.RecreateDeploymentStrategyType)) + }) + }) + + Describe("setDeployment with scaling", func() { + setFilePersistence := func() { + featureStore.Status.Applied.Services.OnlineStore = &feastdevv1.OnlineStore{ + Server: &feastdevv1.ServerConfigs{ + ContainerConfigs: feastdevv1.ContainerConfigs{ + DefaultCtrConfigs: feastdevv1.DefaultCtrConfigs{ + Image: ptr.To("test-image"), + }, + }, + }, + Persistence: &feastdevv1.OnlineStorePersistence{ + FilePersistence: &feastdevv1.OnlineStoreFilePersistence{ + Path: "/feast-data/online.db", + }, + }, + } + featureStore.Status.Applied.Services.Registry = &feastdevv1.Registry{ + Local: &feastdevv1.LocalRegistryConfig{ + Server: &feastdevv1.RegistryServerConfigs{ + ServerConfigs: feastdevv1.ServerConfigs{ + ContainerConfigs: feastdevv1.ContainerConfigs{ + DefaultCtrConfigs: feastdevv1.DefaultCtrConfigs{ + Image: ptr.To("test-image"), + }, + }, + }, + GRPC: ptr.To(true), + }, + Persistence: &feastdevv1.RegistryPersistence{ + FilePersistence: &feastdevv1.RegistryFilePersistence{ + Path: "/feast-data/registry.db", + }, + }, + }, + } + } + + It("should set static replicas on the deployment", func() { + setFilePersistence() + featureStore.Status.Applied.Replicas = ptr.To(int32(3)) + + deployment := feast.initFeastDeploy() + Expect(feast.setDeployment(deployment)).To(Succeed()) + Expect(deployment.Spec.Replicas).NotTo(BeNil()) + Expect(*deployment.Spec.Replicas).To(Equal(int32(3))) + }) + + It("should preserve existing replicas when autoscaling is configured", func() { + setFilePersistence() + featureStore.Status.Applied.Services.Scaling = &feastdevv1.ScalingConfig{ + Autoscaling: &feastdevv1.AutoscalingConfig{ + MaxReplicas: 5, + }, + } + + deployment := feast.initFeastDeploy() + existing := int32(4) + deployment.Spec.Replicas = &existing + Expect(feast.setDeployment(deployment)).To(Succeed()) + Expect(deployment.Spec.Replicas).NotTo(BeNil()) + Expect(*deployment.Spec.Replicas).To(Equal(int32(4))) + }) + + It("should set default replicas=1 when no explicit scaling is configured", func() { + setFilePersistence() + Expect(k8sClient.Status().Update(ctx, featureStore)).To(Succeed()) + feast.refreshFeatureStore(ctx, typeNamespacedName) + + deployment := feast.initFeastDeploy() + Expect(feast.setDeployment(deployment)).To(Succeed()) + Expect(deployment.Spec.Replicas).NotTo(BeNil()) + Expect(*deployment.Spec.Replicas).To(Equal(int32(1))) + }) + }) + + Describe("HPA Configuration", func() { + It("should build an HPA apply config with default CPU metrics", func() { + featureStore.Status.Applied.Services.Scaling = &feastdevv1.ScalingConfig{ + Autoscaling: &feastdevv1.AutoscalingConfig{ + MaxReplicas: 10, + }, + } + + hpa := feast.buildHPAApplyConfig() + Expect(*hpa.Spec.MaxReplicas).To(Equal(int32(10))) + Expect(*hpa.Spec.MinReplicas).To(Equal(int32(1))) + Expect(hpa.Spec.Metrics).To(HaveLen(1)) + Expect(*hpa.Spec.Metrics[0].Resource.Name).To(Equal(corev1.ResourceCPU)) + }) + + It("should build an HPA apply config with custom min replicas", func() { + featureStore.Status.Applied.Services.Scaling = &feastdevv1.ScalingConfig{ + Autoscaling: &feastdevv1.AutoscalingConfig{ + MinReplicas: ptr.To(int32(2)), + MaxReplicas: 10, + }, + } + + hpa := feast.buildHPAApplyConfig() + Expect(*hpa.Spec.MinReplicas).To(Equal(int32(2))) + Expect(*hpa.Spec.MaxReplicas).To(Equal(int32(10))) + }) + + It("should set correct scale target reference", func() { + featureStore.Status.Applied.Services.Scaling = &feastdevv1.ScalingConfig{ + Autoscaling: &feastdevv1.AutoscalingConfig{ + MaxReplicas: 5, + }, + } + + hpa := feast.buildHPAApplyConfig() + Expect(*hpa.Spec.ScaleTargetRef.APIVersion).To(Equal("apps/v1")) + Expect(*hpa.Spec.ScaleTargetRef.Kind).To(Equal("Deployment")) + Expect(*hpa.Spec.ScaleTargetRef.Name).To(Equal(GetFeastName(featureStore))) + }) + + It("should set TypeMeta and owner reference for SSA", func() { + featureStore.Status.Applied.Services.Scaling = &feastdevv1.ScalingConfig{ + Autoscaling: &feastdevv1.AutoscalingConfig{ + MaxReplicas: 5, + }, + } + + hpa := feast.buildHPAApplyConfig() + Expect(*hpa.Kind).To(Equal("HorizontalPodAutoscaler")) + Expect(*hpa.APIVersion).To(Equal("autoscaling/v2")) + Expect(hpa.OwnerReferences).To(HaveLen(1)) + Expect(*hpa.OwnerReferences[0].Name).To(Equal(featureStore.Name)) + Expect(*hpa.OwnerReferences[0].Controller).To(BeTrue()) + }) + + It("should convert custom metrics via JSON round-trip", func() { + customMetrics := []autoscalingv2.MetricSpec{ + { + Type: autoscalingv2.ResourceMetricSourceType, + Resource: &autoscalingv2.ResourceMetricSource{ + Name: corev1.ResourceMemory, + Target: autoscalingv2.MetricTarget{ + Type: autoscalingv2.UtilizationMetricType, + AverageUtilization: ptr.To(int32(75)), + }, + }, + }, + } + featureStore.Status.Applied.Services.Scaling = &feastdevv1.ScalingConfig{ + Autoscaling: &feastdevv1.AutoscalingConfig{ + MaxReplicas: 10, + Metrics: customMetrics, + }, + } + + hpa := feast.buildHPAApplyConfig() + Expect(hpa.Spec.Metrics).To(HaveLen(1)) + Expect(*hpa.Spec.Metrics[0].Resource.Name).To(Equal(corev1.ResourceMemory)) + Expect(*hpa.Spec.Metrics[0].Resource.Target.AverageUtilization).To(Equal(int32(75))) + }) + }) + + Describe("PDB Configuration", func() { + It("should build a PDB apply config with maxUnavailable", func() { + maxUnavail := intstr.FromInt(1) + featureStore.Status.Applied.Services.PodDisruptionBudgets = &feastdevv1.PDBConfig{ + MaxUnavailable: &maxUnavail, + } + featureStore.Status.Applied.Replicas = ptr.To(int32(3)) + + pdb := feast.buildPDBApplyConfig() + Expect(*pdb.Kind).To(Equal("PodDisruptionBudget")) + Expect(*pdb.APIVersion).To(Equal("policy/v1")) + Expect(pdb.Spec.MaxUnavailable).NotTo(BeNil()) + Expect(pdb.Spec.MaxUnavailable.IntValue()).To(Equal(1)) + Expect(pdb.Spec.MinAvailable).To(BeNil()) + Expect(pdb.Spec.Selector.MatchLabels).To(HaveKeyWithValue(NameLabelKey, featureStore.Name)) + }) + + It("should build a PDB apply config with minAvailable", func() { + minAvail := intstr.FromString("50%") + featureStore.Status.Applied.Services.PodDisruptionBudgets = &feastdevv1.PDBConfig{ + MinAvailable: &minAvail, + } + featureStore.Status.Applied.Replicas = ptr.To(int32(3)) + + pdb := feast.buildPDBApplyConfig() + Expect(pdb.Spec.MinAvailable).NotTo(BeNil()) + Expect(pdb.Spec.MinAvailable.String()).To(Equal("50%")) + Expect(pdb.Spec.MaxUnavailable).To(BeNil()) + }) + + It("should set owner reference on PDB for SSA", func() { + maxUnavail := intstr.FromInt(1) + featureStore.Status.Applied.Services.PodDisruptionBudgets = &feastdevv1.PDBConfig{ + MaxUnavailable: &maxUnavail, + } + featureStore.Status.Applied.Replicas = ptr.To(int32(3)) + + pdb := feast.buildPDBApplyConfig() + Expect(pdb.OwnerReferences).To(HaveLen(1)) + Expect(*pdb.OwnerReferences[0].Name).To(Equal(featureStore.Name)) + Expect(*pdb.OwnerReferences[0].Controller).To(BeTrue()) + }) + }) + + Describe("CEL admission validation rejects invalid PDB configurations", func() { + dbOnlineStore := &feastdevv1.OnlineStore{ + Persistence: &feastdevv1.OnlineStorePersistence{ + DBPersistence: &feastdevv1.OnlineStoreDBStorePersistence{ + Type: "redis", + SecretRef: corev1.LocalObjectReference{Name: "redis-secret"}, + }, + }, + } + dbRegistry := &feastdevv1.Registry{ + Local: &feastdevv1.LocalRegistryConfig{ + Persistence: &feastdevv1.RegistryPersistence{ + DBPersistence: &feastdevv1.RegistryDBStorePersistence{ + Type: "sql", + SecretRef: corev1.LocalObjectReference{Name: "registry-secret"}, + }, + }, + }, + } + + It("should reject PDB with both minAvailable and maxUnavailable set", func() { + fs := &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{Name: "cel-pdb-both", Namespace: "default"}, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "celtest", + Replicas: ptr.To(int32(3)), + Services: &feastdevv1.FeatureStoreServices{ + OnlineStore: dbOnlineStore, + Registry: dbRegistry, + PodDisruptionBudgets: &feastdevv1.PDBConfig{ + MinAvailable: ptr.To(intstr.FromInt(1)), + MaxUnavailable: ptr.To(intstr.FromInt(1)), + }, + }, + }, + } + err := k8sClient.Create(ctx, fs) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("Exactly one of minAvailable or maxUnavailable")) + }) + + It("should reject PDB with neither minAvailable nor maxUnavailable set", func() { + fs := &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{Name: "cel-pdb-none", Namespace: "default"}, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "celtest", + Replicas: ptr.To(int32(3)), + Services: &feastdevv1.FeatureStoreServices{ + OnlineStore: dbOnlineStore, + Registry: dbRegistry, + PodDisruptionBudgets: &feastdevv1.PDBConfig{}, + }, + }, + } + err := k8sClient.Create(ctx, fs) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("Exactly one of minAvailable or maxUnavailable")) + }) + + It("should accept PDB with only maxUnavailable", func() { + fs := &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{Name: "cel-pdb-maxu", Namespace: "default"}, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "celtest", + Replicas: ptr.To(int32(3)), + Services: &feastdevv1.FeatureStoreServices{ + OnlineStore: dbOnlineStore, + Registry: dbRegistry, + PodDisruptionBudgets: &feastdevv1.PDBConfig{ + MaxUnavailable: ptr.To(intstr.FromInt(1)), + }, + }, + }, + } + Expect(k8sClient.Create(ctx, fs)).To(Succeed()) + Expect(k8sClient.Delete(ctx, fs)).To(Succeed()) + }) + + It("should accept PDB with only minAvailable", func() { + fs := &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{Name: "cel-pdb-mina", Namespace: "default"}, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "celtest", + Replicas: ptr.To(int32(3)), + Services: &feastdevv1.FeatureStoreServices{ + OnlineStore: dbOnlineStore, + Registry: dbRegistry, + PodDisruptionBudgets: &feastdevv1.PDBConfig{ + MinAvailable: ptr.To(intstr.FromString("50%")), + }, + }, + }, + } + Expect(k8sClient.Create(ctx, fs)).To(Succeed()) + Expect(k8sClient.Delete(ctx, fs)).To(Succeed()) + }) + }) + + Describe("Topology Spread", func() { + It("should auto-inject soft zone constraint when replicas > 1 and no explicit constraints", func() { + featureStore.Status.Applied.Replicas = ptr.To(int32(3)) + + podSpec := &corev1.PodSpec{} + feast.applyTopologySpread(podSpec) + + Expect(podSpec.TopologySpreadConstraints).To(HaveLen(1)) + Expect(podSpec.TopologySpreadConstraints[0].TopologyKey).To(Equal("topology.kubernetes.io/zone")) + Expect(podSpec.TopologySpreadConstraints[0].WhenUnsatisfiable).To(Equal(corev1.ScheduleAnyway)) + Expect(podSpec.TopologySpreadConstraints[0].MaxSkew).To(Equal(int32(1))) + Expect(podSpec.TopologySpreadConstraints[0].LabelSelector.MatchLabels).To(HaveKeyWithValue(NameLabelKey, featureStore.Name)) + }) + + It("should auto-inject when autoscaling is configured", func() { + featureStore.Status.Applied.Services.Scaling = &feastdevv1.ScalingConfig{ + Autoscaling: &feastdevv1.AutoscalingConfig{MaxReplicas: 5}, + } + + podSpec := &corev1.PodSpec{} + feast.applyTopologySpread(podSpec) + + Expect(podSpec.TopologySpreadConstraints).To(HaveLen(1)) + Expect(podSpec.TopologySpreadConstraints[0].WhenUnsatisfiable).To(Equal(corev1.ScheduleAnyway)) + }) + + It("should not inject when replicas is 1 and no autoscaling", func() { + podSpec := &corev1.PodSpec{} + feast.applyTopologySpread(podSpec) + + Expect(podSpec.TopologySpreadConstraints).To(BeEmpty()) + }) + + It("should use user-provided constraints instead of defaults", func() { + featureStore.Status.Applied.Replicas = ptr.To(int32(3)) + featureStore.Status.Applied.Services.TopologySpreadConstraints = []corev1.TopologySpreadConstraint{{ + MaxSkew: 2, + TopologyKey: "kubernetes.io/hostname", + WhenUnsatisfiable: corev1.DoNotSchedule, + LabelSelector: metav1.SetAsLabelSelector(map[string]string{"custom": "label"}), + }} + + podSpec := &corev1.PodSpec{} + feast.applyTopologySpread(podSpec) + + Expect(podSpec.TopologySpreadConstraints).To(HaveLen(1)) + Expect(podSpec.TopologySpreadConstraints[0].TopologyKey).To(Equal("kubernetes.io/hostname")) + Expect(podSpec.TopologySpreadConstraints[0].WhenUnsatisfiable).To(Equal(corev1.DoNotSchedule)) + Expect(podSpec.TopologySpreadConstraints[0].MaxSkew).To(Equal(int32(2))) + }) + + It("should disable auto-injection when empty array is set", func() { + featureStore.Status.Applied.Replicas = ptr.To(int32(3)) + featureStore.Status.Applied.Services.TopologySpreadConstraints = []corev1.TopologySpreadConstraint{} + + podSpec := &corev1.PodSpec{} + feast.applyTopologySpread(podSpec) + + Expect(podSpec.TopologySpreadConstraints).To(BeEmpty()) + }) + }) + + Describe("Pod Anti-Affinity", func() { + It("should auto-inject soft node anti-affinity when replicas > 1", func() { + featureStore.Status.Applied.Replicas = ptr.To(int32(3)) + + podSpec := &corev1.PodSpec{} + feast.applyAffinity(podSpec) + + Expect(podSpec.Affinity).NotTo(BeNil()) + Expect(podSpec.Affinity.PodAntiAffinity).NotTo(BeNil()) + terms := podSpec.Affinity.PodAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution + Expect(terms).To(HaveLen(1)) + Expect(terms[0].Weight).To(Equal(int32(100))) + Expect(terms[0].PodAffinityTerm.TopologyKey).To(Equal("kubernetes.io/hostname")) + Expect(terms[0].PodAffinityTerm.LabelSelector.MatchLabels).To(HaveKeyWithValue(NameLabelKey, featureStore.Name)) + }) + + It("should auto-inject when autoscaling is configured", func() { + featureStore.Status.Applied.Services.Scaling = &feastdevv1.ScalingConfig{ + Autoscaling: &feastdevv1.AutoscalingConfig{MaxReplicas: 5}, + } + + podSpec := &corev1.PodSpec{} + feast.applyAffinity(podSpec) + + Expect(podSpec.Affinity).NotTo(BeNil()) + Expect(podSpec.Affinity.PodAntiAffinity).NotTo(BeNil()) + }) + + It("should not inject when replicas is 1 and no autoscaling", func() { + podSpec := &corev1.PodSpec{} + feast.applyAffinity(podSpec) + + Expect(podSpec.Affinity).To(BeNil()) + }) + + It("should use user-provided affinity instead of defaults", func() { + featureStore.Status.Applied.Replicas = ptr.To(int32(3)) + featureStore.Status.Applied.Services.Affinity = &corev1.Affinity{ + PodAntiAffinity: &corev1.PodAntiAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: []corev1.PodAffinityTerm{{ + TopologyKey: "kubernetes.io/hostname", + LabelSelector: metav1.SetAsLabelSelector(map[string]string{"custom": "label"}), + }}, + }, + } + + podSpec := &corev1.PodSpec{} + feast.applyAffinity(podSpec) + + Expect(podSpec.Affinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution).To(HaveLen(1)) + Expect(podSpec.Affinity.PodAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution).To(BeEmpty()) + Expect(podSpec.Affinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution[0].TopologyKey).To(Equal("kubernetes.io/hostname")) + }) + + It("should allow user to set node affinity alongside anti-affinity", func() { + featureStore.Status.Applied.Replicas = ptr.To(int32(3)) + featureStore.Status.Applied.Services.Affinity = &corev1.Affinity{ + NodeAffinity: &corev1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ + NodeSelectorTerms: []corev1.NodeSelectorTerm{{ + MatchExpressions: []corev1.NodeSelectorRequirement{{ + Key: "gpu", + Operator: corev1.NodeSelectorOpIn, + Values: []string{"true"}, + }}, + }}, + }, + }, + } + + podSpec := &corev1.PodSpec{} + feast.applyAffinity(podSpec) + + Expect(podSpec.Affinity.NodeAffinity).NotTo(BeNil()) + Expect(podSpec.Affinity.PodAntiAffinity).To(BeNil()) + }) + }) + + Describe("Scale sub-resource", func() { + newDBFeatureStore := func(name string) *feastdevv1.FeatureStore { + return &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: "default", + }, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "scaletest", + Services: &feastdevv1.FeatureStoreServices{ + OnlineStore: &feastdevv1.OnlineStore{ + Persistence: &feastdevv1.OnlineStorePersistence{ + DBPersistence: &feastdevv1.OnlineStoreDBStorePersistence{ + Type: "redis", + SecretRef: corev1.LocalObjectReference{Name: "redis-secret"}, + }, + }, + }, + Registry: &feastdevv1.Registry{ + Local: &feastdevv1.LocalRegistryConfig{ + Persistence: &feastdevv1.RegistryPersistence{ + DBPersistence: &feastdevv1.RegistryDBStorePersistence{ + Type: "sql", + SecretRef: corev1.LocalObjectReference{Name: "registry-secret"}, + }, + }, + }, + }, + }, + }, + } + } + + It("should allow scaling up via the scale sub-resource with DB persistence", func() { + fs := newDBFeatureStore("scale-sub-valid") + Expect(k8sClient.Create(ctx, fs)).To(Succeed()) + defer func() { Expect(k8sClient.Delete(ctx, fs)).To(Succeed()) }() + + scale := &autoscalingv1.Scale{} + Expect(k8sClient.SubResource("scale").Get(ctx, fs, scale)).To(Succeed()) + Expect(scale.Spec.Replicas).To(Equal(int32(1))) + + scale.Spec.Replicas = 3 + Expect(k8sClient.SubResource("scale").Update(ctx, fs, client.WithSubResourceBody(scale))).To(Succeed()) + + updated := &feastdevv1.FeatureStore{} + Expect(k8sClient.Get(ctx, types.NamespacedName{Name: fs.Name, Namespace: fs.Namespace}, updated)).To(Succeed()) + Expect(updated.Spec.Replicas).NotTo(BeNil()) + Expect(*updated.Spec.Replicas).To(Equal(int32(3))) + }) + + It("should reject scaling up via the scale sub-resource without DB persistence", func() { + fs := &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{ + Name: "scale-sub-reject", + Namespace: "default", + }, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "scaletest", + }, + } + Expect(k8sClient.Create(ctx, fs)).To(Succeed()) + defer func() { Expect(k8sClient.Delete(ctx, fs)).To(Succeed()) }() + + scale := &autoscalingv1.Scale{} + Expect(k8sClient.SubResource("scale").Get(ctx, fs, scale)).To(Succeed()) + + scale.Spec.Replicas = 3 + err := k8sClient.SubResource("scale").Update(ctx, fs, client.WithSubResourceBody(scale)) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("online store")) + }) + + It("should read the status replicas from the scale sub-resource", func() { + fs := newDBFeatureStore("scale-sub-status") + fs.Spec.Replicas = ptr.To(int32(2)) + Expect(k8sClient.Create(ctx, fs)).To(Succeed()) + defer func() { Expect(k8sClient.Delete(ctx, fs)).To(Succeed()) }() + + fs.Status.Replicas = 2 + fs.Status.Applied.FeastProject = fs.Spec.FeastProject + Expect(k8sClient.Status().Update(ctx, fs)).To(Succeed()) + + scale := &autoscalingv1.Scale{} + Expect(k8sClient.SubResource("scale").Get(ctx, fs, scale)).To(Succeed()) + Expect(scale.Status.Replicas).To(Equal(int32(2))) + Expect(scale.Spec.Replicas).To(Equal(int32(2))) + }) + }) +}) diff --git a/infra/feast-operator/internal/controller/services/service_monitor.go b/infra/feast-operator/internal/controller/services/service_monitor.go new file mode 100644 index 00000000000..8de4d131289 --- /dev/null +++ b/infra/feast-operator/internal/controller/services/service_monitor.go @@ -0,0 +1,117 @@ +/* +Copyright 2026 Feast Community. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package services + +import ( + "encoding/json" + + feastdevv1 "github.com/feast-dev/feast/infra/feast-operator/api/v1" + monitoringv1apply "github.com/prometheus-operator/prometheus-operator/pkg/client/applyconfiguration/monitoring/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + metav1apply "k8s.io/client-go/applyconfigurations/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" +) + +var serviceMonitorGVK = schema.GroupVersionKind{ + Group: "monitoring.coreos.com", + Version: "v1", + Kind: "ServiceMonitor", +} + +// createOrDeleteServiceMonitor reconciles the ServiceMonitor for the +// FeatureStore's online store metrics endpoint using Server-Side Apply. +// When the Prometheus Operator CRD is not present in the cluster, this is +// a no-op. When metrics are enabled on the online store, a ServiceMonitor +// is applied; otherwise any existing ServiceMonitor is deleted. +func (feast *FeastServices) createOrDeleteServiceMonitor() error { + if !hasServiceMonitorCRD { + return nil + } + + if feast.isOnlineStore() && feast.isMetricsEnabled(OnlineFeastType) { + return feast.applyServiceMonitor() + } + + return feast.deleteServiceMonitor() +} + +func (feast *FeastServices) applyServiceMonitor() error { + smApply := feast.buildServiceMonitorApplyConfig() + data, err := json.Marshal(smApply) + if err != nil { + return err + } + + sm := feast.initServiceMonitor() + logger := log.FromContext(feast.Handler.Context) + if err := feast.Handler.Client.Patch(feast.Handler.Context, sm, + client.RawPatch(types.ApplyPatchType, data), + client.FieldOwner(fieldManager), client.ForceOwnership); err != nil { + return err + } + logger.Info("Successfully applied", "ServiceMonitor", sm.GetName()) + + return nil +} + +func (feast *FeastServices) deleteServiceMonitor() error { + sm := feast.initServiceMonitor() + return feast.Handler.DeleteOwnedFeastObj(sm) +} + +func (feast *FeastServices) initServiceMonitor() *unstructured.Unstructured { + sm := &unstructured.Unstructured{} + sm.SetGroupVersionKind(serviceMonitorGVK) + sm.SetName(feast.GetFeastServiceName(OnlineFeastType)) + sm.SetNamespace(feast.Handler.FeatureStore.Namespace) + return sm +} + +// buildServiceMonitorApplyConfig constructs the fully desired ServiceMonitor +// state for Server-Side Apply. +func (feast *FeastServices) buildServiceMonitorApplyConfig() *monitoringv1apply.ServiceMonitorApplyConfiguration { + cr := feast.Handler.FeatureStore + objMeta := feast.GetObjectMetaType(OnlineFeastType) + + return monitoringv1apply.ServiceMonitor(objMeta.Name, objMeta.Namespace). + WithLabels(feast.getFeastTypeLabels(OnlineFeastType)). + WithOwnerReferences( + metav1apply.OwnerReference(). + WithAPIVersion(feastdevv1.GroupVersion.String()). + WithKind("FeatureStore"). + WithName(cr.Name). + WithUID(cr.UID). + WithController(true). + WithBlockOwnerDeletion(true), + ). + WithSpec(monitoringv1apply.ServiceMonitorSpec(). + WithEndpoints( + monitoringv1apply.Endpoint(). + WithPort("metrics"). + WithPath("/metrics"), + ). + WithSelector(metav1apply.LabelSelector(). + WithMatchLabels(map[string]string{ + NameLabelKey: cr.Name, + ServiceTypeLabelKey: string(OnlineFeastType), + }), + ), + ) +} diff --git a/infra/feast-operator/internal/controller/services/service_monitor_test.go b/infra/feast-operator/internal/controller/services/service_monitor_test.go new file mode 100644 index 00000000000..f6e7f87ebf9 --- /dev/null +++ b/infra/feast-operator/internal/controller/services/service_monitor_test.go @@ -0,0 +1,168 @@ +/* +Copyright 2026 Feast Community. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package services + +import ( + "context" + + feastdevv1 "github.com/feast-dev/feast/infra/feast-operator/api/v1" + "github.com/feast-dev/feast/infra/feast-operator/internal/controller/handler" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" +) + +var _ = Describe("ServiceMonitor", func() { + var ( + featureStore *feastdevv1.FeatureStore + feast *FeastServices + typeNamespacedName types.NamespacedName + ctx context.Context + ) + + BeforeEach(func() { + ctx = context.Background() + typeNamespacedName = types.NamespacedName{ + Name: "sm-test-fs", + Namespace: "default", + } + + featureStore = &feastdevv1.FeatureStore{ + ObjectMeta: metav1.ObjectMeta{ + Name: typeNamespacedName.Name, + Namespace: typeNamespacedName.Namespace, + }, + Spec: feastdevv1.FeatureStoreSpec{ + FeastProject: "smtestproject", + Services: &feastdevv1.FeatureStoreServices{ + OnlineStore: &feastdevv1.OnlineStore{ + Server: &feastdevv1.ServerConfigs{ + ContainerConfigs: feastdevv1.ContainerConfigs{ + DefaultCtrConfigs: feastdevv1.DefaultCtrConfigs{ + Image: ptr.To("test-image"), + }, + }, + }, + }, + Registry: &feastdevv1.Registry{ + Local: &feastdevv1.LocalRegistryConfig{ + Server: &feastdevv1.RegistryServerConfigs{ + ServerConfigs: feastdevv1.ServerConfigs{ + ContainerConfigs: feastdevv1.ContainerConfigs{ + DefaultCtrConfigs: feastdevv1.DefaultCtrConfigs{ + Image: ptr.To("test-image"), + }, + }, + }, + GRPC: ptr.To(true), + }, + }, + }, + }, + }, + } + + Expect(k8sClient.Create(ctx, featureStore)).To(Succeed()) + + feast = &FeastServices{ + Handler: handler.FeastHandler{ + Client: k8sClient, + Context: ctx, + Scheme: k8sClient.Scheme(), + FeatureStore: featureStore, + }, + } + + Expect(feast.ApplyDefaults()).To(Succeed()) + applySpecToStatus(featureStore) + feast.refreshFeatureStore(ctx, typeNamespacedName) + }) + + AfterEach(func() { + testSetHasServiceMonitorCRD(false) + Expect(k8sClient.Delete(ctx, featureStore)).To(Succeed()) + }) + + Describe("initServiceMonitor", func() { + It("should create an unstructured ServiceMonitor with correct GVK and name", func() { + sm := feast.initServiceMonitor() + Expect(sm).NotTo(BeNil()) + Expect(sm.GetKind()).To(Equal("ServiceMonitor")) + Expect(sm.GetAPIVersion()).To(Equal("monitoring.coreos.com/v1")) + Expect(sm.GetName()).To(Equal(feast.GetFeastServiceName(OnlineFeastType))) + Expect(sm.GetNamespace()).To(Equal(featureStore.Namespace)) + }) + }) + + Describe("buildServiceMonitorApplyConfig", func() { + It("should build the correct SSA payload with labels, endpoints, selector, and owner reference", func() { + sm := feast.buildServiceMonitorApplyConfig() + + Expect(*sm.APIVersion).To(Equal("monitoring.coreos.com/v1")) + Expect(*sm.Kind).To(Equal("ServiceMonitor")) + Expect(*sm.Name).To(Equal(feast.GetFeastServiceName(OnlineFeastType))) + Expect(*sm.Namespace).To(Equal(featureStore.Namespace)) + + Expect(sm.Labels).To(HaveKeyWithValue(NameLabelKey, featureStore.Name)) + Expect(sm.Labels).To(HaveKeyWithValue(ServiceTypeLabelKey, string(OnlineFeastType))) + + Expect(sm.OwnerReferences).To(HaveLen(1)) + ownerRef := sm.OwnerReferences[0] + Expect(*ownerRef.APIVersion).To(Equal(feastdevv1.GroupVersion.String())) + Expect(*ownerRef.Kind).To(Equal("FeatureStore")) + Expect(*ownerRef.Name).To(Equal(featureStore.Name)) + Expect(*ownerRef.Controller).To(BeTrue()) + Expect(*ownerRef.BlockOwnerDeletion).To(BeTrue()) + + Expect(sm.Spec).NotTo(BeNil()) + Expect(sm.Spec.Endpoints).To(HaveLen(1)) + Expect(*sm.Spec.Endpoints[0].Port).To(Equal("metrics")) + Expect(*sm.Spec.Endpoints[0].Path).To(Equal("/metrics")) + + Expect(sm.Spec.Selector).NotTo(BeNil()) + Expect(sm.Spec.Selector.MatchLabels).To(HaveKeyWithValue(NameLabelKey, featureStore.Name)) + Expect(sm.Spec.Selector.MatchLabels).To(HaveKeyWithValue(ServiceTypeLabelKey, string(OnlineFeastType))) + }) + }) + + Describe("createOrDeleteServiceMonitor", func() { + It("should be a no-op when ServiceMonitor CRD is not available", func() { + testSetHasServiceMonitorCRD(false) + Expect(feast.createOrDeleteServiceMonitor()).To(Succeed()) + }) + + It("should not error when metrics is not enabled and CRD is unavailable", func() { + testSetHasServiceMonitorCRD(false) + featureStore.Status.Applied.Services.OnlineStore.Server.Metrics = ptr.To(false) + Expect(feast.createOrDeleteServiceMonitor()).To(Succeed()) + }) + }) + + Describe("HasServiceMonitorCRD", func() { + It("should return false by default", func() { + testSetHasServiceMonitorCRD(false) + Expect(HasServiceMonitorCRD()).To(BeFalse()) + }) + + It("should return true when set", func() { + testSetHasServiceMonitorCRD(true) + Expect(HasServiceMonitorCRD()).To(BeTrue()) + }) + }) +}) diff --git a/infra/feast-operator/internal/controller/services/services.go b/infra/feast-operator/internal/controller/services/services.go index 6771e9498af..d8ff12a9348 100644 --- a/infra/feast-operator/internal/controller/services/services.go +++ b/infra/feast-operator/internal/controller/services/services.go @@ -71,14 +71,48 @@ func (feast *FeastServices) Deploy() error { _ = feast.Handler.DeleteOwnedFeastObj(feast.initCaConfigMap()) } + if err := feast.reconcileServices(); err != nil { + return err + } + + if err := feast.createServiceAccount(); err != nil { + return err + } + if err := feast.createDeployment(); err != nil { + return err + } + if err := feast.createOrDeleteHPA(); err != nil { + return err + } + if err := feast.applyOrDeletePDB(); err != nil { + return err + } + if err := feast.deployClient(); err != nil { + return err + } + if err := feast.deployNamespaceRegistry(); err != nil { + return err + } + if err := feast.deployCronJob(); err != nil { + return err + } + if err := feast.createOrDeleteServiceMonitor(); err != nil { + return err + } + + return nil +} + +// reconcileServices validates persistence and deploys or removes each feast +// service type based on the applied spec. +func (feast *FeastServices) reconcileServices() error { services := feast.Handler.FeatureStore.Status.Applied.Services + if feast.isOfflineStore() { - err := feast.validateOfflineStorePersistence(services.OfflineStore.Persistence) - if err != nil { + if err := feast.validateOfflineStorePersistence(services.OfflineStore.Persistence); err != nil { return err } - - if err = feast.deployFeastServiceByType(OfflineFeastType); err != nil { + if err := feast.deployFeastServiceByType(OfflineFeastType); err != nil { return err } } else { @@ -88,12 +122,10 @@ func (feast *FeastServices) Deploy() error { } if feast.isOnlineStore() { - err := feast.validateOnlineStorePersistence(services.OnlineStore.Persistence) - if err != nil { + if err := feast.validateOnlineStorePersistence(services.OnlineStore.Persistence); err != nil { return err } - - if err = feast.deployFeastServiceByType(OnlineFeastType); err != nil { + if err := feast.deployFeastServiceByType(OnlineFeastType); err != nil { return err } } else { @@ -103,12 +135,10 @@ func (feast *FeastServices) Deploy() error { } if feast.isLocalRegistry() { - err := feast.validateRegistryPersistence(services.Registry.Local.Persistence) - if err != nil { + if err := feast.validateRegistryPersistence(services.Registry.Local.Persistence); err != nil { return err } - - if err = feast.deployFeastServiceByType(RegistryFeastType); err != nil { + if err := feast.deployFeastServiceByType(RegistryFeastType); err != nil { return err } } else { @@ -116,11 +146,12 @@ func (feast *FeastServices) Deploy() error { return err } } + if feast.isUiServer() { - if err = feast.deployFeastServiceByType(UIFeastType); err != nil { + if err := feast.deployFeastServiceByType(UIFeastType); err != nil { return err } - if err = feast.createRoute(UIFeastType); err != nil { + if err := feast.createRoute(UIFeastType); err != nil { return err } } else { @@ -132,22 +163,6 @@ func (feast *FeastServices) Deploy() error { } } - if err := feast.createServiceAccount(); err != nil { - return err - } - if err := feast.createDeployment(); err != nil { - return err - } - if err := feast.deployClient(); err != nil { - return err - } - if err := feast.deployNamespaceRegistry(); err != nil { - return err - } - if err := feast.deployCronJob(); err != nil { - return err - } - return nil } @@ -338,6 +353,8 @@ func (feast *FeastServices) createDeployment() error { logger.Info("Successfully reconciled", "Deployment", deploy.Name, "operation", op) } + feast.updateScalingStatus(deploy) + return nil } @@ -381,7 +398,14 @@ func (feast *FeastServices) createPVC(pvcCreate *feastdevv1.PvcCreate, feastType func (feast *FeastServices) setDeployment(deploy *appsv1.Deployment) error { cr := feast.Handler.FeatureStore + + // Determine replica count: + // - spec.replicas is set on the Deployment (defaults to 1) + // - When HPA is configured, replicas is left unset so the HPA controller manages it replicas := deploy.Spec.Replicas + if desired := feast.getDesiredReplicas(); desired != nil { + replicas = desired + } deploy.Labels = feast.getLabels() deploy.Spec = appsv1.DeploymentSpec{ @@ -390,7 +414,8 @@ func (feast *FeastServices) setDeployment(deploy *appsv1.Deployment) error { Strategy: feast.getDeploymentStrategy(), Template: corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Labels: deploy.GetLabels(), + Labels: deploy.GetLabels(), + Annotations: cr.Status.Applied.Services.PodAnnotations, }, Spec: corev1.PodSpec{ ServiceAccountName: feast.initFeastSA().Name, @@ -413,6 +438,8 @@ func (feast *FeastServices) setPod(podSpec *corev1.PodSpec) error { feast.mountEmptyDirVolumes(podSpec) feast.mountUserDefinedVolumes(podSpec) feast.applyNodeSelector(podSpec) + feast.applyTopologySpread(podSpec) + feast.applyAffinity(podSpec) return nil } @@ -635,6 +662,11 @@ func (feast *FeastServices) getDeploymentStrategy() appsv1.DeploymentStrategy { if feast.Handler.FeatureStore.Status.Applied.Services.DeploymentStrategy != nil { return *feast.Handler.FeatureStore.Status.Applied.Services.DeploymentStrategy } + if isScalingEnabled(feast.Handler.FeatureStore) { + return appsv1.DeploymentStrategy{ + Type: appsv1.RollingUpdateDeploymentStrategyType, + } + } return appsv1.DeploymentStrategy{ Type: appsv1.RecreateDeploymentStrategyType, } @@ -697,6 +729,35 @@ func (feast *FeastServices) setInitContainer(podSpec *corev1.PodSpec, fsYamlB64 "echo $" + TmpFeatureStoreYamlEnvVar + " | base64 -d \u003e " + featureRepoDir + "/feature_store.yaml;\necho \"Feast repo creation complete\";\n", } podSpec.InitContainers = append(podSpec.InitContainers, container) + + if applied.Services.RunFeastApplyOnInit != nil && *applied.Services.RunFeastApplyOnInit { + applyContainer := corev1.Container{ + Name: "feast-apply", + Image: getFeatureServerImage(), + Command: []string{"feast", "apply"}, + WorkingDir: featureRepoDir, + } + // feast apply needs DB/store connectivity, so inherit env, envFrom + // and volume mounts from all server container configs. + seen := map[string]bool{} + for _, feastType := range []FeastServiceType{RegistryFeastType, OnlineFeastType, OfflineFeastType} { + if serverConfigs := feast.getServerConfigs(feastType); serverConfigs != nil { + if serverConfigs.OptionalCtrConfigs.Env != nil { + applyContainer.Env = envOverride(applyContainer.Env, *serverConfigs.OptionalCtrConfigs.Env) + } + if serverConfigs.OptionalCtrConfigs.EnvFrom != nil { + applyContainer.EnvFrom = append(applyContainer.EnvFrom, *serverConfigs.OptionalCtrConfigs.EnvFrom...) + } + for _, vm := range feast.getVolumeMounts(feastType) { + if !seen[vm.MountPath] { + applyContainer.VolumeMounts = append(applyContainer.VolumeMounts, vm) + seen[vm.MountPath] = true + } + } + } + } + podSpec.InitContainers = append(podSpec.InitContainers, applyContainer) + } } } @@ -897,6 +958,54 @@ func (feast *FeastServices) applyNodeSelector(podSpec *corev1.PodSpec) { podSpec.NodeSelector = finalNodeSelector } +func (feast *FeastServices) applyTopologySpread(podSpec *corev1.PodSpec) { + cr := feast.Handler.FeatureStore + services := cr.Status.Applied.Services + + // User-provided explicit constraints take precedence (including empty array to disable) + if services != nil && services.TopologySpreadConstraints != nil { + podSpec.TopologySpreadConstraints = services.TopologySpreadConstraints + return + } + + if !isScalingEnabled(cr) { + return + } + + podSpec.TopologySpreadConstraints = []corev1.TopologySpreadConstraint{{ + MaxSkew: 1, + TopologyKey: "topology.kubernetes.io/zone", + WhenUnsatisfiable: corev1.ScheduleAnyway, + LabelSelector: metav1.SetAsLabelSelector(feast.getLabels()), + }} +} + +func (feast *FeastServices) applyAffinity(podSpec *corev1.PodSpec) { + cr := feast.Handler.FeatureStore + services := cr.Status.Applied.Services + + if services != nil && services.Affinity != nil { + podSpec.Affinity = services.Affinity + return + } + + if !isScalingEnabled(cr) { + return + } + + podSpec.Affinity = &corev1.Affinity{ + PodAntiAffinity: &corev1.PodAntiAffinity{ + PreferredDuringSchedulingIgnoredDuringExecution: []corev1.WeightedPodAffinityTerm{{ + Weight: 100, + PodAffinityTerm: corev1.PodAffinityTerm{ + TopologyKey: "kubernetes.io/hostname", + LabelSelector: metav1.SetAsLabelSelector(feast.getLabels()), + }, + }}, + }, + } +} + // mergeNodeSelectors merges existing and operator node selectors // Existing selectors are preserved, operator selectors can override existing keys func (feast *FeastServices) mergeNodeSelectors(existing, operator map[string]string) map[string]string { @@ -1046,9 +1155,6 @@ func (feast *FeastServices) getRemoteRegistryFeastHandler() (*FeastServices, err } return nil, err } - if feast.Handler.FeatureStore.Status.Applied.FeastProject != remoteFeastObj.Status.Applied.FeastProject { - return nil, errors.New("FeatureStore '" + remoteFeastObj.Name + "' is using a different feast project than '" + feast.Handler.FeatureStore.Status.Applied.FeastProject + "'. Project names must match.") - } return &FeastServices{ Handler: handler.FeastHandler{ Client: feast.Handler.Client, @@ -1206,13 +1312,11 @@ func (feast *FeastServices) mountPvcConfig(podSpec *corev1.PodSpec, pvcConfig *f }, }, }) - if feastType == OfflineFeastType { - for i := range podSpec.InitContainers { - podSpec.InitContainers[i].VolumeMounts = append(podSpec.InitContainers[i].VolumeMounts, corev1.VolumeMount{ - Name: volName, - MountPath: pvcConfig.MountPath, - }) - } + for i := range podSpec.InitContainers { + podSpec.InitContainers[i].VolumeMounts = append(podSpec.InitContainers[i].VolumeMounts, corev1.VolumeMount{ + Name: volName, + MountPath: pvcConfig.MountPath, + }) } for i := range podSpec.Containers { podSpec.Containers[i].VolumeMounts = append(podSpec.Containers[i].VolumeMounts, corev1.VolumeMount{ @@ -1329,6 +1433,67 @@ func IsDeploymentAvailable(conditions []appsv1.DeploymentCondition) bool { return false } +// GetPodContainerFailureMessage inspects pods belonging to the given deployment +// and returns a human-readable message describing the first init or regular +// container that is in a failing state. Returns empty string if no failure found. +func (feast *FeastServices) GetPodContainerFailureMessage(deploy appsv1.Deployment) string { + podList := corev1.PodList{} + labels := feast.getLabels() + if err := feast.Handler.Client.List(feast.Handler.Context, &podList, + client.InNamespace(deploy.Namespace), + client.MatchingLabels(labels), + ); err != nil { + return "" + } + for i := range podList.Items { + pod := &podList.Items[i] + if msg := initContainerFailureMessage(pod); msg != "" { + return msg + } + if msg := containerFailureMessage(pod); msg != "" { + return msg + } + } + return "" +} + +func initContainerFailureMessage(pod *corev1.Pod) string { + for _, cs := range pod.Status.InitContainerStatuses { + if cs.State.Waiting != nil && cs.State.Waiting.Reason != "" && cs.State.Waiting.Reason != "PodInitializing" { + return "Init container '" + cs.Name + "' waiting: " + cs.State.Waiting.Reason + + messageIfPresent(cs.State.Waiting.Message) + } + if cs.State.Terminated != nil && cs.State.Terminated.ExitCode != 0 { + return "Init container '" + cs.Name + "' failed with exit code " + + strconv.Itoa(int(cs.State.Terminated.ExitCode)) + + messageIfPresent(cs.State.Terminated.Message) + } + } + return "" +} + +func containerFailureMessage(pod *corev1.Pod) string { + for _, cs := range pod.Status.ContainerStatuses { + if cs.State.Waiting != nil && cs.State.Waiting.Reason != "" && cs.State.Waiting.Reason != "ContainerCreating" { + return "Container '" + cs.Name + "' waiting: " + cs.State.Waiting.Reason + + messageIfPresent(cs.State.Waiting.Message) + } + if cs.State.Terminated != nil && cs.State.Terminated.ExitCode != 0 { + return "Container '" + cs.Name + "' failed with exit code " + + strconv.Itoa(int(cs.State.Terminated.ExitCode)) + + messageIfPresent(cs.State.Terminated.Message) + } + } + return "" +} + +func messageIfPresent(msg string) string { + if msg != "" { + return " - " + msg + } + return "" +} + // GetFeastRestServiceName returns the feast REST service object name based on service type func (feast *FeastServices) GetFeastRestServiceName(feastType FeastServiceType) string { return feast.GetFeastServiceName(feastType) + "-rest" diff --git a/infra/feast-operator/internal/controller/services/services_test.go b/infra/feast-operator/internal/controller/services/services_test.go index b8863e10a74..4b7b4343216 100644 --- a/infra/feast-operator/internal/controller/services/services_test.go +++ b/infra/feast-operator/internal/controller/services/services_test.go @@ -27,12 +27,9 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/utils/ptr" ) -func ptr[T any](v T) *T { - return &v -} - func (feast *FeastServices) refreshFeatureStore(ctx context.Context, key types.NamespacedName) { fs := &feastdevv1.FeatureStore{} Expect(k8sClient.Get(ctx, key, fs)).To(Succeed()) @@ -54,8 +51,8 @@ var _ = Describe("Registry Service", func() { ) var setFeatureStoreServerConfig = func(grpcEnabled, restEnabled bool) { - featureStore.Spec.Services.Registry.Local.Server.GRPC = ptr(grpcEnabled) - featureStore.Spec.Services.Registry.Local.Server.RestAPI = ptr(restEnabled) + featureStore.Spec.Services.Registry.Local.Server.GRPC = ptr.To(grpcEnabled) + featureStore.Spec.Services.Registry.Local.Server.RestAPI = ptr.To(restEnabled) Expect(k8sClient.Update(ctx, featureStore)).To(Succeed()) Expect(feast.ApplyDefaults()).To(Succeed()) applySpecToStatus(featureStore) @@ -83,12 +80,12 @@ var _ = Describe("Registry Service", func() { ServerConfigs: feastdevv1.ServerConfigs{ ContainerConfigs: feastdevv1.ContainerConfigs{ DefaultCtrConfigs: feastdevv1.DefaultCtrConfigs{ - Image: ptr("test-image"), + Image: ptr.To("test-image"), }, }, }, - GRPC: ptr(true), - RestAPI: ptr(false), + GRPC: ptr.To(true), + RestAPI: ptr.To(false), }, }, }, @@ -205,6 +202,64 @@ var _ = Describe("Registry Service", func() { }) }) + Describe("PodAnnotations Configuration", func() { + It("should apply podAnnotations to deployment pod template", func() { + featureStore.Spec.Services.PodAnnotations = map[string]string{ + "instrumentation.opentelemetry.io/inject-python": "true", + "sidecar.istio.io/inject": "true", + } + Expect(k8sClient.Update(ctx, featureStore)).To(Succeed()) + Expect(feast.ApplyDefaults()).To(Succeed()) + applySpecToStatus(featureStore) + feast.refreshFeatureStore(ctx, typeNamespacedName) + + deployment := feast.initFeastDeploy() + Expect(deployment).NotTo(BeNil()) + Expect(feast.setDeployment(deployment)).To(Succeed()) + + Expect(deployment.Spec.Template.Annotations).To(Equal(map[string]string{ + "instrumentation.opentelemetry.io/inject-python": "true", + "sidecar.istio.io/inject": "true", + })) + }) + + It("should have no pod template annotations when podAnnotations is not set", func() { + Expect(feast.ApplyDefaults()).To(Succeed()) + applySpecToStatus(featureStore) + feast.refreshFeatureStore(ctx, typeNamespacedName) + + deployment := feast.initFeastDeploy() + Expect(deployment).NotTo(BeNil()) + Expect(feast.setDeployment(deployment)).To(Succeed()) + + Expect(deployment.Spec.Template.Annotations).To(BeNil()) + }) + + It("should remove pod template annotations when podAnnotations is removed", func() { + featureStore.Spec.Services.PodAnnotations = map[string]string{ + "instrumentation.opentelemetry.io/inject-python": "true", + } + Expect(k8sClient.Update(ctx, featureStore)).To(Succeed()) + Expect(feast.ApplyDefaults()).To(Succeed()) + applySpecToStatus(featureStore) + feast.refreshFeatureStore(ctx, typeNamespacedName) + + deployment := feast.initFeastDeploy() + Expect(deployment).NotTo(BeNil()) + Expect(feast.setDeployment(deployment)).To(Succeed()) + Expect(deployment.Spec.Template.Annotations).To(HaveKey("instrumentation.opentelemetry.io/inject-python")) + + featureStore.Spec.Services.PodAnnotations = nil + Expect(k8sClient.Update(ctx, featureStore)).To(Succeed()) + Expect(feast.ApplyDefaults()).To(Succeed()) + applySpecToStatus(featureStore) + feast.refreshFeatureStore(ctx, typeNamespacedName) + + Expect(feast.setDeployment(deployment)).To(Succeed()) + Expect(deployment.Spec.Template.Annotations).To(BeNil()) + }) + }) + Describe("NodeSelector Configuration", func() { It("should apply NodeSelector to pod spec when configured", func() { // Set NodeSelector for registry service @@ -248,7 +303,7 @@ var _ = Describe("Registry Service", func() { Server: &feastdevv1.ServerConfigs{ ContainerConfigs: feastdevv1.ContainerConfigs{ DefaultCtrConfigs: feastdevv1.DefaultCtrConfigs{ - Image: ptr("test-image"), + Image: ptr.To("test-image"), }, OptionalCtrConfigs: feastdevv1.OptionalCtrConfigs{ NodeSelector: &onlineNodeSelector, @@ -284,7 +339,7 @@ var _ = Describe("Registry Service", func() { featureStore.Spec.Services.UI = &feastdevv1.ServerConfigs{ ContainerConfigs: feastdevv1.ContainerConfigs{ DefaultCtrConfigs: feastdevv1.DefaultCtrConfigs{ - Image: ptr("test-image"), + Image: ptr.To("test-image"), }, OptionalCtrConfigs: feastdevv1.OptionalCtrConfigs{ NodeSelector: &uiNodeSelector, @@ -332,7 +387,7 @@ var _ = Describe("Registry Service", func() { Server: &feastdevv1.ServerConfigs{ ContainerConfigs: feastdevv1.ContainerConfigs{ DefaultCtrConfigs: feastdevv1.DefaultCtrConfigs{ - Image: ptr("test-image"), + Image: ptr.To("test-image"), }, OptionalCtrConfigs: feastdevv1.OptionalCtrConfigs{ NodeSelector: &onlineNodeSelector, @@ -349,7 +404,7 @@ var _ = Describe("Registry Service", func() { featureStore.Spec.Services.UI = &feastdevv1.ServerConfigs{ ContainerConfigs: feastdevv1.ContainerConfigs{ DefaultCtrConfigs: feastdevv1.DefaultCtrConfigs{ - Image: ptr("test-image"), + Image: ptr.To("test-image"), }, OptionalCtrConfigs: feastdevv1.OptionalCtrConfigs{ NodeSelector: &uiNodeSelector, @@ -377,7 +432,7 @@ var _ = Describe("Registry Service", func() { It("should enable metrics on the online service when configured", func() { featureStore.Spec.Services.OnlineStore = &feastdevv1.OnlineStore{ - Server: &feastdevv1.ServerConfigs{Metrics: ptr(true)}, + Server: &feastdevv1.ServerConfigs{Metrics: ptr.To(true)}, } Expect(k8sClient.Update(ctx, featureStore)).To(Succeed()) @@ -451,7 +506,7 @@ var _ = Describe("Registry Service", func() { Server: &feastdevv1.ServerConfigs{ ContainerConfigs: feastdevv1.ContainerConfigs{ DefaultCtrConfigs: feastdevv1.DefaultCtrConfigs{ - Image: ptr("test-image"), + Image: ptr.To("test-image"), }, }, WorkerConfigs: &feastdevv1.WorkerConfigs{ @@ -503,7 +558,7 @@ var _ = Describe("Registry Service", func() { Server: &feastdevv1.ServerConfigs{ ContainerConfigs: feastdevv1.ContainerConfigs{ DefaultCtrConfigs: feastdevv1.DefaultCtrConfigs{ - Image: ptr("test-image"), + Image: ptr.To("test-image"), }, }, WorkerConfigs: &feastdevv1.WorkerConfigs{ @@ -545,7 +600,7 @@ var _ = Describe("Registry Service", func() { Server: &feastdevv1.ServerConfigs{ ContainerConfigs: feastdevv1.ContainerConfigs{ DefaultCtrConfigs: feastdevv1.DefaultCtrConfigs{ - Image: ptr("test-image"), + Image: ptr.To("test-image"), }, }, // WorkerConfigs is not set (nil) @@ -576,3 +631,119 @@ var _ = Describe("Registry Service", func() { }) }) }) + +var _ = Describe("Pod Container Failure Messages", func() { + It("should detect init container in CrashLoopBackOff", func() { + pod := &corev1.Pod{ + Status: corev1.PodStatus{ + InitContainerStatuses: []corev1.ContainerStatus{ + { + Name: "feast-init", + State: corev1.ContainerState{ + Terminated: &corev1.ContainerStateTerminated{ExitCode: 0}, + }, + }, + { + Name: "feast-apply", + State: corev1.ContainerState{ + Waiting: &corev1.ContainerStateWaiting{ + Reason: "CrashLoopBackOff", + Message: "back-off 5m0s restarting failed container", + }, + }, + }, + }, + }, + } + msg := initContainerFailureMessage(pod) + Expect(msg).To(ContainSubstring("feast-apply")) + Expect(msg).To(ContainSubstring("CrashLoopBackOff")) + Expect(msg).To(ContainSubstring("back-off 5m0s")) + }) + + It("should detect init container terminated with non-zero exit code", func() { + pod := &corev1.Pod{ + Status: corev1.PodStatus{ + InitContainerStatuses: []corev1.ContainerStatus{ + { + Name: "feast-apply", + State: corev1.ContainerState{ + Terminated: &corev1.ContainerStateTerminated{ + ExitCode: 1, + Message: "feast apply failed", + }, + }, + }, + }, + }, + } + msg := initContainerFailureMessage(pod) + Expect(msg).To(ContainSubstring("feast-apply")) + Expect(msg).To(ContainSubstring("exit code 1")) + Expect(msg).To(ContainSubstring("feast apply failed")) + }) + + It("should return empty for init containers still initializing", func() { + pod := &corev1.Pod{ + Status: corev1.PodStatus{ + InitContainerStatuses: []corev1.ContainerStatus{ + { + Name: "feast-init", + State: corev1.ContainerState{ + Waiting: &corev1.ContainerStateWaiting{ + Reason: "PodInitializing", + }, + }, + }, + }, + }, + } + Expect(initContainerFailureMessage(pod)).To(BeEmpty()) + }) + + It("should detect regular container failure", func() { + pod := &corev1.Pod{ + Status: corev1.PodStatus{ + ContainerStatuses: []corev1.ContainerStatus{ + { + Name: "registry", + State: corev1.ContainerState{ + Waiting: &corev1.ContainerStateWaiting{ + Reason: "ImagePullBackOff", + Message: "image not found", + }, + }, + }, + }, + }, + } + msg := containerFailureMessage(pod) + Expect(msg).To(ContainSubstring("registry")) + Expect(msg).To(ContainSubstring("ImagePullBackOff")) + }) + + It("should return empty for healthy pods", func() { + pod := &corev1.Pod{ + Status: corev1.PodStatus{ + InitContainerStatuses: []corev1.ContainerStatus{ + { + Name: "feast-init", + State: corev1.ContainerState{ + Terminated: &corev1.ContainerStateTerminated{ExitCode: 0}, + }, + }, + }, + ContainerStatuses: []corev1.ContainerStatus{ + { + Name: "registry", + State: corev1.ContainerState{ + Running: &corev1.ContainerStateRunning{}, + }, + }, + }, + }, + } + Expect(initContainerFailureMessage(pod)).To(BeEmpty()) + Expect(containerFailureMessage(pod)).To(BeEmpty()) + }) +}) diff --git a/infra/feast-operator/internal/controller/services/services_types.go b/infra/feast-operator/internal/controller/services/services_types.go index 10ac3538a99..5b4479698f3 100644 --- a/infra/feast-operator/internal/controller/services/services_types.go +++ b/infra/feast-operator/internal/controller/services/services_types.go @@ -50,6 +50,11 @@ const ( caBundleAnnotation = "config.openshift.io/inject-trusted-cabundle" caBundleName = "odh-trusted-ca-bundle" + odhCaBundleKey = "odh-ca-bundle.crt" + tlsPathOdhCABundle = "/etc/pki/tls/custom-certs/odh-ca-bundle.crt" + tlsPathOidcCA = "/etc/pki/tls/oidc-ca/ca.crt" + oidcCaVolumeName = "oidc-ca-cert" + defaultCACertKey = "ca-bundle.crt" DefaultOfflineStorageRequest = "20Gi" DefaultOnlineStorageRequest = "5Gi" @@ -91,6 +96,9 @@ const ( OidcClientSecret OidcPropertyType = "client_secret" OidcUsername OidcPropertyType = "username" OidcPassword OidcPropertyType = "password" + OidcTokenEnvVar OidcPropertyType = "token_env_var" + OidcVerifySsl OidcPropertyType = "verify_ssl" + OidcCaCertPath OidcPropertyType = "ca_cert_path" OidcMissingSecretError string = "missing OIDC secret: %s" ) @@ -208,9 +216,7 @@ var ( }, } - OidcServerProperties = []OidcPropertyType{OidcClientId, OidcAuthDiscoveryUrl} - OidcClientProperties = []OidcPropertyType{OidcClientSecret, OidcUsername, OidcPassword} - OidcProperties = []OidcPropertyType{OidcClientId, OidcAuthDiscoveryUrl, OidcClientSecret, OidcUsername, OidcPassword} + OidcOptionalSecretProperties = []OidcPropertyType{OidcAuthDiscoveryUrl, OidcClientId, OidcClientSecret, OidcUsername, OidcPassword} ) // Feast server types: Reserved only for server types like Online, Offline, and Registry servers. Should not be used for client types like the UI, etc. diff --git a/infra/feast-operator/internal/controller/services/suite_test.go b/infra/feast-operator/internal/controller/services/suite_test.go index a3d5bb3dae8..de1b75817ef 100644 --- a/infra/feast-operator/internal/controller/services/suite_test.go +++ b/infra/feast-operator/internal/controller/services/suite_test.go @@ -88,3 +88,7 @@ var _ = AfterSuite(func() { func testSetIsOpenShift() { isOpenShift = true } + +func testSetHasServiceMonitorCRD(val bool) { + hasServiceMonitorCRD = val +} diff --git a/infra/feast-operator/internal/controller/services/tls.go b/infra/feast-operator/internal/controller/services/tls.go index 4a50697c5a1..cd1121f770c 100644 --- a/infra/feast-operator/internal/controller/services/tls.go +++ b/infra/feast-operator/internal/controller/services/tls.go @@ -210,6 +210,10 @@ func (feast *FeastServices) mountTlsConfigs(podSpec *corev1.PodSpec) { feast.mountTlsConfig(OnlineFeastType, podSpec) feast.mountTlsConfig(UIFeastType, podSpec) feast.mountCustomCABundle(podSpec) + appliedSpec := feast.Handler.FeatureStore.Status.Applied + if appliedSpec.AuthzConfig != nil && appliedSpec.AuthzConfig.OidcAuthz != nil { + feast.mountOidcCACert(podSpec, appliedSpec.AuthzConfig.OidcAuthz) + } } func (feast *FeastServices) mountTlsConfig(feastType FeastServiceType, podSpec *corev1.PodSpec) { @@ -224,12 +228,16 @@ func (feast *FeastServices) mountTlsConfig(feastType FeastServiceType, podSpec * }, }, }) + tlsMount := corev1.VolumeMount{ + Name: volName, + MountPath: GetTlsPath(feastType), + ReadOnly: true, + } if i, container := getContainerByType(feastType, *podSpec); container != nil { - podSpec.Containers[i].VolumeMounts = append(podSpec.Containers[i].VolumeMounts, corev1.VolumeMount{ - Name: volName, - MountPath: GetTlsPath(feastType), - ReadOnly: true, - }) + podSpec.Containers[i].VolumeMounts = append(podSpec.Containers[i].VolumeMounts, tlsMount) + } + for i := range podSpec.InitContainers { + podSpec.InitContainers[i].VolumeMounts = append(podSpec.InitContainers[i].VolumeMounts, tlsMount) } } } @@ -245,12 +253,16 @@ func mountTlsRemoteRegistryConfig(podSpec *corev1.PodSpec, tls *feastdevv1.TlsRe }, }, }) + tlsMount := corev1.VolumeMount{ + Name: volName, + MountPath: GetTlsPath(RegistryFeastType), + ReadOnly: true, + } for i := range podSpec.Containers { - podSpec.Containers[i].VolumeMounts = append(podSpec.Containers[i].VolumeMounts, corev1.VolumeMount{ - Name: volName, - MountPath: GetTlsPath(RegistryFeastType), - ReadOnly: true, - }) + podSpec.Containers[i].VolumeMounts = append(podSpec.Containers[i].VolumeMounts, tlsMount) + } + for i := range podSpec.InitContainers { + podSpec.InitContainers[i].VolumeMounts = append(podSpec.InitContainers[i].VolumeMounts, tlsMount) } } } @@ -267,19 +279,64 @@ func (feast *FeastServices) mountCustomCABundle(podSpec *corev1.PodSpec) { }, }) + caMount := corev1.VolumeMount{ + Name: customCaBundle.VolumeName, + MountPath: tlsPathCustomCABundle, + ReadOnly: true, + SubPath: "ca-bundle.crt", + } + odhCaMount := corev1.VolumeMount{ + Name: customCaBundle.VolumeName, + MountPath: tlsPathOdhCABundle, + ReadOnly: true, + SubPath: odhCaBundleKey, + } for i := range podSpec.Containers { - podSpec.Containers[i].VolumeMounts = append(podSpec.Containers[i].VolumeMounts, corev1.VolumeMount{ - Name: customCaBundle.VolumeName, - MountPath: tlsPathCustomCABundle, - ReadOnly: true, - SubPath: "ca-bundle.crt", - }) + podSpec.Containers[i].VolumeMounts = append(podSpec.Containers[i].VolumeMounts, caMount, odhCaMount) + } + for i := range podSpec.InitContainers { + podSpec.InitContainers[i].VolumeMounts = append(podSpec.InitContainers[i].VolumeMounts, caMount, odhCaMount) } log.FromContext(feast.Handler.Context).Info("Mounted custom CA bundle ConfigMap to Feast pods.") } } +func (feast *FeastServices) mountOidcCACert(podSpec *corev1.PodSpec, oidcAuthz *feastdevv1.OidcAuthz) { + if oidcAuthz.CACertConfigMap == nil { + return + } + cmName := oidcAuthz.CACertConfigMap.Name + cmKey := oidcAuthz.CACertConfigMap.Key + if cmKey == "" { + cmKey = defaultCACertKey + } + + podSpec.Volumes = append(podSpec.Volumes, corev1.Volume{ + Name: oidcCaVolumeName, + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{Name: cmName}, + }, + }, + }) + + mount := corev1.VolumeMount{ + Name: oidcCaVolumeName, + MountPath: tlsPathOidcCA, + ReadOnly: true, + SubPath: cmKey, + } + for i := range podSpec.Containers { + podSpec.Containers[i].VolumeMounts = append(podSpec.Containers[i].VolumeMounts, mount) + } + for i := range podSpec.InitContainers { + podSpec.InitContainers[i].VolumeMounts = append(podSpec.InitContainers[i].VolumeMounts, mount) + } + + log.FromContext(feast.Handler.Context).Info("Mounted OIDC CA certificate ConfigMap to Feast pods.", "configMap", cmName, "key", cmKey) +} + // GetCustomCertificatesBundle retrieves the custom CA bundle ConfigMap if it exists when deployed with RHOAI or ODH func (feast *FeastServices) GetCustomCertificatesBundle() CustomCertificatesBundle { var customCertificatesBundle CustomCertificatesBundle diff --git a/infra/feast-operator/internal/controller/services/tls_test.go b/infra/feast-operator/internal/controller/services/tls_test.go index e5299d79119..0bd3bb82694 100644 --- a/infra/feast-operator/internal/controller/services/tls_test.go +++ b/infra/feast-operator/internal/controller/services/tls_test.go @@ -128,8 +128,7 @@ var _ = Describe("TLS Config", func() { err = feast.ApplyDefaults() Expect(err).ToNot(HaveOccurred()) - repoConfig, err := getClientRepoConfig(feast.Handler.FeatureStore, emptyMockExtractConfigFromSecret, &feast) - Expect(err).NotTo(HaveOccurred()) + repoConfig := getClientRepoConfig(feast.Handler.FeatureStore, &feast) Expect(repoConfig.OfflineStore.Port).To(Equal(HttpsPort)) Expect(repoConfig.OfflineStore.Scheme).To(Equal(HttpsScheme)) Expect(repoConfig.OfflineStore.Cert).To(ContainSubstring(string(OfflineFeastType))) @@ -173,7 +172,7 @@ var _ = Describe("TLS Config", func() { feastDeploy := feast.initFeastDeploy() err = feast.setDeployment(feastDeploy) Expect(err).ToNot(HaveOccurred()) - Expect(feastDeploy.Spec.Template.Spec.InitContainers).To(HaveLen(1)) + Expect(feastDeploy.Spec.Template.Spec.InitContainers).To(HaveLen(2)) Expect(feastDeploy.Spec.Template.Spec.Containers).To(HaveLen(4)) Expect(feastDeploy.Spec.Template.Spec.Containers[0].Command).To(ContainElements(ContainSubstring("--key"))) Expect(feastDeploy.Spec.Template.Spec.Containers[1].Command).To(ContainElements(ContainSubstring("--key"))) @@ -181,6 +180,19 @@ var _ = Describe("TLS Config", func() { Expect(feastDeploy.Spec.Template.Spec.Containers[3].Command).To(ContainElements(ContainSubstring("--key"))) Expect(feastDeploy.Spec.Template.Spec.Volumes).To(HaveLen(5)) + // verify init containers receive TLS volume mounts when all services have TLS + for _, initContainer := range feastDeploy.Spec.Template.Spec.InitContainers { + Expect(initContainer.VolumeMounts).To(ContainElement( + HaveField("MountPath", GetTlsPath(RegistryFeastType)), + ), "init container %s should have registry TLS mount", initContainer.Name) + Expect(initContainer.VolumeMounts).To(ContainElement( + HaveField("MountPath", GetTlsPath(OnlineFeastType)), + ), "init container %s should have online TLS mount", initContainer.Name) + Expect(initContainer.VolumeMounts).To(ContainElement( + HaveField("MountPath", GetTlsPath(OfflineFeastType)), + ), "init container %s should have offline TLS mount", initContainer.Name) + } + // registry service w/ tls and in an openshift cluster feast.Handler.FeatureStore = minimalFeatureStore() feast.Handler.FeatureStore.Spec.Services = &feastdevv1.FeatureStoreServices{ @@ -262,8 +274,7 @@ var _ = Describe("TLS Config", func() { err = feast.ApplyDefaults() Expect(err).ToNot(HaveOccurred()) - repoConfig, err = getClientRepoConfig(feast.Handler.FeatureStore, emptyMockExtractConfigFromSecret, &feast) - Expect(err).NotTo(HaveOccurred()) + repoConfig = getClientRepoConfig(feast.Handler.FeatureStore, &feast) Expect(repoConfig.OfflineStore.Port).To(Equal(HttpsPort)) Expect(repoConfig.OfflineStore.Scheme).To(Equal(HttpsScheme)) Expect(repoConfig.OfflineStore.Cert).To(ContainSubstring(string(OfflineFeastType))) @@ -336,6 +347,19 @@ var _ = Describe("TLS Config", func() { Expect(GetUIContainer(*feastDeploy).Command).NotTo(ContainElements(ContainSubstring("--key"))) Expect(GetUIContainer(*feastDeploy).VolumeMounts).To(HaveLen(1)) + // verify init containers receive only the offline TLS mount when only offline has TLS + for _, initContainer := range feastDeploy.Spec.Template.Spec.InitContainers { + Expect(initContainer.VolumeMounts).To(ContainElement( + HaveField("MountPath", GetTlsPath(OfflineFeastType)), + ), "init container %s should have offline TLS mount", initContainer.Name) + Expect(initContainer.VolumeMounts).NotTo(ContainElement( + HaveField("MountPath", GetTlsPath(RegistryFeastType)), + ), "init container %s should not have registry TLS mount when registry TLS is disabled", initContainer.Name) + Expect(initContainer.VolumeMounts).NotTo(ContainElement( + HaveField("MountPath", GetTlsPath(OnlineFeastType)), + ), "init container %s should not have online TLS mount when online TLS is disabled", initContainer.Name) + } + // Test REST registry server TLS configuration feast.Handler.FeatureStore = minimalFeatureStore() restEnabled := true diff --git a/infra/feast-operator/internal/controller/services/util.go b/infra/feast-operator/internal/controller/services/util.go index 33d750251e9..ecf97f2f865 100644 --- a/infra/feast-operator/internal/controller/services/util.go +++ b/infra/feast-operator/internal/controller/services/util.go @@ -21,6 +21,7 @@ import ( ) var isOpenShift = false +var hasServiceMonitorCRD = false func IsRegistryServer(featureStore *feastdevv1.FeatureStore) bool { return IsLocalRegistry(featureStore) && featureStore.Status.Applied.Services.Registry.Local.Server != nil @@ -99,6 +100,9 @@ func ApplyDefaultsToStatus(cr *feastdevv1.FeatureStore) { applied.Services = &feastdevv1.FeatureStoreServices{} } services := applied.Services + if services.RunFeastApplyOnInit == nil { + services.RunFeastApplyOnInit = boolPtr(true) + } if services.Registry != nil { // if remote registry not set, proceed w/ local registry defaults @@ -371,6 +375,12 @@ func IsOpenShift() bool { return isOpenShift } +// HasServiceMonitorCRD returns whether the monitoring.coreos.com API group +// (Prometheus Operator) is available in the cluster. +func HasServiceMonitorCRD() bool { + return hasServiceMonitorCRD +} + // SetIsOpenShift sets the global flag isOpenShift by the controller manager. // We don't need to keep fetching the API every reconciliation cycle that we need to know about the platform. func SetIsOpenShift(cfg *rest.Config) { @@ -390,15 +400,13 @@ func SetIsOpenShift(cfg *rest.Config) { for _, v := range apiList.Groups { if v.Name == "route.openshift.io" { isOpenShift = true - break + } + if v.Name == "monitoring.coreos.com" { + hasServiceMonitorCRD = true } } } -func missingOidcSecretProperty(property OidcPropertyType) error { - return fmt.Errorf(OidcMissingSecretError, property) -} - // getEnvVar returns the position of the EnvVar found by name func getEnvVar(envName string, env []corev1.EnvVar) int { for pos, v := range env { @@ -493,6 +501,16 @@ func getVolumeMountByType(feastType FeastServiceType, featureStore *feastdevv1.F return nil } +// isScalingEnabled returns true when the user has configured horizontal scaling +// with either static replicas > 1 or HPA autoscaling. +func isScalingEnabled(featureStore *feastdevv1.FeatureStore) bool { + if featureStore.Status.Applied.Replicas != nil && *featureStore.Status.Applied.Replicas > 1 { + return true + } + services := featureStore.Status.Applied.Services + return services != nil && services.Scaling != nil && services.Scaling.Autoscaling != nil +} + func boolPtr(value bool) *bool { return &value } diff --git a/infra/feast-operator/test/data-source-types/data-source-types.py b/infra/feast-operator/test/data-source-types/data-source-types.py index be7d70e5ede..ccda6665286 100644 --- a/infra/feast-operator/test/data-source-types/data-source-types.py +++ b/infra/feast-operator/test/data-source-types/data-source-types.py @@ -1,13 +1,20 @@ import os -from feast.repo_config import REGISTRY_CLASS_FOR_TYPE, OFFLINE_STORE_CLASS_FOR_TYPE, ONLINE_STORE_CLASS_FOR_TYPE, LEGACY_ONLINE_STORE_CLASS_FOR_TYPE +from feast.repo_config import ( + REGISTRY_CLASS_FOR_TYPE, + OFFLINE_STORE_CLASS_FOR_TYPE, + ONLINE_STORE_CLASS_FOR_TYPE, + LEGACY_ONLINE_STORE_CLASS_FOR_TYPE, +) + def save_in_script_directory(filename: str, typedict: dict[str, str]): script_dir = os.path.dirname(os.path.abspath(__file__)) file_path = os.path.join(script_dir, filename) - - with open(file_path, 'w') as file: + + with open(file_path, "w") as file: for k in typedict.keys(): - file.write(k+"\n") + file.write(k + "\n") + for legacyType in LEGACY_ONLINE_STORE_CLASS_FOR_TYPE.keys(): if legacyType in ONLINE_STORE_CLASS_FOR_TYPE: diff --git a/infra/feast-operator/test/testdata/feast_integration_test_crs/feast.yaml b/infra/feast-operator/test/testdata/feast_integration_test_crs/feast.yaml index 9dec3831b8c..56ab0ffbd4b 100644 --- a/infra/feast-operator/test/testdata/feast_integration_test_crs/feast.yaml +++ b/infra/feast-operator/test/testdata/feast_integration_test_crs/feast.yaml @@ -7,7 +7,7 @@ stringData: redis: | connection_string: redis.test-ns-feast.svc.cluster.local:6379 sql: | - path: postgresql+psycopg://${POSTGRESQL_USER}:${POSTGRESQL_PASSWORD}@postgres.test-ns-feast.svc.cluster.local:5432/${POSTGRESQL_DATABASE} + path: postgresql+psycopg://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres.test-ns-feast.svc.cluster.local:5432/${POSTGRES_DB} cache_ttl_seconds: 60 sqlalchemy_config_kwargs: echo: false diff --git a/infra/feast-operator/test/testdata/feast_integration_test_crs/postgres.yaml b/infra/feast-operator/test/testdata/feast_integration_test_crs/postgres.yaml index 8fbb11cf1cd..ba4599cea25 100644 --- a/infra/feast-operator/test/testdata/feast_integration_test_crs/postgres.yaml +++ b/infra/feast-operator/test/testdata/feast_integration_test_crs/postgres.yaml @@ -4,9 +4,9 @@ metadata: name: postgres-secret namespace: test-ns-feast stringData: - POSTGRESQL_DATABASE: feast - POSTGRESQL_USER: feast - POSTGRESQL_PASSWORD: feast + POSTGRES_DB: feast + POSTGRES_USER: feast + POSTGRES_PASSWORD: feast --- apiVersion: apps/v1 kind: Deployment @@ -25,7 +25,7 @@ spec: spec: containers: - name: postgres - image: 'quay.io/sclorg/postgresql-16-c9s@sha256:5879226a0fd2ea295df6836cc30ab624d2a1c51b81b3406284885604e10ddefe' + image: 'quay.io/feastdev-ci/feast-test-images:postgres-17-alpine' ports: - containerPort: 5432 envFrom: diff --git a/infra/feast-operator/test/testdata/feast_integration_test_crs/redis.yaml b/infra/feast-operator/test/testdata/feast_integration_test_crs/redis.yaml index cd88fb88fe5..b6e2fc9623c 100644 --- a/infra/feast-operator/test/testdata/feast_integration_test_crs/redis.yaml +++ b/infra/feast-operator/test/testdata/feast_integration_test_crs/redis.yaml @@ -15,7 +15,7 @@ spec: spec: containers: - name: redis - image: 'quay.io/sclorg/redis-7-c9s@sha256:ce07d358cea749e67bcc77f73b2c5244d771ac0781ed20d7ebb2ba271c169173' + image: 'quay.io/feastdev-ci/feast-test-images:redis-7-alpine' ports: - containerPort: 6379 env: diff --git a/infra/feast-operator/test/utils/test_util.go b/infra/feast-operator/test/utils/test_util.go index 7b5f0f8d6a0..15cd558ea16 100644 --- a/infra/feast-operator/test/utils/test_util.go +++ b/infra/feast-operator/test/utils/test_util.go @@ -409,6 +409,10 @@ func DeployOperatorFromCode(testDir string, skipBuilds bool) { _, err = Run(cmd, testDir) ExpectWithOffset(1, err).NotTo(HaveOccurred()) + By("deleting existing controller-manager deployment to allow selector changes on upgrade") + cmd = exec.Command("kubectl", "delete", "deployment", ControllerDeploymentName, "-n", FeastControllerNamespace, "--ignore-not-found=true") + _, _ = Run(cmd, testDir) + By("deploying the controller-manager") cmd = exec.Command("make", "deploy", fmt.Sprintf("IMG=%s", projectimage), fmt.Sprintf("FS_IMG=%s", feastLocalImage)) _, err = Run(cmd, testDir) diff --git a/infra/scripts/cleanup_ci.py b/infra/scripts/cleanup_ci.py index 262adf1e3eb..347e8ce1d39 100644 --- a/infra/scripts/cleanup_ci.py +++ b/infra/scripts/cleanup_ci.py @@ -1,4 +1,3 @@ -from time import sleep import boto3 from tqdm import tqdm from google.cloud import bigtable @@ -25,7 +24,7 @@ def cleanup_bigtable_ci(): client = bigtable.Client(project="kf-feast", admin=True) instance = client.instance("feast-integration-tests") if instance.exists(): - print(f"Deleted Bigtable CI instance") + print("Deleted Bigtable CI instance") instance.delete() location_id = "us-central1-f" @@ -38,7 +37,7 @@ def cleanup_bigtable_ci(): default_storage_type=storage_type, ) instance.create(clusters=[cluster]) - print(f"Created new Bigtable CI tables") + print("Created new Bigtable CI tables") def main() -> None: diff --git a/infra/scripts/feature_server_docker_smoke.py b/infra/scripts/feature_server_docker_smoke.py new file mode 100644 index 00000000000..5eac394bccd --- /dev/null +++ b/infra/scripts/feature_server_docker_smoke.py @@ -0,0 +1,38 @@ +from types import SimpleNamespace + +import uvicorn + +from feast.feature_server import get_app + + +class _FakeRegistry: + def proto(self): + return object() + + +class _FakeStore: + def __init__(self): + self.config = SimpleNamespace() + self.registry = _FakeRegistry() + self._provider = SimpleNamespace( + async_supported=SimpleNamespace( + online=SimpleNamespace(read=False, write=False) + ) + ) + + def _get_provider(self): + return self._provider + + async def initialize(self): + return None + + def refresh_registry(self): + return None + + async def close(self): + return None + + +if __name__ == "__main__": + app = get_app(_FakeStore()) + uvicorn.run(app, host="0.0.0.0", port=6566, log_level="error") diff --git a/infra/scripts/feature_store_client_configs_gen.py b/infra/scripts/feature_store_client_configs_gen.py index 124877a18ef..71a2d5d4d53 100644 --- a/infra/scripts/feature_store_client_configs_gen.py +++ b/infra/scripts/feature_store_client_configs_gen.py @@ -13,19 +13,18 @@ import os import yaml from pathlib import Path -from typing import Dict, List, Any, Optional +from typing import Dict, Any from feast import FeatureStore -from feast.repo_config import RepoConfig def create_feature_store_yaml(config_content: str, config_name: str) -> str: """ Create a feature_store.yaml file from config content. - + Args: config_content: YAML content as string config_name: Name identifier for the config (used for filename) - + Returns: Path to the created YAML file """ @@ -34,31 +33,33 @@ def create_feature_store_yaml(config_content: str, config_name: str) -> str: config_dict = yaml.safe_load(config_content) except yaml.YAMLError as e: raise ValueError(f"Failed to parse YAML content for {config_name}: {e}") - + # Ensure required fields are present - required_fields = ['project', 'registry', 'provider'] + required_fields = ["project", "registry", "provider"] for field in required_fields: if field not in config_dict: - raise ValueError(f"Failed to create config {config_name}: missing required field '{field}'") - + raise ValueError( + f"Failed to create config {config_name}: missing required field '{field}'" + ) + # Create filename filename = f"feature_store_{config_name}.yaml" filepath = Path(filename) - + # Write the YAML file - with open(filepath, 'w') as f: + with open(filepath, "w") as f: yaml.dump(config_dict, f, default_flow_style=False, sort_keys=False) - + return str(filepath) def create_feature_store_object(yaml_file_path: str) -> FeatureStore: """ Create a FeatureStore object from a YAML file. - + Args: yaml_file_path: Path to the feature_store.yaml file - + Returns: FeatureStore object """ @@ -67,26 +68,28 @@ def create_feature_store_object(yaml_file_path: str) -> FeatureStore: fs = FeatureStore(fs_yaml_file=Path(yaml_file_path)) return fs except Exception as e: - raise RuntimeError(f"Failed to create FeatureStore object from {yaml_file_path}: {e}") + raise RuntimeError( + f"Failed to create FeatureStore object from {yaml_file_path}: {e}" + ) def process_client_configs(client_configs: Dict[str, str]) -> Dict[str, Dict[str, Any]]: """ Process multiple client config YAML contents and create feature stores. - + Args: client_configs: Dictionary mapping config names to YAML content strings - + Returns: Dictionary with results for each config """ results = {} created_yamls = [] feature_stores = {} - + print("Creating feature store YAMLs and objects...") print("=" * 50) - + for config_name, config_content in client_configs.items(): try: print(f"\nProcessing config: {config_name}") @@ -95,7 +98,7 @@ def process_client_configs(client_configs: Dict[str, str]) -> Dict[str, Dict[str yaml_path = create_feature_store_yaml(config_content, config_name) created_yamls.append(yaml_path) print(f"✓ Created YAML file: {yaml_path}") - + # Create FeatureStore object fs = create_feature_store_object(yaml_path) fs_var_name = f"fs_{fs.project}" @@ -104,30 +107,30 @@ def process_client_configs(client_configs: Dict[str, str]) -> Dict[str, Dict[str print(f"✓ Created FeatureStore object: {fs_var_name}") results[config_name] = { - 'yaml_path': yaml_path, - 'feature_store': fs_var_name, - 'project_name': fs.project, - 'success': True, - 'error': None + "yaml_path": yaml_path, + "feature_store": fs_var_name, + "project_name": fs.project, + "success": True, + "error": None, } - + except Exception as e: print(f"✗ Failed to process config {config_name}: {e}") results[config_name] = { - 'yaml_path': None, - 'feature_store': None, - 'project_name': None, - 'success': False, - 'error': str(e) + "yaml_path": None, + "feature_store": None, + "project_name": None, + "success": False, + "error": str(e), } - + return results def print_summary(results: Dict[str, Dict[str, Any]]) -> None: """ Print summary of all operations. - + Args: results: Results dictionary from process_client_configs """ @@ -135,13 +138,15 @@ def print_summary(results: Dict[str, Dict[str, Any]]) -> None: print("SUMMARY") print("=" * 50) - successful_configs = [name for name, result in results.items() if result['success']] - failed_configs = [name for name, result in results.items() if not result['success']] + successful_configs = [name for name, result in results.items() if result["success"]] + failed_configs = [name for name, result in results.items() if not result["success"]] print(f"\n\n✓✓Feature Store YAML files have been created in: {os.getcwd()}") print(f"\n✓ Successfully processed {len(successful_configs)} config(s):") for config_name in successful_configs: result = results[config_name] - print(f" - {config_name}: {result['yaml_path']} (Project: {result['project_name']})") + print( + f" - {config_name}: {result['yaml_path']} (Project: {result['project_name']})" + ) if failed_configs: print(f"\n✗ Failed to process {len(failed_configs)} config(s):") @@ -149,15 +154,21 @@ def print_summary(results: Dict[str, Dict[str, Any]]) -> None: result = results[config_name] print(f" - {config_name}: {result['error']}") - print(f"\n\n✓✓ Feature Store Object(s) details:") + print("\n\n✓✓ Feature Store Object(s) details:") for config_name in successful_configs: result = results[config_name] - print(f"> Object Name - {result['feature_store']} ; project name - {result['project_name']} ; yaml path - {result['yaml_path']}") + print( + f"> Object Name - {result['feature_store']} ; project name - {result['project_name']} ; yaml path - {result['yaml_path']}" + ) print("\n") print("=" * 25, "Usage:", "=" * 25) - print("You can now use feature store object(s) to access the feature store resources and functions!") - print("\n// Note: Replace object_name with the actual object name from the list above.") + print( + "You can now use feature store object(s) to access the feature store resources and functions!" + ) + print( + "\n// Note: Replace object_name with the actual object name from the list above." + ) print("object_name.list_features()\nobject_name.get_historical_features()") print("=" * 58) @@ -179,7 +190,6 @@ def main(): type: file entity_key_serialization_version: 3 """, - "aws_redshift": """ project: aws_feature_store registry: data/registry.db @@ -197,7 +207,6 @@ def main(): iam_role: arn:aws:iam::123456789012:role/RedshiftRole entity_key_serialization_version: 3 """, - "gcp_bigquery": """ project: gcp_feature_store registry: data/registry.db @@ -210,18 +219,20 @@ def main(): project_id: my-gcp-project dataset_id: my_dataset entity_key_serialization_version: 3 -""" +""", } print("=" * 50) - print("This script will create feature store YAMLs and objects from client configs.") + print( + "This script will create feature store YAMLs and objects from client configs." + ) print(f"Processing {len(example_configs)} example configurations...") - + # Process the configs results = process_client_configs(example_configs) - + # Print summary print_summary(results) if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/infra/scripts/generate_protos.py b/infra/scripts/generate_protos.py index 2ce7e29e12e..c030a9347df 100644 --- a/infra/scripts/generate_protos.py +++ b/infra/scripts/generate_protos.py @@ -9,6 +9,7 @@ PROTO_SUBDIRS = ["core", "registry", "serving", "types", "storage"] PYTHON_CODE_PREFIX = "sdk/python" + class BuildPythonProtosCommand: description = "Builds the proto files into Python files." user_options = [ @@ -76,5 +77,6 @@ def run(self): with open(path, "w") as file: file.write(filedata) + if __name__ == "__main__": - BuildPythonProtosCommand().run() \ No newline at end of file + BuildPythonProtosCommand().run() diff --git a/infra/scripts/pixi/pixi.toml b/infra/scripts/pixi/pixi.toml index afb6407042d..b5ce74b1791 100644 --- a/infra/scripts/pixi/pixi.toml +++ b/infra/scripts/pixi/pixi.toml @@ -1,4 +1,4 @@ -[project] +[workspace] name = "pixi-feast" channels = ["conda-forge"] platforms = ["linux-64", "osx-arm64", "osx-64"] diff --git a/infra/scripts/release/bump_file_versions.py b/infra/scripts/release/bump_file_versions.py index c913e9f43f7..f13b9e257df 100644 --- a/infra/scripts/release/bump_file_versions.py +++ b/infra/scripts/release/bump_file_versions.py @@ -4,7 +4,9 @@ import pathlib import sys -USAGE = f"Usage: python {sys.argv[0]} [--help] | current_semver_version new_semver_version]" +USAGE = ( + f"Usage: python {sys.argv[0]} [--help] | current_semver_version new_semver_version]" +) VERSIONS_TO_BUMP = 27 @@ -17,18 +19,24 @@ def main() -> None: new_version = args[1].strip() if current_version == new_version: - raise SystemExit(f"Current and new versions are the same: {current_version} == {new_version}") + raise SystemExit( + f"Current and new versions are the same: {current_version} == {new_version}" + ) # Validate that the input arguments are semver versions if not is_semantic_version(current_version): - raise SystemExit(f"Current version is not a valid semantic version: {current_version}") + raise SystemExit( + f"Current version is not a valid semantic version: {current_version}" + ) if not is_semantic_version(new_version): raise SystemExit(f"New version is not a valid semantic version: {new_version}") # Get git repo root directory repo_root = pathlib.Path(__file__).resolve().parent.parent.parent.parent - path_to_file_list = repo_root.joinpath("infra", "scripts", "release", "files_to_bump.txt") + path_to_file_list = repo_root.joinpath( + "infra", "scripts", "release", "files_to_bump.txt" + ) # Get files to bump versions within with open(path_to_file_list, "r") as f: @@ -47,11 +55,15 @@ def main() -> None: file_contents = f.readlines() for line in lines: # note we validate the version above already - current_parsed_version = _get_semantic_version(file_contents[int(line) - 1]) - file_contents[int(line) - 1] = file_contents[int(line) - 1].replace(current_parsed_version, new_version) + current_parsed_version = _get_semantic_version( + file_contents[int(line) - 1] + ) + file_contents[int(line) - 1] = file_contents[int(line) - 1].replace( + current_parsed_version, new_version + ) with open(repo_root.joinpath(file_path), "w") as f: - f.write(''.join(file_contents)) + f.write("".join(file_contents)) updated_count += 1 print(f"Updated {updated_count} files with new version {new_version}") @@ -70,22 +82,27 @@ def is_semantic_version(version: str) -> bool: def validate_files_to_bump(current_version, files_to_bump, repo_root): for file in files_to_bump: components = file.split(" ") - assert len(components) > 1, f"Entry {file} should have a file name, and a list of line numbers with versions" + assert len(components) > 1, ( + f"Entry {file} should have a file name, and a list of line numbers with versions" + ) file_path = components[0] lines = components[1:] with open(repo_root.joinpath(file_path), "r") as f: file_contents = f.readlines() for line in lines: new_version = _get_semantic_version(file_contents[int(line) - 1]) - current_major_minor_version = '.'.join(current_version.split(".")[0:1]) - assert current_version in new_version or current_major_minor_version in new_version, ( + current_major_minor_version = ".".join(current_version.split(".")[0:1]) + assert ( + current_version in new_version + or current_major_minor_version in new_version + ), ( f"File `{file_path}` line `{line}` didn't contain version {current_version}. " f"Contents: {file_contents[int(line) - 1]}" ) def _get_semantic_version(input_string: str) -> str: - semver_pattern = r'\bv?(\d+\.\d+\.\d+)\b' + semver_pattern = r"\bv?(\d+\.\d+\.\d+)\b" match = re.search(semver_pattern, input_string) return match.group(1) diff --git a/infra/scripts/release/unset_prerelease.py b/infra/scripts/release/unset_prerelease.py index 4a2ba131970..c474c0908de 100644 --- a/infra/scripts/release/unset_prerelease.py +++ b/infra/scripts/release/unset_prerelease.py @@ -4,7 +4,9 @@ import sys import requests -USAGE = f"Usage: python {sys.argv[0]} [--help] | version_being_released (e.g., v0.19.1)]" +USAGE = ( + f"Usage: python {sys.argv[0]} [--help] | version_being_released (e.g., v0.19.1)]" +) def get_prerelease_status(version_being_released, token): @@ -13,12 +15,12 @@ def get_prerelease_status(version_being_released, token): headers = { "Content-Type": "application/json", "Accept": "application/vnd.github.v3+json", - "Authorization": f"Bearer {token}" + "Authorization": f"Bearer {token}", } response = requests.request("GET", url, headers=headers) response_json = response.json() - return bool(response_json['prerelease']), response_json['id'] + return bool(response_json["prerelease"]), response_json["id"] def set_prerelease_status(release_id, status, token): @@ -29,7 +31,7 @@ def set_prerelease_status(release_id, status, token): headers = { "Content-Type": "application/json", "Accept": "application/vnd.github.v3+json", - "Authorization": f"Bearer {token}" + "Authorization": f"Bearer {token}", } requests.request("PATCH", url, json=payload, headers=headers) @@ -44,7 +46,7 @@ def main() -> None: print(f"Disabling prerelease status for {version_being_released}") - token = os.getenv('GITHUB_TOKEN', default=None) + token = os.getenv("GITHUB_TOKEN", default=None) if token is None: raise OSError("GITHUB_TOKEN environmental variable is not set") @@ -61,9 +63,14 @@ def main() -> None: if is_prerelease: import warnings - warnings.warn(f"Failed to unset prerelease status for {version_being_released} release id {release_id}") + + warnings.warn( + f"Failed to unset prerelease status for {version_being_released} release id {release_id}" + ) else: - print(f"Successfully unset prerelease status for {version_being_released} release id {release_id}") + print( + f"Successfully unset prerelease status for {version_being_released} release id {release_id}" + ) if __name__ == "__main__": diff --git a/infra/website/docs/blog/entity-less-historical-features-retrieval.md b/infra/website/docs/blog/entity-less-historical-features-retrieval.md new file mode 100644 index 00000000000..ec907fe26de --- /dev/null +++ b/infra/website/docs/blog/entity-less-historical-features-retrieval.md @@ -0,0 +1,142 @@ +--- +title: Historical Features Without Entity IDs +description: Feast now supports entity-less historical feature retrieval by datetime range—making it easier to train models when you don't have or need entity IDs. +date: 2026-02-19 +authors: ["Jitendra Yejare", "Aniket Paluskar"] +--- + +# Historical Features Without Entity IDs + +For years, Historical Feature Retrieval in Feast required an **entity dataframe**; you had to supply the exact entity keys (e.g. `driver_id`, `user_id`) and timestamps you wanted to join features for. That works well when you have a fixed set of entities—for example, a list of users you want to score or a training set already keyed by IDs. But in many AI and ML projects, you **don’t have** entity IDs upfront, or the problem **doesn’t naturally have** entities at all. In those cases, being forced to create and pass an entity dataframe was a real friction. + +We’re excited to share that Feast now supports **entity-less historical feature retrieval** based on a **datetime range**. You can pull all historical feature data for a time window without specifying any entity dataframe—addressing the long-standing [GitHub issue #1611](https://github.com/feast-dev/feast/issues/1611) and simplifying training and tuning workflows where entity IDs are optional or irrelevant. + +# The Problem: Entity IDs Aren’t Always There + +Classic use of a feature store looks like this: + +```python +entity_df = pd.DataFrame({ + "driver_id": [1001, 1002, 1003], + "event_timestamp": [datetime(2025, 1, 1), datetime(2025, 1, 2), datetime(2025, 1, 3)] +}) + +training_df = store.get_historical_features( + entity_df=entity_df, + features=["driver_hourly_stats:conv_rate", "driver_hourly_stats:acc_rate"], +).to_df() +``` + +You already have a set of entities and timestamps; Feast joins features onto them. But in many real-world setups: + +- **Time-series and sequence models** – You care about a time range and all data in it, not a pre-defined list of entity IDs. Building an entity dataframe means first querying “who existed in this period?” and then passing those IDs in, which is extra plumbing and can be expensive. +- **Global or population-level models** – You’re modeling aggregates, trends, or system-wide behavior. There may be no natural “entity” to key on, or you want “all entities” in a window. +- **Exploratory analysis and research** – You want “all features in the last 7 days” to experiment with models or features. Requiring entity IDs forces you to materialize a full entity list before you can even call the feature store. +- **Cold start and new users** – When training models that will later serve new or rarely-seen entities (e.g. recommendation cold start, fraud detection for new accounts), you often don’t have a fixed, known entity set at training time. You want to train on “all entities that had activity in this window” so the model generalizes from the full population. +- **Batch training on full history** – You want to train on all available history in a date range. Generating and passing a huge entity dataframe is cumbersome and sometimes not even possible if the entity set is large or dynamic. + +In all these cases, **passing entity IDs is either not possible, not required, or unnecessarily complex**. Making the entity dataframe optional and supporting retrieval by datetime range makes the feature store much easier to use in production and in research. + +# What’s New: Optional Entity DataFrame and Date Range + +Feast now supports entity-less historical feature retrieval by datetime range for several offline stores; you can pull historical feature data for a time window without specifying any entity dataframe. You specify a time window (and optionally rely on TTL for defaults), and the offline store returns all feature data in that range. + +- **Entity dataframe is optional** – You can omit `entity_df` and use `start_date` and/or `end_date` instead. +- **Point-in-time correctness** – Retrieval still uses point-in-time semantics (e.g. LATERAL joins in the offline stores) so you get correct historical values. +- **Smart defaults** – If you don’t pass `start_date`, the range can be derived from the feature view TTL; if you don’t pass `end_date`, it defaults to “now”. +- **Backward compatible** – The existing entity-based API is unchanged. When you have an entity dataframe (e.g. for ODFV or targeted batch scoring), you keep using it with entity dataframe as before. + +Entity-less retrieval is supported across multiple offline stores: **Postgres** (where it was first introduced), **Dask**, **Spark**, and **Ray**—with Spark and Ray being especially important for large-scale and distributed training workloads. More offline stores will be supported in the future based on user demand and priority. + +# How to Use It + +You can use any of these patterns depending on how much you want to specify. + +**1. Explicit date range (data between start and end):** + +```python +training_df = store.get_historical_features( + features=[ + "driver_hourly_stats:conv_rate", + "driver_hourly_stats:acc_rate", + "driver_hourly_stats:avg_daily_trips", + ], + start_date=datetime(2025, 7, 1, 1, 0, 0), + end_date=datetime(2025, 7, 2, 3, 30, 0), +).to_df() +``` + +**2. Only end date (Start date is end date minus TTL):** + +```python +training_df = store.get_historical_features( + features=[ + "driver_hourly_stats:conv_rate", + "driver_hourly_stats:acc_rate", + "driver_hourly_stats:avg_daily_trips", + ], + end_date=datetime(2025, 7, 2, 3, 30, 0), +).to_df() +``` + +**3. Only start date (data from start date to now):** + +```python +training_df = store.get_historical_features( + features=[ + "driver_hourly_stats:conv_rate", + "driver_hourly_stats:acc_rate", + "driver_hourly_stats:avg_daily_trips", + ], + start_date=datetime(2025, 7, 1, 1, 0, 0), +).to_df() +``` + +**4. No dates (data from TTL window to now):** + +```python +training_df = store.get_historical_features( + features=[ + "driver_hourly_stats:conv_rate", + "driver_hourly_stats:acc_rate", + "driver_hourly_stats:avg_daily_trips", + ], +).to_df() +``` + +**5. Entity-based retrieval still works (e.g. for ODFV or when you need data for specific entities):** + +```python +entity_df = pd.DataFrame.from_dict({ + "driver_id": [1005], + "event_timestamp": [datetime(2025, 6, 29, 23, 0, 0)], +}) + +training_df = store.get_historical_features( + entity_df=entity_df, + features=[ + "driver_hourly_stats:conv_rate", + "driver_hourly_stats:acc_rate", + "transformed_conv_rate:conv_rate_plus_val1", + ], +).to_df() +``` + +Feast does not support mixing entity-based and range-based retrieval in one call; either pass `entity_df` or pass `start_date`/`end_date`, not both. + +# Try It Out + +To experiment with entity-less retrieval: + +1. Use a feature store backed by an offline store that supports it: **Postgres**, **Dask**, **Spark**, or **Ray** (see [Feast docs](https://docs.feast.dev/) for setup). Spark and Ray are a great fit for distributed and large-scale training. +2. Call `get_historical_features()` with only `features` and, as needed, `start_date` and `end_date` (or rely on TTL and default end time). +3. For full details, tests, and behavior, see [PR #5527](https://github.com/feast-dev/feast/pull/5527) and the updated [FAQ on historical retrieval without an entity dataframe](https://docs.feast.dev/getting-started/faq#how-do-i-run-get_historical_features-without-providing-an-entity-dataframe). + +# Why This Makes Production Easier + +- **Simpler training pipelines** – No need to pre-query “all entity IDs in range” or maintain a separate entity table just to call the feature store. You specify a time window and get features. +- **Fewer moving parts** – Less code, fewer joins, and fewer failure modes when you don’t need entity-based slicing. +- **Better fit for time-range-centric workflows** – Time-series, global models, and exploratory jobs can all use the same API without artificial entity construction. +- **Same point-in-time guarantees** – Entity-less retrieval still respects feature view TTL and temporal correctness, so your training data remains valid. + +We’re excited to see how the community uses entity-less historical retrieval. If you have feedback or want to help bring this to more offline stores, join the discussion on [GitHub issue #1611](https://github.com/feast-dev/feast/issues/1611) or [Feast Slack](https://slack.feast.dev). diff --git a/infra/website/docs/blog/feast-feature-server-monitoring.md b/infra/website/docs/blog/feast-feature-server-monitoring.md new file mode 100644 index 00000000000..c416e84e82b --- /dev/null +++ b/infra/website/docs/blog/feast-feature-server-monitoring.md @@ -0,0 +1,443 @@ +--- +title: "Monitoring Your Feast Feature Server with Prometheus and Grafana" +description: "Feast now ships built-in Prometheus metrics for the feature server — request latency, feature freshness, materialization health, ODFV transformation duration, and more. Enable with a single flag and get production-grade observability for your ML infrastructure." +date: 2026-03-26 +authors: ["Nikhil Kathole"] +--- + +
+ Feast Feature Server Monitoring — Feast exports metrics to Prometheus for monitoring and alerting, visualized in Grafana dashboards +
+ +# Monitoring Your Feast Feature Server with Prometheus and Grafana + +As feature stores become a critical part of production ML systems, the question shifts from *"Can I serve features?"* to *"Can I trust what I'm serving?"*. Are my features fresh? Is latency within SLA? Are materialization pipelines succeeding? How long are my on-demand transformations taking? + +Until now, answering these questions for Feast required ad-hoc monitoring — parsing logs, writing custom health checks, or bolting on external instrumentation. That changes today. + +**Feast now ships built-in Prometheus metrics for the feature server**, covering the full request lifecycle — from HTTP request handling through online store reads and on-demand feature transformations to materialization pipelines and feature freshness tracking. Enable it with a single flag, point Prometheus at the metrics endpoint, and get production-grade observability for your feature serving infrastructure. + +This post walks through the metrics available, what each one tells you, how to enable and configure them, and how to build a Grafana dashboard that gives you a complete operational picture of your feature server. + +## What's New + +Feast's feature server now exposes a comprehensive set of Prometheus metrics across seven categories, designed to give ML platform teams full visibility into their feature serving infrastructure: + +- **Request metrics** — Per-endpoint request counters and latency histograms with `feature_count` and `feature_view_count` labels, so you can correlate latency with request complexity. +- **Online store read duration** — A histogram capturing total time spent reading from the online store (Redis, DynamoDB, PostgreSQL, etc.), covering both synchronous and async paths across all backends. +- **ODFV transformation duration** — Per-ODFV histograms for both read-path (during `/get-online-features`) and write-path (during push/materialize) transformations, with `odfv_name` and `mode` labels to compare Pandas vs Python vs Substrait performance. +- **Online feature retrieval counters** — Request counts and entity-row-per-request histograms, revealing the shape of your traffic. +- **Push counters** — Tracked by push source and mode (online/offline/both), giving early warning when ingestion pipelines stop sending data. +- **Materialization tracking** — Success/failure counters and duration histograms per feature view, so you know immediately when a pipeline breaks. +- **Feature freshness gauges** — Per-feature-view staleness (seconds since last materialization), updated by a background thread every 30 seconds. The single most important metric for ML model quality. +- **CPU and memory gauges** — Per-worker resource usage for capacity planning and leak detection. +- **Kubernetes-native discovery** — The Feast Operator auto-generates a `ServiceMonitor` when metrics are enabled, so Prometheus Operator discovers the scrape target automatically. + +All metrics are fully opt-in with zero overhead when disabled. Per-category toggles let you enable exactly the metrics you need. + +## Enabling Metrics + +### CLI: One Flag + +The simplest way — one flag, everything enabled: + +```bash +feast serve --metrics +``` + +This starts the feature server on its default port (6566) and a Prometheus metrics endpoint on port 8000. + +### YAML: Fine-Grained Control + +For production deployments, configure metrics in `feature_store.yaml` with per-category toggles: + +```yaml +feature_server: + metrics: + enabled: true + resource: true # CPU and memory gauges + request: true # HTTP request counters and latency histograms + online_features: true # Entity count and retrieval tracking + push: true # Push/ingestion request counters + materialization: true # Pipeline success/failure and duration + freshness: true # Per-feature-view data staleness +``` + +### Kubernetes: Feast Operator + +If you're running Feast on Kubernetes with the [Feast Operator](/blog/scaling-feast-feature-server), set `metrics: true` on the online store server: + +```yaml +apiVersion: feast.dev/v1alpha1 +kind: FeatureStore +metadata: + name: production-feast +spec: + feastProject: my_project + services: + onlineStore: + server: + metrics: true +``` + +The operator automatically appends `--metrics` to the serve command and exposes port 8000 as a `metrics` port on the Service. It also auto-generates a `ServiceMonitor` resource for Prometheus Operator discovery. The operator detects the `monitoring.coreos.com` API group at startup; if the Prometheus Operator CRD is absent, ServiceMonitor creation is silently skipped, so vanilla Kubernetes clusters are unaffected. + +## The Metrics + +Feast exposes metrics across seven categories. Here's the full reference, organized by what each category helps you answer. + +### Request Metrics — "How is my API performing?" + +| Metric | Type | Labels | +|---|---|---| +| `feast_feature_server_request_total` | Counter | `endpoint`, `status` | +| `feast_feature_server_request_latency_seconds` | Histogram | `endpoint`, `feature_count`, `feature_view_count` | + +These are the core RED metrics (Rate, Errors, Duration) for your feature server. The latency histogram includes `feature_count` and `feature_view_count` labels so you can correlate latency with request complexity — a request fetching 200 features from 15 feature views will naturally be slower than one fetching 5 features from 2 views. + +The histogram uses bucket boundaries tuned for feature serving workloads: `5ms, 10ms, 25ms, 50ms, 100ms, 250ms, 500ms, 1s, 2.5s, 5s, 10s`. Most online feature requests should complete in the lower buckets. + +### Online Feature Retrieval — "What does my traffic look like?" + +| Metric | Type | Labels | +|---|---|---| +| `feast_online_features_request_total` | Counter | — | +| `feast_online_features_entity_count` | Histogram | — | + +The entity count histogram (buckets: `1, 5, 10, 25, 50, 100, 250, 500, 1000`) tells you the shape of your traffic. Are callers sending single-entity lookups (real-time inference) or batch requests of hundreds (batch scoring)? A sudden spike in entity count per request means an upstream service changed its batching strategy — this directly impacts latency and memory. + +### Online Store Read Duration — "Where is my latency coming from?" + +| Metric | Type | Labels | +|---|---|---| +| `feast_feature_server_online_store_read_duration_seconds` | Histogram | — | + +This metric captures the total time spent reading from the online store (Redis, DynamoDB, PostgreSQL, etc.) during a `/get-online-features` request. It covers both the synchronous for-loop path and the async `asyncio.gather` path across all backends. + +By comparing this with the overall request latency, you can determine whether latency is dominated by the store read or by other processing (serialization, transformation, network overhead). + +### ODFV Transformation Duration — "How expensive are my transforms?" + +| Metric | Type | Labels | +|---|---|---| +| `feast_feature_server_transformation_duration_seconds` | Histogram | `odfv_name`, `mode` | +| `feast_feature_server_write_transformation_duration_seconds` | Histogram | `odfv_name`, `mode` | + +These metrics capture per-ODFV transformation time for both read-path (during `/get-online-features`) and write-path (during push/materialize with `write_to_online_store=True`) operations. The `mode` label distinguishes `pandas`, `python`, and `substrait` transformation modes, making it easy to compare their performance characteristics side by side. + +ODFV transformation metrics are **opt-in at the definition level** via `track_metrics=True`: + +```python +@on_demand_feature_view( + sources=[driver_stats_fv, input_request], + schema=[Field(name="conv_rate_plus_val1", dtype=Float64)], + mode="python", + track_metrics=True, # Enable Prometheus metrics for this ODFV +) +def transformed_conv_rate_python(inputs: Dict[str, Any]) -> Dict[str, Any]: + return {"conv_rate_plus_val1": inputs["conv_rate"] + inputs["val_to_add"]} +``` + +When `track_metrics=False` (the default), zero metrics code runs for that ODFV — no timing, no Prometheus recording. This lets you selectively instrument the transforms you care about without adding overhead to others. + +### Push Metrics — "Is my ingestion pipeline healthy?" + +| Metric | Type | Labels | +|---|---|---| +| `feast_push_request_total` | Counter | `push_source`, `mode` | + +The `push_source` label identifies which source is pushing data. The `mode` label is one of `online`, `offline`, or `online_and_offline`. A push source that stops sending data is an early signal that an upstream pipeline is broken — long before feature staleness becomes visible. + +### Materialization Metrics — "Are my pipelines succeeding?" + +| Metric | Type | Labels | +|---|---|---| +| `feast_materialization_total` | Counter | `feature_view`, `status` | +| `feast_materialization_duration_seconds` | Histogram | `feature_view` | + +The `status` label is `success` or `failure`. The duration histogram uses wide buckets (`1s, 5s, 10s, 30s, 60s, 2min, 5min, 10min, 30min, 1hr`) because materialization jobs can range from seconds to tens of minutes depending on the feature view size and offline store. + +### Feature Freshness — "How stale is my data?" + +| Metric | Type | Labels | +|---|---|---| +| `feast_feature_freshness_seconds` | Gauge | `feature_view`, `project` | + +**This is the single most important metric for ML teams.** It measures data staleness — the gap between "now" and the last successful materialization end time — per feature view. A background thread computes this every 30 seconds. + +If your model was trained on hourly features and the freshness gauge crosses 2 hours, your model is receiving data it has never seen patterns for. Before this metric existed, this was a silent failure. Now you can set an alert and catch it in minutes. + +The dashboard below shows these ML-specific metrics in action — latency correlated with feature count, online feature request rate, average entities per request, feature freshness per feature view, and materialization success counts with duration: + +
+ Grafana dashboard showing latency by feature count, feature freshness, average entities per request, and materialization metrics +
+ +### Resource Metrics — "Is my server healthy?" + +| Metric | Type | Labels | +|---|---|---| +| `feast_feature_server_cpu_usage` | Gauge | (per worker PID) | +| `feast_feature_server_memory_usage` | Gauge | (per worker PID) | + +Per-worker CPU and memory gauges, updated every 5 seconds by a background thread. In Gunicorn deployments, each worker reports independently, so you can spot an individual worker consuming excessive resources. + +## Latency Breakdown: Understanding Where Time Is Spent + +One of the most powerful uses of these metrics is **latency decomposition**. By overlaying the overall request latency with the online store read duration and ODFV transformation duration, you can pinpoint exactly where time is spent: + +``` +Total request latency = Store read + ODFV transforms + Serialization/overhead +``` + +The Grafana dashboard below shows this decomposition in action — online store read latency (p50/p95/p99), per-ODFV read-path and write-path transform latency, and a side-by-side Pandas vs Python ODFV comparison: + +
+ Grafana dashboard showing online store read latency, ODFV transformation latency by name, and Pandas vs Python ODFV comparison +
+ +If store reads dominate, the bottleneck is your online store (consider Redis instead of PostgreSQL, or tune your connection pool). If ODFV transforms dominate, consider switching from Pandas mode to Python mode — or re-evaluate whether the transformation should be precomputed during materialization instead of computed on the fly. + +### Pandas vs Python ODFV Comparison + +The `mode` label on transformation metrics makes it straightforward to compare Pandas and Python ODFV performance. The bottom-left panel in the dashboard above shows p50/p95 latencies for Pandas-mode and Python-mode ODFVs overlaid, making the comparison immediate. You can also query these directly: + +```promql +# Pandas p95 read-path latency +histogram_quantile(0.95, + sum(rate(feast_feature_server_transformation_duration_seconds_bucket{mode="pandas"}[1m])) by (le)) + +# Python p95 read-path latency +histogram_quantile(0.95, + sum(rate(feast_feature_server_transformation_duration_seconds_bucket{mode="python"}[1m])) by (le)) +``` + +## Building Alerts + +Here are the recommended alert rules, ordered by impact: + +### Feature Freshness SLO Breach + +```yaml +- alert: FeastFeatureViewStale + expr: feast_feature_freshness_seconds > 3600 + for: 5m + labels: + severity: critical + annotations: + summary: > + Feature view {{ $labels.feature_view }} in project {{ $labels.project }} + has not been materialized in {{ $value | humanizeDuration }}. + impact: Models consuming this feature view are receiving stale data. +``` + +### Materialization Failures + +```yaml +- alert: FeastMaterializationFailing + expr: rate(feast_materialization_total{status="failure"}[15m]) > 0 + for: 5m + labels: + severity: critical + annotations: + summary: > + Materialization is failing for feature view {{ $labels.feature_view }}. +``` + +### High p99 Latency + +```yaml +- alert: FeastHighLatency + expr: | + histogram_quantile(0.99, + rate(feast_feature_server_request_latency_seconds_bucket{ + endpoint="/get-online-features" + }[5m]) + ) > 1.0 + for: 5m + labels: + severity: warning + annotations: + summary: > + Feast p99 latency for online features is {{ $value }}s. +``` + +### High Error Rate + +```yaml +- alert: FeastHighErrorRate + expr: | + sum(rate(feast_feature_server_request_total{status="error"}[5m])) + / sum(rate(feast_feature_server_request_total[5m])) + > 0.01 + for: 5m + labels: + severity: warning + annotations: + summary: > + Feast feature server error rate is {{ $value | humanizePercentage }}. +``` + +## Building a Grafana Dashboard + +With these metrics exposed, you can build a Grafana dashboard that gives you a complete operational picture of your feature server. We've published a [ready-to-import Grafana dashboard JSON](https://github.com/ntkathole/feast-automated-setups/blob/main/feast-prometheus-metrics/grafana_dashboard.json) that covers all the panels described below — import it into your Grafana instance and point it at your Prometheus datasource to get started immediately. + +### Connecting Prometheus to Feast + +Add the Feast metrics endpoint to your Prometheus scrape configuration: + +```yaml +scrape_configs: + - job_name: feast + static_configs: + - targets: [":8000"] + scrape_interval: 15s +``` + +Once Prometheus is scraping, verify the raw metrics output: + +```bash +curl -s http://localhost:8000 | grep feast_ +``` + +### Key PromQL Queries + +Here are the most useful queries for building your own panels or running ad-hoc investigations in the Prometheus UI: + +**Throughput and errors:** + +```promql +# Request rate by endpoint +rate(feast_feature_server_request_total[5m]) + +# Error rate +sum(rate(feast_feature_server_request_total{status="error"}[5m])) + / sum(rate(feast_feature_server_request_total[5m])) +``` + +**Latency percentiles:** + +```promql +# p99 latency for online features +histogram_quantile(0.99, + rate(feast_feature_server_request_latency_seconds_bucket{endpoint="/get-online-features"}[5m])) + +# Online store read p95 +histogram_quantile(0.95, + sum(rate(feast_feature_server_online_store_read_duration_seconds_bucket[1m])) by (le)) + +# ODFV transform p95 by name and mode +histogram_quantile(0.95, + sum(rate(feast_feature_server_transformation_duration_seconds_bucket[1m])) by (le, odfv_name)) + +# ODFV write-path transform p95 by name +histogram_quantile(0.95, + sum(rate(feast_feature_server_write_transformation_duration_seconds_bucket[1m])) by (le, odfv_name)) +``` + +**Latency decomposition:** + +```promql +# Average total request latency +rate(feast_feature_server_request_latency_seconds_sum{endpoint="/get-online-features"}[5m]) + / rate(feast_feature_server_request_latency_seconds_count{endpoint="/get-online-features"}[5m]) + +# Average store read time +rate(feast_feature_server_online_store_read_duration_seconds_sum[5m]) + / rate(feast_feature_server_online_store_read_duration_seconds_count[5m]) + +# Average ODFV transform time +rate(feast_feature_server_transformation_duration_seconds_sum[5m]) + / rate(feast_feature_server_transformation_duration_seconds_count[5m]) +``` + +**Pandas vs Python comparison:** + +```promql +# Pandas p95 +histogram_quantile(0.95, + sum(rate(feast_feature_server_transformation_duration_seconds_bucket{mode="pandas"}[1m])) by (le)) + +# Python p95 +histogram_quantile(0.95, + sum(rate(feast_feature_server_transformation_duration_seconds_bucket{mode="python"}[1m])) by (le)) +``` + +**ML-specific signals:** + +```promql +# Feature freshness — views stale beyond 1 hour +feast_feature_freshness_seconds > 3600 + +# Materialization failure rate +rate(feast_materialization_total{status="failure"}[1h]) + +# Average entities per request +rate(feast_online_features_entity_count_sum[5m]) + / rate(feast_online_features_entity_count_count[5m]) + +# Push rate by source +rate(feast_push_request_total[5m]) +``` + +## Try the Automated Demo + +Want to see all of this in action without manual setup? We've published an [automated demo](https://github.com/ntkathole/feast-automated-setups/tree/main/feast-prometheus-metrics) that deploys a Feast feature server with metrics, a Prometheus instance, and the pre-built Grafana dashboard — all with a single `./setup.sh` command. It includes a traffic generator that exercises every metric category (plain online features, Pandas and Python ODFVs, push, materialize, and write-path transforms), so the dashboard populates immediately. + +## Kubernetes: Automatic Prometheus Discovery + +For teams running Feast on Kubernetes, the Feast Operator now auto-generates a `ServiceMonitor` when `metrics: true` is set on the online store. The operator: + +1. Detects the `monitoring.coreos.com` API group at startup +2. If present, creates a `ServiceMonitor` owned by the `FeatureStore` CR, targeting the `metrics` port (8000) +3. If absent (vanilla Kubernetes without Prometheus Operator), skips silently — no errors, no CRD dependency + +This means on an OpenShift or Prometheus-Operator-enabled cluster, metrics discovery is fully automatic — no manual `ServiceMonitor` creation required. The `ServiceMonitor` is cleaned up automatically when the `FeatureStore` CR is deleted or `metrics` is set back to `false`. + +For teams using [KEDA for autoscaling](/blog/scaling-feast-feature-server), these Prometheus metrics also serve as scaling signals. For example, you can scale the feature server based on request rate: + +```yaml +apiVersion: keda.sh/v1alpha1 +kind: ScaledObject +metadata: + name: feast-scaledobject +spec: + scaleTargetRef: + apiVersion: feast.dev/v1 + kind: FeatureStore + name: my-feast + triggers: + - type: prometheus + metadata: + serverAddress: http://prometheus.monitoring.svc:9090 + query: sum(rate(feast_feature_server_request_total[2m])) + threshold: "100" +``` + +## Metrics Summary + +| Category | Metric | What It Answers | +|---|---|---| +| Request | `feast_feature_server_request_total` | What is my throughput and error rate? | +| Request | `feast_feature_server_request_latency_seconds` | What are my p50/p99 latencies? | +| Online Features | `feast_online_features_entity_count` | What is my traffic shape? | +| Store Read | `feast_feature_server_online_store_read_duration_seconds` | Is my online store the bottleneck? | +| ODFV Transform | `feast_feature_server_transformation_duration_seconds` | How expensive are my read-path transforms? | +| ODFV Transform | `feast_feature_server_write_transformation_duration_seconds` | How expensive are my write-path transforms? | +| Push | `feast_push_request_total` | Is my ingestion pipeline sending data? | +| Materialization | `feast_materialization_total` | Are my pipelines succeeding? | +| Materialization | `feast_materialization_duration_seconds` | How long do my pipelines take? | +| Freshness | `feast_feature_freshness_seconds` | How stale is the data my models are using? | +| Resource | `feast_feature_server_cpu_usage` / `memory_usage` | Is my server healthy? | + +## How Can I Get Started? + +1. **Enable metrics**: `feast serve --metrics` or set `metrics.enabled: true` in your `feature_store.yaml` +2. **Verify the endpoint**: `curl http://localhost:8000` +3. **Import the dashboard**: Grab the [Grafana dashboard JSON](https://github.com/ntkathole/feast-automated-setups/blob/main/feast-prometheus-metrics/grafana_dashboard.json) and import it into your Grafana instance +4. **Set up alerts**: Start with freshness and materialization failures — those catch the problems that affect ML model quality first +5. **Try the automated demo**: Run the [feast-prometheus-metrics setup](https://github.com/ntkathole/feast-automated-setups/tree/main/feast-prometheus-metrics) for a one-command local experience +6. Check out the [Feast documentation](https://docs.feast.dev/) for the full configuration reference +7. Join the [Feast Slack](https://slack.feast.dev) to share feedback and ask questions + +We're excited to bring production-grade observability to Feast and welcome feedback from the community! diff --git a/infra/website/docs/blog/feast-mlflow-kubeflow.md b/infra/website/docs/blog/feast-mlflow-kubeflow.md new file mode 100644 index 00000000000..3e15cbda26a --- /dev/null +++ b/infra/website/docs/blog/feast-mlflow-kubeflow.md @@ -0,0 +1,534 @@ +--- +title: "Feast + MLflow + Kubeflow: A Unified AI/ML Lifecycle" +description: Learn how to use Feast, MLflow, and Kubeflow to power your AI/ML Lifecycle +date: 2026-03-09 +authors: ["Francisco Javier Arceo", "Nikhil Kathole"] +--- + +
+ Feast, MLflow, and Kubeflow +
+ +# Feast + MLflow + Kubeflow: A Unified AI/ML Lifecycle + +## Overview + +Building production-ready machine learning systems requires more than a great model. It demands a clear separation of concerns between feature management, experiment tracking, and workflow orchestration. This post explores how [Feast](https://feast.dev/), [MLflow](https://mlflow.org/), and [Kubeflow](https://www.kubeflow.org/) work together as complementary open-source tools to cover the full AI/ML lifecycle — from raw data to serving predictions at scale. + +These tools are not competitors. Each one occupies a distinct role: + +* **Feast** manages feature data: defining, transforming, storing, and serving features consistently for both training and inference. It also tracks feature lineage and supports data quality monitoring. +* **MLflow** tracks experiments: logging runs, metrics, parameters, artifacts, and candidate models. +* **Kubeflow** orchestrates ML workflows: running distributed training, hyperparameter sweeps, and end-to-end pipelines on Kubernetes. + +Together they form a complete, open-source foundation for operationalizing ML. + +### How are Feast, MLflow, and Kubeflow different? + +If you are new to these tools, it is natural to wonder whether they overlap. The short answer is: they solve fundamentally different problems in the ML lifecycle. The table below makes this concrete. + +| Capability | Feast | MLflow | Kubeflow | +|---|---|---|---| +| Define and version feature schemas | Yes | No | No | +| Store and serve features (online + offline) | Yes | No | No | +| Point-in-time-correct feature retrieval | Yes | No | No | +| Feature transformations (training = serving) | Yes | No | No | +| Feature lineage and registry | Yes | No | No | +| Data quality validation on features | Yes | No | No | +| Log experiments, metrics, and parameters | No | Yes | No | +| Track and compare model versions | No | Yes | No | +| Model registry (promote / alias models) | No | Yes | No | +| Orchestrate multi-step ML pipelines | No | No | Yes (Pipelines) | +| Distributed training on Kubernetes | No | No | Yes (Training Operator) | +| Hyperparameter tuning | No | Yes (with Optuna, etc.) | Yes (Katib) | + +A few common misconceptions: + +* **"Can't MLflow track my features?"** — MLflow can *log* feature names as parameters, but it does not *define*, *store*, *transform*, or *serve* features. It has no concept of an offline store, an online store, or point-in-time joins. Feast fills that gap. +* **"Doesn't Kubeflow handle everything end-to-end?"** — Kubeflow orchestrates *workflows* — it tells your pipeline steps when to run and where. But it does not provide feature storage, experiment tracking, or model versioning. You still need Feast for the data layer and MLflow for the experiment layer. +* **"Why do I need Feast if I just read from a database?"** — Without Feast, teams typically duplicate feature logic between training scripts and serving endpoints, which leads to training–serving skew. Feast guarantees the same transformation and retrieval logic is used in both contexts. + +With that context, the rest of this post walks through each tool in detail and shows how they hand off to one another in practice. + +This topic has been explored by the community before — the post ["Feast with AI: Feed Your MLflow Models with Feature Store"](https://blog.qooba.net/2021/05/22/feast-with-ai-feed-your-mlflow-models-with-feature-store/) by [@qooba](https://github.com/qooba) is an excellent early look at combining Feast and MLflow. For a hands-on, end-to-end example of Feast and Kubeflow working together, see ["From Raw Data to Model Serving: A Blueprint for the AI/ML Lifecycle with Kubeflow and Feast"](/blog/kubeflow-fraud-detection-e2e) by Helber Belmiro. This post builds on that prior work and brings all three tools — Feast, MLflow, and Kubeflow — into a single narrative. + +--- + +## The AI/ML Lifecycle + +A typical production ML project passes through several stages: + +1. **Feature development** — raw data is transformed into meaningful signals. +2. **Model development** — data scientists experiment with algorithms, features, and hyperparameters. +3. **Model evaluation & selection** — the best experiment is chosen for promotion. +4. **Production deployment** — the selected model is deployed and features are served in real time. +5. **Monitoring & iteration** — model and feature health is observed; the cycle repeats. + +The diagram below maps each stage to its primary tool: + +``` +Raw Data ──► Feast (Feature Engineering & Storage) + │ + ▼ + MLflow + Kubeflow Pipelines (Experiment Tracking & Orchestration) + │ + ▼ + Kubeflow Training Operator (Distributed Training) + │ + ▼ + MLflow Model Registry (Candidate Models) + │ + ▼ + Feast Online Store + Feature Server (Production Serving) +``` + +--- + +## Feast: Feature Development, Iteration, and Serving + +Feast is the data layer of the ML stack. Its core job is to make the same feature logic available both at training time (via the offline store) and at inference time (via the online store), eliminating training–serving skew. Beyond storage and serving, Feast also handles **feature transformations**, **feature lineage tracking**, and **data quality monitoring** — capabilities that are essential when moving features from experimentation to production. + +### Defining features + +A Feast `FeatureView` declares how a feature is computed and where it is stored: + +```python +from datetime import timedelta +from feast import FeatureView, Field, FileSource +from feast.types import Float64, Int64 + +driver_stats = FeatureView( + name="driver_hourly_stats", + entities=["driver_id"], + ttl=timedelta(days=7), + schema=[ + Field(name="conv_rate", dtype=Float64), + Field(name="acc_rate", dtype=Float64), + Field(name="avg_daily_trips", dtype=Int64), + ], + source=FileSource(path="data/driver_stats.parquet", timestamp_field="event_timestamp"), +) +``` + +After running `feast apply`, these features are registered in the Feast registry and visible in the Feast UI: + +
+ Feast UI showing the Feature List for the Driver Ranking project with conv_rate, acc_rate, and avg_daily_trips features +

The Feast UI showing three registered features in the driver_hourly_stats feature view — conv_rate, acc_rate, and avg_daily_trips — each linked to the Driver Ranking project.

+
+ +### Retrieving historical features for training + +Point-in-time-correct historical features are retrieved from the offline store. This prevents future data from leaking into training examples: + +```python +from feast import FeatureStore +import pandas as pd + +store = FeatureStore(repo_path=".") + +entity_df = pd.DataFrame({ + "driver_id": [1001, 1002, 1003], + "event_timestamp": pd.to_datetime(["2025-01-01", "2025-01-02", "2025-01-03"]), +}) + +training_df = store.get_historical_features( + entity_df=entity_df, + features=["driver_hourly_stats:conv_rate", "driver_hourly_stats:acc_rate"], +).to_df() +``` + +### Materializing features for real-time serving + +When a model is promoted to production, features are materialized to the online store so they can be retrieved with single-digit millisecond latency: + +```python +from datetime import datetime + +store.materialize_incremental(end_date=datetime.utcnow()) +``` + +Serving then becomes a single call: + +```python +features = store.get_online_features( + features=["driver_hourly_stats:conv_rate", "driver_hourly_stats:acc_rate"], + entity_rows=[{"driver_id": 1001}], +).to_dict() +``` + +### Feature transformations + +Feast supports on-demand feature transformations, allowing you to define transformation logic that runs at retrieval time — both offline (for training) and online (for serving) — using the same Python function. This eliminates the need to duplicate transformation code across training and inference pipelines: + +```python +from feast.on_demand_feature_view import on_demand_feature_view +from feast import Field +from feast.types import Float64 + +@on_demand_feature_view( + sources=[driver_stats], + schema=[Field(name="conv_acc_ratio", dtype=Float64)], +) +def driver_ratios(inputs): + df = inputs.copy() + df["conv_acc_ratio"] = df["conv_rate"] / (df["acc_rate"] + 1e-6) + return df[["conv_acc_ratio"]] +``` + +Here `driver_stats` is the `FeatureView` object defined earlier. The `sources` parameter accepts `FeatureView`, `RequestSource`, or `FeatureViewProjection` objects. + +Using `on_demand_feature_view` ensures that the same transformation logic is applied whether features are retrieved from the offline store for training or from the online store at inference time, preventing transformation skew. + +### Feature lineage + +The Feast feature registry acts as the single source of truth for feature definitions. Every `FeatureView`, data source, entity, and transformation is registered and versioned in the registry. This gives you full lineage from raw data source through transformation logic to the feature values consumed by a model — a critical requirement for debugging, auditing, and regulatory compliance. + +You can inspect the lineage of any feature programmatically: + +```python +from feast import FeatureStore + +store = FeatureStore(repo_path=".") +feature_view = store.get_feature_view("driver_hourly_stats") +print(feature_view.source) # upstream data source +print(feature_view.schema) # feature schema +``` + +For cross-system lineage that extends beyond Feast into upstream data pipelines and downstream model training, Feast also supports native [OpenLineage integration](/blog/feast-openlineage-integration). Enabling it in your `feature_store.yaml` automatically emits lineage events on `feast apply` and `feast materialize`, letting you visualize the full data flow in tools like [Marquez](https://marquezproject.ai/). + +### Data quality monitoring + +Feast integrates with data quality frameworks like [Great Expectations](https://greatexpectations.io/) to detect feature drift, stale data, and schema violations before they silently degrade model performance. The workflow centers on Feast's `SavedDataset` and `ValidationReference` APIs: you save a profiled dataset during training, define a profiler using Great Expectations, and then validate new feature data against that reference in subsequent runs. + +```python +from feast import FeatureStore +from feast.dqm.profilers.ge_profiler import ge_profiler +from great_expectations.core import ExpectationSuite +from great_expectations.dataset import PandasDataset + +store = FeatureStore(repo_path=".") + +@ge_profiler +def my_profiler(dataset: PandasDataset) -> ExpectationSuite: + dataset.expect_column_values_to_be_between("conv_rate", min_value=0, max_value=1) + dataset.expect_column_values_to_be_between("acc_rate", min_value=0, max_value=1) + return dataset.get_expectation_suite() + +reference_job = store.get_historical_features( + entity_df=entity_df, + features=["driver_hourly_stats:conv_rate", "driver_hourly_stats:acc_rate"], +) + +dataset = store.create_saved_dataset( + from_=reference_job, + name="driver_stats_validation", + storage=storage, +) + +reference = dataset.as_reference(name="driver_stats_ref", profiler=my_profiler) + +new_job = store.get_historical_features( + entity_df=new_entity_df, + features=["driver_hourly_stats:conv_rate", "driver_hourly_stats:acc_rate"], +) +new_job.to_df(validation_reference=reference) +``` + +If validation fails, Feast raises a `ValidationFailed` exception with details on which expectations were violated. Monitoring feature distributions over time — and comparing them to the distributions seen during training — allows you to detect training–serving skew early, before it causes silent model degradation in production. + +### Feast Feature Registry vs. MLflow Model Registry + +A common question is how the **Feast feature registry** relates to the **MLflow model registry**. They are different things that serve complementary roles. + +| | Feast Feature Registry | MLflow Model Registry | +|---|---|---| +| **What it tracks** | Feature definitions, schemas, data sources, entity relationships | Model artifacts, versions, model aliases (e.g., "production", "staging") | +| **Primary users** | Feature engineers, data scientists, ML platform teams | Data scientists, ML engineers | +| **Relationship to production** | Defines what data is available for training *and* serving | Tracks which model version is promoted to production | +| **Scope** | All features ever defined — a superset of what any one model uses | All model versions, including candidates that never ship | + +This distinction is important: the **Feast registry is a superset of the MLflow model registry** from a feature perspective. During experimentation, a data scientist may train models using dozens of features. Once a model is selected for production, only a *subset* of those features will be needed for online serving. Feast's registry records all available features; the specific features required by the production model are a narrower slice that corresponds to what MLflow logged as model inputs. + +--- + +## MLflow: Experiment Tracking, Hyperparameter Optimization, and Feature Selection + +MLflow is the experimentation layer. It answers the question: *"Which combination of features, model architecture, and hyperparameters produced the best result?"* + +### Logging a training run with Feast features + +Because Feast provides a consistent `get_historical_features` API, it is straightforward to combine it with MLflow tracking: + +```python +import mlflow +import mlflow.sklearn +from feast import FeatureStore +from sklearn.linear_model import LogisticRegression +from sklearn.model_selection import train_test_split +from sklearn.metrics import roc_auc_score +import pandas as pd + +store = FeatureStore(repo_path=".") + +entity_df = pd.read_parquet("data/driver_labels.parquet") +feature_df = store.get_historical_features( + entity_df=entity_df, + features=["driver_hourly_stats:conv_rate", "driver_hourly_stats:acc_rate", "driver_hourly_stats:avg_daily_trips"], +).to_df() + +X = feature_df[["conv_rate", "acc_rate", "avg_daily_trips"]] +y = feature_df["label"] +X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) + +with mlflow.start_run(): + mlflow.log_param("features", ["conv_rate", "acc_rate", "avg_daily_trips"]) + mlflow.log_param("model_type", "LogisticRegression") + + model = LogisticRegression() + model.fit(X_train, y_train) + + auc = roc_auc_score(y_test, model.predict_proba(X_test)[:, 1]) + mlflow.log_metric("auc", auc) + + # Log the feature store snapshot alongside the model + mlflow.sklearn.log_model(model, artifact_path="model") + mlflow.log_artifact("feature_store.yaml", artifact_path="feast_config") +``` + +Logging `feature_store.yaml` together with the model artifact ensures that, at any future point, the exact set of Feast feature definitions used for that run can be reproduced. + +### Feature selection with MLflow + +One of the most powerful uses of Feast + MLflow together is systematic **feature selection**: training models with different subsets of Feast features and using MLflow's comparison UI to identify which combination produces the best results. This is far more rigorous than manually trying feature sets in a notebook, and the results are often counterintuitive. + +The pattern is to loop over candidate feature subsets, retrieve each one from Feast, train a model, and log the metrics and feature names as a separate MLflow run: + +```python +import mlflow +import mlflow.sklearn +from feast import FeatureStore +from sklearn.linear_model import LogisticRegression +from sklearn.model_selection import train_test_split +from sklearn.metrics import roc_auc_score +import pandas as pd + +store = FeatureStore(repo_path=".") + +entity_df = pd.read_parquet("data/driver_labels.parquet") + +# Define candidate feature subsets to compare +feature_subsets = { + "acc_rate_only": ["driver_hourly_stats:acc_rate"], + "acc_rate_trips": ["driver_hourly_stats:acc_rate", "driver_hourly_stats:avg_daily_trips"], + "all_features": ["driver_hourly_stats:conv_rate", "driver_hourly_stats:acc_rate", + "driver_hourly_stats:avg_daily_trips"], +} + +with mlflow.start_run(run_name="feast_feature_selection"): + for subset_name, feature_refs in feature_subsets.items(): + feature_df = store.get_historical_features( + entity_df=entity_df, + features=feature_refs, + ).to_df() + + feature_cols = [ref.split(":")[1] for ref in feature_refs] + X = feature_df[feature_cols] + y = feature_df["label"] + X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) + + with mlflow.start_run(run_name=subset_name, nested=True): + mlflow.log_param("features", feature_cols) + model = LogisticRegression() + model.fit(X_train, y_train) + auc = roc_auc_score(y_test, model.predict_proba(X_test)[:, 1]) + mlflow.log_metric("auc", auc) + mlflow.sklearn.log_model(model, artifact_path="model") +``` + +After running, the MLflow UI lets you sort all nested runs by AUC and immediately see which feature subset wins. The results can be surprising — for example, with synthetic driver data a single feature may outperform the full feature set: + +| Features | Model | AUC | +|---|---|---| +| `acc_rate` only | LogisticRegression | 0.645 | +| `acc_rate` + `avg_daily_trips` | LogisticRegression | 0.613 | +| All 3 features | LogisticRegression | 0.570 | + +
+ MLflow UI showing a LogisticRegression run with all three Feast features, metrics, parameters, and feature tags +

The MLflow UI showing a LogisticRegression run trained with all three Feast features (conv_rate, acc_rate, avg_daily_trips). The run logs five metrics (accuracy, AUC, precision, recall, F1), the feature list as a parameter, and the demo tags each included feature (e.g., feature_conv_rate: included) for easy filtering.

+
+ +This is exactly the kind of insight MLflow's comparison interface is built for. You can sort runs by AUC, filter by which features were included, and visualize performance across experiments. Note that with synthetic data these numbers won't carry real meaning — the point is that the tooling makes it trivial to *observe* these differences systematically and let data drive the feature selection decision. + +
+ MLflow comparison view showing three experiment runs side by side with different feature combinations +

MLflow's comparison view showing three runs side by side with different feature subsets. The "Show diff only" toggle highlights how the features parameter varies across runs, making it easy to identify which combination of Feast features produces the best results.

+
+ +
+ MLflow metric charts showing accuracy, AUC, F1, precision, and recall grouped by num_features across three feature subsets +

MLflow's metric charts view visualizing accuracy, AUC, F1, precision, and recall across all feature selection runs, grouped by num_features. This chart makes it easy to spot how model performance changes as more Feast features are included.

+
+ +Once you have identified the winning subset, the Feast registry ensures that only those features need to be materialized into the online store for production serving. + +### Hyperparameter sweeps + +MLflow integrates natively with hyperparameter optimization libraries. For example, using MLflow with [Optuna](https://optuna.org/): + +```python +import optuna +import mlflow + +def objective(trial): + C = trial.suggest_float("C", 1e-3, 10.0, log=True) + max_iter = trial.suggest_int("max_iter", 100, 1000) + + with mlflow.start_run(nested=True): + mlflow.log_params({"C": C, "max_iter": max_iter}) + model = LogisticRegression(C=C, max_iter=max_iter) + model.fit(X_train, y_train) + auc = roc_auc_score(y_test, model.predict_proba(X_test)[:, 1]) + mlflow.log_metric("auc", auc) + return auc + +with mlflow.start_run(run_name="optuna_sweep"): + study = optuna.create_study(direction="maximize") + study.optimize(objective, n_trials=20) +``` + +All trials, their parameters, and their metrics are automatically captured in the MLflow tracking server, making it easy to compare runs and select the best candidate for promotion. + +--- + +## Kubeflow: Orchestrating the ML Workflow + +[Kubeflow](https://www.kubeflow.org/) brings Kubernetes-native orchestration to the ML lifecycle. Its two most relevant components here are: + +* **Kubeflow Pipelines** — a platform for building and deploying repeatable ML workflows as DAGs. +* **Kubeflow Training Operator** — manages distributed training jobs (PyTorchJob, TFJob, etc.) on Kubernetes. + +### Kubeflow Pipelines integrating Feast and MLflow + +Kubeflow Pipelines lets you compose the entire workflow — feature retrieval, training, evaluation, and registration — as a single, reproducible pipeline: + +```python +from kfp import dsl + +@dsl.component(base_image="python:3.10-slim", packages_to_install=["feast", "mlflow", "scikit-learn", "pandas", "pyarrow"]) +def retrieve_features(entity_df_path: str, feature_store_repo: str, output_path: dsl.Output[dsl.Dataset]): + from feast import FeatureStore + import pandas as pd + + store = FeatureStore(repo_path=feature_store_repo) + entity_df = pd.read_parquet(entity_df_path) + df = store.get_historical_features( + entity_df=entity_df, + features=["driver_hourly_stats:conv_rate", "driver_hourly_stats:acc_rate"], + ).to_df() + df.to_parquet(output_path.path) + + +@dsl.component(base_image="python:3.10-slim", packages_to_install=["feast", "mlflow", "scikit-learn", "pandas"]) +def train_and_log(features_path: dsl.Input[dsl.Dataset], mlflow_tracking_uri: str, model_name: str): + import mlflow, mlflow.sklearn + import pandas as pd + from sklearn.linear_model import LogisticRegression + from sklearn.model_selection import train_test_split + from sklearn.metrics import roc_auc_score + + mlflow.set_tracking_uri(mlflow_tracking_uri) + df = pd.read_parquet(features_path.path) + X = df[["conv_rate", "acc_rate"]] + y = df["label"] + X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) + + with mlflow.start_run(): + model = LogisticRegression() + model.fit(X_train, y_train) + auc = roc_auc_score(y_test, model.predict_proba(X_test)[:, 1]) + mlflow.log_metric("auc", auc) + mlflow.sklearn.log_model(model, artifact_path="model", registered_model_name=model_name) + + +@dsl.pipeline(name="feast-mlflow-training-pipeline") +def training_pipeline(entity_df_path: str, feature_store_repo: str, mlflow_tracking_uri: str, model_name: str): + fetch_step = retrieve_features(entity_df_path=entity_df_path, feature_store_repo=feature_store_repo) + train_and_log( + features_path=fetch_step.outputs["output_path"], + mlflow_tracking_uri=mlflow_tracking_uri, + model_name=model_name, + ) +``` + +Each step runs in its own container, making the pipeline portable and reproducible across environments. + +### Distributed training with the Kubeflow Training Operator + +For large-scale models, the [Kubeflow Training Operator](https://www.kubeflow.org/docs/components/training/) schedules distributed training jobs. Feast integrates naturally because it provides a consistent Python API for retrieving feature data — whether training is running on a single machine or across a cluster of workers. Each worker calls `get_historical_features` for its shard of the entity dataframe, and the resulting features are passed directly into the training loop. + +--- + +## Bringing It All Together: Feast → MLflow → Production + +The following end-to-end workflow shows how the three tools hand off to one another: + +### Step 1: Register and materialize features with Feast + +```bash +feast apply # Register feature definitions in the registry +feast materialize-incremental $(date -u +"%Y-%m-%dT%H:%M:%S") +``` + +### Step 2: Run experiments and select the best model with MLflow + +Feature engineers iterate on feature definitions in Feast while data scientists run experiments in MLflow, logging which features were used for each run. The best run is registered in the MLflow Model Registry: + +```python +mlflow.register_model(f"runs:/{best_run_id}/model", "driver_conversion_model") +``` + +### Step 3: Promote to production + +Promoting the model in MLflow signals that it is ready for deployment. At this point, you also know the exact subset of Feast features required by that model — these are the features to materialize and serve. + +```python +client = mlflow.tracking.MlflowClient() +client.set_registered_model_alias( + name="driver_conversion_model", alias="production", version="3" +) +``` + +### Step 4: Serve features and predictions + +The deployed model reads its inputs from the Feast online store at inference time: + +```python +from feast import FeatureStore + +store = FeatureStore(repo_path=".") + +def predict(driver_id: int) -> float: + features = store.get_online_features( + features=["driver_hourly_stats:conv_rate", "driver_hourly_stats:acc_rate"], + entity_rows=[{"driver_id": driver_id}], + ).to_dict() + return model.predict_proba([[features["conv_rate"][0], features["acc_rate"][0]]])[0][1] +``` + +--- + +## Summary + +| Concern | Tool | +|---|---| +| Feature definition, storage, and serving | **Feast** | +| Experiment tracking, metric logging, and model versioning | **MLflow** | +| Workflow orchestration and distributed training | **Kubeflow Pipelines + Training Operator** | +| Hyperparameter optimization | **MLflow + Katib (Kubeflow)** | +| Production feature serving | **Feast Online Store / Feature Server** | + +Feast, MLflow, and Kubeflow are each best-in-class at what they do, and they are designed to work alongside one another rather than replace each other. By combining them you get a fully open-source, end-to-end ML platform that handles everything from raw data to live predictions — without lock-in. + +If you are new to Feast, check out the [Feast documentation](https://docs.feast.dev/) and [GitHub](https://github.com/feast-dev/feast) to get started. Join the community on [Slack](http://slack.feastsite.wpenginepowered.com/) and let us know how you are using Feast in your ML stack! diff --git a/infra/website/docs/blog/feast-oracle-offline-store.md b/infra/website/docs/blog/feast-oracle-offline-store.md new file mode 100644 index 00000000000..e8ce13d81ae --- /dev/null +++ b/infra/website/docs/blog/feast-oracle-offline-store.md @@ -0,0 +1,274 @@ +--- +title: "Feast Meets Oracle: Unlocking Feature Store for Oracle Database Users" +description: Oracle Database is now a fully featured Feast offline store, integrated with Kubernetes-native operators. This enables teams to leverage their existing Oracle infrastructure for scalable, production ML feature engineering. +date: 2026-03-16 +authors: ["Aniket Paluskar", "Srihari Venkataramaiah"] +--- + +
+ Feast and Oracle Database +
+ +# Feast Meets Oracle: Unlocking Feature Store for Oracle Database Users + +## The Problem: Your Data Is Already in Oracle — Why Move It? + +If you work in a Fortune 500 company, chances are your most valuable data lives in Oracle Database. It is the one of the most widely used enterprise database for a reason — decades of battle-tested reliability, performance, and governance have made it the backbone of mission-critical systems across finance, healthcare, telecommunications, government, and retail. + +But here's the friction: when ML teams want to build features for their models, they typically export data *out* of Oracle into some other system — a data lake, a warehouse, a CSV on someone's laptop. That data movement introduces latency, staleness bugs, security blind spots, and an entire class of silent failures that only surface when a model starts degrading in production. + +**What if you didn't have to move your data at all?** + +With Feast's new Oracle offline store support — now fully integrated into the Feast Kubernetes operator — you can define, compute, and serve ML features directly from your existing Oracle infrastructure. No data migration. No pipeline duct tape. No compromises. + +--- + +## What's New + +Oracle Database is now a first-class offline store in Feast, supported across the full stack: + +| Layer | What Changed | +|---|---| +| **Python SDK** | `OracleOfflineStore` and `OracleSource` — a complete offline store implementation built on `ibis-framework[oracle]` | +| **Feast Operator (v1 API)** | `oracle` is a validated persistence type in the `FeatureStore` CRD, with Secret-backed credential management | +| **CRD & Validation** | Kubernetes validates `oracle` at admission time — bad configs are rejected before they ever reach the operator | +| **Type System** | Full Oracle-to-Feast type mapping covering `NUMBER`, `VARCHAR2`, `CLOB`, `BLOB`, `BINARY_FLOAT`, `TIMESTAMP`, and more | +| **Documentation** | Reference docs for the [Oracle offline store](https://docs.feast.dev/reference/offline-stores/oracle) and [Oracle data source](https://docs.feast.dev/reference/data-sources/oracle) | + +This isn't a thin wrapper or a partial integration. The Oracle offline store supports the complete Feast offline store interface: + +- **`get_historical_features`** — point-in-time correct feature retrieval for training datasets, preventing future data leakage +- **`pull_latest_from_table_or_query`** — fetch the most recent feature values +- **`pull_all_from_table_or_query`** — full table scans for batch processing +- **`offline_write_batch`** — write feature data back to Oracle +- **`write_logged_features`** — persist logged features for monitoring and debugging + +--- + +## Why This Matters: Oracle Is Where the Enterprise Lives + +Oracle Database isn't just another backend option. It is the database that runs the world's banks, hospitals, supply chains, and telecom networks. When we say "number one enterprise database," we mean it in terms of: + +- **Installed base** — More Fortune 100 companies run Oracle than any other database +- **Data gravity** — Petabytes of the world's most regulated, most valuable data already sits in Oracle +- **Operational maturity** — Decades of enterprise features: partitioning, RAC, Data Guard, Advanced Security, Audit Vault + +For ML teams in these organizations, the path to production has always involved a painful detour: extract data from Oracle, load it somewhere else, build features there, then figure out how to serve them. Every step in that chain is a potential point of failure, a security review, and a compliance headache. + +Feast's Oracle integration eliminates the detour entirely. Your features are computed where your data already has governance, backup, encryption, and access controls in place. + +--- + +## How It Works: From Oracle Table to Production Features + +### Step 1: Configure your feature store + +Point Feast at your Oracle database in `feature_store.yaml`: + +```yaml +project: my_project +registry: data/registry.db +provider: local +offline_store: + type: oracle + host: oracle-db.example.com + port: 1521 + user: feast_user + password: ${DB_PASSWORD} + service_name: ORCL +online_store: + path: data/online_store.db +``` + +Feast supports three Oracle connection modes — `service_name`, `sid`, or `dsn` — so it fits however your DBA has set things up: + +```yaml +# Using SID +offline_store: + type: oracle + host: oracle-db.example.com + port: 1521 + user: feast_user + password: ${DB_PASSWORD} + sid: ORCL + +# Using full DSN +offline_store: + type: oracle + host: oracle-db.example.com + port: 1521 + user: feast_user + password: ${DB_PASSWORD} + dsn: "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=oracle-db.example.com)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCL)))" +``` + +### Step 2: Define features backed by Oracle tables + +```python +from feast import FeatureView, Field, Entity +from feast.types import Float64, Int64 +from feast.infra.offline_stores.contrib.oracle_offline_store.oracle_source import OracleSource +from datetime import timedelta + +customer = Entity(name="customer_id", join_keys=["customer_id"]) + +customer_transactions = OracleSource( + name="customer_txn_source", + table_ref="ANALYTICS.CUSTOMER_TRANSACTIONS", + event_timestamp_column="TXN_TIMESTAMP", +) + +customer_features = FeatureView( + name="customer_transaction_features", + entities=[customer], + ttl=timedelta(days=30), + schema=[ + Field(name="avg_txn_amount_30d", dtype=Float64), + Field(name="txn_count_7d", dtype=Int64), + Field(name="max_txn_amount_90d", dtype=Float64), + ], + source=customer_transactions, +) +``` + +### Step 3: Retrieve features for training + +```python +from feast import FeatureStore +import pandas as pd + +store = FeatureStore(repo_path=".") + +entity_df = pd.DataFrame({ + "customer_id": [101, 102, 103, 104], + "event_timestamp": pd.to_datetime(["2026-01-15", "2026-01-16", "2026-02-01", "2026-02-15"]), +}) + +training_df = store.get_historical_features( + entity_df=entity_df, + features=[ + "customer_transaction_features:avg_txn_amount_30d", + "customer_transaction_features:txn_count_7d", + "customer_transaction_features:max_txn_amount_90d", + ], +).to_df() +``` + +Feast performs point-in-time correct joins against Oracle — no future data leaks into your training set, and the query runs *inside* Oracle, not in some external compute engine. + +### Step 4: Serve features in production + +```python +store.materialize_incremental(end_date=datetime.utcnow()) + +features = store.get_online_features( + features=[ + "customer_transaction_features:avg_txn_amount_30d", + "customer_transaction_features:txn_count_7d", + ], + entity_rows=[{"customer_id": 101}], +).to_dict() +``` + +--- + +## Kubernetes-Native: The Feast Operator and Oracle + +For teams running Feast on Kubernetes, the Feast operator now natively manages Oracle-backed feature stores through the `FeatureStore` custom resource. + +### Create a Secret with your Oracle credentials + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: oracle-offline-store +type: Opaque +stringData: + oracle: | + host: oracle-db.example.com + port: "1521" + user: feast_user + password: changeme + service_name: ORCL +``` + +### Define a FeatureStore custom resource + +```yaml +apiVersion: feast.dev/v1 +kind: FeatureStore +metadata: + name: production-feature-store +spec: + services: + offlineStore: + persistence: + store: + type: oracle + secretRef: + name: oracle-offline-store +``` + +### Apply and let the operator do the rest + +```bash +kubectl apply -f feature-store.yaml +``` + +The operator validates the configuration against the CRD schema (rejecting invalid types at admission), reads the Secret, merges the Oracle connection parameters into the generated Feast config, and deploys the offline store service. Credential rotation, version upgrades, and config changes are all handled through Kubernetes-native reconciliation — the same operational model your platform team already knows. + +Because credentials live in Kubernetes Secrets, they integrate naturally with external secret managers like HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault through standard Kubernetes mechanisms. Oracle credentials never appear in plain text in your manifests or CI/CD logs. + +--- + +## Real-World Use Cases + +### Financial Services: Fraud Detection Without Data Movement + +A global bank running Oracle for core banking can now build fraud detection features — transaction velocity, merchant category patterns, geographic anomaly scores — directly from their existing Oracle tables. The features stay within the same security perimeter, audit trail, and encryption boundary as the source data. No ETL pipeline to a secondary warehouse means no replication lag and no additional attack surface. + +### Healthcare: Predictive Models on Regulated Data + +Hospitals and insurers with patient data in Oracle can compute ML features (readmission risk scores, treatment outcome signals, resource utilization patterns) without copying PHI into a less governed system. Feast's feature definitions become the documented lineage trail that compliance teams need. + +### Telecommunications: Network Optimization at Scale + +Telcos managing billions of CDRs and network metrics in Oracle can build churn prediction, capacity forecasting, and service quality features on top of the data they already have — avoiding the cost and latency of replicating to a separate analytical platform. + +### Retail: Demand Forecasting from Point-of-Sale Data + +Retailers with Oracle-backed inventory and transaction systems can build demand forecasting and recommendation features without standing up a parallel data infrastructure. Features computed in Oracle can be materialized to the online store for real-time serving at the edge. + +--- + +## Under the Hood: Built on ibis + +The Oracle offline store is built on the [ibis framework](https://ibis-project.org/), a portable Python dataframe API that compiles to native SQL for each backend. This means: + +- **Queries execute inside Oracle** — ibis translates Feast's retrieval operations into Oracle SQL, pushing computation to where the data lives +- **No intermediate data movement** — results are streamed back as Arrow tables without staging in a temporary system +- **Full Oracle type fidelity** — the type mapping covers the complete spectrum of Oracle data types, including `NUMBER`, `VARCHAR2`, `NVARCHAR2`, `CHAR`, `CLOB`, `NCLOB`, `BLOB`, `RAW`, `BINARY_FLOAT`, `BINARY_DOUBLE`, `DATE`, `TIMESTAMP`, `INTEGER`, `SMALLINT`, and `FLOAT` +- **Automatic DATE-to-TIMESTAMP casting** — Oracle's `DATE` type (which includes time components, unlike SQL standard) is properly handled + +--- + +## Getting Started + +Install Feast with Oracle support: + +```bash +pip install 'feast[oracle]' +``` + +For Kubernetes deployments, ensure you're running Feast operator v0.61.0+ with the v1 API. + +The full configuration reference, functionality matrix, and data source documentation are available in the Feast docs: + +- [Oracle Offline Store Reference](https://docs.feast.dev/reference/offline-stores/oracle) +- [Oracle Data Source Reference](https://docs.feast.dev/reference/data-sources/oracle) +- [Feast Operator Documentation](https://docs.feast.dev/) + +--- + +*Get started with the [Feast documentation](https://docs.feast.dev/) and join the community on [GitHub](https://github.com/feast-dev/feast) and [Slack](https://feastopensource.slack.com/). We'd love to hear how you're using Feast with Oracle.* diff --git a/infra/website/docs/blog/feature-view-versioning.md b/infra/website/docs/blog/feature-view-versioning.md new file mode 100644 index 00000000000..574dac54cc1 --- /dev/null +++ b/infra/website/docs/blog/feature-view-versioning.md @@ -0,0 +1,244 @@ +--- +title: Feast Introduces Experimental Feature View Versioning +description: Feast now supports experimental feature view versioning — bringing automatic version tracking, safe rollback, and multi-version online serving to your feature store. Only supported for SQLite today; we're inviting the community to test and give feedback. +date: 2026-03-31 +authors: ["Francisco Javier Arceo"] +--- + +
+ Feast Feature Versioning +
+ +# Feast Introduces Experimental Feature View Versioning 🚀 + +We are excited to announce the experimental release of **Feature View Versioning** in Feast — a [long-requested capability](https://github.com/feast-dev/feast/issues/2728) that brings automatic version tracking, safe rollback, and multi-version online serving to your feature store. + +This feature is still **experimental** and we would love to hear your feedback. Try it out and let us know what works, what doesn't, and which online stores you'd like to see supported next. + +## Why Feature Versioning Matters + +Serving data in production AI applications is one of the hardest problems in ML engineering. The Feast community is built on practitioners who run these high-stakes pipelines every day — where **point-in-time correctness** is not just a nice-to-have but a hard requirement for model integrity. A feature value seen by the wrong model at the wrong time can silently corrupt predictions and, in high stakes scenarios, impact critical business applications. This is the most important motivating factor behind our versioning work. + +Feature versioning solves two distinct but equally real problems: + +### Case 1: Fixing Forward in Production (the critical path) + +A live feature view powering a production model needs to be updated — perhaps a critical bug in a transformation logic, a renamed column, or a changed data source. In an ideal world you'd cut over to a brand-new feature view and update every downstream consumer atomically. In practice that's rarely viable: models are already deployed, consumers are already reading that name, and a rename causes an immediate outage. + +With feature versioning you can overwrite the existing feature view definition while retaining the complete history as a recoverable snapshot. If the change turns out to break something, you can roll back to the previous version. You always have an audit trail: who changed what, when, and what the feature looked like at every prior point in time. + +This case is the hardest to get right. When your feature is live in production, correctness is non-negotiable. The materialized data that feeds real-time predictions must stay consistent with the schema that was active when it was written — otherwise you risk serving stale rows with the wrong columns to models that expect the new schema, or vice versa. Our per-version table design (see below) exists precisely to prevent that class of failure. + +### Case 2: Offline Experimentation Before Production + +During active feature development, multiple data scientists may be building and evaluating competing versions of the same feature simultaneously — different transformations, different data sources, different schemas. Today there is no first-class way to manage this in Feast without creating separate feature views with different names and hoping teams don't collide. + +With versioning, teams can stage a new feature version using `--no-promote`, test it in isolation, and only promote it to the active (default) definition once it has been validated. The rest of the system sees no change until the promotion happens. + +### The Persistent Pain Points + +Both cases expose the same underlying gaps that exist today: + +1. **No audit trail.** Teams struggle to answer "what did this feature view look like last week?" or "when was this schema changed and by whom?" +2. **No safe rollback.** If a schema change breaks a downstream model, the only recourse is to manually reconstruct the old definition — often from memory or version control history. +3. **No multi-version serving.** During a migration, Model A might rely on the old feature schema while Model B needs the new one. Without versioning, serving both simultaneously requires duplicating the entire feature view under a different name. + +## How It Works + +Version tracking is fully automatic. You don't need to change anything about how you write or apply feature views: + +```bash +feast apply # First apply → saved as v0 +# ... edit schema ... +feast apply # Detects change → saved as v1 +feast apply # No change detected → still v1 (idempotent) +# ... edit source or UDF ... +feast apply # Detects change → saved as v2 +``` + +Every time `feast apply` detects a real change to a feature view's schema or transformation logic, it automatically saves a versioned snapshot to the registry. Metadata-only changes (description, tags, TTL) are updated in place without creating a new version. + +### What Gets Versioned + +- Changes to the feature schema (adding, removing, or renaming fields) +- Changes to batch or stream data sources +- Changes to on-demand feature view UDFs +- Any other structural change that affects data layout or derivation + +### What Does Not Trigger a New Version + +- Tag or description updates +- TTL changes +- Re-applying an identical definition (idempotent behavior) + +## Exploring Version History + +You can list all recorded versions of a feature view from the CLI: + +```bash +feast feature-views list-versions driver_stats +``` + +``` +VERSION TYPE CREATED VERSION_ID +v0 feature_view 2026-01-15 10:30:00 a1b2c3d4-... +v1 feature_view 2026-01-16 14:22:00 e5f6g7h8-... +v2 feature_view 2026-01-20 09:15:00 i9j0k1l2-... +``` + +Or programmatically: + +```python +store = FeatureStore(repo_path=".") +versions = store.list_feature_view_versions("driver_stats") +for v in versions: + print(f"{v['version']} created at {v['created_timestamp']}") +``` + +## Multi-Version Online Serving + +When `enable_online_feature_view_versioning: true` is set in your `feature_store.yaml`, you can read features from a specific version using the `@v` syntax: + +```yaml +registry: + path: data/registry.db + enable_online_feature_view_versioning: true +``` + +```python +online_features = store.get_online_features( + features=[ + "driver_stats:trips_today", # latest version (default) + "driver_stats@v1:trips_today", # read from v1 + "driver_stats@v2:avg_rating", # read from v2 + ], + entity_rows=[{"driver_id": 1001}], +) +``` + +Multiple versions can be queried in a single call, making gradual migrations straightforward: keep serving the old version to existing consumers while routing new consumers to the latest. **By default, unversioned requests always resolve to the latest promoted version** — opting into a specific version requires the explicit `@v` syntax. + +### Online Store Table Naming + +Each version owns its own isolated online table (see [The Challenges of Correctness](#the-challenges-of-correctness-in-feature-versioning) below for why this design is necessary for point-in-time correctness): + +- v0 continues to use the existing, unversioned table (e.g., `project_driver_stats`) — fully backward compatible +- v1 and later use suffixed tables (e.g., `project_driver_stats_v1`, `project_driver_stats_v2`) + +Each version requires its own materialization: + +```bash +feast materialize --views driver_stats --version v2 +``` + +## Safe Rollback + +You can pin a feature view to a specific historical version by setting the `version` parameter. `feast apply` will replace the active definition with the stored snapshot: + +```python +# Revert to v1 — restores schema, source, and transformations from the v1 snapshot +driver_stats = FeatureView( + name="driver_stats", + entities=[driver], + schema=[...], + source=my_source, + version="v1", +) +``` + +After running `feast apply`, the active feature view will match the v1 snapshot exactly. Remove the `version` parameter (or set it to `"latest"`) to resume auto-incrementing behavior. + +## Staged Publishing with `--no-promote` + +For breaking schema changes, you may want to publish a new version without immediately making it the default for unversioned consumers. Use the `--no-promote` flag: + +```bash +feast apply --no-promote +``` + +This saves the version snapshot without updating the active definition. Unversioned consumers (`driver_stats:trips_today`) continue reading from the previous version, while opted-in consumers can start using `driver_stats@v2:trips_today` right away. When you're ready to make the new schema the default, run `feast apply` without the flag. + +## The Challenges of Correctness in Feature Versioning + +Feature versioning might sound simple in principle, but **getting it right is surprisingly hard**, especially for materialization. This is particularly acute for Case 1 above — production systems where the consistency of data matters and the cost of a mistake is high. + +### Why We Can't Share a Single Online Table + +The naive approach to versioning would be to keep a single online table and tag rows with a version column. We explicitly rejected this design. + +Each version of a feature view may have a completely different schema — different columns, different types, different derivation logic. A single shared table would require the union of all column schemas across all versions, leading to sparse rows, broken type contracts, and materialization jobs that cannot safely run in parallel. More fundamentally, it makes **point-in-time correctness impossible**: a model trained against v1 of a feature must retrieve v1 rows, not v2 rows that happen to occupy the same table. + +Instead, we give each version its own online table: + +- v0 continues to use the existing, unversioned table (e.g., `project_driver_stats`) — fully backward compatible +- v1 and later use suffixed tables (e.g., `project_driver_stats_v1`, `project_driver_stats_v2`) + +This is more operationally complex — more tables to manage, more materialization jobs to schedule — but it is the **only design that guarantees correctness**. Each version's materialized data is isolated, independently freshed, and independently queryable. A buggy v2 materialization cannot corrupt v1 data. + +### The Core Tension + +Each version of a feature view may have a completely different schema, source, or transformation. This means: + +- Each version needs its own online store table with the right columns +- Materializing one version must not corrupt data in another version's table +- Version-qualified online reads must resolve the snapshot at the right point in time before looking up the online table +- The active (promoted) version and historical snapshots must stay consistent + +### Materialization Complexity + +Today, running `feast materialize` without specifying a version fills the **active** version's table. To populate a historical version's table, you must explicitly pass `--version v` so Feast can reconstruct the schema from the saved snapshot and target the correct online table. + +This matters for correctness: if you apply v2 of a feature view (which drops a column) and then run an unversioned `feast materialize`, the v1 online table is not automatically backfilled or maintained. Teams need to think carefully about which versions they want to keep materialized and for how long. + +### What This Means for Clients + +The multi-table design does introduce a responsibility shift toward the client. By default, unversioned feature requests (`driver_stats:trips_today`) resolve to the **latest promoted version** — no change to existing consumers. But clients that need to pin to a specific version must opt in explicitly using the `@v` syntax (`driver_stats@v1:trips_today`). + +This is an intentional design choice. Automatic version following would hide schema changes from consumers that may not be ready for them. Explicit version pinning keeps the contract between producers and consumers clear and auditable — each consumer controls exactly which version of a feature it reads. + +### Tradeoffs + +| Concern | Tradeoff | +|---|---| +| Storage cost | Each active version requires its own online table — storage scales with the number of versions kept live | +| Operational complexity | Teams must manage materialization schedules per version | +| Consistency windows | Because each version has its own materialization job, two versions of the same feature for the same entity may have different freshness | +| Concurrency | Two simultaneous `feast apply` calls can race on version number assignment — the registry backends use optimistic locking to handle this, but teams should be aware | + +These tradeoffs are real and we're still refining the model based on community experience. We've tried to make the defaults safe (versioning is opt-in for online reads, backward compatible for unversioned access) while giving teams the controls they need. + +## Current Limitations + +This is an experimental feature and there are known gaps: + +- **Online store support** — Version-qualified reads (`@v`) are **SQLite-only** today. We plan to add Redis, DynamoDB, Bigtable, Postgres, and others based on community demand. If you need a specific store, [comment or upvote on the appropriate the child GitHub issue of the main GitHub issue](https://github.com/feast-dev/feast/issues/2728) and let us know. +- **Offline store versioning** — Versioned historical retrieval is not yet supported. +- **Version deletion** — There is no mechanism today to prune old versions from the registry. +- **Feature services** — Feature services always resolve to the active (promoted) version. `--no-promote` versions are not accessible through feature services until promoted. + +## Supported Feature View Types + +Versioning works across all three feature view types: + +- `FeatureView` (and `BatchFeatureView`) +- `StreamFeatureView` +- `OnDemandFeatureView` + +## Getting Started + +1. Upgrade to the latest version of Feast. +2. Add `enable_online_feature_view_versioning: true` to your registry config in `feature_store.yaml` (only needed for versioned online reads). +3. Run `feast apply` as usual — version history tracking starts automatically. +4. Explore your version history with `feast feature-views list-versions `. + +For full details, see the [Feature View Versioning documentation](https://docs.feast.dev/reference/alpha-feature-view-versioning). + +## Share Your Feedback + +We want to hear from you! Try out feature view versioning and tell us: + +- Which online stores you need supported next +- Which workflows feel awkward or incomplete +- How the materialization model fits your real-world pipelines + +Join the conversation on [GitHub](https://github.com/feast-dev/feast/issues) or in the [Feast Slack community](https://slack.feast.dev/). Your feedback directly shapes what we build next. diff --git a/infra/website/docs/blog/scaling-feast-feature-server.md b/infra/website/docs/blog/scaling-feast-feature-server.md new file mode 100644 index 00000000000..994811ea0ac --- /dev/null +++ b/infra/website/docs/blog/scaling-feast-feature-server.md @@ -0,0 +1,317 @@ +--- +title: Feature Server High-Availability and Auto-Scaling on Kubernetes +description: The Feast Operator now supports horizontal scaling with static replicas, HPA autoscaling, KEDA, and high-availability features including PodDisruptionBudgets and topology spread constraints. +date: 2026-03-02 +authors: ["Nikhil Kathole", "Antonin Stefanutti"] +--- + +# Feature Server High-Availability and Auto-Scaling on Kubernetes + +As ML systems move from experimentation to production, the feature server often becomes a critical bottleneck. A single-replica deployment might handle development traffic, but production workloads — real-time inference, batch scoring, multiple consuming services — demand the ability to scale horizontally. + +We're excited to announce that the Feast Operator now supports **horizontal scaling** for the FeatureStore deployment, giving teams the tools to run Feast at production scale on Kubernetes. + +# The Problem: Single-Replica Limitations + +By default, the Feast Operator deploys a single-replica Deployment. This works well for getting started, but presents challenges as traffic grows: + +- **Single point of failure** — one pod crash means downtime for all feature consumers +- **Throughput ceiling** — a single pod can only handle so many concurrent requests +- **No elasticity** — traffic spikes (model retraining, batch inference) can overwhelm the server +- **Rolling updates cause downtime** — the default `Recreate` strategy tears down the old pod before starting a new one + +Teams have been manually patching Deployments or creating external HPAs, but this bypasses the operator's reconciliation loop and can lead to configuration drift. + +# The Solution: Native Scaling Support + +The Feast Operator now supports three scaling modes. The FeatureStore CRD implements the Kubernetes **scale sub-resource**, which means you can also scale with `kubectl scale featurestore/my-feast --replicas=3`. + +## 1. Static Replicas + +The simplest approach — set a fixed number of replicas via `spec.replicas`: + +```yaml +apiVersion: feast.dev/v1 +kind: FeatureStore +metadata: + name: production-feast +spec: + feastProject: my_project + replicas: 3 + services: + onlineStore: + persistence: + store: + type: postgres + secretRef: + name: feast-data-stores + registry: + local: + persistence: + store: + type: sql + secretRef: + name: feast-data-stores +``` + +This gives you high availability and load distribution with a predictable resource footprint. The operator automatically switches the Deployment strategy to `RollingUpdate`, ensuring zero-downtime deployments. + +## 2. HPA Autoscaling + +For workloads with variable traffic patterns, the operator can create and manage a `HorizontalPodAutoscaler` directly. HPA autoscaling is configured under `services.scaling.autoscaling` and is mutually exclusive with `spec.replicas > 1`: + +```yaml +apiVersion: feast.dev/v1 +kind: FeatureStore +metadata: + name: autoscaled-feast +spec: + feastProject: my_project + services: + scaling: + autoscaling: + minReplicas: 2 + maxReplicas: 10 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 70 + podDisruptionBudgets: + maxUnavailable: 1 + onlineStore: + persistence: + store: + type: postgres + secretRef: + name: feast-data-stores + server: + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + cpu: "1" + memory: 1Gi + registry: + local: + persistence: + store: + type: sql + secretRef: + name: feast-data-stores +``` + +The operator creates the HPA as an owned resource — it's automatically cleaned up if you remove the autoscaling configuration or delete the FeatureStore CR. If no custom metrics are specified, the operator defaults to **80% CPU utilization**. The operator also auto-injects soft pod anti-affinity (node-level) and topology spread constraints (zone-level) to improve resilience — see the [High Availability](#high-availability) section for details. + +## 3. External Autoscalers (KEDA, Custom HPAs) + +For teams using [KEDA](https://keda.sh) or other external autoscalers, KEDA should target the FeatureStore's scale sub-resource directly (since it implements the Kubernetes scale API). This is the recommended approach because the operator manages the Deployment's replica count from `spec.replicas` — targeting the Deployment directly would conflict with the operator's reconciliation. + +When using KEDA, do **not** set `spec.replicas > 1` or `services.scaling.autoscaling` — KEDA manages the replica count through the scale sub-resource. Configure the FeatureStore with DB-backed persistence, then create a KEDA `ScaledObject` targeting the FeatureStore resource: + +```yaml +apiVersion: feast.dev/v1 +kind: FeatureStore +metadata: + name: keda-feast +spec: + feastProject: my_project + services: + onlineStore: + persistence: + store: + type: postgres + secretRef: + name: feast-data-stores + registry: + local: + persistence: + store: + type: sql + secretRef: + name: feast-data-stores +--- +apiVersion: keda.sh/v1alpha1 +kind: ScaledObject +metadata: + name: feast-scaledobject +spec: + scaleTargetRef: + apiVersion: feast.dev/v1 + kind: FeatureStore + name: keda-feast + minReplicaCount: 1 + maxReplicaCount: 10 + triggers: + - type: prometheus + metadata: + serverAddress: http://prometheus.monitoring.svc:9090 + metricName: http_requests_total + query: sum(rate(http_requests_total{service="feast"}[2m])) + threshold: "100" +``` + +When KEDA scales up `spec.replicas` via the scale sub-resource, the CRD's CEL validation rules automatically ensure DB-backed persistence is configured. The operator also automatically switches the deployment strategy to `RollingUpdate` when `replicas > 1`. This gives you the full power of KEDA's 50+ event-driven triggers with built-in safety checks. + +# High Availability + +Scaling to multiple replicas is only half the story — you also need to ensure pods are spread across failure domains and protected during disruptions. The operator includes two HA features that activate when scaling is enabled: + +## Pod Anti-Affinity + +When scaling is enabled, the operator **automatically injects** a soft pod anti-affinity rule that prefers spreading pods across different nodes: + +```yaml +affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + feast.dev/name: my-feast +``` + +This means the scheduler will *try* to place each replica on a separate node, but won't prevent scheduling if nodes are constrained. You can override this with your own `affinity` configuration in the CR, or set it to an explicit value to customize the behavior (e.g. `requiredDuringSchedulingIgnoredDuringExecution` for strict anti-affinity). + +## Topology Spread Constraints + +When `replicas > 1` or autoscaling is configured, the operator **automatically injects** a soft zone-spread constraint: + +```yaml +topologySpreadConstraints: +- maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + feast.dev/name: my-feast +``` + +This distributes pods across availability zones on a best-effort basis. If your cluster has 3 zones and 3 replicas, each zone gets one pod. If zones are unavailable, pods still get scheduled rather than staying pending. + +You can override this with explicit constraints (e.g. strict `DoNotSchedule`) or disable it entirely by setting `topologySpreadConstraints: []`. + +## PodDisruptionBudgets + +For protection during voluntary disruptions (node drains, cluster upgrades), you can configure a PDB: + +```yaml +spec: + replicas: 3 + services: + podDisruptionBudgets: + maxUnavailable: 1 + onlineStore: + # ... +``` + +The PDB requires explicit configuration — it's not auto-injected because a misconfigured PDB can block node drains. The operator enforces that exactly one of `minAvailable` or `maxUnavailable` is set via CEL validation. The PDB is only created when scaling is enabled and is automatically cleaned up when scaling is disabled. + +# Safety First: Persistence Validation + +Not all persistence backends are safe for multi-replica deployments. File-based stores like SQLite, DuckDB, and local `registry.db` use single-writer file locks that don't work across pods. + +The operator enforces this at admission time via CEL validation rules on the CRD — if you try to create or update a FeatureStore with scaling and file-based persistence, the API server rejects the request immediately: + +``` +Scaling requires DB-backed persistence for the online store. +Configure services.onlineStore.persistence.store when using replicas > 1 or autoscaling. +``` + +This validation applies to all enabled services (online store, offline store, and registry) and is enforced for both direct CR updates and `kubectl scale` commands via the scale sub-resource. Object-store-backed registry paths (`s3://` and `gs://`) are treated as safe since they support concurrent readers. + +| Persistence Type | Compatible with Scaling? | +|---|---| +| PostgreSQL / MySQL | Yes | +| Redis | Yes | +| Cassandra | Yes | +| SQL-based Registry | Yes | +| S3/GCS Registry | Yes | +| SQLite | No | +| DuckDB | No | +| Local `registry.db` | No | + +# How It Works Under the Hood + +The implementation adds three key behaviors to the operator's reconciliation loop: + +**1. Replica management** — The operator sets the Deployment's replica count from `spec.replicas` (which defaults to 1). When HPA is configured, the operator leaves the `replicas` field unset so the HPA controller can manage it. External autoscalers like KEDA can update the replica count through the FeatureStore's scale sub-resource, which updates `spec.replicas` and triggers the operator to reconcile. + +**2. Deployment strategy** — The operator automatically switches from `Recreate` (the default for single-replica) to `RollingUpdate` when scaling is enabled. This prevents the "kill-all-pods-then-start-new-ones" behavior that would cause downtime during scaling events. Users can always override this with an explicit `deploymentStrategy` in the CR. + +**3. HPA lifecycle** — The operator creates, updates, and deletes the HPA as an owned resource tied to the FeatureStore CR. Removing the `autoscaling` configuration automatically cleans up the HPA. + +**4. HA features** — The operator auto-injects soft topology spread constraints across zones when scaling is enabled, and manages PodDisruptionBudgets as owned resources when explicitly configured. + +The scaling status is reported back on the FeatureStore status: + +```yaml +status: + scalingStatus: + currentReplicas: 3 + desiredReplicas: 3 +``` + +# What About TLS, CronJobs, and Services? + +Scaling is designed to work seamlessly with existing operator features: + +- **TLS** — Each pod mounts the same TLS secret. OpenShift service-serving certificates work automatically since they're bound to the Service, not individual pods. +- **Kubernetes Services** — The Service's label selector already matches all pods in the Deployment, so load balancing across replicas works out of the box. +- **CronJobs** — The `feast apply` and `feast materialize-incremental` CronJobs use `kubectl exec` into a single pod. Since DB-backed persistence is required for scaling, all pods share the same state — it doesn't matter which pod the CronJob runs against. + +# Getting Started + +**1. Ensure DB-backed persistence** for all enabled services (online store, offline store, registry). + +**2. Configure scaling** in your FeatureStore CR — use either static replicas or HPA (mutually exclusive). Optionally add a PDB for disruption protection: + +```yaml +spec: + replicas: 3 # static replicas (top-level) + services: + podDisruptionBudgets: # optional: protect against disruptions + maxUnavailable: 1 + # -- OR -- + # services: + # scaling: + # autoscaling: # HPA + # minReplicas: 2 + # maxReplicas: 10 + # podDisruptionBudgets: + # maxUnavailable: 1 +``` + +**3. Apply** the updated CR: + +```bash +kubectl apply -f my-featurestore.yaml +``` + +**4. Verify** the scaling: + +```bash +# Check pods +kubectl get pods -l app.kubernetes.io/managed-by=feast + +# Check HPA (if using autoscaling) +kubectl get hpa + +# Check FeatureStore status +kubectl get feast -o yaml +``` + +# Learn More + +- [Scaling Feast documentation](https://docs.feast.dev/how-to-guides/scaling-feast) +- [Feast on Kubernetes guide](https://docs.feast.dev/how-to-guides/feast-on-kubernetes) +- [FeatureStore CRD API reference](https://github.com/feast-dev/feast/blob/master/infra/feast-operator/docs/api/markdown/ref.md) +- [Sample CRs for static scaling and HPA](https://github.com/feast-dev/feast/tree/master/infra/feast-operator/config/samples) +- Join the [Feast Slack](https://slack.feast.dev) to share feedback and ask questions + +We're excited to see teams scale their feature serving infrastructure with confidence. Try it out and let us know how it works for your use case! diff --git a/infra/website/public/images/blog/feast-feature-versioning-hero.png b/infra/website/public/images/blog/feast-feature-versioning-hero.png new file mode 100644 index 00000000000..d40d71a16dd Binary files /dev/null and b/infra/website/public/images/blog/feast-feature-versioning-hero.png differ diff --git a/infra/website/public/images/blog/feast-features-ui.png b/infra/website/public/images/blog/feast-features-ui.png new file mode 100644 index 00000000000..2b728e4c43a Binary files /dev/null and b/infra/website/public/images/blog/feast-features-ui.png differ diff --git a/infra/website/public/images/blog/feast-metrics-dashboard-overview.png b/infra/website/public/images/blog/feast-metrics-dashboard-overview.png new file mode 100644 index 00000000000..21293e8499e Binary files /dev/null and b/infra/website/public/images/blog/feast-metrics-dashboard-overview.png differ diff --git a/infra/website/public/images/blog/feast-metrics-hero.png b/infra/website/public/images/blog/feast-metrics-hero.png new file mode 100644 index 00000000000..b7c11e13e8d Binary files /dev/null and b/infra/website/public/images/blog/feast-metrics-hero.png differ diff --git a/infra/website/public/images/blog/feast-metrics-odfv-latency.png b/infra/website/public/images/blog/feast-metrics-odfv-latency.png new file mode 100644 index 00000000000..d6d33c0e5db Binary files /dev/null and b/infra/website/public/images/blog/feast-metrics-odfv-latency.png differ diff --git a/infra/website/public/images/blog/feast-mlflow-kubeflow.png b/infra/website/public/images/blog/feast-mlflow-kubeflow.png new file mode 100644 index 00000000000..c4e92228189 Binary files /dev/null and b/infra/website/public/images/blog/feast-mlflow-kubeflow.png differ diff --git a/infra/website/public/images/blog/feast-oracle-offline-store.png b/infra/website/public/images/blog/feast-oracle-offline-store.png new file mode 100644 index 00000000000..425c7fda0cc Binary files /dev/null and b/infra/website/public/images/blog/feast-oracle-offline-store.png differ diff --git a/infra/website/public/images/blog/mlflow-feast-feature-selection-metrics.png b/infra/website/public/images/blog/mlflow-feast-feature-selection-metrics.png new file mode 100644 index 00000000000..b6ad16c3346 Binary files /dev/null and b/infra/website/public/images/blog/mlflow-feast-feature-selection-metrics.png differ diff --git a/infra/website/public/images/blog/mlflow-feature-selection-comparison.png b/infra/website/public/images/blog/mlflow-feature-selection-comparison.png new file mode 100644 index 00000000000..4cad26065c6 Binary files /dev/null and b/infra/website/public/images/blog/mlflow-feature-selection-comparison.png differ diff --git a/infra/website/public/images/blog/mlflow-feature-selection-run.png b/infra/website/public/images/blog/mlflow-feature-selection-run.png new file mode 100644 index 00000000000..aabc6055480 Binary files /dev/null and b/infra/website/public/images/blog/mlflow-feature-selection-run.png differ diff --git a/infra/website/public/images/blog/mlflow-feature-selection-ui.png b/infra/website/public/images/blog/mlflow-feature-selection-ui.png new file mode 100644 index 00000000000..a598bbf4151 Binary files /dev/null and b/infra/website/public/images/blog/mlflow-feature-selection-ui.png differ diff --git a/java/pom.xml b/java/pom.xml index f7248902fe1..8d21af1c940 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -35,7 +35,7 @@ - 0.60.0 + 0.62.0 https://github.com/feast-dev/feast UTF-8 diff --git a/java/serving/src/test/resources/docker-compose/feast10/definitions.py b/java/serving/src/test/resources/docker-compose/feast10/definitions.py index 769ac155452..580605fe149 100644 --- a/java/serving/src/test/resources/docker-compose/feast10/definitions.py +++ b/java/serving/src/test/resources/docker-compose/feast10/definitions.py @@ -9,7 +9,6 @@ from feast.field import Field from feast.on_demand_feature_view import on_demand_feature_view from feast.types import Float32, Float64, Int64 -from feast.value_type import ValueType from feast import FileSource file_path = "driver_stats.parquet" @@ -70,7 +69,8 @@ def transformed_conv_rate(features_df: pd.DataFrame) -> pd.DataFrame: generated_data_source = FileSource( - path="benchmark_data.parquet", timestamp_field="event_timestamp", + path="benchmark_data.parquet", + timestamp_field="event_timestamp", ) entity = Entity(name="entity") @@ -88,5 +88,6 @@ def transformed_conv_rate(features_df: pd.DataFrame) -> pd.DataFrame: benchmark_feature_views.append(fv) benchmark_feature_service = FeatureService( - name=f"benchmark_feature_service", features=benchmark_feature_views, + name="benchmark_feature_service", + features=benchmark_feature_views, ) diff --git a/java/serving/src/test/resources/docker-compose/feast10/materialize.py b/java/serving/src/test/resources/docker-compose/feast10/materialize.py index 404fec27e12..3307805f2a5 100644 --- a/java/serving/src/test/resources/docker-compose/feast10/materialize.py +++ b/java/serving/src/test/resources/docker-compose/feast10/materialize.py @@ -55,7 +55,7 @@ def generate_data(num_rows: int, num_features: int, destination: str) -> pd.Data df.to_parquet(destination) -generate_data(10 ** 3, 250, "benchmark_data.parquet") +generate_data(10**3, 250, "benchmark_data.parquet") fs = FeatureStore(".") diff --git a/java/serving/src/test/resources/docker-compose/feast10/setup_it.py b/java/serving/src/test/resources/docker-compose/feast10/setup_it.py index 61aaa6fec8e..ad1cab07da4 100644 --- a/java/serving/src/test/resources/docker-compose/feast10/setup_it.py +++ b/java/serving/src/test/resources/docker-compose/feast10/setup_it.py @@ -41,9 +41,7 @@ def setup_data(): # Please read more in Feast RFC-031 # (link https://docs.google.com/document/d/12UuvTQnTTCJhdRgy6h10zSbInNGSyEJkIxpOcgOen1I/edit) # about this benchmark setup - def generate_data( - num_rows, num_features, destination - ): + def generate_data(num_rows, num_features, destination): features = [f"feature_{i}" for i in range(num_features)] columns = ["entity", "event_timestamp"] + features df = pd.DataFrame(0, index=np.arange(num_rows), columns=columns) diff --git a/pixi.lock b/pixi.lock new file mode 100644 index 00000000000..193bb7ea383 --- /dev/null +++ b/pixi.lock @@ -0,0 +1,7345 @@ +version: 6 +environments: + default: + channels: + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + options: + pypi-prerelease-mode: if-necessary-or-explicit + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.5-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.3-h32b2ec7_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/e9/ed9f202cdf6bfa89ff09241a15a2b44a2d4a61cbe24119c2e391128562b1/bigtree-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/47/5c/032c2d5a07fe4d4855fea851209cca2b6f03ebeb6d4e3afdb3358386a684/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/84/a4/5caa2de7f917a04ada20018eccf60d6cc6145b0199d55ca3711b0fc08312/fastapi-0.135.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d5/1f/5f4a3cd9e4440e9d9bc78ad0a91a1c8d46b4d429d5239ebe6793c9fe5c41/fsspec-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/d8/09bfa816572a4d83bccd6750df1926f79158b1c36c5f73786e26dbe4ee38/greenlet-3.3.2-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/43/c8/8aaf447698c4d59aa853fd318eed300b5c9e44459f242ab8ead6c9c09792/gunicorn-25.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/cb/eea88506f191fb552c11787c23f9a405f4c7b0c5799bf73f2249cd4f5228/httptools-0.7.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/96/ef04902aad1424fd7299b62d1890e803e6ab4018c3044dca5922319c4b97/librt-0.8.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b6/71/c1a60c1652b8813ef9de6d289784847355417ee0f2980bca002fe87f4ae5/mmh3-5.2.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/6b/8d/93491ff7b79419edc7eabf95cb3b3f7490e2e574b2855c7c7e7394ff933f/mypy-1.20.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/98/7c/21252050676612625449b4807d6b695b9ce8a7c9e1c197ee6216c8a65c7c/numpy-2.4.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/15/b2/0e62f78c0c5ba7e3d2c5945a82456f4fac76c480940f805e0b97fcbc2f65/pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/53/1b/3b431694a4dc6d37b9f653f0c64b0a0d9ec074ee810710c0c3da21d67ba7/protobuf-7.34.1-cp310-abi3-manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/36/2e/c0f017c405fcdc252dbccafbe05e36b0d0eb1ea9a958f081e01c6972927f/pyarrow-23.0.1-cp314-cp314-manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/7a/8dd906bd22e79e47397a61742927f6747fe93242ef86645ee9092e610244/pyjwt-2.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/99/781fe0c827be2742bcc775efefccb3b048a3a9c6ce9aec0cbf4a101677e5/pytz-2026.1.post1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/8e/7540e8a2036f79a125c1d2ebadf69ed7901608859186c856fa0388ef4197/requests-2.33.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ce/81/9a91c0111ce1758c92516a3e44776920b579d9a7c09b2b06b642d4de3f0f/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f2/5e/327428a034407651a048f5e624361adf3f9fbac9d0fa98e981e9c6ff2f5e/sqlalchemy-2.0.48-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/0b/c9/584bc9651441b4ba60cc4d557d8a547b5aff901af35bda3a4ee30c819b82/starlette-1.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/3f/8ba87d9e287b9d385a02a7114ddcef61b26f86411e121c9003eb509a1773/tenacity-8.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/1f/4e5f8770c2cf4faa2c3ed3c19f9d4485ac9db0a6b029a7866921709bdc6c/uvicorn_worker-0.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b5/35/60249e9fd07b32c665192cec7af29e06c7cd96fa1d08b84f012a56a0b38e/uvloop-0.22.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b4/36/ded8aebea91919485b7bbabbd14f5f359326cb5ec218cd67074d1e426d74/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/63/bc/d3e208028de777087e6fb2b122051a6ff7bbcca0d6df9d9c2bf1dd869ae9/websockets-16.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + osx-64: + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.7.5-hcc62823_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-hf3981d6_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.52.0-h77d7759_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.14.3-h4f44bb5_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h68b038d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda + - pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/e9/ed9f202cdf6bfa89ff09241a15a2b44a2d4a61cbe24119c2e391128562b1/bigtree-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/97/c8/c67cb8c70e19ef1960b97b22ed2a1567711de46c4ddf19799923adc836c2/charset_normalizer-3.4.7-cp314-cp314-macosx_10_15_universal2.whl + - pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/84/a4/5caa2de7f917a04ada20018eccf60d6cc6145b0199d55ca3711b0fc08312/fastapi-0.135.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d5/1f/5f4a3cd9e4440e9d9bc78ad0a91a1c8d46b4d429d5239ebe6793c9fe5c41/fsspec-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/ae/8bffcbd373b57a5992cd077cbe8858fff39110480a9d50697091faea6f39/greenlet-3.3.2-cp314-cp314-macosx_11_0_universal2.whl + - pypi: https://files.pythonhosted.org/packages/43/c8/8aaf447698c4d59aa853fd318eed300b5c9e44459f242ab8ead6c9c09792/gunicorn-25.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/34/50/9d095fcbb6de2d523e027a2f304d4551855c2f46e0b82befd718b8b20056/httptools-0.7.1-cp314-cp314-macosx_10_13_universal2.whl + - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c9/6a/907ef6800f7bca71b525a05f1839b21f708c09043b1c6aa77b6b827b3996/librt-0.8.1-cp314-cp314-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/6f/75/2c24517d4b2ce9e4917362d24f274d3d541346af764430249ddcc4cb3a08/mmh3-5.2.1-cp314-cp314-macosx_10_15_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/4e/0e/6ca4a84cbed9e62384bc0b2974c90395ece5ed672393e553996501625fc5/mypy-1.20.0-cp314-cp314-macosx_10_15_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/06/c54062f85f673dd5c04cbe2f14c3acb8c8b95e3384869bb8cc9bff8cb9df/numpy-2.4.4-cp314-cp314-macosx_10_15_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/fd/74903979833db8390b73b3a8a7d30d146d710bd32703724dd9083950386f/pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/11/3325d41e6ee15bf1125654301211247b042563bcc898784351252549a8ad/protobuf-7.34.1-cp310-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/ae/b5/d58a241fbe324dbaeb8df07be6af8752c846192d78d2272e551098f74e88/pyarrow-23.0.1-cp314-cp314-macosx_12_0_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ea/28/46b7c5c9635ae96ea0fbb779e271a38129df2550f763937659ee6c5dbc65/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/7a/8dd906bd22e79e47397a61742927f6747fe93242ef86645ee9092e610244/pyjwt-2.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/99/781fe0c827be2742bcc775efefccb3b048a3a9c6ce9aec0cbf4a101677e5/pytz-2026.1.post1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/8e/7540e8a2036f79a125c1d2ebadf69ed7901608859186c856fa0388ef4197/requests-2.33.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/86/81/dad16382ebbd3d0e0328776d8fd7ca94220e4fa0798d1dc5e7da48cb3201/rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/2c/9664130905f03db57961b8980b05cab624afd114bf2be2576628a9f22da4/sqlalchemy-2.0.48-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0b/c9/584bc9651441b4ba60cc4d557d8a547b5aff901af35bda3a4ee30c819b82/starlette-1.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/3f/8ba87d9e287b9d385a02a7114ddcef61b26f86411e121c9003eb509a1773/tenacity-8.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/1f/4e5f8770c2cf4faa2c3ed3c19f9d4485ac9db0a6b029a7866921709bdc6c/uvicorn_worker-0.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/f8/a132124dfda0777e489ca86732e85e69afcd1ff7686647000050ba670689/uvloop-0.22.1-cp314-cp314-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c3/f4/0872229324ef69b2c3edec35e84bd57a1289e7d3fe74588048ed8947a323/watchfiles-1.1.1-cp314-cp314-macosx_10_12_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f2/78/e63be1bf0724eeb4616efb1ae1c9044f7c3953b7957799abb5915bffd38e/websockets-16.0-cp314-cp314-macosx_10_15_x86_64.whl + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.5-hf6b4638_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.52.0-h1ae2325_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.3-h4c637c5_101_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + - pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/e9/ed9f202cdf6bfa89ff09241a15a2b44a2d4a61cbe24119c2e391128562b1/bigtree-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/97/c8/c67cb8c70e19ef1960b97b22ed2a1567711de46c4ddf19799923adc836c2/charset_normalizer-3.4.7-cp314-cp314-macosx_10_15_universal2.whl + - pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/84/a4/5caa2de7f917a04ada20018eccf60d6cc6145b0199d55ca3711b0fc08312/fastapi-0.135.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d5/1f/5f4a3cd9e4440e9d9bc78ad0a91a1c8d46b4d429d5239ebe6793c9fe5c41/fsspec-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/c8/8aaf447698c4d59aa853fd318eed300b5c9e44459f242ab8ead6c9c09792/gunicorn-25.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/07/f0/89720dc5139ae54b03f861b5e2c55a37dba9a5da7d51e1e824a1f343627f/httptools-0.7.1-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1b/18/25e991cd5640c9fb0f8d91b18797b29066b792f17bf8493da183bf5caabe/librt-0.8.1-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/bf/b9/e4a360164365ac9f07a25f0f7928e3a66eb9ecc989384060747aa170e6aa/mmh3-5.2.1-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/7d/c5/5fe9d8a729dd9605064691816243ae6c49fde0bd28f6e5e17f6a24203c43/mypy-1.20.0-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4c/39/8a320264a84404c74cc7e79715de85d6130fa07a0898f67fb5cd5bd79908/numpy-2.4.4-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/21/00/266d6b357ad5e6d3ad55093a7e8efc7dd245f5a842b584db9f30b0f0a287/pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/11/3325d41e6ee15bf1125654301211247b042563bcc898784351252549a8ad/protobuf-7.34.1-cp310-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/8d/1b/6da9a89583ce7b23ac611f183ae4843cd3a6cf54f079549b0e8c14031e73/pyarrow-23.0.1-cp314-cp314-macosx_12_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/7a/8dd906bd22e79e47397a61742927f6747fe93242ef86645ee9092e610244/pyjwt-2.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/99/781fe0c827be2742bcc775efefccb3b048a3a9c6ce9aec0cbf4a101677e5/pytz-2026.1.post1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/8e/7540e8a2036f79a125c1d2ebadf69ed7901608859186c856fa0388ef4197/requests-2.33.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/60/19f7884db5d5603edf3c6bce35408f45ad3e97e10007df0e17dd57af18f8/rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/b3/f437eaa1cf028bb3c927172c7272366393e73ccd104dcf5b6963f4ab5318/sqlalchemy-2.0.48-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/0b/c9/584bc9651441b4ba60cc4d557d8a547b5aff901af35bda3a4ee30c819b82/starlette-1.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/3f/8ba87d9e287b9d385a02a7114ddcef61b26f86411e121c9003eb509a1773/tenacity-8.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/1f/4e5f8770c2cf4faa2c3ed3c19f9d4485ac9db0a6b029a7866921709bdc6c/uvicorn_worker-0.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/cd/b62bdeaa429758aee8de8b00ac0dd26593a9de93d302bff3d21439e9791d/uvloop-0.22.1-cp314-cp314-macosx_10_13_universal2.whl + - pypi: https://files.pythonhosted.org/packages/7b/22/16d5331eaed1cb107b873f6ae1b69e9ced582fcf0c59a50cd84f403b1c32/watchfiles-1.1.1-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/bb/f4/d3c9220d818ee955ae390cf319a7c7a467beceb24f05ee7aaaa2414345ba/websockets-16.0-cp314-cp314-macosx_11_0_arm64.whl + duckdb-tests: + channels: + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + options: + pypi-prerelease-mode: if-necessary-or-explicit + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.5-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.10.20-h3c07f61_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/09/52/94108adfdd6e2ddf58be64f959a0b9c7d4ef2fa71086c38356d22dc501ea/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c7/80/9f608d13b4b3afcebd1dd13baf9551c95fc424d6390e4b1cfd7b1810cd06/async_property-0.2.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/96/c0/271f3e1e3502a8decb8ee5c680dbed2d8dc2cd504f5e20f7ed491d5f37e1/atpublic-7.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/e9/ed9f202cdf6bfa89ff09241a15a2b44a2d4a61cbe24119c2e391128562b1/bigtree-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/98/29/9b366e70e243eb3d14a5cb488dfd3a0b6b2f1fb001a203f653b93ccfac88/cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/20/e7/bed0024a0f4ab0c8a9c64d4445f39b30c99bd1acd228291959e3de664247/charset_normalizer-3.4.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/8a/b14f3101fe9c3592603339eb5d94046c3ce5f7fc76d6512a2d40efd9724e/cryptography-46.0.6-cp38-abi3-manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/24/e6b7a8fe8b9e336d684779a88027b261374417f2be7c5a0fcdb40f0c8cc5/deltalake-0.25.5-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/02/c3/253a89ee03fc9b9682f1541728eb66db7db22148cd94f89ab22528cd1e1b/deprecation-2.1.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/09/4c4dd94f521d016e0fb83cca2c203d10ce1e3f8bcc679691b5271fc98b83/duckdb-1.5.1-cp310-cp310-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/84/a4/5caa2de7f917a04ada20018eccf60d6cc6145b0199d55ca3711b0fc08312/fastapi-0.135.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d5/1f/5f4a3cd9e4440e9d9bc78ad0a91a1c8d46b4d429d5239ebe6793c9fe5c41/fsspec-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/55/9f1ebb5a825215fadcc0f7d5073f6e79e3007e3282b14b22d6aba7ca6cb8/greenlet-3.3.2-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/58/2f/f3fc773270cf17e7ca076c1f6435278f58641d475a25cdeea5b2d8d4845b/grpcio-1.62.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/40/4c/ee3173906196b741ac6ba55a9788ba9ebf2cd05f91715a49b6c3bfbb9d73/grpcio_health_checking-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/54/acc6a6e684827b0f6bb4e2c27f3d7e25b71322c4078ef5b455c07c43260e/grpcio_reflection-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/c8/8aaf447698c4d59aa853fd318eed300b5c9e44459f242ab8ead6c9c09792/gunicorn-25.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f5/71/b0a9193641d9e2471ac541d3b1b869538a5fb6419d52fd2669fa9c79e4b8/httptools-0.7.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9d/b3/11d406849715b47c9d69bb22f50874f80caee96bd1cbe7b61abbebbf5a05/ibis_framework-12.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/3d/2d244233ac4f76e38533cfcb2991c9eb4c7bf688ae0a036d30725b8faafe/importlib_metadata-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cd/58/4a1880ea64032185e9ae9f63940c9327c6952d5584ea544a8f66972f2fda/jwcrypto-1.5.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/01/99/f85130582f05dcf0c8902f3d629270231d2f4afdfc567f8305a952ac7f14/librt-0.8.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/af/cd/ce6e848bbf2c32314c9b237839119c5a564a59725b53157c856e90937b7a/markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b6/9e/8d9f6b9746f8ede78b0a4e4b8908e4d80bd609fca0b3e3195a07dda29534/minio-7.2.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c6/b1/e20d5f0d19c4c0f3df213fa7dcfa0942c4fb127d38e11f398ae8ddf6cccc/mmh3-5.2.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/fa/9d/2860be7355c45247ccc0be1501c91176318964c2a137bd4743f58ce6200e/mypy-1.20.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/40/a8/4dac1f8f8235e5d25b9955d02ff6f29396191d4e665d71122c3722ca83c5/pandas-2.3.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/77/fc/8cb9073bb1bee54eb49a1ae501a36402d01763812962ac811cdc1c81a9d7/parsy-2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/53/1b/3b431694a4dc6d37b9f653f0c64b0a0d9ec074ee810710c0c3da21d67ba7/protobuf-7.34.1-cp310-abi3-manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f8/82/c40b68001dbec8a3faa4c08cd8c200798ac732d2854537c5449dc859f55a/pyarrow-23.0.1-cp310-cp310-manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2e/c3/94ade4906a2f88bc935772f59c934013b4205e773bcb4239db114a6da136/pyarrow_hotfix-0.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5f/e9/a09476d436d0ff1402ac3867d933c61805ec2326c6ea557aeeac3825604e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a8/76/7727ef2ffa4b62fcab916686a68a0426b9b790139720e1934e8ba797e238/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/7a/8dd906bd22e79e47397a61742927f6747fe93242ef86645ee9092e610244/pyjwt-2.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/51/ff/f6e8b8f39e08547faece4bd80f89d5a8de68a38b2d179cc1c4490ffa3286/pytest-7.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/82/62e2d63639ecb0fbe8a7ee59ef0bc69a4669ec50f6d3459f74ad4e4189a2/pytest_asyncio-0.23.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/60/423a63fb190a0483d049786a121bd3dfd7d93bb5ff1bb5b5cd13e5df99a7/pytest_benchmark-3.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/25/b2/bdc663a5647ce2034f7e8420122af340df87c01ba97745fc753b8c917acb/pytest_env-1.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2d/a1/2f2c1c2353350d66c4d110d283e422e4943eb5ad10effa9357ba66f7b5b9/pytest_lazy_fixture-0.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/43/8deecb4c123bbc16d25666f1a6d241109c97aeb2e50806b952661c8e4b95/pytest_mock-1.10.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/98/adc368fe369465f291ab24e18b9900473786ed1afdf861ba90467eb0767e/pytest_ordering-0.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/df/97cc0b5b8b53da0e265acd0aeecfc0c279e950a029acd2d7b4e54b00b25f/pytest_timeout-1.4.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2e/2e/dfbd2c9b3edf6a5a8cd9e66090221046839b488ea27824970426bf06b242/python_keycloak-4.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/99/781fe0c827be2742bcc775efefccb3b048a3a9c6ce9aec0cbf4a101677e5/pytz-2026.1.post1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/8e/7540e8a2036f79a125c1d2ebadf69ed7901608859186c856fa0388ef4197/requests-2.33.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/61/b5/707f6cf0066a6412aacc11d17920ea2e19e5b2f04081c64526eb35b5c6e7/rpds_py-0.30.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5c/ad/6c4395649a212a6c603a72c5b9ab5dce3135a1546cfdffa3c427e71fd535/sqlalchemy-2.0.48-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/69/13/f8c5dd59b119feee28cce53f23361d955cd46d0612697d49db0070f41ea9/sqlglot-30.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0b/c9/584bc9651441b4ba60cc4d557d8a547b5aff901af35bda3a4ee30c819b82/starlette-1.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/3f/8ba87d9e287b9d385a02a7114ddcef61b26f86411e121c9003eb509a1773/tenacity-8.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/f8/6425ff800894784160290bcb9737878d910b6da6a08633bfe7f2ed8c9ae3/testcontainers-4.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/1f/4e5f8770c2cf4faa2c3ed3c19f9d4485ac9db0a6b029a7866921709bdc6c/uvicorn_worker-0.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/f6/21657bb3beb5f8c57ce8be3b83f653dd7933c2fd00545ed1b092d464799a/uvloop-0.22.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/d5/dc/1a680b7458ffa3b14bb64878112aefc8f2e4f73c5af763cbf0bd43100658/watchfiles-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/9d/2f/4b3ca7e106bc608744b1cdae041e005e446124bebb037b18799c2d356864/websockets-16.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c2/7a/32758ca2853b07a887a4574b74e28843919103194bb47001a304e24af62f/wrapt-2.1.2-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl + - pypi: ./ + osx-64: + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.7.5-hcc62823_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.52.0-h77d7759_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.10.20-hea035f4_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h68b038d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0a/08/a9bebdb2e0e602dde230bdde8021b29f71f7841bd54801bcfd514acb5dcf/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c7/80/9f608d13b4b3afcebd1dd13baf9551c95fc424d6390e4b1cfd7b1810cd06/async_property-0.2.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/96/c0/271f3e1e3502a8decb8ee5c680dbed2d8dc2cd504f5e20f7ed491d5f37e1/atpublic-7.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/e9/ed9f202cdf6bfa89ff09241a15a2b44a2d4a61cbe24119c2e391128562b1/bigtree-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/93/d7/516d984057745a6cd96575eea814fe1edd6646ee6efd552fb7b0921dec83/cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/26/08/0f303cb0b529e456bb116f2d50565a482694fbb94340bf56d44677e7ed03/charset_normalizer-3.4.7-cp310-cp310-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c4/cc/f330e982852403da79008552de9906804568ae9230da8432f7496ce02b71/cryptography-46.0.6-cp38-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/0e/f372bb290cef68c67331cd649b94d62220183ddc1b5bf3a9351ea6e9c8ec/deltalake-0.25.5-cp39-abi3-macosx_10_12_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/02/c3/253a89ee03fc9b9682f1541728eb66db7db22148cd94f89ab22528cd1e1b/deprecation-2.1.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/b8/22e6c605d9281df7a83653f4a60168eec0f650b23f1d4648aca940d79d00/duckdb-1.5.1-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/84/a4/5caa2de7f917a04ada20018eccf60d6cc6145b0199d55ca3711b0fc08312/fastapi-0.135.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d5/1f/5f4a3cd9e4440e9d9bc78ad0a91a1c8d46b4d429d5239ebe6793c9fe5c41/fsspec-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/3f/9859f655d11901e7b2996c6e3d33e0caa9a1d4572c3bc61ed0faa64b2f4c/greenlet-3.3.2-cp310-cp310-macosx_11_0_universal2.whl + - pypi: https://files.pythonhosted.org/packages/c5/63/ee244c4b64f0e71cef5314f9fa1d120c072e33c2e4c545dc75bd1af2a5c5/grpcio-1.62.3-cp310-cp310-macosx_12_0_universal2.whl + - pypi: https://files.pythonhosted.org/packages/40/4c/ee3173906196b741ac6ba55a9788ba9ebf2cd05f91715a49b6c3bfbb9d73/grpcio_health_checking-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/54/acc6a6e684827b0f6bb4e2c27f3d7e25b71322c4078ef5b455c07c43260e/grpcio_reflection-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/c8/8aaf447698c4d59aa853fd318eed300b5c9e44459f242ab8ead6c9c09792/gunicorn-25.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/e5/c07e0bcf4ec8db8164e9f6738c048b2e66aabf30e7506f440c4cc6953f60/httptools-0.7.1-cp310-cp310-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9d/b3/11d406849715b47c9d69bb22f50874f80caee96bd1cbe7b61abbebbf5a05/ibis_framework-12.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/3d/2d244233ac4f76e38533cfcb2991c9eb4c7bf688ae0a036d30725b8faafe/importlib_metadata-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cd/58/4a1880ea64032185e9ae9f63940c9327c6952d5584ea544a8f66972f2fda/jwcrypto-1.5.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7c/5f/63f5fa395c7a8a93558c0904ba8f1c8d1b997ca6a3de61bc7659970d66bf/librt-0.8.1-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e8/4b/3541d44f3937ba468b75da9eebcae497dcf67adb65caa16760b0a6807ebb/markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b6/9e/8d9f6b9746f8ede78b0a4e4b8908e4d80bd609fca0b3e3195a07dda29534/minio-7.2.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cc/bf/5404c2fd6ac84819e8ff1b7e34437b37cf55a2b11318894909e7bb88de3f/mmh3-5.2.1-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/4d/a2/a965c8c3fcd4fa8b84ba0d46606181b0d0a1d50f274c67877f3e9ed4882c/mypy-1.20.0-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3d/f7/f425a00df4fcc22b292c6895c6831c0c8ae1d9fac1e024d16f98a9ce8749/pandas-2.3.3-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/77/fc/8cb9073bb1bee54eb49a1ae501a36402d01763812962ac811cdc1c81a9d7/parsy-2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/11/3325d41e6ee15bf1125654301211247b042563bcc898784351252549a8ad/protobuf-7.34.1-cp310-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bc/8e/4be5617b4aaae0287f621ad31c6036e5f63118cfca0dc57d42121ff49b51/pyarrow-23.0.1-cp310-cp310-macosx_12_0_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2e/c3/94ade4906a2f88bc935772f59c934013b4205e773bcb4239db114a6da136/pyarrow_hotfix-0.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/4e/a066527e079fc5002390c8acdd3aca431e6ea0a50ffd7201551175b47323/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c6/90/32c9941e728d564b411d574d8ee0cf09b12ec978cb22b294995bae5549a5/pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/7a/8dd906bd22e79e47397a61742927f6747fe93242ef86645ee9092e610244/pyjwt-2.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/51/ff/f6e8b8f39e08547faece4bd80f89d5a8de68a38b2d179cc1c4490ffa3286/pytest-7.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/82/62e2d63639ecb0fbe8a7ee59ef0bc69a4669ec50f6d3459f74ad4e4189a2/pytest_asyncio-0.23.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/60/423a63fb190a0483d049786a121bd3dfd7d93bb5ff1bb5b5cd13e5df99a7/pytest_benchmark-3.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/25/b2/bdc663a5647ce2034f7e8420122af340df87c01ba97745fc753b8c917acb/pytest_env-1.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2d/a1/2f2c1c2353350d66c4d110d283e422e4943eb5ad10effa9357ba66f7b5b9/pytest_lazy_fixture-0.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/43/8deecb4c123bbc16d25666f1a6d241109c97aeb2e50806b952661c8e4b95/pytest_mock-1.10.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/98/adc368fe369465f291ab24e18b9900473786ed1afdf861ba90467eb0767e/pytest_ordering-0.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/df/97cc0b5b8b53da0e265acd0aeecfc0c279e950a029acd2d7b4e54b00b25f/pytest_timeout-1.4.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2e/2e/dfbd2c9b3edf6a5a8cd9e66090221046839b488ea27824970426bf06b242/python_keycloak-4.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/99/781fe0c827be2742bcc775efefccb3b048a3a9c6ce9aec0cbf4a101677e5/pytz-2026.1.post1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/8e/7540e8a2036f79a125c1d2ebadf69ed7901608859186c856fa0388ef4197/requests-2.33.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/06/0c/0c411a0ec64ccb6d104dcabe0e713e05e153a9a2c3c2bd2b32ce412166fe/rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/2c/9664130905f03db57961b8980b05cab624afd114bf2be2576628a9f22da4/sqlalchemy-2.0.48-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/13/f8c5dd59b119feee28cce53f23361d955cd46d0612697d49db0070f41ea9/sqlglot-30.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0b/c9/584bc9651441b4ba60cc4d557d8a547b5aff901af35bda3a4ee30c819b82/starlette-1.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/3f/8ba87d9e287b9d385a02a7114ddcef61b26f86411e121c9003eb509a1773/tenacity-8.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/f8/6425ff800894784160290bcb9737878d910b6da6a08633bfe7f2ed8c9ae3/testcontainers-4.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/1f/4e5f8770c2cf4faa2c3ed3c19f9d4485ac9db0a6b029a7866921709bdc6c/uvicorn_worker-0.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/ae/6f6f9af7f590b319c94532b9567409ba11f4fa71af1148cab1bf48a07048/uvloop-0.22.1-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/a7/1a/206e8cf2dd86fddf939165a57b4df61607a1e0add2785f170a3f616b7d9f/watchfiles-1.1.1-cp310-cp310-macosx_10_12_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/19/0f/22ef6107ee52ab7f0b710d55d36f5a5d3ef19e8a205541a6d7ffa7994e5a/websockets-16.0-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/da/d2/387594fb592d027366645f3d7cc9b4d7ca7be93845fbaba6d835a912ef3c/wrapt-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl + - pypi: ./ + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.5-hf6b4638_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.52.0-h1ae2325_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.10.20-h1b19095_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b6/02/d297943bcacf05e4f2a94ab6f462831dc20158614e5d067c35d4e63b9acb/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/c7/80/9f608d13b4b3afcebd1dd13baf9551c95fc424d6390e4b1cfd7b1810cd06/async_property-0.2.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/96/c0/271f3e1e3502a8decb8ee5c680dbed2d8dc2cd504f5e20f7ed491d5f37e1/atpublic-7.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/e9/ed9f202cdf6bfa89ff09241a15a2b44a2d4a61cbe24119c2e391128562b1/bigtree-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/84/ad6a0b408daa859246f57c03efd28e5dd1b33c21737c2db84cae8c237aa5/cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/26/08/0f303cb0b529e456bb116f2d50565a482694fbb94340bf56d44677e7ed03/charset_normalizer-3.4.7-cp310-cp310-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c4/cc/f330e982852403da79008552de9906804568ae9230da8432f7496ce02b71/cryptography-46.0.6-cp38-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/7a/ec22ff9d5c891b4f9ae834ef70524c92bd59d1408e9944e2652c87bc3f02/deltalake-0.25.5-cp39-abi3-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/02/c3/253a89ee03fc9b9682f1541728eb66db7db22148cd94f89ab22528cd1e1b/deprecation-2.1.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/85/b1/88a457cd3105525cba0d4c155f847c5c32fa4f543d3ba4ee38b4fd75f82e/duckdb-1.5.1-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/84/a4/5caa2de7f917a04ada20018eccf60d6cc6145b0199d55ca3711b0fc08312/fastapi-0.135.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d5/1f/5f4a3cd9e4440e9d9bc78ad0a91a1c8d46b4d429d5239ebe6793c9fe5c41/fsspec-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c5/63/ee244c4b64f0e71cef5314f9fa1d120c072e33c2e4c545dc75bd1af2a5c5/grpcio-1.62.3-cp310-cp310-macosx_12_0_universal2.whl + - pypi: https://files.pythonhosted.org/packages/40/4c/ee3173906196b741ac6ba55a9788ba9ebf2cd05f91715a49b6c3bfbb9d73/grpcio_health_checking-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/54/acc6a6e684827b0f6bb4e2c27f3d7e25b71322c4078ef5b455c07c43260e/grpcio_reflection-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/c8/8aaf447698c4d59aa853fd318eed300b5c9e44459f242ab8ead6c9c09792/gunicorn-25.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7e/4f/35e3a63f863a659f92ffd92bef131f3e81cf849af26e6435b49bd9f6f751/httptools-0.7.1-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9d/b3/11d406849715b47c9d69bb22f50874f80caee96bd1cbe7b61abbebbf5a05/ibis_framework-12.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/3d/2d244233ac4f76e38533cfcb2991c9eb4c7bf688ae0a036d30725b8faafe/importlib_metadata-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cd/58/4a1880ea64032185e9ae9f63940c9327c6952d5584ea544a8f66972f2fda/jwcrypto-1.5.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/e0/0472cf37267b5920eff2f292ccfaede1886288ce35b7f3203d8de00abfe6/librt-0.8.1-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/98/1b/fbd8eed11021cabd9226c37342fa6ca4e8a98d8188a8d9b66740494960e4/markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b6/9e/8d9f6b9746f8ede78b0a4e4b8908e4d80bd609fca0b3e3195a07dda29534/minio-7.2.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/de/0b/52bffad0b52ae4ea53e222b594bd38c08ecac1fc410323220a7202e43da5/mmh3-5.2.1-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/53/6e/043477501deeb8eabbab7f1a2f6cac62cfb631806dc1d6862a04a7f5011b/mypy-1.20.0-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/4f/66d99628ff8ce7857aca52fed8f0066ce209f96be2fede6cef9f84e8d04f/pandas-2.3.3-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/77/fc/8cb9073bb1bee54eb49a1ae501a36402d01763812962ac811cdc1c81a9d7/parsy-2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/11/3325d41e6ee15bf1125654301211247b042563bcc898784351252549a8ad/protobuf-7.34.1-cp310-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bc/a8/24e5dc6855f50a62936ceb004e6e9645e4219a8065f304145d7fb8a79d5d/pyarrow-23.0.1-cp310-cp310-macosx_12_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/2e/c3/94ade4906a2f88bc935772f59c934013b4205e773bcb4239db114a6da136/pyarrow_hotfix-0.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/6c/a1f71542c969912bb0e106f64f60a56cc1f0fabecf9396f45accbe63fa68/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/a8/61c96a77fe28993d9a6fb0f4127e05430a267b235a124545d79fea46dd65/pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/7a/8dd906bd22e79e47397a61742927f6747fe93242ef86645ee9092e610244/pyjwt-2.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/51/ff/f6e8b8f39e08547faece4bd80f89d5a8de68a38b2d179cc1c4490ffa3286/pytest-7.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/82/62e2d63639ecb0fbe8a7ee59ef0bc69a4669ec50f6d3459f74ad4e4189a2/pytest_asyncio-0.23.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/60/423a63fb190a0483d049786a121bd3dfd7d93bb5ff1bb5b5cd13e5df99a7/pytest_benchmark-3.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/25/b2/bdc663a5647ce2034f7e8420122af340df87c01ba97745fc753b8c917acb/pytest_env-1.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2d/a1/2f2c1c2353350d66c4d110d283e422e4943eb5ad10effa9357ba66f7b5b9/pytest_lazy_fixture-0.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/43/8deecb4c123bbc16d25666f1a6d241109c97aeb2e50806b952661c8e4b95/pytest_mock-1.10.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/98/adc368fe369465f291ab24e18b9900473786ed1afdf861ba90467eb0767e/pytest_ordering-0.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/df/97cc0b5b8b53da0e265acd0aeecfc0c279e950a029acd2d7b4e54b00b25f/pytest_timeout-1.4.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2e/2e/dfbd2c9b3edf6a5a8cd9e66090221046839b488ea27824970426bf06b242/python_keycloak-4.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/99/781fe0c827be2742bcc775efefccb3b048a3a9c6ce9aec0cbf4a101677e5/pytz-2026.1.post1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/8e/7540e8a2036f79a125c1d2ebadf69ed7901608859186c856fa0388ef4197/requests-2.33.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/6a/4ba3d0fb7297ebae71171822554abe48d7cab29c28b8f9f2c04b79988c05/rpds_py-0.30.0-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9a/67/1235676e93dd3b742a4a8eddfae49eea46c85e3eed29f0da446a8dd57500/sqlalchemy-2.0.48-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/69/13/f8c5dd59b119feee28cce53f23361d955cd46d0612697d49db0070f41ea9/sqlglot-30.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0b/c9/584bc9651441b4ba60cc4d557d8a547b5aff901af35bda3a4ee30c819b82/starlette-1.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/3f/8ba87d9e287b9d385a02a7114ddcef61b26f86411e121c9003eb509a1773/tenacity-8.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/f8/6425ff800894784160290bcb9737878d910b6da6a08633bfe7f2ed8c9ae3/testcontainers-4.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/1f/4e5f8770c2cf4faa2c3ed3c19f9d4485ac9db0a6b029a7866921709bdc6c/uvicorn_worker-0.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/eb/14/ecceb239b65adaaf7fde510aa8bd534075695d1e5f8dadfa32b5723d9cfb/uvloop-0.22.1-cp310-cp310-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/b3/0f/abaf5262b9c496b5dad4ed3c0e799cbecb1f8ea512ecb6ddd46646a9fca3/watchfiles-1.1.1-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/10/40/904a4cb30d9b61c0e278899bf36342e9b0208eb3c470324a9ecbaac2a30f/websockets-16.0-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/c9/18/3f373935bc5509e7ac444c8026a56762e50c1183e7061797437ca96c12ce/wrapt-2.1.2-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl + - pypi: ./ + ray-tests: + channels: + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + options: + pypi-prerelease-mode: if-necessary-or-explicit + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.5-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.10.20-h3c07f61_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/09/52/94108adfdd6e2ddf58be64f959a0b9c7d4ef2fa71086c38356d22dc501ea/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c7/80/9f608d13b4b3afcebd1dd13baf9551c95fc424d6390e4b1cfd7b1810cd06/async_property-0.2.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/e9/ed9f202cdf6bfa89ff09241a15a2b44a2d4a61cbe24119c2e391128562b1/bigtree-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/98/29/9b366e70e243eb3d14a5cb488dfd3a0b6b2f1fb001a203f653b93ccfac88/cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/20/e7/bed0024a0f4ab0c8a9c64d4445f39b30c99bd1acd228291959e3de664247/charset_normalizer-3.4.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/8a/b14f3101fe9c3592603339eb5d94046c3ce5f7fc76d6512a2d40efd9724e/cryptography-46.0.6-cp38-abi3-manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/02/c3/253a89ee03fc9b9682f1541728eb66db7db22148cd94f89ab22528cd1e1b/deprecation-2.1.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/84/a4/5caa2de7f917a04ada20018eccf60d6cc6145b0199d55ca3711b0fc08312/fastapi-0.135.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d5/1f/5f4a3cd9e4440e9d9bc78ad0a91a1c8d46b4d429d5239ebe6793c9fe5c41/fsspec-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/55/9f1ebb5a825215fadcc0f7d5073f6e79e3007e3282b14b22d6aba7ca6cb8/greenlet-3.3.2-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/58/2f/f3fc773270cf17e7ca076c1f6435278f58641d475a25cdeea5b2d8d4845b/grpcio-1.62.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/40/4c/ee3173906196b741ac6ba55a9788ba9ebf2cd05f91715a49b6c3bfbb9d73/grpcio_health_checking-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/54/acc6a6e684827b0f6bb4e2c27f3d7e25b71322c4078ef5b455c07c43260e/grpcio_reflection-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/c8/8aaf447698c4d59aa853fd318eed300b5c9e44459f242ab8ead6c9c09792/gunicorn-25.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f5/71/b0a9193641d9e2471ac541d3b1b869538a5fb6419d52fd2669fa9c79e4b8/httptools-0.7.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/3d/2d244233ac4f76e38533cfcb2991c9eb4c7bf688ae0a036d30725b8faafe/importlib_metadata-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cd/58/4a1880ea64032185e9ae9f63940c9327c6952d5584ea544a8f66972f2fda/jwcrypto-1.5.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/01/99/f85130582f05dcf0c8902f3d629270231d2f4afdfc567f8305a952ac7f14/librt-0.8.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/af/cd/ce6e848bbf2c32314c9b237839119c5a564a59725b53157c856e90937b7a/markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b6/9e/8d9f6b9746f8ede78b0a4e4b8908e4d80bd609fca0b3e3195a07dda29534/minio-7.2.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c6/b1/e20d5f0d19c4c0f3df213fa7dcfa0942c4fb127d38e11f398ae8ddf6cccc/mmh3-5.2.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b7/09/2a06956383c0fdebaef5aa9246e2356776f12ea6f2a44bd1368abf0e46c4/msgpack-1.1.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/fa/9d/2860be7355c45247ccc0be1501c91176318964c2a137bd4743f58ce6200e/mypy-1.20.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/40/a8/4dac1f8f8235e5d25b9955d02ff6f29396191d4e665d71122c3722ca83c5/pandas-2.3.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/53/1b/3b431694a4dc6d37b9f653f0c64b0a0d9ec074ee810710c0c3da21d67ba7/protobuf-7.34.1-cp310-abi3-manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f8/82/c40b68001dbec8a3faa4c08cd8c200798ac732d2854537c5449dc859f55a/pyarrow-23.0.1-cp310-cp310-manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5f/e9/a09476d436d0ff1402ac3867d933c61805ec2326c6ea557aeeac3825604e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a8/76/7727ef2ffa4b62fcab916686a68a0426b9b790139720e1934e8ba797e238/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/7a/8dd906bd22e79e47397a61742927f6747fe93242ef86645ee9092e610244/pyjwt-2.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/51/ff/f6e8b8f39e08547faece4bd80f89d5a8de68a38b2d179cc1c4490ffa3286/pytest-7.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/82/62e2d63639ecb0fbe8a7ee59ef0bc69a4669ec50f6d3459f74ad4e4189a2/pytest_asyncio-0.23.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/60/423a63fb190a0483d049786a121bd3dfd7d93bb5ff1bb5b5cd13e5df99a7/pytest_benchmark-3.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/25/b2/bdc663a5647ce2034f7e8420122af340df87c01ba97745fc753b8c917acb/pytest_env-1.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2d/a1/2f2c1c2353350d66c4d110d283e422e4943eb5ad10effa9357ba66f7b5b9/pytest_lazy_fixture-0.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/43/8deecb4c123bbc16d25666f1a6d241109c97aeb2e50806b952661c8e4b95/pytest_mock-1.10.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/98/adc368fe369465f291ab24e18b9900473786ed1afdf861ba90467eb0767e/pytest_ordering-0.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/df/97cc0b5b8b53da0e265acd0aeecfc0c279e950a029acd2d7b4e54b00b25f/pytest_timeout-1.4.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2e/2e/dfbd2c9b3edf6a5a8cd9e66090221046839b488ea27824970426bf06b242/python_keycloak-4.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/99/781fe0c827be2742bcc775efefccb3b048a3a9c6ce9aec0cbf4a101677e5/pytz-2026.1.post1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/55/96/7911234a14b891320e652b5ae258050f98584f22a8e33afba9ad43ab27c9/ray-2.54.1-cp310-cp310-manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/8e/7540e8a2036f79a125c1d2ebadf69ed7901608859186c856fa0388ef4197/requests-2.33.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/61/b5/707f6cf0066a6412aacc11d17920ea2e19e5b2f04081c64526eb35b5c6e7/rpds_py-0.30.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5c/ad/6c4395649a212a6c603a72c5b9ab5dce3135a1546cfdffa3c427e71fd535/sqlalchemy-2.0.48-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/0b/c9/584bc9651441b4ba60cc4d557d8a547b5aff901af35bda3a4ee30c819b82/starlette-1.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/3f/8ba87d9e287b9d385a02a7114ddcef61b26f86411e121c9003eb509a1773/tenacity-8.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/f8/6425ff800894784160290bcb9737878d910b6da6a08633bfe7f2ed8c9ae3/testcontainers-4.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/1f/4e5f8770c2cf4faa2c3ed3c19f9d4485ac9db0a6b029a7866921709bdc6c/uvicorn_worker-0.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/f6/21657bb3beb5f8c57ce8be3b83f653dd7933c2fd00545ed1b092d464799a/uvloop-0.22.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/d5/dc/1a680b7458ffa3b14bb64878112aefc8f2e4f73c5af763cbf0bd43100658/watchfiles-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/9d/2f/4b3ca7e106bc608744b1cdae041e005e446124bebb037b18799c2d356864/websockets-16.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c2/7a/32758ca2853b07a887a4574b74e28843919103194bb47001a304e24af62f/wrapt-2.1.2-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl + - pypi: ./ + osx-64: + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.7.5-hcc62823_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.52.0-h77d7759_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.10.20-hea035f4_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h68b038d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0a/08/a9bebdb2e0e602dde230bdde8021b29f71f7841bd54801bcfd514acb5dcf/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c7/80/9f608d13b4b3afcebd1dd13baf9551c95fc424d6390e4b1cfd7b1810cd06/async_property-0.2.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/e9/ed9f202cdf6bfa89ff09241a15a2b44a2d4a61cbe24119c2e391128562b1/bigtree-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/93/d7/516d984057745a6cd96575eea814fe1edd6646ee6efd552fb7b0921dec83/cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/26/08/0f303cb0b529e456bb116f2d50565a482694fbb94340bf56d44677e7ed03/charset_normalizer-3.4.7-cp310-cp310-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c4/cc/f330e982852403da79008552de9906804568ae9230da8432f7496ce02b71/cryptography-46.0.6-cp38-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/02/c3/253a89ee03fc9b9682f1541728eb66db7db22148cd94f89ab22528cd1e1b/deprecation-2.1.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/84/a4/5caa2de7f917a04ada20018eccf60d6cc6145b0199d55ca3711b0fc08312/fastapi-0.135.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d5/1f/5f4a3cd9e4440e9d9bc78ad0a91a1c8d46b4d429d5239ebe6793c9fe5c41/fsspec-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/3f/9859f655d11901e7b2996c6e3d33e0caa9a1d4572c3bc61ed0faa64b2f4c/greenlet-3.3.2-cp310-cp310-macosx_11_0_universal2.whl + - pypi: https://files.pythonhosted.org/packages/c5/63/ee244c4b64f0e71cef5314f9fa1d120c072e33c2e4c545dc75bd1af2a5c5/grpcio-1.62.3-cp310-cp310-macosx_12_0_universal2.whl + - pypi: https://files.pythonhosted.org/packages/40/4c/ee3173906196b741ac6ba55a9788ba9ebf2cd05f91715a49b6c3bfbb9d73/grpcio_health_checking-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/54/acc6a6e684827b0f6bb4e2c27f3d7e25b71322c4078ef5b455c07c43260e/grpcio_reflection-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/c8/8aaf447698c4d59aa853fd318eed300b5c9e44459f242ab8ead6c9c09792/gunicorn-25.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/e5/c07e0bcf4ec8db8164e9f6738c048b2e66aabf30e7506f440c4cc6953f60/httptools-0.7.1-cp310-cp310-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/3d/2d244233ac4f76e38533cfcb2991c9eb4c7bf688ae0a036d30725b8faafe/importlib_metadata-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cd/58/4a1880ea64032185e9ae9f63940c9327c6952d5584ea544a8f66972f2fda/jwcrypto-1.5.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7c/5f/63f5fa395c7a8a93558c0904ba8f1c8d1b997ca6a3de61bc7659970d66bf/librt-0.8.1-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e8/4b/3541d44f3937ba468b75da9eebcae497dcf67adb65caa16760b0a6807ebb/markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b6/9e/8d9f6b9746f8ede78b0a4e4b8908e4d80bd609fca0b3e3195a07dda29534/minio-7.2.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cc/bf/5404c2fd6ac84819e8ff1b7e34437b37cf55a2b11318894909e7bb88de3f/mmh3-5.2.1-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f5/a2/3b68a9e769db68668b25c6108444a35f9bd163bb848c0650d516761a59c0/msgpack-1.1.2-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/4d/a2/a965c8c3fcd4fa8b84ba0d46606181b0d0a1d50f274c67877f3e9ed4882c/mypy-1.20.0-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3d/f7/f425a00df4fcc22b292c6895c6831c0c8ae1d9fac1e024d16f98a9ce8749/pandas-2.3.3-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/11/3325d41e6ee15bf1125654301211247b042563bcc898784351252549a8ad/protobuf-7.34.1-cp310-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bc/8e/4be5617b4aaae0287f621ad31c6036e5f63118cfca0dc57d42121ff49b51/pyarrow-23.0.1-cp310-cp310-macosx_12_0_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/4e/a066527e079fc5002390c8acdd3aca431e6ea0a50ffd7201551175b47323/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c6/90/32c9941e728d564b411d574d8ee0cf09b12ec978cb22b294995bae5549a5/pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/7a/8dd906bd22e79e47397a61742927f6747fe93242ef86645ee9092e610244/pyjwt-2.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/51/ff/f6e8b8f39e08547faece4bd80f89d5a8de68a38b2d179cc1c4490ffa3286/pytest-7.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/82/62e2d63639ecb0fbe8a7ee59ef0bc69a4669ec50f6d3459f74ad4e4189a2/pytest_asyncio-0.23.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/60/423a63fb190a0483d049786a121bd3dfd7d93bb5ff1bb5b5cd13e5df99a7/pytest_benchmark-3.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/25/b2/bdc663a5647ce2034f7e8420122af340df87c01ba97745fc753b8c917acb/pytest_env-1.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2d/a1/2f2c1c2353350d66c4d110d283e422e4943eb5ad10effa9357ba66f7b5b9/pytest_lazy_fixture-0.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/43/8deecb4c123bbc16d25666f1a6d241109c97aeb2e50806b952661c8e4b95/pytest_mock-1.10.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/98/adc368fe369465f291ab24e18b9900473786ed1afdf861ba90467eb0767e/pytest_ordering-0.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/df/97cc0b5b8b53da0e265acd0aeecfc0c279e950a029acd2d7b4e54b00b25f/pytest_timeout-1.4.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2e/2e/dfbd2c9b3edf6a5a8cd9e66090221046839b488ea27824970426bf06b242/python_keycloak-4.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/99/781fe0c827be2742bcc775efefccb3b048a3a9c6ce9aec0cbf4a101677e5/pytz-2026.1.post1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/61/c5/c2ceba832fe3f47cfd7e11cd7cc7a1bbc2c028424c5bca70435aa4ca1dec/ray-2.49.2-cp310-cp310-macosx_12_0_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/8e/7540e8a2036f79a125c1d2ebadf69ed7901608859186c856fa0388ef4197/requests-2.33.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/06/0c/0c411a0ec64ccb6d104dcabe0e713e05e153a9a2c3c2bd2b32ce412166fe/rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/2c/9664130905f03db57961b8980b05cab624afd114bf2be2576628a9f22da4/sqlalchemy-2.0.48-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0b/c9/584bc9651441b4ba60cc4d557d8a547b5aff901af35bda3a4ee30c819b82/starlette-1.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/3f/8ba87d9e287b9d385a02a7114ddcef61b26f86411e121c9003eb509a1773/tenacity-8.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/f8/6425ff800894784160290bcb9737878d910b6da6a08633bfe7f2ed8c9ae3/testcontainers-4.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/1f/4e5f8770c2cf4faa2c3ed3c19f9d4485ac9db0a6b029a7866921709bdc6c/uvicorn_worker-0.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/ae/6f6f9af7f590b319c94532b9567409ba11f4fa71af1148cab1bf48a07048/uvloop-0.22.1-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/a7/1a/206e8cf2dd86fddf939165a57b4df61607a1e0add2785f170a3f616b7d9f/watchfiles-1.1.1-cp310-cp310-macosx_10_12_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/19/0f/22ef6107ee52ab7f0b710d55d36f5a5d3ef19e8a205541a6d7ffa7994e5a/websockets-16.0-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/da/d2/387594fb592d027366645f3d7cc9b4d7ca7be93845fbaba6d835a912ef3c/wrapt-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl + - pypi: ./ + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.5-hf6b4638_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.52.0-h1ae2325_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.10.20-h1b19095_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b6/02/d297943bcacf05e4f2a94ab6f462831dc20158614e5d067c35d4e63b9acb/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/c7/80/9f608d13b4b3afcebd1dd13baf9551c95fc424d6390e4b1cfd7b1810cd06/async_property-0.2.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/e9/ed9f202cdf6bfa89ff09241a15a2b44a2d4a61cbe24119c2e391128562b1/bigtree-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/84/ad6a0b408daa859246f57c03efd28e5dd1b33c21737c2db84cae8c237aa5/cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/26/08/0f303cb0b529e456bb116f2d50565a482694fbb94340bf56d44677e7ed03/charset_normalizer-3.4.7-cp310-cp310-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c4/cc/f330e982852403da79008552de9906804568ae9230da8432f7496ce02b71/cryptography-46.0.6-cp38-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/02/c3/253a89ee03fc9b9682f1541728eb66db7db22148cd94f89ab22528cd1e1b/deprecation-2.1.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/84/a4/5caa2de7f917a04ada20018eccf60d6cc6145b0199d55ca3711b0fc08312/fastapi-0.135.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d5/1f/5f4a3cd9e4440e9d9bc78ad0a91a1c8d46b4d429d5239ebe6793c9fe5c41/fsspec-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c5/63/ee244c4b64f0e71cef5314f9fa1d120c072e33c2e4c545dc75bd1af2a5c5/grpcio-1.62.3-cp310-cp310-macosx_12_0_universal2.whl + - pypi: https://files.pythonhosted.org/packages/40/4c/ee3173906196b741ac6ba55a9788ba9ebf2cd05f91715a49b6c3bfbb9d73/grpcio_health_checking-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/54/acc6a6e684827b0f6bb4e2c27f3d7e25b71322c4078ef5b455c07c43260e/grpcio_reflection-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/c8/8aaf447698c4d59aa853fd318eed300b5c9e44459f242ab8ead6c9c09792/gunicorn-25.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7e/4f/35e3a63f863a659f92ffd92bef131f3e81cf849af26e6435b49bd9f6f751/httptools-0.7.1-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/3d/2d244233ac4f76e38533cfcb2991c9eb4c7bf688ae0a036d30725b8faafe/importlib_metadata-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cd/58/4a1880ea64032185e9ae9f63940c9327c6952d5584ea544a8f66972f2fda/jwcrypto-1.5.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/e0/0472cf37267b5920eff2f292ccfaede1886288ce35b7f3203d8de00abfe6/librt-0.8.1-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/98/1b/fbd8eed11021cabd9226c37342fa6ca4e8a98d8188a8d9b66740494960e4/markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/b6/9e/8d9f6b9746f8ede78b0a4e4b8908e4d80bd609fca0b3e3195a07dda29534/minio-7.2.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/de/0b/52bffad0b52ae4ea53e222b594bd38c08ecac1fc410323220a7202e43da5/mmh3-5.2.1-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/5b/e1/2b720cc341325c00be44e1ed59e7cfeae2678329fbf5aa68f5bda57fe728/msgpack-1.1.2-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/53/6e/043477501deeb8eabbab7f1a2f6cac62cfb631806dc1d6862a04a7f5011b/mypy-1.20.0-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/4f/66d99628ff8ce7857aca52fed8f0066ce209f96be2fede6cef9f84e8d04f/pandas-2.3.3-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/11/3325d41e6ee15bf1125654301211247b042563bcc898784351252549a8ad/protobuf-7.34.1-cp310-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bc/a8/24e5dc6855f50a62936ceb004e6e9645e4219a8065f304145d7fb8a79d5d/pyarrow-23.0.1-cp310-cp310-macosx_12_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/6c/a1f71542c969912bb0e106f64f60a56cc1f0fabecf9396f45accbe63fa68/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/a8/61c96a77fe28993d9a6fb0f4127e05430a267b235a124545d79fea46dd65/pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/7a/8dd906bd22e79e47397a61742927f6747fe93242ef86645ee9092e610244/pyjwt-2.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/51/ff/f6e8b8f39e08547faece4bd80f89d5a8de68a38b2d179cc1c4490ffa3286/pytest-7.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/82/62e2d63639ecb0fbe8a7ee59ef0bc69a4669ec50f6d3459f74ad4e4189a2/pytest_asyncio-0.23.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/60/423a63fb190a0483d049786a121bd3dfd7d93bb5ff1bb5b5cd13e5df99a7/pytest_benchmark-3.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/25/b2/bdc663a5647ce2034f7e8420122af340df87c01ba97745fc753b8c917acb/pytest_env-1.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2d/a1/2f2c1c2353350d66c4d110d283e422e4943eb5ad10effa9357ba66f7b5b9/pytest_lazy_fixture-0.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/43/8deecb4c123bbc16d25666f1a6d241109c97aeb2e50806b952661c8e4b95/pytest_mock-1.10.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/98/adc368fe369465f291ab24e18b9900473786ed1afdf861ba90467eb0767e/pytest_ordering-0.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/df/97cc0b5b8b53da0e265acd0aeecfc0c279e950a029acd2d7b4e54b00b25f/pytest_timeout-1.4.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2e/2e/dfbd2c9b3edf6a5a8cd9e66090221046839b488ea27824970426bf06b242/python_keycloak-4.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/99/781fe0c827be2742bcc775efefccb3b048a3a9c6ce9aec0cbf4a101677e5/pytz-2026.1.post1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/af/cf/9a6e33b59e1a12428b4fbd6cc38f7e32d116ccde4c72e15c3f76a22bf36d/ray-2.54.1-cp310-cp310-macosx_12_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/8e/7540e8a2036f79a125c1d2ebadf69ed7901608859186c856fa0388ef4197/requests-2.33.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/6a/4ba3d0fb7297ebae71171822554abe48d7cab29c28b8f9f2c04b79988c05/rpds_py-0.30.0-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9a/67/1235676e93dd3b742a4a8eddfae49eea46c85e3eed29f0da446a8dd57500/sqlalchemy-2.0.48-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/0b/c9/584bc9651441b4ba60cc4d557d8a547b5aff901af35bda3a4ee30c819b82/starlette-1.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/3f/8ba87d9e287b9d385a02a7114ddcef61b26f86411e121c9003eb509a1773/tenacity-8.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/f8/6425ff800894784160290bcb9737878d910b6da6a08633bfe7f2ed8c9ae3/testcontainers-4.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/1f/4e5f8770c2cf4faa2c3ed3c19f9d4485ac9db0a6b029a7866921709bdc6c/uvicorn_worker-0.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/eb/14/ecceb239b65adaaf7fde510aa8bd534075695d1e5f8dadfa32b5723d9cfb/uvloop-0.22.1-cp310-cp310-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/b3/0f/abaf5262b9c496b5dad4ed3c0e799cbecb1f8ea512ecb6ddd46646a9fca3/watchfiles-1.1.1-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/10/40/904a4cb30d9b61c0e278899bf36342e9b0208eb3c470324a9ecbaac2a30f/websockets-16.0-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/c9/18/3f373935bc5509e7ac444c8026a56762e50c1183e7061797437ca96c12ce/wrapt-2.1.2-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl + - pypi: ./ + registration-tests: + channels: + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + options: + pypi-prerelease-mode: if-necessary-or-explicit + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.5-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.10.20-h3c07f61_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - pypi: https://files.pythonhosted.org/packages/92/d9/25a697a959a7149c93efa4d849421aa5f22bcb82350ac89b4284b0b88aa8/aiobotocore-2.23.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2f/86/a6f3ff1fd795f49545a7c74b2c92f62729135d73e7e4055bf74da5a26c82/aiohttp-3.13.5-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/10/a1/510b0a7fadc6f43a6ce50152e69dbd86415240835868bb0bd9b5b88b1e06/aioitertools-0.13.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/09/52/94108adfdd6e2ddf58be64f959a0b9c7d4ef2fa71086c38356d22dc501ea/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c9/7f/09065fd9e27da0eda08b4d6897f1c13535066174cc023af248fc2a8d5e5a/asn1crypto-1.5.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/80/9f608d13b4b3afcebd1dd13baf9551c95fc424d6390e4b1cfd7b1810cd06/async_property-0.2.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fe/ba/e2081de779ca30d473f21f5b30e0e737c438205440784c7dfc81efc2b029/async_timeout-5.0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/e9/ed9f202cdf6bfa89ff09241a15a2b44a2d4a61cbe24119c2e391128562b1/bigtree-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/8b/b2361188bd1e293eede1bc165e2461d390394f71ec0c8c21211c8dabf62c/boto3-1.38.27-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/00/dd90b7a0255587ba1c9754d32a221adb4a9022f181df3eef401b0b9fadfc/botocore-1.38.46-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/98/29/9b366e70e243eb3d14a5cb488dfd3a0b6b2f1fb001a203f653b93ccfac88/cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/20/e7/bed0024a0f4ab0c8a9c64d4445f39b30c99bd1acd228291959e3de664247/charset_normalizer-3.4.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/8a/b14f3101fe9c3592603339eb5d94046c3ce5f7fc76d6512a2d40efd9724e/cryptography-46.0.6-cp38-abi3-manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/76/09/22793699ce02e5e58836f98cff1d2b872c94608446f772bd3a50065aa9fb/db_dtypes-1.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/02/c3/253a89ee03fc9b9682f1541728eb66db7db22148cd94f89ab22528cd1e1b/deprecation-2.1.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/84/a4/5caa2de7f917a04ada20018eccf60d6cc6145b0199d55ca3711b0fc08312/fastapi-0.135.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5d/ed/c7895fd2fde7f3ee70d248175f9b6cdf792fb741ab92dc59cd9ef3bd241b/frozenlist-1.8.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/1d/a0/6aaea0c2fbea2f89bfd5db25fb1e3481896a423002ebe4e55288907a97a3/fsspec-2024.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/84/e1/ebd5100cbb202e561c0c8b59e485ef3bd63fa9beb610f3fdcaea443f0288/google_api_core-2.30.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/eb/c6c2478d8a8d633460be40e2a8a6f8f429171997a35a96f81d3b680dec83/google_auth-2.49.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2a/e0/cb454a95f460903e39f101e950038ec24a072ca69d0a294a6df625cc1627/google_auth_oauthlib-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/40/33/1d3902efadef9194566d499d61507e1f038454e0b55499d2d7f8ab2a4fee/google_cloud_bigquery-3.41.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/0e/2950d4d0160300f51c7397a080b1685d3e25b40badb2c96f03d58d0ee868/google_cloud_bigquery_storage-2.37.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/19/1cc695fa8489ef446a70ee9e983c12f4b47e0649005758035530eaec4b1c/google_cloud_bigtable-2.36.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/73/d9/5bb050cb32826466aa9b25f79e2ca2879fe66cb76782d4ed798dd7506151/google_cloud_core-2.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5b/88/357efc6b331fd29155dcb92a5dfb0030a8a6feddb7bbf8a6215defbed6c7/google_cloud_datastore-2.24.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d5/94/6db383d8ee1adf45dc6c73477152b82731fa4c4a46d9c1932cc8757e0fd4/google_cloud_storage-2.19.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3d/63/bec827e70b7a0d4094e7476f863c0dbd6b5f0f1f91d9c9b32b76dcdfeb4e/google_crc32c-1.8.0-cp310-cp310-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/5e/f8/50bfaf4658431ff9de45c5c3935af7ab01157a4903c603cd0eee6e78e087/google_resumable_media-2.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b6/b0/be5d3329badb9230b765de6eea66b73abd5944bdeb5afb3562ddcd80ae84/googleapis_common_protos-1.74.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/55/9f1ebb5a825215fadcc0f7d5073f6e79e3007e3282b14b22d6aba7ca6cb8/greenlet-3.3.2-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/89/22/c2dd50c09bf679bd38173656cd4402d2511e563b33bc88f90009cf50613c/grpc_google_iam_v1-0.14.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/58/2f/f3fc773270cf17e7ca076c1f6435278f58641d475a25cdeea5b2d8d4845b/grpcio-1.62.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/40/4c/ee3173906196b741ac6ba55a9788ba9ebf2cd05f91715a49b6c3bfbb9d73/grpcio_health_checking-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/54/acc6a6e684827b0f6bb4e2c27f3d7e25b71322c4078ef5b455c07c43260e/grpcio_reflection-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/40/972271de05f9315c0d69f9f7ebbcadd83bc85322f538637d11bb8c67803d/grpcio_status-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b2/23/55d40e1bf54c141f541ab31b4b4b0f58610440c8837b1406f3467c2b4853/grpcio_testing-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/c8/8aaf447698c4d59aa853fd318eed300b5c9e44459f242ab8ead6c9c09792/gunicorn-25.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/42/6e/8adaefff7e3e216b0f7bd6cafce6d5d06798f31c3e2852dc3db6a7d758c9/hiredis-2.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f5/71/b0a9193641d9e2471ac541d3b1b869538a5fb6419d52fd2669fa9c79e4b8/httptools-0.7.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/3d/2d244233ac4f76e38533cfcb2991c9eb4c7bf688ae0a036d30725b8faafe/importlib_metadata-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/14/2f/967ba146e6d58cf6a652da73885f52fc68001525b4197effc174321d70b4/jmespath-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cd/58/4a1880ea64032185e9ae9f63940c9327c6952d5584ea544a8f66972f2fda/jwcrypto-1.5.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/01/99/f85130582f05dcf0c8902f3d629270231d2f4afdfc567f8305a952ac7f14/librt-0.8.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/af/cd/ce6e848bbf2c32314c9b237839119c5a564a59725b53157c856e90937b7a/markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b6/9e/8d9f6b9746f8ede78b0a4e4b8908e4d80bd609fca0b3e3195a07dda29534/minio-7.2.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c6/b1/e20d5f0d19c4c0f3df213fa7dcfa0942c4fb127d38e11f398ae8ddf6cccc/mmh3-5.2.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/4b/ac/b605473de2bb404e742f2cc3583d12aedb2352a70e49ae8fce455b50c5aa/multidict-6.7.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/fa/9d/2860be7355c45247ccc0be1501c91176318964c2a137bd4743f58ce6200e/mypy-1.20.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/be/9c/92789c596b8df838baa98fa71844d84283302f7604ed565dafe5a6b5041a/oauthlib-3.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/40/a8/4dac1f8f8235e5d25b9955d02ff6f29396191d4e665d71122c3722ca83c5/pandas-2.3.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c2/51/72b7c3b25ecfc6810b29ae9bffe76e26a407adb20de5b90ed984b3d483ca/pandas_gbq-0.34.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/08/57/8c87e93142b2c1fa2408e45695205a7ba05fb5db458c0bf5c06ba0e09ea6/propcache-0.4.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/84/f3/1fba73eeffafc998a25d59703b63f8be4fe8a5cb12eaff7386a0ba0f7125/proto_plus-1.27.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/92/d1e32e3e0d894fe00b15ce28ad4944ab692713f2e7f0a99787405e43533a/protobuf-6.33.6-cp39-abi3-manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/18/f3/14a1370b1449ca875d5e353ef02cb9db6b70bd46ec361c236176837c0be1/psycopg-3.2.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a5/90/9f2c41b3b42d8cd8b9866f0bbd27a5796a1ca8042a1a019b39a6645df523/psycopg_binary-3.2.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/e7/c3/26b8a0908a9db249de3b4169692e1c7c19048a9bc41a4d3209cee7dbb758/psycopg_pool-3.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/db/ea0203e495be491c85af87b66e37acfd3bf756fd985f87e46fc5e3bf022c/py4j-0.10.9.9-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f8/82/c40b68001dbec8a3faa4c08cd8c200798ac732d2854537c5449dc859f55a/pyarrow-23.0.1-cp310-cp310-manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/5d/a0/7d793dce3fa811fe047d6ae2431c672364b462850c6235ae306c0efd025f/pyasn1-0.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5f/e9/a09476d436d0ff1402ac3867d933c61805ec2326c6ea557aeeac3825604e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a8/76/7727ef2ffa4b62fcab916686a68a0426b9b790139720e1934e8ba797e238/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/ca/cb/cdeaba62aa3c48f0d8834afb82b4a21463cd83df34fe01f9daa89a08ec6c/pydata_google_auth-1.9.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/7a/8dd906bd22e79e47397a61742927f6747fe93242ef86645ee9092e610244/pyjwt-2.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7c/4c/ad33b92b9864cbde84f259d5df035a6447f91891f5be77788e2a3892bce3/pymysql-1.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/7d/d4f7d908fa8415571771b30669251d57c3cf313b36a856e6d7548ae01619/pyopenssl-26.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/bf/58ee13add151469c25825b7125bbf62c3bdcec05eec4d458fcb5c5516066/pyspark-4.1.1.tar.gz + - pypi: https://files.pythonhosted.org/packages/51/ff/f6e8b8f39e08547faece4bd80f89d5a8de68a38b2d179cc1c4490ffa3286/pytest-7.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/82/62e2d63639ecb0fbe8a7ee59ef0bc69a4669ec50f6d3459f74ad4e4189a2/pytest_asyncio-0.23.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/60/423a63fb190a0483d049786a121bd3dfd7d93bb5ff1bb5b5cd13e5df99a7/pytest_benchmark-3.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/25/b2/bdc663a5647ce2034f7e8420122af340df87c01ba97745fc753b8c917acb/pytest_env-1.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2d/a1/2f2c1c2353350d66c4d110d283e422e4943eb5ad10effa9357ba66f7b5b9/pytest_lazy_fixture-0.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/43/8deecb4c123bbc16d25666f1a6d241109c97aeb2e50806b952661c8e4b95/pytest_mock-1.10.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/98/adc368fe369465f291ab24e18b9900473786ed1afdf861ba90467eb0767e/pytest_ordering-0.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/df/97cc0b5b8b53da0e265acd0aeecfc0c279e950a029acd2d7b4e54b00b25f/pytest_timeout-1.4.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2e/2e/dfbd2c9b3edf6a5a8cd9e66090221046839b488ea27824970426bf06b242/python_keycloak-4.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/99/781fe0c827be2742bcc775efefccb3b048a3a9c6ce9aec0cbf4a101677e5/pytz-2026.1.post1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/20/2e/409703d645363352a20c944f5d119bdae3eb3034051a53724a7c5fee12b8/redis-4.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/8e/7540e8a2036f79a125c1d2ebadf69ed7901608859186c856fa0388ef4197/requests-2.33.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3b/5d/63d4ae3b9daea098d5d6f5da83984853c1bbacd5dc826764b249fe119d24/requests_oauthlib-2.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/61/b5/707f6cf0066a6412aacc11d17920ea2e19e5b2f04081c64526eb35b5c6e7/rpds_py-0.30.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/6d/4f/d073e09df851cfa251ef7840007d04db3293a0482ce607d2b993926089be/s3transfer-0.13.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9d/76/f789f7a86709c6b087c5a2f52f911838cad707cc613162401badc665acfe/setuptools-82.0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/2f/4e1d2c1f93fa0009a4f34ba5168060e719cb1d9fef319fb0970f1e0bd8d6/snowflake_connector_python-4.4.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5c/ad/6c4395649a212a6c603a72c5b9ab5dce3135a1546cfdffa3c427e71fd535/sqlalchemy-2.0.48-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/0b/c9/584bc9651441b4ba60cc4d557d8a547b5aff901af35bda3a4ee30c819b82/starlette-1.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/3f/8ba87d9e287b9d385a02a7114ddcef61b26f86411e121c9003eb509a1773/tenacity-8.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/f8/6425ff800894784160290bcb9737878d910b6da6a08633bfe7f2ed8c9ae3/testcontainers-4.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b5/11/87d6d29fb5d237229d67973a6c9e06e048f01cf4994dee194ab0ea841814/tomlkit-0.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/fa/4f4d3bfca9ef6dd17d69ed18b96564c53b32d3ce774132308d0bee849f10/types_pymysql-1.1.0.20251220-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/1f/4e5f8770c2cf4faa2c3ed3c19f9d4485ac9db0a6b029a7866921709bdc6c/uvicorn_worker-0.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/f6/21657bb3beb5f8c57ce8be3b83f653dd7933c2fd00545ed1b092d464799a/uvloop-0.22.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/d5/dc/1a680b7458ffa3b14bb64878112aefc8f2e4f73c5af763cbf0bd43100658/watchfiles-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/9d/2f/4b3ca7e106bc608744b1cdae041e005e446124bebb037b18799c2d356864/websockets-16.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/de/17/9f8f86755c191d6779d7ddead1a53c7a8aa18bccb7cea8e7e72dfa6a8a09/wrapt-1.17.3-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/50/12/95a1d33f04a79c402664070d43b8b9f72dc18914e135b345b611b0b1f8cc/yarl-1.23.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl + - pypi: ./ + osx-64: + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.7.5-hcc62823_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.52.0-h77d7759_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.10.20-hea035f4_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h68b038d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - pypi: https://files.pythonhosted.org/packages/92/d9/25a697a959a7149c93efa4d849421aa5f22bcb82350ac89b4284b0b88aa8/aiobotocore-2.23.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/05/98/afd308e35b9d3d8c9ec54c0918f1d722c86dc17ddfec272fcdbcce5a3124/aiohttp-3.13.5-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/10/a1/510b0a7fadc6f43a6ce50152e69dbd86415240835868bb0bd9b5b88b1e06/aioitertools-0.13.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0a/08/a9bebdb2e0e602dde230bdde8021b29f71f7841bd54801bcfd514acb5dcf/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c9/7f/09065fd9e27da0eda08b4d6897f1c13535066174cc023af248fc2a8d5e5a/asn1crypto-1.5.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/80/9f608d13b4b3afcebd1dd13baf9551c95fc424d6390e4b1cfd7b1810cd06/async_property-0.2.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fe/ba/e2081de779ca30d473f21f5b30e0e737c438205440784c7dfc81efc2b029/async_timeout-5.0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/e9/ed9f202cdf6bfa89ff09241a15a2b44a2d4a61cbe24119c2e391128562b1/bigtree-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/8b/b2361188bd1e293eede1bc165e2461d390394f71ec0c8c21211c8dabf62c/boto3-1.38.27-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/00/dd90b7a0255587ba1c9754d32a221adb4a9022f181df3eef401b0b9fadfc/botocore-1.38.46-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/93/d7/516d984057745a6cd96575eea814fe1edd6646ee6efd552fb7b0921dec83/cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/26/08/0f303cb0b529e456bb116f2d50565a482694fbb94340bf56d44677e7ed03/charset_normalizer-3.4.7-cp310-cp310-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c4/cc/f330e982852403da79008552de9906804568ae9230da8432f7496ce02b71/cryptography-46.0.6-cp38-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/76/09/22793699ce02e5e58836f98cff1d2b872c94608446f772bd3a50065aa9fb/db_dtypes-1.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/02/c3/253a89ee03fc9b9682f1541728eb66db7db22148cd94f89ab22528cd1e1b/deprecation-2.1.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/84/a4/5caa2de7f917a04ada20018eccf60d6cc6145b0199d55ca3711b0fc08312/fastapi-0.135.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/fb/c85f9fed3ea8fe8740e5b46a59cc141c23b842eca617da8876cfce5f760e/frozenlist-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/1d/a0/6aaea0c2fbea2f89bfd5db25fb1e3481896a423002ebe4e55288907a97a3/fsspec-2024.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/84/e1/ebd5100cbb202e561c0c8b59e485ef3bd63fa9beb610f3fdcaea443f0288/google_api_core-2.30.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/eb/c6c2478d8a8d633460be40e2a8a6f8f429171997a35a96f81d3b680dec83/google_auth-2.49.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2a/e0/cb454a95f460903e39f101e950038ec24a072ca69d0a294a6df625cc1627/google_auth_oauthlib-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/40/33/1d3902efadef9194566d499d61507e1f038454e0b55499d2d7f8ab2a4fee/google_cloud_bigquery-3.41.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/0e/2950d4d0160300f51c7397a080b1685d3e25b40badb2c96f03d58d0ee868/google_cloud_bigquery_storage-2.37.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/19/1cc695fa8489ef446a70ee9e983c12f4b47e0649005758035530eaec4b1c/google_cloud_bigtable-2.36.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/73/d9/5bb050cb32826466aa9b25f79e2ca2879fe66cb76782d4ed798dd7506151/google_cloud_core-2.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5b/88/357efc6b331fd29155dcb92a5dfb0030a8a6feddb7bbf8a6215defbed6c7/google_cloud_datastore-2.24.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d5/94/6db383d8ee1adf45dc6c73477152b82731fa4c4a46d9c1932cc8757e0fd4/google_cloud_storage-2.19.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/97/a5accde175dee985311d949cfcb1249dcbb290f5ec83c994ea733311948f/google_crc32c-1.8.0-cp310-cp310-macosx_12_0_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/5e/f8/50bfaf4658431ff9de45c5c3935af7ab01157a4903c603cd0eee6e78e087/google_resumable_media-2.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b6/b0/be5d3329badb9230b765de6eea66b73abd5944bdeb5afb3562ddcd80ae84/googleapis_common_protos-1.74.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/3f/9859f655d11901e7b2996c6e3d33e0caa9a1d4572c3bc61ed0faa64b2f4c/greenlet-3.3.2-cp310-cp310-macosx_11_0_universal2.whl + - pypi: https://files.pythonhosted.org/packages/89/22/c2dd50c09bf679bd38173656cd4402d2511e563b33bc88f90009cf50613c/grpc_google_iam_v1-0.14.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c5/63/ee244c4b64f0e71cef5314f9fa1d120c072e33c2e4c545dc75bd1af2a5c5/grpcio-1.62.3-cp310-cp310-macosx_12_0_universal2.whl + - pypi: https://files.pythonhosted.org/packages/40/4c/ee3173906196b741ac6ba55a9788ba9ebf2cd05f91715a49b6c3bfbb9d73/grpcio_health_checking-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/54/acc6a6e684827b0f6bb4e2c27f3d7e25b71322c4078ef5b455c07c43260e/grpcio_reflection-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/40/972271de05f9315c0d69f9f7ebbcadd83bc85322f538637d11bb8c67803d/grpcio_status-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b2/23/55d40e1bf54c141f541ab31b4b4b0f58610440c8837b1406f3467c2b4853/grpcio_testing-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/c8/8aaf447698c4d59aa853fd318eed300b5c9e44459f242ab8ead6c9c09792/gunicorn-25.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d8/70/3f39ebfb3824578c34400df3b037b268abb5af0abaa789b430ffd17dd74e/hiredis-2.4.0-cp310-cp310-macosx_10_15_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/e5/c07e0bcf4ec8db8164e9f6738c048b2e66aabf30e7506f440c4cc6953f60/httptools-0.7.1-cp310-cp310-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/3d/2d244233ac4f76e38533cfcb2991c9eb4c7bf688ae0a036d30725b8faafe/importlib_metadata-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/14/2f/967ba146e6d58cf6a652da73885f52fc68001525b4197effc174321d70b4/jmespath-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cd/58/4a1880ea64032185e9ae9f63940c9327c6952d5584ea544a8f66972f2fda/jwcrypto-1.5.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7c/5f/63f5fa395c7a8a93558c0904ba8f1c8d1b997ca6a3de61bc7659970d66bf/librt-0.8.1-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e8/4b/3541d44f3937ba468b75da9eebcae497dcf67adb65caa16760b0a6807ebb/markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b6/9e/8d9f6b9746f8ede78b0a4e4b8908e4d80bd609fca0b3e3195a07dda29534/minio-7.2.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cc/bf/5404c2fd6ac84819e8ff1b7e34437b37cf55a2b11318894909e7bb88de3f/mmh3-5.2.1-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/ef/04/9de3f8077852e3d438215c81e9b691244532d2e05b4270e89ce67b7d103c/multidict-6.7.1-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/4d/a2/a965c8c3fcd4fa8b84ba0d46606181b0d0a1d50f274c67877f3e9ed4882c/mypy-1.20.0-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/be/9c/92789c596b8df838baa98fa71844d84283302f7604ed565dafe5a6b5041a/oauthlib-3.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3d/f7/f425a00df4fcc22b292c6895c6831c0c8ae1d9fac1e024d16f98a9ce8749/pandas-2.3.3-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c2/51/72b7c3b25ecfc6810b29ae9bffe76e26a407adb20de5b90ed984b3d483ca/pandas_gbq-0.34.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a1/6b/db0d03d96726d995dc7171286c6ba9d8d14251f37433890f88368951a44e/propcache-0.4.1-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/84/f3/1fba73eeffafc998a25d59703b63f8be4fe8a5cb12eaff7386a0ba0f7125/proto_plus-1.27.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5c/01/a3c3ed5cd186f39e7880f8303cc51385a198a81469d53d0fdecf1f64d929/protobuf-6.33.6-cp39-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/18/f3/14a1370b1449ca875d5e353ef02cb9db6b70bd46ec361c236176837c0be1/psycopg-3.2.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d6/30/af3806081adc75b5a8addde839d4c6b171a8c5d0d07dd92de20ca4dd6717/psycopg_binary-3.2.5-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/e7/c3/26b8a0908a9db249de3b4169692e1c7c19048a9bc41a4d3209cee7dbb758/psycopg_pool-3.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/db/ea0203e495be491c85af87b66e37acfd3bf756fd985f87e46fc5e3bf022c/py4j-0.10.9.9-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bc/8e/4be5617b4aaae0287f621ad31c6036e5f63118cfca0dc57d42121ff49b51/pyarrow-23.0.1-cp310-cp310-macosx_12_0_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/5d/a0/7d793dce3fa811fe047d6ae2431c672364b462850c6235ae306c0efd025f/pyasn1-0.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/4e/a066527e079fc5002390c8acdd3aca431e6ea0a50ffd7201551175b47323/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c6/90/32c9941e728d564b411d574d8ee0cf09b12ec978cb22b294995bae5549a5/pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/ca/cb/cdeaba62aa3c48f0d8834afb82b4a21463cd83df34fe01f9daa89a08ec6c/pydata_google_auth-1.9.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/7a/8dd906bd22e79e47397a61742927f6747fe93242ef86645ee9092e610244/pyjwt-2.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7c/4c/ad33b92b9864cbde84f259d5df035a6447f91891f5be77788e2a3892bce3/pymysql-1.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/7d/d4f7d908fa8415571771b30669251d57c3cf313b36a856e6d7548ae01619/pyopenssl-26.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/bf/58ee13add151469c25825b7125bbf62c3bdcec05eec4d458fcb5c5516066/pyspark-4.1.1.tar.gz + - pypi: https://files.pythonhosted.org/packages/51/ff/f6e8b8f39e08547faece4bd80f89d5a8de68a38b2d179cc1c4490ffa3286/pytest-7.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/82/62e2d63639ecb0fbe8a7ee59ef0bc69a4669ec50f6d3459f74ad4e4189a2/pytest_asyncio-0.23.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/60/423a63fb190a0483d049786a121bd3dfd7d93bb5ff1bb5b5cd13e5df99a7/pytest_benchmark-3.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/25/b2/bdc663a5647ce2034f7e8420122af340df87c01ba97745fc753b8c917acb/pytest_env-1.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2d/a1/2f2c1c2353350d66c4d110d283e422e4943eb5ad10effa9357ba66f7b5b9/pytest_lazy_fixture-0.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/43/8deecb4c123bbc16d25666f1a6d241109c97aeb2e50806b952661c8e4b95/pytest_mock-1.10.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/98/adc368fe369465f291ab24e18b9900473786ed1afdf861ba90467eb0767e/pytest_ordering-0.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/df/97cc0b5b8b53da0e265acd0aeecfc0c279e950a029acd2d7b4e54b00b25f/pytest_timeout-1.4.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2e/2e/dfbd2c9b3edf6a5a8cd9e66090221046839b488ea27824970426bf06b242/python_keycloak-4.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/99/781fe0c827be2742bcc775efefccb3b048a3a9c6ce9aec0cbf4a101677e5/pytz-2026.1.post1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/20/2e/409703d645363352a20c944f5d119bdae3eb3034051a53724a7c5fee12b8/redis-4.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/8e/7540e8a2036f79a125c1d2ebadf69ed7901608859186c856fa0388ef4197/requests-2.33.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3b/5d/63d4ae3b9daea098d5d6f5da83984853c1bbacd5dc826764b249fe119d24/requests_oauthlib-2.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/06/0c/0c411a0ec64ccb6d104dcabe0e713e05e153a9a2c3c2bd2b32ce412166fe/rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/6d/4f/d073e09df851cfa251ef7840007d04db3293a0482ce607d2b993926089be/s3transfer-0.13.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9d/76/f789f7a86709c6b087c5a2f52f911838cad707cc613162401badc665acfe/setuptools-82.0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/01/b1/11c03e05bd2a2da590c1b77c8455f40eb505888a2683c4e41b487d79568c/snowflake_connector_python-4.4.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/2c/9664130905f03db57961b8980b05cab624afd114bf2be2576628a9f22da4/sqlalchemy-2.0.48-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0b/c9/584bc9651441b4ba60cc4d557d8a547b5aff901af35bda3a4ee30c819b82/starlette-1.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/3f/8ba87d9e287b9d385a02a7114ddcef61b26f86411e121c9003eb509a1773/tenacity-8.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/f8/6425ff800894784160290bcb9737878d910b6da6a08633bfe7f2ed8c9ae3/testcontainers-4.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b5/11/87d6d29fb5d237229d67973a6c9e06e048f01cf4994dee194ab0ea841814/tomlkit-0.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/fa/4f4d3bfca9ef6dd17d69ed18b96564c53b32d3ce774132308d0bee849f10/types_pymysql-1.1.0.20251220-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/1f/4e5f8770c2cf4faa2c3ed3c19f9d4485ac9db0a6b029a7866921709bdc6c/uvicorn_worker-0.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/ae/6f6f9af7f590b319c94532b9567409ba11f4fa71af1148cab1bf48a07048/uvloop-0.22.1-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/a7/1a/206e8cf2dd86fddf939165a57b4df61607a1e0add2785f170a3f616b7d9f/watchfiles-1.1.1-cp310-cp310-macosx_10_12_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/19/0f/22ef6107ee52ab7f0b710d55d36f5a5d3ef19e8a205541a6d7ffa7994e5a/websockets-16.0-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/45/69/f3c47642b79485a30a59c63f6d739ed779fb4cc8323205d047d741d55220/wrapt-1.17.3-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/7a/35/5a553687c5793df5429cd1db45909d4f3af7eee90014888c208d086a44f0/yarl-1.23.0-cp310-cp310-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl + - pypi: ./ + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.5-hf6b4638_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.52.0-h1ae2325_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.10.20-h1b19095_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - pypi: https://files.pythonhosted.org/packages/92/d9/25a697a959a7149c93efa4d849421aa5f22bcb82350ac89b4284b0b88aa8/aiobotocore-2.23.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6f/4d/926c183e06b09d5270a309eb50fbde7b09782bfd305dec1e800f329834fb/aiohttp-3.13.5-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/10/a1/510b0a7fadc6f43a6ce50152e69dbd86415240835868bb0bd9b5b88b1e06/aioitertools-0.13.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b6/02/d297943bcacf05e4f2a94ab6f462831dc20158614e5d067c35d4e63b9acb/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/c9/7f/09065fd9e27da0eda08b4d6897f1c13535066174cc023af248fc2a8d5e5a/asn1crypto-1.5.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/80/9f608d13b4b3afcebd1dd13baf9551c95fc424d6390e4b1cfd7b1810cd06/async_property-0.2.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fe/ba/e2081de779ca30d473f21f5b30e0e737c438205440784c7dfc81efc2b029/async_timeout-5.0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/e9/ed9f202cdf6bfa89ff09241a15a2b44a2d4a61cbe24119c2e391128562b1/bigtree-1.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/8b/b2361188bd1e293eede1bc165e2461d390394f71ec0c8c21211c8dabf62c/boto3-1.38.27-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/00/dd90b7a0255587ba1c9754d32a221adb4a9022f181df3eef401b0b9fadfc/botocore-1.38.46-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/84/ad6a0b408daa859246f57c03efd28e5dd1b33c21737c2db84cae8c237aa5/cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/26/08/0f303cb0b529e456bb116f2d50565a482694fbb94340bf56d44677e7ed03/charset_normalizer-3.4.7-cp310-cp310-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c4/cc/f330e982852403da79008552de9906804568ae9230da8432f7496ce02b71/cryptography-46.0.6-cp38-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/76/09/22793699ce02e5e58836f98cff1d2b872c94608446f772bd3a50065aa9fb/db_dtypes-1.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/02/c3/253a89ee03fc9b9682f1541728eb66db7db22148cd94f89ab22528cd1e1b/deprecation-2.1.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/84/a4/5caa2de7f917a04ada20018eccf60d6cc6145b0199d55ca3711b0fc08312/fastapi-0.135.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/70/26ca3f06aace16f2352796b08704338d74b6d1a24ca38f2771afbb7ed915/frozenlist-1.8.0-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/1d/a0/6aaea0c2fbea2f89bfd5db25fb1e3481896a423002ebe4e55288907a97a3/fsspec-2024.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/84/e1/ebd5100cbb202e561c0c8b59e485ef3bd63fa9beb610f3fdcaea443f0288/google_api_core-2.30.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/eb/c6c2478d8a8d633460be40e2a8a6f8f429171997a35a96f81d3b680dec83/google_auth-2.49.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2a/e0/cb454a95f460903e39f101e950038ec24a072ca69d0a294a6df625cc1627/google_auth_oauthlib-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/40/33/1d3902efadef9194566d499d61507e1f038454e0b55499d2d7f8ab2a4fee/google_cloud_bigquery-3.41.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/0e/2950d4d0160300f51c7397a080b1685d3e25b40badb2c96f03d58d0ee868/google_cloud_bigquery_storage-2.37.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d1/19/1cc695fa8489ef446a70ee9e983c12f4b47e0649005758035530eaec4b1c/google_cloud_bigtable-2.36.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/73/d9/5bb050cb32826466aa9b25f79e2ca2879fe66cb76782d4ed798dd7506151/google_cloud_core-2.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5b/88/357efc6b331fd29155dcb92a5dfb0030a8a6feddb7bbf8a6215defbed6c7/google_cloud_datastore-2.24.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d5/94/6db383d8ee1adf45dc6c73477152b82731fa4c4a46d9c1932cc8757e0fd4/google_cloud_storage-2.19.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/95/ac/6f7bc93886a823ab545948c2dd48143027b2355ad1944c7cf852b338dc91/google_crc32c-1.8.0-cp310-cp310-macosx_12_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/5e/f8/50bfaf4658431ff9de45c5c3935af7ab01157a4903c603cd0eee6e78e087/google_resumable_media-2.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b6/b0/be5d3329badb9230b765de6eea66b73abd5944bdeb5afb3562ddcd80ae84/googleapis_common_protos-1.74.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/89/22/c2dd50c09bf679bd38173656cd4402d2511e563b33bc88f90009cf50613c/grpc_google_iam_v1-0.14.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c5/63/ee244c4b64f0e71cef5314f9fa1d120c072e33c2e4c545dc75bd1af2a5c5/grpcio-1.62.3-cp310-cp310-macosx_12_0_universal2.whl + - pypi: https://files.pythonhosted.org/packages/40/4c/ee3173906196b741ac6ba55a9788ba9ebf2cd05f91715a49b6c3bfbb9d73/grpcio_health_checking-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/82/54/acc6a6e684827b0f6bb4e2c27f3d7e25b71322c4078ef5b455c07c43260e/grpcio_reflection-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/90/40/972271de05f9315c0d69f9f7ebbcadd83bc85322f538637d11bb8c67803d/grpcio_status-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b2/23/55d40e1bf54c141f541ab31b4b4b0f58610440c8837b1406f3467c2b4853/grpcio_testing-1.62.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/43/c8/8aaf447698c4d59aa853fd318eed300b5c9e44459f242ab8ead6c9c09792/gunicorn-25.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ed/b7/26a56a3b991abe7fcf7bcfa8e0a08de3c3766c6caecb1ba46239342792ff/hiredis-2.4.0-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7e/4f/35e3a63f863a659f92ffd92bef131f3e81cf849af26e6435b49bd9f6f751/httptools-0.7.1-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/3d/2d244233ac4f76e38533cfcb2991c9eb4c7bf688ae0a036d30725b8faafe/importlib_metadata-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/14/2f/967ba146e6d58cf6a652da73885f52fc68001525b4197effc174321d70b4/jmespath-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cd/58/4a1880ea64032185e9ae9f63940c9327c6952d5584ea544a8f66972f2fda/jwcrypto-1.5.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/e0/0472cf37267b5920eff2f292ccfaede1886288ce35b7f3203d8de00abfe6/librt-0.8.1-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/98/1b/fbd8eed11021cabd9226c37342fa6ca4e8a98d8188a8d9b66740494960e4/markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/b6/9e/8d9f6b9746f8ede78b0a4e4b8908e4d80bd609fca0b3e3195a07dda29534/minio-7.2.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/de/0b/52bffad0b52ae4ea53e222b594bd38c08ecac1fc410323220a7202e43da5/mmh3-5.2.1-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/31/5c/08c7f7fe311f32e83f7621cd3f99d805f45519cd06fafb247628b861da7d/multidict-6.7.1-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/53/6e/043477501deeb8eabbab7f1a2f6cac62cfb631806dc1d6862a04a7f5011b/mypy-1.20.0-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/be/9c/92789c596b8df838baa98fa71844d84283302f7604ed565dafe5a6b5041a/oauthlib-3.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/4f/66d99628ff8ce7857aca52fed8f0066ce209f96be2fede6cef9f84e8d04f/pandas-2.3.3-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/c2/51/72b7c3b25ecfc6810b29ae9bffe76e26a407adb20de5b90ed984b3d483ca/pandas_gbq-0.34.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e4/c3/82728404aea669e1600f304f2609cde9e665c18df5a11cdd57ed73c1dceb/propcache-0.4.1-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/84/f3/1fba73eeffafc998a25d59703b63f8be4fe8a5cb12eaff7386a0ba0f7125/proto_plus-1.27.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5c/01/a3c3ed5cd186f39e7880f8303cc51385a198a81469d53d0fdecf1f64d929/protobuf-6.33.6-cp39-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/18/f3/14a1370b1449ca875d5e353ef02cb9db6b70bd46ec361c236176837c0be1/psycopg-3.2.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/31/77/31968655db2efe83c519e6296ff3a85a0c9e50432e0c11c8ffae1b404870/psycopg_binary-3.2.5-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/e7/c3/26b8a0908a9db249de3b4169692e1c7c19048a9bc41a4d3209cee7dbb758/psycopg_pool-3.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bd/db/ea0203e495be491c85af87b66e37acfd3bf756fd985f87e46fc5e3bf022c/py4j-0.10.9.9-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bc/a8/24e5dc6855f50a62936ceb004e6e9645e4219a8065f304145d7fb8a79d5d/pyarrow-23.0.1-cp310-cp310-macosx_12_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/5d/a0/7d793dce3fa811fe047d6ae2431c672364b462850c6235ae306c0efd025f/pyasn1-0.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/6c/a1f71542c969912bb0e106f64f60a56cc1f0fabecf9396f45accbe63fa68/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/a8/61c96a77fe28993d9a6fb0f4127e05430a267b235a124545d79fea46dd65/pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/ca/cb/cdeaba62aa3c48f0d8834afb82b4a21463cd83df34fe01f9daa89a08ec6c/pydata_google_auth-1.9.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/7a/8dd906bd22e79e47397a61742927f6747fe93242ef86645ee9092e610244/pyjwt-2.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7c/4c/ad33b92b9864cbde84f259d5df035a6447f91891f5be77788e2a3892bce3/pymysql-1.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/7d/d4f7d908fa8415571771b30669251d57c3cf313b36a856e6d7548ae01619/pyopenssl-26.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/bf/58ee13add151469c25825b7125bbf62c3bdcec05eec4d458fcb5c5516066/pyspark-4.1.1.tar.gz + - pypi: https://files.pythonhosted.org/packages/51/ff/f6e8b8f39e08547faece4bd80f89d5a8de68a38b2d179cc1c4490ffa3286/pytest-7.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/82/62e2d63639ecb0fbe8a7ee59ef0bc69a4669ec50f6d3459f74ad4e4189a2/pytest_asyncio-0.23.8-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/60/423a63fb190a0483d049786a121bd3dfd7d93bb5ff1bb5b5cd13e5df99a7/pytest_benchmark-3.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/25/b2/bdc663a5647ce2034f7e8420122af340df87c01ba97745fc753b8c917acb/pytest_env-1.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2d/a1/2f2c1c2353350d66c4d110d283e422e4943eb5ad10effa9357ba66f7b5b9/pytest_lazy_fixture-0.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/43/8deecb4c123bbc16d25666f1a6d241109c97aeb2e50806b952661c8e4b95/pytest_mock-1.10.4-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/98/adc368fe369465f291ab24e18b9900473786ed1afdf861ba90467eb0767e/pytest_ordering-0.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/46/df/97cc0b5b8b53da0e265acd0aeecfc0c279e950a029acd2d7b4e54b00b25f/pytest_timeout-1.4.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2e/2e/dfbd2c9b3edf6a5a8cd9e66090221046839b488ea27824970426bf06b242/python_keycloak-4.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/10/99/781fe0c827be2742bcc775efefccb3b048a3a9c6ce9aec0cbf4a101677e5/pytz-2026.1.post1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/20/2e/409703d645363352a20c944f5d119bdae3eb3034051a53724a7c5fee12b8/redis-4.6.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d7/8e/7540e8a2036f79a125c1d2ebadf69ed7901608859186c856fa0388ef4197/requests-2.33.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3b/5d/63d4ae3b9daea098d5d6f5da83984853c1bbacd5dc826764b249fe119d24/requests_oauthlib-2.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/6a/4ba3d0fb7297ebae71171822554abe48d7cab29c28b8f9f2c04b79988c05/rpds_py-0.30.0-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/6d/4f/d073e09df851cfa251ef7840007d04db3293a0482ce607d2b993926089be/s3transfer-0.13.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9d/76/f789f7a86709c6b087c5a2f52f911838cad707cc613162401badc665acfe/setuptools-82.0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a7/31/0d6a1da486dc13263f43cdad0bbacdd041616c32220b9bcbff79160bdcc1/snowflake_connector_python-4.4.0-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9a/67/1235676e93dd3b742a4a8eddfae49eea46c85e3eed29f0da446a8dd57500/sqlalchemy-2.0.48-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/0b/c9/584bc9651441b4ba60cc4d557d8a547b5aff901af35bda3a4ee30c819b82/starlette-1.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/3f/8ba87d9e287b9d385a02a7114ddcef61b26f86411e121c9003eb509a1773/tenacity-8.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/f8/6425ff800894784160290bcb9737878d910b6da6a08633bfe7f2ed8c9ae3/testcontainers-4.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b5/11/87d6d29fb5d237229d67973a6c9e06e048f01cf4994dee194ab0ea841814/tomlkit-0.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/fa/4f4d3bfca9ef6dd17d69ed18b96564c53b32d3ce774132308d0bee849f10/types_pymysql-1.1.0.20251220-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/1f/4e5f8770c2cf4faa2c3ed3c19f9d4485ac9db0a6b029a7866921709bdc6c/uvicorn_worker-0.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/eb/14/ecceb239b65adaaf7fde510aa8bd534075695d1e5f8dadfa32b5723d9cfb/uvloop-0.22.1-cp310-cp310-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/b3/0f/abaf5262b9c496b5dad4ed3c0e799cbecb1f8ea512ecb6ddd46646a9fca3/watchfiles-1.1.1-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/10/40/904a4cb30d9b61c0e278899bf36342e9b0208eb3c470324a9ecbaac2a30f/websockets-16.0-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/d1/71/e7e7f5670c1eafd9e990438e69d8fb46fa91a50785332e06b560c869454f/wrapt-1.17.3-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/68/2e/c5a2234238f8ce37a8312b52801ee74117f576b1539eec8404a480434acc/yarl-1.23.0-cp310-cp310-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl + - pypi: ./ +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + build_number: 20 + sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 + md5: a9f577daf3de00bca7c3c76c0ecbd1de + depends: + - __glibc >=2.17,<3.0.a0 + - libgomp >=7.5.0 + constrains: + - openmp_impl <0.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 28948 + timestamp: 1770939786096 +- pypi: https://files.pythonhosted.org/packages/92/d9/25a697a959a7149c93efa4d849421aa5f22bcb82350ac89b4284b0b88aa8/aiobotocore-2.23.1-py3-none-any.whl + name: aiobotocore + version: 2.23.1 + sha256: d81c54d2eae2406ea9a473fea518fed580cf37bc4fc51ce43ba81546e5305114 + requires_dist: + - aiohttp>=3.9.2,<4.0.0 + - aioitertools>=0.5.1,<1.0.0 + - botocore>=1.38.40,<1.38.47 + - python-dateutil>=2.1,<3.0.0 + - jmespath>=0.7.1,<2.0.0 + - multidict>=6.0.0,<7.0.0 + - wrapt>=1.10.10,<2.0.0 + - awscli>=1.40.39,<1.40.46 ; extra == 'awscli' + - boto3>=1.38.40,<1.38.47 ; extra == 'boto3' + - httpx>=0.25.1,<0.29 ; extra == 'httpx' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl + name: aiohappyeyeballs + version: 2.6.1 + sha256: f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/05/98/afd308e35b9d3d8c9ec54c0918f1d722c86dc17ddfec272fcdbcce5a3124/aiohttp-3.13.5-cp310-cp310-macosx_10_9_x86_64.whl + name: aiohttp + version: 3.13.5 + sha256: bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5 + requires_dist: + - aiohappyeyeballs>=2.5.0 + - aiosignal>=1.4.0 + - async-timeout>=4.0,<6.0 ; python_full_version < '3.11' + - attrs>=17.3.0 + - frozenlist>=1.1.1 + - multidict>=4.5,<7.0 + - propcache>=0.2.0 + - yarl>=1.17.0,<2.0 + - aiodns>=3.3.0 ; extra == 'speedups' + - brotli>=1.2 ; platform_python_implementation == 'CPython' and extra == 'speedups' + - brotlicffi>=1.2 ; platform_python_implementation != 'CPython' and extra == 'speedups' + - backports-zstd ; python_full_version < '3.14' and platform_python_implementation == 'CPython' and extra == 'speedups' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/2f/86/a6f3ff1fd795f49545a7c74b2c92f62729135d73e7e4055bf74da5a26c82/aiohttp-3.13.5-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: aiohttp + version: 3.13.5 + sha256: bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95 + requires_dist: + - aiohappyeyeballs>=2.5.0 + - aiosignal>=1.4.0 + - async-timeout>=4.0,<6.0 ; python_full_version < '3.11' + - attrs>=17.3.0 + - frozenlist>=1.1.1 + - multidict>=4.5,<7.0 + - propcache>=0.2.0 + - yarl>=1.17.0,<2.0 + - aiodns>=3.3.0 ; extra == 'speedups' + - brotli>=1.2 ; platform_python_implementation == 'CPython' and extra == 'speedups' + - brotlicffi>=1.2 ; platform_python_implementation != 'CPython' and extra == 'speedups' + - backports-zstd ; python_full_version < '3.14' and platform_python_implementation == 'CPython' and extra == 'speedups' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/6f/4d/926c183e06b09d5270a309eb50fbde7b09782bfd305dec1e800f329834fb/aiohttp-3.13.5-cp310-cp310-macosx_11_0_arm64.whl + name: aiohttp + version: 3.13.5 + sha256: 8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670 + requires_dist: + - aiohappyeyeballs>=2.5.0 + - aiosignal>=1.4.0 + - async-timeout>=4.0,<6.0 ; python_full_version < '3.11' + - attrs>=17.3.0 + - frozenlist>=1.1.1 + - multidict>=4.5,<7.0 + - propcache>=0.2.0 + - yarl>=1.17.0,<2.0 + - aiodns>=3.3.0 ; extra == 'speedups' + - brotli>=1.2 ; platform_python_implementation == 'CPython' and extra == 'speedups' + - brotlicffi>=1.2 ; platform_python_implementation != 'CPython' and extra == 'speedups' + - backports-zstd ; python_full_version < '3.14' and platform_python_implementation == 'CPython' and extra == 'speedups' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/10/a1/510b0a7fadc6f43a6ce50152e69dbd86415240835868bb0bd9b5b88b1e06/aioitertools-0.13.0-py3-none-any.whl + name: aioitertools + version: 0.13.0 + sha256: 0be0292b856f08dfac90e31f4739432f4cb6d7520ab9eb73e143f4f2fa5259be + requires_dist: + - typing-extensions>=4.0 ; python_full_version < '3.10' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl + name: aiosignal + version: 1.4.0 + sha256: 053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e + requires_dist: + - frozenlist>=1.1.0 + - typing-extensions>=4.2 ; python_full_version < '3.13' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl + name: annotated-doc + version: 0.0.4 + sha256: 571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl + name: annotated-types + version: 0.7.0 + sha256: 1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 + requires_dist: + - typing-extensions>=4.0.0 ; python_full_version < '3.9' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl + name: anyio + version: 4.13.0 + sha256: 08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708 + requires_dist: + - exceptiongroup>=1.0.2 ; python_full_version < '3.11' + - idna>=2.8 + - typing-extensions>=4.5 ; python_full_version < '3.13' + - trio>=0.32.0 ; extra == 'trio' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl + name: argon2-cffi + version: 25.1.0 + sha256: fdc8b074db390fccb6eb4a3604ae7231f219aa669a2652e0f20e16ba513d5741 + requires_dist: + - argon2-cffi-bindings + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/09/52/94108adfdd6e2ddf58be64f959a0b9c7d4ef2fa71086c38356d22dc501ea/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl + name: argon2-cffi-bindings + version: 25.1.0 + sha256: d3e924cfc503018a714f94a49a149fdc0b644eaead5d1f089330399134fa028a + requires_dist: + - cffi>=1.0.1 ; python_full_version < '3.14' + - cffi>=2.0.0b1 ; python_full_version >= '3.14' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/0a/08/a9bebdb2e0e602dde230bdde8021b29f71f7841bd54801bcfd514acb5dcf/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl + name: argon2-cffi-bindings + version: 25.1.0 + sha256: 2630b6240b495dfab90aebe159ff784d08ea999aa4b0d17efa734055a07d2f44 + requires_dist: + - cffi>=1.0.1 ; python_full_version < '3.14' + - cffi>=2.0.0b1 ; python_full_version >= '3.14' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/b6/02/d297943bcacf05e4f2a94ab6f462831dc20158614e5d067c35d4e63b9acb/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl + name: argon2-cffi-bindings + version: 25.1.0 + sha256: 7aef0c91e2c0fbca6fc68e7555aa60ef7008a739cbe045541e438373bc54d2b0 + requires_dist: + - cffi>=1.0.1 ; python_full_version < '3.14' + - cffi>=2.0.0b1 ; python_full_version >= '3.14' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/c9/7f/09065fd9e27da0eda08b4d6897f1c13535066174cc023af248fc2a8d5e5a/asn1crypto-1.5.1-py2.py3-none-any.whl + name: asn1crypto + version: 1.5.1 + sha256: db4e40728b728508912cbb3d44f19ce188f218e9eba635821bb4b68564f8fd67 +- pypi: https://files.pythonhosted.org/packages/c7/80/9f608d13b4b3afcebd1dd13baf9551c95fc424d6390e4b1cfd7b1810cd06/async_property-0.2.2-py2.py3-none-any.whl + name: async-property + version: 0.2.2 + sha256: 8924d792b5843994537f8ed411165700b27b2bd966cefc4daeefc1253442a9d7 +- pypi: https://files.pythonhosted.org/packages/fe/ba/e2081de779ca30d473f21f5b30e0e737c438205440784c7dfc81efc2b029/async_timeout-5.0.1-py3-none-any.whl + name: async-timeout + version: 5.0.1 + sha256: 39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/96/c0/271f3e1e3502a8decb8ee5c680dbed2d8dc2cd504f5e20f7ed491d5f37e1/atpublic-7.0.0-py3-none-any.whl + name: atpublic + version: 7.0.0 + sha256: 6702bd9e7245eb4e8220a3e222afcef7f87412154732271ee7deee4433b72b4b + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl + name: attrs + version: 26.1.0 + sha256: c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/43/e9/ed9f202cdf6bfa89ff09241a15a2b44a2d4a61cbe24119c2e391128562b1/bigtree-1.4.0-py3-none-any.whl + name: bigtree + version: 1.4.0 + sha256: d0d99550ae64ce4529f132602ab875c2ab472c96c942f5704f8c72a17450d3ea + requires_dist: + - lark ; extra == 'all' + - matplotlib ; extra == 'all' + - pandas ; extra == 'all' + - pillow ; extra == 'all' + - polars ; extra == 'all' + - pydot ; extra == 'all' + - pyvis ; extra == 'all' + - rich ; extra == 'all' + - pillow ; extra == 'image' + - pydot ; extra == 'image' + - matplotlib ; extra == 'matplotlib' + - pandas ; extra == 'pandas' + - polars ; extra == 'polars' + - lark ; extra == 'query' + - rich ; extra == 'rich' + - pyvis ; extra == 'vis' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/43/8b/b2361188bd1e293eede1bc165e2461d390394f71ec0c8c21211c8dabf62c/boto3-1.38.27-py3-none-any.whl + name: boto3 + version: 1.38.27 + sha256: 95f5fe688795303a8a15e8b7e7f255cadab35eae459d00cc281a4fd77252ea80 + requires_dist: + - botocore>=1.38.27,<1.39.0 + - jmespath>=0.7.1,<2.0.0 + - s3transfer>=0.13.0,<0.14.0 + - botocore[crt]>=1.21.0,<2.0a0 ; extra == 'crt' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/a4/00/dd90b7a0255587ba1c9754d32a221adb4a9022f181df3eef401b0b9fadfc/botocore-1.38.46-py3-none-any.whl + name: botocore + version: 1.38.46 + sha256: 89ca782ffbf2e8769ca9c89234cfa5ca577f1987d07d913ee3c68c4776b1eb5b + requires_dist: + - jmespath>=0.7.1,<2.0.0 + - python-dateutil>=2.1,<3.0.0 + - urllib3>=1.25.4,<1.27 ; python_full_version < '3.10' + - urllib3>=1.25.4,!=2.2.0,<3 ; python_full_version >= '3.10' + - awscrt==0.23.8 ; extra == 'crt' + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + sha256: 0b75d45f0bba3e95dc693336fa51f40ea28c980131fec438afb7ce6118ed05f6 + md5: d2ffd7602c02f2b316fd921d39876885 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: bzip2-1.0.6 + license_family: BSD + purls: [] + size: 260182 + timestamp: 1771350215188 +- conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h500dc9f_9.conda + sha256: 9f242f13537ef1ce195f93f0cc162965d6cc79da578568d6d8e50f70dd025c42 + md5: 4173ac3b19ec0a4f400b4f782910368b + depends: + - __osx >=10.13 + license: bzip2-1.0.6 + license_family: BSD + purls: [] + size: 133427 + timestamp: 1771350680709 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-hd037594_9.conda + sha256: 540fe54be35fac0c17feefbdc3e29725cce05d7367ffedfaaa1bdda234b019df + md5: 620b85a3f45526a8bc4d23fd78fc22f0 + depends: + - __osx >=11.0 + license: bzip2-1.0.6 + license_family: BSD + purls: [] + size: 124834 + timestamp: 1771350416561 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + sha256: 67cc7101b36421c5913a1687ef1b99f85b5d6868da3abbf6ec1a4181e79782fc + md5: 4492fd26db29495f0ba23f146cd5638d + depends: + - __unix + license: ISC + purls: [] + size: 147413 + timestamp: 1772006283803 +- pypi: https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl + name: certifi + version: 2026.2.25 + sha256: 027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/93/d7/516d984057745a6cd96575eea814fe1edd6646ee6efd552fb7b0921dec83/cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl + name: cffi + version: 2.0.0 + sha256: 0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44 + requires_dist: + - pycparser ; implementation_name != 'PyPy' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/98/29/9b366e70e243eb3d14a5cb488dfd3a0b6b2f1fb001a203f653b93ccfac88/cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + name: cffi + version: 2.0.0 + sha256: fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453 + requires_dist: + - pycparser ; implementation_name != 'PyPy' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/9e/84/ad6a0b408daa859246f57c03efd28e5dd1b33c21737c2db84cae8c237aa5/cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl + name: cffi + version: 2.0.0 + sha256: f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49 + requires_dist: + - pycparser ; implementation_name != 'PyPy' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/20/e7/bed0024a0f4ab0c8a9c64d4445f39b30c99bd1acd228291959e3de664247/charset_normalizer-3.4.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: charset-normalizer + version: 3.4.7 + sha256: cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393 + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/26/08/0f303cb0b529e456bb116f2d50565a482694fbb94340bf56d44677e7ed03/charset_normalizer-3.4.7-cp310-cp310-macosx_10_9_universal2.whl + name: charset-normalizer + version: 3.4.7 + sha256: cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/47/5c/032c2d5a07fe4d4855fea851209cca2b6f03ebeb6d4e3afdb3358386a684/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: charset-normalizer + version: 3.4.7 + sha256: bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/97/c8/c67cb8c70e19ef1960b97b22ed2a1567711de46c4ddf19799923adc836c2/charset_normalizer-3.4.7-cp314-cp314-macosx_10_15_universal2.whl + name: charset-normalizer + version: 3.4.7 + sha256: c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0 + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl + name: click + version: 8.3.1 + sha256: 981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6 + requires_dist: + - colorama ; sys_platform == 'win32' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl + name: cloudpickle + version: 3.1.2 + sha256: 9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl + name: colorama + version: 0.4.6 + sha256: 4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*' +- pypi: https://files.pythonhosted.org/packages/c4/cc/f330e982852403da79008552de9906804568ae9230da8432f7496ce02b71/cryptography-46.0.6-cp38-abi3-macosx_10_9_universal2.whl + name: cryptography + version: 46.0.6 + sha256: 12cae594e9473bca1a7aceb90536060643128bb274fcea0fc459ab90f7d1ae7a + requires_dist: + - cffi>=1.14 ; python_full_version == '3.8.*' and platform_python_implementation != 'PyPy' + - cffi>=2.0.0 ; python_full_version >= '3.9' and platform_python_implementation != 'PyPy' + - typing-extensions>=4.13.2 ; python_full_version < '3.11' + - bcrypt>=3.1.5 ; extra == 'ssh' + - nox[uv]>=2024.4.15 ; extra == 'nox' + - cryptography-vectors==46.0.6 ; extra == 'test' + - pytest>=7.4.0 ; extra == 'test' + - pytest-benchmark>=4.0 ; extra == 'test' + - pytest-cov>=2.10.1 ; extra == 'test' + - pytest-xdist>=3.5.0 ; extra == 'test' + - pretend>=0.7 ; extra == 'test' + - certifi>=2024 ; extra == 'test' + - pytest-randomly ; extra == 'test-randomorder' + - sphinx>=5.3.0 ; extra == 'docs' + - sphinx-rtd-theme>=3.0.0 ; extra == 'docs' + - sphinx-inline-tabs ; extra == 'docs' + - pyenchant>=3 ; extra == 'docstest' + - readme-renderer>=30.0 ; extra == 'docstest' + - sphinxcontrib-spelling>=7.3.1 ; extra == 'docstest' + - build>=1.0.0 ; extra == 'sdist' + - ruff>=0.11.11 ; extra == 'pep8test' + - mypy>=1.14 ; extra == 'pep8test' + - check-sdist ; extra == 'pep8test' + - click>=8.0.1 ; extra == 'pep8test' + requires_python: '>=3.8,!=3.9.0,!=3.9.1' +- pypi: https://files.pythonhosted.org/packages/ff/8a/b14f3101fe9c3592603339eb5d94046c3ce5f7fc76d6512a2d40efd9724e/cryptography-46.0.6-cp38-abi3-manylinux_2_28_x86_64.whl + name: cryptography + version: 46.0.6 + sha256: 063b67749f338ca9c5a0b7fe438a52c25f9526b851e24e6c9310e7195aad3b4d + requires_dist: + - cffi>=1.14 ; python_full_version == '3.8.*' and platform_python_implementation != 'PyPy' + - cffi>=2.0.0 ; python_full_version >= '3.9' and platform_python_implementation != 'PyPy' + - typing-extensions>=4.13.2 ; python_full_version < '3.11' + - bcrypt>=3.1.5 ; extra == 'ssh' + - nox[uv]>=2024.4.15 ; extra == 'nox' + - cryptography-vectors==46.0.6 ; extra == 'test' + - pytest>=7.4.0 ; extra == 'test' + - pytest-benchmark>=4.0 ; extra == 'test' + - pytest-cov>=2.10.1 ; extra == 'test' + - pytest-xdist>=3.5.0 ; extra == 'test' + - pretend>=0.7 ; extra == 'test' + - certifi>=2024 ; extra == 'test' + - pytest-randomly ; extra == 'test-randomorder' + - sphinx>=5.3.0 ; extra == 'docs' + - sphinx-rtd-theme>=3.0.0 ; extra == 'docs' + - sphinx-inline-tabs ; extra == 'docs' + - pyenchant>=3 ; extra == 'docstest' + - readme-renderer>=30.0 ; extra == 'docstest' + - sphinxcontrib-spelling>=7.3.1 ; extra == 'docstest' + - build>=1.0.0 ; extra == 'sdist' + - ruff>=0.11.11 ; extra == 'pep8test' + - mypy>=1.14 ; extra == 'pep8test' + - check-sdist ; extra == 'pep8test' + - click>=8.0.1 ; extra == 'pep8test' + requires_python: '>=3.8,!=3.9.0,!=3.9.1' +- pypi: https://files.pythonhosted.org/packages/4a/f3/00bb1e867fba351e2d784170955713bee200c43ea306c59f30bd7e748192/dask-2026.3.0-py3-none-any.whl + name: dask + version: 2026.3.0 + sha256: be614b9242b0b38288060fb2d7696125946469c98a1c30e174883fd199e0428d + requires_dist: + - click>=8.1 + - cloudpickle>=3.0.0 + - fsspec>=2021.9.0 + - packaging>=20.0 + - partd>=1.4.0 + - pyyaml>=5.3.1 + - toolz>=0.12.0 + - importlib-metadata>=4.13.0 ; python_full_version < '3.12' + - numpy>=1.24 ; extra == 'array' + - dask[array] ; extra == 'dataframe' + - pandas>=2.0 ; extra == 'dataframe' + - pyarrow>=16.0 ; extra == 'dataframe' + - distributed>=2026.3.0,<2026.3.1 ; extra == 'distributed' + - bokeh>=3.1.0 ; extra == 'diagnostics' + - jinja2>=2.10.3 ; extra == 'diagnostics' + - dask[array,dataframe,diagnostics,distributed] ; extra == 'complete' + - pyarrow>=16.0 ; extra == 'complete' + - lz4>=4.3.2 ; extra == 'complete' + - pandas[test] ; extra == 'test' + - pytest ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-mock ; extra == 'test' + - pytest-rerunfailures ; extra == 'test' + - pytest-timeout ; extra == 'test' + - pytest-xdist ; extra == 'test' + - pre-commit ; extra == 'test' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/76/09/22793699ce02e5e58836f98cff1d2b872c94608446f772bd3a50065aa9fb/db_dtypes-1.5.1-py3-none-any.whl + name: db-dtypes + version: 1.5.1 + sha256: ad71a6645e3c1f06d4d32023940576648f43119822f825f0d22587c6ef8afe15 + requires_dist: + - numpy>=1.24.0,<=2.2.6 ; python_full_version == '3.10.*' + - numpy>=1.24.0 ; python_full_version != '3.10.*' + - packaging>=24.2.0 + - pandas>=1.5.3,<3.0.0 + - pyarrow>=13.0.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/6e/24/e6b7a8fe8b9e336d684779a88027b261374417f2be7c5a0fcdb40f0c8cc5/deltalake-0.25.5-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: deltalake + version: 0.25.5 + sha256: 0b36afba5936f74c42920c06d140535e6efc8361f659770014944d8e69fbca09 + requires_dist: + - pyarrow>=16,!=19.0.0 + - pandas ; extra == 'pandas' + - azure-storage-blob==12.20.0 ; extra == 'devel' + - packaging>=20 ; extra == 'devel' + - pytest ; extra == 'devel' + - pytest-mock ; extra == 'devel' + - pytest-cov ; extra == 'devel' + - pytest-timeout ; extra == 'devel' + - sphinx<=4.5 ; extra == 'devel' + - sphinx-rtd-theme ; extra == 'devel' + - toml ; extra == 'devel' + - wheel ; extra == 'devel' + - pip>=24.0 ; extra == 'devel' + - pytest-benchmark ; extra == 'devel' + - mypy==1.10.1 ; extra == 'devel' + - ruff==0.5.2 ; extra == 'devel' + - polars==1.17.1 ; extra == 'polars' + - lakefs==0.8.0 ; extra == 'lakefs' + - pyspark ; extra == 'pyspark' + - delta-spark ; extra == 'pyspark' + - numpy==1.26.4 ; extra == 'pyspark' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/74/7a/ec22ff9d5c891b4f9ae834ef70524c92bd59d1408e9944e2652c87bc3f02/deltalake-0.25.5-cp39-abi3-macosx_11_0_arm64.whl + name: deltalake + version: 0.25.5 + sha256: e8f0d24bf64455f702da8402307b22e01f91e0f76694f7c5e33c9513011e8d29 + requires_dist: + - pyarrow>=16,!=19.0.0 + - pandas ; extra == 'pandas' + - azure-storage-blob==12.20.0 ; extra == 'devel' + - packaging>=20 ; extra == 'devel' + - pytest ; extra == 'devel' + - pytest-mock ; extra == 'devel' + - pytest-cov ; extra == 'devel' + - pytest-timeout ; extra == 'devel' + - sphinx<=4.5 ; extra == 'devel' + - sphinx-rtd-theme ; extra == 'devel' + - toml ; extra == 'devel' + - wheel ; extra == 'devel' + - pip>=24.0 ; extra == 'devel' + - pytest-benchmark ; extra == 'devel' + - mypy==1.10.1 ; extra == 'devel' + - ruff==0.5.2 ; extra == 'devel' + - polars==1.17.1 ; extra == 'polars' + - lakefs==0.8.0 ; extra == 'lakefs' + - pyspark ; extra == 'pyspark' + - delta-spark ; extra == 'pyspark' + - numpy==1.26.4 ; extra == 'pyspark' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/dc/0e/f372bb290cef68c67331cd649b94d62220183ddc1b5bf3a9351ea6e9c8ec/deltalake-0.25.5-cp39-abi3-macosx_10_12_x86_64.whl + name: deltalake + version: 0.25.5 + sha256: 76be7e1ed8d13f2dc933361057a44a47a89e6112d4f5ea0a73fb510bedd96efc + requires_dist: + - pyarrow>=16,!=19.0.0 + - pandas ; extra == 'pandas' + - azure-storage-blob==12.20.0 ; extra == 'devel' + - packaging>=20 ; extra == 'devel' + - pytest ; extra == 'devel' + - pytest-mock ; extra == 'devel' + - pytest-cov ; extra == 'devel' + - pytest-timeout ; extra == 'devel' + - sphinx<=4.5 ; extra == 'devel' + - sphinx-rtd-theme ; extra == 'devel' + - toml ; extra == 'devel' + - wheel ; extra == 'devel' + - pip>=24.0 ; extra == 'devel' + - pytest-benchmark ; extra == 'devel' + - mypy==1.10.1 ; extra == 'devel' + - ruff==0.5.2 ; extra == 'devel' + - polars==1.17.1 ; extra == 'polars' + - lakefs==0.8.0 ; extra == 'lakefs' + - pyspark ; extra == 'pyspark' + - delta-spark ; extra == 'pyspark' + - numpy==1.26.4 ; extra == 'pyspark' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/02/c3/253a89ee03fc9b9682f1541728eb66db7db22148cd94f89ab22528cd1e1b/deprecation-2.1.0-py2.py3-none-any.whl + name: deprecation + version: 2.1.0 + sha256: a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a + requires_dist: + - packaging +- pypi: https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl + name: dill + version: 0.3.9 + sha256: 468dff3b89520b474c0397703366b7b95eebe6303f108adf9b19da1f702be87a + requires_dist: + - objgraph>=1.7.2 ; extra == 'graph' + - gprof2dot>=2022.7.29 ; extra == 'profile' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl + name: docker + version: 7.1.0 + sha256: c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0 + requires_dist: + - pywin32>=304 ; sys_platform == 'win32' + - requests>=2.26.0 + - urllib3>=1.26.0 + - coverage==7.2.7 ; extra == 'dev' + - pytest-cov==4.1.0 ; extra == 'dev' + - pytest-timeout==2.1.0 ; extra == 'dev' + - pytest==7.4.2 ; extra == 'dev' + - ruff==0.1.8 ; extra == 'dev' + - myst-parser==0.18.0 ; extra == 'docs' + - sphinx==5.1.1 ; extra == 'docs' + - paramiko>=2.4.3 ; extra == 'ssh' + - websocket-client>=1.3.0 ; extra == 'websockets' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/3a/09/4c4dd94f521d016e0fb83cca2c203d10ce1e3f8bcc679691b5271fc98b83/duckdb-1.5.1-cp310-cp310-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl + name: duckdb + version: 1.5.1 + sha256: 715f05ea198d20d7f8b407b9b84e0023d17f2b9096c194cea702b7840e74f1f7 + requires_dist: + - ipython ; extra == 'all' + - fsspec ; extra == 'all' + - numpy ; extra == 'all' + - pandas ; extra == 'all' + - pyarrow ; extra == 'all' + - adbc-driver-manager ; extra == 'all' + requires_python: '>=3.10.0' +- pypi: https://files.pythonhosted.org/packages/85/b1/88a457cd3105525cba0d4c155f847c5c32fa4f543d3ba4ee38b4fd75f82e/duckdb-1.5.1-cp310-cp310-macosx_11_0_arm64.whl + name: duckdb + version: 1.5.1 + sha256: 8c0088765747ae5d6c9f89987bb36f9fb83564f07090d721344ce8e1abedffea + requires_dist: + - ipython ; extra == 'all' + - fsspec ; extra == 'all' + - numpy ; extra == 'all' + - pandas ; extra == 'all' + - pyarrow ; extra == 'all' + - adbc-driver-manager ; extra == 'all' + requires_python: '>=3.10.0' +- pypi: https://files.pythonhosted.org/packages/ba/b8/22e6c605d9281df7a83653f4a60168eec0f650b23f1d4648aca940d79d00/duckdb-1.5.1-cp310-cp310-macosx_10_9_x86_64.whl + name: duckdb + version: 1.5.1 + sha256: caa65e1f5bf007430bf657c37cab7ab81a4ddf8d337e3062bcc5085d17ef038b + requires_dist: + - ipython ; extra == 'all' + - fsspec ; extra == 'all' + - numpy ; extra == 'all' + - pandas ; extra == 'all' + - pyarrow ; extra == 'all' + - adbc-driver-manager ; extra == 'all' + requires_python: '>=3.10.0' +- pypi: https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl + name: exceptiongroup + version: 1.3.1 + sha256: a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598 + requires_dist: + - typing-extensions>=4.6.0 ; python_full_version < '3.13' + - pytest>=6 ; extra == 'test' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl + name: execnet + version: 2.1.2 + sha256: 67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec + requires_dist: + - hatch ; extra == 'testing' + - pre-commit ; extra == 'testing' + - pytest ; extra == 'testing' + - tox ; extra == 'testing' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/84/a4/5caa2de7f917a04ada20018eccf60d6cc6145b0199d55ca3711b0fc08312/fastapi-0.135.3-py3-none-any.whl + name: fastapi + version: 0.135.3 + sha256: 9b0f590c813acd13d0ab43dd8494138eb58e484bfac405db1f3187cfc5810d98 + requires_dist: + - starlette>=0.46.0 + - pydantic>=2.9.0 + - typing-extensions>=4.8.0 + - typing-inspection>=0.4.2 + - annotated-doc>=0.0.2 + - fastapi-cli[standard]>=0.0.8 ; extra == 'standard' + - httpx>=0.23.0,<1.0.0 ; extra == 'standard' + - jinja2>=3.1.5 ; extra == 'standard' + - python-multipart>=0.0.18 ; extra == 'standard' + - email-validator>=2.0.0 ; extra == 'standard' + - uvicorn[standard]>=0.12.0 ; extra == 'standard' + - pydantic-settings>=2.0.0 ; extra == 'standard' + - pydantic-extra-types>=2.0.0 ; extra == 'standard' + - fastapi-cli[standard-no-fastapi-cloud-cli]>=0.0.8 ; extra == 'standard-no-fastapi-cloud-cli' + - httpx>=0.23.0,<1.0.0 ; extra == 'standard-no-fastapi-cloud-cli' + - jinja2>=3.1.5 ; extra == 'standard-no-fastapi-cloud-cli' + - python-multipart>=0.0.18 ; extra == 'standard-no-fastapi-cloud-cli' + - email-validator>=2.0.0 ; extra == 'standard-no-fastapi-cloud-cli' + - uvicorn[standard]>=0.12.0 ; extra == 'standard-no-fastapi-cloud-cli' + - pydantic-settings>=2.0.0 ; extra == 'standard-no-fastapi-cloud-cli' + - pydantic-extra-types>=2.0.0 ; extra == 'standard-no-fastapi-cloud-cli' + - fastapi-cli[standard]>=0.0.8 ; extra == 'all' + - httpx>=0.23.0,<1.0.0 ; extra == 'all' + - jinja2>=3.1.5 ; extra == 'all' + - python-multipart>=0.0.18 ; extra == 'all' + - itsdangerous>=1.1.0 ; extra == 'all' + - pyyaml>=5.3.1 ; extra == 'all' + - email-validator>=2.0.0 ; extra == 'all' + - uvicorn[standard]>=0.12.0 ; extra == 'all' + - pydantic-settings>=2.0.0 ; extra == 'all' + - pydantic-extra-types>=2.0.0 ; extra == 'all' + requires_python: '>=3.10' +- pypi: ./ + name: feast + version: 0.60.1.dev87+ge33047ba1 + sha256: d7bc70f699b91a11b2fe3f88eb56144eca2156776247d94c40f658ab39caa4a8 + requires_dist: + - click>=7.0.0,<9.0.0 + - colorama>=0.3.9,<1 + - dill~=0.3.0 + - protobuf>=4.24.0 + - jinja2>=2,<4 + - jsonschema + - mmh3 + - numpy>=2.0.0,<3 + - pandas>=1.4.3,<3 + - pyarrow>=21.0.0 + - pydantic>=2.10.6 + - pygments>=2.12.0,<3 + - pyyaml>=5.4.0,<7 + - requests + - sqlalchemy[mypy]>1 + - tabulate>=0.8.0,<1 + - tenacity>=7,<9 + - toml>=0.10.0,<1 + - tqdm>=4,<5 + - typeguard>=4.0.0 + - fastapi>=0.68.0 + - uvicorn[standard]>=0.30.6,<=0.34.0 + - uvicorn-worker + - gunicorn ; sys_platform != 'win32' + - dask[dataframe]>=2024.2.1 + - prometheus-client + - psutil + - bigtree>=0.19.2 + - pyjwt + - boto3==1.38.27 ; extra == 'aws' + - fsspec<=2024.9.0 ; extra == 'aws' + - aiobotocore>2,<3 ; extra == 'aws' + - azure-storage-blob>=0.37.0 ; extra == 'azure' + - azure-identity>=1.6.1 ; extra == 'azure' + - sqlalchemy>=1.4.19 ; extra == 'azure' + - pyodbc>=4.0.30 ; extra == 'azure' + - pymssql<2.3.3 ; extra == 'azure' + - cassandra-driver>=3.24.0,<4 ; extra == 'cassandra' + - clickhouse-connect>=0.7.19 ; extra == 'clickhouse' + - couchbase==4.3.2 ; extra == 'couchbase' + - couchbase-columnar==1.0.0 ; extra == 'couchbase' + - deltalake<1.0.0 ; extra == 'delta' + - docling==2.27.0 ; extra == 'docling' + - ibis-framework[duckdb]>=10.0.0 ; extra == 'duckdb' + - elasticsearch>=8.13.0 ; extra == 'elasticsearch' + - faiss-cpu>=1.7.0,<=1.10.0 ; extra == 'faiss' + - google-api-core>=1.23.0,<3 ; extra == 'gcp' + - googleapis-common-protos>=1.52.0,<2 ; extra == 'gcp' + - google-cloud-bigquery[pandas]>=2,<4 ; extra == 'gcp' + - google-cloud-bigquery-storage>=2.0.0,<3 ; extra == 'gcp' + - google-cloud-datastore>=2.16.0,<3 ; extra == 'gcp' + - google-cloud-storage>=1.34.0,<3 ; extra == 'gcp' + - google-cloud-bigtable>=2.11.0,<3 ; extra == 'gcp' + - fsspec<=2024.9.0 ; extra == 'gcp' + - great-expectations>=0.15.41,<1 ; extra == 'ge' + - cffi>=1.15.0 ; extra == 'go' + - grpcio>=1.56.2,<=1.62.3 ; extra == 'grpcio' + - grpcio-reflection>=1.56.2,<=1.62.3 ; extra == 'grpcio' + - grpcio-health-checking>=1.56.2,<=1.62.3 ; extra == 'grpcio' + - hazelcast-python-client>=5.1 ; extra == 'hazelcast' + - happybase>=1.2.0,<3 ; extra == 'hbase' + - ibis-framework>=10.0.0 ; extra == 'ibis' + - kubernetes ; extra == 'k8s' + - feast[pytorch] ; extra == 'image' + - timm>=0.6.0 ; extra == 'image' + - pillow>=8.0.0 ; extra == 'image' + - scikit-learn>=1.0.0 ; extra == 'image' + - pymilvus>2.5 ; extra == 'milvus' + - milvus-lite==2.4.12 ; extra == 'milvus' + - feast[setuptools] ; extra == 'milvus' + - pymongo>=4.13.0,<5.0.0 ; extra == 'mongodb' + - dnspython>=2.0.0 ; extra == 'mongodb' + - ibis-framework[mssql]>=10.0.0 ; extra == 'mssql' + - ibis-framework[oracle]>=10.0.0 ; extra == 'oracle' + - pymysql ; extra == 'mysql' + - types-pymysql ; extra == 'mysql' + - openlineage-python>=1.40.0 ; extra == 'openlineage' + - prometheus-client ; extra == 'opentelemetry' + - psutil ; extra == 'opentelemetry' + - pyspark>=4.0.0 ; extra == 'spark' + - trino>=0.305.0,<0.400.0 ; extra == 'trino' + - regex ; extra == 'trino' + - psycopg[binary,pool]==3.2.5 ; extra == 'postgres' + - psycopg[c,pool]==3.2.5 ; extra == 'postgres-c' + - torch>=2.7.0 ; extra == 'pytorch' + - torchvision>=0.22.1 ; extra == 'pytorch' + - qdrant-client>=1.12.0 ; extra == 'qdrant' + - transformers>=4.36.0 ; extra == 'rag' + - datasets>=3.6.0 ; extra == 'rag' + - sentence-transformers>=3.0.0 ; extra == 'rag' + - ray>=2.47.0 ; python_full_version == '3.10.*' and extra == 'ray' + - codeflare-sdk>=0.31.1 ; python_full_version >= '3.11' and extra == 'ray' + - redis>=4.2.2,<5 ; extra == 'redis' + - hiredis>=2.0.0,<3 ; extra == 'redis' + - singlestoredb<1.8.0 ; extra == 'singlestore' + - snowflake-connector-python[pandas]>=3.7,<5 ; extra == 'snowflake' + - sqlite-vec==0.1.6 ; extra == 'sqlite-vec' + - fastapi-mcp ; extra == 'mcp' + - dbt-artifacts-parser ; extra == 'dbt' + - pytest>=6.0.0,<8 ; extra == 'test' + - pytest-xdist>=3.8.0 ; extra == 'test' + - pytest-timeout==1.4.2 ; extra == 'test' + - pytest-lazy-fixture==0.6.3 ; extra == 'test' + - pytest-ordering~=0.6.0 ; extra == 'test' + - pytest-mock==1.10.4 ; extra == 'test' + - pytest-env ; extra == 'test' + - pytest-benchmark>=3.4.1,<4 ; extra == 'test' + - pytest-asyncio<=0.24.0 ; extra == 'test' + - py>=1.11.0 ; extra == 'test' + - testcontainers==4.9.0 ; extra == 'test' + - minio==7.2.11 ; extra == 'test' + - python-keycloak==4.2.2 ; extra == 'test' + - cryptography>=43.0 ; extra == 'test' + - feast[aws,azure,cassandra,clickhouse,couchbase,delta,docling,duckdb,elasticsearch,faiss,gcp,ge,go,grpcio,hazelcast,hbase,ibis,image,k8s,mcp,milvus,mssql,mysql,openlineage,opentelemetry,oracle,postgres,pytorch,qdrant,rag,ray,redis,singlestore,snowflake,spark,sqlite-vec,test,trino] ; extra == 'ci' + - build ; extra == 'ci' + - virtualenv==20.23.0 ; extra == 'ci' + - dbt-artifacts-parser ; extra == 'ci' + - ruff>=0.8.0 ; extra == 'ci' + - mypy-protobuf>=3.1 ; extra == 'ci' + - grpcio-tools>=1.56.2,<=1.62.3 ; extra == 'ci' + - grpcio-testing>=1.56.2,<=1.62.3 ; extra == 'ci' + - httpx==0.27.2 ; extra == 'ci' + - mock==2.0.0 ; extra == 'ci' + - moto<5 ; extra == 'ci' + - mypy>=1.4.1,<1.11.3 ; extra == 'ci' + - urllib3>=2.6.3,<3 ; extra == 'ci' + - psutil==5.9.0 ; extra == 'ci' + - pytest-cov ; extra == 'ci' + - sphinx>4.0.0,<7 ; extra == 'ci' + - sqlglot[rs]>=23.4 ; extra == 'ci' + - pre-commit<3.3.2 ; extra == 'ci' + - assertpy==1.1 ; extra == 'ci' + - pip-tools ; extra == 'ci' + - pybindgen==0.22.0 ; extra == 'ci' + - types-protobuf~=3.19.22 ; extra == 'ci' + - python-dateutil==2.9.0 ; extra == 'ci' + - types-python-dateutil ; extra == 'ci' + - types-pytz ; extra == 'ci' + - types-pyyaml ; extra == 'ci' + - types-redis ; extra == 'ci' + - types-requests<2.31.0 ; extra == 'ci' + - types-setuptools ; extra == 'ci' + - types-tabulate ; extra == 'ci' + - feast[docling,image,milvus,pytorch,rag] ; extra == 'nlp' + - feast[ci] ; extra == 'dev' + - feast[ci] ; extra == 'docs' + - feast[aws,duckdb,gcp,go,grpcio,k8s,mcp,milvus,mysql,opentelemetry,postgres-c,redis,snowflake] ; extra == 'minimal' + - feast[minimal] ; extra == 'minimal-sdist-build' + - feast[ibis] ; extra == 'minimal-sdist-build' + - meson<1.7.2 ; extra == 'minimal-sdist-build' + - pybindgen==0.22.0 ; extra == 'minimal-sdist-build' + - sphinx!=4.0.0 ; extra == 'minimal-sdist-build' + - types-psutil<7.0.0.20250401 ; extra == 'minimal-sdist-build' + - greenlet!=0.4.17 ; extra == 'minimal-sdist-build' + - meson-python>=0.15.0,<0.16.0 ; extra == 'minimal-sdist-build' + - cython>=0.29.34,<3.1 ; extra == 'minimal-sdist-build' + - flit-core>=3.8,<4 ; extra == 'minimal-sdist-build' + - patchelf>=0.11.0 ; extra == 'minimal-sdist-build' + - scikit-build-core>=0.10 ; extra == 'minimal-sdist-build' + - hatch-fancy-pypi-readme>=23.2.0 ; extra == 'minimal-sdist-build' + - hatch-vcs==0.4.0 ; extra == 'minimal-sdist-build' + - hatchling>=1.6.0,<2 ; extra == 'minimal-sdist-build' + - calver<2025.4.1 ; extra == 'minimal-sdist-build' + - setuptools>=60,<81 ; extra == 'setuptools' + requires_python: '>=3.10.0' +- pypi: https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl + name: filelock + version: 3.25.2 + sha256: ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/5d/ed/c7895fd2fde7f3ee70d248175f9b6cdf792fb741ab92dc59cd9ef3bd241b/frozenlist-1.8.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + name: frozenlist + version: 1.8.0 + sha256: f57fb59d9f385710aa7060e89410aeb5058b99e62f4d16b08b91986b9a2140c2 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/63/70/26ca3f06aace16f2352796b08704338d74b6d1a24ca38f2771afbb7ed915/frozenlist-1.8.0-cp310-cp310-macosx_11_0_arm64.whl + name: frozenlist + version: 1.8.0 + sha256: a88f062f072d1589b7b46e951698950e7da00442fc1cacbe17e19e025dc327ad + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/a2/fb/c85f9fed3ea8fe8740e5b46a59cc141c23b842eca617da8876cfce5f760e/frozenlist-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl + name: frozenlist + version: 1.8.0 + sha256: ef2b7b394f208233e471abc541cc6991f907ffd47dc72584acee3147899d6565 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/1d/a0/6aaea0c2fbea2f89bfd5db25fb1e3481896a423002ebe4e55288907a97a3/fsspec-2024.9.0-py3-none-any.whl + name: fsspec + version: 2024.9.0 + sha256: a0947d552d8a6efa72cc2c730b12c41d043509156966cca4fb157b0f2a0c574b + requires_dist: + - adlfs ; extra == 'abfs' + - adlfs ; extra == 'adl' + - pyarrow>=1 ; extra == 'arrow' + - dask ; extra == 'dask' + - distributed ; extra == 'dask' + - pre-commit ; extra == 'dev' + - ruff ; extra == 'dev' + - numpydoc ; extra == 'doc' + - sphinx ; extra == 'doc' + - sphinx-design ; extra == 'doc' + - sphinx-rtd-theme ; extra == 'doc' + - yarl ; extra == 'doc' + - dropbox ; extra == 'dropbox' + - dropboxdrivefs ; extra == 'dropbox' + - requests ; extra == 'dropbox' + - adlfs ; extra == 'full' + - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'full' + - dask ; extra == 'full' + - distributed ; extra == 'full' + - dropbox ; extra == 'full' + - dropboxdrivefs ; extra == 'full' + - fusepy ; extra == 'full' + - gcsfs ; extra == 'full' + - libarchive-c ; extra == 'full' + - ocifs ; extra == 'full' + - panel ; extra == 'full' + - paramiko ; extra == 'full' + - pyarrow>=1 ; extra == 'full' + - pygit2 ; extra == 'full' + - requests ; extra == 'full' + - s3fs ; extra == 'full' + - smbprotocol ; extra == 'full' + - tqdm ; extra == 'full' + - fusepy ; extra == 'fuse' + - gcsfs ; extra == 'gcs' + - pygit2 ; extra == 'git' + - requests ; extra == 'github' + - gcsfs ; extra == 'gs' + - panel ; extra == 'gui' + - pyarrow>=1 ; extra == 'hdfs' + - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'http' + - libarchive-c ; extra == 'libarchive' + - ocifs ; extra == 'oci' + - s3fs ; extra == 's3' + - paramiko ; extra == 'sftp' + - smbprotocol ; extra == 'smb' + - paramiko ; extra == 'ssh' + - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'test' + - numpy ; extra == 'test' + - pytest ; extra == 'test' + - pytest-asyncio!=0.22.0 ; extra == 'test' + - pytest-benchmark ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-mock ; extra == 'test' + - pytest-recording ; extra == 'test' + - pytest-rerunfailures ; extra == 'test' + - requests ; extra == 'test' + - aiobotocore>=2.5.4,<3.0.0 ; extra == 'test-downstream' + - dask-expr ; extra == 'test-downstream' + - dask[dataframe,test] ; extra == 'test-downstream' + - moto[server]>4,<5 ; extra == 'test-downstream' + - pytest-timeout ; extra == 'test-downstream' + - xarray ; extra == 'test-downstream' + - adlfs ; extra == 'test-full' + - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'test-full' + - cloudpickle ; extra == 'test-full' + - dask ; extra == 'test-full' + - distributed ; extra == 'test-full' + - dropbox ; extra == 'test-full' + - dropboxdrivefs ; extra == 'test-full' + - fastparquet ; extra == 'test-full' + - fusepy ; extra == 'test-full' + - gcsfs ; extra == 'test-full' + - jinja2 ; extra == 'test-full' + - kerchunk ; extra == 'test-full' + - libarchive-c ; extra == 'test-full' + - lz4 ; extra == 'test-full' + - notebook ; extra == 'test-full' + - numpy ; extra == 'test-full' + - ocifs ; extra == 'test-full' + - pandas ; extra == 'test-full' + - panel ; extra == 'test-full' + - paramiko ; extra == 'test-full' + - pyarrow ; extra == 'test-full' + - pyarrow>=1 ; extra == 'test-full' + - pyftpdlib ; extra == 'test-full' + - pygit2 ; extra == 'test-full' + - pytest ; extra == 'test-full' + - pytest-asyncio!=0.22.0 ; extra == 'test-full' + - pytest-benchmark ; extra == 'test-full' + - pytest-cov ; extra == 'test-full' + - pytest-mock ; extra == 'test-full' + - pytest-recording ; extra == 'test-full' + - pytest-rerunfailures ; extra == 'test-full' + - python-snappy ; extra == 'test-full' + - requests ; extra == 'test-full' + - smbprotocol ; extra == 'test-full' + - tqdm ; extra == 'test-full' + - urllib3 ; extra == 'test-full' + - zarr ; extra == 'test-full' + - zstandard ; extra == 'test-full' + - tqdm ; extra == 'tqdm' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/d5/1f/5f4a3cd9e4440e9d9bc78ad0a91a1c8d46b4d429d5239ebe6793c9fe5c41/fsspec-2026.3.0-py3-none-any.whl + name: fsspec + version: 2026.3.0 + sha256: d2ceafaad1b3457968ed14efa28798162f1638dbb5d2a6868a2db002a5ee39a4 + requires_dist: + - adlfs ; extra == 'abfs' + - adlfs ; extra == 'adl' + - pyarrow>=1 ; extra == 'arrow' + - dask ; extra == 'dask' + - distributed ; extra == 'dask' + - pre-commit ; extra == 'dev' + - ruff>=0.5 ; extra == 'dev' + - numpydoc ; extra == 'doc' + - sphinx ; extra == 'doc' + - sphinx-design ; extra == 'doc' + - sphinx-rtd-theme ; extra == 'doc' + - yarl ; extra == 'doc' + - dropbox ; extra == 'dropbox' + - dropboxdrivefs ; extra == 'dropbox' + - requests ; extra == 'dropbox' + - adlfs ; extra == 'full' + - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'full' + - dask ; extra == 'full' + - distributed ; extra == 'full' + - dropbox ; extra == 'full' + - dropboxdrivefs ; extra == 'full' + - fusepy ; extra == 'full' + - gcsfs>2024.2.0 ; extra == 'full' + - libarchive-c ; extra == 'full' + - ocifs ; extra == 'full' + - panel ; extra == 'full' + - paramiko ; extra == 'full' + - pyarrow>=1 ; extra == 'full' + - pygit2 ; extra == 'full' + - requests ; extra == 'full' + - s3fs>2024.2.0 ; extra == 'full' + - smbprotocol ; extra == 'full' + - tqdm ; extra == 'full' + - fusepy ; extra == 'fuse' + - gcsfs>2024.2.0 ; extra == 'gcs' + - pygit2 ; extra == 'git' + - requests ; extra == 'github' + - gcsfs ; extra == 'gs' + - panel ; extra == 'gui' + - pyarrow>=1 ; extra == 'hdfs' + - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'http' + - libarchive-c ; extra == 'libarchive' + - ocifs ; extra == 'oci' + - s3fs>2024.2.0 ; extra == 's3' + - paramiko ; extra == 'sftp' + - smbprotocol ; extra == 'smb' + - paramiko ; extra == 'ssh' + - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'test' + - numpy ; extra == 'test' + - pytest ; extra == 'test' + - pytest-asyncio!=0.22.0 ; extra == 'test' + - pytest-benchmark ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-mock ; extra == 'test' + - pytest-recording ; extra == 'test' + - pytest-rerunfailures ; extra == 'test' + - requests ; extra == 'test' + - aiobotocore>=2.5.4,<3.0.0 ; extra == 'test-downstream' + - dask[dataframe,test] ; extra == 'test-downstream' + - moto[server]>4,<5 ; extra == 'test-downstream' + - pytest-timeout ; extra == 'test-downstream' + - xarray ; extra == 'test-downstream' + - adlfs ; extra == 'test-full' + - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'test-full' + - backports-zstd ; python_full_version < '3.14' and extra == 'test-full' + - cloudpickle ; extra == 'test-full' + - dask ; extra == 'test-full' + - distributed ; extra == 'test-full' + - dropbox ; extra == 'test-full' + - dropboxdrivefs ; extra == 'test-full' + - fastparquet ; extra == 'test-full' + - fusepy ; extra == 'test-full' + - gcsfs ; extra == 'test-full' + - jinja2 ; extra == 'test-full' + - kerchunk ; extra == 'test-full' + - libarchive-c ; extra == 'test-full' + - lz4 ; extra == 'test-full' + - notebook ; extra == 'test-full' + - numpy ; extra == 'test-full' + - ocifs ; extra == 'test-full' + - pandas<3.0.0 ; extra == 'test-full' + - panel ; extra == 'test-full' + - paramiko ; extra == 'test-full' + - pyarrow ; extra == 'test-full' + - pyarrow>=1 ; extra == 'test-full' + - pyftpdlib ; extra == 'test-full' + - pygit2 ; extra == 'test-full' + - pytest ; extra == 'test-full' + - pytest-asyncio!=0.22.0 ; extra == 'test-full' + - pytest-benchmark ; extra == 'test-full' + - pytest-cov ; extra == 'test-full' + - pytest-mock ; extra == 'test-full' + - pytest-recording ; extra == 'test-full' + - pytest-rerunfailures ; extra == 'test-full' + - python-snappy ; extra == 'test-full' + - requests ; extra == 'test-full' + - smbprotocol ; extra == 'test-full' + - tqdm ; extra == 'test-full' + - urllib3 ; extra == 'test-full' + - zarr ; extra == 'test-full' + - zstandard ; python_full_version < '3.14' and extra == 'test-full' + - tqdm ; extra == 'tqdm' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/84/e1/ebd5100cbb202e561c0c8b59e485ef3bd63fa9beb610f3fdcaea443f0288/google_api_core-2.30.2-py3-none-any.whl + name: google-api-core + version: 2.30.2 + sha256: a4c226766d6af2580577db1f1a51bf53cd262f722b49731ce7414c43068a9594 + requires_dist: + - googleapis-common-protos>=1.63.2,<2.0.0 + - protobuf>=4.25.8,<8.0.0 + - proto-plus>=1.22.3,<2.0.0 + - proto-plus>=1.25.0,<2.0.0 ; python_full_version >= '3.13' + - google-auth>=2.14.1,<3.0.0 + - requests>=2.20.0,<3.0.0 + - google-auth[aiohttp]>=2.35.0,<3.0.0 ; extra == 'async-rest' + - grpcio>=1.33.2,<2.0.0 ; extra == 'grpc' + - grpcio>=1.49.1,<2.0.0 ; python_full_version >= '3.11' and extra == 'grpc' + - grpcio>=1.75.1,<2.0.0 ; python_full_version >= '3.14' and extra == 'grpc' + - grpcio-status>=1.33.2,<2.0.0 ; extra == 'grpc' + - grpcio-status>=1.49.1,<2.0.0 ; python_full_version >= '3.11' and extra == 'grpc' + - grpcio-status>=1.75.1,<2.0.0 ; python_full_version >= '3.14' and extra == 'grpc' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/e9/eb/c6c2478d8a8d633460be40e2a8a6f8f429171997a35a96f81d3b680dec83/google_auth-2.49.1-py3-none-any.whl + name: google-auth + version: 2.49.1 + sha256: 195ebe3dca18eddd1b3db5edc5189b76c13e96f29e73043b923ebcf3f1a860f7 + requires_dist: + - pyasn1-modules>=0.2.1 + - cryptography>=38.0.3 + - cryptography>=38.0.3 ; extra == 'cryptography' + - aiohttp>=3.6.2,<4.0.0 ; extra == 'aiohttp' + - requests>=2.20.0,<3.0.0 ; extra == 'aiohttp' + - pyopenssl ; extra == 'enterprise-cert' + - pyopenssl>=20.0.0 ; extra == 'pyopenssl' + - pyjwt>=2.0 ; extra == 'pyjwt' + - pyu2f>=0.1.5 ; extra == 'reauth' + - requests>=2.20.0,<3.0.0 ; extra == 'requests' + - grpcio ; extra == 'testing' + - flask ; extra == 'testing' + - freezegun ; extra == 'testing' + - pyjwt>=2.0 ; extra == 'testing' + - pytest ; extra == 'testing' + - pytest-cov ; extra == 'testing' + - pytest-localserver ; extra == 'testing' + - pyopenssl>=20.0.0 ; extra == 'testing' + - pyu2f>=0.1.5 ; extra == 'testing' + - responses ; extra == 'testing' + - urllib3 ; extra == 'testing' + - packaging ; extra == 'testing' + - aiohttp>=3.6.2,<4.0.0 ; extra == 'testing' + - requests>=2.20.0,<3.0.0 ; extra == 'testing' + - aioresponses ; extra == 'testing' + - pytest-asyncio ; extra == 'testing' + - pyopenssl<24.3.0 ; extra == 'testing' + - aiohttp<3.10.0 ; extra == 'testing' + - urllib3 ; extra == 'urllib3' + - packaging ; extra == 'urllib3' + - rsa>=3.1.4,<5 ; extra == 'rsa' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/2a/e0/cb454a95f460903e39f101e950038ec24a072ca69d0a294a6df625cc1627/google_auth_oauthlib-1.3.1-py3-none-any.whl + name: google-auth-oauthlib + version: 1.3.1 + sha256: 1a139ef23f1318756805b0e95f655c238bffd29655329a2978218248da4ee7f8 + requires_dist: + - google-auth>=2.15.0,!=2.43.0,!=2.44.0,!=2.45.0,<3.0.0 + - requests-oauthlib>=0.7.0 + - click>=6.0.0 ; extra == 'tool' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/40/33/1d3902efadef9194566d499d61507e1f038454e0b55499d2d7f8ab2a4fee/google_cloud_bigquery-3.41.0-py3-none-any.whl + name: google-cloud-bigquery + version: 3.41.0 + sha256: 2a5b5a737b401cbd824a6e5eac7554100b878668d908e6548836b5d8aaa4dcaa + requires_dist: + - google-api-core[grpc]>=2.11.1,<3.0.0 + - google-auth>=2.14.1,<3.0.0 + - google-cloud-core>=2.4.1,<3.0.0 + - google-resumable-media>=2.0.0,<3.0.0 + - packaging>=24.2.0 + - python-dateutil>=2.8.2,<3.0.0 + - requests>=2.21.0,<3.0.0 + - google-cloud-bigquery-storage>=2.18.0,<3.0.0 ; extra == 'bqstorage' + - grpcio>=1.47.0,<2.0.0 ; extra == 'bqstorage' + - grpcio>=1.49.1,<2.0.0 ; python_full_version >= '3.11' and extra == 'bqstorage' + - grpcio>=1.75.1,<2.0.0 ; python_full_version >= '3.14' and extra == 'bqstorage' + - pyarrow>=4.0.0 ; extra == 'bqstorage' + - pandas>=1.3.0 ; extra == 'pandas' + - pandas-gbq>=0.26.1 ; extra == 'pandas' + - grpcio>=1.47.0,<2.0.0 ; extra == 'pandas' + - grpcio>=1.49.1,<2.0.0 ; python_full_version >= '3.11' and extra == 'pandas' + - grpcio>=1.75.1,<2.0.0 ; python_full_version >= '3.14' and extra == 'pandas' + - pyarrow>=3.0.0 ; extra == 'pandas' + - db-dtypes>=1.0.4,<2.0.0 ; extra == 'pandas' + - ipywidgets>=7.7.1 ; extra == 'ipywidgets' + - ipykernel>=6.2.0 ; extra == 'ipywidgets' + - geopandas>=0.9.0,<2.0.0 ; extra == 'geopandas' + - shapely>=1.8.4,<3.0.0 ; extra == 'geopandas' + - ipython>=7.23.1 ; extra == 'ipython' + - bigquery-magics>=0.6.0 ; extra == 'ipython' + - matplotlib>=3.7.1,<=3.9.2 ; python_full_version == '3.9.*' and extra == 'matplotlib' + - matplotlib>=3.10.3 ; python_full_version >= '3.10' and extra == 'matplotlib' + - tqdm>=4.23.4,<5.0.0 ; extra == 'tqdm' + - opentelemetry-api>=1.1.0 ; extra == 'opentelemetry' + - opentelemetry-sdk>=1.1.0 ; extra == 'opentelemetry' + - opentelemetry-instrumentation>=0.20b0 ; extra == 'opentelemetry' + - proto-plus>=1.22.3,<2.0.0 ; extra == 'bigquery-v2' + - protobuf>=3.20.2,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<7.0.0 ; extra == 'bigquery-v2' + - google-cloud-bigquery[bigquery-v2,bqstorage,geopandas,ipython,ipywidgets,matplotlib,opentelemetry,pandas,tqdm] ; extra == 'all' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/74/0e/2950d4d0160300f51c7397a080b1685d3e25b40badb2c96f03d58d0ee868/google_cloud_bigquery_storage-2.37.0-py3-none-any.whl + name: google-cloud-bigquery-storage + version: 2.37.0 + sha256: 1e319c27ef60fc31030f6e0b52e5e891e1cdd50551effe8c6f673a4c3c56fcb6 + requires_dist: + - google-api-core[grpc]>=2.11.0,<3.0.0 + - google-auth>=2.14.1,!=2.24.0,!=2.25.0,<3.0.0 + - grpcio>=1.33.2,<2.0.0 + - grpcio>=1.75.1,<2.0.0 ; python_full_version >= '3.14' + - proto-plus>=1.22.3,<2.0.0 + - proto-plus>=1.25.0,<2.0.0 ; python_full_version >= '3.13' + - protobuf>=4.25.8,<8.0.0 + - pandas>=1.1.3 ; extra == 'pandas' + - fastavro>=1.1.0 ; extra == 'fastavro' + - pyarrow>=3.0.0 ; extra == 'pyarrow' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/d1/19/1cc695fa8489ef446a70ee9e983c12f4b47e0649005758035530eaec4b1c/google_cloud_bigtable-2.36.0-py3-none-any.whl + name: google-cloud-bigtable + version: 2.36.0 + sha256: 21b2f41231b7368a550b44d5b493b811b3507fcb23eb26d00005cd3f205f2207 + requires_dist: + - google-api-core[grpc]>=2.17.0,<3.0.0 + - google-cloud-core>=1.4.4,<3.0.0 + - google-auth>=2.23.0,!=2.24.0,!=2.25.0,<3.0.0 + - grpc-google-iam-v1>=0.12.4,<1.0.0 + - proto-plus>=1.22.3,<2.0.0 + - proto-plus>=1.25.0,<2.0.0 ; python_full_version >= '3.13' + - protobuf>=3.20.2,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<7.0.0 + - google-crc32c>=1.5.0,<2.0.0.dev0 + - libcst>=0.2.5 ; extra == 'libcst' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/73/d9/5bb050cb32826466aa9b25f79e2ca2879fe66cb76782d4ed798dd7506151/google_cloud_core-2.5.1-py3-none-any.whl + name: google-cloud-core + version: 2.5.1 + sha256: ea62cdf502c20e3e14be8a32c05ed02113d7bef454e40ff3fab6fe1ec9f1f4e7 + requires_dist: + - google-api-core>=2.11.0,<3.0.0 + - google-auth>=2.14.1,!=2.24.0,!=2.25.0,<3.0.0 + - grpcio>=1.38.0,<2.0.0 ; python_full_version < '3.14' and extra == 'grpc' + - grpcio>=1.75.1,<2.0.0 ; python_full_version >= '3.14' and extra == 'grpc' + - grpcio-status>=1.38.0,<2.0.0 ; extra == 'grpc' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/5b/88/357efc6b331fd29155dcb92a5dfb0030a8a6feddb7bbf8a6215defbed6c7/google_cloud_datastore-2.24.0-py3-none-any.whl + name: google-cloud-datastore + version: 2.24.0 + sha256: 81f1d1c12c2906f59507f72742545ab04c38f62ed70b0542057e3cf04a53aa65 + requires_dist: + - google-api-core[grpc]>=2.11.0,<3.0.0 + - google-auth>=2.14.1,!=2.24.0,!=2.25.0,<3.0.0 + - google-cloud-core>=2.0.0,<3.0.0 + - grpcio>=1.38.0,<2.0.0 + - grpcio>=1.75.1,<2.0.0 ; python_full_version >= '3.14' + - proto-plus>=1.22.3,<2.0.0 + - proto-plus>=1.25.0,<2.0.0 ; python_full_version >= '3.13' + - protobuf>=4.25.8,<8.0.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/d5/94/6db383d8ee1adf45dc6c73477152b82731fa4c4a46d9c1932cc8757e0fd4/google_cloud_storage-2.19.0-py2.py3-none-any.whl + name: google-cloud-storage + version: 2.19.0 + sha256: aeb971b5c29cf8ab98445082cbfe7b161a1f48ed275822f59ed3f1524ea54fba + requires_dist: + - google-auth>=2.26.1,<3.0.dev0 + - google-api-core>=2.15.0,<3.0.0.dev0 + - google-cloud-core>=2.3.0,<3.0.dev0 + - google-resumable-media>=2.7.2 + - requests>=2.18.0,<3.0.0.dev0 + - google-crc32c>=1.0,<2.0.dev0 + - protobuf<6.0.0.dev0 ; extra == 'protobuf' + - opentelemetry-api>=1.1.0 ; extra == 'tracing' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/3d/63/bec827e70b7a0d4094e7476f863c0dbd6b5f0f1f91d9c9b32b76dcdfeb4e/google_crc32c-1.8.0-cp310-cp310-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl + name: google-crc32c + version: 1.8.0 + sha256: 6f35aaffc8ccd81ba3162443fabb920e65b1f20ab1952a31b13173a67811467d + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/95/ac/6f7bc93886a823ab545948c2dd48143027b2355ad1944c7cf852b338dc91/google_crc32c-1.8.0-cp310-cp310-macosx_12_0_arm64.whl + name: google-crc32c + version: 1.8.0 + sha256: 0470b8c3d73b5f4e3300165498e4cf25221c7eb37f1159e221d1825b6df8a7ff + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/f7/97/a5accde175dee985311d949cfcb1249dcbb290f5ec83c994ea733311948f/google_crc32c-1.8.0-cp310-cp310-macosx_12_0_x86_64.whl + name: google-crc32c + version: 1.8.0 + sha256: 119fcd90c57c89f30040b47c211acee231b25a45d225e3225294386f5d258288 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/5e/f8/50bfaf4658431ff9de45c5c3935af7ab01157a4903c603cd0eee6e78e087/google_resumable_media-2.8.2-py3-none-any.whl + name: google-resumable-media + version: 2.8.2 + sha256: 82b6d8ccd11765268cdd2a2123f417ec806b8eef3000a9a38dfe3033da5fb220 + requires_dist: + - google-crc32c>=1.0.0,<2.0.0 + - requests>=2.18.0,<3.0.0 ; extra == 'requests' + - aiohttp>=3.6.2,<4.0.0 ; extra == 'aiohttp' + - google-auth>=1.22.0,<2.0.0 ; extra == 'aiohttp' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/b6/b0/be5d3329badb9230b765de6eea66b73abd5944bdeb5afb3562ddcd80ae84/googleapis_common_protos-1.74.0-py3-none-any.whl + name: googleapis-common-protos + version: 1.74.0 + sha256: 702216f78610bb510e3f12ac3cafd281b7ac45cc5d86e90ad87e4d301a3426b5 + requires_dist: + - protobuf>=4.25.8,<8.0.0 + - grpcio>=1.44.0,<2.0.0 ; extra == 'grpc' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/38/3f/9859f655d11901e7b2996c6e3d33e0caa9a1d4572c3bc61ed0faa64b2f4c/greenlet-3.3.2-cp310-cp310-macosx_11_0_universal2.whl + name: greenlet + version: 3.3.2 + sha256: 9bc885b89709d901859cf95179ec9f6bb67a3d2bb1f0e88456461bd4b7f8fd0d + requires_dist: + - sphinx ; extra == 'docs' + - furo ; extra == 'docs' + - objgraph ; extra == 'test' + - psutil ; extra == 'test' + - setuptools ; extra == 'test' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/3f/ae/8bffcbd373b57a5992cd077cbe8858fff39110480a9d50697091faea6f39/greenlet-3.3.2-cp314-cp314-macosx_11_0_universal2.whl + name: greenlet + version: 3.3.2 + sha256: 8d1658d7291f9859beed69a776c10822a0a799bc4bfe1bd4272bb60e62507dab + requires_dist: + - sphinx ; extra == 'docs' + - furo ; extra == 'docs' + - objgraph ; extra == 'test' + - psutil ; extra == 'test' + - setuptools ; extra == 'test' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/ad/55/9f1ebb5a825215fadcc0f7d5073f6e79e3007e3282b14b22d6aba7ca6cb8/greenlet-3.3.2-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + name: greenlet + version: 3.3.2 + sha256: ad0c8917dd42a819fe77e6bdfcb84e3379c0de956469301d9fd36427a1ca501f + requires_dist: + - sphinx ; extra == 'docs' + - furo ; extra == 'docs' + - objgraph ; extra == 'test' + - psutil ; extra == 'test' + - setuptools ; extra == 'test' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/d2/d8/09bfa816572a4d83bccd6750df1926f79158b1c36c5f73786e26dbe4ee38/greenlet-3.3.2-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + name: greenlet + version: 3.3.2 + sha256: 63d10328839d1973e5ba35e98cccbca71b232b14051fd957b6f8b6e8e80d0506 + requires_dist: + - sphinx ; extra == 'docs' + - furo ; extra == 'docs' + - objgraph ; extra == 'test' + - psutil ; extra == 'test' + - setuptools ; extra == 'test' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/89/22/c2dd50c09bf679bd38173656cd4402d2511e563b33bc88f90009cf50613c/grpc_google_iam_v1-0.14.4-py3-none-any.whl + name: grpc-google-iam-v1 + version: 0.14.4 + sha256: 412facc320fcbd94034b4df3d557662051d4d8adfa86e0ddb4dca70a3f739964 + requires_dist: + - grpcio>=1.44.0,<2.0.0 + - googleapis-common-protos[grpc]>=1.63.2,<2.0.0 + - protobuf>=4.25.8,<8.0.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/58/2f/f3fc773270cf17e7ca076c1f6435278f58641d475a25cdeea5b2d8d4845b/grpcio-1.62.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: grpcio + version: 1.62.3 + sha256: 807176971c504c598976f5a9ea62363cffbbbb6c7509d9808c2342b020880fa2 + requires_dist: + - grpcio-tools>=1.62.3 ; extra == 'protobuf' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/c5/63/ee244c4b64f0e71cef5314f9fa1d120c072e33c2e4c545dc75bd1af2a5c5/grpcio-1.62.3-cp310-cp310-macosx_12_0_universal2.whl + name: grpcio + version: 1.62.3 + sha256: f5def814c5a4c90c8fe389c526ab881f4a28b7e239b23ed8e02dd02934dfaa1a + requires_dist: + - grpcio-tools>=1.62.3 ; extra == 'protobuf' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/40/4c/ee3173906196b741ac6ba55a9788ba9ebf2cd05f91715a49b6c3bfbb9d73/grpcio_health_checking-1.62.3-py3-none-any.whl + name: grpcio-health-checking + version: 1.62.3 + sha256: f29da7dd144d73b4465fe48f011a91453e9ff6c8af0d449254cf80021cab3e0d + requires_dist: + - protobuf>=4.21.6 + - grpcio>=1.62.3 + requires_python: '>=3.6' +- pypi: https://files.pythonhosted.org/packages/82/54/acc6a6e684827b0f6bb4e2c27f3d7e25b71322c4078ef5b455c07c43260e/grpcio_reflection-1.62.3-py3-none-any.whl + name: grpcio-reflection + version: 1.62.3 + sha256: a48ef37df81a3bada78261fc92ef382f061112f989d1312398b945cc69838b9c + requires_dist: + - protobuf>=4.21.6 + - grpcio>=1.62.3 + requires_python: '>=3.6' +- pypi: https://files.pythonhosted.org/packages/90/40/972271de05f9315c0d69f9f7ebbcadd83bc85322f538637d11bb8c67803d/grpcio_status-1.62.3-py3-none-any.whl + name: grpcio-status + version: 1.62.3 + sha256: f9049b762ba8de6b1086789d8315846e094edac2c50beaf462338b301a8fd4b8 + requires_dist: + - protobuf>=4.21.6 + - grpcio>=1.62.3 + - googleapis-common-protos>=1.5.5 + requires_python: '>=3.6' +- pypi: https://files.pythonhosted.org/packages/b2/23/55d40e1bf54c141f541ab31b4b4b0f58610440c8837b1406f3467c2b4853/grpcio_testing-1.62.3-py3-none-any.whl + name: grpcio-testing + version: 1.62.3 + sha256: 06a4d7eb30d22f91368aa7f48bfc33563da13b9d951314455ca8c9c987fb75bb + requires_dist: + - protobuf>=4.21.6 + - grpcio>=1.62.3 +- pypi: https://files.pythonhosted.org/packages/43/c8/8aaf447698c4d59aa853fd318eed300b5c9e44459f242ab8ead6c9c09792/gunicorn-25.3.0-py3-none-any.whl + name: gunicorn + version: 25.3.0 + sha256: cacea387dab08cd6776501621c295a904fe8e3b7aae9a1a3cbb26f4e7ed54660 + requires_dist: + - packaging + - gevent>=24.10.1 ; extra == 'gevent' + - eventlet>=0.40.3 ; extra == 'eventlet' + - tornado>=6.5.0 ; extra == 'tornado' + - setproctitle ; extra == 'setproctitle' + - h2>=4.1.0 ; extra == 'http2' + - gunicorn-h1c>=0.6.3 ; extra == 'fast' + - gevent>=24.10.1 ; extra == 'testing' + - eventlet>=0.40.3 ; extra == 'testing' + - h2>=4.1.0 ; extra == 'testing' + - coverage ; extra == 'testing' + - pytest ; extra == 'testing' + - pytest-cov ; extra == 'testing' + - pytest-asyncio ; extra == 'testing' + - uvloop>=0.19.0 ; extra == 'testing' + - httpx[http2] ; extra == 'testing' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl + name: h11 + version: 0.16.0 + sha256: 63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/42/6e/8adaefff7e3e216b0f7bd6cafce6d5d06798f31c3e2852dc3db6a7d758c9/hiredis-2.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: hiredis + version: 2.4.0 + sha256: 87a8ece3e893f45354395c6b9dc0479744c1c8c6ee4471b60945d96c9b5ce6c2 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/d8/70/3f39ebfb3824578c34400df3b037b268abb5af0abaa789b430ffd17dd74e/hiredis-2.4.0-cp310-cp310-macosx_10_15_x86_64.whl + name: hiredis + version: 2.4.0 + sha256: 76503a0edaf3d1557518127511e69e5d9fa37b6ff15598b0d9d9c2db18b08a41 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/ed/b7/26a56a3b991abe7fcf7bcfa8e0a08de3c3766c6caecb1ba46239342792ff/hiredis-2.4.0-cp310-cp310-macosx_11_0_arm64.whl + name: hiredis + version: 2.4.0 + sha256: b027b53adb1df11923753d85587e3ab611fe70bc69596e9eb3269acab809c376 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl + name: httpcore + version: 1.0.9 + sha256: 2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55 + requires_dist: + - certifi + - h11>=0.16 + - anyio>=4.0,<5.0 ; extra == 'asyncio' + - h2>=3,<5 ; extra == 'http2' + - socksio==1.* ; extra == 'socks' + - trio>=0.22.0,<1.0 ; extra == 'trio' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/07/f0/89720dc5139ae54b03f861b5e2c55a37dba9a5da7d51e1e824a1f343627f/httptools-0.7.1-cp314-cp314-macosx_11_0_arm64.whl + name: httptools + version: 0.7.1 + sha256: 7aea2e3c3953521c3c51106ee11487a910d45586e351202474d45472db7d72d3 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/34/50/9d095fcbb6de2d523e027a2f304d4551855c2f46e0b82befd718b8b20056/httptools-0.7.1-cp314-cp314-macosx_10_13_universal2.whl + name: httptools + version: 0.7.1 + sha256: c08fe65728b8d70b6923ce31e3956f859d5e1e8548e6f22ec520a962c6757270 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/7e/4f/35e3a63f863a659f92ffd92bef131f3e81cf849af26e6435b49bd9f6f751/httptools-0.7.1-cp310-cp310-macosx_11_0_arm64.whl + name: httptools + version: 0.7.1 + sha256: 84d86c1e5afdc479a6fdabf570be0d3eb791df0ae727e8dbc0259ed1249998d4 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/b3/cb/eea88506f191fb552c11787c23f9a405f4c7b0c5799bf73f2249cd4f5228/httptools-0.7.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + name: httptools + version: 0.7.1 + sha256: 0e68b8582f4ea9166be62926077a3334064d422cf08ab87d8b74664f8e9058e1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/c7/e5/c07e0bcf4ec8db8164e9f6738c048b2e66aabf30e7506f440c4cc6953f60/httptools-0.7.1-cp310-cp310-macosx_10_9_universal2.whl + name: httptools + version: 0.7.1 + sha256: 11d01b0ff1fe02c4c32d60af61a4d613b74fad069e47e06e9067758c01e9ac78 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/f5/71/b0a9193641d9e2471ac541d3b1b869538a5fb6419d52fd2669fa9c79e4b8/httptools-0.7.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + name: httptools + version: 0.7.1 + sha256: c8c751014e13d88d2be5f5f14fc8b89612fcfa92a9cc480f2bc1598357a23a05 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl + name: httpx + version: 0.28.1 + sha256: d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad + requires_dist: + - anyio + - certifi + - httpcore==1.* + - idna + - brotli ; platform_python_implementation == 'CPython' and extra == 'brotli' + - brotlicffi ; platform_python_implementation != 'CPython' and extra == 'brotli' + - click==8.* ; extra == 'cli' + - pygments==2.* ; extra == 'cli' + - rich>=10,<14 ; extra == 'cli' + - h2>=3,<5 ; extra == 'http2' + - socksio==1.* ; extra == 'socks' + - zstandard>=0.18.0 ; extra == 'zstd' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/9d/b3/11d406849715b47c9d69bb22f50874f80caee96bd1cbe7b61abbebbf5a05/ibis_framework-12.0.0-py3-none-any.whl + name: ibis-framework + version: 12.0.0 + sha256: 0bbd790f268da9cb87926d5eaad2b827a573927113c4ed3be5095efa89b9e512 + requires_dist: + - atpublic>=2.3 + - parsy>=2 + - python-dateutil>=2.8.2 + - sqlglot>=23.4,!=26.32.0 + - toolz>=0.11 + - typing-extensions>=4.3.0 + - tzdata>=2022.7 + - fsspec[s3] ; extra == 'athena' + - numpy>=1.23.2,<3 ; extra == 'athena' + - pandas>=1.5.3,<4 ; extra == 'athena' + - pyarrow-hotfix>=0.4 ; extra == 'athena' + - pyarrow>=10.0.1 ; extra == 'athena' + - pyathena[arrow,pandas]>=3.11.0 ; extra == 'athena' + - rich>=12.4.4 ; extra == 'athena' + - db-dtypes>=0.3 ; extra == 'bigquery' + - google-cloud-bigquery-storage>=2 ; extra == 'bigquery' + - google-cloud-bigquery>=3 ; extra == 'bigquery' + - numpy>=1.23.2,<3 ; extra == 'bigquery' + - pandas-gbq>=0.26.1 ; extra == 'bigquery' + - pandas>=1.5.3,<4 ; extra == 'bigquery' + - pyarrow-hotfix>=0.4 ; extra == 'bigquery' + - pyarrow>=10.0.1 ; extra == 'bigquery' + - pydata-google-auth>=1.4.0 ; extra == 'bigquery' + - rich>=12.4.4 ; extra == 'bigquery' + - clickhouse-connect[arrow,numpy,pandas]>=0.5.23 ; extra == 'clickhouse' + - numpy>=1.23.2,<3 ; extra == 'clickhouse' + - pandas>=1.5.3,<4 ; extra == 'clickhouse' + - pyarrow-hotfix>=0.4 ; extra == 'clickhouse' + - pyarrow>=10.0.1 ; extra == 'clickhouse' + - rich>=12.4.4 ; extra == 'clickhouse' + - databricks-sql-connector>=4 ; extra == 'databricks' + - numpy>=1.23.2,<3 ; extra == 'databricks' + - pandas>=1.5.3,<4 ; extra == 'databricks' + - pyarrow-hotfix>=0.4 ; extra == 'databricks' + - pyarrow>=10.0.1 ; extra == 'databricks' + - rich>=12.4.4 ; extra == 'databricks' + - datafusion>=0.6 ; extra == 'datafusion' + - numpy>=1.23.2,<3 ; extra == 'datafusion' + - packaging>=21.3 ; extra == 'datafusion' + - pandas>=1.5.3,<4 ; extra == 'datafusion' + - pyarrow-hotfix>=0.4 ; extra == 'datafusion' + - pyarrow>=10.0.1 ; extra == 'datafusion' + - rich>=12.4.4 ; extra == 'datafusion' + - black>=22.1.0 ; extra == 'decompiler' + - deltalake>=0.9.0 ; extra == 'deltalake' + - numpy>=1.23.2,<3 ; extra == 'druid' + - pandas>=1.5.3,<4 ; extra == 'druid' + - pyarrow-hotfix>=0.4 ; extra == 'druid' + - pyarrow>=10.0.1 ; extra == 'druid' + - pydruid>=0.6.7 ; extra == 'druid' + - rich>=12.4.4 ; extra == 'druid' + - duckdb>=0.10.3,!=1.3.0 ; extra == 'duckdb' + - numpy>=1.23.2,<3 ; extra == 'duckdb' + - packaging>=21.3 ; extra == 'duckdb' + - pandas>=1.5.3,<4 ; extra == 'duckdb' + - pyarrow-hotfix>=0.4 ; extra == 'duckdb' + - pyarrow>=10.0.1 ; extra == 'duckdb' + - rich>=12.4.4 ; extra == 'duckdb' + - pins[gcs]>=0.8.3 ; extra == 'examples' + - numpy>=1.23.2,<3 ; extra == 'exasol' + - pandas>=1.5.3,<4 ; extra == 'exasol' + - pyarrow-hotfix>=0.4 ; extra == 'exasol' + - pyarrow>=10.0.1 ; extra == 'exasol' + - pyexasol>=0.25.2 ; extra == 'exasol' + - rich>=12.4.4 ; extra == 'exasol' + - numpy>=1.23.2,<3 ; extra == 'flink' + - pandas>=1.5.3,<4 ; extra == 'flink' + - pyarrow-hotfix>=0.4 ; extra == 'flink' + - pyarrow>=10.0.1 ; extra == 'flink' + - rich>=12.4.4 ; extra == 'flink' + - geoarrow-types>=0.2 ; extra == 'geospatial' + - geopandas>=0.6 ; extra == 'geospatial' + - pyproj>=3.3.0 ; extra == 'geospatial' + - shapely>=2 ; extra == 'geospatial' + - impyla>=0.17 ; extra == 'impala' + - numpy>=1.23.2,<3 ; extra == 'impala' + - pandas>=1.5.3,<4 ; extra == 'impala' + - pyarrow-hotfix>=0.4 ; extra == 'impala' + - pyarrow>=10.0.1 ; extra == 'impala' + - rich>=12.4.4 ; extra == 'impala' + - numpy>=1.23.2,<3 ; extra == 'materialize' + - pandas>=1.5.3,<4 ; extra == 'materialize' + - psycopg>=3.2.0 ; extra == 'materialize' + - pyarrow-hotfix>=0.4 ; extra == 'materialize' + - pyarrow>=10.0.1 ; extra == 'materialize' + - rich>=12.4.4 ; extra == 'materialize' + - numpy>=1.23.2,<3 ; extra == 'mssql' + - pandas>=1.5.3,<4 ; extra == 'mssql' + - pyarrow-hotfix>=0.4 ; extra == 'mssql' + - pyarrow>=10.0.1 ; extra == 'mssql' + - pyodbc>=4.0.39 ; extra == 'mssql' + - rich>=12.4.4 ; extra == 'mssql' + - mysqlclient>=2.2.4 ; extra == 'mysql' + - numpy>=1.23.2,<3 ; extra == 'mysql' + - pandas>=1.5.3,<4 ; extra == 'mysql' + - pyarrow-hotfix>=0.4 ; extra == 'mysql' + - pyarrow>=10.0.1 ; extra == 'mysql' + - rich>=12.4.4 ; extra == 'mysql' + - numpy>=1.23.2,<3 ; extra == 'oracle' + - oracledb>=1.3.1 ; extra == 'oracle' + - pandas>=1.5.3,<4 ; extra == 'oracle' + - pyarrow-hotfix>=0.4 ; extra == 'oracle' + - pyarrow>=10.0.1 ; extra == 'oracle' + - rich>=12.4.4 ; extra == 'oracle' + - numpy>=1.23.2,<3 ; extra == 'polars' + - pandas>=1.5.3,<4 ; extra == 'polars' + - polars>=1 ; extra == 'polars' + - pyarrow-hotfix>=0.4 ; extra == 'polars' + - pyarrow>=10.0.1 ; extra == 'polars' + - rich>=12.4.4 ; extra == 'polars' + - numpy>=1.23.2,<3 ; extra == 'postgres' + - pandas>=1.5.3,<4 ; extra == 'postgres' + - psycopg>=3.2.0 ; extra == 'postgres' + - pyarrow-hotfix>=0.4 ; extra == 'postgres' + - pyarrow>=10.0.1 ; extra == 'postgres' + - rich>=12.4.4 ; extra == 'postgres' + - numpy>=1.23.2,<3 ; extra == 'pyspark' + - packaging>=21.3 ; extra == 'pyspark' + - pandas>=1.5.3,<4 ; extra == 'pyspark' + - pyarrow-hotfix>=0.4 ; extra == 'pyspark' + - pyarrow>=10.0.1 ; extra == 'pyspark' + - pyspark>=3.5,<4.1 ; extra == 'pyspark' + - rich>=12.4.4 ; extra == 'pyspark' + - numpy>=1.23.2,<3 ; extra == 'risingwave' + - pandas>=1.5.3,<4 ; extra == 'risingwave' + - psycopg2>=2.8.4 ; extra == 'risingwave' + - pyarrow-hotfix>=0.4 ; extra == 'risingwave' + - pyarrow>=10.0.1 ; extra == 'risingwave' + - rich>=12.4.4 ; extra == 'risingwave' + - numpy>=1.23.2,<3 ; extra == 'singlestoredb' + - pandas>=1.5.3,<4 ; extra == 'singlestoredb' + - parsimonious>=0.11.0 ; extra == 'singlestoredb' + - pyarrow-hotfix>=0.4 ; extra == 'singlestoredb' + - pyarrow>=10.0.1 ; extra == 'singlestoredb' + - rich>=12.4.4 ; extra == 'singlestoredb' + - singlestoredb>=1.0 ; extra == 'singlestoredb' + - numpy>=1.23.2,<3 ; extra == 'snowflake' + - pandas>=1.5.3,<4 ; extra == 'snowflake' + - pyarrow-hotfix>=0.4 ; extra == 'snowflake' + - pyarrow>=10.0.1 ; extra == 'snowflake' + - rich>=12.4.4 ; extra == 'snowflake' + - snowflake-connector-python>=3.0.2,!=3.3.0b1 ; extra == 'snowflake' + - numpy>=1.23.2,<3 ; extra == 'sqlite' + - packaging>=21.3 ; extra == 'sqlite' + - pandas>=1.5.3,<4 ; extra == 'sqlite' + - pyarrow-hotfix>=0.4 ; extra == 'sqlite' + - pyarrow>=10.0.1 ; extra == 'sqlite' + - regex>=2021.7.6 ; extra == 'sqlite' + - rich>=12.4.4 ; extra == 'sqlite' + - numpy>=1.23.2,<3 ; extra == 'trino' + - pandas>=1.5.3,<4 ; extra == 'trino' + - pyarrow-hotfix>=0.4 ; extra == 'trino' + - pyarrow>=10.0.1 ; extra == 'trino' + - rich>=12.4.4 ; extra == 'trino' + - trino>=0.321 ; extra == 'trino' + - graphviz>=0.16 ; extra == 'visualization' + requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda + sha256: fbf86c4a59c2ed05bbffb2ba25c7ed94f6185ec30ecb691615d42342baa1a16a + md5: c80d8a3b84358cb967fa81e7075fbc8a + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + license: MIT + license_family: MIT + purls: [] + size: 12723451 + timestamp: 1773822285671 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-78.3-hef89b57_0.conda + sha256: 3a7907a17e9937d3a46dfd41cffaf815abad59a569440d1e25177c15fd0684e5 + md5: f1182c91c0de31a7abd40cedf6a5ebef + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 12361647 + timestamp: 1773822915649 +- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl + name: idna + version: '3.11' + sha256: 771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea + requires_dist: + - ruff>=0.6.2 ; extra == 'all' + - mypy>=1.11.2 ; extra == 'all' + - pytest>=8.3.2 ; extra == 'all' + - flake8>=7.1.1 ; extra == 'all' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/38/3d/2d244233ac4f76e38533cfcb2991c9eb4c7bf688ae0a036d30725b8faafe/importlib_metadata-9.0.0-py3-none-any.whl + name: importlib-metadata + version: 9.0.0 + sha256: 2d21d1cc5a017bd0559e36150c21c830ab1dc304dedd1b7ea85d20f45ef3edd7 + requires_dist: + - zipp>=3.20 + - pytest>=6,!=8.1.* ; extra == 'test' + - packaging ; extra == 'test' + - pyfakefs ; extra == 'test' + - pytest-perf>=0.9.2 ; extra == 'test' + - sphinx>=3.5 ; extra == 'doc' + - jaraco-packaging>=9.3 ; extra == 'doc' + - rst-linker>=1.9 ; extra == 'doc' + - furo ; extra == 'doc' + - sphinx-lint ; extra == 'doc' + - jaraco-tidelift>=1.4 ; extra == 'doc' + - ipython ; extra == 'perf' + - pytest-checkdocs>=2.14 ; extra == 'check' + - pytest-ruff>=0.2.1 ; sys_platform != 'cygwin' and extra == 'check' + - pytest-cov ; extra == 'cover' + - pytest-enabler>=3.4 ; extra == 'enabler' + - pytest-mypy>=1.0.1 ; platform_python_implementation != 'PyPy' and extra == 'type' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl + name: iniconfig + version: 2.3.0 + sha256: f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl + name: jinja2 + version: 3.1.6 + sha256: 85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 + requires_dist: + - markupsafe>=2.0 + - babel>=2.7 ; extra == 'i18n' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/14/2f/967ba146e6d58cf6a652da73885f52fc68001525b4197effc174321d70b4/jmespath-1.1.0-py3-none-any.whl + name: jmespath + version: 1.1.0 + sha256: a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl + name: jsonschema + version: 4.26.0 + sha256: d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce + requires_dist: + - attrs>=22.2.0 + - jsonschema-specifications>=2023.3.6 + - referencing>=0.28.4 + - rpds-py>=0.25.0 + - fqdn ; extra == 'format' + - idna ; extra == 'format' + - isoduration ; extra == 'format' + - jsonpointer>1.13 ; extra == 'format' + - rfc3339-validator ; extra == 'format' + - rfc3987 ; extra == 'format' + - uri-template ; extra == 'format' + - webcolors>=1.11 ; extra == 'format' + - fqdn ; extra == 'format-nongpl' + - idna ; extra == 'format-nongpl' + - isoduration ; extra == 'format-nongpl' + - jsonpointer>1.13 ; extra == 'format-nongpl' + - rfc3339-validator ; extra == 'format-nongpl' + - rfc3986-validator>0.1.0 ; extra == 'format-nongpl' + - rfc3987-syntax>=1.1.0 ; extra == 'format-nongpl' + - uri-template ; extra == 'format-nongpl' + - webcolors>=24.6.0 ; extra == 'format-nongpl' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl + name: jsonschema-specifications + version: 2025.9.1 + sha256: 98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe + requires_dist: + - referencing>=0.31.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/cd/58/4a1880ea64032185e9ae9f63940c9327c6952d5584ea544a8f66972f2fda/jwcrypto-1.5.6-py3-none-any.whl + name: jwcrypto + version: 1.5.6 + sha256: 150d2b0ebbdb8f40b77f543fb44ffd2baeff48788be71f67f03566692fd55789 + requires_dist: + - cryptography>=3.4 + - typing-extensions>=4.5.0 + requires_python: '>=3.8' +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda + sha256: 3d584956604909ff5df353767f3a2a2f60e07d070b328d109f30ac40cd62df6c + md5: 18335a698559cdbcd86150a48bf54ba6 + depends: + - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 + constrains: + - binutils_impl_linux-64 2.45.1 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 728002 + timestamp: 1774197446916 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.5-hecca717_0.conda + sha256: e8c2b57f6aacabdf2f1b0924bd4831ce5071ba080baa4a9e8c0d720588b6794c + md5: 49f570f3bc4c874a06ea69b7225753af + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - expat 2.7.5.* + license: MIT + license_family: MIT + purls: [] + size: 76624 + timestamp: 1774719175983 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.7.5-hcc62823_0.conda + sha256: 341d8a457a8342c396a8ac788da2639cbc8b62568f6ba2a3d322d1ace5aa9e16 + md5: 1d6e71b8c73711e28ffe207acdc4e2f8 + depends: + - __osx >=11.0 + constrains: + - expat 2.7.5.* + license: MIT + license_family: MIT + purls: [] + size: 74797 + timestamp: 1774719557730 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.5-hf6b4638_0.conda + sha256: 06780dec91dd25770c8cf01e158e1062fbf7c576b1406427475ce69a8af75b7e + md5: a32123f93e168eaa4080d87b0fb5da8a + depends: + - __osx >=11.0 + constrains: + - expat 2.7.5.* + license: MIT + license_family: MIT + purls: [] + size: 68192 + timestamp: 1774719211725 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 + md5: a360c33a5abe61c07959e449fa1453eb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: MIT + license_family: MIT + purls: [] + size: 58592 + timestamp: 1769456073053 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.5.2-hd1f9c09_0.conda + sha256: 951958d1792238006fdc6fce7f71f1b559534743b26cc1333497d46e5903a2d6 + md5: 66a0dc7464927d0853b590b6f53ba3ea + depends: + - __osx >=10.13 + license: MIT + license_family: MIT + purls: [] + size: 53583 + timestamp: 1769456300951 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda + sha256: 6686a26466a527585e6a75cc2a242bf4a3d97d6d6c86424a441677917f28bec7 + md5: 43c04d9cb46ef176bb2a4c77e324d599 + depends: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: [] + size: 40979 + timestamp: 1769456747661 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda + sha256: faf7d2017b4d718951e3a59d081eb09759152f93038479b768e3d612688f83f5 + md5: 0aa00f03f9e39fb9876085dee11a85d4 + depends: + - __glibc >=2.17,<3.0.a0 + - _openmp_mutex >=4.5 + constrains: + - libgcc-ng ==15.2.0=*_18 + - libgomp 15.2.0 he0feb66_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 1041788 + timestamp: 1771378212382 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda + sha256: e318a711400f536c81123e753d4c797a821021fb38970cebfb3f454126016893 + md5: d5e96b1ed75ca01906b3d2469b4ce493 + depends: + - libgcc 15.2.0 he0feb66_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 27526 + timestamp: 1771378224552 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda + sha256: 21337ab58e5e0649d869ab168d4e609b033509de22521de1bfed0c031bfc5110 + md5: 239c5e9546c38a1e884d69effcf4c882 + depends: + - __glibc >=2.17,<3.0.a0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 603262 + timestamp: 1771378117851 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda + sha256: 755c55ebab181d678c12e49cced893598f2bab22d582fbbf4d8b83c18be207eb + md5: c7c83eecbb72d88b940c249af56c8b17 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + constrains: + - xz 5.8.2.* + license: 0BSD + purls: [] + size: 113207 + timestamp: 1768752626120 +- conda: https://conda.anaconda.org/conda-forge/osx-64/liblzma-5.8.2-h11316ed_0.conda + sha256: 7ab3c98abd3b5d5ec72faa8d9f5d4b50dcee4970ed05339bc381861199dabb41 + md5: 688a0c3d57fa118b9c97bf7e471ab46c + depends: + - __osx >=10.13 + constrains: + - xz 5.8.2.* + license: 0BSD + purls: [] + size: 105482 + timestamp: 1768753411348 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblzma-5.8.2-h8088a28_0.conda + sha256: 7bfc7ffb2d6a9629357a70d4eadeadb6f88fa26ebc28f606b1c1e5e5ed99dc7e + md5: 009f0d956d7bfb00de86901d16e486c7 + depends: + - __osx >=11.0 + constrains: + - xz 5.8.2.* + license: 0BSD + purls: [] + size: 92242 + timestamp: 1768752982486 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda + sha256: fe171ed5cf5959993d43ff72de7596e8ac2853e9021dec0344e583734f1e0843 + md5: 2c21e66f50753a083cbe6b80f38268fa + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 92400 + timestamp: 1769482286018 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libmpdec-4.0.0-hf3981d6_1.conda + sha256: 1096c740109386607938ab9f09a7e9bca06d86770a284777586d6c378b8fb3fd + md5: ec88ba8a245855935b871a7324373105 + depends: + - __osx >=10.13 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 79899 + timestamp: 1769482558610 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmpdec-4.0.0-h84a0fba_1.conda + sha256: 1089c7f15d5b62c622625ec6700732ece83be8b705da8c6607f4dabb0c4bd6d2 + md5: 57c4be259f5e0b99a5983799a228ae55 + depends: + - __osx >=11.0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 73690 + timestamp: 1769482560514 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda + sha256: 927fe72b054277cde6cb82597d0fcf6baf127dcbce2e0a9d8925a68f1265eef5 + md5: d864d34357c3b65a4b731f78c0801dc4 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: LGPL-2.1-only + license_family: GPL + purls: [] + size: 33731 + timestamp: 1750274110928 +- pypi: https://files.pythonhosted.org/packages/01/99/f85130582f05dcf0c8902f3d629270231d2f4afdfc567f8305a952ac7f14/librt-0.8.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: librt + version: 0.8.1 + sha256: 97c2b54ff6717a7a563b72627990bec60d8029df17df423f0ed37d56a17a176b + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/1b/18/25e991cd5640c9fb0f8d91b18797b29066b792f17bf8493da183bf5caabe/librt-0.8.1-cp314-cp314-macosx_11_0_arm64.whl + name: librt + version: 0.8.1 + sha256: 228c2409c079f8c11fb2e5d7b277077f694cb93443eb760e00b3b83cb8b3176c + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/7c/5f/63f5fa395c7a8a93558c0904ba8f1c8d1b997ca6a3de61bc7659970d66bf/librt-0.8.1-cp310-cp310-macosx_10_9_x86_64.whl + name: librt + version: 0.8.1 + sha256: 81fd938344fecb9373ba1b155968c8a329491d2ce38e7ddb76f30ffb938f12dc + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/c9/6a/907ef6800f7bca71b525a05f1839b21f708c09043b1c6aa77b6b827b3996/librt-0.8.1-cp314-cp314-macosx_10_13_x86_64.whl + name: librt + version: 0.8.1 + sha256: 6cfa7fe54fd4d1f47130017351a959fe5804bda7a0bc7e07a2cdbc3fdd28d34f + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/d1/96/ef04902aad1424fd7299b62d1890e803e6ab4018c3044dca5922319c4b97/librt-0.8.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: librt + version: 0.8.1 + sha256: 6b1977c4ea97ce5eb7755a78fae68d87e4102e4aaf54985e8b56806849cc06a3 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/ff/e0/0472cf37267b5920eff2f292ccfaede1886288ce35b7f3203d8de00abfe6/librt-0.8.1-cp310-cp310-macosx_11_0_arm64.whl + name: librt + version: 0.8.1 + sha256: 5db05697c82b3a2ec53f6e72b2ed373132b0c2e05135f0696784e97d7f5d48e7 + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda + sha256: d716847b7deca293d2e49ed1c8ab9e4b9e04b9d780aea49a97c26925b28a7993 + md5: fd893f6a3002a635b5e50ceb9dd2c0f4 + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=78.2,<79.0a0 + - libgcc >=14 + - libzlib >=1.3.1,<2.0a0 + license: blessing + purls: [] + size: 951405 + timestamp: 1772818874251 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.52.0-h77d7759_0.conda + sha256: f500d1cd50cfcd288d02b8fc3c3b7ecf8de6fec7b86e57ea058def02908e4231 + md5: d553eb96758e038b04027b30fe314b2d + depends: + - __osx >=11.0 + - libzlib >=1.3.1,<2.0a0 + license: blessing + purls: [] + size: 996526 + timestamp: 1772819669038 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.52.0-h1ae2325_0.conda + sha256: beb0fd5594d6d7c7cd42c992b6bb4d66cbb39d6c94a8234f15956da99a04306c + md5: f6233a3fddc35a2ec9f617f79d6f3d71 + depends: + - __osx >=11.0 + - icu >=78.2,<79.0a0 + - libzlib >=1.3.1,<2.0a0 + license: blessing + purls: [] + size: 918420 + timestamp: 1772819478684 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda + sha256: 78668020064fdaa27e9ab65cd2997e2c837b564ab26ce3bf0e58a2ce1a525c6e + md5: 1b08cd684f34175e4514474793d44bcb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc 15.2.0 he0feb66_18 + constrains: + - libstdcxx-ng ==15.2.0=*_18 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 5852330 + timestamp: 1771378262446 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda + sha256: bc1b08c92626c91500fd9f26f2c797f3eb153b627d53e9c13cd167f1e12b2829 + md5: 38ffe67b78c9d4de527be8315e5ada2c + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 40297 + timestamp: 1775052476770 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + sha256: 6ae68e0b86423ef188196fff6207ed0c8195dd84273cb5623b85aa08033a410c + md5: 5aa797f8787fe7a17d1b0821485b5adc + depends: + - libgcc-ng >=12 + license: LGPL-2.1-or-later + purls: [] + size: 100393 + timestamp: 1702724383534 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda + sha256: 55044c403570f0dc26e6364de4dc5368e5f3fc7ff103e867c487e2b5ab2bcda9 + md5: d87ff7921124eccd67248aa483c23fec + depends: + - __glibc >=2.17,<3.0.a0 + constrains: + - zlib 1.3.2 *_2 + license: Zlib + license_family: Other + purls: [] + size: 63629 + timestamp: 1774072609062 +- conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.3.2-hbb4bfdb_2.conda + sha256: 4c6da089952b2d70150c74234679d6f7ac04f4a98f9432dec724968f912691e7 + md5: 30439ff30578e504ee5e0b390afc8c65 + depends: + - __osx >=11.0 + constrains: + - zlib 1.3.2 *_2 + license: Zlib + license_family: Other + purls: [] + size: 59000 + timestamp: 1774073052242 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.3.2-h8088a28_2.conda + sha256: 361415a698514b19a852f5d1123c5da746d4642139904156ddfca7c922d23a05 + md5: bc5a5721b6439f2f62a84f2548136082 + depends: + - __osx >=11.0 + constrains: + - zlib 1.3.2 *_2 + license: Zlib + license_family: Other + purls: [] + size: 47759 + timestamp: 1774072956767 +- pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + name: locket + version: 1.0.0 + sha256: b6c819a722f7b6bd955b80781788e4a66a55628b858d347536b7e81325a3a5e3 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*' +- pypi: https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl + name: markdown-it-py + version: 4.0.0 + sha256: 87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147 + requires_dist: + - mdurl~=0.1 + - psutil ; extra == 'benchmarking' + - pytest ; extra == 'benchmarking' + - pytest-benchmark ; extra == 'benchmarking' + - commonmark~=0.9 ; extra == 'compare' + - markdown~=3.4 ; extra == 'compare' + - mistletoe~=1.0 ; extra == 'compare' + - mistune~=3.0 ; extra == 'compare' + - panflute~=2.3 ; extra == 'compare' + - markdown-it-pyrs ; extra == 'compare' + - linkify-it-py>=1,<3 ; extra == 'linkify' + - mdit-py-plugins>=0.5.0 ; extra == 'plugins' + - gprof2dot ; extra == 'profiling' + - mdit-py-plugins>=0.5.0 ; extra == 'rtd' + - myst-parser ; extra == 'rtd' + - pyyaml ; extra == 'rtd' + - sphinx ; extra == 'rtd' + - sphinx-copybutton ; extra == 'rtd' + - sphinx-design ; extra == 'rtd' + - sphinx-book-theme~=1.0 ; extra == 'rtd' + - jupyter-sphinx ; extra == 'rtd' + - ipykernel ; extra == 'rtd' + - coverage ; extra == 'testing' + - pytest ; extra == 'testing' + - pytest-cov ; extra == 'testing' + - pytest-regressions ; extra == 'testing' + - requests ; extra == 'testing' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl + name: markupsafe + version: 3.0.3 + sha256: eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: markupsafe + version: 3.0.3 + sha256: 457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/98/1b/fbd8eed11021cabd9226c37342fa6ca4e8a98d8188a8d9b66740494960e4/markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl + name: markupsafe + version: 3.0.3 + sha256: e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/af/cd/ce6e848bbf2c32314c9b237839119c5a564a59725b53157c856e90937b7a/markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: markupsafe + version: 3.0.3 + sha256: f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl + name: markupsafe + version: 3.0.3 + sha256: c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/e8/4b/3541d44f3937ba468b75da9eebcae497dcf67adb65caa16760b0a6807ebb/markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl + name: markupsafe + version: 3.0.3 + sha256: 2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl + name: mdurl + version: 0.1.2 + sha256: 84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/b6/9e/8d9f6b9746f8ede78b0a4e4b8908e4d80bd609fca0b3e3195a07dda29534/minio-7.2.11-py3-none-any.whl + name: minio + version: 7.2.11 + sha256: 153582ed52ff3b5005ba558e1f25bfe1e9e834f7f0745e594777f28e3e81e1a0 + requires_dist: + - certifi + - urllib3 + - argon2-cffi + - pycryptodome + - typing-extensions + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/6f/75/2c24517d4b2ce9e4917362d24f274d3d541346af764430249ddcc4cb3a08/mmh3-5.2.1-cp314-cp314-macosx_10_15_x86_64.whl + name: mmh3 + version: 5.2.1 + sha256: 72d1cc63bcc91e14933f77d51b3df899d6a07d184ec515ea7f56bff659e124d7 + requires_dist: + - pytest==9.0.2 ; extra == 'test' + - pytest-sugar==1.1.1 ; extra == 'test' + - actionlint-py==1.7.11.24 ; extra == 'lint' + - clang-format==22.1.0 ; extra == 'lint' + - codespell==2.4.1 ; extra == 'lint' + - pylint==4.0.5 ; extra == 'lint' + - ruff==0.15.4 ; extra == 'lint' + - mypy==1.19.1 ; extra == 'type' + - myst-parser==5.0.0 ; extra == 'docs' + - shibuya==2026.1.9 ; extra == 'docs' + - sphinx==8.2.3 ; extra == 'docs' + - sphinx-copybutton==0.5.2 ; extra == 'docs' + - pymmh3==0.0.5 ; extra == 'benchmark' + - pyperf==2.10.0 ; extra == 'benchmark' + - xxhash==3.6.0 ; extra == 'benchmark' + - matplotlib==3.10.8 ; extra == 'plot' + - pandas==3.0.1 ; extra == 'plot' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/b6/71/c1a60c1652b8813ef9de6d289784847355417ee0f2980bca002fe87f4ae5/mmh3-5.2.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + name: mmh3 + version: 5.2.1 + sha256: 8ff038d52ef6aa0f309feeba00c5095c9118d0abf787e8e8454d6048db2037fc + requires_dist: + - pytest==9.0.2 ; extra == 'test' + - pytest-sugar==1.1.1 ; extra == 'test' + - actionlint-py==1.7.11.24 ; extra == 'lint' + - clang-format==22.1.0 ; extra == 'lint' + - codespell==2.4.1 ; extra == 'lint' + - pylint==4.0.5 ; extra == 'lint' + - ruff==0.15.4 ; extra == 'lint' + - mypy==1.19.1 ; extra == 'type' + - myst-parser==5.0.0 ; extra == 'docs' + - shibuya==2026.1.9 ; extra == 'docs' + - sphinx==8.2.3 ; extra == 'docs' + - sphinx-copybutton==0.5.2 ; extra == 'docs' + - pymmh3==0.0.5 ; extra == 'benchmark' + - pyperf==2.10.0 ; extra == 'benchmark' + - xxhash==3.6.0 ; extra == 'benchmark' + - matplotlib==3.10.8 ; extra == 'plot' + - pandas==3.0.1 ; extra == 'plot' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/bf/b9/e4a360164365ac9f07a25f0f7928e3a66eb9ecc989384060747aa170e6aa/mmh3-5.2.1-cp314-cp314-macosx_11_0_arm64.whl + name: mmh3 + version: 5.2.1 + sha256: e8b4b5580280b9265af3e0409974fb79c64cf7523632d03fbf11df18f8b0181e + requires_dist: + - pytest==9.0.2 ; extra == 'test' + - pytest-sugar==1.1.1 ; extra == 'test' + - actionlint-py==1.7.11.24 ; extra == 'lint' + - clang-format==22.1.0 ; extra == 'lint' + - codespell==2.4.1 ; extra == 'lint' + - pylint==4.0.5 ; extra == 'lint' + - ruff==0.15.4 ; extra == 'lint' + - mypy==1.19.1 ; extra == 'type' + - myst-parser==5.0.0 ; extra == 'docs' + - shibuya==2026.1.9 ; extra == 'docs' + - sphinx==8.2.3 ; extra == 'docs' + - sphinx-copybutton==0.5.2 ; extra == 'docs' + - pymmh3==0.0.5 ; extra == 'benchmark' + - pyperf==2.10.0 ; extra == 'benchmark' + - xxhash==3.6.0 ; extra == 'benchmark' + - matplotlib==3.10.8 ; extra == 'plot' + - pandas==3.0.1 ; extra == 'plot' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/c6/b1/e20d5f0d19c4c0f3df213fa7dcfa0942c4fb127d38e11f398ae8ddf6cccc/mmh3-5.2.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + name: mmh3 + version: 5.2.1 + sha256: fb9d44c25244e11c8be3f12c938ca8ba8404620ef8092245d2093c6ab3df260f + requires_dist: + - pytest==9.0.2 ; extra == 'test' + - pytest-sugar==1.1.1 ; extra == 'test' + - actionlint-py==1.7.11.24 ; extra == 'lint' + - clang-format==22.1.0 ; extra == 'lint' + - codespell==2.4.1 ; extra == 'lint' + - pylint==4.0.5 ; extra == 'lint' + - ruff==0.15.4 ; extra == 'lint' + - mypy==1.19.1 ; extra == 'type' + - myst-parser==5.0.0 ; extra == 'docs' + - shibuya==2026.1.9 ; extra == 'docs' + - sphinx==8.2.3 ; extra == 'docs' + - sphinx-copybutton==0.5.2 ; extra == 'docs' + - pymmh3==0.0.5 ; extra == 'benchmark' + - pyperf==2.10.0 ; extra == 'benchmark' + - xxhash==3.6.0 ; extra == 'benchmark' + - matplotlib==3.10.8 ; extra == 'plot' + - pandas==3.0.1 ; extra == 'plot' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/cc/bf/5404c2fd6ac84819e8ff1b7e34437b37cf55a2b11318894909e7bb88de3f/mmh3-5.2.1-cp310-cp310-macosx_10_9_x86_64.whl + name: mmh3 + version: 5.2.1 + sha256: 30e4d2084df019880d55f6f7bea35328d9b464ebee090baa372c096dc77556fb + requires_dist: + - pytest==9.0.2 ; extra == 'test' + - pytest-sugar==1.1.1 ; extra == 'test' + - actionlint-py==1.7.11.24 ; extra == 'lint' + - clang-format==22.1.0 ; extra == 'lint' + - codespell==2.4.1 ; extra == 'lint' + - pylint==4.0.5 ; extra == 'lint' + - ruff==0.15.4 ; extra == 'lint' + - mypy==1.19.1 ; extra == 'type' + - myst-parser==5.0.0 ; extra == 'docs' + - shibuya==2026.1.9 ; extra == 'docs' + - sphinx==8.2.3 ; extra == 'docs' + - sphinx-copybutton==0.5.2 ; extra == 'docs' + - pymmh3==0.0.5 ; extra == 'benchmark' + - pyperf==2.10.0 ; extra == 'benchmark' + - xxhash==3.6.0 ; extra == 'benchmark' + - matplotlib==3.10.8 ; extra == 'plot' + - pandas==3.0.1 ; extra == 'plot' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/de/0b/52bffad0b52ae4ea53e222b594bd38c08ecac1fc410323220a7202e43da5/mmh3-5.2.1-cp310-cp310-macosx_11_0_arm64.whl + name: mmh3 + version: 5.2.1 + sha256: 0bbc17250b10d3466875a40a52520a6bac3c02334ca709207648abd3c223ed5c + requires_dist: + - pytest==9.0.2 ; extra == 'test' + - pytest-sugar==1.1.1 ; extra == 'test' + - actionlint-py==1.7.11.24 ; extra == 'lint' + - clang-format==22.1.0 ; extra == 'lint' + - codespell==2.4.1 ; extra == 'lint' + - pylint==4.0.5 ; extra == 'lint' + - ruff==0.15.4 ; extra == 'lint' + - mypy==1.19.1 ; extra == 'type' + - myst-parser==5.0.0 ; extra == 'docs' + - shibuya==2026.1.9 ; extra == 'docs' + - sphinx==8.2.3 ; extra == 'docs' + - sphinx-copybutton==0.5.2 ; extra == 'docs' + - pymmh3==0.0.5 ; extra == 'benchmark' + - pyperf==2.10.0 ; extra == 'benchmark' + - xxhash==3.6.0 ; extra == 'benchmark' + - matplotlib==3.10.8 ; extra == 'plot' + - pandas==3.0.1 ; extra == 'plot' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/5b/e1/2b720cc341325c00be44e1ed59e7cfeae2678329fbf5aa68f5bda57fe728/msgpack-1.1.2-cp310-cp310-macosx_11_0_arm64.whl + name: msgpack + version: 1.1.2 + sha256: a605409040f2da88676e9c9e5853b3449ba8011973616189ea5ee55ddbc5bc87 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/b7/09/2a06956383c0fdebaef5aa9246e2356776f12ea6f2a44bd1368abf0e46c4/msgpack-1.1.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: msgpack + version: 1.1.2 + sha256: 365c0bbe981a27d8932da71af63ef86acc59ed5c01ad929e09a0b88c6294e28a + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/f5/a2/3b68a9e769db68668b25c6108444a35f9bd163bb848c0650d516761a59c0/msgpack-1.1.2-cp310-cp310-macosx_10_9_x86_64.whl + name: msgpack + version: 1.1.2 + sha256: 0051fffef5a37ca2cd16978ae4f0aef92f164df86823871b5162812bebecd8e2 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/31/5c/08c7f7fe311f32e83f7621cd3f99d805f45519cd06fafb247628b861da7d/multidict-6.7.1-cp310-cp310-macosx_11_0_arm64.whl + name: multidict + version: 6.7.1 + sha256: cdea2e7b2456cfb6694fb113066fd0ec7ea4d67e3a35e1f4cbeea0b448bf5872 + requires_dist: + - typing-extensions>=4.1.0 ; python_full_version < '3.11' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/4b/ac/b605473de2bb404e742f2cc3583d12aedb2352a70e49ae8fce455b50c5aa/multidict-6.7.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: multidict + version: 6.7.1 + sha256: 9b0d9b91d1aa44db9c1f1ecd0d9d2ae610b2f4f856448664e01a3b35899f3f92 + requires_dist: + - typing-extensions>=4.1.0 ; python_full_version < '3.11' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/ef/04/9de3f8077852e3d438215c81e9b691244532d2e05b4270e89ce67b7d103c/multidict-6.7.1-cp310-cp310-macosx_10_9_x86_64.whl + name: multidict + version: 6.7.1 + sha256: 974e72a2474600827abaeda71af0c53d9ebbc3c2eb7da37b37d7829ae31232d8 + requires_dist: + - typing-extensions>=4.1.0 ; python_full_version < '3.11' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/4d/a2/a965c8c3fcd4fa8b84ba0d46606181b0d0a1d50f274c67877f3e9ed4882c/mypy-1.20.0-cp310-cp310-macosx_10_9_x86_64.whl + name: mypy + version: 1.20.0 + sha256: d99f515f95fd03a90875fdb2cca12ff074aa04490db4d190905851bdf8a549a8 + requires_dist: + - typing-extensions>=4.6.0 + - mypy-extensions>=1.0.0 + - pathspec>=1.0.0 + - tomli>=1.1.0 ; python_full_version < '3.11' + - librt>=0.8.0 ; platform_python_implementation != 'PyPy' + - psutil>=4.0 ; extra == 'dmypy' + - setuptools>=50 ; extra == 'mypyc' + - lxml ; extra == 'reports' + - pip ; extra == 'install-types' + - orjson ; extra == 'faster-cache' + - ast-serialize>=0.1.1,<1.0.0 ; extra == 'native-parser' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/4e/0e/6ca4a84cbed9e62384bc0b2974c90395ece5ed672393e553996501625fc5/mypy-1.20.0-cp314-cp314-macosx_10_15_x86_64.whl + name: mypy + version: 1.20.0 + sha256: 0f42dfaab7ec1baff3b383ad7af562ab0de573c5f6edb44b2dab016082b89948 + requires_dist: + - typing-extensions>=4.6.0 + - mypy-extensions>=1.0.0 + - pathspec>=1.0.0 + - tomli>=1.1.0 ; python_full_version < '3.11' + - librt>=0.8.0 ; platform_python_implementation != 'PyPy' + - psutil>=4.0 ; extra == 'dmypy' + - setuptools>=50 ; extra == 'mypyc' + - lxml ; extra == 'reports' + - pip ; extra == 'install-types' + - orjson ; extra == 'faster-cache' + - ast-serialize>=0.1.1,<1.0.0 ; extra == 'native-parser' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/53/6e/043477501deeb8eabbab7f1a2f6cac62cfb631806dc1d6862a04a7f5011b/mypy-1.20.0-cp310-cp310-macosx_11_0_arm64.whl + name: mypy + version: 1.20.0 + sha256: bd0212976dc57a5bfeede7c219e7cd66568a32c05c9129686dd487c059c1b88a + requires_dist: + - typing-extensions>=4.6.0 + - mypy-extensions>=1.0.0 + - pathspec>=1.0.0 + - tomli>=1.1.0 ; python_full_version < '3.11' + - librt>=0.8.0 ; platform_python_implementation != 'PyPy' + - psutil>=4.0 ; extra == 'dmypy' + - setuptools>=50 ; extra == 'mypyc' + - lxml ; extra == 'reports' + - pip ; extra == 'install-types' + - orjson ; extra == 'faster-cache' + - ast-serialize>=0.1.1,<1.0.0 ; extra == 'native-parser' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/6b/8d/93491ff7b79419edc7eabf95cb3b3f7490e2e574b2855c7c7e7394ff933f/mypy-1.20.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: mypy + version: 1.20.0 + sha256: 7d3243c406773185144527f83be0e0aefc7bf4601b0b2b956665608bf7c98a83 + requires_dist: + - typing-extensions>=4.6.0 + - mypy-extensions>=1.0.0 + - pathspec>=1.0.0 + - tomli>=1.1.0 ; python_full_version < '3.11' + - librt>=0.8.0 ; platform_python_implementation != 'PyPy' + - psutil>=4.0 ; extra == 'dmypy' + - setuptools>=50 ; extra == 'mypyc' + - lxml ; extra == 'reports' + - pip ; extra == 'install-types' + - orjson ; extra == 'faster-cache' + - ast-serialize>=0.1.1,<1.0.0 ; extra == 'native-parser' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/7d/c5/5fe9d8a729dd9605064691816243ae6c49fde0bd28f6e5e17f6a24203c43/mypy-1.20.0-cp314-cp314-macosx_11_0_arm64.whl + name: mypy + version: 1.20.0 + sha256: 31b5dbb55293c1bd27c0fc813a0d2bb5ceef9d65ac5afa2e58f829dab7921fd5 + requires_dist: + - typing-extensions>=4.6.0 + - mypy-extensions>=1.0.0 + - pathspec>=1.0.0 + - tomli>=1.1.0 ; python_full_version < '3.11' + - librt>=0.8.0 ; platform_python_implementation != 'PyPy' + - psutil>=4.0 ; extra == 'dmypy' + - setuptools>=50 ; extra == 'mypyc' + - lxml ; extra == 'reports' + - pip ; extra == 'install-types' + - orjson ; extra == 'faster-cache' + - ast-serialize>=0.1.1,<1.0.0 ; extra == 'native-parser' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/fa/9d/2860be7355c45247ccc0be1501c91176318964c2a137bd4743f58ce6200e/mypy-1.20.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: mypy + version: 1.20.0 + sha256: 02cca0761c75b42a20a2757ae58713276605eb29a08dd8a6e092aa347c4115ca + requires_dist: + - typing-extensions>=4.6.0 + - mypy-extensions>=1.0.0 + - pathspec>=1.0.0 + - tomli>=1.1.0 ; python_full_version < '3.11' + - librt>=0.8.0 ; platform_python_implementation != 'PyPy' + - psutil>=4.0 ; extra == 'dmypy' + - setuptools>=50 ; extra == 'mypyc' + - lxml ; extra == 'reports' + - pip ; extra == 'install-types' + - orjson ; extra == 'faster-cache' + - ast-serialize>=0.1.1,<1.0.0 ; extra == 'native-parser' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl + name: mypy-extensions + version: 1.1.0 + sha256: 1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505 + requires_python: '>=3.8' +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda + sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586 + md5: 47e340acb35de30501a76c7c799c41d7 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + license: X11 AND BSD-3-Clause + purls: [] + size: 891641 + timestamp: 1738195959188 +- conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-h0622a9a_3.conda + sha256: ea4a5d27ded18443749aefa49dc79f6356da8506d508b5296f60b8d51e0c4bd9 + md5: ced34dd9929f491ca6dab6a2927aff25 + depends: + - __osx >=10.13 + license: X11 AND BSD-3-Clause + purls: [] + size: 822259 + timestamp: 1738196181298 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda + sha256: 2827ada40e8d9ca69a153a45f7fd14f32b2ead7045d3bbb5d10964898fe65733 + md5: 068d497125e4bf8a66bf707254fff5ae + depends: + - __osx >=11.0 + license: X11 AND BSD-3-Clause + purls: [] + size: 797030 + timestamp: 1738196177597 +- pypi: https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl + name: numpy + version: 2.2.6 + sha256: 8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl + name: numpy + version: 2.2.6 + sha256: b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: numpy + version: 2.2.6 + sha256: fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/4c/39/8a320264a84404c74cc7e79715de85d6130fa07a0898f67fb5cd5bd79908/numpy-2.4.4-cp314-cp314-macosx_11_0_arm64.whl + name: numpy + version: 2.4.4 + sha256: 2483e4584a1cb3092da4470b38866634bafb223cbcd551ee047633fd2584599a + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/6e/06/c54062f85f673dd5c04cbe2f14c3acb8c8b95e3384869bb8cc9bff8cb9df/numpy-2.4.4-cp314-cp314-macosx_10_15_x86_64.whl + name: numpy + version: 2.4.4 + sha256: f169b9a863d34f5d11b8698ead99febeaa17a13ca044961aa8e2662a6c7766a0 + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/98/7c/21252050676612625449b4807d6b695b9ce8a7c9e1c197ee6216c8a65c7c/numpy-2.4.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl + name: numpy + version: 2.4.4 + sha256: 27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d + requires_python: '>=3.11' +- pypi: https://files.pythonhosted.org/packages/be/9c/92789c596b8df838baa98fa71844d84283302f7604ed565dafe5a6b5041a/oauthlib-3.3.1-py3-none-any.whl + name: oauthlib + version: 3.3.1 + sha256: 88119c938d2b8fb88561af5f6ee0eec8cc8d552b7bb1f712743136eb7523b7a1 + requires_dist: + - cryptography>=3.0.0 ; extra == 'rsa' + - cryptography>=3.0.0 ; extra == 'signedtoken' + - pyjwt>=2.0.0,<3 ; extra == 'signedtoken' + - blinker>=1.4.0 ; extra == 'signals' + requires_python: '>=3.8' +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda + sha256: 44c877f8af015332a5d12f5ff0fb20ca32f896526a7d0cdb30c769df1144fb5c + md5: f61eb8cd60ff9057122a3d338b99c00f + depends: + - __glibc >=2.17,<3.0.a0 + - ca-certificates + - libgcc >=14 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 3164551 + timestamp: 1769555830639 +- conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.6.1-hb6871ef_1.conda + sha256: e02e5639b0e4d6d4fcf0f3b082642844fb5a37316f5b0a1126c6271347462e90 + md5: 30bb8d08b99b9a7600d39efb3559fff0 + depends: + - __osx >=10.13 + - ca-certificates + license: Apache-2.0 + license_family: Apache + purls: [] + size: 2777136 + timestamp: 1769557662405 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda + sha256: 361f5c5e60052abc12bdd1b50d7a1a43e6a6653aab99a2263bf2288d709dcf67 + md5: f4f6ad63f98f64191c3e77c5f5f29d76 + depends: + - __osx >=11.0 + - ca-certificates + license: Apache-2.0 + license_family: Apache + purls: [] + size: 3104268 + timestamp: 1769556384749 +- pypi: https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl + name: packaging + version: '26.0' + sha256: b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/04/fd/74903979833db8390b73b3a8a7d30d146d710bd32703724dd9083950386f/pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl + name: pandas + version: 2.3.3 + sha256: ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0 + requires_dist: + - numpy>=1.22.4 ; python_full_version < '3.11' + - numpy>=1.23.2 ; python_full_version == '3.11.*' + - numpy>=1.26.0 ; python_full_version >= '3.12' + - python-dateutil>=2.8.2 + - pytz>=2020.1 + - tzdata>=2022.7 + - hypothesis>=6.46.1 ; extra == 'test' + - pytest>=7.3.2 ; extra == 'test' + - pytest-xdist>=2.2.0 ; extra == 'test' + - pyarrow>=10.0.1 ; extra == 'pyarrow' + - bottleneck>=1.3.6 ; extra == 'performance' + - numba>=0.56.4 ; extra == 'performance' + - numexpr>=2.8.4 ; extra == 'performance' + - scipy>=1.10.0 ; extra == 'computation' + - xarray>=2022.12.0 ; extra == 'computation' + - fsspec>=2022.11.0 ; extra == 'fss' + - s3fs>=2022.11.0 ; extra == 'aws' + - gcsfs>=2022.11.0 ; extra == 'gcp' + - pandas-gbq>=0.19.0 ; extra == 'gcp' + - odfpy>=1.4.1 ; extra == 'excel' + - openpyxl>=3.1.0 ; extra == 'excel' + - python-calamine>=0.1.7 ; extra == 'excel' + - pyxlsb>=1.0.10 ; extra == 'excel' + - xlrd>=2.0.1 ; extra == 'excel' + - xlsxwriter>=3.0.5 ; extra == 'excel' + - pyarrow>=10.0.1 ; extra == 'parquet' + - pyarrow>=10.0.1 ; extra == 'feather' + - tables>=3.8.0 ; extra == 'hdf5' + - pyreadstat>=1.2.0 ; extra == 'spss' + - sqlalchemy>=2.0.0 ; extra == 'postgresql' + - psycopg2>=2.9.6 ; extra == 'postgresql' + - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql' + - sqlalchemy>=2.0.0 ; extra == 'mysql' + - pymysql>=1.0.2 ; extra == 'mysql' + - sqlalchemy>=2.0.0 ; extra == 'sql-other' + - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other' + - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other' + - beautifulsoup4>=4.11.2 ; extra == 'html' + - html5lib>=1.1 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'xml' + - matplotlib>=3.6.3 ; extra == 'plot' + - jinja2>=3.1.2 ; extra == 'output-formatting' + - tabulate>=0.9.0 ; extra == 'output-formatting' + - pyqt5>=5.15.9 ; extra == 'clipboard' + - qtpy>=2.3.0 ; extra == 'clipboard' + - zstandard>=0.19.0 ; extra == 'compression' + - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard' + - adbc-driver-postgresql>=0.8.0 ; extra == 'all' + - adbc-driver-sqlite>=0.8.0 ; extra == 'all' + - beautifulsoup4>=4.11.2 ; extra == 'all' + - bottleneck>=1.3.6 ; extra == 'all' + - dataframe-api-compat>=0.1.7 ; extra == 'all' + - fastparquet>=2022.12.0 ; extra == 'all' + - fsspec>=2022.11.0 ; extra == 'all' + - gcsfs>=2022.11.0 ; extra == 'all' + - html5lib>=1.1 ; extra == 'all' + - hypothesis>=6.46.1 ; extra == 'all' + - jinja2>=3.1.2 ; extra == 'all' + - lxml>=4.9.2 ; extra == 'all' + - matplotlib>=3.6.3 ; extra == 'all' + - numba>=0.56.4 ; extra == 'all' + - numexpr>=2.8.4 ; extra == 'all' + - odfpy>=1.4.1 ; extra == 'all' + - openpyxl>=3.1.0 ; extra == 'all' + - pandas-gbq>=0.19.0 ; extra == 'all' + - psycopg2>=2.9.6 ; extra == 'all' + - pyarrow>=10.0.1 ; extra == 'all' + - pymysql>=1.0.2 ; extra == 'all' + - pyqt5>=5.15.9 ; extra == 'all' + - pyreadstat>=1.2.0 ; extra == 'all' + - pytest>=7.3.2 ; extra == 'all' + - pytest-xdist>=2.2.0 ; extra == 'all' + - python-calamine>=0.1.7 ; extra == 'all' + - pyxlsb>=1.0.10 ; extra == 'all' + - qtpy>=2.3.0 ; extra == 'all' + - scipy>=1.10.0 ; extra == 'all' + - s3fs>=2022.11.0 ; extra == 'all' + - sqlalchemy>=2.0.0 ; extra == 'all' + - tables>=3.8.0 ; extra == 'all' + - tabulate>=0.9.0 ; extra == 'all' + - xarray>=2022.12.0 ; extra == 'all' + - xlrd>=2.0.1 ; extra == 'all' + - xlsxwriter>=3.0.5 ; extra == 'all' + - zstandard>=0.19.0 ; extra == 'all' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/13/4f/66d99628ff8ce7857aca52fed8f0066ce209f96be2fede6cef9f84e8d04f/pandas-2.3.3-cp310-cp310-macosx_11_0_arm64.whl + name: pandas + version: 2.3.3 + sha256: e19d192383eab2f4ceb30b412b22ea30690c9e618f78870357ae1d682912015a + requires_dist: + - numpy>=1.22.4 ; python_full_version < '3.11' + - numpy>=1.23.2 ; python_full_version == '3.11.*' + - numpy>=1.26.0 ; python_full_version >= '3.12' + - python-dateutil>=2.8.2 + - pytz>=2020.1 + - tzdata>=2022.7 + - hypothesis>=6.46.1 ; extra == 'test' + - pytest>=7.3.2 ; extra == 'test' + - pytest-xdist>=2.2.0 ; extra == 'test' + - pyarrow>=10.0.1 ; extra == 'pyarrow' + - bottleneck>=1.3.6 ; extra == 'performance' + - numba>=0.56.4 ; extra == 'performance' + - numexpr>=2.8.4 ; extra == 'performance' + - scipy>=1.10.0 ; extra == 'computation' + - xarray>=2022.12.0 ; extra == 'computation' + - fsspec>=2022.11.0 ; extra == 'fss' + - s3fs>=2022.11.0 ; extra == 'aws' + - gcsfs>=2022.11.0 ; extra == 'gcp' + - pandas-gbq>=0.19.0 ; extra == 'gcp' + - odfpy>=1.4.1 ; extra == 'excel' + - openpyxl>=3.1.0 ; extra == 'excel' + - python-calamine>=0.1.7 ; extra == 'excel' + - pyxlsb>=1.0.10 ; extra == 'excel' + - xlrd>=2.0.1 ; extra == 'excel' + - xlsxwriter>=3.0.5 ; extra == 'excel' + - pyarrow>=10.0.1 ; extra == 'parquet' + - pyarrow>=10.0.1 ; extra == 'feather' + - tables>=3.8.0 ; extra == 'hdf5' + - pyreadstat>=1.2.0 ; extra == 'spss' + - sqlalchemy>=2.0.0 ; extra == 'postgresql' + - psycopg2>=2.9.6 ; extra == 'postgresql' + - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql' + - sqlalchemy>=2.0.0 ; extra == 'mysql' + - pymysql>=1.0.2 ; extra == 'mysql' + - sqlalchemy>=2.0.0 ; extra == 'sql-other' + - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other' + - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other' + - beautifulsoup4>=4.11.2 ; extra == 'html' + - html5lib>=1.1 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'xml' + - matplotlib>=3.6.3 ; extra == 'plot' + - jinja2>=3.1.2 ; extra == 'output-formatting' + - tabulate>=0.9.0 ; extra == 'output-formatting' + - pyqt5>=5.15.9 ; extra == 'clipboard' + - qtpy>=2.3.0 ; extra == 'clipboard' + - zstandard>=0.19.0 ; extra == 'compression' + - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard' + - adbc-driver-postgresql>=0.8.0 ; extra == 'all' + - adbc-driver-sqlite>=0.8.0 ; extra == 'all' + - beautifulsoup4>=4.11.2 ; extra == 'all' + - bottleneck>=1.3.6 ; extra == 'all' + - dataframe-api-compat>=0.1.7 ; extra == 'all' + - fastparquet>=2022.12.0 ; extra == 'all' + - fsspec>=2022.11.0 ; extra == 'all' + - gcsfs>=2022.11.0 ; extra == 'all' + - html5lib>=1.1 ; extra == 'all' + - hypothesis>=6.46.1 ; extra == 'all' + - jinja2>=3.1.2 ; extra == 'all' + - lxml>=4.9.2 ; extra == 'all' + - matplotlib>=3.6.3 ; extra == 'all' + - numba>=0.56.4 ; extra == 'all' + - numexpr>=2.8.4 ; extra == 'all' + - odfpy>=1.4.1 ; extra == 'all' + - openpyxl>=3.1.0 ; extra == 'all' + - pandas-gbq>=0.19.0 ; extra == 'all' + - psycopg2>=2.9.6 ; extra == 'all' + - pyarrow>=10.0.1 ; extra == 'all' + - pymysql>=1.0.2 ; extra == 'all' + - pyqt5>=5.15.9 ; extra == 'all' + - pyreadstat>=1.2.0 ; extra == 'all' + - pytest>=7.3.2 ; extra == 'all' + - pytest-xdist>=2.2.0 ; extra == 'all' + - python-calamine>=0.1.7 ; extra == 'all' + - pyxlsb>=1.0.10 ; extra == 'all' + - qtpy>=2.3.0 ; extra == 'all' + - scipy>=1.10.0 ; extra == 'all' + - s3fs>=2022.11.0 ; extra == 'all' + - sqlalchemy>=2.0.0 ; extra == 'all' + - tables>=3.8.0 ; extra == 'all' + - tabulate>=0.9.0 ; extra == 'all' + - xarray>=2022.12.0 ; extra == 'all' + - xlrd>=2.0.1 ; extra == 'all' + - xlsxwriter>=3.0.5 ; extra == 'all' + - zstandard>=0.19.0 ; extra == 'all' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/15/b2/0e62f78c0c5ba7e3d2c5945a82456f4fac76c480940f805e0b97fcbc2f65/pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + name: pandas + version: 2.3.3 + sha256: ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b + requires_dist: + - numpy>=1.22.4 ; python_full_version < '3.11' + - numpy>=1.23.2 ; python_full_version == '3.11.*' + - numpy>=1.26.0 ; python_full_version >= '3.12' + - python-dateutil>=2.8.2 + - pytz>=2020.1 + - tzdata>=2022.7 + - hypothesis>=6.46.1 ; extra == 'test' + - pytest>=7.3.2 ; extra == 'test' + - pytest-xdist>=2.2.0 ; extra == 'test' + - pyarrow>=10.0.1 ; extra == 'pyarrow' + - bottleneck>=1.3.6 ; extra == 'performance' + - numba>=0.56.4 ; extra == 'performance' + - numexpr>=2.8.4 ; extra == 'performance' + - scipy>=1.10.0 ; extra == 'computation' + - xarray>=2022.12.0 ; extra == 'computation' + - fsspec>=2022.11.0 ; extra == 'fss' + - s3fs>=2022.11.0 ; extra == 'aws' + - gcsfs>=2022.11.0 ; extra == 'gcp' + - pandas-gbq>=0.19.0 ; extra == 'gcp' + - odfpy>=1.4.1 ; extra == 'excel' + - openpyxl>=3.1.0 ; extra == 'excel' + - python-calamine>=0.1.7 ; extra == 'excel' + - pyxlsb>=1.0.10 ; extra == 'excel' + - xlrd>=2.0.1 ; extra == 'excel' + - xlsxwriter>=3.0.5 ; extra == 'excel' + - pyarrow>=10.0.1 ; extra == 'parquet' + - pyarrow>=10.0.1 ; extra == 'feather' + - tables>=3.8.0 ; extra == 'hdf5' + - pyreadstat>=1.2.0 ; extra == 'spss' + - sqlalchemy>=2.0.0 ; extra == 'postgresql' + - psycopg2>=2.9.6 ; extra == 'postgresql' + - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql' + - sqlalchemy>=2.0.0 ; extra == 'mysql' + - pymysql>=1.0.2 ; extra == 'mysql' + - sqlalchemy>=2.0.0 ; extra == 'sql-other' + - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other' + - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other' + - beautifulsoup4>=4.11.2 ; extra == 'html' + - html5lib>=1.1 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'xml' + - matplotlib>=3.6.3 ; extra == 'plot' + - jinja2>=3.1.2 ; extra == 'output-formatting' + - tabulate>=0.9.0 ; extra == 'output-formatting' + - pyqt5>=5.15.9 ; extra == 'clipboard' + - qtpy>=2.3.0 ; extra == 'clipboard' + - zstandard>=0.19.0 ; extra == 'compression' + - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard' + - adbc-driver-postgresql>=0.8.0 ; extra == 'all' + - adbc-driver-sqlite>=0.8.0 ; extra == 'all' + - beautifulsoup4>=4.11.2 ; extra == 'all' + - bottleneck>=1.3.6 ; extra == 'all' + - dataframe-api-compat>=0.1.7 ; extra == 'all' + - fastparquet>=2022.12.0 ; extra == 'all' + - fsspec>=2022.11.0 ; extra == 'all' + - gcsfs>=2022.11.0 ; extra == 'all' + - html5lib>=1.1 ; extra == 'all' + - hypothesis>=6.46.1 ; extra == 'all' + - jinja2>=3.1.2 ; extra == 'all' + - lxml>=4.9.2 ; extra == 'all' + - matplotlib>=3.6.3 ; extra == 'all' + - numba>=0.56.4 ; extra == 'all' + - numexpr>=2.8.4 ; extra == 'all' + - odfpy>=1.4.1 ; extra == 'all' + - openpyxl>=3.1.0 ; extra == 'all' + - pandas-gbq>=0.19.0 ; extra == 'all' + - psycopg2>=2.9.6 ; extra == 'all' + - pyarrow>=10.0.1 ; extra == 'all' + - pymysql>=1.0.2 ; extra == 'all' + - pyqt5>=5.15.9 ; extra == 'all' + - pyreadstat>=1.2.0 ; extra == 'all' + - pytest>=7.3.2 ; extra == 'all' + - pytest-xdist>=2.2.0 ; extra == 'all' + - python-calamine>=0.1.7 ; extra == 'all' + - pyxlsb>=1.0.10 ; extra == 'all' + - qtpy>=2.3.0 ; extra == 'all' + - scipy>=1.10.0 ; extra == 'all' + - s3fs>=2022.11.0 ; extra == 'all' + - sqlalchemy>=2.0.0 ; extra == 'all' + - tables>=3.8.0 ; extra == 'all' + - tabulate>=0.9.0 ; extra == 'all' + - xarray>=2022.12.0 ; extra == 'all' + - xlrd>=2.0.1 ; extra == 'all' + - xlsxwriter>=3.0.5 ; extra == 'all' + - zstandard>=0.19.0 ; extra == 'all' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/21/00/266d6b357ad5e6d3ad55093a7e8efc7dd245f5a842b584db9f30b0f0a287/pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl + name: pandas + version: 2.3.3 + sha256: 1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593 + requires_dist: + - numpy>=1.22.4 ; python_full_version < '3.11' + - numpy>=1.23.2 ; python_full_version == '3.11.*' + - numpy>=1.26.0 ; python_full_version >= '3.12' + - python-dateutil>=2.8.2 + - pytz>=2020.1 + - tzdata>=2022.7 + - hypothesis>=6.46.1 ; extra == 'test' + - pytest>=7.3.2 ; extra == 'test' + - pytest-xdist>=2.2.0 ; extra == 'test' + - pyarrow>=10.0.1 ; extra == 'pyarrow' + - bottleneck>=1.3.6 ; extra == 'performance' + - numba>=0.56.4 ; extra == 'performance' + - numexpr>=2.8.4 ; extra == 'performance' + - scipy>=1.10.0 ; extra == 'computation' + - xarray>=2022.12.0 ; extra == 'computation' + - fsspec>=2022.11.0 ; extra == 'fss' + - s3fs>=2022.11.0 ; extra == 'aws' + - gcsfs>=2022.11.0 ; extra == 'gcp' + - pandas-gbq>=0.19.0 ; extra == 'gcp' + - odfpy>=1.4.1 ; extra == 'excel' + - openpyxl>=3.1.0 ; extra == 'excel' + - python-calamine>=0.1.7 ; extra == 'excel' + - pyxlsb>=1.0.10 ; extra == 'excel' + - xlrd>=2.0.1 ; extra == 'excel' + - xlsxwriter>=3.0.5 ; extra == 'excel' + - pyarrow>=10.0.1 ; extra == 'parquet' + - pyarrow>=10.0.1 ; extra == 'feather' + - tables>=3.8.0 ; extra == 'hdf5' + - pyreadstat>=1.2.0 ; extra == 'spss' + - sqlalchemy>=2.0.0 ; extra == 'postgresql' + - psycopg2>=2.9.6 ; extra == 'postgresql' + - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql' + - sqlalchemy>=2.0.0 ; extra == 'mysql' + - pymysql>=1.0.2 ; extra == 'mysql' + - sqlalchemy>=2.0.0 ; extra == 'sql-other' + - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other' + - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other' + - beautifulsoup4>=4.11.2 ; extra == 'html' + - html5lib>=1.1 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'xml' + - matplotlib>=3.6.3 ; extra == 'plot' + - jinja2>=3.1.2 ; extra == 'output-formatting' + - tabulate>=0.9.0 ; extra == 'output-formatting' + - pyqt5>=5.15.9 ; extra == 'clipboard' + - qtpy>=2.3.0 ; extra == 'clipboard' + - zstandard>=0.19.0 ; extra == 'compression' + - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard' + - adbc-driver-postgresql>=0.8.0 ; extra == 'all' + - adbc-driver-sqlite>=0.8.0 ; extra == 'all' + - beautifulsoup4>=4.11.2 ; extra == 'all' + - bottleneck>=1.3.6 ; extra == 'all' + - dataframe-api-compat>=0.1.7 ; extra == 'all' + - fastparquet>=2022.12.0 ; extra == 'all' + - fsspec>=2022.11.0 ; extra == 'all' + - gcsfs>=2022.11.0 ; extra == 'all' + - html5lib>=1.1 ; extra == 'all' + - hypothesis>=6.46.1 ; extra == 'all' + - jinja2>=3.1.2 ; extra == 'all' + - lxml>=4.9.2 ; extra == 'all' + - matplotlib>=3.6.3 ; extra == 'all' + - numba>=0.56.4 ; extra == 'all' + - numexpr>=2.8.4 ; extra == 'all' + - odfpy>=1.4.1 ; extra == 'all' + - openpyxl>=3.1.0 ; extra == 'all' + - pandas-gbq>=0.19.0 ; extra == 'all' + - psycopg2>=2.9.6 ; extra == 'all' + - pyarrow>=10.0.1 ; extra == 'all' + - pymysql>=1.0.2 ; extra == 'all' + - pyqt5>=5.15.9 ; extra == 'all' + - pyreadstat>=1.2.0 ; extra == 'all' + - pytest>=7.3.2 ; extra == 'all' + - pytest-xdist>=2.2.0 ; extra == 'all' + - python-calamine>=0.1.7 ; extra == 'all' + - pyxlsb>=1.0.10 ; extra == 'all' + - qtpy>=2.3.0 ; extra == 'all' + - scipy>=1.10.0 ; extra == 'all' + - s3fs>=2022.11.0 ; extra == 'all' + - sqlalchemy>=2.0.0 ; extra == 'all' + - tables>=3.8.0 ; extra == 'all' + - tabulate>=0.9.0 ; extra == 'all' + - xarray>=2022.12.0 ; extra == 'all' + - xlrd>=2.0.1 ; extra == 'all' + - xlsxwriter>=3.0.5 ; extra == 'all' + - zstandard>=0.19.0 ; extra == 'all' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/3d/f7/f425a00df4fcc22b292c6895c6831c0c8ae1d9fac1e024d16f98a9ce8749/pandas-2.3.3-cp310-cp310-macosx_10_9_x86_64.whl + name: pandas + version: 2.3.3 + sha256: 376c6446ae31770764215a6c937f72d917f214b43560603cd60da6408f183b6c + requires_dist: + - numpy>=1.22.4 ; python_full_version < '3.11' + - numpy>=1.23.2 ; python_full_version == '3.11.*' + - numpy>=1.26.0 ; python_full_version >= '3.12' + - python-dateutil>=2.8.2 + - pytz>=2020.1 + - tzdata>=2022.7 + - hypothesis>=6.46.1 ; extra == 'test' + - pytest>=7.3.2 ; extra == 'test' + - pytest-xdist>=2.2.0 ; extra == 'test' + - pyarrow>=10.0.1 ; extra == 'pyarrow' + - bottleneck>=1.3.6 ; extra == 'performance' + - numba>=0.56.4 ; extra == 'performance' + - numexpr>=2.8.4 ; extra == 'performance' + - scipy>=1.10.0 ; extra == 'computation' + - xarray>=2022.12.0 ; extra == 'computation' + - fsspec>=2022.11.0 ; extra == 'fss' + - s3fs>=2022.11.0 ; extra == 'aws' + - gcsfs>=2022.11.0 ; extra == 'gcp' + - pandas-gbq>=0.19.0 ; extra == 'gcp' + - odfpy>=1.4.1 ; extra == 'excel' + - openpyxl>=3.1.0 ; extra == 'excel' + - python-calamine>=0.1.7 ; extra == 'excel' + - pyxlsb>=1.0.10 ; extra == 'excel' + - xlrd>=2.0.1 ; extra == 'excel' + - xlsxwriter>=3.0.5 ; extra == 'excel' + - pyarrow>=10.0.1 ; extra == 'parquet' + - pyarrow>=10.0.1 ; extra == 'feather' + - tables>=3.8.0 ; extra == 'hdf5' + - pyreadstat>=1.2.0 ; extra == 'spss' + - sqlalchemy>=2.0.0 ; extra == 'postgresql' + - psycopg2>=2.9.6 ; extra == 'postgresql' + - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql' + - sqlalchemy>=2.0.0 ; extra == 'mysql' + - pymysql>=1.0.2 ; extra == 'mysql' + - sqlalchemy>=2.0.0 ; extra == 'sql-other' + - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other' + - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other' + - beautifulsoup4>=4.11.2 ; extra == 'html' + - html5lib>=1.1 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'xml' + - matplotlib>=3.6.3 ; extra == 'plot' + - jinja2>=3.1.2 ; extra == 'output-formatting' + - tabulate>=0.9.0 ; extra == 'output-formatting' + - pyqt5>=5.15.9 ; extra == 'clipboard' + - qtpy>=2.3.0 ; extra == 'clipboard' + - zstandard>=0.19.0 ; extra == 'compression' + - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard' + - adbc-driver-postgresql>=0.8.0 ; extra == 'all' + - adbc-driver-sqlite>=0.8.0 ; extra == 'all' + - beautifulsoup4>=4.11.2 ; extra == 'all' + - bottleneck>=1.3.6 ; extra == 'all' + - dataframe-api-compat>=0.1.7 ; extra == 'all' + - fastparquet>=2022.12.0 ; extra == 'all' + - fsspec>=2022.11.0 ; extra == 'all' + - gcsfs>=2022.11.0 ; extra == 'all' + - html5lib>=1.1 ; extra == 'all' + - hypothesis>=6.46.1 ; extra == 'all' + - jinja2>=3.1.2 ; extra == 'all' + - lxml>=4.9.2 ; extra == 'all' + - matplotlib>=3.6.3 ; extra == 'all' + - numba>=0.56.4 ; extra == 'all' + - numexpr>=2.8.4 ; extra == 'all' + - odfpy>=1.4.1 ; extra == 'all' + - openpyxl>=3.1.0 ; extra == 'all' + - pandas-gbq>=0.19.0 ; extra == 'all' + - psycopg2>=2.9.6 ; extra == 'all' + - pyarrow>=10.0.1 ; extra == 'all' + - pymysql>=1.0.2 ; extra == 'all' + - pyqt5>=5.15.9 ; extra == 'all' + - pyreadstat>=1.2.0 ; extra == 'all' + - pytest>=7.3.2 ; extra == 'all' + - pytest-xdist>=2.2.0 ; extra == 'all' + - python-calamine>=0.1.7 ; extra == 'all' + - pyxlsb>=1.0.10 ; extra == 'all' + - qtpy>=2.3.0 ; extra == 'all' + - scipy>=1.10.0 ; extra == 'all' + - s3fs>=2022.11.0 ; extra == 'all' + - sqlalchemy>=2.0.0 ; extra == 'all' + - tables>=3.8.0 ; extra == 'all' + - tabulate>=0.9.0 ; extra == 'all' + - xarray>=2022.12.0 ; extra == 'all' + - xlrd>=2.0.1 ; extra == 'all' + - xlsxwriter>=3.0.5 ; extra == 'all' + - zstandard>=0.19.0 ; extra == 'all' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/40/a8/4dac1f8f8235e5d25b9955d02ff6f29396191d4e665d71122c3722ca83c5/pandas-2.3.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl + name: pandas + version: 2.3.3 + sha256: dd7478f1463441ae4ca7308a70e90b33470fa593429f9d4c578dd00d1fa78838 + requires_dist: + - numpy>=1.22.4 ; python_full_version < '3.11' + - numpy>=1.23.2 ; python_full_version == '3.11.*' + - numpy>=1.26.0 ; python_full_version >= '3.12' + - python-dateutil>=2.8.2 + - pytz>=2020.1 + - tzdata>=2022.7 + - hypothesis>=6.46.1 ; extra == 'test' + - pytest>=7.3.2 ; extra == 'test' + - pytest-xdist>=2.2.0 ; extra == 'test' + - pyarrow>=10.0.1 ; extra == 'pyarrow' + - bottleneck>=1.3.6 ; extra == 'performance' + - numba>=0.56.4 ; extra == 'performance' + - numexpr>=2.8.4 ; extra == 'performance' + - scipy>=1.10.0 ; extra == 'computation' + - xarray>=2022.12.0 ; extra == 'computation' + - fsspec>=2022.11.0 ; extra == 'fss' + - s3fs>=2022.11.0 ; extra == 'aws' + - gcsfs>=2022.11.0 ; extra == 'gcp' + - pandas-gbq>=0.19.0 ; extra == 'gcp' + - odfpy>=1.4.1 ; extra == 'excel' + - openpyxl>=3.1.0 ; extra == 'excel' + - python-calamine>=0.1.7 ; extra == 'excel' + - pyxlsb>=1.0.10 ; extra == 'excel' + - xlrd>=2.0.1 ; extra == 'excel' + - xlsxwriter>=3.0.5 ; extra == 'excel' + - pyarrow>=10.0.1 ; extra == 'parquet' + - pyarrow>=10.0.1 ; extra == 'feather' + - tables>=3.8.0 ; extra == 'hdf5' + - pyreadstat>=1.2.0 ; extra == 'spss' + - sqlalchemy>=2.0.0 ; extra == 'postgresql' + - psycopg2>=2.9.6 ; extra == 'postgresql' + - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql' + - sqlalchemy>=2.0.0 ; extra == 'mysql' + - pymysql>=1.0.2 ; extra == 'mysql' + - sqlalchemy>=2.0.0 ; extra == 'sql-other' + - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other' + - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other' + - beautifulsoup4>=4.11.2 ; extra == 'html' + - html5lib>=1.1 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'xml' + - matplotlib>=3.6.3 ; extra == 'plot' + - jinja2>=3.1.2 ; extra == 'output-formatting' + - tabulate>=0.9.0 ; extra == 'output-formatting' + - pyqt5>=5.15.9 ; extra == 'clipboard' + - qtpy>=2.3.0 ; extra == 'clipboard' + - zstandard>=0.19.0 ; extra == 'compression' + - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard' + - adbc-driver-postgresql>=0.8.0 ; extra == 'all' + - adbc-driver-sqlite>=0.8.0 ; extra == 'all' + - beautifulsoup4>=4.11.2 ; extra == 'all' + - bottleneck>=1.3.6 ; extra == 'all' + - dataframe-api-compat>=0.1.7 ; extra == 'all' + - fastparquet>=2022.12.0 ; extra == 'all' + - fsspec>=2022.11.0 ; extra == 'all' + - gcsfs>=2022.11.0 ; extra == 'all' + - html5lib>=1.1 ; extra == 'all' + - hypothesis>=6.46.1 ; extra == 'all' + - jinja2>=3.1.2 ; extra == 'all' + - lxml>=4.9.2 ; extra == 'all' + - matplotlib>=3.6.3 ; extra == 'all' + - numba>=0.56.4 ; extra == 'all' + - numexpr>=2.8.4 ; extra == 'all' + - odfpy>=1.4.1 ; extra == 'all' + - openpyxl>=3.1.0 ; extra == 'all' + - pandas-gbq>=0.19.0 ; extra == 'all' + - psycopg2>=2.9.6 ; extra == 'all' + - pyarrow>=10.0.1 ; extra == 'all' + - pymysql>=1.0.2 ; extra == 'all' + - pyqt5>=5.15.9 ; extra == 'all' + - pyreadstat>=1.2.0 ; extra == 'all' + - pytest>=7.3.2 ; extra == 'all' + - pytest-xdist>=2.2.0 ; extra == 'all' + - python-calamine>=0.1.7 ; extra == 'all' + - pyxlsb>=1.0.10 ; extra == 'all' + - qtpy>=2.3.0 ; extra == 'all' + - scipy>=1.10.0 ; extra == 'all' + - s3fs>=2022.11.0 ; extra == 'all' + - sqlalchemy>=2.0.0 ; extra == 'all' + - tables>=3.8.0 ; extra == 'all' + - tabulate>=0.9.0 ; extra == 'all' + - xarray>=2022.12.0 ; extra == 'all' + - xlrd>=2.0.1 ; extra == 'all' + - xlsxwriter>=3.0.5 ; extra == 'all' + - zstandard>=0.19.0 ; extra == 'all' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/c2/51/72b7c3b25ecfc6810b29ae9bffe76e26a407adb20de5b90ed984b3d483ca/pandas_gbq-0.34.1-py3-none-any.whl + name: pandas-gbq + version: 0.34.1 + sha256: b74932c6ee35dfc81582f39c792e3a68c9ef9bee8c85f25667d9d05dfadd0daf + requires_dist: + - setuptools + - db-dtypes>=1.0.4,<2.0.0 + - numpy>=1.18.1 + - pandas>=1.1.4 + - pyarrow>=4.0.0 + - pyarrow>=22.0.0 ; python_full_version >= '3.14' + - pydata-google-auth>=1.5.0 + - psutil>=5.9.8 + - google-api-core>=2.15.0,<3.0.0 + - google-auth>=2.14.1 + - google-auth-oauthlib>=0.7.0 + - google-cloud-bigquery>=3.20.0,<4.0.0 + - packaging>=22.0.0 + - google-cloud-bigquery-storage>=2.16.2,<3.0.0 ; extra == 'bqstorage' + - tqdm>=4.23.0 ; extra == 'tqdm' + - geopandas>=0.9.0 ; extra == 'geopandas' + - shapely>=1.8.4 ; extra == 'geopandas' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/77/fc/8cb9073bb1bee54eb49a1ae501a36402d01763812962ac811cdc1c81a9d7/parsy-2.2-py3-none-any.whl + name: parsy + version: '2.2' + sha256: 5e981613d9d2d8b68012d1dd0afe928967bea2e4eefdb76c2f545af0dd02a9e7 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl + name: partd + version: 1.4.2 + sha256: 978e4ac767ec4ba5b86c6eaa52e5a2a3bc748a2ca839e8cc798f1cc6ce6efb0f + requires_dist: + - locket + - toolz + - numpy>=1.20.0 ; extra == 'complete' + - pandas>=1.3 ; extra == 'complete' + - pyzmq ; extra == 'complete' + - blosc ; extra == 'complete' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl + name: pathspec + version: 1.0.4 + sha256: fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723 + requires_dist: + - hyperscan>=0.7 ; extra == 'hyperscan' + - typing-extensions>=4 ; extra == 'optional' + - google-re2>=1.1 ; extra == 're2' + - pytest>=9 ; extra == 'tests' + - typing-extensions>=4.15 ; extra == 'tests' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl + name: platformdirs + version: 4.9.4 + sha256: 68a9a4619a666ea6439f2ff250c12a853cd1cbd5158d258bd824a7df6be2f868 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl + name: pluggy + version: 1.6.0 + sha256: e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746 + requires_dist: + - pre-commit ; extra == 'dev' + - tox ; extra == 'dev' + - pytest ; extra == 'testing' + - pytest-benchmark ; extra == 'testing' + - coverage ; extra == 'testing' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl + name: prometheus-client + version: 0.24.1 + sha256: 150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055 + requires_dist: + - twisted ; extra == 'twisted' + - aiohttp ; extra == 'aiohttp' + - django ; extra == 'django' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/08/57/8c87e93142b2c1fa2408e45695205a7ba05fb5db458c0bf5c06ba0e09ea6/propcache-0.4.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: propcache + version: 0.4.1 + sha256: 2b16ec437a8c8a965ecf95739448dd938b5c7f56e67ea009f4300d8df05f32b7 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/a1/6b/db0d03d96726d995dc7171286c6ba9d8d14251f37433890f88368951a44e/propcache-0.4.1-cp310-cp310-macosx_10_9_x86_64.whl + name: propcache + version: 0.4.1 + sha256: 1eb2994229cc8ce7fe9b3db88f5465f5fd8651672840b2e426b88cdb1a30aac8 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/e4/c3/82728404aea669e1600f304f2609cde9e665c18df5a11cdd57ed73c1dceb/propcache-0.4.1-cp310-cp310-macosx_11_0_arm64.whl + name: propcache + version: 0.4.1 + sha256: 66c1f011f45a3b33d7bcb22daed4b29c0c9e2224758b6be00686731e1b46f925 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/84/f3/1fba73eeffafc998a25d59703b63f8be4fe8a5cb12eaff7386a0ba0f7125/proto_plus-1.27.2-py3-none-any.whl + name: proto-plus + version: 1.27.2 + sha256: 6432f75893d3b9e70b9c412f1d2f03f65b11fb164b793d14ae2ca01821d22718 + requires_dist: + - protobuf>=4.25.8,<8.0.0 + - google-api-core>=1.31.5 ; extra == 'testing' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/16/92/d1e32e3e0d894fe00b15ce28ad4944ab692713f2e7f0a99787405e43533a/protobuf-6.33.6-cp39-abi3-manylinux2014_x86_64.whl + name: protobuf + version: 6.33.6 + sha256: e9db7e292e0ab79dd108d7f1a94fe31601ce1ee3f7b79e0692043423020b0593 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/5c/01/a3c3ed5cd186f39e7880f8303cc51385a198a81469d53d0fdecf1f64d929/protobuf-6.33.6-cp39-abi3-macosx_10_9_universal2.whl + name: protobuf + version: 6.33.6 + sha256: 9720e6961b251bde64edfdab7d500725a2af5280f3f4c87e57c0208376aa8c3a + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/53/1b/3b431694a4dc6d37b9f653f0c64b0a0d9ec074ee810710c0c3da21d67ba7/protobuf-7.34.1-cp310-abi3-manylinux2014_x86_64.whl + name: protobuf + version: 7.34.1 + sha256: 8ff40ce8cd688f7265326b38d5a1bed9bfdf5e6723d49961432f83e21d5713e4 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/ec/11/3325d41e6ee15bf1125654301211247b042563bcc898784351252549a8ad/protobuf-7.34.1-cp310-abi3-macosx_10_9_universal2.whl + name: protobuf + version: 7.34.1 + sha256: d8b2cc79c4d8f62b293ad9b11ec3aebce9af481fa73e64556969f7345ebf9fc7 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl + name: psutil + version: 7.2.2 + sha256: 1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979 + requires_dist: + - psleak ; extra == 'dev' + - pytest ; extra == 'dev' + - pytest-instafail ; extra == 'dev' + - pytest-xdist ; extra == 'dev' + - setuptools ; extra == 'dev' + - abi3audit ; extra == 'dev' + - black ; extra == 'dev' + - check-manifest ; extra == 'dev' + - coverage ; extra == 'dev' + - packaging ; extra == 'dev' + - pylint ; extra == 'dev' + - pyperf ; extra == 'dev' + - pypinfo ; extra == 'dev' + - pytest-cov ; extra == 'dev' + - requests ; extra == 'dev' + - rstcheck ; extra == 'dev' + - ruff ; extra == 'dev' + - sphinx ; extra == 'dev' + - sphinx-rtd-theme ; extra == 'dev' + - toml-sort ; extra == 'dev' + - twine ; extra == 'dev' + - validate-pyproject[all] ; extra == 'dev' + - virtualenv ; extra == 'dev' + - vulture ; extra == 'dev' + - wheel ; extra == 'dev' + - colorama ; os_name == 'nt' and extra == 'dev' + - pyreadline3 ; os_name == 'nt' and extra == 'dev' + - pywin32 ; implementation_name != 'pypy' and os_name == 'nt' and extra == 'dev' + - wheel ; implementation_name != 'pypy' and os_name == 'nt' and extra == 'dev' + - wmi ; implementation_name != 'pypy' and os_name == 'nt' and extra == 'dev' + - psleak ; extra == 'test' + - pytest ; extra == 'test' + - pytest-instafail ; extra == 'test' + - pytest-xdist ; extra == 'test' + - setuptools ; extra == 'test' + - pywin32 ; implementation_name != 'pypy' and os_name == 'nt' and extra == 'test' + - wheel ; implementation_name != 'pypy' and os_name == 'nt' and extra == 'test' + - wmi ; implementation_name != 'pypy' and os_name == 'nt' and extra == 'test' + requires_python: '>=3.6' +- pypi: https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl + name: psutil + version: 7.2.2 + sha256: 076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9 + requires_dist: + - psleak ; extra == 'dev' + - pytest ; extra == 'dev' + - pytest-instafail ; extra == 'dev' + - pytest-xdist ; extra == 'dev' + - setuptools ; extra == 'dev' + - abi3audit ; extra == 'dev' + - black ; extra == 'dev' + - check-manifest ; extra == 'dev' + - coverage ; extra == 'dev' + - packaging ; extra == 'dev' + - pylint ; extra == 'dev' + - pyperf ; extra == 'dev' + - pypinfo ; extra == 'dev' + - pytest-cov ; extra == 'dev' + - requests ; extra == 'dev' + - rstcheck ; extra == 'dev' + - ruff ; extra == 'dev' + - sphinx ; extra == 'dev' + - sphinx-rtd-theme ; extra == 'dev' + - toml-sort ; extra == 'dev' + - twine ; extra == 'dev' + - validate-pyproject[all] ; extra == 'dev' + - virtualenv ; extra == 'dev' + - vulture ; extra == 'dev' + - wheel ; extra == 'dev' + - colorama ; os_name == 'nt' and extra == 'dev' + - pyreadline3 ; os_name == 'nt' and extra == 'dev' + - pywin32 ; implementation_name != 'pypy' and os_name == 'nt' and extra == 'dev' + - wheel ; implementation_name != 'pypy' and os_name == 'nt' and extra == 'dev' + - wmi ; implementation_name != 'pypy' and os_name == 'nt' and extra == 'dev' + - psleak ; extra == 'test' + - pytest ; extra == 'test' + - pytest-instafail ; extra == 'test' + - pytest-xdist ; extra == 'test' + - setuptools ; extra == 'test' + - pywin32 ; implementation_name != 'pypy' and os_name == 'nt' and extra == 'test' + - wheel ; implementation_name != 'pypy' and os_name == 'nt' and extra == 'test' + - wmi ; implementation_name != 'pypy' and os_name == 'nt' and extra == 'test' + requires_python: '>=3.6' +- pypi: https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl + name: psutil + version: 7.2.2 + sha256: ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486 + requires_dist: + - psleak ; extra == 'dev' + - pytest ; extra == 'dev' + - pytest-instafail ; extra == 'dev' + - pytest-xdist ; extra == 'dev' + - setuptools ; extra == 'dev' + - abi3audit ; extra == 'dev' + - black ; extra == 'dev' + - check-manifest ; extra == 'dev' + - coverage ; extra == 'dev' + - packaging ; extra == 'dev' + - pylint ; extra == 'dev' + - pyperf ; extra == 'dev' + - pypinfo ; extra == 'dev' + - pytest-cov ; extra == 'dev' + - requests ; extra == 'dev' + - rstcheck ; extra == 'dev' + - ruff ; extra == 'dev' + - sphinx ; extra == 'dev' + - sphinx-rtd-theme ; extra == 'dev' + - toml-sort ; extra == 'dev' + - twine ; extra == 'dev' + - validate-pyproject[all] ; extra == 'dev' + - virtualenv ; extra == 'dev' + - vulture ; extra == 'dev' + - wheel ; extra == 'dev' + - colorama ; os_name == 'nt' and extra == 'dev' + - pyreadline3 ; os_name == 'nt' and extra == 'dev' + - pywin32 ; implementation_name != 'pypy' and os_name == 'nt' and extra == 'dev' + - wheel ; implementation_name != 'pypy' and os_name == 'nt' and extra == 'dev' + - wmi ; implementation_name != 'pypy' and os_name == 'nt' and extra == 'dev' + - psleak ; extra == 'test' + - pytest ; extra == 'test' + - pytest-instafail ; extra == 'test' + - pytest-xdist ; extra == 'test' + - setuptools ; extra == 'test' + - pywin32 ; implementation_name != 'pypy' and os_name == 'nt' and extra == 'test' + - wheel ; implementation_name != 'pypy' and os_name == 'nt' and extra == 'test' + - wmi ; implementation_name != 'pypy' and os_name == 'nt' and extra == 'test' + requires_python: '>=3.6' +- pypi: https://files.pythonhosted.org/packages/18/f3/14a1370b1449ca875d5e353ef02cb9db6b70bd46ec361c236176837c0be1/psycopg-3.2.5-py3-none-any.whl + name: psycopg + version: 3.2.5 + sha256: b782130983e5b3de30b4c529623d3687033b4dafa05bb661fc6bf45837ca5879 + requires_dist: + - backports-zoneinfo>=0.2.0 ; python_full_version < '3.9' + - typing-extensions>=4.6 ; python_full_version < '3.13' + - tzdata ; sys_platform == 'win32' + - psycopg-c==3.2.5 ; implementation_name != 'pypy' and extra == 'c' + - psycopg-binary==3.2.5 ; implementation_name != 'pypy' and extra == 'binary' + - psycopg-pool ; extra == 'pool' + - anyio>=4.0 ; extra == 'test' + - mypy>=1.14 ; extra == 'test' + - pproxy>=2.7 ; extra == 'test' + - pytest>=6.2.5 ; extra == 'test' + - pytest-cov>=3.0 ; extra == 'test' + - pytest-randomly>=3.5 ; extra == 'test' + - ast-comments>=1.1.2 ; extra == 'dev' + - black>=24.1.0 ; extra == 'dev' + - codespell>=2.2 ; extra == 'dev' + - dnspython>=2.1 ; extra == 'dev' + - flake8>=4.0 ; extra == 'dev' + - isort[colors]>=6.0 ; extra == 'dev' + - isort-psycopg ; extra == 'dev' + - mypy>=1.14 ; extra == 'dev' + - pre-commit>=4.0.1 ; extra == 'dev' + - types-setuptools>=57.4 ; extra == 'dev' + - wheel>=0.37 ; extra == 'dev' + - sphinx>=5.0 ; extra == 'docs' + - furo==2022.6.21 ; extra == 'docs' + - sphinx-autobuild>=2021.3.14 ; extra == 'docs' + - sphinx-autodoc-typehints>=1.12 ; extra == 'docs' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/31/77/31968655db2efe83c519e6296ff3a85a0c9e50432e0c11c8ffae1b404870/psycopg_binary-3.2.5-cp310-cp310-macosx_11_0_arm64.whl + name: psycopg-binary + version: 3.2.5 + sha256: e7d215a43343d91ba08301865f059d9518818d66a222a85fb425e4156716f5a6 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/a5/90/9f2c41b3b42d8cd8b9866f0bbd27a5796a1ca8042a1a019b39a6645df523/psycopg_binary-3.2.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: psycopg-binary + version: 3.2.5 + sha256: c37eb3be7a6be93f4925ccf52bbfa60244da6c63201770a709dd81a3d2d08534 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/d6/30/af3806081adc75b5a8addde839d4c6b171a8c5d0d07dd92de20ca4dd6717/psycopg_binary-3.2.5-cp310-cp310-macosx_10_9_x86_64.whl + name: psycopg-binary + version: 3.2.5 + sha256: a82211a43372cba9b1555a110e84e679deec2dc9463ae4c736977dad99dca5ed + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/e7/c3/26b8a0908a9db249de3b4169692e1c7c19048a9bc41a4d3209cee7dbb758/psycopg_pool-3.3.0-py3-none-any.whl + name: psycopg-pool + version: 3.3.0 + sha256: 2e44329155c410b5e8666372db44276a8b1ebd8c90f1c3026ebba40d4bc81063 + requires_dist: + - typing-extensions>=4.6 + - anyio>=4.0 ; extra == 'test' + - mypy>=1.14 ; extra == 'test' + - pproxy>=2.7 ; extra == 'test' + - pytest>=6.2.5 ; extra == 'test' + - pytest-cov>=3.0 ; extra == 'test' + - pytest-randomly>=3.5 ; extra == 'test' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl + name: py + version: 1.11.0 + sha256: 607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*' +- pypi: https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl + name: py-cpuinfo + version: 9.0.0 + sha256: 859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5 +- pypi: https://files.pythonhosted.org/packages/bd/db/ea0203e495be491c85af87b66e37acfd3bf756fd985f87e46fc5e3bf022c/py4j-0.10.9.9-py2.py3-none-any.whl + name: py4j + version: 0.10.9.9 + sha256: c7c26e4158defb37b0bb124933163641a2ff6e3a3913f7811b0ddbe07ed61533 +- pypi: https://files.pythonhosted.org/packages/36/2e/c0f017c405fcdc252dbccafbe05e36b0d0eb1ea9a958f081e01c6972927f/pyarrow-23.0.1-cp314-cp314-manylinux_2_28_x86_64.whl + name: pyarrow + version: 23.0.1 + sha256: 4982d71350b1a6e5cfe1af742c53dfb759b11ce14141870d05d9e540d13bc5d1 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/8d/1b/6da9a89583ce7b23ac611f183ae4843cd3a6cf54f079549b0e8c14031e73/pyarrow-23.0.1-cp314-cp314-macosx_12_0_arm64.whl + name: pyarrow + version: 23.0.1 + sha256: 5df1161da23636a70838099d4aaa65142777185cc0cdba4037a18cee7d8db9ca + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/ae/b5/d58a241fbe324dbaeb8df07be6af8752c846192d78d2272e551098f74e88/pyarrow-23.0.1-cp314-cp314-macosx_12_0_x86_64.whl + name: pyarrow + version: 23.0.1 + sha256: fa8e51cb04b9f8c9c5ace6bab63af9a1f88d35c0d6cbf53e8c17c098552285e1 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/bc/8e/4be5617b4aaae0287f621ad31c6036e5f63118cfca0dc57d42121ff49b51/pyarrow-23.0.1-cp310-cp310-macosx_12_0_x86_64.whl + name: pyarrow + version: 23.0.1 + sha256: 3f91c038b95f71ddfc865f11d5876c42f343b4495535bd262c7b321b0b94507c + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/bc/a8/24e5dc6855f50a62936ceb004e6e9645e4219a8065f304145d7fb8a79d5d/pyarrow-23.0.1-cp310-cp310-macosx_12_0_arm64.whl + name: pyarrow + version: 23.0.1 + sha256: 3fab8f82571844eb3c460f90a75583801d14ca0cc32b1acc8c361650e006fd56 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/f8/82/c40b68001dbec8a3faa4c08cd8c200798ac732d2854537c5449dc859f55a/pyarrow-23.0.1-cp310-cp310-manylinux_2_28_x86_64.whl + name: pyarrow + version: 23.0.1 + sha256: c33b5bf406284fd0bba436ed6f6c3ebe8e311722b441d89397c54f871c6863a2 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/2e/c3/94ade4906a2f88bc935772f59c934013b4205e773bcb4239db114a6da136/pyarrow_hotfix-0.7-py3-none-any.whl + name: pyarrow-hotfix + version: '0.7' + sha256: 3236f3b5f1260f0e2ac070a55c1a7b339c4bb7267839bd2015e283234e758100 + requires_python: '>=3.5' +- pypi: https://files.pythonhosted.org/packages/5d/a0/7d793dce3fa811fe047d6ae2431c672364b462850c6235ae306c0efd025f/pyasn1-0.6.3-py3-none-any.whl + name: pyasn1 + version: 0.6.3 + sha256: a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl + name: pyasn1-modules + version: 0.4.2 + sha256: 29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a + requires_dist: + - pyasn1>=0.6.1,<0.7.0 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl + name: pycparser + version: '3.0' + sha256: b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/5f/e9/a09476d436d0ff1402ac3867d933c61805ec2326c6ea557aeeac3825604e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: pycryptodome + version: 3.23.0 + sha256: c8987bd3307a39bc03df5c8e0e3d8be0c4c3518b7f044b0f4c15d1aa78f52575 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*' +- pypi: https://files.pythonhosted.org/packages/6e/4e/a066527e079fc5002390c8acdd3aca431e6ea0a50ffd7201551175b47323/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl + name: pycryptodome + version: 3.23.0 + sha256: cfb5cd445280c5b0a4e6187a7ce8de5a07b5f3f897f235caa11f1f435f182843 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*' +- pypi: https://files.pythonhosted.org/packages/db/6c/a1f71542c969912bb0e106f64f60a56cc1f0fabecf9396f45accbe63fa68/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_universal2.whl + name: pycryptodome + version: 3.23.0 + sha256: 187058ab80b3281b1de11c2e6842a357a1f71b42cb1e15bce373f3d238135c27 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*' +- pypi: https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl + name: pydantic + version: 2.12.5 + sha256: e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d + requires_dist: + - annotated-types>=0.6.0 + - pydantic-core==2.41.5 + - typing-extensions>=4.14.1 + - typing-inspection>=0.4.2 + - email-validator>=2.0.0 ; extra == 'email' + - tzdata ; python_full_version >= '3.9' and sys_platform == 'win32' and extra == 'timezone' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: pydantic-core + version: 2.41.5 + sha256: 22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375 + requires_dist: + - typing-extensions>=4.14.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl + name: pydantic-core + version: 2.41.5 + sha256: 1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14 + requires_dist: + - typing-extensions>=4.14.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/a8/76/7727ef2ffa4b62fcab916686a68a0426b9b790139720e1934e8ba797e238/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: pydantic-core + version: 2.41.5 + sha256: 100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a + requires_dist: + - typing-extensions>=4.14.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/c6/90/32c9941e728d564b411d574d8ee0cf09b12ec978cb22b294995bae5549a5/pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl + name: pydantic-core + version: 2.41.5 + sha256: 77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146 + requires_dist: + - typing-extensions>=4.14.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/ea/28/46b7c5c9635ae96ea0fbb779e271a38129df2550f763937659ee6c5dbc65/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl + name: pydantic-core + version: 2.41.5 + sha256: 3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a + requires_dist: + - typing-extensions>=4.14.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/fb/a8/61c96a77fe28993d9a6fb0f4127e05430a267b235a124545d79fea46dd65/pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl + name: pydantic-core + version: 2.41.5 + sha256: dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2 + requires_dist: + - typing-extensions>=4.14.1 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/ca/cb/cdeaba62aa3c48f0d8834afb82b4a21463cd83df34fe01f9daa89a08ec6c/pydata_google_auth-1.9.1-py2.py3-none-any.whl + name: pydata-google-auth + version: 1.9.1 + sha256: 75ffce5d106e34b717b31844c1639ea505b7d9550dc23b96fb6c20d086b53fa3 + requires_dist: + - setuptools + - google-auth>=1.25.0,<3.0.dev0 + - google-auth-oauthlib>=0.4.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl + name: pygments + version: 2.20.0 + sha256: 81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176 + requires_dist: + - colorama>=0.4.6 ; extra == 'windows-terminal' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/e5/7a/8dd906bd22e79e47397a61742927f6747fe93242ef86645ee9092e610244/pyjwt-2.12.1-py3-none-any.whl + name: pyjwt + version: 2.12.1 + sha256: 28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c + requires_dist: + - typing-extensions>=4.0 ; python_full_version < '3.11' + - cryptography>=3.4.0 ; extra == 'crypto' + - coverage[toml]==7.10.7 ; extra == 'dev' + - cryptography>=3.4.0 ; extra == 'dev' + - pre-commit ; extra == 'dev' + - pytest>=8.4.2,<9.0.0 ; extra == 'dev' + - sphinx ; extra == 'dev' + - sphinx-rtd-theme ; extra == 'dev' + - zope-interface ; extra == 'dev' + - sphinx ; extra == 'docs' + - sphinx-rtd-theme ; extra == 'docs' + - zope-interface ; extra == 'docs' + - coverage[toml]==7.10.7 ; extra == 'tests' + - pytest>=8.4.2,<9.0.0 ; extra == 'tests' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/7c/4c/ad33b92b9864cbde84f259d5df035a6447f91891f5be77788e2a3892bce3/pymysql-1.1.2-py3-none-any.whl + name: pymysql + version: 1.1.2 + sha256: e6b1d89711dd51f8f74b1631fe08f039e7d76cf67a42a323d3178f0f25762ed9 + requires_dist: + - cryptography ; extra == 'rsa' + - pynacl>=1.4.0 ; extra == 'ed25519' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/fb/7d/d4f7d908fa8415571771b30669251d57c3cf313b36a856e6d7548ae01619/pyopenssl-26.0.0-py3-none-any.whl + name: pyopenssl + version: 26.0.0 + sha256: df94d28498848b98cc1c0ffb8ef1e71e40210d3b0a8064c9d29571ed2904bf81 + requires_dist: + - cryptography>=46.0.0,<47 + - typing-extensions>=4.9 ; python_full_version >= '3.8' and python_full_version < '3.13' + - pytest-rerunfailures ; extra == 'test' + - pretend ; extra == 'test' + - pytest>=3.0.1 ; extra == 'test' + - sphinx!=5.2.0,!=5.2.0.post0,!=7.2.5 ; extra == 'docs' + - sphinx-rtd-theme ; extra == 'docs' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/19/bf/58ee13add151469c25825b7125bbf62c3bdcec05eec4d458fcb5c5516066/pyspark-4.1.1.tar.gz + name: pyspark + version: 4.1.1 + sha256: 77f78984aa84fbe865c717dd37b49913b4e5c97d76ef6824f932f1aefa6621ec + requires_dist: + - py4j>=0.10.9.7,<0.10.9.10 + - numpy>=1.21 ; extra == 'ml' + - numpy>=1.21 ; extra == 'mllib' + - pandas>=2.2.0 ; extra == 'sql' + - pyarrow>=15.0.0 ; extra == 'sql' + - numpy>=1.21 ; extra == 'sql' + - pandas>=2.2.0 ; extra == 'pandas-on-spark' + - pyarrow>=15.0.0 ; extra == 'pandas-on-spark' + - numpy>=1.21 ; extra == 'pandas-on-spark' + - pandas>=2.2.0 ; extra == 'connect' + - pyarrow>=15.0.0 ; extra == 'connect' + - grpcio>=1.76.0 ; extra == 'connect' + - grpcio-status>=1.76.0 ; extra == 'connect' + - googleapis-common-protos>=1.71.0 ; extra == 'connect' + - zstandard>=0.25.0 ; extra == 'connect' + - numpy>=1.21 ; extra == 'connect' + - pandas>=2.2.0 ; extra == 'pipelines' + - pyarrow>=15.0.0 ; extra == 'pipelines' + - numpy>=1.21 ; extra == 'pipelines' + - grpcio>=1.76.0 ; extra == 'pipelines' + - grpcio-status>=1.76.0 ; extra == 'pipelines' + - googleapis-common-protos>=1.71.0 ; extra == 'pipelines' + - zstandard>=0.25.0 ; extra == 'pipelines' + - pyyaml>=3.11 ; extra == 'pipelines' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/51/ff/f6e8b8f39e08547faece4bd80f89d5a8de68a38b2d179cc1c4490ffa3286/pytest-7.4.4-py3-none-any.whl + name: pytest + version: 7.4.4 + sha256: b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8 + requires_dist: + - iniconfig + - packaging + - pluggy>=0.12,<2.0 + - exceptiongroup>=1.0.0rc8 ; python_full_version < '3.11' + - tomli>=1.0.0 ; python_full_version < '3.11' + - importlib-metadata>=0.12 ; python_full_version < '3.8' + - colorama ; sys_platform == 'win32' + - argcomplete ; extra == 'testing' + - attrs>=19.2.0 ; extra == 'testing' + - hypothesis>=3.56 ; extra == 'testing' + - mock ; extra == 'testing' + - nose ; extra == 'testing' + - pygments>=2.7.2 ; extra == 'testing' + - requests ; extra == 'testing' + - setuptools ; extra == 'testing' + - xmlschema ; extra == 'testing' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/ee/82/62e2d63639ecb0fbe8a7ee59ef0bc69a4669ec50f6d3459f74ad4e4189a2/pytest_asyncio-0.23.8-py3-none-any.whl + name: pytest-asyncio + version: 0.23.8 + sha256: 50265d892689a5faefb84df80819d1ecef566eb3549cf915dfb33569359d1ce2 + requires_dist: + - pytest>=7.0.0,<9 + - sphinx>=5.3 ; extra == 'docs' + - sphinx-rtd-theme>=1.0 ; extra == 'docs' + - coverage>=6.2 ; extra == 'testing' + - hypothesis>=5.7.1 ; extra == 'testing' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/2c/60/423a63fb190a0483d049786a121bd3dfd7d93bb5ff1bb5b5cd13e5df99a7/pytest_benchmark-3.4.1-py2.py3-none-any.whl + name: pytest-benchmark + version: 3.4.1 + sha256: 36d2b08c4882f6f997fd3126a3d6dfd70f3249cde178ed8bbc0b73db7c20f809 + requires_dist: + - pytest>=3.8 + - py-cpuinfo + - statistics ; python_full_version < '3.4' + - pathlib2 ; python_full_version < '3.4' + - aspectlib ; extra == 'aspect' + - elasticsearch ; extra == 'elasticsearch' + - pygal ; extra == 'histogram' + - pygaljs ; extra == 'histogram' + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*' +- pypi: https://files.pythonhosted.org/packages/25/b2/bdc663a5647ce2034f7e8420122af340df87c01ba97745fc753b8c917acb/pytest_env-1.1.3-py3-none-any.whl + name: pytest-env + version: 1.1.3 + sha256: aada77e6d09fcfb04540a6e462c58533c37df35fa853da78707b17ec04d17dfc + requires_dist: + - pytest>=7.4.3 + - tomli>=2.0.1 ; python_full_version < '3.11' + - covdefaults>=2.3 ; extra == 'test' + - coverage>=7.3.2 ; extra == 'test' + - pytest-mock>=3.12 ; extra == 'test' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/2d/a1/2f2c1c2353350d66c4d110d283e422e4943eb5ad10effa9357ba66f7b5b9/pytest_lazy_fixture-0.6.3-py3-none-any.whl + name: pytest-lazy-fixture + version: 0.6.3 + sha256: e0b379f38299ff27a653f03eaa69b08a6fd4484e46fd1c9907d984b9f9daeda6 + requires_dist: + - pytest>=3.2.5 +- pypi: https://files.pythonhosted.org/packages/30/43/8deecb4c123bbc16d25666f1a6d241109c97aeb2e50806b952661c8e4b95/pytest_mock-1.10.4-py2.py3-none-any.whl + name: pytest-mock + version: 1.10.4 + sha256: 43ce4e9dd5074993e7c021bb1c22cbb5363e612a2b5a76bc6d956775b10758b7 + requires_dist: + - pytest>=2.7 + - mock ; python_full_version < '3' + - pre-commit ; extra == 'dev' + - tox ; extra == 'dev' + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*' +- pypi: https://files.pythonhosted.org/packages/ec/98/adc368fe369465f291ab24e18b9900473786ed1afdf861ba90467eb0767e/pytest_ordering-0.6-py3-none-any.whl + name: pytest-ordering + version: '0.6' + sha256: 3f314a178dbeb6777509548727dc69edf22d6d9a2867bf2d310ab85c403380b6 + requires_dist: + - pytest +- pypi: https://files.pythonhosted.org/packages/46/df/97cc0b5b8b53da0e265acd0aeecfc0c279e950a029acd2d7b4e54b00b25f/pytest_timeout-1.4.2-py2.py3-none-any.whl + name: pytest-timeout + version: 1.4.2 + sha256: 541d7aa19b9a6b4e475c759fd6073ef43d7cdc9a92d95644c260076eb257a063 + requires_dist: + - pytest>=3.6.0 +- pypi: https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl + name: pytest-xdist + version: 3.8.0 + sha256: 202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88 + requires_dist: + - execnet>=2.1 + - pytest>=7.0.0 + - filelock ; extra == 'testing' + - psutil>=3.0 ; extra == 'psutil' + - setproctitle ; extra == 'setproctitle' + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.10.20-h3c07f61_0_cpython.conda + sha256: 8ff2ce308faf2588b69c65b120293f59a8f2577b772b34df4e817d220b09e081 + md5: 5d4e2b00d99feacd026859b7fa239dc0 + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.7.4,<3.0a0 + - libffi >=3.4,<4.0a0 + - libgcc >=14 + - liblzma >=5.8.2,<6.0a0 + - libnsl >=2.0.1,<2.1.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libuuid >=2.41.3,<3.0a0 + - libxcrypt >=4.4.36 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + constrains: + - python_abi 3.10.* *_cp310 + license: Python-2.0 + purls: [] + size: 25455342 + timestamp: 1772729810280 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.3-h32b2ec7_101_cp314.conda + build_number: 101 + sha256: cb0628c5f1732f889f53a877484da98f5a0e0f47326622671396fb4f2b0cd6bd + md5: c014ad06e60441661737121d3eae8a60 + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.7.3,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - libgcc >=14 + - liblzma >=5.8.2,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libuuid >=2.41.3,<3.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + purls: [] + size: 36702440 + timestamp: 1770675584356 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.10.20-hea035f4_0_cpython.conda + sha256: b6b9d6a85003b21ac17cc1485e196906bd704759caaab1315f6f8eeb85f26202 + md5: bc2a1cfdea76213972b98c65be1e2023 + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.7.4,<3.0a0 + - libffi >=3.4,<4.0a0 + - liblzma >=5.8.2,<6.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + constrains: + - python_abi 3.10.* *_cp310 + license: Python-2.0 + purls: [] + size: 13083662 + timestamp: 1772730522090 +- conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.14.3-h4f44bb5_101_cp314.conda + build_number: 101 + sha256: f64e357aa0168a201c9b3eedf500d89a8550d6631d26a95590b12de61f8fd660 + md5: 030ec23658b941438ac42303aff0db2b + depends: + - __osx >=10.13 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.7.3,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - liblzma >=5.8.2,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + purls: [] + size: 14387288 + timestamp: 1770676578632 + python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.10.20-h1b19095_0_cpython.conda + sha256: f0f6fcbb6cfdee5a6b9c03b5b94d2bbe737f3b17a618006c7685cc48992ae667 + md5: 55ec25b0d09379eb11c32dbe09ee28c4 + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.7.4,<3.0a0 + - libffi >=3.4,<4.0a0 + - liblzma >=5.8.2,<6.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + constrains: + - python_abi 3.10.* *_cp310 + license: Python-2.0 + purls: [] + size: 12468674 + timestamp: 1772730636766 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.14.3-h4c637c5_101_cp314.conda + build_number: 101 + sha256: fccce2af62d11328d232df9f6bbf63464fd45f81f718c661757f9c628c4378ce + md5: 753c8d0447677acb7ddbcc6e03e82661 + depends: + - __osx >=11.0 + - bzip2 >=1.0.8,<2.0a0 + - libexpat >=2.7.3,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 + - liblzma >=5.8.2,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.5.5,<4.0a0 + - python_abi 3.14.* *_cp314 + - readline >=8.3,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + purls: [] + size: 13522698 + timestamp: 1770675365241 + python_site_packages_path: lib/python3.14/site-packages +- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl + name: python-dateutil + version: 2.9.0.post0 + sha256: a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 + requires_dist: + - six>=1.5 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*' +- pypi: https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl + name: python-dotenv + version: 1.2.2 + sha256: 1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a + requires_dist: + - click>=5.0 ; extra == 'cli' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/2e/2e/dfbd2c9b3edf6a5a8cd9e66090221046839b488ea27824970426bf06b242/python_keycloak-4.2.2-py3-none-any.whl + name: python-keycloak + version: 4.2.2 + sha256: 5137fd87c69031a372a578df96bae96b9aead2c9dad976613bc978e9e0246a1e + requires_dist: + - async-property>=0.2.2 + - deprecation>=2.1.0 + - httpx>=0.23.2 + - jwcrypto>=1.5.4 + - requests>=2.20.0 + - requests-toolbelt>=0.6.0 + requires_python: '>=3.8,<4.0' +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda + build_number: 8 + sha256: ad6d2e9ac39751cc0529dd1566a26751a0bf2542adb0c232533d32e176e21db5 + md5: 0539938c55b6b1a59b560e843ad864a4 + constrains: + - python 3.14.* *_cp314 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 6989 + timestamp: 1752805904792 +- pypi: https://files.pythonhosted.org/packages/10/99/781fe0c827be2742bcc775efefccb3b048a3a9c6ce9aec0cbf4a101677e5/pytz-2026.1.post1-py2.py3-none-any.whl + name: pytz + version: 2026.1.post1 + sha256: f2fd16142fda348286a75e1a524be810bb05d444e5a081f37f7affc635035f7a +- pypi: https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl + name: pyyaml + version: 6.0.3 + sha256: 02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: pyyaml + version: 6.0.3 + sha256: 9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: pyyaml + version: 6.0.3 + sha256: c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl + name: pyyaml + version: 6.0.3 + sha256: 8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl + name: pyyaml + version: 6.0.3 + sha256: 34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl + name: pyyaml + version: 6.0.3 + sha256: 214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/61/c5/c2ceba832fe3f47cfd7e11cd7cc7a1bbc2c028424c5bca70435aa4ca1dec/ray-2.49.2-cp310-cp310-macosx_12_0_x86_64.whl + name: ray + version: 2.49.2 + sha256: 3e441bf2acd7f368cf45132752066c5c3b83d88cd5f85762e703774bba4f2b6d + requires_dist: + - click>=7.0 + - filelock + - jsonschema + - msgpack>=1.0.0,<2.0.0 + - packaging + - protobuf>=3.20.3 + - pyyaml + - requests + - cupy-cuda12x ; sys_platform != 'darwin' and extra == 'cgraph' + - grpcio!=1.56.0 ; sys_platform == 'darwin' and extra == 'client' + - grpcio ; extra == 'client' + - numpy>=1.20 ; extra == 'data' + - pandas>=1.3 ; extra == 'data' + - pyarrow>=9.0.0 ; extra == 'data' + - fsspec ; extra == 'data' + - aiohttp>=3.7 ; extra == 'default' + - aiohttp-cors ; extra == 'default' + - colorful ; extra == 'default' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'default' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'default' + - requests ; extra == 'default' + - grpcio>=1.32.0 ; python_full_version < '3.10' and extra == 'default' + - grpcio>=1.42.0 ; python_full_version >= '3.10' and extra == 'default' + - opencensus ; extra == 'default' + - opentelemetry-sdk>=1.30.0 ; extra == 'default' + - opentelemetry-exporter-prometheus ; extra == 'default' + - opentelemetry-proto ; extra == 'default' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,<3 ; extra == 'default' + - prometheus-client>=0.7.1 ; extra == 'default' + - smart-open ; extra == 'default' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'default' + - memray ; sys_platform != 'win32' and extra == 'observability' + - smart-open ; extra == 'serve' + - aiohttp>=3.7 ; extra == 'serve' + - grpcio>=1.42.0 ; python_full_version >= '3.10' and extra == 'serve' + - prometheus-client>=0.7.1 ; extra == 'serve' + - fastapi ; extra == 'serve' + - opencensus ; extra == 'serve' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'serve' + - grpcio>=1.32.0 ; python_full_version < '3.10' and extra == 'serve' + - opentelemetry-sdk>=1.30.0 ; extra == 'serve' + - aiohttp-cors ; extra == 'serve' + - requests ; extra == 'serve' + - starlette ; extra == 'serve' + - opentelemetry-exporter-prometheus ; extra == 'serve' + - watchfiles ; extra == 'serve' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'serve' + - uvicorn[standard] ; extra == 'serve' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'serve' + - colorful ; extra == 'serve' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,<3 ; extra == 'serve' + - opentelemetry-proto ; extra == 'serve' + - pandas ; extra == 'tune' + - tensorboardx>=1.9 ; extra == 'tune' + - requests ; extra == 'tune' + - pyarrow>=9.0.0 ; extra == 'tune' + - fsspec ; extra == 'tune' + - cupy-cuda12x ; sys_platform != 'darwin' and extra == 'adag' + - smart-open ; extra == 'serve-grpc' + - aiohttp>=3.7 ; extra == 'serve-grpc' + - grpcio>=1.42.0 ; python_full_version >= '3.10' and extra == 'serve-grpc' + - prometheus-client>=0.7.1 ; extra == 'serve-grpc' + - fastapi ; extra == 'serve-grpc' + - opencensus ; extra == 'serve-grpc' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'serve-grpc' + - grpcio>=1.32.0 ; python_full_version < '3.10' and extra == 'serve-grpc' + - opentelemetry-sdk>=1.30.0 ; extra == 'serve-grpc' + - aiohttp-cors ; extra == 'serve-grpc' + - requests ; extra == 'serve-grpc' + - starlette ; extra == 'serve-grpc' + - opentelemetry-exporter-prometheus ; extra == 'serve-grpc' + - watchfiles ; extra == 'serve-grpc' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'serve-grpc' + - uvicorn[standard] ; extra == 'serve-grpc' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'serve-grpc' + - colorful ; extra == 'serve-grpc' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,<3 ; extra == 'serve-grpc' + - opentelemetry-proto ; extra == 'serve-grpc' + - pyopenssl ; extra == 'serve-grpc' + - smart-open ; extra == 'serve-async-inference' + - aiohttp>=3.7 ; extra == 'serve-async-inference' + - celery ; extra == 'serve-async-inference' + - grpcio>=1.42.0 ; python_full_version >= '3.10' and extra == 'serve-async-inference' + - prometheus-client>=0.7.1 ; extra == 'serve-async-inference' + - fastapi ; extra == 'serve-async-inference' + - opencensus ; extra == 'serve-async-inference' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'serve-async-inference' + - grpcio>=1.32.0 ; python_full_version < '3.10' and extra == 'serve-async-inference' + - opentelemetry-sdk>=1.30.0 ; extra == 'serve-async-inference' + - aiohttp-cors ; extra == 'serve-async-inference' + - requests ; extra == 'serve-async-inference' + - starlette ; extra == 'serve-async-inference' + - opentelemetry-exporter-prometheus ; extra == 'serve-async-inference' + - watchfiles ; extra == 'serve-async-inference' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'serve-async-inference' + - uvicorn[standard] ; extra == 'serve-async-inference' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'serve-async-inference' + - colorful ; extra == 'serve-async-inference' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,<3 ; extra == 'serve-async-inference' + - opentelemetry-proto ; extra == 'serve-async-inference' + - ray-cpp==2.49.2 ; extra == 'cpp' + - pandas ; extra == 'rllib' + - tensorboardx>=1.9 ; extra == 'rllib' + - requests ; extra == 'rllib' + - pyarrow>=9.0.0 ; extra == 'rllib' + - fsspec ; extra == 'rllib' + - dm-tree ; extra == 'rllib' + - gymnasium==1.1.1 ; extra == 'rllib' + - lz4 ; extra == 'rllib' + - ormsgpack==1.7.0 ; extra == 'rllib' + - pyyaml ; extra == 'rllib' + - scipy ; extra == 'rllib' + - pandas ; extra == 'train' + - tensorboardx>=1.9 ; extra == 'train' + - requests ; extra == 'train' + - pyarrow>=9.0.0 ; extra == 'train' + - fsspec ; extra == 'train' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,<3 ; extra == 'train' + - smart-open ; extra == 'air' + - aiohttp>=3.7 ; extra == 'air' + - grpcio>=1.42.0 ; python_full_version >= '3.10' and extra == 'air' + - fsspec ; extra == 'air' + - prometheus-client>=0.7.1 ; extra == 'air' + - fastapi ; extra == 'air' + - pandas ; extra == 'air' + - opencensus ; extra == 'air' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'air' + - grpcio>=1.32.0 ; python_full_version < '3.10' and extra == 'air' + - opentelemetry-sdk>=1.30.0 ; extra == 'air' + - numpy>=1.20 ; extra == 'air' + - aiohttp-cors ; extra == 'air' + - requests ; extra == 'air' + - starlette ; extra == 'air' + - opentelemetry-exporter-prometheus ; extra == 'air' + - watchfiles ; extra == 'air' + - pyarrow>=9.0.0 ; extra == 'air' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'air' + - uvicorn[standard] ; extra == 'air' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'air' + - colorful ; extra == 'air' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,<3 ; extra == 'air' + - tensorboardx>=1.9 ; extra == 'air' + - pandas>=1.3 ; extra == 'air' + - opentelemetry-proto ; extra == 'air' + - smart-open ; extra == 'all' + - aiohttp>=3.7 ; extra == 'all' + - celery ; extra == 'all' + - grpcio>=1.42.0 ; python_full_version >= '3.10' and extra == 'all' + - fsspec ; extra == 'all' + - grpcio!=1.56.0 ; sys_platform == 'darwin' and extra == 'all' + - cupy-cuda12x ; sys_platform != 'darwin' and extra == 'all' + - prometheus-client>=0.7.1 ; extra == 'all' + - gymnasium==1.1.1 ; extra == 'all' + - ormsgpack==1.7.0 ; extra == 'all' + - scipy ; extra == 'all' + - fastapi ; extra == 'all' + - pandas ; extra == 'all' + - opencensus ; extra == 'all' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'all' + - grpcio>=1.32.0 ; python_full_version < '3.10' and extra == 'all' + - opentelemetry-sdk>=1.30.0 ; extra == 'all' + - dm-tree ; extra == 'all' + - numpy>=1.20 ; extra == 'all' + - lz4 ; extra == 'all' + - aiohttp-cors ; extra == 'all' + - requests ; extra == 'all' + - starlette ; extra == 'all' + - memray ; sys_platform != 'win32' and extra == 'all' + - opentelemetry-exporter-prometheus ; extra == 'all' + - watchfiles ; extra == 'all' + - pyyaml ; extra == 'all' + - pyarrow>=9.0.0 ; extra == 'all' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'all' + - grpcio ; extra == 'all' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'all' + - uvicorn[standard] ; extra == 'all' + - colorful ; extra == 'all' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,<3 ; extra == 'all' + - tensorboardx>=1.9 ; extra == 'all' + - pandas>=1.3 ; extra == 'all' + - opentelemetry-proto ; extra == 'all' + - pyopenssl ; extra == 'all' + - smart-open ; extra == 'all-cpp' + - aiohttp>=3.7 ; extra == 'all-cpp' + - celery ; extra == 'all-cpp' + - grpcio>=1.42.0 ; python_full_version >= '3.10' and extra == 'all-cpp' + - fsspec ; extra == 'all-cpp' + - grpcio!=1.56.0 ; sys_platform == 'darwin' and extra == 'all-cpp' + - cupy-cuda12x ; sys_platform != 'darwin' and extra == 'all-cpp' + - prometheus-client>=0.7.1 ; extra == 'all-cpp' + - gymnasium==1.1.1 ; extra == 'all-cpp' + - ormsgpack==1.7.0 ; extra == 'all-cpp' + - scipy ; extra == 'all-cpp' + - fastapi ; extra == 'all-cpp' + - pandas ; extra == 'all-cpp' + - opencensus ; extra == 'all-cpp' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'all-cpp' + - grpcio>=1.32.0 ; python_full_version < '3.10' and extra == 'all-cpp' + - dm-tree ; extra == 'all-cpp' + - opentelemetry-sdk>=1.30.0 ; extra == 'all-cpp' + - numpy>=1.20 ; extra == 'all-cpp' + - lz4 ; extra == 'all-cpp' + - aiohttp-cors ; extra == 'all-cpp' + - requests ; extra == 'all-cpp' + - starlette ; extra == 'all-cpp' + - memray ; sys_platform != 'win32' and extra == 'all-cpp' + - opentelemetry-exporter-prometheus ; extra == 'all-cpp' + - watchfiles ; extra == 'all-cpp' + - pyyaml ; extra == 'all-cpp' + - pyarrow>=9.0.0 ; extra == 'all-cpp' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'all-cpp' + - grpcio ; extra == 'all-cpp' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'all-cpp' + - uvicorn[standard] ; extra == 'all-cpp' + - ray-cpp==2.49.2 ; extra == 'all-cpp' + - colorful ; extra == 'all-cpp' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,<3 ; extra == 'all-cpp' + - tensorboardx>=1.9 ; extra == 'all-cpp' + - pandas>=1.3 ; extra == 'all-cpp' + - opentelemetry-proto ; extra == 'all-cpp' + - pyopenssl ; extra == 'all-cpp' + - smart-open ; extra == 'llm' + - typer ; extra == 'llm' + - aiohttp>=3.7 ; extra == 'llm' + - grpcio>=1.42.0 ; python_full_version >= '3.10' and extra == 'llm' + - fsspec ; extra == 'llm' + - vllm>=0.10.0 ; extra == 'llm' + - async-timeout ; python_full_version < '3.11' and extra == 'llm' + - prometheus-client>=0.7.1 ; extra == 'llm' + - fastapi ; extra == 'llm' + - hf-transfer ; extra == 'llm' + - jsonschema ; extra == 'llm' + - opencensus ; extra == 'llm' + - jsonref>=1.1.0 ; extra == 'llm' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'llm' + - grpcio>=1.32.0 ; python_full_version < '3.10' and extra == 'llm' + - opentelemetry-sdk>=1.30.0 ; extra == 'llm' + - numpy>=1.20 ; extra == 'llm' + - ninja ; extra == 'llm' + - aiohttp-cors ; extra == 'llm' + - requests ; extra == 'llm' + - starlette ; extra == 'llm' + - opentelemetry-exporter-prometheus ; extra == 'llm' + - watchfiles ; extra == 'llm' + - pyarrow>=9.0.0 ; extra == 'llm' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'llm' + - uvicorn[standard] ; extra == 'llm' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'llm' + - colorful ; extra == 'llm' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,<3 ; extra == 'llm' + - pandas>=1.3 ; extra == 'llm' + - opentelemetry-proto ; extra == 'llm' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/55/96/7911234a14b891320e652b5ae258050f98584f22a8e33afba9ad43ab27c9/ray-2.54.1-cp310-cp310-manylinux2014_x86_64.whl + name: ray + version: 2.54.1 + sha256: 054985194bd32f4464c93f9318d247fac61e1f32ac221565ecfdc81ab8c75d0b + requires_dist: + - click>=7.0 + - filelock + - jsonschema + - msgpack>=1.0.0,<2.0.0 + - packaging>=24.2 + - protobuf>=3.20.3 + - pyyaml + - requests + - cupy-cuda12x ; sys_platform != 'darwin' and extra == 'cgraph' + - grpcio!=1.56.0 ; sys_platform == 'darwin' and extra == 'client' + - grpcio ; extra == 'client' + - numpy>=1.20 ; extra == 'data' + - pandas>=1.3 ; extra == 'data' + - pyarrow>=9.0.0 ; extra == 'data' + - fsspec ; extra == 'data' + - aiohttp>=3.13.3 ; extra == 'default' + - aiohttp-cors ; extra == 'default' + - colorful ; extra == 'default' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'default' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'default' + - requests ; extra == 'default' + - grpcio>=1.42.0 ; extra == 'default' + - opencensus ; extra == 'default' + - opentelemetry-sdk>=1.30.0 ; extra == 'default' + - opentelemetry-exporter-prometheus ; extra == 'default' + - opentelemetry-proto ; extra == 'default' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'default' + - prometheus-client>=0.7.1 ; extra == 'default' + - smart-open ; extra == 'default' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'default' + - memray ; sys_platform != 'win32' and extra == 'observability' + - requests ; extra == 'serve' + - opentelemetry-exporter-prometheus ; extra == 'serve' + - opentelemetry-proto ; extra == 'serve' + - prometheus-client>=0.7.1 ; extra == 'serve' + - uvicorn[standard] ; extra == 'serve' + - aiohttp-cors ; extra == 'serve' + - smart-open ; extra == 'serve' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'serve' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'serve' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'serve' + - watchfiles ; extra == 'serve' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'serve' + - opentelemetry-sdk>=1.30.0 ; extra == 'serve' + - colorful ; extra == 'serve' + - starlette ; extra == 'serve' + - aiohttp>=3.13.3 ; extra == 'serve' + - fastapi ; extra == 'serve' + - grpcio>=1.42.0 ; extra == 'serve' + - opencensus ; extra == 'serve' + - pandas ; extra == 'tune' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'tune' + - tensorboardx>=1.9 ; extra == 'tune' + - requests ; extra == 'tune' + - pyarrow>=9.0.0 ; extra == 'tune' + - fsspec ; extra == 'tune' + - cupy-cuda12x ; sys_platform != 'darwin' and extra == 'adag' + - requests ; extra == 'serve-grpc' + - opentelemetry-exporter-prometheus ; extra == 'serve-grpc' + - opentelemetry-proto ; extra == 'serve-grpc' + - prometheus-client>=0.7.1 ; extra == 'serve-grpc' + - uvicorn[standard] ; extra == 'serve-grpc' + - aiohttp-cors ; extra == 'serve-grpc' + - smart-open ; extra == 'serve-grpc' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'serve-grpc' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'serve-grpc' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'serve-grpc' + - watchfiles ; extra == 'serve-grpc' + - pyopenssl ; extra == 'serve-grpc' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'serve-grpc' + - opentelemetry-sdk>=1.30.0 ; extra == 'serve-grpc' + - colorful ; extra == 'serve-grpc' + - starlette ; extra == 'serve-grpc' + - aiohttp>=3.13.3 ; extra == 'serve-grpc' + - fastapi ; extra == 'serve-grpc' + - grpcio>=1.42.0 ; extra == 'serve-grpc' + - opencensus ; extra == 'serve-grpc' + - requests ; extra == 'serve-async-inference' + - opentelemetry-exporter-prometheus ; extra == 'serve-async-inference' + - opentelemetry-proto ; extra == 'serve-async-inference' + - prometheus-client>=0.7.1 ; extra == 'serve-async-inference' + - uvicorn[standard] ; extra == 'serve-async-inference' + - aiohttp-cors ; extra == 'serve-async-inference' + - smart-open ; extra == 'serve-async-inference' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'serve-async-inference' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'serve-async-inference' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'serve-async-inference' + - watchfiles ; extra == 'serve-async-inference' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'serve-async-inference' + - opentelemetry-sdk>=1.30.0 ; extra == 'serve-async-inference' + - colorful ; extra == 'serve-async-inference' + - starlette ; extra == 'serve-async-inference' + - celery ; extra == 'serve-async-inference' + - aiohttp>=3.13.3 ; extra == 'serve-async-inference' + - fastapi ; extra == 'serve-async-inference' + - grpcio>=1.42.0 ; extra == 'serve-async-inference' + - opencensus ; extra == 'serve-async-inference' + - ray-cpp==2.54.1 ; extra == 'cpp' + - pandas ; extra == 'rllib' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'rllib' + - tensorboardx>=1.9 ; extra == 'rllib' + - requests ; extra == 'rllib' + - pyarrow>=9.0.0 ; extra == 'rllib' + - fsspec ; extra == 'rllib' + - dm-tree ; extra == 'rllib' + - gymnasium==1.2.2 ; extra == 'rllib' + - lz4 ; extra == 'rllib' + - ormsgpack>=1.7.0 ; extra == 'rllib' + - pyyaml ; extra == 'rllib' + - scipy ; extra == 'rllib' + - pandas ; extra == 'train' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'train' + - tensorboardx>=1.9 ; extra == 'train' + - requests ; extra == 'train' + - pyarrow>=9.0.0 ; extra == 'train' + - fsspec ; extra == 'train' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'train' + - requests ; extra == 'air' + - opentelemetry-exporter-prometheus ; extra == 'air' + - opentelemetry-proto ; extra == 'air' + - pyarrow>=9.0.0 ; extra == 'air' + - fsspec ; extra == 'air' + - tensorboardx>=1.9 ; extra == 'air' + - prometheus-client>=0.7.1 ; extra == 'air' + - uvicorn[standard] ; extra == 'air' + - numpy>=1.20 ; extra == 'air' + - pandas ; extra == 'air' + - aiohttp-cors ; extra == 'air' + - smart-open ; extra == 'air' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'air' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'air' + - pandas>=1.3 ; extra == 'air' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'air' + - watchfiles ; extra == 'air' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'air' + - opentelemetry-sdk>=1.30.0 ; extra == 'air' + - colorful ; extra == 'air' + - starlette ; extra == 'air' + - aiohttp>=3.13.3 ; extra == 'air' + - fastapi ; extra == 'air' + - grpcio>=1.42.0 ; extra == 'air' + - opencensus ; extra == 'air' + - memray ; sys_platform != 'win32' and extra == 'all' + - requests ; extra == 'all' + - opentelemetry-exporter-prometheus ; extra == 'all' + - opentelemetry-proto ; extra == 'all' + - cupy-cuda12x ; sys_platform != 'darwin' and extra == 'all' + - pyarrow>=9.0.0 ; extra == 'all' + - fsspec ; extra == 'all' + - tensorboardx>=1.9 ; extra == 'all' + - prometheus-client>=0.7.1 ; extra == 'all' + - uvicorn[standard] ; extra == 'all' + - numpy>=1.20 ; extra == 'all' + - pandas ; extra == 'all' + - aiohttp-cors ; extra == 'all' + - smart-open ; extra == 'all' + - pyyaml ; extra == 'all' + - grpcio!=1.56.0 ; sys_platform == 'darwin' and extra == 'all' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'all' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'all' + - pandas>=1.3 ; extra == 'all' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'all' + - lz4 ; extra == 'all' + - scipy ; extra == 'all' + - watchfiles ; extra == 'all' + - pyopenssl ; extra == 'all' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'all' + - opentelemetry-sdk>=1.30.0 ; extra == 'all' + - grpcio ; extra == 'all' + - dm-tree ; extra == 'all' + - gymnasium==1.2.2 ; extra == 'all' + - colorful ; extra == 'all' + - starlette ; extra == 'all' + - celery ; extra == 'all' + - aiohttp>=3.13.3 ; extra == 'all' + - ormsgpack>=1.7.0 ; extra == 'all' + - fastapi ; extra == 'all' + - grpcio>=1.42.0 ; extra == 'all' + - opencensus ; extra == 'all' + - ray-cpp==2.54.1 ; extra == 'all-cpp' + - memray ; sys_platform != 'win32' and extra == 'all-cpp' + - requests ; extra == 'all-cpp' + - opentelemetry-exporter-prometheus ; extra == 'all-cpp' + - opentelemetry-proto ; extra == 'all-cpp' + - cupy-cuda12x ; sys_platform != 'darwin' and extra == 'all-cpp' + - pyarrow>=9.0.0 ; extra == 'all-cpp' + - fsspec ; extra == 'all-cpp' + - tensorboardx>=1.9 ; extra == 'all-cpp' + - prometheus-client>=0.7.1 ; extra == 'all-cpp' + - uvicorn[standard] ; extra == 'all-cpp' + - numpy>=1.20 ; extra == 'all-cpp' + - pandas ; extra == 'all-cpp' + - aiohttp-cors ; extra == 'all-cpp' + - smart-open ; extra == 'all-cpp' + - pyyaml ; extra == 'all-cpp' + - grpcio!=1.56.0 ; sys_platform == 'darwin' and extra == 'all-cpp' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'all-cpp' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'all-cpp' + - pandas>=1.3 ; extra == 'all-cpp' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'all-cpp' + - lz4 ; extra == 'all-cpp' + - scipy ; extra == 'all-cpp' + - watchfiles ; extra == 'all-cpp' + - pyopenssl ; extra == 'all-cpp' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'all-cpp' + - opentelemetry-sdk>=1.30.0 ; extra == 'all-cpp' + - grpcio ; extra == 'all-cpp' + - dm-tree ; extra == 'all-cpp' + - gymnasium==1.2.2 ; extra == 'all-cpp' + - colorful ; extra == 'all-cpp' + - starlette ; extra == 'all-cpp' + - celery ; extra == 'all-cpp' + - aiohttp>=3.13.3 ; extra == 'all-cpp' + - ormsgpack>=1.7.0 ; extra == 'all-cpp' + - fastapi ; extra == 'all-cpp' + - grpcio>=1.42.0 ; extra == 'all-cpp' + - opencensus ; extra == 'all-cpp' + - hf-transfer ; extra == 'llm' + - requests ; extra == 'llm' + - opentelemetry-exporter-prometheus ; extra == 'llm' + - opentelemetry-proto ; extra == 'llm' + - vllm[audio]>=0.15.0 ; extra == 'llm' + - async-timeout ; python_full_version < '3.11' and extra == 'llm' + - pyarrow>=9.0.0 ; extra == 'llm' + - transformers>=4.57.3 ; extra == 'llm' + - fsspec ; extra == 'llm' + - pybind11 ; extra == 'llm' + - prometheus-client>=0.7.1 ; extra == 'llm' + - uvicorn[standard] ; extra == 'llm' + - numpy>=1.20 ; extra == 'llm' + - aiohttp-cors ; extra == 'llm' + - smart-open ; extra == 'llm' + - jsonref>=1.1.0 ; extra == 'llm' + - ninja ; extra == 'llm' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'llm' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'llm' + - typer ; extra == 'llm' + - meson ; extra == 'llm' + - pandas>=1.3 ; extra == 'llm' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'llm' + - jsonschema ; extra == 'llm' + - watchfiles ; extra == 'llm' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'llm' + - opentelemetry-sdk>=1.30.0 ; extra == 'llm' + - colorful ; extra == 'llm' + - starlette ; extra == 'llm' + - aiohttp>=3.13.3 ; extra == 'llm' + - nixl>=0.6.1 ; extra == 'llm' + - fastapi ; extra == 'llm' + - grpcio>=1.42.0 ; extra == 'llm' + - opencensus ; extra == 'llm' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/af/cf/9a6e33b59e1a12428b4fbd6cc38f7e32d116ccde4c72e15c3f76a22bf36d/ray-2.54.1-cp310-cp310-macosx_12_0_arm64.whl + name: ray + version: 2.54.1 + sha256: 2ea650e648acc6e76edd98c694657fd1fcb1cd97700d944a7d20da90269e9810 + requires_dist: + - click>=7.0 + - filelock + - jsonschema + - msgpack>=1.0.0,<2.0.0 + - packaging>=24.2 + - protobuf>=3.20.3 + - pyyaml + - requests + - cupy-cuda12x ; sys_platform != 'darwin' and extra == 'cgraph' + - grpcio!=1.56.0 ; sys_platform == 'darwin' and extra == 'client' + - grpcio ; extra == 'client' + - numpy>=1.20 ; extra == 'data' + - pandas>=1.3 ; extra == 'data' + - pyarrow>=9.0.0 ; extra == 'data' + - fsspec ; extra == 'data' + - aiohttp>=3.13.3 ; extra == 'default' + - aiohttp-cors ; extra == 'default' + - colorful ; extra == 'default' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'default' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'default' + - requests ; extra == 'default' + - grpcio>=1.42.0 ; extra == 'default' + - opencensus ; extra == 'default' + - opentelemetry-sdk>=1.30.0 ; extra == 'default' + - opentelemetry-exporter-prometheus ; extra == 'default' + - opentelemetry-proto ; extra == 'default' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'default' + - prometheus-client>=0.7.1 ; extra == 'default' + - smart-open ; extra == 'default' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'default' + - memray ; sys_platform != 'win32' and extra == 'observability' + - fastapi ; extra == 'serve' + - opencensus ; extra == 'serve' + - opentelemetry-exporter-prometheus ; extra == 'serve' + - prometheus-client>=0.7.1 ; extra == 'serve' + - colorful ; extra == 'serve' + - grpcio>=1.42.0 ; extra == 'serve' + - aiohttp-cors ; extra == 'serve' + - opentelemetry-proto ; extra == 'serve' + - uvicorn[standard] ; extra == 'serve' + - smart-open ; extra == 'serve' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'serve' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'serve' + - watchfiles ; extra == 'serve' + - starlette ; extra == 'serve' + - requests ; extra == 'serve' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'serve' + - opentelemetry-sdk>=1.30.0 ; extra == 'serve' + - aiohttp>=3.13.3 ; extra == 'serve' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'serve' + - pandas ; extra == 'tune' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'tune' + - tensorboardx>=1.9 ; extra == 'tune' + - requests ; extra == 'tune' + - pyarrow>=9.0.0 ; extra == 'tune' + - fsspec ; extra == 'tune' + - cupy-cuda12x ; sys_platform != 'darwin' and extra == 'adag' + - fastapi ; extra == 'serve-grpc' + - opencensus ; extra == 'serve-grpc' + - opentelemetry-exporter-prometheus ; extra == 'serve-grpc' + - prometheus-client>=0.7.1 ; extra == 'serve-grpc' + - colorful ; extra == 'serve-grpc' + - grpcio>=1.42.0 ; extra == 'serve-grpc' + - aiohttp-cors ; extra == 'serve-grpc' + - opentelemetry-proto ; extra == 'serve-grpc' + - uvicorn[standard] ; extra == 'serve-grpc' + - smart-open ; extra == 'serve-grpc' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'serve-grpc' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'serve-grpc' + - pyopenssl ; extra == 'serve-grpc' + - watchfiles ; extra == 'serve-grpc' + - starlette ; extra == 'serve-grpc' + - requests ; extra == 'serve-grpc' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'serve-grpc' + - opentelemetry-sdk>=1.30.0 ; extra == 'serve-grpc' + - aiohttp>=3.13.3 ; extra == 'serve-grpc' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'serve-grpc' + - fastapi ; extra == 'serve-async-inference' + - opencensus ; extra == 'serve-async-inference' + - opentelemetry-exporter-prometheus ; extra == 'serve-async-inference' + - prometheus-client>=0.7.1 ; extra == 'serve-async-inference' + - colorful ; extra == 'serve-async-inference' + - grpcio>=1.42.0 ; extra == 'serve-async-inference' + - aiohttp-cors ; extra == 'serve-async-inference' + - opentelemetry-proto ; extra == 'serve-async-inference' + - uvicorn[standard] ; extra == 'serve-async-inference' + - celery ; extra == 'serve-async-inference' + - smart-open ; extra == 'serve-async-inference' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'serve-async-inference' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'serve-async-inference' + - watchfiles ; extra == 'serve-async-inference' + - starlette ; extra == 'serve-async-inference' + - requests ; extra == 'serve-async-inference' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'serve-async-inference' + - opentelemetry-sdk>=1.30.0 ; extra == 'serve-async-inference' + - aiohttp>=3.13.3 ; extra == 'serve-async-inference' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'serve-async-inference' + - ray-cpp==2.54.1 ; extra == 'cpp' + - pandas ; extra == 'rllib' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'rllib' + - tensorboardx>=1.9 ; extra == 'rllib' + - requests ; extra == 'rllib' + - pyarrow>=9.0.0 ; extra == 'rllib' + - fsspec ; extra == 'rllib' + - dm-tree ; extra == 'rllib' + - gymnasium==1.2.2 ; extra == 'rllib' + - lz4 ; extra == 'rllib' + - ormsgpack>=1.7.0 ; extra == 'rllib' + - pyyaml ; extra == 'rllib' + - scipy ; extra == 'rllib' + - pandas ; extra == 'train' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'train' + - tensorboardx>=1.9 ; extra == 'train' + - requests ; extra == 'train' + - pyarrow>=9.0.0 ; extra == 'train' + - fsspec ; extra == 'train' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'train' + - fastapi ; extra == 'air' + - tensorboardx>=1.9 ; extra == 'air' + - opencensus ; extra == 'air' + - opentelemetry-exporter-prometheus ; extra == 'air' + - prometheus-client>=0.7.1 ; extra == 'air' + - colorful ; extra == 'air' + - pandas>=1.3 ; extra == 'air' + - pyarrow>=9.0.0 ; extra == 'air' + - grpcio>=1.42.0 ; extra == 'air' + - aiohttp-cors ; extra == 'air' + - opentelemetry-proto ; extra == 'air' + - uvicorn[standard] ; extra == 'air' + - smart-open ; extra == 'air' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'air' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'air' + - pandas ; extra == 'air' + - watchfiles ; extra == 'air' + - starlette ; extra == 'air' + - fsspec ; extra == 'air' + - requests ; extra == 'air' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'air' + - opentelemetry-sdk>=1.30.0 ; extra == 'air' + - aiohttp>=3.13.3 ; extra == 'air' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'air' + - numpy>=1.20 ; extra == 'air' + - lz4 ; extra == 'all' + - fastapi ; extra == 'all' + - tensorboardx>=1.9 ; extra == 'all' + - opencensus ; extra == 'all' + - opentelemetry-exporter-prometheus ; extra == 'all' + - prometheus-client>=0.7.1 ; extra == 'all' + - colorful ; extra == 'all' + - scipy ; extra == 'all' + - pandas>=1.3 ; extra == 'all' + - pyarrow>=9.0.0 ; extra == 'all' + - memray ; sys_platform != 'win32' and extra == 'all' + - grpcio>=1.42.0 ; extra == 'all' + - grpcio ; extra == 'all' + - aiohttp-cors ; extra == 'all' + - opentelemetry-proto ; extra == 'all' + - uvicorn[standard] ; extra == 'all' + - celery ; extra == 'all' + - smart-open ; extra == 'all' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'all' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'all' + - pandas ; extra == 'all' + - pyopenssl ; extra == 'all' + - watchfiles ; extra == 'all' + - starlette ; extra == 'all' + - fsspec ; extra == 'all' + - cupy-cuda12x ; sys_platform != 'darwin' and extra == 'all' + - ormsgpack>=1.7.0 ; extra == 'all' + - requests ; extra == 'all' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'all' + - opentelemetry-sdk>=1.30.0 ; extra == 'all' + - gymnasium==1.2.2 ; extra == 'all' + - dm-tree ; extra == 'all' + - pyyaml ; extra == 'all' + - grpcio!=1.56.0 ; sys_platform == 'darwin' and extra == 'all' + - aiohttp>=3.13.3 ; extra == 'all' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'all' + - numpy>=1.20 ; extra == 'all' + - lz4 ; extra == 'all-cpp' + - fastapi ; extra == 'all-cpp' + - tensorboardx>=1.9 ; extra == 'all-cpp' + - opencensus ; extra == 'all-cpp' + - opentelemetry-exporter-prometheus ; extra == 'all-cpp' + - prometheus-client>=0.7.1 ; extra == 'all-cpp' + - colorful ; extra == 'all-cpp' + - scipy ; extra == 'all-cpp' + - pandas>=1.3 ; extra == 'all-cpp' + - pyarrow>=9.0.0 ; extra == 'all-cpp' + - memray ; sys_platform != 'win32' and extra == 'all-cpp' + - grpcio>=1.42.0 ; extra == 'all-cpp' + - grpcio ; extra == 'all-cpp' + - aiohttp-cors ; extra == 'all-cpp' + - opentelemetry-proto ; extra == 'all-cpp' + - uvicorn[standard] ; extra == 'all-cpp' + - celery ; extra == 'all-cpp' + - smart-open ; extra == 'all-cpp' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'all-cpp' + - ray-cpp==2.54.1 ; extra == 'all-cpp' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'all-cpp' + - pandas ; extra == 'all-cpp' + - pyopenssl ; extra == 'all-cpp' + - watchfiles ; extra == 'all-cpp' + - starlette ; extra == 'all-cpp' + - fsspec ; extra == 'all-cpp' + - cupy-cuda12x ; sys_platform != 'darwin' and extra == 'all-cpp' + - ormsgpack>=1.7.0 ; extra == 'all-cpp' + - requests ; extra == 'all-cpp' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'all-cpp' + - opentelemetry-sdk>=1.30.0 ; extra == 'all-cpp' + - gymnasium==1.2.2 ; extra == 'all-cpp' + - dm-tree ; extra == 'all-cpp' + - pyyaml ; extra == 'all-cpp' + - grpcio!=1.56.0 ; sys_platform == 'darwin' and extra == 'all-cpp' + - aiohttp>=3.13.3 ; extra == 'all-cpp' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'all-cpp' + - numpy>=1.20 ; extra == 'all-cpp' + - nixl>=0.6.1 ; extra == 'llm' + - fastapi ; extra == 'llm' + - hf-transfer ; extra == 'llm' + - opencensus ; extra == 'llm' + - opentelemetry-exporter-prometheus ; extra == 'llm' + - prometheus-client>=0.7.1 ; extra == 'llm' + - colorful ; extra == 'llm' + - pandas>=1.3 ; extra == 'llm' + - pyarrow>=9.0.0 ; extra == 'llm' + - ninja ; extra == 'llm' + - grpcio>=1.42.0 ; extra == 'llm' + - aiohttp-cors ; extra == 'llm' + - opentelemetry-proto ; extra == 'llm' + - uvicorn[standard] ; extra == 'llm' + - smart-open ; extra == 'llm' + - py-spy>=0.2.0 ; python_full_version < '3.12' and extra == 'llm' + - jsonref>=1.1.0 ; extra == 'llm' + - vllm[audio]>=0.15.0 ; extra == 'llm' + - meson ; extra == 'llm' + - virtualenv>=20.0.24,!=20.21.1 ; extra == 'llm' + - async-timeout ; python_full_version < '3.11' and extra == 'llm' + - watchfiles ; extra == 'llm' + - starlette ; extra == 'llm' + - fsspec ; extra == 'llm' + - requests ; extra == 'llm' + - pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,!=2.10.*,!=2.11.*,<3 ; extra == 'llm' + - opentelemetry-sdk>=1.30.0 ; extra == 'llm' + - aiohttp>=3.13.3 ; extra == 'llm' + - transformers>=4.57.3 ; extra == 'llm' + - py-spy>=0.4.0 ; python_full_version >= '3.12' and extra == 'llm' + - pybind11 ; extra == 'llm' + - typer ; extra == 'llm' + - numpy>=1.20 ; extra == 'llm' + - jsonschema ; extra == 'llm' + requires_python: '>=3.10' +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002 + md5: d7d95fc8287ea7bf33e0e7116d2b95ec + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - ncurses >=6.5,<7.0a0 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 345073 + timestamp: 1765813471974 +- conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.3-h68b038d_0.conda + sha256: 4614af680aa0920e82b953fece85a03007e0719c3399f13d7de64176874b80d5 + md5: eefd65452dfe7cce476a519bece46704 + depends: + - __osx >=10.13 + - ncurses >=6.5,<7.0a0 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 317819 + timestamp: 1765813692798 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.3-h46df422_0.conda + sha256: a77010528efb4b548ac2a4484eaf7e1c3907f2aec86123ed9c5212ae44502477 + md5: f8381319127120ce51e081dce4865cf4 + depends: + - __osx >=11.0 + - ncurses >=6.5,<7.0a0 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 313930 + timestamp: 1765813902568 +- pypi: https://files.pythonhosted.org/packages/20/2e/409703d645363352a20c944f5d119bdae3eb3034051a53724a7c5fee12b8/redis-4.6.0-py3-none-any.whl + name: redis + version: 4.6.0 + sha256: e2b03db868160ee4591de3cb90d40ebb50a90dd302138775937f6a42b7ed183c + requires_dist: + - async-timeout>=4.0.2 ; python_full_version <= '3.11.2' + - importlib-metadata>=1.0 ; python_full_version < '3.8' + - typing-extensions ; python_full_version < '3.8' + - hiredis>=1.0.0 ; extra == 'hiredis' + - cryptography>=36.0.1 ; extra == 'ocsp' + - pyopenssl==20.0.1 ; extra == 'ocsp' + - requests>=2.26.0 ; extra == 'ocsp' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl + name: referencing + version: 0.37.0 + sha256: 381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231 + requires_dist: + - attrs>=22.2.0 + - rpds-py>=0.7.0 + - typing-extensions>=4.4.0 ; python_full_version < '3.13' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/d7/8e/7540e8a2036f79a125c1d2ebadf69ed7901608859186c856fa0388ef4197/requests-2.33.1-py3-none-any.whl + name: requests + version: 2.33.1 + sha256: 4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a + requires_dist: + - charset-normalizer>=2,<4 + - idna>=2.5,<4 + - urllib3>=1.26,<3 + - certifi>=2023.5.7 + - pysocks>=1.5.6,!=1.5.7 ; extra == 'socks' + - chardet>=3.0.2,<8 ; extra == 'use-chardet-on-py3' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/3b/5d/63d4ae3b9daea098d5d6f5da83984853c1bbacd5dc826764b249fe119d24/requests_oauthlib-2.0.0-py2.py3-none-any.whl + name: requests-oauthlib + version: 2.0.0 + sha256: 7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36 + requires_dist: + - oauthlib>=3.0.0 + - requests>=2.0.0 + - oauthlib[signedtoken]>=3.0.0 ; extra == 'rsa' + requires_python: '>=3.4' +- pypi: https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl + name: requests-toolbelt + version: 1.0.0 + sha256: cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06 + requires_dist: + - requests>=2.0.1,<3.0.0 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*' +- pypi: https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl + name: rich + version: 14.3.3 + sha256: 793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d + requires_dist: + - ipywidgets>=7.5.1,<9 ; extra == 'jupyter' + - markdown-it-py>=2.2.0 + - pygments>=2.13.0,<3.0.0 + requires_python: '>=3.8.0' +- pypi: https://files.pythonhosted.org/packages/06/0c/0c411a0ec64ccb6d104dcabe0e713e05e153a9a2c3c2bd2b32ce412166fe/rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl + name: rpds-py + version: 0.30.0 + sha256: 679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/19/6a/4ba3d0fb7297ebae71171822554abe48d7cab29c28b8f9f2c04b79988c05/rpds_py-0.30.0-cp310-cp310-macosx_11_0_arm64.whl + name: rpds-py + version: 0.30.0 + sha256: 4cc2206b76b4f576934f0ed374b10d7ca5f457858b157ca52064bdfc26b9fc00 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/2b/60/19f7884db5d5603edf3c6bce35408f45ad3e97e10007df0e17dd57af18f8/rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl + name: rpds-py + version: 0.30.0 + sha256: ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/61/b5/707f6cf0066a6412aacc11d17920ea2e19e5b2f04081c64526eb35b5c6e7/rpds_py-0.30.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: rpds-py + version: 0.30.0 + sha256: 0c0e95f6819a19965ff420f65578bacb0b00f251fefe2c8b23347c37174271f3 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/86/81/dad16382ebbd3d0e0328776d8fd7ca94220e4fa0798d1dc5e7da48cb3201/rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl + name: rpds-py + version: 0.30.0 + sha256: 68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/ce/81/9a91c0111ce1758c92516a3e44776920b579d9a7c09b2b06b642d4de3f0f/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: rpds-py + version: 0.30.0 + sha256: 47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/6d/4f/d073e09df851cfa251ef7840007d04db3293a0482ce607d2b993926089be/s3transfer-0.13.1-py3-none-any.whl + name: s3transfer + version: 0.13.1 + sha256: a981aa7429be23fe6dfc13e80e4020057cbab622b08c0315288758d67cabc724 + requires_dist: + - botocore>=1.37.4,<2.0a0 + - botocore[crt]>=1.37.4,<2.0a0 ; extra == 'crt' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/9d/76/f789f7a86709c6b087c5a2f52f911838cad707cc613162401badc665acfe/setuptools-82.0.1-py3-none-any.whl + name: setuptools + version: 82.0.1 + sha256: a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb + requires_dist: + - pytest>=6,!=8.1.* ; extra == 'test' + - virtualenv>=13.0.0 ; extra == 'test' + - wheel>=0.44.0 ; extra == 'test' + - pip>=19.1 ; extra == 'test' + - packaging>=24.2 ; extra == 'test' + - jaraco-envs>=2.2 ; extra == 'test' + - pytest-xdist>=3 ; extra == 'test' + - jaraco-path>=3.7.2 ; extra == 'test' + - build[virtualenv]>=1.0.3 ; extra == 'test' + - filelock>=3.4.0 ; extra == 'test' + - ini2toml[lite]>=0.14 ; extra == 'test' + - tomli-w>=1.0.0 ; extra == 'test' + - pytest-timeout ; extra == 'test' + - pytest-perf ; sys_platform != 'cygwin' and extra == 'test' + - jaraco-develop>=7.21 ; python_full_version >= '3.9' and sys_platform != 'cygwin' and extra == 'test' + - pytest-home>=0.5 ; extra == 'test' + - pytest-subprocess ; extra == 'test' + - pyproject-hooks!=1.1 ; extra == 'test' + - jaraco-test>=5.5 ; extra == 'test' + - sphinx>=3.5 ; extra == 'doc' + - jaraco-packaging>=9.3 ; extra == 'doc' + - rst-linker>=1.9 ; extra == 'doc' + - furo ; extra == 'doc' + - sphinx-lint ; extra == 'doc' + - jaraco-tidelift>=1.4 ; extra == 'doc' + - pygments-github-lexers==0.0.5 ; extra == 'doc' + - sphinx-favicon ; extra == 'doc' + - sphinx-inline-tabs ; extra == 'doc' + - sphinx-reredirects ; extra == 'doc' + - sphinxcontrib-towncrier ; extra == 'doc' + - sphinx-notfound-page>=1,<2 ; extra == 'doc' + - pyproject-hooks!=1.1 ; extra == 'doc' + - towncrier<24.7 ; extra == 'doc' + - packaging>=24.2 ; extra == 'core' + - more-itertools>=8.8 ; extra == 'core' + - jaraco-text>=3.7 ; extra == 'core' + - importlib-metadata>=6 ; python_full_version < '3.10' and extra == 'core' + - tomli>=2.0.1 ; python_full_version < '3.11' and extra == 'core' + - wheel>=0.43.0 ; extra == 'core' + - jaraco-functools>=4 ; extra == 'core' + - more-itertools ; extra == 'core' + - pytest-checkdocs>=2.4 ; extra == 'check' + - pytest-ruff>=0.2.1 ; sys_platform != 'cygwin' and extra == 'check' + - ruff>=0.13.0 ; sys_platform != 'cygwin' and extra == 'check' + - pytest-cov ; extra == 'cover' + - pytest-enabler>=2.2 ; extra == 'enabler' + - pytest-mypy ; extra == 'type' + - mypy==1.18.* ; extra == 'type' + - importlib-metadata>=7.0.2 ; python_full_version < '3.10' and extra == 'type' + - jaraco-develop>=7.21 ; sys_platform != 'cygwin' and extra == 'type' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl + name: six + version: 1.17.0 + sha256: 4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*' +- pypi: https://files.pythonhosted.org/packages/01/b1/11c03e05bd2a2da590c1b77c8455f40eb505888a2683c4e41b487d79568c/snowflake_connector_python-4.4.0.tar.gz + name: snowflake-connector-python + version: 4.4.0 + sha256: 648f49029d699591af0f253e81c5bf60efc4411c7b0149ef074a59a038210a3b + requires_dist: + - asn1crypto>0.24.0,<2.0.0 + - cryptography>=46.0.5 + - pyopenssl>=24.0.0 + - pyjwt>=2.10.1,<3.0.0 + - pytz + - requests>=2.32.4,<3.0.0 + - packaging + - charset-normalizer>=2,<4 + - idna>=3.7,<4 + - urllib3>=1.26.5,<2.0.0 ; python_full_version < '3.10' + - certifi>=2024.7.4 + - typing-extensions>=4.3,<5 + - filelock>=3.5,<4 + - sortedcontainers>=2.4.0 + - platformdirs>=2.6.0,<5.0.0 + - tomlkit + - boto3>=1.24 + - botocore>=1.24 + - boto3>=1.24 ; extra == 'boto' + - botocore>=1.24 ; extra == 'boto' + - cython ; extra == 'development' + - coverage ; extra == 'development' + - mitmproxy>=12.0.0 ; python_full_version >= '3.12' and extra == 'development' + - more-itertools ; extra == 'development' + - numpy<=2.4.3 ; extra == 'development' + - pendulum!=2.1.1 ; extra == 'development' + - pexpect ; extra == 'development' + - pytest<7.5.0 ; extra == 'development' + - pytest-asyncio ; extra == 'development' + - pytest-cov ; extra == 'development' + - pytest-rerunfailures<16.0 ; extra == 'development' + - pytest-timeout ; extra == 'development' + - pytest-xdist ; extra == 'development' + - pytzdata ; extra == 'development' + - responses ; extra == 'development' + - pandas>=1.0.0,<3.0.0 ; python_full_version < '3.13' and extra == 'pandas' + - pandas>=2.1.2,<3.0.0 ; python_full_version >= '3.13' and extra == 'pandas' + - pyarrow>=14.0.1 ; extra == 'pandas' + - keyring>=23.1.0,<26.0.0 ; extra == 'secure-local-storage' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/a7/31/0d6a1da486dc13263f43cdad0bbacdd041616c32220b9bcbff79160bdcc1/snowflake_connector_python-4.4.0-cp310-cp310-macosx_11_0_arm64.whl + name: snowflake-connector-python + version: 4.4.0 + sha256: fb628d5ea1999e23bfbaabce4125eb44d56605ca5634b8b1d6092ab22d555598 + requires_dist: + - asn1crypto>0.24.0,<2.0.0 + - cryptography>=46.0.5 + - pyopenssl>=24.0.0 + - pyjwt>=2.10.1,<3.0.0 + - pytz + - requests>=2.32.4,<3.0.0 + - packaging + - charset-normalizer>=2,<4 + - idna>=3.7,<4 + - urllib3>=1.26.5,<2.0.0 ; python_full_version < '3.10' + - certifi>=2024.7.4 + - typing-extensions>=4.3,<5 + - filelock>=3.5,<4 + - sortedcontainers>=2.4.0 + - platformdirs>=2.6.0,<5.0.0 + - tomlkit + - boto3>=1.24 + - botocore>=1.24 + - boto3>=1.24 ; extra == 'boto' + - botocore>=1.24 ; extra == 'boto' + - cython ; extra == 'development' + - coverage ; extra == 'development' + - mitmproxy>=12.0.0 ; python_full_version >= '3.12' and extra == 'development' + - more-itertools ; extra == 'development' + - numpy<=2.4.3 ; extra == 'development' + - pendulum!=2.1.1 ; extra == 'development' + - pexpect ; extra == 'development' + - pytest<7.5.0 ; extra == 'development' + - pytest-asyncio ; extra == 'development' + - pytest-cov ; extra == 'development' + - pytest-rerunfailures<16.0 ; extra == 'development' + - pytest-timeout ; extra == 'development' + - pytest-xdist ; extra == 'development' + - pytzdata ; extra == 'development' + - responses ; extra == 'development' + - pandas>=1.0.0,<3.0.0 ; python_full_version < '3.13' and extra == 'pandas' + - pandas>=2.1.2,<3.0.0 ; python_full_version >= '3.13' and extra == 'pandas' + - pyarrow>=14.0.1 ; extra == 'pandas' + - keyring>=23.1.0,<26.0.0 ; extra == 'secure-local-storage' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/ab/2f/4e1d2c1f93fa0009a4f34ba5168060e719cb1d9fef319fb0970f1e0bd8d6/snowflake_connector_python-4.4.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + name: snowflake-connector-python + version: 4.4.0 + sha256: 9b1a28f843c1c0b582db7854789525d0c8aac4ea5c56e31113684e38220d0af9 + requires_dist: + - asn1crypto>0.24.0,<2.0.0 + - cryptography>=46.0.5 + - pyopenssl>=24.0.0 + - pyjwt>=2.10.1,<3.0.0 + - pytz + - requests>=2.32.4,<3.0.0 + - packaging + - charset-normalizer>=2,<4 + - idna>=3.7,<4 + - urllib3>=1.26.5,<2.0.0 ; python_full_version < '3.10' + - certifi>=2024.7.4 + - typing-extensions>=4.3,<5 + - filelock>=3.5,<4 + - sortedcontainers>=2.4.0 + - platformdirs>=2.6.0,<5.0.0 + - tomlkit + - boto3>=1.24 + - botocore>=1.24 + - boto3>=1.24 ; extra == 'boto' + - botocore>=1.24 ; extra == 'boto' + - cython ; extra == 'development' + - coverage ; extra == 'development' + - mitmproxy>=12.0.0 ; python_full_version >= '3.12' and extra == 'development' + - more-itertools ; extra == 'development' + - numpy<=2.4.3 ; extra == 'development' + - pendulum!=2.1.1 ; extra == 'development' + - pexpect ; extra == 'development' + - pytest<7.5.0 ; extra == 'development' + - pytest-asyncio ; extra == 'development' + - pytest-cov ; extra == 'development' + - pytest-rerunfailures<16.0 ; extra == 'development' + - pytest-timeout ; extra == 'development' + - pytest-xdist ; extra == 'development' + - pytzdata ; extra == 'development' + - responses ; extra == 'development' + - pandas>=1.0.0,<3.0.0 ; python_full_version < '3.13' and extra == 'pandas' + - pandas>=2.1.2,<3.0.0 ; python_full_version >= '3.13' and extra == 'pandas' + - pyarrow>=14.0.1 ; extra == 'pandas' + - keyring>=23.1.0,<26.0.0 ; extra == 'secure-local-storage' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl + name: sortedcontainers + version: 2.4.0 + sha256: a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0 +- pypi: https://files.pythonhosted.org/packages/46/2c/9664130905f03db57961b8980b05cab624afd114bf2be2576628a9f22da4/sqlalchemy-2.0.48-py3-none-any.whl + name: sqlalchemy + version: 2.0.48 + sha256: a66fe406437dd65cacd96a72689a3aaaecaebbcd62d81c5ac1c0fdbeac835096 + requires_dist: + - importlib-metadata ; python_full_version < '3.8' + - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64' + - typing-extensions>=4.6.0 + - greenlet>=1 ; extra == 'asyncio' + - mypy>=0.910 ; extra == 'mypy' + - pyodbc ; extra == 'mssql' + - pymssql ; extra == 'mssql-pymssql' + - pyodbc ; extra == 'mssql-pyodbc' + - mysqlclient>=1.4.0 ; extra == 'mysql' + - mysql-connector-python ; extra == 'mysql-connector' + - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector' + - cx-oracle>=8 ; extra == 'oracle' + - oracledb>=1.0.1 ; extra == 'oracle-oracledb' + - psycopg2>=2.7 ; extra == 'postgresql' + - pg8000>=1.29.1 ; extra == 'postgresql-pg8000' + - greenlet>=1 ; extra == 'postgresql-asyncpg' + - asyncpg ; extra == 'postgresql-asyncpg' + - psycopg2-binary ; extra == 'postgresql-psycopg2binary' + - psycopg2cffi ; extra == 'postgresql-psycopg2cffi' + - psycopg>=3.0.7 ; extra == 'postgresql-psycopg' + - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary' + - pymysql ; extra == 'pymysql' + - greenlet>=1 ; extra == 'aiomysql' + - aiomysql>=0.2.0 ; extra == 'aiomysql' + - greenlet>=1 ; extra == 'aioodbc' + - aioodbc ; extra == 'aioodbc' + - greenlet>=1 ; extra == 'asyncmy' + - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy' + - greenlet>=1 ; extra == 'aiosqlite' + - aiosqlite ; extra == 'aiosqlite' + - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite' + - sqlcipher3-binary ; extra == 'sqlcipher' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/5c/ad/6c4395649a212a6c603a72c5b9ab5dce3135a1546cfdffa3c427e71fd535/sqlalchemy-2.0.48-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: sqlalchemy + version: 2.0.48 + sha256: 10853a53a4a00417a00913d270dddda75815fcb80675874285f41051c094d7dd + requires_dist: + - importlib-metadata ; python_full_version < '3.8' + - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64' + - typing-extensions>=4.6.0 + - greenlet>=1 ; extra == 'asyncio' + - mypy>=0.910 ; extra == 'mypy' + - pyodbc ; extra == 'mssql' + - pymssql ; extra == 'mssql-pymssql' + - pyodbc ; extra == 'mssql-pyodbc' + - mysqlclient>=1.4.0 ; extra == 'mysql' + - mysql-connector-python ; extra == 'mysql-connector' + - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector' + - cx-oracle>=8 ; extra == 'oracle' + - oracledb>=1.0.1 ; extra == 'oracle-oracledb' + - psycopg2>=2.7 ; extra == 'postgresql' + - pg8000>=1.29.1 ; extra == 'postgresql-pg8000' + - greenlet>=1 ; extra == 'postgresql-asyncpg' + - asyncpg ; extra == 'postgresql-asyncpg' + - psycopg2-binary ; extra == 'postgresql-psycopg2binary' + - psycopg2cffi ; extra == 'postgresql-psycopg2cffi' + - psycopg>=3.0.7 ; extra == 'postgresql-psycopg' + - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary' + - pymysql ; extra == 'pymysql' + - greenlet>=1 ; extra == 'aiomysql' + - aiomysql>=0.2.0 ; extra == 'aiomysql' + - greenlet>=1 ; extra == 'aioodbc' + - aioodbc ; extra == 'aioodbc' + - greenlet>=1 ; extra == 'asyncmy' + - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy' + - greenlet>=1 ; extra == 'aiosqlite' + - aiosqlite ; extra == 'aiosqlite' + - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite' + - sqlcipher3-binary ; extra == 'sqlcipher' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/9a/67/1235676e93dd3b742a4a8eddfae49eea46c85e3eed29f0da446a8dd57500/sqlalchemy-2.0.48-cp310-cp310-macosx_11_0_arm64.whl + name: sqlalchemy + version: 2.0.48 + sha256: 7001dc9d5f6bb4deb756d5928eaefe1930f6f4179da3924cbd95ee0e9f4dce89 + requires_dist: + - importlib-metadata ; python_full_version < '3.8' + - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64' + - typing-extensions>=4.6.0 + - greenlet>=1 ; extra == 'asyncio' + - mypy>=0.910 ; extra == 'mypy' + - pyodbc ; extra == 'mssql' + - pymssql ; extra == 'mssql-pymssql' + - pyodbc ; extra == 'mssql-pyodbc' + - mysqlclient>=1.4.0 ; extra == 'mysql' + - mysql-connector-python ; extra == 'mysql-connector' + - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector' + - cx-oracle>=8 ; extra == 'oracle' + - oracledb>=1.0.1 ; extra == 'oracle-oracledb' + - psycopg2>=2.7 ; extra == 'postgresql' + - pg8000>=1.29.1 ; extra == 'postgresql-pg8000' + - greenlet>=1 ; extra == 'postgresql-asyncpg' + - asyncpg ; extra == 'postgresql-asyncpg' + - psycopg2-binary ; extra == 'postgresql-psycopg2binary' + - psycopg2cffi ; extra == 'postgresql-psycopg2cffi' + - psycopg>=3.0.7 ; extra == 'postgresql-psycopg' + - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary' + - pymysql ; extra == 'pymysql' + - greenlet>=1 ; extra == 'aiomysql' + - aiomysql>=0.2.0 ; extra == 'aiomysql' + - greenlet>=1 ; extra == 'aioodbc' + - aioodbc ; extra == 'aioodbc' + - greenlet>=1 ; extra == 'asyncmy' + - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy' + - greenlet>=1 ; extra == 'aiosqlite' + - aiosqlite ; extra == 'aiosqlite' + - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite' + - sqlcipher3-binary ; extra == 'sqlcipher' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/f2/5e/327428a034407651a048f5e624361adf3f9fbac9d0fa98e981e9c6ff2f5e/sqlalchemy-2.0.48-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: sqlalchemy + version: 2.0.48 + sha256: 426c5ca86415d9b8945c7073597e10de9644802e2ff502b8e1f11a7a2642856b + requires_dist: + - importlib-metadata ; python_full_version < '3.8' + - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64' + - typing-extensions>=4.6.0 + - greenlet>=1 ; extra == 'asyncio' + - mypy>=0.910 ; extra == 'mypy' + - pyodbc ; extra == 'mssql' + - pymssql ; extra == 'mssql-pymssql' + - pyodbc ; extra == 'mssql-pyodbc' + - mysqlclient>=1.4.0 ; extra == 'mysql' + - mysql-connector-python ; extra == 'mysql-connector' + - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector' + - cx-oracle>=8 ; extra == 'oracle' + - oracledb>=1.0.1 ; extra == 'oracle-oracledb' + - psycopg2>=2.7 ; extra == 'postgresql' + - pg8000>=1.29.1 ; extra == 'postgresql-pg8000' + - greenlet>=1 ; extra == 'postgresql-asyncpg' + - asyncpg ; extra == 'postgresql-asyncpg' + - psycopg2-binary ; extra == 'postgresql-psycopg2binary' + - psycopg2cffi ; extra == 'postgresql-psycopg2cffi' + - psycopg>=3.0.7 ; extra == 'postgresql-psycopg' + - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary' + - pymysql ; extra == 'pymysql' + - greenlet>=1 ; extra == 'aiomysql' + - aiomysql>=0.2.0 ; extra == 'aiomysql' + - greenlet>=1 ; extra == 'aioodbc' + - aioodbc ; extra == 'aioodbc' + - greenlet>=1 ; extra == 'asyncmy' + - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy' + - greenlet>=1 ; extra == 'aiosqlite' + - aiosqlite ; extra == 'aiosqlite' + - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite' + - sqlcipher3-binary ; extra == 'sqlcipher' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/f7/b3/f437eaa1cf028bb3c927172c7272366393e73ccd104dcf5b6963f4ab5318/sqlalchemy-2.0.48-cp314-cp314-macosx_11_0_arm64.whl + name: sqlalchemy + version: 2.0.48 + sha256: e2d0d88686e3d35a76f3e15a34e8c12d73fc94c1dea1cd55782e695cc14086dd + requires_dist: + - importlib-metadata ; python_full_version < '3.8' + - greenlet>=1 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64' + - typing-extensions>=4.6.0 + - greenlet>=1 ; extra == 'asyncio' + - mypy>=0.910 ; extra == 'mypy' + - pyodbc ; extra == 'mssql' + - pymssql ; extra == 'mssql-pymssql' + - pyodbc ; extra == 'mssql-pyodbc' + - mysqlclient>=1.4.0 ; extra == 'mysql' + - mysql-connector-python ; extra == 'mysql-connector' + - mariadb>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10 ; extra == 'mariadb-connector' + - cx-oracle>=8 ; extra == 'oracle' + - oracledb>=1.0.1 ; extra == 'oracle-oracledb' + - psycopg2>=2.7 ; extra == 'postgresql' + - pg8000>=1.29.1 ; extra == 'postgresql-pg8000' + - greenlet>=1 ; extra == 'postgresql-asyncpg' + - asyncpg ; extra == 'postgresql-asyncpg' + - psycopg2-binary ; extra == 'postgresql-psycopg2binary' + - psycopg2cffi ; extra == 'postgresql-psycopg2cffi' + - psycopg>=3.0.7 ; extra == 'postgresql-psycopg' + - psycopg[binary]>=3.0.7 ; extra == 'postgresql-psycopgbinary' + - pymysql ; extra == 'pymysql' + - greenlet>=1 ; extra == 'aiomysql' + - aiomysql>=0.2.0 ; extra == 'aiomysql' + - greenlet>=1 ; extra == 'aioodbc' + - aioodbc ; extra == 'aioodbc' + - greenlet>=1 ; extra == 'asyncmy' + - asyncmy>=0.2.3,!=0.2.4,!=0.2.6 ; extra == 'asyncmy' + - greenlet>=1 ; extra == 'aiosqlite' + - aiosqlite ; extra == 'aiosqlite' + - typing-extensions!=3.10.0.1 ; extra == 'aiosqlite' + - sqlcipher3-binary ; extra == 'sqlcipher' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/69/13/f8c5dd59b119feee28cce53f23361d955cd46d0612697d49db0070f41ea9/sqlglot-30.2.1-py3-none-any.whl + name: sqlglot + version: 30.2.1 + sha256: f23d9ee9427ef9d20df15f9b0ffa57d9eb45e52b012219a349d1e6b50ed926d1 + requires_dist: + - duckdb>=0.6 ; extra == 'dev' + - sqlglot-mypy>=1.19.1.post1 ; extra == 'dev' + - setuptools-scm ; extra == 'dev' + - pandas ; extra == 'dev' + - pandas-stubs ; extra == 'dev' + - python-dateutil ; extra == 'dev' + - pytz ; extra == 'dev' + - pdoc ; extra == 'dev' + - pre-commit ; extra == 'dev' + - ruff==0.15.6 ; extra == 'dev' + - types-python-dateutil ; extra == 'dev' + - types-pytz ; extra == 'dev' + - typing-extensions ; extra == 'dev' + - pyperf ; extra == 'dev' + - sqlglotc==30.2.1 ; extra == 'c' + - sqlglotrs==0.13.0 ; extra == 'rs' + - sqlglotc==30.2.1 ; extra == 'rs' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/0b/c9/584bc9651441b4ba60cc4d557d8a547b5aff901af35bda3a4ee30c819b82/starlette-1.0.0-py3-none-any.whl + name: starlette + version: 1.0.0 + sha256: d3ec55e0bb321692d275455ddfd3df75fff145d009685eb40dc91fc66b03d38b + requires_dist: + - anyio>=3.6.2,<5 + - typing-extensions>=4.10.0 ; python_full_version < '3.13' + - httpx>=0.27.0,<0.29.0 ; extra == 'full' + - itsdangerous ; extra == 'full' + - jinja2 ; extra == 'full' + - python-multipart>=0.0.18 ; extra == 'full' + - pyyaml ; extra == 'full' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl + name: tabulate + version: 0.10.0 + sha256: f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3 + requires_dist: + - wcwidth ; extra == 'widechars' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/d2/3f/8ba87d9e287b9d385a02a7114ddcef61b26f86411e121c9003eb509a1773/tenacity-8.5.0-py3-none-any.whl + name: tenacity + version: 8.5.0 + sha256: b594c2a5945830c267ce6b79a166228323ed52718f30302c1359836112346687 + requires_dist: + - reno ; extra == 'doc' + - sphinx ; extra == 'doc' + - pytest ; extra == 'test' + - tornado>=4.5 ; extra == 'test' + - typeguard ; extra == 'test' + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/3e/f8/6425ff800894784160290bcb9737878d910b6da6a08633bfe7f2ed8c9ae3/testcontainers-4.9.0-py3-none-any.whl + name: testcontainers + version: 4.9.0 + sha256: c6fee929990972c40bf6b91b7072c94064ff3649b405a14fde0274c8b2479d32 + requires_dist: + - azure-cosmos ; extra == 'cosmosdb' + - azure-storage-blob>=12.19,<13.0 ; extra == 'azurite' + - bcrypt ; extra == 'registry' + - boto3 ; extra == 'aws' or extra == 'localstack' + - cassandra-driver==3.29.1 ; extra == 'scylla' + - chromadb-client ; extra == 'chroma' + - clickhouse-driver ; extra == 'clickhouse' + - cryptography ; extra == 'mailpit' or extra == 'sftp' + - docker + - google-cloud-datastore>=2 ; extra == 'google' + - google-cloud-pubsub>=2 ; extra == 'google' + - httpx ; extra == 'aws' or extra == 'generic' or extra == 'test-module-import' + - ibm-db-sa ; extra == 'db2' + - influxdb ; extra == 'influxdb' + - influxdb-client ; extra == 'influxdb' + - kubernetes ; extra == 'k3s' + - minio ; extra == 'minio' + - nats-py ; extra == 'nats' + - neo4j ; extra == 'neo4j' + - opensearch-py ; extra == 'opensearch' + - oracledb ; extra == 'oracle' or extra == 'oracle-free' + - pika ; extra == 'rabbitmq' + - pymongo ; extra == 'mongodb' + - pymssql ; extra == 'mssql' + - pymysql[rsa] ; extra == 'mysql' + - python-arango>=7.8,<8.0 ; extra == 'arangodb' + - python-dotenv + - python-keycloak ; extra == 'keycloak' + - pyyaml ; extra == 'k3s' + - qdrant-client ; extra == 'qdrant' + - redis ; extra == 'generic' or extra == 'redis' + - selenium ; extra == 'selenium' + - sqlalchemy ; extra == 'db2' or extra == 'mssql' or extra == 'mysql' or extra == 'oracle' or extra == 'oracle-free' + - trino ; extra == 'trino' + - typing-extensions + - urllib3 + - weaviate-client>=4.5.4,<5.0.0 ; extra == 'weaviate' + - wrapt + requires_python: '>=3.9,<4.0' +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + sha256: cafeec44494f842ffeca27e9c8b0c27ed714f93ac77ddadc6aaf726b5554ebac + md5: cffd3bdd58090148f4cfcd831f4b26ab + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libzlib >=1.3.1,<2.0a0 + constrains: + - xorg-libx11 >=1.8.12,<2.0a0 + license: TCL + license_family: BSD + purls: [] + size: 3301196 + timestamp: 1769460227866 +- conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h7142dee_3.conda + sha256: 7f0d9c320288532873e2d8486c331ec6d87919c9028208d3f6ac91dc8f99a67b + md5: 6e6efb7463f8cef69dbcb4c2205bf60e + depends: + - __osx >=10.13 + - libzlib >=1.3.1,<2.0a0 + license: TCL + license_family: BSD + purls: [] + size: 3282953 + timestamp: 1769460532442 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h010d191_3.conda + sha256: 799cab4b6cde62f91f750149995d149bc9db525ec12595e8a1d91b9317f038b3 + md5: a9d86bc62f39b94c4661716624eb21b0 + depends: + - __osx >=11.0 + - libzlib >=1.3.1,<2.0a0 + license: TCL + license_family: BSD + purls: [] + size: 3127137 + timestamp: 1769460817696 +- pypi: https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl + name: toml + version: 0.10.2 + sha256: 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b + requires_python: '>=2.6,!=3.0.*,!=3.1.*,!=3.2.*' +- pypi: https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl + name: tomli + version: 2.4.1 + sha256: 0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/b5/11/87d6d29fb5d237229d67973a6c9e06e048f01cf4994dee194ab0ea841814/tomlkit-0.14.0-py3-none-any.whl + name: tomlkit + version: 0.14.0 + sha256: 592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl + name: toolz + version: 1.1.0 + sha256: 15ccc861ac51c53696de0a5d6d4607f99c210739caf987b5d2054f3efed429d8 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl + name: tqdm + version: 4.67.3 + sha256: ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf + requires_dist: + - colorama ; sys_platform == 'win32' + - importlib-metadata ; python_full_version < '3.8' + - pytest>=6 ; extra == 'dev' + - pytest-cov ; extra == 'dev' + - pytest-timeout ; extra == 'dev' + - pytest-asyncio>=0.24 ; extra == 'dev' + - nbval ; extra == 'dev' + - requests ; extra == 'discord' + - slack-sdk ; extra == 'slack' + - requests ; extra == 'telegram' + - ipywidgets>=6 ; extra == 'notebook' + requires_python: '>=3.7' +- pypi: https://files.pythonhosted.org/packages/91/88/b55b3117287a8540b76dbdd87733808d4d01c8067a3b339408c250bb3600/typeguard-4.5.1-py3-none-any.whl + name: typeguard + version: 4.5.1 + sha256: 44d2bf329d49a244110a090b55f5f91aa82d9a9834ebfd30bcc73651e4a8cc40 + requires_dist: + - importlib-metadata>=3.6 ; python_full_version < '3.10' + - typing-extensions>=4.14.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/8b/fa/4f4d3bfca9ef6dd17d69ed18b96564c53b32d3ce774132308d0bee849f10/types_pymysql-1.1.0.20251220-py3-none-any.whl + name: types-pymysql + version: 1.1.0.20251220 + sha256: fa1082af7dea6c53b6caa5784241924b1296ea3a8d3bd060417352c5e10c0618 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl + name: typing-extensions + version: 4.15.0 + sha256: f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl + name: typing-inspection + version: 0.4.2 + sha256: 4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7 + requires_dist: + - typing-extensions>=4.12.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl + name: tzdata + version: '2025.3' + sha256: 06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1 + requires_python: '>=2' +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c + md5: ad659d0a2b3e47e38d829aa8cad2d610 + license: LicenseRef-Public-Domain + purls: [] + size: 119135 + timestamp: 1767016325805 +- pypi: https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl + name: urllib3 + version: 2.6.3 + sha256: bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4 + requires_dist: + - brotli>=1.2.0 ; platform_python_implementation == 'CPython' and extra == 'brotli' + - brotlicffi>=1.2.0.0 ; platform_python_implementation != 'CPython' and extra == 'brotli' + - h2>=4,<5 ; extra == 'h2' + - pysocks>=1.5.6,!=1.5.7,<2.0 ; extra == 'socks' + - backports-zstd>=1.0.0 ; python_full_version < '3.14' and extra == 'zstd' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl + name: uvicorn + version: 0.34.0 + sha256: 023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4 + requires_dist: + - click>=7.0 + - h11>=0.8 + - typing-extensions>=4.0 ; python_full_version < '3.11' + - colorama>=0.4 ; sys_platform == 'win32' and extra == 'standard' + - httptools>=0.6.3 ; extra == 'standard' + - python-dotenv>=0.13 ; extra == 'standard' + - pyyaml>=5.1 ; extra == 'standard' + - uvloop>=0.14.0,!=0.15.0,!=0.15.1 ; platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32' and extra == 'standard' + - watchfiles>=0.13 ; extra == 'standard' + - websockets>=10.4 ; extra == 'standard' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/f7/1f/4e5f8770c2cf4faa2c3ed3c19f9d4485ac9db0a6b029a7866921709bdc6c/uvicorn_worker-0.3.0-py3-none-any.whl + name: uvicorn-worker + version: 0.3.0 + sha256: ef0fe8aad27b0290a9e602a256b03f5a5da3a9e5f942414ca587b645ec77dd52 + requires_dist: + - gunicorn>=20.1.0 + - uvicorn>=0.15.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/0d/f8/a132124dfda0777e489ca86732e85e69afcd1ff7686647000050ba670689/uvloop-0.22.1-cp314-cp314-macosx_10_13_x86_64.whl + name: uvloop + version: 0.22.1 + sha256: 4baa86acedf1d62115c1dc6ad1e17134476688f08c6efd8a2ab076e815665c74 + requires_dist: + - aiohttp>=3.10.5 ; extra == 'test' + - flake8~=6.1 ; extra == 'test' + - psutil ; extra == 'test' + - pycodestyle~=2.11.0 ; extra == 'test' + - pyopenssl~=25.3.0 ; extra == 'test' + - mypy>=0.800 ; extra == 'test' + - setuptools>=60 ; extra == 'dev' + - cython~=3.0 ; extra == 'dev' + - sphinx~=4.1.2 ; extra == 'docs' + - sphinxcontrib-asyncio~=0.3.0 ; extra == 'docs' + - sphinx-rtd-theme~=0.5.2 ; extra == 'docs' + requires_python: '>=3.8.1' +- pypi: https://files.pythonhosted.org/packages/90/cd/b62bdeaa429758aee8de8b00ac0dd26593a9de93d302bff3d21439e9791d/uvloop-0.22.1-cp314-cp314-macosx_10_13_universal2.whl + name: uvloop + version: 0.22.1 + sha256: 3879b88423ec7e97cd4eba2a443aa26ed4e59b45e6b76aabf13fe2f27023a142 + requires_dist: + - aiohttp>=3.10.5 ; extra == 'test' + - flake8~=6.1 ; extra == 'test' + - psutil ; extra == 'test' + - pycodestyle~=2.11.0 ; extra == 'test' + - pyopenssl~=25.3.0 ; extra == 'test' + - mypy>=0.800 ; extra == 'test' + - setuptools>=60 ; extra == 'dev' + - cython~=3.0 ; extra == 'dev' + - sphinx~=4.1.2 ; extra == 'docs' + - sphinxcontrib-asyncio~=0.3.0 ; extra == 'docs' + - sphinx-rtd-theme~=0.5.2 ; extra == 'docs' + requires_python: '>=3.8.1' +- pypi: https://files.pythonhosted.org/packages/b3/f6/21657bb3beb5f8c57ce8be3b83f653dd7933c2fd00545ed1b092d464799a/uvloop-0.22.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: uvloop + version: 0.22.1 + sha256: 481c990a7abe2c6f4fc3d98781cc9426ebd7f03a9aaa7eb03d3bfc68ac2a46bd + requires_dist: + - aiohttp>=3.10.5 ; extra == 'test' + - flake8~=6.1 ; extra == 'test' + - psutil ; extra == 'test' + - pycodestyle~=2.11.0 ; extra == 'test' + - pyopenssl~=25.3.0 ; extra == 'test' + - mypy>=0.800 ; extra == 'test' + - setuptools>=60 ; extra == 'dev' + - cython~=3.0 ; extra == 'dev' + - sphinx~=4.1.2 ; extra == 'docs' + - sphinxcontrib-asyncio~=0.3.0 ; extra == 'docs' + - sphinx-rtd-theme~=0.5.2 ; extra == 'docs' + requires_python: '>=3.8.1' +- pypi: https://files.pythonhosted.org/packages/b5/35/60249e9fd07b32c665192cec7af29e06c7cd96fa1d08b84f012a56a0b38e/uvloop-0.22.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: uvloop + version: 0.22.1 + sha256: c1955d5a1dd43198244d47664a5858082a3239766a839b2102a269aaff7a4e25 + requires_dist: + - aiohttp>=3.10.5 ; extra == 'test' + - flake8~=6.1 ; extra == 'test' + - psutil ; extra == 'test' + - pycodestyle~=2.11.0 ; extra == 'test' + - pyopenssl~=25.3.0 ; extra == 'test' + - mypy>=0.800 ; extra == 'test' + - setuptools>=60 ; extra == 'dev' + - cython~=3.0 ; extra == 'dev' + - sphinx~=4.1.2 ; extra == 'docs' + - sphinxcontrib-asyncio~=0.3.0 ; extra == 'docs' + - sphinx-rtd-theme~=0.5.2 ; extra == 'docs' + requires_python: '>=3.8.1' +- pypi: https://files.pythonhosted.org/packages/ba/ae/6f6f9af7f590b319c94532b9567409ba11f4fa71af1148cab1bf48a07048/uvloop-0.22.1-cp310-cp310-macosx_10_9_x86_64.whl + name: uvloop + version: 0.22.1 + sha256: 7cd375a12b71d33d46af85a3343b35d98e8116134ba404bd657b3b1d15988792 + requires_dist: + - aiohttp>=3.10.5 ; extra == 'test' + - flake8~=6.1 ; extra == 'test' + - psutil ; extra == 'test' + - pycodestyle~=2.11.0 ; extra == 'test' + - pyopenssl~=25.3.0 ; extra == 'test' + - mypy>=0.800 ; extra == 'test' + - setuptools>=60 ; extra == 'dev' + - cython~=3.0 ; extra == 'dev' + - sphinx~=4.1.2 ; extra == 'docs' + - sphinxcontrib-asyncio~=0.3.0 ; extra == 'docs' + - sphinx-rtd-theme~=0.5.2 ; extra == 'docs' + requires_python: '>=3.8.1' +- pypi: https://files.pythonhosted.org/packages/eb/14/ecceb239b65adaaf7fde510aa8bd534075695d1e5f8dadfa32b5723d9cfb/uvloop-0.22.1-cp310-cp310-macosx_10_9_universal2.whl + name: uvloop + version: 0.22.1 + sha256: ef6f0d4cc8a9fa1f6a910230cd53545d9a14479311e87e3cb225495952eb672c + requires_dist: + - aiohttp>=3.10.5 ; extra == 'test' + - flake8~=6.1 ; extra == 'test' + - psutil ; extra == 'test' + - pycodestyle~=2.11.0 ; extra == 'test' + - pyopenssl~=25.3.0 ; extra == 'test' + - mypy>=0.800 ; extra == 'test' + - setuptools>=60 ; extra == 'dev' + - cython~=3.0 ; extra == 'dev' + - sphinx~=4.1.2 ; extra == 'docs' + - sphinxcontrib-asyncio~=0.3.0 ; extra == 'docs' + - sphinx-rtd-theme~=0.5.2 ; extra == 'docs' + requires_python: '>=3.8.1' +- pypi: https://files.pythonhosted.org/packages/7b/22/16d5331eaed1cb107b873f6ae1b69e9ced582fcf0c59a50cd84f403b1c32/watchfiles-1.1.1-cp314-cp314-macosx_11_0_arm64.whl + name: watchfiles + version: 1.1.1 + sha256: 39574d6370c4579d7f5d0ad940ce5b20db0e4117444e39b6d8f99db5676c52fd + requires_dist: + - anyio>=3.0.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/a7/1a/206e8cf2dd86fddf939165a57b4df61607a1e0add2785f170a3f616b7d9f/watchfiles-1.1.1-cp310-cp310-macosx_10_12_x86_64.whl + name: watchfiles + version: 1.1.1 + sha256: eef58232d32daf2ac67f42dea51a2c80f0d03379075d44a587051e63cc2e368c + requires_dist: + - anyio>=3.0.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/b3/0f/abaf5262b9c496b5dad4ed3c0e799cbecb1f8ea512ecb6ddd46646a9fca3/watchfiles-1.1.1-cp310-cp310-macosx_11_0_arm64.whl + name: watchfiles + version: 1.1.1 + sha256: 03fa0f5237118a0c5e496185cafa92878568b652a2e9a9382a5151b1a0380a43 + requires_dist: + - anyio>=3.0.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/b4/36/ded8aebea91919485b7bbabbd14f5f359326cb5ec218cd67074d1e426d74/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: watchfiles + version: 1.1.1 + sha256: 5c85794a4cfa094714fb9c08d4a218375b2b95b8ed1666e8677c349906246c05 + requires_dist: + - anyio>=3.0.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/c3/f4/0872229324ef69b2c3edec35e84bd57a1289e7d3fe74588048ed8947a323/watchfiles-1.1.1-cp314-cp314-macosx_10_12_x86_64.whl + name: watchfiles + version: 1.1.1 + sha256: d1715143123baeeaeadec0528bb7441103979a1d5f6fd0e1f915383fea7ea6d5 + requires_dist: + - anyio>=3.0.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/d5/dc/1a680b7458ffa3b14bb64878112aefc8f2e4f73c5af763cbf0bd43100658/watchfiles-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + name: watchfiles + version: 1.1.1 + sha256: 544364b2b51a9b0c7000a4b4b02f90e9423d97fbbf7e06689236443ebcad81ab + requires_dist: + - anyio>=3.0.0 + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/10/40/904a4cb30d9b61c0e278899bf36342e9b0208eb3c470324a9ecbaac2a30f/websockets-16.0-cp310-cp310-macosx_11_0_arm64.whl + name: websockets + version: '16.0' + sha256: 583b7c42688636f930688d712885cf1531326ee05effd982028212ccc13e5957 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/19/0f/22ef6107ee52ab7f0b710d55d36f5a5d3ef19e8a205541a6d7ffa7994e5a/websockets-16.0-cp310-cp310-macosx_10_9_x86_64.whl + name: websockets + version: '16.0' + sha256: 8ff32bb86522a9e5e31439a58addbb0166f0204d64066fb955265c4e214160f0 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/63/bc/d3e208028de777087e6fb2b122051a6ff7bbcca0d6df9d9c2bf1dd869ae9/websockets-16.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + name: websockets + version: '16.0' + sha256: 781caf5e8eee67f663126490c2f96f40906594cb86b408a703630f95550a8c3e + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/9d/2f/4b3ca7e106bc608744b1cdae041e005e446124bebb037b18799c2d356864/websockets-16.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + name: websockets + version: '16.0' + sha256: 7d837379b647c0c4c2355c2499723f82f1635fd2c26510e1f587d89bc2199e72 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/bb/f4/d3c9220d818ee955ae390cf319a7c7a467beceb24f05ee7aaaa2414345ba/websockets-16.0-cp314-cp314-macosx_11_0_arm64.whl + name: websockets + version: '16.0' + sha256: fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/f2/78/e63be1bf0724eeb4616efb1ae1c9044f7c3953b7957799abb5915bffd38e/websockets-16.0-cp314-cp314-macosx_10_15_x86_64.whl + name: websockets + version: '16.0' + sha256: daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/45/69/f3c47642b79485a30a59c63f6d739ed779fb4cc8323205d047d741d55220/wrapt-1.17.3-cp310-cp310-macosx_10_9_x86_64.whl + name: wrapt + version: 1.17.3 + sha256: e6b13af258d6a9ad602d57d889f83b9d5543acd471eee12eb51f5b01f8eb1bc2 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/d1/71/e7e7f5670c1eafd9e990438e69d8fb46fa91a50785332e06b560c869454f/wrapt-1.17.3-cp310-cp310-macosx_11_0_arm64.whl + name: wrapt + version: 1.17.3 + sha256: fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/de/17/9f8f86755c191d6779d7ddead1a53c7a8aa18bccb7cea8e7e72dfa6a8a09/wrapt-1.17.3-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + name: wrapt + version: 1.17.3 + sha256: f9b2601381be482f70e5d1051a5965c25fb3625455a2bf520b5a077b22afb775 + requires_python: '>=3.8' +- pypi: https://files.pythonhosted.org/packages/c2/7a/32758ca2853b07a887a4574b74e28843919103194bb47001a304e24af62f/wrapt-2.1.2-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + name: wrapt + version: 2.1.2 + sha256: 5681123e60aed0e64c7d44f72bbf8b4ce45f79d81467e2c4c728629f5baf06eb + requires_dist: + - pytest ; extra == 'dev' + - setuptools ; extra == 'dev' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/c9/18/3f373935bc5509e7ac444c8026a56762e50c1183e7061797437ca96c12ce/wrapt-2.1.2-cp310-cp310-macosx_11_0_arm64.whl + name: wrapt + version: 2.1.2 + sha256: a819e39017f95bf7aede768f75915635aa8f671f2993c036991b8d3bfe8dbb6f + requires_dist: + - pytest ; extra == 'dev' + - setuptools ; extra == 'dev' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/da/d2/387594fb592d027366645f3d7cc9b4d7ca7be93845fbaba6d835a912ef3c/wrapt-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl + name: wrapt + version: 2.1.2 + sha256: 4b7a86d99a14f76facb269dc148590c01aaf47584071809a70da30555228158c + requires_dist: + - pytest ; extra == 'dev' + - setuptools ; extra == 'dev' + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/50/12/95a1d33f04a79c402664070d43b8b9f72dc18914e135b345b611b0b1f8cc/yarl-1.23.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: yarl + version: 1.23.0 + sha256: 31c9921eb8bd12633b41ad27686bbb0b1a2a9b8452bfdf221e34f311e9942ed4 + requires_dist: + - idna>=2.0 + - multidict>=4.0 + - propcache>=0.2.1 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/68/2e/c5a2234238f8ce37a8312b52801ee74117f576b1539eec8404a480434acc/yarl-1.23.0-cp310-cp310-macosx_11_0_arm64.whl + name: yarl + version: 1.23.0 + sha256: 2a6940a074fb3c48356ed0158a3ca5699c955ee4185b4d7d619be3c327143e05 + requires_dist: + - idna>=2.0 + - multidict>=4.0 + - propcache>=0.2.1 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/7a/35/5a553687c5793df5429cd1db45909d4f3af7eee90014888c208d086a44f0/yarl-1.23.0-cp310-cp310-macosx_10_9_x86_64.whl + name: yarl + version: 1.23.0 + sha256: e4c53f8347cd4200f0d70a48ad059cabaf24f5adc6ba08622a23423bc7efa10d + requires_dist: + - idna>=2.0 + - multidict>=4.0 + - propcache>=0.2.1 + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl + name: zipp + version: 3.23.0 + sha256: 071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e + requires_dist: + - pytest>=6,!=8.1.* ; extra == 'test' + - jaraco-itertools ; extra == 'test' + - jaraco-functools ; extra == 'test' + - more-itertools ; extra == 'test' + - big-o ; extra == 'test' + - pytest-ignore-flaky ; extra == 'test' + - jaraco-test ; extra == 'test' + - sphinx>=3.5 ; extra == 'doc' + - jaraco-packaging>=9.3 ; extra == 'doc' + - rst-linker>=1.9 ; extra == 'doc' + - furo ; extra == 'doc' + - sphinx-lint ; extra == 'doc' + - jaraco-tidelift>=1.4 ; extra == 'doc' + - pytest-checkdocs>=2.4 ; extra == 'check' + - pytest-ruff>=0.2.1 ; sys_platform != 'cygwin' and extra == 'check' + - pytest-cov ; extra == 'cover' + - pytest-enabler>=2.2 ; extra == 'enabler' + - pytest-mypy ; extra == 'type' + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 + md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 + depends: + - __glibc >=2.17,<3.0.a0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 601375 + timestamp: 1764777111296 +- conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.7-h3eecb57_6.conda + sha256: 47101a4055a70a4876ffc87b750ab2287b67eca793f21c8224be5e1ee6394d3f + md5: 727109b184d680772e3122f40136d5ca + depends: + - __osx >=10.13 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 528148 + timestamp: 1764777156963 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.7-hbf9d68e_6.conda + sha256: 9485ba49e8f47d2b597dd399e88f4802e100851b27c21d7525625b0b4025a5d9 + md5: ab136e4c34e97f34fb621d2592a393d8 + depends: + - __osx >=11.0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 433413 + timestamp: 1764777166076 diff --git a/protos/feast/core/Aggregation.proto b/protos/feast/core/Aggregation.proto index d2d6cab7021..c1103b78769 100644 --- a/protos/feast/core/Aggregation.proto +++ b/protos/feast/core/Aggregation.proto @@ -12,4 +12,5 @@ message Aggregation { string function = 2; google.protobuf.Duration time_window = 3; google.protobuf.Duration slide_interval = 4; + string name = 5; } \ No newline at end of file diff --git a/protos/feast/core/FeatureView.proto b/protos/feast/core/FeatureView.proto index 6306d425be3..19ffe562dc8 100644 --- a/protos/feast/core/FeatureView.proto +++ b/protos/feast/core/FeatureView.proto @@ -36,7 +36,7 @@ message FeatureView { FeatureViewMeta meta = 2; } -// Next available id: 17 +// Next available id: 19 // TODO(adchia): refactor common fields from this and ODFV into separate metadata proto message FeatureViewSpec { // Name of the feature view. Must be unique. Not updated. @@ -61,6 +61,7 @@ message FeatureViewSpec { google.protobuf.Duration ttl = 6; // Batch/Offline DataSource where this view can retrieve offline feature data. + // Optional: if not set, the feature view has no associated batch data source (e.g. purely derived views). DataSource batch_source = 7; // Whether these features should be served online or not @@ -68,6 +69,7 @@ message FeatureViewSpec { bool online = 8; // Streaming DataSource from where this view can consume "online" feature data. + // Optional: only required for streaming feature views. DataSource stream_source = 9; // Description of the feature view. @@ -89,6 +91,12 @@ message FeatureViewSpec { // The transformation mode (e.g., "python", "pandas", "spark", "sql", "ray") string mode = 16; + + // Whether schema validation is enabled during materialization + bool enable_validation = 17; + + // User-specified version pin (e.g. "latest", "v2", "version2") + string version = 18; } message FeatureViewMeta { @@ -100,6 +108,12 @@ message FeatureViewMeta { // List of pairs (start_time, end_time) for which this feature view has been materialized. repeated MaterializationInterval materialization_intervals = 3; + + // The current version number of this feature view in the version history. + int32 current_version_number = 4; + + // Auto-generated UUID identifying this specific version. + string version_id = 5; } message MaterializationInterval { diff --git a/protos/feast/core/FeatureViewProjection.proto b/protos/feast/core/FeatureViewProjection.proto index b0e697b656f..60a26139abd 100644 --- a/protos/feast/core/FeatureViewProjection.proto +++ b/protos/feast/core/FeatureViewProjection.proto @@ -1,35 +1,38 @@ -syntax = "proto3"; -package feast.core; - -option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; -option java_outer_classname = "FeatureReferenceProto"; -option java_package = "feast.proto.core"; - -import "feast/core/Feature.proto"; -import "feast/core/DataSource.proto"; - - -// A projection to be applied on top of a FeatureView. -// Contains the modifications to a FeatureView such as the features subset to use. -message FeatureViewProjection { - // The feature view name - string feature_view_name = 1; - - // Alias for feature view name - string feature_view_name_alias = 3; - - // The features of the feature view that are a part of the feature reference. - repeated FeatureSpecV2 feature_columns = 2; - - // Map for entity join_key overrides of feature data entity join_key to entity data join_key - map join_key_map = 4; - - string timestamp_field = 5; - string date_partition_column = 6; - string created_timestamp_column = 7; - // Batch/Offline DataSource where this view can retrieve offline feature data. - DataSource batch_source = 8; - // Streaming DataSource from where this view can consume "online" feature data. - DataSource stream_source = 9; - -} +syntax = "proto3"; +package feast.core; + +option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; +option java_outer_classname = "FeatureReferenceProto"; +option java_package = "feast.proto.core"; + +import "feast/core/Feature.proto"; +import "feast/core/DataSource.proto"; + + +// A projection to be applied on top of a FeatureView. +// Contains the modifications to a FeatureView such as the features subset to use. +message FeatureViewProjection { + // The feature view name + string feature_view_name = 1; + + // Alias for feature view name + string feature_view_name_alias = 3; + + // The features of the feature view that are a part of the feature reference. + repeated FeatureSpecV2 feature_columns = 2; + + // Map for entity join_key overrides of feature data entity join_key to entity data join_key + map join_key_map = 4; + + string timestamp_field = 5; + string date_partition_column = 6; + string created_timestamp_column = 7; + // Batch/Offline DataSource where this view can retrieve offline feature data. + DataSource batch_source = 8; + // Streaming DataSource from where this view can consume "online" feature data. + DataSource stream_source = 9; + + // Optional version tag for version-qualified feature references (e.g., @v2). + optional int32 version_tag = 10; + +} diff --git a/protos/feast/core/FeatureViewVersion.proto b/protos/feast/core/FeatureViewVersion.proto new file mode 100644 index 00000000000..c88a43eea80 --- /dev/null +++ b/protos/feast/core/FeatureViewVersion.proto @@ -0,0 +1,42 @@ +// +// Copyright 2024 The Feast Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; +package feast.core; + +option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; +option java_outer_classname = "FeatureViewVersionProto"; +option java_package = "feast.proto.core"; + +import "google/protobuf/timestamp.proto"; + +message FeatureViewVersionRecord { + string feature_view_name = 1; + string project_id = 2; + int32 version_number = 3; + // "feature_view" | "stream_feature_view" | "on_demand_feature_view" + string feature_view_type = 4; + // serialized FV proto snapshot + bytes feature_view_proto = 5; + google.protobuf.Timestamp created_timestamp = 6; + string description = 7; + // auto-generated UUID for unique identification + string version_id = 8; +} + +message FeatureViewVersionHistory { + repeated FeatureViewVersionRecord records = 1; +} diff --git a/protos/feast/core/OnDemandFeatureView.proto b/protos/feast/core/OnDemandFeatureView.proto index 4b8dabb4f39..d518f22c6cd 100644 --- a/protos/feast/core/OnDemandFeatureView.proto +++ b/protos/feast/core/OnDemandFeatureView.proto @@ -36,7 +36,7 @@ message OnDemandFeatureView { OnDemandFeatureViewMeta meta = 2; } -// Next available id: 9 +// Next available id: 18 message OnDemandFeatureViewSpec { // Name of the feature view. Must be unique. Not updated. string name = 1; @@ -75,6 +75,8 @@ message OnDemandFeatureViewSpec { // Aggregation definitions repeated Aggregation aggregations = 16; + // User-specified version pin (e.g. "latest", "v2", "version2") + string version = 17; } message OnDemandFeatureViewMeta { @@ -83,6 +85,12 @@ message OnDemandFeatureViewMeta { // Time where this Feature View is last updated google.protobuf.Timestamp last_updated_timestamp = 2; + + // The current version number of this feature view in the version history. + int32 current_version_number = 3; + + // Auto-generated UUID identifying this specific version. + string version_id = 4; } message OnDemandSource { diff --git a/protos/feast/core/Registry.proto b/protos/feast/core/Registry.proto index 45ecd2c173e..45c885c7906 100644 --- a/protos/feast/core/Registry.proto +++ b/protos/feast/core/Registry.proto @@ -1,63 +1,65 @@ -// -// * Copyright 2020 The Feast Authors -// * -// * Licensed under the Apache License, Version 2.0 (the "License"); -// * you may not use this file except in compliance with the License. -// * You may obtain a copy of the License at -// * -// * https://www.apache.org/licenses/LICENSE-2.0 -// * -// * Unless required by applicable law or agreed to in writing, software -// * distributed under the License is distributed on an "AS IS" BASIS, -// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// * See the License for the specific language governing permissions and -// * limitations under the License. -// - -syntax = "proto3"; - -package feast.core; -option java_package = "feast.proto.core"; -option java_outer_classname = "RegistryProto"; -option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; - -import "feast/core/Entity.proto"; -import "feast/core/FeatureService.proto"; -import "feast/core/FeatureTable.proto"; -import "feast/core/FeatureView.proto"; -import "feast/core/InfraObject.proto"; -import "feast/core/OnDemandFeatureView.proto"; -import "feast/core/StreamFeatureView.proto"; -import "feast/core/DataSource.proto"; -import "feast/core/SavedDataset.proto"; -import "feast/core/ValidationProfile.proto"; -import "google/protobuf/timestamp.proto"; -import "feast/core/Permission.proto"; -import "feast/core/Project.proto"; - -// Next id: 18 -message Registry { - repeated Entity entities = 1; - repeated FeatureTable feature_tables = 2; - repeated FeatureView feature_views = 6; - repeated DataSource data_sources = 12; - repeated OnDemandFeatureView on_demand_feature_views = 8; - repeated StreamFeatureView stream_feature_views = 14; - repeated FeatureService feature_services = 7; - repeated SavedDataset saved_datasets = 11; - repeated ValidationReference validation_references = 13; - Infra infra = 10; - // Tracking metadata of Feast by project - repeated ProjectMetadata project_metadata = 15 [deprecated = true]; - - string registry_schema_version = 3; // to support migrations; incremented when schema is changed - string version_id = 4; // version id, random string generated on each update of the data; now used only for debugging purposes - google.protobuf.Timestamp last_updated = 5; - repeated Permission permissions = 16; - repeated Project projects = 17; -} - -message ProjectMetadata { - string project = 1; - string project_uuid = 2; -} +// +// * Copyright 2020 The Feast Authors +// * +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * https://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the License is distributed on an "AS IS" BASIS, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// * See the License for the specific language governing permissions and +// * limitations under the License. +// + +syntax = "proto3"; + +package feast.core; +option java_package = "feast.proto.core"; +option java_outer_classname = "RegistryProto"; +option go_package = "github.com/feast-dev/feast/go/protos/feast/core"; + +import "feast/core/Entity.proto"; +import "feast/core/FeatureService.proto"; +import "feast/core/FeatureTable.proto"; +import "feast/core/FeatureView.proto"; +import "feast/core/InfraObject.proto"; +import "feast/core/OnDemandFeatureView.proto"; +import "feast/core/StreamFeatureView.proto"; +import "feast/core/DataSource.proto"; +import "feast/core/SavedDataset.proto"; +import "feast/core/ValidationProfile.proto"; +import "google/protobuf/timestamp.proto"; +import "feast/core/Permission.proto"; +import "feast/core/Project.proto"; +import "feast/core/FeatureViewVersion.proto"; + +// Next id: 19 +message Registry { + repeated Entity entities = 1; + repeated FeatureTable feature_tables = 2; + repeated FeatureView feature_views = 6; + repeated DataSource data_sources = 12; + repeated OnDemandFeatureView on_demand_feature_views = 8; + repeated StreamFeatureView stream_feature_views = 14; + repeated FeatureService feature_services = 7; + repeated SavedDataset saved_datasets = 11; + repeated ValidationReference validation_references = 13; + Infra infra = 10; + // Tracking metadata of Feast by project + repeated ProjectMetadata project_metadata = 15 [deprecated = true]; + + string registry_schema_version = 3; // to support migrations; incremented when schema is changed + string version_id = 4; // version id, random string generated on each update of the data; now used only for debugging purposes + google.protobuf.Timestamp last_updated = 5; + repeated Permission permissions = 16; + repeated Project projects = 17; + FeatureViewVersionHistory feature_view_version_history = 18; +} + +message ProjectMetadata { + string project = 1; + string project_uuid = 2; +} diff --git a/protos/feast/core/StreamFeatureView.proto b/protos/feast/core/StreamFeatureView.proto index 6492cbe3069..05c829b70d3 100644 --- a/protos/feast/core/StreamFeatureView.proto +++ b/protos/feast/core/StreamFeatureView.proto @@ -37,7 +37,7 @@ message StreamFeatureView { FeatureViewMeta meta = 2; } -// Next available id: 20 +// Next available id: 22 message StreamFeatureViewSpec { // Name of the feature view. Must be unique. Not updated. string name = 1; @@ -99,5 +99,11 @@ message StreamFeatureViewSpec { // Hop size for tiling (e.g., 5 minutes). Determines the granularity of pre-aggregated tiles. // If not specified, defaults to 5 minutes. Only used when enable_tiling is true. google.protobuf.Duration tiling_hop_size = 19; + + // Whether schema validation is enabled during materialization + bool enable_validation = 20; + + // User-specified version pin (e.g. "latest", "v2", "version2") + string version = 21; } diff --git a/protos/feast/serving/GrpcServer.proto b/protos/feast/serving/GrpcServer.proto index 19caf0b7119..44d7c393b7c 100644 --- a/protos/feast/serving/GrpcServer.proto +++ b/protos/feast/serving/GrpcServer.proto @@ -1,6 +1,7 @@ syntax = "proto3"; import "feast/serving/ServingService.proto"; +import "feast/types/Value.proto"; option java_package = "feast.proto.serving"; option java_outer_classname = "GrpcServerAPIProto"; @@ -11,6 +12,7 @@ message PushRequest { string stream_feature_view = 2; bool allow_registry_cache = 3; string to = 4; + map typed_features = 5; } message PushResponse { @@ -21,6 +23,7 @@ message WriteToOnlineStoreRequest { map features = 1; string feature_view_name = 2; bool allow_registry_cache = 3; + map typed_features = 4; } message WriteToOnlineStoreResponse { diff --git a/protos/feast/serving/ServingService.proto b/protos/feast/serving/ServingService.proto index 154d850099f..87e35ac4edf 100644 --- a/protos/feast/serving/ServingService.proto +++ b/protos/feast/serving/ServingService.proto @@ -91,6 +91,9 @@ message GetOnlineFeaturesRequest { // (was moved to dedicated parameter to avoid unnecessary separation logic on serving side) // A map of variable name -> list of values map request_context = 5; + + // Whether to include feature view version metadata in the response + bool include_feature_view_version_metadata = 6; } message GetOnlineFeaturesResponse { @@ -109,8 +112,14 @@ message GetOnlineFeaturesResponse { bool status = 3; } +message FeatureViewMetadata { + string name = 1; // Feature view name (e.g., "driver_stats") + int32 version = 2; // Version number (e.g., 2) +} + message GetOnlineFeaturesResponseMetadata { - FeatureList feature_names = 1; + FeatureList feature_names = 1; // Clean feature names without @v2 syntax + repeated FeatureViewMetadata feature_view_metadata = 2; // Only populated when requested } enum FieldStatus { diff --git a/protos/feast/types/Value.proto b/protos/feast/types/Value.proto index be93235ab36..6c8082a43b9 100644 --- a/protos/feast/types/Value.proto +++ b/protos/feast/types/Value.proto @@ -53,6 +53,21 @@ message ValueType { FLOAT_SET = 27; BOOL_SET = 28; UNIX_TIMESTAMP_SET = 29; + JSON = 32; + JSON_LIST = 33; + STRUCT = 34; + STRUCT_LIST = 35; + UUID = 36; + TIME_UUID = 37; + UUID_LIST = 38; + TIME_UUID_LIST = 39; + UUID_SET = 40; + TIME_UUID_SET = 41; + VALUE_LIST = 42; + VALUE_SET = 43; + DECIMAL = 44; + DECIMAL_LIST = 45; + DECIMAL_SET = 46; } } @@ -88,6 +103,21 @@ message Value { FloatSet float_set_val = 27; BoolSet bool_set_val = 28; Int64Set unix_timestamp_set_val = 29; + string json_val = 32; + StringList json_list_val = 33; + Map struct_val = 34; + MapList struct_list_val = 35; + string uuid_val = 36; + string time_uuid_val = 37; + StringList uuid_list_val = 38; + StringList time_uuid_list_val = 39; + StringSet uuid_set_val = 40; + StringSet time_uuid_set_val = 41; + RepeatedValue list_val = 42; + RepeatedValue set_val = 43; + string decimal_val = 44; + StringList decimal_list_val = 45; + StringSet decimal_set_val = 46; } } diff --git a/pyproject.toml b/pyproject.toml index 40125f430f5..2e45d1820e7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -84,9 +84,6 @@ hbase = ["happybase>=1.2.0,<3"] ibis = [ "ibis-framework>=10.0.0", ] -ikv = [ - "ikvpy>=0.0.36", -] k8s = ["kubernetes"] image = [ "feast[pytorch]", @@ -99,10 +96,15 @@ milvus = [ "milvus-lite==2.4.12", "feast[setuptools]" ] +mongodb = [ + "pymongo>=4.13.0,<5.0.0", + "dnspython>=2.0.0", +] mssql = ["ibis-framework[mssql]>=10.0.0"] +oracle = ["ibis-framework[oracle]>=10.0.0"] mysql = ["pymysql", "types-PyMySQL"] -opentelemetry = ["prometheus_client", "psutil"] openlineage = ["openlineage-python>=1.40.0"] +opentelemetry = ["prometheus_client", "psutil"] spark = ["pyspark>=4.0.0"] trino = ["trino>=0.305.0,<0.400.0", "regex"] postgres = ["psycopg[binary,pool]==3.2.5"] @@ -114,6 +116,7 @@ qdrant = ["qdrant-client>=1.12.0"] rag = [ "transformers>=4.36.0", "datasets>=3.6.0", + "sentence-transformers>=3.0.0", ] ray = [ 'ray>=2.47.0; python_version == "3.10"', @@ -132,10 +135,27 @@ mcp = ["fastapi_mcp"] dbt = ["dbt-artifacts-parser"] +test = [ + "pytest>=6.0.0,<8", + "pytest-xdist>=3.8.0", + "pytest-timeout==1.4.2", + "pytest-lazy-fixture==0.6.3", + "pytest-ordering~=0.6.0", + "pytest-mock==1.10.4", + "pytest-env", + "pytest-benchmark>=3.4.1,<4", + "pytest-asyncio<=0.24.0", + "py>=1.11.0", + "testcontainers==4.9.0", + "minio==7.2.11", + "python-keycloak==4.2.2", + "cryptography>=43.0", +] + ci = [ + "feast[test, aws, azure, cassandra, clickhouse, couchbase, delta, docling, duckdb, elasticsearch, faiss, gcp, ge, go, grpcio, hazelcast, hbase, ibis, image, k8s, mcp, milvus, mssql, mysql, openlineage, opentelemetry, oracle, spark, trino, postgres, pytorch, qdrant, rag, ray, redis, singlestore, snowflake, sqlite_vec]", "build", "virtualenv==20.23.0", - "cryptography>=43.0,<44", "dbt-artifacts-parser", "ruff>=0.8.0", "mypy-protobuf>=3.1", @@ -143,27 +163,14 @@ ci = [ "grpcio-testing>=1.56.2,<=1.62.3", # FastAPI does not correctly pull starlette dependency on httpx see thread(https://github.com/tiangolo/fastapi/issues/5656). "httpx==0.27.2", - "minio==7.2.11", "mock==2.0.0", "moto<5", "mypy>=1.4.1,<1.11.3", "urllib3>=2.6.3,<3", "psutil==5.9.0", - "py>=1.11.0", # https://github.com/pytest-dev/pytest/issues/10420 - "pytest>=6.0.0,<8", - "pytest-asyncio<=0.24.0", "pytest-cov", - "pytest-xdist", - "pytest-benchmark>=3.4.1,<4", - "pytest-lazy-fixture==0.6.3", - "pytest-timeout==1.4.2", - "pytest-ordering~=0.6.0", - "pytest-mock==1.10.4", - "pytest-env", "Sphinx>4.0.0,<7", "sqlglot[rs]>=23.4", - "testcontainers==4.9.0", - "python-keycloak==4.2.2", "pre-commit<3.3.2", "assertpy==1.1", "pip-tools", @@ -177,8 +184,6 @@ ci = [ "types-requests<2.31.0", "types-setuptools", "types-tabulate", - "virtualenv<20.24.2", - "feast[aws, azure, cassandra, clickhouse, couchbase, delta, docling, duckdb, elasticsearch, faiss, gcp, ge, go, grpcio, hazelcast, hbase, ibis, ikv, image, k8s, mcp, milvus, mssql, mysql, openlineage, opentelemetry, spark, trino, postgres, pytorch, qdrant, rag, ray, redis, singlestore, snowflake, sqlite_vec]" ] nlp = ["feast[docling, image, milvus, pytorch, rag]"] dev = ["feast[ci]"] @@ -249,14 +254,14 @@ include = ["*.py", "*.pyi"] [tool.ruff.format] # exclude a few common directories in the root of the project -exclude = [ - ".eggs", - ".git", - ".hg", +exclude = [ + ".eggs", + ".git", + ".hg", ".mypy_cache", - ".tox", - ".venv", - "_build", + ".tox", + ".venv", + "_build", "buck-out", "build", "dist", @@ -269,3 +274,38 @@ exclude = [ dev = [ "pytest-xdist>=3.8.0", ] + +# Pixi configuration +[tool.pixi.workspace] +channels = ["conda-forge"] +platforms = ["linux-64", "osx-arm64", "osx-64"] + +[tool.pixi.feature.py310.dependencies] +python = "~=3.10.0" + +[tool.pixi.feature.duckdb-tests.pypi-dependencies] +feast = { path = ".", editable = true, extras = ["duckdb", "delta", "grpcio", "test"] } + +[tool.pixi.feature.duckdb-tests.tasks] +test = { cmd = "python -m pytest -n 8 --integration -m 'not ray_offline_stores_only' --ignore=sdk/python/tests/integration/offline_store/test_dqm_validation.py sdk/python/tests/integration/offline_store", env = { PYTHONPATH = ".", FULL_REPO_CONFIGS_MODULE = "sdk.python.tests.universal.feature_repos.duckdb_repo_configuration", FEAST_IS_LOCAL_TEST = "True" } } + +[tool.pixi.feature.ray-tests.pypi-dependencies] +feast = { path = ".", editable = true, extras = ["ray", "grpcio", "test"] } + +[tool.pixi.feature.ray-tests.tasks] +test-offline = { cmd = "python -m pytest -v --integration --ignore=sdk/python/tests/integration/offline_store/test_dqm_validation.py sdk/python/tests/integration/offline_store", env = { PYTHONPATH = ".", FULL_REPO_CONFIGS_MODULE = "sdk.python.tests.universal.feature_repos.ray_repo_configuration", FEAST_IS_LOCAL_TEST = "True" } } +test-compute = { cmd = "python -m pytest -v --integration sdk/python/tests/component/ray", env = { PYTHONPATH = ".", FEAST_IS_LOCAL_TEST = "True" } } +test = { depends-on = ["test-offline", "test-compute"] } + +[tool.pixi.feature.registration-tests.pypi-dependencies] +feast = { path = ".", editable = true, extras = ["aws", "gcp", "grpcio", "postgres", "mysql", "redis", "snowflake", "spark", "test"] } +grpcio-testing = ">=1.56.2,<=1.62.3" + +[tool.pixi.feature.registration-tests.tasks] +test = { cmd = "python -m pytest -n auto --dist loadgroup --integration sdk/python/tests/integration/registration", env = { PYTHONPATH = ".", FEAST_IS_LOCAL_TEST = "True" } } +test-ci = { cmd = "python -m pytest -n auto --dist loadgroup --integration sdk/python/tests/integration/registration", env = { PYTHONPATH = "." } } + +[tool.pixi.environments] +duckdb-tests = ["py310", "duckdb-tests"] +ray-tests = ["py310", "ray-tests"] +registration-tests = ["py310", "registration-tests"] diff --git a/sdk/python/docs/source/feast.infra.online_stores.contrib.ikv_online_store.rst b/sdk/python/docs/source/feast.infra.online_stores.contrib.ikv_online_store.rst deleted file mode 100644 index 812e30932d5..00000000000 --- a/sdk/python/docs/source/feast.infra.online_stores.contrib.ikv_online_store.rst +++ /dev/null @@ -1,21 +0,0 @@ -feast.infra.online\_stores.contrib.ikv\_online\_store package -============================================================= - -Submodules ----------- - -feast.infra.online\_stores.contrib.ikv\_online\_store.ikv module ----------------------------------------------------------------- - -.. automodule:: feast.infra.online_stores.ikv_online_store.ikv - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: feast.infra.online_stores.ikv_online_store - :members: - :undoc-members: - :show-inheritance: diff --git a/sdk/python/docs/source/feast.infra.online_stores.contrib.rst b/sdk/python/docs/source/feast.infra.online_stores.contrib.rst index d77e7d175d5..92b4b182d32 100644 --- a/sdk/python/docs/source/feast.infra.online_stores.contrib.rst +++ b/sdk/python/docs/source/feast.infra.online_stores.contrib.rst @@ -11,7 +11,6 @@ Subpackages feast.infra.online_stores.couchbase_online_store feast.infra.online_stores.hazelcast_online_store feast.infra.online_stores.hbase_online_store - feast.infra.online_stores.ikv_online_store feast.infra.online_stores.mysql_online_store Submodules diff --git a/sdk/python/docs/source/feast.infra.online_stores.ikv_online_store.rst b/sdk/python/docs/source/feast.infra.online_stores.ikv_online_store.rst deleted file mode 100644 index 391af17024f..00000000000 --- a/sdk/python/docs/source/feast.infra.online_stores.ikv_online_store.rst +++ /dev/null @@ -1,21 +0,0 @@ -feast.infra.online\_stores.ikv\_online\_store package -===================================================== - -Submodules ----------- - -feast.infra.online\_stores.ikv\_online\_store.ikv module --------------------------------------------------------- - -.. automodule:: feast.infra.online_stores.ikv_online_store.ikv - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: feast.infra.online_stores.ikv_online_store - :members: - :undoc-members: - :show-inheritance: diff --git a/sdk/python/docs/source/feast.infra.online_stores.mongodb_online_store.rst b/sdk/python/docs/source/feast.infra.online_stores.mongodb_online_store.rst new file mode 100644 index 00000000000..b221a370d31 --- /dev/null +++ b/sdk/python/docs/source/feast.infra.online_stores.mongodb_online_store.rst @@ -0,0 +1,29 @@ +feast.infra.online\_stores.mongodb\_online\_store package +================================================================= + +Submodules +---------- + +feast.infra.online\_stores.mongodb\_online\_store.mongodb module +------------------------------------------------------------------------ + +.. automodule:: feast.infra.online_stores.mongodb_online_store.mongodb + :members: + :undoc-members: + :show-inheritance: + +feast.infra.online\_stores.mongodb\_online\_store.mongodb\_repo\_configuration module +--------------------------------------------------------------------------------------------- + +.. automodule:: feast.infra.online_stores.mongodb_online_store.mongodb_repo_configuration + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: feast.infra.online_stores.mongodb_online_store + :members: + :undoc-members: + :show-inheritance: diff --git a/sdk/python/docs/source/feast.infra.online_stores.rst b/sdk/python/docs/source/feast.infra.online_stores.rst index c07c7e0c279..91c3c6c90fa 100644 --- a/sdk/python/docs/source/feast.infra.online_stores.rst +++ b/sdk/python/docs/source/feast.infra.online_stores.rst @@ -12,8 +12,8 @@ Subpackages feast.infra.online_stores.elasticsearch_online_store feast.infra.online_stores.hazelcast_online_store feast.infra.online_stores.hbase_online_store - feast.infra.online_stores.ikv_online_store feast.infra.online_stores.milvus_online_store + feast.infra.online_stores.mongodb_online_store feast.infra.online_stores.mysql_online_store feast.infra.online_stores.postgres_online_store feast.infra.online_stores.qdrant_online_store diff --git a/sdk/python/feast/__init__.py b/sdk/python/feast/__init__.py index ffd05559ee1..c91e6b4c3ec 100644 --- a/sdk/python/feast/__init__.py +++ b/sdk/python/feast/__init__.py @@ -5,14 +5,20 @@ from feast.infra.offline_stores.contrib.athena_offline_store.athena_source import ( AthenaSource, ) +from feast.infra.offline_stores.contrib.oracle_offline_store.oracle_source import ( + OracleSource, +) from feast.infra.offline_stores.file_source import FileSource from feast.infra.offline_stores.redshift_source import RedshiftSource from feast.infra.offline_stores.snowflake_source import SnowflakeSource from .aggregation import Aggregation from .batch_feature_view import BatchFeatureView +from .chunker import BaseChunker, ChunkingConfig, TextChunker from .data_source import KafkaSource, KinesisSource, PushSource, RequestSource from .dataframe import DataFrameEngine, FeastDataFrame +from .doc_embedder import DocEmbedder, LogicalLayerFn +from .embedder import BaseEmbedder, EmbeddingConfig, MultiModalEmbedder from .entity import Entity from .feature import Feature from .feature_service import FeatureService @@ -56,6 +62,15 @@ "PushSource", "RequestSource", "AthenaSource", + "OracleSource", "Project", "FeastVectorStore", + "DocEmbedder", + "LogicalLayerFn", + "BaseChunker", + "TextChunker", + "ChunkingConfig", + "BaseEmbedder", + "MultiModalEmbedder", + "EmbeddingConfig", ] diff --git a/sdk/python/feast/aggregation/__init__.py b/sdk/python/feast/aggregation/__init__.py index 470f91f09c2..464e49edd9b 100644 --- a/sdk/python/feast/aggregation/__init__.py +++ b/sdk/python/feast/aggregation/__init__.py @@ -18,15 +18,17 @@ class Aggregation: Attributes: column: str # Column name of the feature we are aggregating. - function: str # Provided built in aggregations sum, max, min, count mean + function: str # Provided built in aggregations sum, max, min, count, mean, count_distinct time_window: timedelta # The time window for this aggregation. slide_interval: timedelta # The sliding window for these aggregations + name: str # Optional override for the output feature name (defaults to {function}_{column}) """ column: str function: str time_window: Optional[timedelta] slide_interval: Optional[timedelta] + name: str def __init__( self, @@ -34,6 +36,7 @@ def __init__( function: Optional[str] = "", time_window: Optional[timedelta] = None, slide_interval: Optional[timedelta] = None, + name: Optional[str] = None, ): self.column = column or "" self.function = function or "" @@ -42,6 +45,7 @@ def __init__( self.slide_interval = self.time_window else: self.slide_interval = slide_interval + self.name = name or "" def to_proto(self) -> AggregationProto: window_duration = None @@ -59,6 +63,7 @@ def to_proto(self) -> AggregationProto: function=self.function, time_window=window_duration, slide_interval=slide_interval_duration, + name=self.name, ) @classmethod @@ -79,6 +84,7 @@ def from_proto(cls, agg_proto: AggregationProto): function=agg_proto.function, time_window=time_window, slide_interval=slide_interval, + name=agg_proto.name or None, ) return aggregation @@ -91,11 +97,31 @@ def __eq__(self, other): or self.function != other.function or self.time_window != other.time_window or self.slide_interval != other.slide_interval + or self.name != other.name ): return False return True + def resolved_name(self, time_window: Optional[timedelta] = None) -> str: + """Return the output feature name for this aggregation. + + If ``name`` is set it is returned as-is. Otherwise the name is + derived as ``{function}_{column}``, with ``_{seconds}s`` appended + when *time_window* is provided. + """ + if self.name: + return self.name + base = f"{self.function}_{self.column}" + if time_window is not None and time_window.total_seconds() > 0: + return f"{base}_{int(time_window.total_seconds())}s" + return base + + +_FUNCTION_ALIASES: Dict[str, str] = { + "count_distinct": "nunique", +} + def aggregation_specs_to_agg_ops( agg_specs: Iterable[Any], @@ -106,8 +132,9 @@ def aggregation_specs_to_agg_ops( for agg in agg_specs: if getattr(agg, "time_window", None) is not None: raise ValueError(time_window_unsupported_error_message) - alias = f"{agg.function}_{agg.column}" - agg_ops[alias] = (agg.function, agg.column) + alias = getattr(agg, "name", None) or f"{agg.function}_{agg.column}" + func_name = _FUNCTION_ALIASES.get(agg.function, agg.function) + agg_ops[alias] = (func_name, agg.column) return agg_ops diff --git a/sdk/python/feast/aggregation/tiling/base.py b/sdk/python/feast/aggregation/tiling/base.py index c5ff765a0a9..8a4bbacf3ca 100644 --- a/sdk/python/feast/aggregation/tiling/base.py +++ b/sdk/python/feast/aggregation/tiling/base.py @@ -86,6 +86,12 @@ def get_ir_metadata_for_aggregation( ), ) + elif agg_type == "count_distinct": + raise ValueError( + "count_distinct does not support tiling. " + "Use enable_tiling=False or choose an algebraic aggregation (sum, count, min, max)." + ) + else: # Unknown aggregation: treat as algebraic return ([], IRMetadata(type="algebraic")) diff --git a/sdk/python/feast/aggregation/tiling/orchestrator.py b/sdk/python/feast/aggregation/tiling/orchestrator.py index 16e047f465c..fbec5568799 100644 --- a/sdk/python/feast/aggregation/tiling/orchestrator.py +++ b/sdk/python/feast/aggregation/tiling/orchestrator.py @@ -61,9 +61,7 @@ def apply_sawtooth_window_tiling( ir_metadata_dict = {} for agg in aggregations: - feature_name = ( - f"{agg.function}_{agg.column}_{int(window_size.total_seconds())}s" - ) + feature_name = agg.resolved_name(window_size) _, metadata = get_ir_metadata_for_aggregation(agg, feature_name) ir_metadata_dict[feature_name] = metadata @@ -161,9 +159,7 @@ def apply_sawtooth_window_tiling( # Step 5: Compute final feature values from IRs (for algebraic aggs, just rename) for agg in aggregations: - feature_name = ( - f"{agg.function}_{agg.column}_{int(window_size.total_seconds())}s" - ) + feature_name = agg.resolved_name(window_size) metadata = ir_metadata_dict[feature_name] if metadata.type == "algebraic": diff --git a/sdk/python/feast/aggregation/tiling/tile_subtraction.py b/sdk/python/feast/aggregation/tiling/tile_subtraction.py index 9dee478effa..778e05ecfb2 100644 --- a/sdk/python/feast/aggregation/tiling/tile_subtraction.py +++ b/sdk/python/feast/aggregation/tiling/tile_subtraction.py @@ -76,9 +76,7 @@ def convert_cumulative_to_windowed( # Subtract previous tile values from current tile for each aggregation for agg in aggregations: - feature_name = ( - f"{agg.function}_{agg.column}_{int(window_size.total_seconds())}s" - ) + feature_name = agg.resolved_name(window_size) _, metadata = get_ir_metadata_for_aggregation(agg, feature_name) if metadata.type == "algebraic": diff --git a/sdk/python/feast/api/registry/rest/metrics.py b/sdk/python/feast/api/registry/rest/metrics.py index 58dc7156144..3be43b5e4b4 100644 --- a/sdk/python/feast/api/registry/rest/metrics.py +++ b/sdk/python/feast/api/registry/rest/metrics.py @@ -65,77 +65,155 @@ async def resource_counts( ), allow_cache: bool = Query(True), ): - def count_resources_for_project(project_name: str): - entities = grpc_call( - grpc_handler.ListEntities, - RegistryServer_pb2.ListEntitiesRequest( - project=project_name, allow_cache=allow_cache - ), - ) - data_sources = grpc_call( - grpc_handler.ListDataSources, - RegistryServer_pb2.ListDataSourcesRequest( - project=project_name, allow_cache=allow_cache - ), - ) + """ + Resource counts and feature store inventory metadata. + + Returns counts per resource type, plus enriched summaries: + feature services (names), feature views (with per-view feature + count and materialization info), project list, and the registry + last-updated timestamp. + """ + + def get_registry_last_updated() -> Optional[str]: + try: + from google.protobuf.empty_pb2 import Empty as EmptyProto + + registry_proto = grpc_call(grpc_handler.Proto, EmptyProto()) + return registry_proto.get("lastUpdated", None) + except Exception: + return None + + def _extract_fv_summary(any_fv: dict, project_name: str) -> Optional[Dict]: + fv = _extract_feature_view_from_any(any_fv) + if not fv: + return None + spec = fv.get("spec", {}) + features = spec.get("features", []) + return { + "name": spec.get("name", ""), + "project": project_name, + "type": fv.get("type", "featureView"), + "featureCount": len(features) if isinstance(features, list) else 0, + } + + def collect_resources_for_project(project_name: str) -> dict: + entities_list: list = [] + try: + entities_resp = grpc_call( + grpc_handler.ListEntities, + RegistryServer_pb2.ListEntitiesRequest( + project=project_name, allow_cache=allow_cache + ), + ) + entities_list = entities_resp.get("entities", []) + except Exception: + pass + + data_sources_list: list = [] try: - saved_datasets = grpc_call( + ds_resp = grpc_call( + grpc_handler.ListDataSources, + RegistryServer_pb2.ListDataSourcesRequest( + project=project_name, allow_cache=allow_cache + ), + ) + data_sources_list = ds_resp.get("dataSources", []) + except Exception: + pass + + saved_datasets_list: list = [] + try: + sd_resp = grpc_call( grpc_handler.ListSavedDatasets, RegistryServer_pb2.ListSavedDatasetsRequest( project=project_name, allow_cache=allow_cache ), ) + saved_datasets_list = sd_resp.get("savedDatasets", []) except Exception: - saved_datasets = {"savedDatasets": []} + pass + + features_list: list = [] try: - features = grpc_call( + feat_resp = grpc_call( grpc_handler.ListFeatures, RegistryServer_pb2.ListFeaturesRequest( project=project_name, allow_cache=allow_cache ), ) + features_list = feat_resp.get("features", []) except Exception: - features = {"features": []} + pass + + raw_fv_list: list = [] + fv_summaries: List[Dict] = [] try: - feature_views = grpc_call( + fv_resp = grpc_call( grpc_handler.ListAllFeatureViews, RegistryServer_pb2.ListAllFeatureViewsRequest( project=project_name, allow_cache=allow_cache ), ) + raw_fv_list = fv_resp.get("featureViews", []) + for any_fv in raw_fv_list: + summary = _extract_fv_summary(any_fv, project_name) + if summary: + fv_summaries.append(summary) except Exception: - feature_views = {"featureViews": []} + pass + + fs_summaries: List[Dict] = [] + raw_fs_list: list = [] try: - feature_services = grpc_call( + fs_resp = grpc_call( grpc_handler.ListFeatureServices, RegistryServer_pb2.ListFeatureServicesRequest( project=project_name, allow_cache=allow_cache ), ) + raw_fs_list = fs_resp.get("featureServices", []) + for fs in raw_fs_list: + spec = fs.get("spec", {}) + fs_summaries.append( + {"name": spec.get("name", ""), "project": project_name} + ) except Exception: - feature_services = {"featureServices": []} + pass + return { - "entities": len(entities.get("entities", [])), - "dataSources": len(data_sources.get("dataSources", [])), - "savedDatasets": len(saved_datasets.get("savedDatasets", [])), - "features": len(features.get("features", [])), - "featureViews": len(feature_views.get("featureViews", [])), - "featureServices": len(feature_services.get("featureServices", [])), + "counts": { + "entities": len(entities_list), + "dataSources": len(data_sources_list), + "savedDatasets": len(saved_datasets_list), + "features": len(features_list), + "featureViews": len(fv_summaries), + "featureServices": len(fs_summaries), + }, + "featureServices": fs_summaries, + "featureViews": fv_summaries, } + registry_last_updated = get_registry_last_updated() + if project: - counts = count_resources_for_project(project) - return {"project": project, "counts": counts} + resources = collect_resources_for_project(project) + return { + "project": project, + "counts": resources["counts"], + "featureServices": resources["featureServices"], + "featureViews": resources["featureViews"], + "projects": [{"name": project}], + "registryLastUpdated": registry_last_updated, + } else: - # List all projects via gRPC projects_resp = grpc_call( grpc_handler.ListProjects, RegistryServer_pb2.ListProjectsRequest(allow_cache=allow_cache), ) - all_projects = [ - p["spec"]["name"] for p in projects_resp.get("projects", []) - ] - all_counts = {} + all_projects = projects_resp.get("projects", []) + project_names = [p["spec"]["name"] for p in all_projects if "spec" in p] + + all_counts: Dict[str, dict] = {} total_counts = { "entities": 0, "dataSources": 0, @@ -144,12 +222,37 @@ def count_resources_for_project(project_name: str): "featureViews": 0, "featureServices": 0, } - for project_name in all_projects: - counts = count_resources_for_project(project_name) - all_counts[project_name] = counts + all_fs: List[Dict] = [] + all_fv: List[Dict] = [] + project_summaries: List[Dict] = [] + + for pname in project_names: + resources = collect_resources_for_project(pname) + counts = resources["counts"] + all_counts[pname] = counts for k in total_counts: total_counts[k] += counts[k] - return {"total": total_counts, "perProject": all_counts} + all_fs.extend(resources["featureServices"]) + all_fv.extend(resources["featureViews"]) + proj_info: Dict = next( + (p for p in all_projects if p.get("spec", {}).get("name") == pname), + {}, + ) + project_summaries.append( + { + "name": pname, + "description": proj_info.get("spec", {}).get("description", ""), + } + ) + + return { + "total": total_counts, + "perProject": all_counts, + "featureServices": all_fs, + "featureViews": all_fv, + "projects": project_summaries, + "registryLastUpdated": registry_last_updated, + } @router.get( "/metrics/popular_tags", tags=["Metrics"], response_model=PopularTagsResponse diff --git a/sdk/python/feast/arrow_error_handler.py b/sdk/python/feast/arrow_error_handler.py index e4862bb0982..59f889a0a34 100644 --- a/sdk/python/feast/arrow_error_handler.py +++ b/sdk/python/feast/arrow_error_handler.py @@ -1,4 +1,6 @@ +import json import logging +import time from functools import wraps import pyarrow.flight as fl @@ -7,17 +9,45 @@ logger = logging.getLogger(__name__) +BACKOFF_FACTOR = 0.5 + def arrow_client_error_handling_decorator(func): @wraps(func) def wrapper(*args, **kwargs): - try: - return func(*args, **kwargs) - except Exception as e: - mapped_error = FeastError.from_error_detail(_get_exception_data(e.args[0])) - if mapped_error is not None: - raise mapped_error - raise e + # Retry only applies to FeastFlightClient methods where args[0] (self) + # carries _connection_retries from RemoteOfflineStoreConfig. + # Standalone stream functions (write_table, read_all) get 0 retries: + # broken streams can't be reused and retrying risks duplicate writes. + max_retries = max(0, getattr(args[0], "_connection_retries", 0)) if args else 0 + + for attempt in range(max_retries + 1): + try: + return func(*args, **kwargs) + except fl.FlightUnavailableError as e: + if attempt < max_retries: + wait_time = BACKOFF_FACTOR * (2**attempt) + logger.warning( + "Transient Arrow Flight error on attempt %d/%d, " + "retrying in %.1fs: %s", + attempt + 1, + max_retries + 1, + wait_time, + e, + ) + time.sleep(wait_time) + continue + mapped_error = FeastError.from_error_detail(_get_exception_data(str(e))) + if mapped_error is not None: + raise mapped_error + raise e + except Exception as e: + mapped_error = FeastError.from_error_detail( + _get_exception_data(e.args[0]) + ) + if mapped_error is not None: + raise mapped_error + raise e return wrapper @@ -38,15 +68,27 @@ def wrapper(*args, **kwargs): def _get_exception_data(except_str) -> str: - substring = "Flight error: " + if not isinstance(except_str, str): + return "" - # Find the starting index of the substring + substring = "Flight error: " position = except_str.find(substring) - end_json_index = except_str.find("}") + if position == -1: + return "" - if position != -1 and end_json_index != -1: - # Extract the part of the string after the substring - result = except_str[position + len(substring) : end_json_index + 1] - return result + search_start = position + len(substring) + json_start = except_str.find("{", search_start) + if json_start == -1: + return "" - return "" + search_pos = json_start + while True: + json_end = except_str.find("}", search_pos + 1) + if json_end == -1: + return "" + candidate = except_str[json_start : json_end + 1] + try: + json.loads(candidate) + return candidate + except (json.JSONDecodeError, ValueError): + search_pos = json_end diff --git a/sdk/python/feast/base_feature_view.py b/sdk/python/feast/base_feature_view.py index d7dc2237bd3..f3e0a2cad5b 100644 --- a/sdk/python/feast/base_feature_view.py +++ b/sdk/python/feast/base_feature_view.py @@ -56,6 +56,8 @@ class BaseFeatureView(ABC): projection: FeatureViewProjection created_timestamp: Optional[datetime] last_updated_timestamp: Optional[datetime] + version: str + current_version_number: Optional[int] @abstractmethod def __init__( @@ -92,9 +94,12 @@ def __init__( self.projection = FeatureViewProjection.from_definition(self) self.created_timestamp = None self.last_updated_timestamp = None + if not hasattr(self, "version"): + self.version = "latest" + if not hasattr(self, "current_version_number"): + self.current_version_number = None - if source: - self.source = source + self.source = source @property @abstractmethod @@ -148,6 +153,17 @@ def __getitem__(self, item): return cp + def _schema_or_udf_changed(self, other: "BaseFeatureView") -> bool: + """Check if schema or UDF-related fields have changed (version-worthy changes). + + Callers always match by name first, so name comparison is omitted here. + """ + if sorted(self.features) != sorted(other.features): + return True + # Skip metadata: description, tags, owner, projection + # Skip source changes: treat as deployment/location details, not schema changes + return False + def __eq__(self, other): if not isinstance(other, BaseFeatureView): raise TypeError( @@ -179,6 +195,18 @@ def ensure_valid(self): """ if not self.name: raise ValueError("Feature view needs a name.") + if "@" in self.name: + raise ValueError( + f"Feature view name '{self.name}' must not contain '@'. " + f"The '@' character is reserved for version-qualified references " + f"(e.g., 'fv@v2:feature')." + ) + if ":" in self.name: + raise ValueError( + f"Feature view name '{self.name}' must not contain ':'. " + f"The ':' character is reserved as the separator in fully qualified " + f"feature references (e.g., 'feature_view:feature_name')." + ) def with_name(self, name: str): """ diff --git a/sdk/python/feast/batch_feature_view.py b/sdk/python/feast/batch_feature_view.py index 3f3e1bf20ec..c9c53dfef91 100644 --- a/sdk/python/feast/batch_feature_view.py +++ b/sdk/python/feast/batch_feature_view.py @@ -82,7 +82,9 @@ def __init__( *, name: str, mode: Union[TransformationMode, str] = TransformationMode.PYTHON, - source: Union[DataSource, "BatchFeatureView", List["BatchFeatureView"]], + source: Optional[ + Union[DataSource, "BatchFeatureView", List["BatchFeatureView"]] + ] = None, sink_source: Optional[DataSource] = None, entities: Optional[List[Entity]] = None, ttl: Optional[timedelta] = None, @@ -97,6 +99,8 @@ def __init__( feature_transformation: Optional[Transformation] = None, batch_engine: Optional[Dict[str, Any]] = None, aggregations: Optional[List[Aggregation]] = None, + enable_validation: bool = False, + version: str = "latest", ): if not flags_helper.is_test(): warnings.warn( @@ -114,6 +118,21 @@ def __init__( f"or CUSTOM_SOURCE, got {type(source).__name__}: {source.name} instead " ) + if source is None and aggregations: + raise ValueError( + "BatchFeatureView with aggregations requires a source to aggregate from." + ) + + if ( + source is None + and not udf + and not feature_transformation + and not aggregations + ): + raise ValueError( + "BatchFeatureView requires at least one of: source, udf, feature_transformation, or aggregations." + ) + self.mode = mode self.udf = udf self.udf_string = udf_string @@ -136,6 +155,8 @@ def __init__( source=source, # type: ignore[arg-type] sink_source=sink_source, mode=mode, + enable_validation=enable_validation, + version=version, ) def get_feature_transformation(self) -> Optional[Transformation]: @@ -169,6 +190,8 @@ def batch_feature_view( description: str = "", owner: str = "", schema: Optional[List[Field]] = None, + enable_validation: bool = False, + version: str = "latest", ): """ Creates a BatchFeatureView object with the given user-defined function (UDF) as the transformation. @@ -199,6 +222,8 @@ def decorator(user_function): schema=schema, udf=user_function, udf_string=udf_string, + enable_validation=enable_validation, + version=version, ) functools.update_wrapper(wrapper=batch_feature_view_obj, wrapped=user_function) return batch_feature_view_obj diff --git a/sdk/python/feast/chunker.py b/sdk/python/feast/chunker.py new file mode 100644 index 00000000000..484f2b398a8 --- /dev/null +++ b/sdk/python/feast/chunker.py @@ -0,0 +1,150 @@ +from abc import ABC, abstractmethod +from dataclasses import dataclass +from typing import Any, Optional + +import pandas as pd + + +@dataclass +class ChunkingConfig: + chunk_size: int = 100 + chunk_overlap: int = 20 + min_chunk_size: int = 20 + max_chunk_chars: Optional[int] = 500 + + +class BaseChunker(ABC): + """ + Abstract base class for document chunking. + + Subclasses implement load_parse_and_chunk() with their own: + - Loading logic + - Parsing logic + - Chunking strategy + """ + + def __init__(self, config: Optional[ChunkingConfig] = None): + self.config = config or ChunkingConfig() + + @abstractmethod + def load_parse_and_chunk( + self, + source: Any, + source_id: str, + source_column: str, + source_type: Optional[str] = None, + ) -> list[dict]: + """ + Load, parse, and chunk a document. + + Args: + source: File path, raw text, bytes, etc. + source_id: Document identifier. + source_type: Optional type hint. + source_column: The column containing the document sources. + + Returns: + List of chunk dicts with keys: + - chunk_id: str + - original_id: str + - text: str + - chunk_index: int + - (any additional metadata) + """ + pass + + def chunk_dataframe( + self, + df: pd.DataFrame, + id_column: str, + source_column: str, + type_column: Optional[str] = None, + ) -> pd.DataFrame: + """ + Chunk all documents in a DataFrame. + + Args: + df: The DataFrame containing the documents to chunk. + id_column: The column containing the document IDs. + source_column: The column containing the document sources. + type_column: The column containing the document types. + """ + + all_chunks = [] + for row in df.itertuples(index=False): + chunks = self.load_parse_and_chunk( + getattr(row, source_column), + str(getattr(row, id_column)), + source_column, + getattr(row, type_column) if type_column else None, + ) + all_chunks.extend(chunks) + + if not all_chunks: + return pd.DataFrame( + columns=["chunk_id", "original_id", source_column, "chunk_index"] + ) + return pd.DataFrame(all_chunks) + + +class TextChunker(BaseChunker): + """Default chunker for plain text. Chunks by word count.""" + + def load_parse_and_chunk( + self, + source: Any, + source_id: str, + source_column: str, + source_type: Optional[str] = None, + ) -> list[dict]: + # Load + text = self._load(source) + + # Chunk by words + return self._chunk_by_words(text, source_id, source_column) + + def _load(self, source: Any) -> str: + from pathlib import Path + + if isinstance(source, Path) and source.exists(): + return Path(source).read_text() + if isinstance(source, str): + if source.endswith(".txt") and Path(source).exists(): + return Path(source).read_text() + return str(source) + + def _chunk_by_words( + self, text: str, source_id: str, source_column: str + ) -> list[dict]: + words = text.split() + chunks = [] + + step = self.config.chunk_size - self.config.chunk_overlap + if step <= 0: + raise ValueError( + f"chunk_overlap ({self.config.chunk_overlap}) must be less than " + f"chunk_size ({self.config.chunk_size})" + ) + chunk_index = 0 + + for i in range(0, len(words), step): + chunk_words = words[i : i + self.config.chunk_size] + + if len(chunk_words) < self.config.min_chunk_size: + continue + + chunk_text = " ".join(chunk_words) + if self.config.max_chunk_chars: + chunk_text = chunk_text[: self.config.max_chunk_chars] + + chunks.append( + { + "chunk_id": f"{source_id}_{chunk_index}", + "original_id": source_id, + source_column: chunk_text, + "chunk_index": chunk_index, + } + ) + chunk_index += 1 + + return chunks diff --git a/sdk/python/feast/cli/cli.py b/sdk/python/feast/cli/cli.py index 4eff2707af9..1e461af4a28 100644 --- a/sdk/python/feast/cli/cli.py +++ b/sdk/python/feast/cli/cli.py @@ -276,12 +276,20 @@ def plan_command( is_flag=True, help="Disable progress bars during apply operation.", ) +@click.option( + "--no-promote", + is_flag=True, + default=False, + help="Save new versions without promoting them to active. " + "New versions are accessible via @v reads and --version materialization.", +) @click.pass_context def apply_total_command( ctx: click.Context, skip_source_validation: bool, skip_feature_view_validation: bool, no_progress: bool, + no_promote: bool, ): """ Create or update a feature store deployment @@ -304,6 +312,7 @@ def apply_total_command( repo, skip_source_validation, skip_feature_view_validation, + no_promote=no_promote, ) except FeastProviderLoginError as e: print(str(e)) @@ -351,6 +360,12 @@ def registry_dump_command(ctx: click.Context): is_flag=True, help="Materialize all available data using current datetime as event timestamp (useful when source data lacks event timestamps)", ) +@click.option( + "--version", + "feature_view_version", + default=None, + help="Version to materialize (e.g., 'v2'). Requires --views with exactly one feature view.", +) @click.pass_context def materialize_command( ctx: click.Context, @@ -358,6 +373,7 @@ def materialize_command( end_ts: Optional[str], views: List[str], disable_event_timestamp: bool, + feature_view_version: Optional[str], ): """ Run a (non-incremental) materialization job to ingest data into the online store. Feast @@ -395,6 +411,7 @@ def materialize_command( start_date=start_date, end_date=end_date, disable_event_timestamp=disable_event_timestamp, + version=feature_view_version, ) @@ -406,8 +423,19 @@ def materialize_command( help="Feature views to incrementally materialize", multiple=True, ) +@click.option( + "--version", + "feature_view_version", + default=None, + help="Version to materialize (e.g., 'v2'). Requires --views with exactly one feature view.", +) @click.pass_context -def materialize_incremental_command(ctx: click.Context, end_ts: str, views: List[str]): +def materialize_incremental_command( + ctx: click.Context, + end_ts: str, + views: List[str], + feature_view_version: Optional[str], +): """ Run an incremental materialization job to ingest new data into the online store. Feast will read all data from the previously ingested point to END_TS from the offline store and write it to the @@ -420,6 +448,7 @@ def materialize_incremental_command(ctx: click.Context, end_ts: str, views: List store.materialize_incremental( feature_views=None if not views else views, end_date=utils.make_tzaware(datetime.fromisoformat(end_ts)), + version=feature_view_version, ) @@ -442,7 +471,6 @@ def materialize_incremental_command(ctx: click.Context, end_ts: str, views: List "hbase", "cassandra", "hazelcast", - "ikv", "couchbase", "milvus", "ray", diff --git a/sdk/python/feast/cli/feature_views.py b/sdk/python/feast/cli/feature_views.py index a1a29ac9f27..99de5e70be7 100644 --- a/sdk/python/feast/cli/feature_views.py +++ b/sdk/python/feast/cli/feature_views.py @@ -70,3 +70,47 @@ def feature_view_list(ctx: click.Context, tags: list[str]): from tabulate import tabulate print(tabulate(table, headers=["NAME", "ENTITIES", "TYPE"], tablefmt="plain")) + + +@feature_views_cmd.command("list-versions") +@click.argument("name", type=click.STRING) +@click.pass_context +def feature_view_versions(ctx: click.Context, name: str): + """ + List version history for a feature view + """ + store = create_feature_store(ctx) + + try: + versions = store.list_feature_view_versions(name) + except NotImplementedError: + print("Version history is not supported by this registry backend.") + exit(1) + except Exception as e: + print(e) + exit(1) + + if not versions: + print(f"No version history found for feature view '{name}'.") + return + + table = [] + for v in versions: + table.append( + [ + v["version"], + v["feature_view_type"], + str(v["created_timestamp"]), + v["version_id"], + ] + ) + + from tabulate import tabulate + + print( + tabulate( + table, + headers=["VERSION", "TYPE", "CREATED", "VERSION_ID"], + tablefmt="plain", + ) + ) diff --git a/sdk/python/feast/diff/registry_diff.py b/sdk/python/feast/diff/registry_diff.py index 272c4590d88..58a92db8139 100644 --- a/sdk/python/feast/diff/registry_diff.py +++ b/sdk/python/feast/diff/registry_diff.py @@ -1,416 +1,421 @@ -from dataclasses import dataclass -from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, TypeVar, cast - -from feast.base_feature_view import BaseFeatureView -from feast.data_source import DataSource -from feast.diff.property_diff import PropertyDiff, TransitionType -from feast.entity import Entity -from feast.feast_object import FeastObject, FeastObjectSpecProto -from feast.feature_service import FeatureService -from feast.feature_view import DUMMY_ENTITY_NAME -from feast.infra.registry.base_registry import BaseRegistry -from feast.infra.registry.registry import FEAST_OBJECT_TYPES, FeastObjectType -from feast.permissions.permission import Permission -from feast.project import Project -from feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto -from feast.protos.feast.core.Entity_pb2 import Entity as EntityProto -from feast.protos.feast.core.FeatureService_pb2 import ( - FeatureService as FeatureServiceProto, -) -from feast.protos.feast.core.FeatureView_pb2 import FeatureView as FeatureViewProto -from feast.protos.feast.core.OnDemandFeatureView_pb2 import ( - OnDemandFeatureView as OnDemandFeatureViewProto, -) -from feast.protos.feast.core.OnDemandFeatureView_pb2 import OnDemandFeatureViewSpec -from feast.protos.feast.core.Permission_pb2 import Permission as PermissionProto -from feast.protos.feast.core.SavedDataset_pb2 import SavedDataset as SavedDatasetProto -from feast.protos.feast.core.StreamFeatureView_pb2 import ( - StreamFeatureView as StreamFeatureViewProto, -) -from feast.protos.feast.core.ValidationProfile_pb2 import ( - ValidationReference as ValidationReferenceProto, -) -from feast.repo_contents import RepoContents - - -@dataclass -class FeastObjectDiff: - name: str - feast_object_type: FeastObjectType - current_feast_object: Optional[FeastObject] - new_feast_object: Optional[FeastObject] - feast_object_property_diffs: List[PropertyDiff] - transition_type: TransitionType - - -@dataclass -class RegistryDiff: - feast_object_diffs: List[FeastObjectDiff] - - def __init__(self): - self.feast_object_diffs = [] - - def add_feast_object_diff(self, feast_object_diff: FeastObjectDiff): - self.feast_object_diffs.append(feast_object_diff) - - def to_string(self): - from colorama import Fore, Style - - log_string = "" - - message_action_map = { - TransitionType.CREATE: ("Created", Fore.GREEN), - TransitionType.DELETE: ("Deleted", Fore.RED), - TransitionType.UNCHANGED: ("Unchanged", Fore.LIGHTBLUE_EX), - TransitionType.UPDATE: ("Updated", Fore.YELLOW), - } - for feast_object_diff in self.feast_object_diffs: - if feast_object_diff.name == DUMMY_ENTITY_NAME: - continue - if feast_object_diff.transition_type == TransitionType.UNCHANGED: - continue - if feast_object_diff.feast_object_type == FeastObjectType.DATA_SOURCE: - # TODO(adchia): Print statements out starting in Feast 0.24 - continue - action, color = message_action_map[feast_object_diff.transition_type] - log_string += f"{action} {feast_object_diff.feast_object_type.value} {Style.BRIGHT + color}{feast_object_diff.name}{Style.RESET_ALL}\n" - if feast_object_diff.transition_type == TransitionType.UPDATE: - for _p in feast_object_diff.feast_object_property_diffs: - log_string += f"\t{_p.property_name}: {Style.BRIGHT + color}{_p.val_existing}{Style.RESET_ALL} -> {Style.BRIGHT + Fore.LIGHTGREEN_EX}{_p.val_declared}{Style.RESET_ALL}\n" - - log_string = ( - f"{Style.BRIGHT + Fore.LIGHTBLUE_EX}No changes to registry" - if not log_string - else log_string - ) - - return log_string - - -def tag_objects_for_keep_delete_update_add( - existing_objs: Iterable[FeastObject], desired_objs: Iterable[FeastObject] -) -> Tuple[Set[FeastObject], Set[FeastObject], Set[FeastObject], Set[FeastObject]]: - # TODO(adchia): Remove the "if X.name" condition when data sources are forced to have names - existing_obj_names = {e.name for e in existing_objs if e.name} - desired_objs = [obj for obj in desired_objs if obj.name] - existing_objs = [obj for obj in existing_objs if obj.name] - desired_obj_names = {e.name for e in desired_objs if e.name} - - objs_to_add = {e for e in desired_objs if e.name not in existing_obj_names} - objs_to_update = {e for e in desired_objs if e.name in existing_obj_names} - objs_to_keep = {e for e in existing_objs if e.name in desired_obj_names} - objs_to_delete = {e for e in existing_objs if e.name not in desired_obj_names} - - return objs_to_keep, objs_to_delete, objs_to_update, objs_to_add - - -FeastObjectProto = TypeVar( - "FeastObjectProto", - DataSourceProto, - EntityProto, - FeatureViewProto, - FeatureServiceProto, - OnDemandFeatureViewProto, - StreamFeatureViewProto, - ValidationReferenceProto, - SavedDatasetProto, - PermissionProto, -) - - -FIELDS_TO_IGNORE = {"project"} - - -def diff_registry_objects( - current: FeastObject, new: FeastObject, object_type: FeastObjectType -) -> FeastObjectDiff: - current_proto = current.to_proto() - new_proto = new.to_proto() - assert current_proto.DESCRIPTOR.full_name == new_proto.DESCRIPTOR.full_name - property_diffs = [] - transition: TransitionType = TransitionType.UNCHANGED - - current_spec: FeastObjectSpecProto - new_spec: FeastObjectSpecProto - if isinstance( - current_proto, (DataSourceProto, ValidationReferenceProto) - ) or isinstance(new_proto, (DataSourceProto, ValidationReferenceProto)): - assert type(current_proto) == type(new_proto) - current_spec = cast(DataSourceProto, current_proto) - new_spec = cast(DataSourceProto, new_proto) - else: - current_spec = current_proto.spec - new_spec = new_proto.spec - if current != new: - for _field in current_spec.DESCRIPTOR.fields: - if _field.name in FIELDS_TO_IGNORE: - continue - elif getattr(current_spec, _field.name) != getattr(new_spec, _field.name): - if _field.name == "feature_transformation": - current_spec = cast(OnDemandFeatureViewSpec, current_spec) - new_spec = cast(OnDemandFeatureViewSpec, new_spec) - # Check if the old proto is populated and use that if it is - feature_transformation_udf = ( - current_spec.feature_transformation.user_defined_function - ) - if ( - current_spec.HasField("user_defined_function") - and not feature_transformation_udf - ): - deprecated_udf = current_spec.user_defined_function - else: - deprecated_udf = None - current_udf = ( - deprecated_udf - if deprecated_udf is not None - else feature_transformation_udf - ) - new_udf = new_spec.feature_transformation.user_defined_function - for _udf_field in current_udf.DESCRIPTOR.fields: - if _udf_field.name == "body": - continue - if getattr(current_udf, _udf_field.name) != getattr( - new_udf, _udf_field.name - ): - transition = TransitionType.UPDATE - property_diffs.append( - PropertyDiff( - _field.name + "." + _udf_field.name, - getattr(current_udf, _udf_field.name), - getattr(new_udf, _udf_field.name), - ) - ) - else: - transition = TransitionType.UPDATE - property_diffs.append( - PropertyDiff( - _field.name, - getattr(current_spec, _field.name), - getattr(new_spec, _field.name), - ) - ) - return FeastObjectDiff( - name=new_spec.name, - feast_object_type=object_type, - current_feast_object=current, - new_feast_object=new, - feast_object_property_diffs=property_diffs, - transition_type=transition, - ) - - -def extract_objects_for_keep_delete_update_add( - registry: BaseRegistry, - current_project: str, - desired_repo_contents: RepoContents, -) -> Tuple[ - Dict[FeastObjectType, Set[FeastObject]], - Dict[FeastObjectType, Set[FeastObject]], - Dict[FeastObjectType, Set[FeastObject]], - Dict[FeastObjectType, Set[FeastObject]], -]: - """ - Returns the objects in the registry that must be modified to achieve the desired repo state. - - Args: - registry: The registry storing the current repo state. - current_project: The Feast project whose objects should be compared. - desired_repo_contents: The desired repo state. - """ - objs_to_keep = {} - objs_to_delete = {} - objs_to_update = {} - objs_to_add = {} - - registry_object_type_to_objects: Dict[FeastObjectType, List[Any]] = ( - FeastObjectType.get_objects_from_registry(registry, current_project) - ) - registry_object_type_to_repo_contents: Dict[FeastObjectType, List[Any]] = ( - FeastObjectType.get_objects_from_repo_contents(desired_repo_contents) - ) - - for object_type in FEAST_OBJECT_TYPES: - ( - to_keep, - to_delete, - to_update, - to_add, - ) = tag_objects_for_keep_delete_update_add( - registry_object_type_to_objects[object_type], - registry_object_type_to_repo_contents[object_type], - ) - - objs_to_keep[object_type] = to_keep - objs_to_delete[object_type] = to_delete - objs_to_update[object_type] = to_update - objs_to_add[object_type] = to_add - - return objs_to_keep, objs_to_delete, objs_to_update, objs_to_add - - -def diff_between( - registry: BaseRegistry, - current_project: str, - desired_repo_contents: RepoContents, -) -> RegistryDiff: - """ - Returns the difference between the current and desired repo states. - - Args: - registry: The registry storing the current repo state. - current_project: The Feast project for which the diff is being computed. - desired_repo_contents: The desired repo state. - """ - diff = RegistryDiff() - - ( - objs_to_keep, - objs_to_delete, - objs_to_update, - objs_to_add, - ) = extract_objects_for_keep_delete_update_add( - registry, current_project, desired_repo_contents - ) - - for object_type in FEAST_OBJECT_TYPES: - objects_to_keep = objs_to_keep[object_type] - objects_to_delete = objs_to_delete[object_type] - objects_to_update = objs_to_update[object_type] - objects_to_add = objs_to_add[object_type] - - for e in objects_to_add: - diff.add_feast_object_diff( - FeastObjectDiff( - name=e.name, - feast_object_type=object_type, - current_feast_object=None, - new_feast_object=e, - feast_object_property_diffs=[], - transition_type=TransitionType.CREATE, - ) - ) - for e in objects_to_delete: - diff.add_feast_object_diff( - FeastObjectDiff( - name=e.name, - feast_object_type=object_type, - current_feast_object=e, - new_feast_object=None, - feast_object_property_diffs=[], - transition_type=TransitionType.DELETE, - ) - ) - for e in objects_to_update: - current_obj = [_e for _e in objects_to_keep if _e.name == e.name][0] - diff.add_feast_object_diff( - diff_registry_objects(current_obj, e, object_type) - ) - - return diff - - -def apply_diff_to_registry( - registry: BaseRegistry, - registry_diff: RegistryDiff, - project: str, - commit: bool = True, -): - """ - Applies the given diff to the given Feast project in the registry. - - Args: - registry: The registry to be updated. - registry_diff: The diff to apply. - project: Feast project to be updated. - commit: Whether the change should be persisted immediately - """ - for feast_object_diff in registry_diff.feast_object_diffs: - # There is no need to delete the object on an update, since applying the new object - # will automatically delete the existing object. - if feast_object_diff.transition_type == TransitionType.DELETE: - if feast_object_diff.feast_object_type == FeastObjectType.ENTITY: - entity_obj = cast(Entity, feast_object_diff.current_feast_object) - registry.delete_entity(entity_obj.name, project, commit=False) - elif feast_object_diff.feast_object_type == FeastObjectType.FEATURE_SERVICE: - feature_service_obj = cast( - FeatureService, feast_object_diff.current_feast_object - ) - registry.delete_feature_service( - feature_service_obj.name, project, commit=False - ) - elif feast_object_diff.feast_object_type in [ - FeastObjectType.FEATURE_VIEW, - FeastObjectType.ON_DEMAND_FEATURE_VIEW, - FeastObjectType.STREAM_FEATURE_VIEW, - ]: - feature_view_obj = cast( - BaseFeatureView, feast_object_diff.current_feast_object - ) - registry.delete_feature_view( - feature_view_obj.name, - project, - commit=False, - ) - elif feast_object_diff.feast_object_type == FeastObjectType.DATA_SOURCE: - ds_obj = cast(DataSource, feast_object_diff.current_feast_object) - registry.delete_data_source( - ds_obj.name, - project, - commit=False, - ) - elif feast_object_diff.feast_object_type == FeastObjectType.PERMISSION: - permission_obj = cast( - Permission, feast_object_diff.current_feast_object - ) - registry.delete_permission( - permission_obj.name, - project, - commit=False, - ) - - if feast_object_diff.transition_type in [ - TransitionType.CREATE, - TransitionType.UPDATE, - ]: - if feast_object_diff.feast_object_type == FeastObjectType.PROJECT: - registry.apply_project( - cast(Project, feast_object_diff.new_feast_object), - commit=False, - ) - if feast_object_diff.feast_object_type == FeastObjectType.DATA_SOURCE: - registry.apply_data_source( - cast(DataSource, feast_object_diff.new_feast_object), - project, - commit=False, - ) - if feast_object_diff.feast_object_type == FeastObjectType.ENTITY: - registry.apply_entity( - cast(Entity, feast_object_diff.new_feast_object), - project, - commit=False, - ) - elif feast_object_diff.feast_object_type == FeastObjectType.FEATURE_SERVICE: - registry.apply_feature_service( - cast(FeatureService, feast_object_diff.new_feast_object), - project, - commit=False, - ) - elif feast_object_diff.feast_object_type in [ - FeastObjectType.FEATURE_VIEW, - FeastObjectType.ON_DEMAND_FEATURE_VIEW, - FeastObjectType.STREAM_FEATURE_VIEW, - ]: - registry.apply_feature_view( - cast(BaseFeatureView, feast_object_diff.new_feast_object), - project, - commit=False, - ) - elif feast_object_diff.feast_object_type == FeastObjectType.PERMISSION: - registry.apply_permission( - cast(Permission, feast_object_diff.new_feast_object), - project, - commit=False, - ) - - if commit: - registry.commit() +from dataclasses import dataclass +from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, TypeVar, cast + +from feast.base_feature_view import BaseFeatureView +from feast.data_source import DataSource +from feast.diff.property_diff import PropertyDiff, TransitionType +from feast.entity import Entity +from feast.feast_object import FeastObject, FeastObjectSpecProto +from feast.feature_service import FeatureService +from feast.feature_view import DUMMY_ENTITY_NAME +from feast.infra.registry.base_registry import BaseRegistry +from feast.infra.registry.registry import FEAST_OBJECT_TYPES, FeastObjectType +from feast.permissions.permission import Permission +from feast.project import Project +from feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto +from feast.protos.feast.core.Entity_pb2 import Entity as EntityProto +from feast.protos.feast.core.FeatureService_pb2 import ( + FeatureService as FeatureServiceProto, +) +from feast.protos.feast.core.FeatureView_pb2 import FeatureView as FeatureViewProto +from feast.protos.feast.core.OnDemandFeatureView_pb2 import ( + OnDemandFeatureView as OnDemandFeatureViewProto, +) +from feast.protos.feast.core.OnDemandFeatureView_pb2 import OnDemandFeatureViewSpec +from feast.protos.feast.core.Permission_pb2 import Permission as PermissionProto +from feast.protos.feast.core.SavedDataset_pb2 import SavedDataset as SavedDatasetProto +from feast.protos.feast.core.StreamFeatureView_pb2 import ( + StreamFeatureView as StreamFeatureViewProto, +) +from feast.protos.feast.core.ValidationProfile_pb2 import ( + ValidationReference as ValidationReferenceProto, +) +from feast.repo_contents import RepoContents + + +@dataclass +class FeastObjectDiff: + name: str + feast_object_type: FeastObjectType + current_feast_object: Optional[FeastObject] + new_feast_object: Optional[FeastObject] + feast_object_property_diffs: List[PropertyDiff] + transition_type: TransitionType + + +@dataclass +class RegistryDiff: + feast_object_diffs: List[FeastObjectDiff] + + def __init__(self): + self.feast_object_diffs = [] + + def add_feast_object_diff(self, feast_object_diff: FeastObjectDiff): + self.feast_object_diffs.append(feast_object_diff) + + def to_string(self): + from colorama import Fore, Style + + log_string = "" + + message_action_map = { + TransitionType.CREATE: ("Created", Fore.GREEN), + TransitionType.DELETE: ("Deleted", Fore.RED), + TransitionType.UNCHANGED: ("Unchanged", Fore.LIGHTBLUE_EX), + TransitionType.UPDATE: ("Updated", Fore.YELLOW), + } + for feast_object_diff in self.feast_object_diffs: + if feast_object_diff.name == DUMMY_ENTITY_NAME: + continue + if feast_object_diff.transition_type == TransitionType.UNCHANGED: + continue + if feast_object_diff.feast_object_type == FeastObjectType.DATA_SOURCE: + # TODO(adchia): Print statements out starting in Feast 0.24 + continue + action, color = message_action_map[feast_object_diff.transition_type] + log_string += f"{action} {feast_object_diff.feast_object_type.value} {Style.BRIGHT + color}{feast_object_diff.name}{Style.RESET_ALL}\n" + if feast_object_diff.transition_type == TransitionType.UPDATE: + for _p in feast_object_diff.feast_object_property_diffs: + log_string += f"\t{_p.property_name}: {Style.BRIGHT + color}{_p.val_existing}{Style.RESET_ALL} -> {Style.BRIGHT + Fore.LIGHTGREEN_EX}{_p.val_declared}{Style.RESET_ALL}\n" + + log_string = ( + f"{Style.BRIGHT + Fore.LIGHTBLUE_EX}No changes to registry" + if not log_string + else log_string + ) + + return log_string + + +def tag_objects_for_keep_delete_update_add( + existing_objs: Iterable[FeastObject], desired_objs: Iterable[FeastObject] +) -> Tuple[Set[FeastObject], Set[FeastObject], Set[FeastObject], Set[FeastObject]]: + # TODO(adchia): Remove the "if X.name" condition when data sources are forced to have names + existing_obj_names = {e.name for e in existing_objs if e.name} + desired_objs = [obj for obj in desired_objs if obj.name] + existing_objs = [obj for obj in existing_objs if obj.name] + desired_obj_names = {e.name for e in desired_objs if e.name} + + objs_to_add = {e for e in desired_objs if e.name not in existing_obj_names} + objs_to_update = {e for e in desired_objs if e.name in existing_obj_names} + objs_to_keep = {e for e in existing_objs if e.name in desired_obj_names} + objs_to_delete = {e for e in existing_objs if e.name not in desired_obj_names} + + return objs_to_keep, objs_to_delete, objs_to_update, objs_to_add + + +FeastObjectProto = TypeVar( + "FeastObjectProto", + DataSourceProto, + EntityProto, + FeatureViewProto, + FeatureServiceProto, + OnDemandFeatureViewProto, + StreamFeatureViewProto, + ValidationReferenceProto, + SavedDatasetProto, + PermissionProto, +) + + +FIELDS_TO_IGNORE = {"project"} + + +def diff_registry_objects( + current: FeastObject, new: FeastObject, object_type: FeastObjectType +) -> FeastObjectDiff: + current_proto = current.to_proto() + new_proto = new.to_proto() + assert current_proto.DESCRIPTOR.full_name == new_proto.DESCRIPTOR.full_name + property_diffs = [] + transition: TransitionType = TransitionType.UNCHANGED + + current_spec: FeastObjectSpecProto + new_spec: FeastObjectSpecProto + if isinstance( + current_proto, (DataSourceProto, ValidationReferenceProto) + ) or isinstance(new_proto, (DataSourceProto, ValidationReferenceProto)): + assert type(current_proto) == type(new_proto) + current_spec = cast(DataSourceProto, current_proto) + new_spec = cast(DataSourceProto, new_proto) + else: + current_spec = current_proto.spec + new_spec = new_proto.spec + if current != new: + for _field in current_spec.DESCRIPTOR.fields: + if _field.name in FIELDS_TO_IGNORE: + continue + elif getattr(current_spec, _field.name) != getattr(new_spec, _field.name): + if _field.name == "feature_transformation": + current_spec = cast(OnDemandFeatureViewSpec, current_spec) + new_spec = cast(OnDemandFeatureViewSpec, new_spec) + # Check if the old proto is populated and use that if it is + feature_transformation_udf = ( + current_spec.feature_transformation.user_defined_function + ) + if ( + current_spec.HasField("user_defined_function") + and not feature_transformation_udf + ): + deprecated_udf = current_spec.user_defined_function + else: + deprecated_udf = None + current_udf = ( + deprecated_udf + if deprecated_udf is not None + else feature_transformation_udf + ) + new_udf = new_spec.feature_transformation.user_defined_function + for _udf_field in current_udf.DESCRIPTOR.fields: + if _udf_field.name == "body": + continue + if getattr(current_udf, _udf_field.name) != getattr( + new_udf, _udf_field.name + ): + transition = TransitionType.UPDATE + property_diffs.append( + PropertyDiff( + _field.name + "." + _udf_field.name, + getattr(current_udf, _udf_field.name), + getattr(new_udf, _udf_field.name), + ) + ) + else: + transition = TransitionType.UPDATE + property_diffs.append( + PropertyDiff( + _field.name, + getattr(current_spec, _field.name), + getattr(new_spec, _field.name), + ) + ) + return FeastObjectDiff( + name=new_spec.name, + feast_object_type=object_type, + current_feast_object=current, + new_feast_object=new, + feast_object_property_diffs=property_diffs, + transition_type=transition, + ) + + +def extract_objects_for_keep_delete_update_add( + registry: BaseRegistry, + current_project: str, + desired_repo_contents: RepoContents, +) -> Tuple[ + Dict[FeastObjectType, Set[FeastObject]], + Dict[FeastObjectType, Set[FeastObject]], + Dict[FeastObjectType, Set[FeastObject]], + Dict[FeastObjectType, Set[FeastObject]], +]: + """ + Returns the objects in the registry that must be modified to achieve the desired repo state. + + Args: + registry: The registry storing the current repo state. + current_project: The Feast project whose objects should be compared. + desired_repo_contents: The desired repo state. + """ + objs_to_keep = {} + objs_to_delete = {} + objs_to_update = {} + objs_to_add = {} + + registry_object_type_to_objects: Dict[FeastObjectType, List[Any]] = ( + FeastObjectType.get_objects_from_registry(registry, current_project) + ) + registry_object_type_to_repo_contents: Dict[FeastObjectType, List[Any]] = ( + FeastObjectType.get_objects_from_repo_contents(desired_repo_contents) + ) + + for object_type in FEAST_OBJECT_TYPES: + ( + to_keep, + to_delete, + to_update, + to_add, + ) = tag_objects_for_keep_delete_update_add( + registry_object_type_to_objects[object_type], + registry_object_type_to_repo_contents[object_type], + ) + + objs_to_keep[object_type] = to_keep + objs_to_delete[object_type] = to_delete + objs_to_update[object_type] = to_update + objs_to_add[object_type] = to_add + + return objs_to_keep, objs_to_delete, objs_to_update, objs_to_add + + +def diff_between( + registry: BaseRegistry, + current_project: str, + desired_repo_contents: RepoContents, +) -> RegistryDiff: + """ + Returns the difference between the current and desired repo states. + + Args: + registry: The registry storing the current repo state. + current_project: The Feast project for which the diff is being computed. + desired_repo_contents: The desired repo state. + """ + diff = RegistryDiff() + + ( + objs_to_keep, + objs_to_delete, + objs_to_update, + objs_to_add, + ) = extract_objects_for_keep_delete_update_add( + registry, current_project, desired_repo_contents + ) + + for object_type in FEAST_OBJECT_TYPES: + objects_to_keep = objs_to_keep[object_type] + objects_to_delete = objs_to_delete[object_type] + objects_to_update = objs_to_update[object_type] + objects_to_add = objs_to_add[object_type] + + for e in objects_to_add: + diff.add_feast_object_diff( + FeastObjectDiff( + name=e.name, + feast_object_type=object_type, + current_feast_object=None, + new_feast_object=e, + feast_object_property_diffs=[], + transition_type=TransitionType.CREATE, + ) + ) + for e in objects_to_delete: + diff.add_feast_object_diff( + FeastObjectDiff( + name=e.name, + feast_object_type=object_type, + current_feast_object=e, + new_feast_object=None, + feast_object_property_diffs=[], + transition_type=TransitionType.DELETE, + ) + ) + for e in objects_to_update: + current_obj = [_e for _e in objects_to_keep if _e.name == e.name][0] + diff.add_feast_object_diff( + diff_registry_objects(current_obj, e, object_type) + ) + + return diff + + +def apply_diff_to_registry( + registry: BaseRegistry, + registry_diff: RegistryDiff, + project: str, + commit: bool = True, + no_promote: bool = False, +): + """ + Applies the given diff to the given Feast project in the registry. + + Args: + registry: The registry to be updated. + registry_diff: The diff to apply. + project: Feast project to be updated. + commit: Whether the change should be persisted immediately + no_promote: If True, save new feature view version snapshots without + promoting them to the active definition. New versions are accessible + only via explicit @v reads. + """ + for feast_object_diff in registry_diff.feast_object_diffs: + # There is no need to delete the object on an update, since applying the new object + # will automatically delete the existing object. + if feast_object_diff.transition_type == TransitionType.DELETE: + if feast_object_diff.feast_object_type == FeastObjectType.ENTITY: + entity_obj = cast(Entity, feast_object_diff.current_feast_object) + registry.delete_entity(entity_obj.name, project, commit=False) + elif feast_object_diff.feast_object_type == FeastObjectType.FEATURE_SERVICE: + feature_service_obj = cast( + FeatureService, feast_object_diff.current_feast_object + ) + registry.delete_feature_service( + feature_service_obj.name, project, commit=False + ) + elif feast_object_diff.feast_object_type in [ + FeastObjectType.FEATURE_VIEW, + FeastObjectType.ON_DEMAND_FEATURE_VIEW, + FeastObjectType.STREAM_FEATURE_VIEW, + ]: + feature_view_obj = cast( + BaseFeatureView, feast_object_diff.current_feast_object + ) + registry.delete_feature_view( + feature_view_obj.name, + project, + commit=False, + ) + elif feast_object_diff.feast_object_type == FeastObjectType.DATA_SOURCE: + ds_obj = cast(DataSource, feast_object_diff.current_feast_object) + registry.delete_data_source( + ds_obj.name, + project, + commit=False, + ) + elif feast_object_diff.feast_object_type == FeastObjectType.PERMISSION: + permission_obj = cast( + Permission, feast_object_diff.current_feast_object + ) + registry.delete_permission( + permission_obj.name, + project, + commit=False, + ) + + if feast_object_diff.transition_type in [ + TransitionType.CREATE, + TransitionType.UPDATE, + ]: + if feast_object_diff.feast_object_type == FeastObjectType.PROJECT: + registry.apply_project( + cast(Project, feast_object_diff.new_feast_object), + commit=False, + ) + if feast_object_diff.feast_object_type == FeastObjectType.DATA_SOURCE: + registry.apply_data_source( + cast(DataSource, feast_object_diff.new_feast_object), + project, + commit=False, + ) + if feast_object_diff.feast_object_type == FeastObjectType.ENTITY: + registry.apply_entity( + cast(Entity, feast_object_diff.new_feast_object), + project, + commit=False, + ) + elif feast_object_diff.feast_object_type == FeastObjectType.FEATURE_SERVICE: + registry.apply_feature_service( + cast(FeatureService, feast_object_diff.new_feast_object), + project, + commit=False, + ) + elif feast_object_diff.feast_object_type in [ + FeastObjectType.FEATURE_VIEW, + FeastObjectType.ON_DEMAND_FEATURE_VIEW, + FeastObjectType.STREAM_FEATURE_VIEW, + ]: + registry.apply_feature_view( + cast(BaseFeatureView, feast_object_diff.new_feast_object), + project, + commit=False, + no_promote=no_promote, + ) + elif feast_object_diff.feast_object_type == FeastObjectType.PERMISSION: + registry.apply_permission( + cast(Permission, feast_object_diff.new_feast_object), + project, + commit=False, + ) + + if commit: + registry.commit() diff --git a/sdk/python/feast/doc_embedder.py b/sdk/python/feast/doc_embedder.py new file mode 100644 index 00000000000..dca2fdef2d0 --- /dev/null +++ b/sdk/python/feast/doc_embedder.py @@ -0,0 +1,380 @@ +import inspect +import os +import warnings +from pathlib import Path +from typing import TYPE_CHECKING, Callable, Optional, Protocol, runtime_checkable + +import pandas as pd + +from feast.chunker import BaseChunker, TextChunker +from feast.embedder import BaseEmbedder, MultiModalEmbedder + +if TYPE_CHECKING: + from feast.feature_store import FeatureStore + + +@runtime_checkable +class LogicalLayerFn(Protocol): + """ + Protocol defining the structure for logical layer functions. + + The logical layer transforms the output of Chunker + Embedder + into the format expected by the FeatureView schema. + """ + + def __call__(self, df: pd.DataFrame) -> pd.DataFrame: + """ + Transform chunked + embedded DataFrame to FeatureView schema. + + Args: + df: Input DataFrame with chunks and embeddings. + + Returns: + DataFrame with columns matching FeatureView schema. + """ + ... + + +def default_logical_layer_fn(df: pd.DataFrame) -> pd.DataFrame: + """ + Default logical layer function that transforms the output of Chunker + Embedder + into the format expected by the FeatureView schema. + """ + from datetime import datetime, timezone + + return pd.DataFrame( + { + "passage_id": df["chunk_id"], + "text": df["text"], + "embedding": df["text_embedding"], + "event_timestamp": [datetime.now(timezone.utc)] * len(df), + "source_id": df["original_id"], + } + ) + + +def generate_repo_file( + repo_path: str, + feature_view_name: str = "text_feature_view", + vector_length: int = 384, +) -> str: + """ + Generate a Python file with Entity and FeatureView definitions. + + This file is compatible with `feast apply` CLI. + + Args: + repo_path: Path to the feature repo directory. + feature_view_name: Name of the feature view to create. + vector_length: Dimension of the embedding vectors. Should match the + output dimension of the embedding model being used. Defaults to + 384 (matching the default all-MiniLM-L6-v2 model). + + Returns: + Path to generated file. + """ + from feast.repo_operations import is_valid_name + + if not is_valid_name(feature_view_name) or not feature_view_name.isidentifier(): + raise ValueError( + f"feature_view_name '{feature_view_name}' is invalid. " + "It should only contain alphanumeric characters, underscores, " + "and must not start with an underscore." + ) + code = f'''""" +Auto-generated by DocEmbedder. +Compatible with `feast apply` CLI. +""" +from datetime import timedelta + +from feast import Entity, FeatureView, Field, FileSource +from feast.types import Array, Float32, String, ValueType + + +# Entity +text_entity = Entity( + name="passage_id", + join_keys=["passage_id"], + description="Passage identifier", + value_type=ValueType.STRING, +) + +# Source +{feature_view_name.replace(" ", "_").replace("-", "_")}_source = FileSource( + name="{feature_view_name}_source", + path="data/{feature_view_name}.parquet", + timestamp_field="event_timestamp", +) + +# FeatureView +{feature_view_name.replace(" ", "_").replace("-", "_")} = FeatureView( + name="{feature_view_name}", + entities=[text_entity], + ttl=timedelta(days=1), + schema=[ + Field( + name="text", + dtype=String, + description="Document text content", + ), + Field( + name="embedding", + dtype=Array(Float32), + description="Vector embedding", + vector_index=True, + vector_length={vector_length}, + vector_search_metric="COSINE", + ), + Field( + name="source_id", + dtype=String, + description="Source ID", + ), + ], + source={feature_view_name.replace(" ", "_").replace("-", "_")}_source, + online=True, +) +''' + + filepath = os.path.join( + repo_path, feature_view_name.replace(" ", "_").replace("-", "_") + ".py" + ) + with open(filepath, "w") as f: + f.write(code) + + return filepath + + +class DocEmbedder: + """ + DocEmbedder is a class that embeds documents and chunks them into a format expected by the FeatureView schema using a Logic Implementation By the user. + + Args: + repo_path: Path to the feature repo (can be "." for current directory). + yaml_file: Name of the feature_store.yaml file inside repo_path. + Defaults to "feature_store.yaml". + feature_view_name: Name of the feature view to create. + chunker: Chunker to use for chunking the documents. + embedder: Embedder to use for embedding the documents. + logical_layer_fn: Logical layer function to use for transforming the output of the chunker and embedder into the format expected by the FeatureView schema. + create_feature_view: Whether to create a feature view in the feature repo. By default it will generate a Python file with the FeatureView definition. + vector_length: Explicit embedding dimension for the generated FeatureView schema. + If None (default), the dimension is auto-detected from the embedder + via ``get_embedding_dim("text")``. Falls back to 384 if detection + is not supported by the embedder. + auto_apply_repo: Whether to apply the repository automatically. By default it will apply the repository after creating the feature view. + """ + + def __init__( + self, + repo_path: str, + yaml_file: str = "feature_store.yaml", + feature_view_name: str = "text_feature_view", + chunker: Optional[BaseChunker] = None, + embedder: Optional[BaseEmbedder] = None, + logical_layer_fn: LogicalLayerFn = default_logical_layer_fn, + create_feature_view: bool = True, + vector_length: Optional[int] = None, + auto_apply_repo: bool = True, + ): + self.repo_path = repo_path + self.yaml_path = os.path.join(Path(repo_path).resolve(), yaml_file) + self.feature_view_name = feature_view_name + self.chunker = chunker or TextChunker() + self.embedder = embedder or MultiModalEmbedder() + self.store: Optional[FeatureStore] = None + + sig = inspect.signature(logical_layer_fn) + params = list(sig.parameters.values()) + if ( + len(params) != 1 + or params[0].annotation != pd.DataFrame + or sig.return_annotation != pd.DataFrame + ): + raise ValueError( + "logical_layer_fn must be a function that takes a DataFrame and returns a DataFrame" + ) + self.logical_layer_fn = logical_layer_fn + if create_feature_view: + resolved_vector_length = self._resolve_vector_length(vector_length, "text") + generate_repo_file( + repo_path=repo_path, + feature_view_name=feature_view_name, + vector_length=resolved_vector_length, + ) + if auto_apply_repo: + self.apply_repo() + + def _resolve_vector_length( + self, explicit_length: Optional[int], modality: str + ) -> int: + """ + Determine the vector length to use for the generated FeatureView. + + Priority: + 1. Explicitly provided vector_length + 2. Auto-detected from embedder via get_embedding_dim("text") + 3. Default of 384 (matching all-MiniLM-L6-v2) + + Args: + explicit_length: User-provided vector length, or None. + + Returns: + The resolved vector length as an integer. + """ + _DEFAULT_VECTOR_LENGTH = 384 + + if explicit_length is not None: + return explicit_length + + try: + dim = self.embedder.get_embedding_dim(modality) + if dim is not None: + return dim + except Exception: + pass + + return _DEFAULT_VECTOR_LENGTH + + def save_to_online_store(self, df: pd.DataFrame, feature_view_name: str) -> None: + """ + Save the embedded documents to the online store. + """ + from feast.feature_store import FeatureStore + + if self.store is None: + self.store = FeatureStore(repo_path=self.repo_path) + self.store.write_to_online_store( + feature_view_name=feature_view_name, + df=df, + ) + + # TODO (Future scope): Implement save_to_offline_store to write embedded + # documents to the offline store. Currently blocked by DaskOfflineStore + # .offline_write_batch not creating the parquet file if it does not exist. + # Once that is fixed, add a method that calls: + # store = FeatureStore(repo_path=self.repo_path) + # store.write_to_offline_store(feature_view_name=feature_view_name, df=df) + + def apply_repo(self) -> None: + """ + Apply the repository to register feature views in the registry. + """ + from feast.repo_config import load_repo_config + from feast.repo_operations import apply_total + + original_cwd = None + try: + original_cwd = os.getcwd() + repo_path = Path(self.repo_path).resolve() + config = load_repo_config( + repo_path=repo_path, + fs_yaml_file=Path(self.yaml_path), + ) + apply_total( + repo_config=config, + repo_path=repo_path, + skip_source_validation=True, + ) + finally: + if original_cwd is not None: + os.chdir(original_cwd) + + def embed_documents( + self, + documents: pd.DataFrame, + id_column: str, + source_column: str, + type_column: Optional[str] = None, + column_mapping: Optional[tuple[str, str]] = None, + custom_logical_layer_fn: Optional[ + Callable[[pd.DataFrame], pd.DataFrame] + ] = None, + ) -> pd.DataFrame: + """ + Embed a list of documents and chunk them into a format expected by the FeatureView schema using a Logic Implementation By the user and save the DataFrame to the online store. + + Args: + documents: DataFrame containing the documents to embed. + id_column: Column name containing the document IDs. + source_column: Column name containing the document sources. + type_column: Column name containing the document types. + column_mapping: Tuple mapping source columns to (modality, output column). + custom_logical_layer_fn: Custom logical layer function to use for transforming the output of the chunker and embedder into the format expected by the FeatureView schema. + Returns: + DataFrame with the embedded documents. + + Example: + documents = pd.DataFrame({ + "id": [1, 2, 3], + "source": ["source1", "source2", "source3"], + "type": ["type1", "type2", "type3"], + "text": ["text1", "text2", "text3"], + }) + column_mapping = ("text", "text_embedding") + df = embed_documents(documents=documents, id_column="id", source_column="source", type_column="type", column_mapping=column_mapping) + + """ + if custom_logical_layer_fn is not None: + sig = inspect.signature(custom_logical_layer_fn) + params = list(sig.parameters.values()) + if ( + len(params) != 1 + or params[0].annotation != pd.DataFrame + or sig.return_annotation != pd.DataFrame + ): + raise ValueError( + "custom_logical_layer_fn must be a function that takes a DataFrame and returns a DataFrame" + ) + current_logical_layer_fn = ( + custom_logical_layer_fn + if custom_logical_layer_fn is not None + else self.logical_layer_fn + ) + + if column_mapping is None: + column_mapping = ("text", "text_embedding") + + if ( + current_logical_layer_fn is default_logical_layer_fn + and column_mapping[0] == "text" + and (source_column != "text" or column_mapping[1] != "text_embedding") + ): + raise ValueError( + f"source_column='{source_column}' with output column='{column_mapping[1]}' " + f"is not compatible with default_logical_layer_fn, which expects " + f"source_column='text' and column_mapping=('text', 'text_embedding'). " + f"Provide a custom logical_layer_fn." + ) + + if column_mapping[0] == "text": + df = self.chunker.chunk_dataframe( + df=documents, + id_column=id_column, + source_column=source_column, + type_column=type_column, + ) + else: + df = documents + + df = self.embedder.embed_dataframe( + df, column_mapping={source_column: column_mapping} + ) + + if ( + column_mapping[0] == "text" + or current_logical_layer_fn is not default_logical_layer_fn + ): + df = current_logical_layer_fn(df) + else: + warnings.warn( + f"Modality '{column_mapping[0]}' is not supported by the default logical layer function. " + f"The output DataFrame will be passed directly to the online store. " + f"Ensure your FeatureView schema matches the output columns. " + f"You can provide a custom logical layer function to handle this.", + UserWarning, + stacklevel=2, + ) + + self.save_to_online_store(df=df, feature_view_name=self.feature_view_name) + return df diff --git a/sdk/python/feast/driver_test_data.py b/sdk/python/feast/driver_test_data.py index d96c9c6d387..39b7faf22c2 100644 --- a/sdk/python/feast/driver_test_data.py +++ b/sdk/python/feast/driver_test_data.py @@ -136,10 +136,38 @@ def create_driver_hourly_stats_df(drivers, start_date, end_date) -> pd.DataFrame df_all_drivers["conv_rate"] = np.random.random(size=rows).astype(np.float32) df_all_drivers["acc_rate"] = np.random.random(size=rows).astype(np.float32) df_all_drivers["avg_daily_trips"] = np.random.randint(0, 1000, size=rows).astype( - np.int32 + np.int64 ) df_all_drivers["created"] = pd.to_datetime(pd.Timestamp.now(tz=None).round("ms")) + # Complex type columns for Map, Json, and Struct examples + import json as _json + + df_all_drivers["driver_metadata"] = [ + { + "vehicle_type": np.random.choice(["sedan", "suv", "truck"]), + "rating": str(round(np.random.uniform(3.0, 5.0), 1)), + } + for _ in range(len(df_all_drivers)) + ] + df_all_drivers["driver_config"] = [ + _json.dumps( + { + "max_distance_km": int(np.random.randint(10, 200)), + "preferred_zones": list( + np.random.choice( + ["north", "south", "east", "west"], size=2, replace=False + ) + ), + } + ) + for _ in range(len(df_all_drivers)) + ] + df_all_drivers["driver_profile"] = [ + {"name": f"driver_{driver_id}", "age": str(int(np.random.randint(25, 60)))} + for driver_id in df_all_drivers["driver_id"] + ] + # Create duplicate rows that should be filtered by created timestamp # TODO: These duplicate rows area indirectly being filtered out by the point in time join already. We need to # inject a bad row at a timestamp where we know it will get joined to the entity dataframe, and then test that diff --git a/sdk/python/feast/embedded_go/online_features_service.py b/sdk/python/feast/embedded_go/online_features_service.py index 8dd7b5ba0a1..cc54808d4e2 100644 --- a/sdk/python/feast/embedded_go/online_features_service.py +++ b/sdk/python/feast/embedded_go/online_features_service.py @@ -1,345 +1,346 @@ -import logging -from functools import partial -from pathlib import Path -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union - -import pyarrow as pa -from google.protobuf.timestamp_pb2 import Timestamp -from pyarrow.cffi import ffi - -from feast.errors import ( - FeatureNameCollisionError, - RequestDataNotFoundInEntityRowsException, -) -from feast.feature_service import FeatureService -from feast.infra.feature_servers.base_config import FeatureLoggingConfig -from feast.online_response import OnlineResponse -from feast.protos.feast.serving.ServingService_pb2 import GetOnlineFeaturesResponse -from feast.protos.feast.types import Value_pb2 -from feast.repo_config import RepoConfig -from feast.types import from_value_type -from feast.value_type import ValueType - -from .lib.embedded import ( - DataTable, - LoggingOptions, - NewOnlineFeatureService, - OnlineFeatureServiceConfig, -) -from .lib.go import Slice_string -from .type_map import FEAST_TYPE_TO_ARROW_TYPE, arrow_array_to_array_of_proto - -if TYPE_CHECKING: - from feast.feature_store import FeatureStore - -NANO_SECOND = 1 -MICRO_SECOND = 1000 * NANO_SECOND -MILLI_SECOND = 1000 * MICRO_SECOND -SECOND = 1000 * MILLI_SECOND - -logger = logging.getLogger(__name__) - - -class EmbeddedOnlineFeatureServer: - def __init__( - self, repo_path: str, repo_config: RepoConfig, feature_store: "FeatureStore" - ): - # keep callback in self to prevent it from GC - self._transformation_callback = partial(transformation_callback, feature_store) - self._logging_callback = partial(logging_callback, feature_store) - - self._config = OnlineFeatureServiceConfig( - RepoPath=repo_path, RepoConfig=repo_config.json() - ) - - self._service = NewOnlineFeatureService( - self._config, - self._transformation_callback, - ) - - # This should raise an exception if there were any errors in NewOnlineFeatureService. - self._service.CheckForInstantiationError() - - def get_online_features( - self, - features_refs: List[str], - feature_service: Optional[FeatureService], - entities: Dict[str, Union[List[Any], Value_pb2.RepeatedValue]], - request_data: Dict[str, Union[List[Any], Value_pb2.RepeatedValue]], - full_feature_names: bool = False, - ): - if feature_service: - join_keys_types = self._service.GetEntityTypesMapByFeatureService( - feature_service.name - ) - else: - join_keys_types = self._service.GetEntityTypesMap( - Slice_string(features_refs) - ) - - join_keys_types = { - join_key: ValueType(enum_value) for join_key, enum_value in join_keys_types - } - - # Here we create C structures that will be shared between Python and Go. - # We will pass entities as arrow Record Batch to Go part (in_c_array & in_c_schema) - # and receive features as Record Batch from Go (out_c_array & out_c_schema) - # This objects needs to be initialized here in order to correctly - # free them later using Python GC. - ( - entities_c_schema, - entities_ptr_schema, - entities_c_array, - entities_ptr_array, - ) = allocate_schema_and_array() - ( - req_data_c_schema, - req_data_ptr_schema, - req_data_c_array, - req_data_ptr_array, - ) = allocate_schema_and_array() - - ( - features_c_schema, - features_ptr_schema, - features_c_array, - features_ptr_array, - ) = allocate_schema_and_array() - - batch, schema = map_to_record_batch(entities, join_keys_types) - schema._export_to_c(entities_ptr_schema) - batch._export_to_c(entities_ptr_array) - - batch, schema = map_to_record_batch(request_data) - schema._export_to_c(req_data_ptr_schema) - batch._export_to_c(req_data_ptr_array) - - try: - self._service.GetOnlineFeatures( - featureRefs=Slice_string(features_refs), - featureServiceName=feature_service and feature_service.name or "", - entities=DataTable( - SchemaPtr=entities_ptr_schema, DataPtr=entities_ptr_array - ), - requestData=DataTable( - SchemaPtr=req_data_ptr_schema, DataPtr=req_data_ptr_array - ), - fullFeatureNames=full_feature_names, - output=DataTable( - SchemaPtr=features_ptr_schema, DataPtr=features_ptr_array - ), - ) - except RuntimeError as exc: - (msg,) = exc.args - if msg.startswith("featureNameCollisionError"): - feature_refs = msg[len("featureNameCollisionError: ") : msg.find(";")] - feature_refs = feature_refs.split(",") - raise FeatureNameCollisionError( - feature_refs_collisions=feature_refs, - full_feature_names=full_feature_names, - ) - - if msg.startswith("requestDataNotFoundInEntityRowsException"): - feature_refs = msg[len("requestDataNotFoundInEntityRowsException: ") :] - feature_refs = feature_refs.split(",") - raise RequestDataNotFoundInEntityRowsException(feature_refs) - - raise - - record_batch = pa.RecordBatch._import_from_c( - features_ptr_array, features_ptr_schema - ) - resp = record_batch_to_online_response(record_batch) - del record_batch - return OnlineResponse(resp) - - def start_grpc_server( - self, - host: str, - port: int, - enable_logging: bool = True, - logging_options: Optional[FeatureLoggingConfig] = None, - ): - if enable_logging: - if logging_options: - self._service.StartGprcServerWithLogging( - host, - port, - self._logging_callback, - LoggingOptions( - FlushInterval=logging_options.flush_interval_secs * SECOND, - WriteInterval=logging_options.write_to_disk_interval_secs - * SECOND, - EmitTimeout=logging_options.emit_timeout_micro_secs - * MICRO_SECOND, - ChannelCapacity=logging_options.queue_capacity, - ), - ) - else: - self._service.StartGprcServerWithLoggingDefaultOpts( - host, port, self._logging_callback - ) - else: - self._service.StartGprcServer(host, port) - - def start_http_server( - self, - host: str, - port: int, - enable_logging: bool = True, - logging_options: Optional[FeatureLoggingConfig] = None, - ): - if enable_logging: - if logging_options: - self._service.StartHttpServerWithLogging( - host, - port, - self._logging_callback, - LoggingOptions( - FlushInterval=logging_options.flush_interval_secs * SECOND, - WriteInterval=logging_options.write_to_disk_interval_secs - * SECOND, - EmitTimeout=logging_options.emit_timeout_micro_secs - * MICRO_SECOND, - ChannelCapacity=logging_options.queue_capacity, - ), - ) - else: - self._service.StartHttpServerWithLoggingDefaultOpts( - host, port, self._logging_callback - ) - else: - self._service.StartHttpServer(host, port) - - def stop_grpc_server(self): - self._service.StopGrpcServer() - - def stop_http_server(self): - self._service.StopHttpServer() - - -def _to_arrow(value, type_hint: Optional[ValueType]) -> pa.Array: - if isinstance(value, Value_pb2.RepeatedValue): - _proto_to_arrow(value) - - if type_hint: - feast_type = from_value_type(type_hint) - if feast_type in FEAST_TYPE_TO_ARROW_TYPE: - return pa.array(value, FEAST_TYPE_TO_ARROW_TYPE[feast_type]) - - return pa.array(value) - - -def _proto_to_arrow(value: Value_pb2.RepeatedValue) -> pa.Array: - """ - ToDo: support entity rows already packed in protos - """ - raise NotImplementedError - - -def transformation_callback( - fs: "FeatureStore", - on_demand_feature_view_name: str, - input_arr_ptr: int, - input_schema_ptr: int, - output_arr_ptr: int, - output_schema_ptr: int, - full_feature_names: bool, -) -> int: - try: - odfv = fs.get_on_demand_feature_view(on_demand_feature_view_name) - - input_record = pa.RecordBatch._import_from_c(input_arr_ptr, input_schema_ptr) - - # For some reason, the callback is called with `full_feature_names` as a 1 if True or 0 if false. This handles - # the typeguard requirement. - full_feature_names = bool(full_feature_names) - - if odfv.mode != "pandas": - raise Exception( - f"OnDemandFeatureView mode '{odfv.mode} not supported by EmbeddedOnlineFeatureServer." - ) - - output = odfv.get_transformed_features_df( # type: ignore - input_record.to_pandas(), full_feature_names=full_feature_names - ) - output_record = pa.RecordBatch.from_pandas(output) - - output_record.schema._export_to_c(output_schema_ptr) - output_record._export_to_c(output_arr_ptr) - - return output_record.num_rows - except Exception as e: - logger.exception(f"transformation callback failed with exception: {e}", e) - return 0 - - -def logging_callback( - fs: "FeatureStore", - feature_service_name: str, - dataset_dir: str, -) -> bytes: - feature_service = fs.get_feature_service(feature_service_name, allow_cache=True) - try: - fs.write_logged_features(logs=Path(dataset_dir), source=feature_service) - except Exception as exc: - return repr(exc).encode() - - return "".encode() # no error - - -def allocate_schema_and_array(): - c_schema = ffi.new("struct ArrowSchema*") - ptr_schema = int(ffi.cast("uintptr_t", c_schema)) - - c_array = ffi.new("struct ArrowArray*") - ptr_array = int(ffi.cast("uintptr_t", c_array)) - return c_schema, ptr_schema, c_array, ptr_array - - -def map_to_record_batch( - map: Dict[str, Union[List[Any], Value_pb2.RepeatedValue]], - type_hint: Optional[Dict[str, ValueType]] = None, -) -> Tuple[pa.RecordBatch, pa.Schema]: - fields = [] - columns = [] - type_hint = type_hint or {} - - for name, values in map.items(): - arr = _to_arrow(values, type_hint.get(name)) - fields.append((name, arr.type)) - columns.append(arr) - - schema = pa.schema(fields) - batch = pa.RecordBatch.from_arrays(columns, schema=schema) - return batch, schema - - -def record_batch_to_online_response(record_batch): - resp = GetOnlineFeaturesResponse() - - for idx, field in enumerate(record_batch.schema): - if field.name.endswith("__timestamp") or field.name.endswith("__status"): - continue - - feature_vector = GetOnlineFeaturesResponse.FeatureVector( - statuses=record_batch.columns[idx + 1].to_pylist(), - event_timestamps=[ - Timestamp(seconds=seconds) - for seconds in record_batch.columns[idx + 2].to_pylist() - ], - ) - - if field.type == pa.null(): - feature_vector.values.extend( - [Value_pb2.Value()] * len(record_batch.columns[idx]) - ) - else: - feature_vector.values.extend( - arrow_array_to_array_of_proto(field.type, record_batch.columns[idx]) - ) - - resp.results.append(feature_vector) - resp.metadata.feature_names.val.append(field.name) - - return resp +import logging +from functools import partial +from pathlib import Path +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union + +import pyarrow as pa +from google.protobuf.timestamp_pb2 import Timestamp +from pyarrow.cffi import ffi + +from feast.errors import ( + FeatureNameCollisionError, + RequestDataNotFoundInEntityRowsException, +) +from feast.feature_service import FeatureService +from feast.infra.feature_servers.base_config import FeatureLoggingConfig +from feast.online_response import OnlineResponse +from feast.protos.feast.serving.ServingService_pb2 import GetOnlineFeaturesResponse +from feast.protos.feast.types import Value_pb2 +from feast.repo_config import RepoConfig +from feast.types import from_value_type +from feast.value_type import ValueType + +from .lib.embedded import ( + DataTable, + LoggingOptions, + NewOnlineFeatureService, + OnlineFeatureServiceConfig, +) +from .lib.go import Slice_string +from .type_map import FEAST_TYPE_TO_ARROW_TYPE, arrow_array_to_array_of_proto + +if TYPE_CHECKING: + from feast.feature_store import FeatureStore + +NANO_SECOND = 1 +MICRO_SECOND = 1000 * NANO_SECOND +MILLI_SECOND = 1000 * MICRO_SECOND +SECOND = 1000 * MILLI_SECOND + +logger = logging.getLogger(__name__) + + +class EmbeddedOnlineFeatureServer: + def __init__( + self, repo_path: str, repo_config: RepoConfig, feature_store: "FeatureStore" + ): + # keep callback in self to prevent it from GC + self._transformation_callback = partial(transformation_callback, feature_store) + self._logging_callback = partial(logging_callback, feature_store) + + self._config = OnlineFeatureServiceConfig( + RepoPath=repo_path, RepoConfig=repo_config.json() + ) + + self._service = NewOnlineFeatureService( + self._config, + self._transformation_callback, + ) + + # This should raise an exception if there were any errors in NewOnlineFeatureService. + self._service.CheckForInstantiationError() + + def get_online_features( + self, + features_refs: List[str], + feature_service: Optional[FeatureService], + entities: Dict[str, Union[List[Any], Value_pb2.RepeatedValue]], + request_data: Dict[str, Union[List[Any], Value_pb2.RepeatedValue]], + full_feature_names: bool = False, + include_feature_view_version_metadata: bool = False, + ): + if feature_service: + join_keys_types = self._service.GetEntityTypesMapByFeatureService( + feature_service.name + ) + else: + join_keys_types = self._service.GetEntityTypesMap( + Slice_string(features_refs) + ) + + join_keys_types = { + join_key: ValueType(enum_value) for join_key, enum_value in join_keys_types + } + + # Here we create C structures that will be shared between Python and Go. + # We will pass entities as arrow Record Batch to Go part (in_c_array & in_c_schema) + # and receive features as Record Batch from Go (out_c_array & out_c_schema) + # This objects needs to be initialized here in order to correctly + # free them later using Python GC. + ( + entities_c_schema, + entities_ptr_schema, + entities_c_array, + entities_ptr_array, + ) = allocate_schema_and_array() + ( + req_data_c_schema, + req_data_ptr_schema, + req_data_c_array, + req_data_ptr_array, + ) = allocate_schema_and_array() + + ( + features_c_schema, + features_ptr_schema, + features_c_array, + features_ptr_array, + ) = allocate_schema_and_array() + + batch, schema = map_to_record_batch(entities, join_keys_types) + schema._export_to_c(entities_ptr_schema) + batch._export_to_c(entities_ptr_array) + + batch, schema = map_to_record_batch(request_data) + schema._export_to_c(req_data_ptr_schema) + batch._export_to_c(req_data_ptr_array) + + try: + self._service.GetOnlineFeatures( + featureRefs=Slice_string(features_refs), + featureServiceName=feature_service and feature_service.name or "", + entities=DataTable( + SchemaPtr=entities_ptr_schema, DataPtr=entities_ptr_array + ), + requestData=DataTable( + SchemaPtr=req_data_ptr_schema, DataPtr=req_data_ptr_array + ), + fullFeatureNames=full_feature_names, + output=DataTable( + SchemaPtr=features_ptr_schema, DataPtr=features_ptr_array + ), + ) + except RuntimeError as exc: + (msg,) = exc.args + if msg.startswith("featureNameCollisionError"): + feature_refs = msg[len("featureNameCollisionError: ") : msg.find(";")] + feature_refs = feature_refs.split(",") + raise FeatureNameCollisionError( + feature_refs_collisions=feature_refs, + full_feature_names=full_feature_names, + ) + + if msg.startswith("requestDataNotFoundInEntityRowsException"): + feature_refs = msg[len("requestDataNotFoundInEntityRowsException: ") :] + feature_refs = feature_refs.split(",") + raise RequestDataNotFoundInEntityRowsException(feature_refs) + + raise + + record_batch = pa.RecordBatch._import_from_c( + features_ptr_array, features_ptr_schema + ) + resp = record_batch_to_online_response(record_batch) + del record_batch + return OnlineResponse(resp) + + def start_grpc_server( + self, + host: str, + port: int, + enable_logging: bool = True, + logging_options: Optional[FeatureLoggingConfig] = None, + ): + if enable_logging: + if logging_options: + self._service.StartGprcServerWithLogging( + host, + port, + self._logging_callback, + LoggingOptions( + FlushInterval=logging_options.flush_interval_secs * SECOND, + WriteInterval=logging_options.write_to_disk_interval_secs + * SECOND, + EmitTimeout=logging_options.emit_timeout_micro_secs + * MICRO_SECOND, + ChannelCapacity=logging_options.queue_capacity, + ), + ) + else: + self._service.StartGprcServerWithLoggingDefaultOpts( + host, port, self._logging_callback + ) + else: + self._service.StartGprcServer(host, port) + + def start_http_server( + self, + host: str, + port: int, + enable_logging: bool = True, + logging_options: Optional[FeatureLoggingConfig] = None, + ): + if enable_logging: + if logging_options: + self._service.StartHttpServerWithLogging( + host, + port, + self._logging_callback, + LoggingOptions( + FlushInterval=logging_options.flush_interval_secs * SECOND, + WriteInterval=logging_options.write_to_disk_interval_secs + * SECOND, + EmitTimeout=logging_options.emit_timeout_micro_secs + * MICRO_SECOND, + ChannelCapacity=logging_options.queue_capacity, + ), + ) + else: + self._service.StartHttpServerWithLoggingDefaultOpts( + host, port, self._logging_callback + ) + else: + self._service.StartHttpServer(host, port) + + def stop_grpc_server(self): + self._service.StopGrpcServer() + + def stop_http_server(self): + self._service.StopHttpServer() + + +def _to_arrow(value, type_hint: Optional[ValueType]) -> pa.Array: + if isinstance(value, Value_pb2.RepeatedValue): + _proto_to_arrow(value) + + if type_hint: + feast_type = from_value_type(type_hint) + if feast_type in FEAST_TYPE_TO_ARROW_TYPE: + return pa.array(value, FEAST_TYPE_TO_ARROW_TYPE[feast_type]) + + return pa.array(value) + + +def _proto_to_arrow(value: Value_pb2.RepeatedValue) -> pa.Array: + """ + ToDo: support entity rows already packed in protos + """ + raise NotImplementedError + + +def transformation_callback( + fs: "FeatureStore", + on_demand_feature_view_name: str, + input_arr_ptr: int, + input_schema_ptr: int, + output_arr_ptr: int, + output_schema_ptr: int, + full_feature_names: bool, +) -> int: + try: + odfv = fs.get_on_demand_feature_view(on_demand_feature_view_name) + + input_record = pa.RecordBatch._import_from_c(input_arr_ptr, input_schema_ptr) + + # For some reason, the callback is called with `full_feature_names` as a 1 if True or 0 if false. This handles + # the typeguard requirement. + full_feature_names = bool(full_feature_names) + + if odfv.mode != "pandas": + raise Exception( + f"OnDemandFeatureView mode '{odfv.mode} not supported by EmbeddedOnlineFeatureServer." + ) + + output = odfv.get_transformed_features_df( # type: ignore + input_record.to_pandas(), full_feature_names=full_feature_names + ) + output_record = pa.RecordBatch.from_pandas(output) + + output_record.schema._export_to_c(output_schema_ptr) + output_record._export_to_c(output_arr_ptr) + + return output_record.num_rows + except Exception as e: + logger.exception(f"transformation callback failed with exception: {e}", e) + return 0 + + +def logging_callback( + fs: "FeatureStore", + feature_service_name: str, + dataset_dir: str, +) -> bytes: + feature_service = fs.get_feature_service(feature_service_name, allow_cache=True) + try: + fs.write_logged_features(logs=Path(dataset_dir), source=feature_service) + except Exception as exc: + return repr(exc).encode() + + return "".encode() # no error + + +def allocate_schema_and_array(): + c_schema = ffi.new("struct ArrowSchema*") + ptr_schema = int(ffi.cast("uintptr_t", c_schema)) + + c_array = ffi.new("struct ArrowArray*") + ptr_array = int(ffi.cast("uintptr_t", c_array)) + return c_schema, ptr_schema, c_array, ptr_array + + +def map_to_record_batch( + map: Dict[str, Union[List[Any], Value_pb2.RepeatedValue]], + type_hint: Optional[Dict[str, ValueType]] = None, +) -> Tuple[pa.RecordBatch, pa.Schema]: + fields = [] + columns = [] + type_hint = type_hint or {} + + for name, values in map.items(): + arr = _to_arrow(values, type_hint.get(name)) + fields.append((name, arr.type)) + columns.append(arr) + + schema = pa.schema(fields) + batch = pa.RecordBatch.from_arrays(columns, schema=schema) + return batch, schema + + +def record_batch_to_online_response(record_batch): + resp = GetOnlineFeaturesResponse() + + for idx, field in enumerate(record_batch.schema): + if field.name.endswith("__timestamp") or field.name.endswith("__status"): + continue + + feature_vector = GetOnlineFeaturesResponse.FeatureVector( + statuses=record_batch.columns[idx + 1].to_pylist(), + event_timestamps=[ + Timestamp(seconds=seconds) + for seconds in record_batch.columns[idx + 2].to_pylist() + ], + ) + + if field.type == pa.null(): + feature_vector.values.extend( + [Value_pb2.Value()] * len(record_batch.columns[idx]) + ) + else: + feature_vector.values.extend( + arrow_array_to_array_of_proto(field.type, record_batch.columns[idx]) + ) + + resp.results.append(feature_vector) + resp.metadata.feature_names.val.append(field.name) + + return resp diff --git a/sdk/python/feast/embedder.py b/sdk/python/feast/embedder.py new file mode 100644 index 00000000000..c847f78a21c --- /dev/null +++ b/sdk/python/feast/embedder.py @@ -0,0 +1,241 @@ +from abc import ABC, abstractmethod +from dataclasses import dataclass +from typing import TYPE_CHECKING, Any, Callable, List, Optional + +if TYPE_CHECKING: + import numpy as np +import pandas as pd + + +@dataclass +class EmbeddingConfig: + batch_size: int = 64 + show_progress: bool = True + + +class BaseEmbedder(ABC): + """ + Abstract base class for embedding generation. + + Supports multiple modalities via routing. + Users can register custom modality handlers. + """ + + def __init__(self, config: Optional[EmbeddingConfig] = None): + self.config = config or EmbeddingConfig() + + # Registry: modality -> embedding function + self._modality_handlers: dict[str, Callable[[List[Any]], "np.ndarray"]] = {} + + # Register default modalities (subclass can override) + self._register_default_modalities() + + def _register_default_modalities(self) -> None: + """Override in subclass to register default modality handlers.""" + pass + + def register_modality( + self, + modality: str, + handler: Callable[[List[Any]], "np.ndarray"], + ) -> None: + """ + Register a handler for a modality. + + Args: + modality: Name of modality ("text", "image", "video", etc.) + handler: Function that takes list of inputs and returns embeddings. + """ + self._modality_handlers[modality] = handler + + @property + def supported_modalities(self) -> List[str]: + """Return list of supported modalities.""" + return list(self._modality_handlers.keys()) + + def get_embedding_dim(self, modality: str) -> Optional[int]: + """ + Return the embedding dimension for a given modality. + + Subclasses should override this to return the actual dimension + so that auto-generated FeatureView schemas use the correct vector_length. + + Args: + modality: The modality to query (e.g. "text", "image"). + + Returns: + The embedding dimension, or None if unknown. + """ + return None + + @abstractmethod + def embed(self, inputs: List[Any], modality: str) -> "np.ndarray": + """ + Generate embeddings for inputs of a given modality. + + Args: + inputs: List of inputs. + modality: Type of content ("text", "image", "video", etc.) + + Returns: + numpy array of shape (len(inputs), embedding_dim) + """ + pass + + def embed_dataframe( + self, + df: pd.DataFrame, + column_mapping: dict[str, tuple[str, str]], + ) -> pd.DataFrame: + """ + Add embeddings for multiple columns with modality routing. + + Args: + df: Input DataFrame. + column_mapping: Dict mapping source_column -> (modality, output_column). + Example: { + "text": ("text", "text_embedding"), + "image_path": ("image", "image_embedding"), + "video_path": ("video", "video_embedding"), + } + """ + df = df.copy() + + for source_column, (modality, output_column) in column_mapping.items(): + inputs = df[source_column].tolist() + embeddings = self.embed(inputs, modality) + df[output_column] = pd.Series( + [emb.tolist() for emb in embeddings], dtype=object, index=df.index + ) + + return df + + +class MultiModalEmbedder(BaseEmbedder): + """ + Multi-modal embedder with built-in support for common modalities. + + Supports: text, image, video (extensible) + """ + + def __init__( + self, + text_model: str = "all-MiniLM-L6-v2", + image_model: str = "openai/clip-vit-base-patch32", + config: Optional[EmbeddingConfig] = None, + ): + self.text_model_name = text_model + self.image_model_name = image_model + + # Lazy-loaded models + self._text_model = None + self._image_model = None + self._image_processor = None + + super().__init__(config) + + def _register_default_modalities(self) -> None: + """Register built-in modality handlers.""" + self.register_modality("text", self._embed_text) + self.register_modality("image", self._embed_image) + # Future: add more as needed + # self.register_modality("video", self._embed_video) + # self.register_modality("audio", self._embed_audio) + + def embed(self, inputs: List[Any], modality: str) -> "np.ndarray": + """Route to appropriate handler based on modality.""" + if modality not in self._modality_handlers: + raise ValueError( + f"Unsupported modality: '{modality}'. " + f"Supported: {self.supported_modalities}" + ) + + handler = self._modality_handlers[modality] + return handler(inputs) + + def get_embedding_dim(self, modality: str) -> Optional[int]: + """ + Return the embedding dimension for a given modality. + + For "text", this queries the SentenceTransformer model's dimension + (which triggers lazy model loading). + + Args: + modality: The modality to query (e.g. "text", "image"). + + Returns: + The embedding dimension, or None if unknown. + """ + if modality == "text": + return self.text_model.get_sentence_embedding_dimension() + elif modality == "image": + return self.image_model.config.vision_config.hidden_size + return None + + # Text Embedding + @property + def text_model(self): + if self._text_model is None: + from sentence_transformers import SentenceTransformer + + self._text_model = SentenceTransformer(self.text_model_name) + return self._text_model + + def _embed_text(self, inputs: List[str]) -> "np.ndarray": + return self.text_model.encode( + inputs, + batch_size=self.config.batch_size, + show_progress_bar=self.config.show_progress, + ) + + # Image Embedding + @property + def image_model(self): + if self._image_model is None: + from transformers import CLIPModel + + self._image_model = CLIPModel.from_pretrained(self.image_model_name) + return self._image_model + + @property + def image_processor(self): + if self._image_processor is None: + from transformers import CLIPProcessor + + self._image_processor = CLIPProcessor.from_pretrained(self.image_model_name) + return self._image_processor + + def _embed_image(self, inputs: List[Any]) -> "np.ndarray": + from pathlib import Path + + import numpy as np + from PIL import Image + + all_embeddings: List["np.ndarray"] = [] + batch_size = self.config.batch_size + + for start in range(0, len(inputs), batch_size): + batch = inputs[start : start + batch_size] + images = [] + opened: List[Image.Image] = [] + try: + for inp in batch: + if isinstance( + inp, (str, Path) + ): # If the input string path is too large that It gives error and we could not open the image. + img = Image.open(inp) + opened.append(img) + images.append(img) + else: + images.append(inp) + + processed = self.image_processor(images=images, return_tensors="pt") + finally: + for opened_img in opened: + opened_img.close() + + embeddings = self.image_model.get_image_features(**processed) + embeddings = embeddings / embeddings.norm(p=2, dim=-1, keepdim=True) + all_embeddings.append(embeddings.detach().numpy()) + + return np.concatenate(all_embeddings, axis=0) diff --git a/sdk/python/feast/errors.py b/sdk/python/feast/errors.py index 8c72422f44e..fb35ff79de8 100644 --- a/sdk/python/feast/errors.py +++ b/sdk/python/feast/errors.py @@ -128,6 +128,38 @@ def __init__(self, name, project=None): super().__init__(f"Feature view {name} does not exist") +class FeatureViewVersionNotFound(FeastObjectNotFoundException): + def __init__(self, name, version, project=None): + if project: + super().__init__( + f"Version {version} of feature view {name} does not exist in project {project}" + ) + else: + super().__init__(f"Version {version} of feature view {name} does not exist") + + +class VersionedOnlineReadNotSupported(FeastError): + def __init__(self, store_name: str, version: int): + super().__init__( + f"Versioned feature reads (@v{version}) are not yet supported by {store_name}. " + f"Currently only SQLite, PostgreSQL, and MySQL support version-qualified feature references. " + ) + + +class FeatureViewPinConflict(FeastError): + def __init__(self, name, version): + super().__init__( + f"Cannot pin feature view '{name}' to {version} because the definition has also been modified. " + f"To pin to an older version, only change the 'version' parameter — do not modify other fields. " + f"To apply a new definition, use version='latest' or omit the version parameter." + ) + + +class ConcurrentVersionConflict(FeastError): + def __init__(self, msg: str): + super().__init__(msg) + + class OnDemandFeatureViewNotFoundException(FeastObjectNotFoundException): def __init__(self, name, project=None): if project: @@ -411,10 +443,32 @@ def __init__(self, entity_type: type): class ConflictingFeatureViewNames(FeastError): # TODO: print file location of conflicting feature views - def __init__(self, feature_view_name: str): - super().__init__( - f"The feature view name: {feature_view_name} refers to feature views of different types." - ) + def __init__( + self, + feature_view_name: str, + existing_type: Optional[str] = None, + new_type: Optional[str] = None, + ): + if existing_type and new_type: + if existing_type == new_type: + # Same-type duplicate + super().__init__( + f"Multiple {existing_type}s with name '{feature_view_name}' found. " + f"Feature view names must be case-insensitively unique. " + f"It may be necessary to ignore certain files in your feature " + f"repository by using a .feastignore file." + ) + else: + # Cross-type conflict + super().__init__( + f"Feature view name '{feature_view_name}' is already used by a {existing_type}. " + f"Cannot register a {new_type} with the same name. " + f"Feature view names must be unique across FeatureView, StreamFeatureView, and OnDemandFeatureView." + ) + else: + super().__init__( + f"The feature view name: {feature_view_name} refers to feature views of different types." + ) class FeastInvalidInfraObjectType(FeastError): diff --git a/sdk/python/feast/feature_server.py b/sdk/python/feast/feature_server.py index 4a7b0f7318e..f60eeb9d87d 100644 --- a/sdk/python/feast/feature_server.py +++ b/sdk/python/feast/feature_server.py @@ -26,7 +26,6 @@ from typing import Any, DefaultDict, Dict, List, NamedTuple, Optional, Set, Union import pandas as pd -import psutil from dateutil import parser from fastapi import ( Depends, @@ -42,10 +41,10 @@ from fastapi.responses import JSONResponse from fastapi.staticfiles import StaticFiles from google.protobuf.json_format import MessageToDict -from prometheus_client import Gauge, start_http_server -from pydantic import BaseModel +from pydantic import BaseModel, field_validator import feast +from feast import metrics as feast_metrics from feast import proto_json, utils from feast.constants import DEFAULT_FEATURE_SERVER_REGISTRY_TTL from feast.data_source import PushMode @@ -64,14 +63,6 @@ str_to_auth_manager_type, ) -# Define prometheus metrics -cpu_usage_gauge = Gauge( - "feast_feature_server_cpu_usage", "CPU usage of the Feast feature server" -) -memory_usage_gauge = Gauge( - "feast_feature_server_memory_usage", "Memory usage of the Feast feature server" -) - # TODO: deprecate this in favor of push features class WriteToFeatureStoreRequest(BaseModel): @@ -108,18 +99,46 @@ class GetOnlineFeaturesRequest(BaseModel): feature_service: Optional[str] = None features: List[str] = [] full_feature_names: bool = False + include_feature_view_version_metadata: bool = False class GetOnlineDocumentsRequest(BaseModel): feature_service: Optional[str] = None features: List[str] = [] full_feature_names: bool = False + include_feature_view_version_metadata: bool = False top_k: Optional[int] = None query: Optional[List[float]] = None query_string: Optional[str] = None api_version: Optional[int] = 1 +class FeatureVectorResponse(BaseModel): + values: List[Any] = [] + statuses: List[str] = [] + event_timestamps: List[str] = [] + + +class OnlineFeaturesMetadataResponse(BaseModel): + feature_names: List[str] = [] + + @field_validator("feature_names", mode="before") + @classmethod + def _unwrap_feature_list(cls, v: Any) -> Any: + """Accept both the proto_json-patched flat list and the raw + protobuf ``{"val": [...]}`` dict produced by ``MessageToDict`` + when the monkey-patch is absent or ineffective.""" + if isinstance(v, dict) and "val" in v: + return v["val"] + return v + + +class OnlineFeaturesResponse(BaseModel): + metadata: Optional[OnlineFeaturesMetadataResponse] = None + results: List[FeatureVectorResponse] = [] + status: Optional[bool] = None + + class ChatMessage(BaseModel): role: str content: str @@ -129,6 +148,30 @@ class ChatRequest(BaseModel): messages: List[ChatMessage] +def _resolve_feature_counts( + features: Union[List[str], "feast.FeatureService"], +) -> tuple: + """Return (feature_count, feature_view_count) from the resolved features. + + ``features`` is either a list of ``"feature_view:feature"`` strings or + a ``FeatureService`` with ``feature_view_projections``. + """ + from feast.feature_service import FeatureService + + if isinstance(features, FeatureService): + projections = features.feature_view_projections + fv_count = len(projections) + feat_count = sum(len(p.features) for p in projections) + elif isinstance(features, list): + feat_count = len(features) + fv_names = {ref.split(":")[0].split("@")[0] for ref in features if ":" in ref} + fv_count = len(fv_names) + else: + feat_count = 0 + fv_count = 0 + return str(feat_count), str(fv_count) + + async def _get_features( request: Union[GetOnlineFeaturesRequest, GetOnlineDocumentsRequest], store: "feast.FeatureStore", @@ -323,161 +366,181 @@ async def lifespan(app: FastAPI): @app.post( "/get-online-features", dependencies=[Depends(inject_user_details)], + response_model=OnlineFeaturesResponse, ) - async def get_online_features(request: GetOnlineFeaturesRequest) -> Dict[str, Any]: - # Initialize parameters for FeatureStore.get_online_features(...) call - features = await _get_features(request, store) - - read_params = dict( - features=features, - entity_rows=request.entities, - full_feature_names=request.full_feature_names, - ) - - if store._get_provider().async_supported.online.read: - response = await store.get_online_features_async(**read_params) # type: ignore - else: - response = await run_in_threadpool( - lambda: store.get_online_features(**read_params) # type: ignore + async def get_online_features(request: GetOnlineFeaturesRequest) -> Any: + with feast_metrics.track_request_latency( + "/get-online-features", + ) as metrics_ctx: + features = await _get_features(request, store) + feat_count, fv_count = _resolve_feature_counts(features) + metrics_ctx.feature_count = feat_count + metrics_ctx.feature_view_count = fv_count + + entity_count = len(next(iter(request.entities.values()), [])) + feast_metrics.track_online_features_entities(entity_count) + + read_params = dict( + features=features, + entity_rows=request.entities, + full_feature_names=request.full_feature_names, + include_feature_view_version_metadata=request.include_feature_view_version_metadata, ) - # Convert the Protobuf object to JSON and return it - response_dict = await run_in_threadpool( - MessageToDict, - response.proto, - preserving_proto_field_name=True, - float_precision=18, - ) - return response_dict + if store._get_provider().async_supported.online.read: + response = await store.get_online_features_async(**read_params) # type: ignore + else: + response = await run_in_threadpool( + lambda: store.get_online_features(**read_params) # type: ignore + ) + + response_dict = await run_in_threadpool( + MessageToDict, + response.proto, + preserving_proto_field_name=True, + float_precision=18, + ) + return response_dict @app.post( "/retrieve-online-documents", dependencies=[Depends(inject_user_details)], + response_model=OnlineFeaturesResponse, ) async def retrieve_online_documents( request: GetOnlineDocumentsRequest, - ) -> Dict[str, Any]: - logger.warning( - "This endpoint is in alpha and will be moved to /get-online-features when stable." - ) - # Initialize parameters for FeatureStore.retrieve_online_documents_v2(...) call - features = await _get_features(request, store) - - read_params = dict(features=features, query=request.query, top_k=request.top_k) - if request.api_version == 2 and request.query_string is not None: - read_params["query_string"] = request.query_string - - if request.api_version == 2: - response = await run_in_threadpool( - lambda: store.retrieve_online_documents_v2(**read_params) # type: ignore + ) -> Any: + with feast_metrics.track_request_latency("/retrieve-online-documents"): + logger.warning( + "This endpoint is in alpha and will be moved to /get-online-features when stable." ) - else: - response = await run_in_threadpool( - lambda: store.retrieve_online_documents(**read_params) # type: ignore + features = await _get_features(request, store) + + read_params = dict( + features=features, + query=request.query, + top_k=request.top_k, ) + if request.api_version == 2 and request.query_string is not None: + read_params["query_string"] = request.query_string - # Convert the Protobuf object to JSON and return it - response_dict = await run_in_threadpool( - MessageToDict, - response.proto, - preserving_proto_field_name=True, - float_precision=18, - ) - return response_dict + if request.api_version == 2: + read_params["include_feature_view_version_metadata"] = ( + request.include_feature_view_version_metadata + ) + response = await run_in_threadpool( + lambda: store.retrieve_online_documents_v2(**read_params) # type: ignore + ) + else: + response = await run_in_threadpool( + lambda: store.retrieve_online_documents(**read_params) # type: ignore + ) + + response_dict = await run_in_threadpool( + MessageToDict, + response.proto, + preserving_proto_field_name=True, + float_precision=18, + ) + return response_dict @app.post("/push", dependencies=[Depends(inject_user_details)]) async def push(request: PushFeaturesRequest) -> Response: - df = pd.DataFrame(request.df) - actions = [] - if request.to == "offline": - to = PushMode.OFFLINE - actions = [AuthzedAction.WRITE_OFFLINE] - elif request.to == "online": - to = PushMode.ONLINE - actions = [AuthzedAction.WRITE_ONLINE] - elif request.to == "online_and_offline": - to = PushMode.ONLINE_AND_OFFLINE - actions = WRITE - else: - raise ValueError( - f"{request.to} is not a supported push format. Please specify one of these ['online', 'offline', 'online_and_offline']." - ) + with feast_metrics.track_request_latency("/push"): + df = pd.DataFrame(request.df) + actions = [] + if request.to == "offline": + to = PushMode.OFFLINE + actions = [AuthzedAction.WRITE_OFFLINE] + elif request.to == "online": + to = PushMode.ONLINE + actions = [AuthzedAction.WRITE_ONLINE] + elif request.to == "online_and_offline": + to = PushMode.ONLINE_AND_OFFLINE + actions = WRITE + else: + raise ValueError( + f"{request.to} is not a supported push format. Please specify one of these ['online', 'offline', 'online_and_offline']." + ) - from feast.data_source import PushSource - - all_fvs = store.list_feature_views( - allow_cache=request.allow_registry_cache - ) + store.list_stream_feature_views(allow_cache=request.allow_registry_cache) - fvs_with_push_sources = { - fv - for fv in all_fvs - if ( - fv.stream_source is not None - and isinstance(fv.stream_source, PushSource) - and fv.stream_source.name == request.push_source_name - ) - } + from feast.data_source import PushSource - for feature_view in fvs_with_push_sources: - assert_permissions(resource=feature_view, actions=actions) - - async def _push_with_to(push_to: PushMode) -> None: - """ - Helper for performing a single push operation. - - NOTE: - - Feast providers **do not currently support async offline writes**. - - Therefore: - * ONLINE and ONLINE_AND_OFFLINE → may be async, depending on provider.async_supported.online.write - * OFFLINE → always synchronous, but executed via run_in_threadpool when called from HTTP handlers. - - The OfflineWriteBatcher handles offline writes directly in its own background thread, but the offline store writes are currently synchronous only. - """ - push_source_name = request.push_source_name - allow_registry_cache = request.allow_registry_cache - transform_on_write = request.transform_on_write - - # Async currently only applies to online store writes (ONLINE / ONLINE_AND_OFFLINE paths) as theres no async for offline store - if push_to in (PushMode.ONLINE, PushMode.ONLINE_AND_OFFLINE) and ( - store._get_provider().async_supported.online.write - ): - await store.push_async( - push_source_name=push_source_name, - df=df, - allow_registry_cache=allow_registry_cache, - to=push_to, - transform_on_write=transform_on_write, + all_fvs = store.list_feature_views( + allow_cache=request.allow_registry_cache + ) + store.list_stream_feature_views( + allow_cache=request.allow_registry_cache + ) + fvs_with_push_sources = { + fv + for fv in all_fvs + if ( + fv.stream_source is not None + and isinstance(fv.stream_source, PushSource) + and fv.stream_source.name == request.push_source_name ) - else: - await run_in_threadpool( - lambda: store.push( + } + + for feature_view in fvs_with_push_sources: + assert_permissions(resource=feature_view, actions=actions) + + async def _push_with_to(push_to: PushMode) -> None: + """ + Helper for performing a single push operation. + + NOTE: + - Feast providers **do not currently support async offline writes**. + - Therefore: + * ONLINE and ONLINE_AND_OFFLINE → may be async, depending on provider.async_supported.online.write + * OFFLINE → always synchronous, but executed via run_in_threadpool when called from HTTP handlers. + - The OfflineWriteBatcher handles offline writes directly in its own background thread, but the offline store writes are currently synchronous only. + """ + push_source_name = request.push_source_name + allow_registry_cache = request.allow_registry_cache + transform_on_write = request.transform_on_write + + # Async currently only applies to online store writes (ONLINE / ONLINE_AND_OFFLINE paths) as theres no async for offline store + if push_to in (PushMode.ONLINE, PushMode.ONLINE_AND_OFFLINE) and ( + store._get_provider().async_supported.online.write + ): + await store.push_async( push_source_name=push_source_name, df=df, allow_registry_cache=allow_registry_cache, to=push_to, transform_on_write=transform_on_write, ) - ) + else: + await run_in_threadpool( + lambda: store.push( + push_source_name=push_source_name, + df=df, + allow_registry_cache=allow_registry_cache, + to=push_to, + transform_on_write=transform_on_write, + ) + ) - needs_online = to in (PushMode.ONLINE, PushMode.ONLINE_AND_OFFLINE) - needs_offline = to in (PushMode.OFFLINE, PushMode.ONLINE_AND_OFFLINE) + needs_online = to in (PushMode.ONLINE, PushMode.ONLINE_AND_OFFLINE) + needs_offline = to in (PushMode.OFFLINE, PushMode.ONLINE_AND_OFFLINE) - status_code = status.HTTP_200_OK + status_code = status.HTTP_200_OK - if offline_batcher is None or not needs_offline: - await _push_with_to(to) - else: - if needs_online: - await _push_with_to(PushMode.ONLINE) - - offline_batcher.enqueue( - push_source_name=request.push_source_name, - df=df, - allow_registry_cache=request.allow_registry_cache, - transform_on_write=request.transform_on_write, - ) - status_code = status.HTTP_202_ACCEPTED + if offline_batcher is None or not needs_offline: + await _push_with_to(to) + else: + if needs_online: + await _push_with_to(PushMode.ONLINE) - return Response(status_code=status_code) + offline_batcher.enqueue( + push_source_name=request.push_source_name, + df=df, + allow_registry_cache=request.allow_registry_cache, + transform_on_write=request.transform_on_write, + ) + status_code = status.HTTP_202_ACCEPTED + + feast_metrics.track_push(request.push_source_name, request.to) + return Response(status_code=status_code) async def _get_feast_object( feature_view_name: str, allow_registry_cache: bool @@ -529,51 +592,50 @@ async def chat_ui(): @app.post("/materialize", dependencies=[Depends(inject_user_details)]) async def materialize(request: MaterializeRequest) -> None: - for feature_view in request.feature_views or []: - resource = await _get_feast_object(feature_view, True) - assert_permissions( - resource=resource, - actions=[AuthzedAction.WRITE_ONLINE], - ) - - if request.disable_event_timestamp: - # Query all available data and use current datetime as event timestamp - now = datetime.now() - start_date = datetime( - 1970, 1, 1 - ) # Beginning of time to capture all historical data - end_date = now - else: - if not request.start_ts or not request.end_ts: - raise ValueError( - "start_ts and end_ts are required when disable_event_timestamp is False" + with feast_metrics.track_request_latency("/materialize"): + for feature_view in request.feature_views or []: + resource = await _get_feast_object(feature_view, True) + assert_permissions( + resource=resource, + actions=[AuthzedAction.WRITE_ONLINE], ) - start_date = utils.make_tzaware(parser.parse(request.start_ts)) - end_date = utils.make_tzaware(parser.parse(request.end_ts)) - await run_in_threadpool( - store.materialize, - start_date, - end_date, - request.feature_views, - disable_event_timestamp=request.disable_event_timestamp, - full_feature_names=request.full_feature_names, - ) + if request.disable_event_timestamp: + now = datetime.now() + start_date = datetime(1970, 1, 1) + end_date = now + else: + if not request.start_ts or not request.end_ts: + raise ValueError( + "start_ts and end_ts are required when disable_event_timestamp is False" + ) + start_date = utils.make_tzaware(parser.parse(request.start_ts)) + end_date = utils.make_tzaware(parser.parse(request.end_ts)) + + await run_in_threadpool( + store.materialize, + start_date, + end_date, + request.feature_views, + disable_event_timestamp=request.disable_event_timestamp, + full_feature_names=request.full_feature_names, + ) @app.post("/materialize-incremental", dependencies=[Depends(inject_user_details)]) async def materialize_incremental(request: MaterializeIncrementalRequest) -> None: - for feature_view in request.feature_views or []: - resource = await _get_feast_object(feature_view, True) - assert_permissions( - resource=resource, - actions=[AuthzedAction.WRITE_ONLINE], + with feast_metrics.track_request_latency("/materialize-incremental"): + for feature_view in request.feature_views or []: + resource = await _get_feast_object(feature_view, True) + assert_permissions( + resource=resource, + actions=[AuthzedAction.WRITE_ONLINE], + ) + await run_in_threadpool( + store.materialize_incremental, + utils.make_tzaware(parser.parse(request.end_ts)), + request.feature_views, + full_feature_names=request.full_feature_names, ) - await run_in_threadpool( - store.materialize_incremental, - utils.make_tzaware(parser.parse(request.end_ts)), - request.feature_views, - full_feature_names=request.full_feature_names, - ) @app.exception_handler(Exception) async def rest_exception_handler(request: Request, exc: Exception): @@ -668,6 +730,7 @@ async def websocket_endpoint(websocket: WebSocket): def _add_mcp_support_if_enabled(app, store: "feast.FeatureStore"): """Add MCP support to the FastAPI app if enabled in configuration.""" + mcp_transport_not_supported_error = None try: # Check if MCP is enabled in feature server config if ( @@ -676,7 +739,16 @@ def _add_mcp_support_if_enabled(app, store: "feast.FeatureStore"): and store.config.feature_server.type == "mcp" and getattr(store.config.feature_server, "mcp_enabled", False) ): - from feast.infra.mcp_servers.mcp_server import add_mcp_support_to_app + try: + from feast.infra.mcp_servers.mcp_server import ( + McpTransportNotSupportedError, + add_mcp_support_to_app, + ) + + mcp_transport_not_supported_error = McpTransportNotSupportedError + except ImportError as e: + logger.error(f"Error checking/adding MCP support: {e}") + return mcp_server = add_mcp_support_to_app(app, store, store.config.feature_server) @@ -687,6 +759,10 @@ def _add_mcp_support_if_enabled(app, store: "feast.FeatureStore"): else: logger.debug("MCP support is not enabled in feature server configuration") except Exception as e: + if mcp_transport_not_supported_error and isinstance( + e, mcp_transport_not_supported_error + ): + raise logger.error(f"Error checking/adding MCP support: {e}") # Don't fail the entire server if MCP fails to initialize @@ -695,12 +771,15 @@ def _add_mcp_support_if_enabled(app, store: "feast.FeatureStore"): import gunicorn.app.base class FeastServeApplication(gunicorn.app.base.BaseApplication): - def __init__(self, store: "feast.FeatureStore", **options): + def __init__( + self, store: "feast.FeatureStore", metrics_enabled: bool = False, **options + ): self._app = get_app( store=store, registry_ttl_sec=options["registry_ttl_sec"], ) self._options = options + self._metrics_enabled = metrics_enabled super().__init__() def load_config(self): @@ -709,25 +788,20 @@ def load_config(self): self.cfg.set(key.lower(), value) self.cfg.set("worker_class", "uvicorn_worker.UvicornWorker") + if self._metrics_enabled: + self.cfg.set("post_worker_init", _gunicorn_post_worker_init) + self.cfg.set("child_exit", _gunicorn_child_exit) def load(self): return self._app + def _gunicorn_post_worker_init(worker): + """Start per-worker resource monitoring after Gunicorn forks.""" + feast_metrics.init_worker_monitoring() -def monitor_resources(self, interval: int = 5): - """Function to monitor and update CPU and memory usage metrics.""" - logger.debug(f"Starting resource monitoring with interval {interval} seconds") - p = psutil.Process() - logger.debug(f"PID is {p.pid}") - while True: - with p.oneshot(): - cpu_usage = p.cpu_percent() - memory_usage = p.memory_percent() - logger.debug(f"CPU usage: {cpu_usage}%, Memory usage: {memory_usage}%") - logger.debug(f"CPU usage: {cpu_usage}%, Memory usage: {memory_usage}%") - cpu_usage_gauge.set(cpu_usage) - memory_usage_gauge.set(memory_usage) - time.sleep(interval) + def _gunicorn_child_exit(server, worker): + """Clean up Prometheus metric files for a dead worker.""" + feast_metrics.mark_process_dead(worker.pid) def start_server( @@ -749,15 +823,19 @@ def start_server( raise ValueError( "Both key and cert file paths are required to start server in TLS mode." ) - if metrics: - logger.info("Starting Prometheus Server") - start_http_server(8000) - logger.debug("Starting background thread to monitor CPU and memory usage") - monitoring_thread = threading.Thread( - target=monitor_resources, args=(5,), daemon=True + fs_cfg = getattr(store.config, "feature_server", None) + metrics_cfg = getattr(fs_cfg, "metrics", None) + metrics_from_config = getattr(metrics_cfg, "enabled", False) + metrics_active = metrics or metrics_from_config + uses_gunicorn = sys.platform != "win32" + if metrics_active: + flags = feast_metrics.build_metrics_flags(metrics_cfg) + feast_metrics.start_metrics_server( + store, + metrics_config=flags, + start_resource_monitoring=not uses_gunicorn, ) - monitoring_thread.start() logger.debug("start_server called") auth_type = str_to_auth_manager_type(store.config.auth_config.type) @@ -771,7 +849,7 @@ def start_server( ) logger.debug("Auth manager initialized successfully") - if sys.platform != "win32": + if uses_gunicorn: options = { "bind": f"{host}:{port}", "accesslog": None if no_access_log else "-", @@ -787,7 +865,9 @@ def start_server( if tls_key_path and tls_cert_path: options["keyfile"] = tls_key_path options["certfile"] = tls_cert_path - FeastServeApplication(store=store, **options).run() + FeastServeApplication( + store=store, metrics_enabled=metrics_active, **options + ).run() else: import uvicorn diff --git a/sdk/python/feast/feature_store.py b/sdk/python/feast/feature_store.py index 36ff2c9d4eb..f95bbf10c03 100644 --- a/sdk/python/feast/feature_store.py +++ b/sdk/python/feast/feature_store.py @@ -15,6 +15,7 @@ import copy import itertools import os +import time import warnings from datetime import datetime, timedelta from pathlib import Path @@ -58,6 +59,7 @@ from feast.dqm.errors import ValidationFailed from feast.entity import Entity from feast.errors import ( + ConflictingFeatureViewNames, DataFrameSerializationError, DataSourceRepeatNamesException, FeatureViewNotFoundException, @@ -98,6 +100,30 @@ from feast.transformation.pandas_transformation import PandasTransformation from feast.transformation.python_transformation import PythonTransformation from feast.utils import _get_feature_view_vector_field_metadata, _utc_now +from feast.version_utils import parse_version + +_track_materialization = None # Lazy-loaded on first materialization call +_track_materialization_loaded = False + + +def _get_track_materialization(): + """Lazy-import feast.metrics only when materialization tracking is needed. + + Avoids importing the metrics module (and its prometheus_client / + psutil dependencies plus temp-dir creation) for every FeatureStore + usage such as ``feast apply`` or simple SDK reads. + """ + global _track_materialization, _track_materialization_loaded + if not _track_materialization_loaded: + _track_materialization_loaded = True + try: + from feast.metrics import track_materialization + + _track_materialization = track_materialization + except Exception: # pragma: no cover + _track_materialization = None + return _track_materialization + warnings.simplefilter("once", DeprecationWarning) @@ -543,6 +569,18 @@ def _get_feature_view( feature_view.entities = [] return feature_view + def list_feature_view_versions(self, name: str) -> List[Dict[str, Any]]: + """ + List version history for a feature view. + + Args: + name: Name of feature view. + + Returns: + List of version records. + """ + return self.registry.list_feature_view_versions(name, self.project) + def get_stream_feature_view( self, name: str, allow_registry_cache: bool = False ) -> StreamFeatureView: @@ -677,11 +715,21 @@ def _make_inferences( ) update_data_sources_with_inferred_event_timestamp_col( - [view.batch_source for view in views_to_update], self.config + [ + view.batch_source + for view in views_to_update + if view.batch_source is not None + ], + self.config, ) update_data_sources_with_inferred_event_timestamp_col( - [view.batch_source for view in sfvs_to_update], self.config + [ + view.batch_source + for view in sfvs_to_update + if view.batch_source is not None + ], + self.config, ) # New feature views may reference previously applied entities. @@ -725,9 +773,39 @@ def _make_inferences( for feature_service in feature_services_to_update: feature_service.infer_features(fvs_to_update=fvs_to_update_map) + def _validate_materialize_version( + self, + version: Optional[str], + feature_views: Optional[List[str]], + ) -> Optional[int]: + """Validate and parse the version parameter for materialize calls. + + Returns the parsed version number, or None if no version was specified. + """ + if version is None: + return None + + if not feature_views or len(feature_views) != 1: + raise ValueError( + "--version requires --views with exactly one feature view." + ) + + if not self.config.registry.enable_online_feature_view_versioning: + raise ValueError( + "Version-aware materialization requires " + "'enable_online_feature_view_versioning: true' under 'registry' " + "in feature_store.yaml." + ) + + is_latest, version_number = parse_version(version) + if is_latest: + return None + return version_number + def _get_feature_views_to_materialize( self, feature_views: Optional[List[str]], + version: Optional[int] = None, ) -> List[Union[FeatureView, OnDemandFeatureView]]: """ Returns the list of feature views that should be materialized. @@ -736,6 +814,8 @@ def _get_feature_views_to_materialize( Args: feature_views: List of names of feature views to materialize. + version: If set, load this specific version number from the registry + instead of the active definition. Requires exactly one feature view name. Raises: FeatureViewNotFoundException: One of the specified feature views could not be found. @@ -767,15 +847,25 @@ def _get_feature_views_to_materialize( else: for name in feature_views: feature_view: Union[FeatureView, OnDemandFeatureView] - try: - feature_view = self._get_feature_view(name, hide_dummy_entity=False) - except FeatureViewNotFoundException: + if version is not None: + feature_view = cast( + Union[FeatureView, OnDemandFeatureView], + self.registry.get_feature_view_by_version( + name, self.project, version + ), + ) + else: try: - feature_view = self._get_stream_feature_view( + feature_view = self._get_feature_view( name, hide_dummy_entity=False ) except FeatureViewNotFoundException: - feature_view = self.get_on_demand_feature_view(name) + try: + feature_view = self._get_stream_feature_view( + name, hide_dummy_entity=False + ) + except FeatureViewNotFoundException: + feature_view = self.get_on_demand_feature_view(name) if hasattr(feature_view, "online") and not feature_view.online: raise ValueError( @@ -885,6 +975,7 @@ def _apply_diffs( infra_diff: InfraDiff, new_infra: Infra, progress_ctx: Optional["ApplyProgressContext"] = None, + no_promote: bool = False, ): """Applies the given diffs to the metadata store and infrastructure. @@ -908,7 +999,11 @@ def _apply_diffs( # Registry phase apply_diff_to_registry( - self.registry, registry_diff, self.project, commit=False + self.registry, + registry_diff, + self.project, + commit=False, + no_promote=no_promote, ) if progress_ctx: @@ -959,6 +1054,7 @@ def apply( objects_to_delete: Optional[List[FeastObject]] = None, partial: bool = True, skip_feature_view_validation: bool = False, + no_promote: bool = False, ): """Register objects to metadata store and update related infrastructure. @@ -1101,9 +1197,12 @@ def apply( for ds in data_sources_to_update: self.registry.apply_data_source(ds, project=self.project, commit=False) for view in itertools.chain(views_to_update, odfvs_to_update, sfvs_to_update): - self.registry.apply_feature_view(view, project=self.project, commit=False) + self.registry.apply_feature_view( + view, project=self.project, commit=False, no_promote=no_promote + ) for ent in entities_to_update: self.registry.apply_entity(ent, project=self.project, commit=False) + for feature_service in services_to_update: self.registry.apply_feature_service( feature_service, project=self.project, commit=False @@ -1348,6 +1447,19 @@ def get_historical_features( feature_views = list(view for view, _ in fvs) on_demand_feature_views = list(view for view, _ in odfvs) + # ODFV source FV dependencies (e.g. driver_stats:conv_rate) are resolved + # by _group_feature_refs and included in `fvs`, but not in _feature_refs. + # Offline stores use feature_refs to map which features to fetch from each + # FV, so we must include these implicit dependency refs. + _feature_refs_for_provider = list(_feature_refs) + existing_refs = set(_feature_refs) + for view, feats in fvs: + for feat in feats: + ref = f"{view.projection.name_to_use()}:{feat}" + if ref not in existing_refs: + _feature_refs_for_provider.append(ref) + existing_refs.add(ref) + # Check that the right request data is present in the entity_df if type(entity_df) == pd.DataFrame: if self.config.coerce_tz_aware: @@ -1374,7 +1486,7 @@ def get_historical_features( job = provider.get_historical_features( self.config, feature_views, - _feature_refs, + _feature_refs_for_provider, entity_df, self.registry, self.project, @@ -1598,6 +1710,7 @@ def materialize_incremental( end_date: datetime, feature_views: Optional[List[str]] = None, full_feature_names: bool = False, + version: Optional[str] = None, ) -> None: """ Materialize incremental new data from the offline store into the online store. @@ -1614,6 +1727,8 @@ def materialize_incremental( materialization for the specified feature views. full_feature_names (bool): If True, feature names will be prefixed with the corresponding feature view name. + version (str): Optional version to materialize (e.g., 'v2'). Requires feature_views + with exactly one entry and enable_online_feature_view_versioning to be enabled. Raises: Exception: A feature view being materialized does not have a TTL set. @@ -1629,8 +1744,9 @@ def materialize_incremental( ... """ + parsed_version = self._validate_materialize_version(version, feature_views) feature_views_to_materialize = self._get_feature_views_to_materialize( - feature_views + feature_views, version=parsed_version ) _print_materialization_log( None, @@ -1704,15 +1820,29 @@ def tqdm_builder(length): start_date = utils.make_tzaware(start_date) end_date = utils.make_tzaware(end_date) or _utc_now() - provider.materialize_single_feature_view( - config=self.config, - feature_view=feature_view, - start_date=start_date, - end_date=end_date, - registry=self.registry, - project=self.project, - tqdm_builder=tqdm_builder, - ) + fv_start = time.monotonic() + fv_success = True + try: + provider.materialize_single_feature_view( + config=self.config, + feature_view=feature_view, + start_date=start_date, + end_date=end_date, + registry=self.registry, + project=self.project, + tqdm_builder=tqdm_builder, + ) + except Exception: + fv_success = False + raise + finally: + _tracker = _get_track_materialization() + if _tracker is not None: + _tracker( + feature_view.name, + fv_success, + time.monotonic() - fv_start, + ) if not isinstance(feature_view, OnDemandFeatureView): self.registry.apply_materialization( feature_view, @@ -1737,6 +1867,7 @@ def materialize( feature_views: Optional[List[str]] = None, disable_event_timestamp: bool = False, full_feature_names: bool = False, + version: Optional[str] = None, ) -> None: """ Materialize data from the offline store into the online store. @@ -1753,6 +1884,8 @@ def materialize( disable_event_timestamp (bool): If True, materializes all available data using current datetime as event timestamp instead of source event timestamps full_feature_names (bool): If True, feature names will be prefixed with the corresponding feature view name. + version (str): Optional version to materialize (e.g., 'v2'). Requires feature_views + with exactly one entry and enable_online_feature_view_versioning to be enabled. Examples: Materialize all features into the online store over the interval @@ -1772,8 +1905,9 @@ def materialize( f"The given start_date {start_date} is greater than the given end_date {end_date}." ) + parsed_version = self._validate_materialize_version(version, feature_views) feature_views_to_materialize = self._get_feature_views_to_materialize( - feature_views + feature_views, version=parsed_version ) _print_materialization_log( start_date, @@ -1813,16 +1947,30 @@ def tqdm_builder(length): start_date = utils.make_tzaware(start_date) end_date = utils.make_tzaware(end_date) - provider.materialize_single_feature_view( - config=self.config, - feature_view=feature_view, - start_date=start_date, - end_date=end_date, - registry=self.registry, - project=self.project, - tqdm_builder=tqdm_builder, - disable_event_timestamp=disable_event_timestamp, - ) + fv_start = time.monotonic() + fv_success = True + try: + provider.materialize_single_feature_view( + config=self.config, + feature_view=feature_view, + start_date=start_date, + end_date=end_date, + registry=self.registry, + project=self.project, + tqdm_builder=tqdm_builder, + disable_event_timestamp=disable_event_timestamp, + ) + except Exception: + fv_success = False + raise + finally: + _tracker = _get_track_materialization() + if _tracker is not None: + _tracker( + feature_view.name, + fv_success, + time.monotonic() - fv_start, + ) self.registry.apply_materialization( feature_view, @@ -2034,76 +2182,104 @@ def _transform_on_demand_feature_view_df( Raises: Exception: For unsupported OnDemandFeatureView modes """ - if feature_view.mode == "python" and isinstance( - feature_view.feature_transformation, PythonTransformation - ): - input_dict = ( - df.to_dict(orient="records")[0] - if feature_view.singleton - else df.to_dict(orient="list") - ) + _should_track = False + try: + from feast.metrics import _config as _metrics_config - if feature_view.singleton: - transformed_rows = [] + _should_track = _metrics_config.online_features and getattr( + feature_view, "track_metrics", False + ) + except Exception: + pass - for i, row in df.iterrows(): - output = feature_view.feature_transformation.udf(row.to_dict()) - if i == 0: - transformed_rows = output - else: - for k in output: - if isinstance(output[k], list): - transformed_rows[k].extend(output[k]) - else: - transformed_rows[k].append(output[k]) + if _should_track: + import time as _time - transformed_data = pd.DataFrame(transformed_rows) - else: - transformed_data = feature_view.feature_transformation.udf(input_dict) + _t0 = _time.monotonic() - if feature_view.write_to_online_store: - entities = [ - self.get_entity(entity) for entity in (feature_view.entities or []) - ] - join_keys = [entity.join_key for entity in entities if entity] - join_keys = [k for k in join_keys if k in input_dict.keys()] - transformed_df = ( - pd.DataFrame(transformed_data) - if not isinstance(transformed_data, pd.DataFrame) - else transformed_data - ) - input_df = pd.DataFrame( - [input_dict] if feature_view.singleton else input_dict + try: + if feature_view.mode == "python" and isinstance( + feature_view.feature_transformation, PythonTransformation + ): + input_dict = ( + df.to_dict(orient="records")[0] + if feature_view.singleton + else df.to_dict(orient="list") ) - if input_df.shape[0] == transformed_df.shape[0]: + + if feature_view.singleton: + transformed_rows = [] + + for i, row in df.iterrows(): + output = feature_view.feature_transformation.udf(row.to_dict()) + if i == 0: + transformed_rows = output + else: + for k in output: + if isinstance(output[k], list): + transformed_rows[k].extend(output[k]) + else: + transformed_rows[k].append(output[k]) + + transformed_data = pd.DataFrame(transformed_rows) + else: + transformed_data = feature_view.feature_transformation.udf( + input_dict + ) + + if feature_view.write_to_online_store: + entities = [ + self.get_entity(entity) + for entity in (feature_view.entities or []) + ] + join_keys = [entity.join_key for entity in entities if entity] + join_keys = [k for k in join_keys if k in input_dict.keys()] + transformed_df = ( + pd.DataFrame(transformed_data) + if not isinstance(transformed_data, pd.DataFrame) + else transformed_data + ) + input_df = pd.DataFrame( + [input_dict] if feature_view.singleton else input_dict + ) + if input_df.shape[0] == transformed_df.shape[0]: + for k in input_dict: + if k not in transformed_data: + transformed_data[k] = input_dict[k] + transformed_df = pd.DataFrame(transformed_data) + else: + transformed_df = pd.merge( + transformed_df, + input_df, + how="left", + on=join_keys, + ) + else: + # overwrite any transformed features and update the dictionary for k in input_dict: if k not in transformed_data: transformed_data[k] = input_dict[k] - transformed_df = pd.DataFrame(transformed_data) - else: - transformed_df = pd.merge( - transformed_df, - input_df, - how="left", - on=join_keys, - ) - else: - # overwrite any transformed features and update the dictionary - for k in input_dict: - if k not in transformed_data: - transformed_data[k] = input_dict[k] - return pd.DataFrame(transformed_data) + return pd.DataFrame(transformed_data) - elif feature_view.mode == "pandas" and isinstance( - feature_view.feature_transformation, PandasTransformation - ): - transformed_df = feature_view.feature_transformation.udf(df) - for col in df.columns: - transformed_df[col] = df[col] - return transformed_df - else: - raise Exception("Unsupported OnDemandFeatureView mode") + elif feature_view.mode == "pandas" and isinstance( + feature_view.feature_transformation, PandasTransformation + ): + transformed_df = feature_view.feature_transformation.udf(df) + for col in df.columns: + transformed_df[col] = df[col] + return transformed_df + else: + raise Exception("Unsupported OnDemandFeatureView mode") + finally: + if _should_track: + from feast.metrics import track_write_transformation + + track_write_transformation( + feature_view.name, + feature_view.mode, + _time.monotonic() - _t0, + ) def _validate_vector_features(self, feature_view, df: pd.DataFrame) -> None: """ @@ -2363,6 +2539,8 @@ def write_to_offline_store( provider = self._get_provider() # Get columns of the batch source and the input dataframe. + if feature_view.batch_source is None: + raise ValueError(f"Feature view '{feature_view.name}' has no batch_source.") column_names_and_types = ( provider.get_table_column_names_and_types_from_data_source( self.config, feature_view.batch_source @@ -2398,6 +2576,7 @@ def get_online_features( Mapping[str, Union[Sequence[Any], Sequence[Value], RepeatedValue]], ], full_feature_names: bool = False, + include_feature_view_version_metadata: bool = False, ) -> OnlineResponse: """ Retrieves the latest online feature data. @@ -2449,6 +2628,7 @@ def get_online_features( registry=self.registry, project=self.project, full_feature_names=full_feature_names, + include_feature_view_version_metadata=include_feature_view_version_metadata, ) return response @@ -2461,6 +2641,7 @@ async def get_online_features_async( Mapping[str, Union[Sequence[Any], Sequence[Value], RepeatedValue]], ], full_feature_names: bool = False, + include_feature_view_version_metadata: bool = False, ) -> OnlineResponse: """ [Alpha] Retrieves the latest online feature data asynchronously. @@ -2497,6 +2678,7 @@ async def get_online_features_async( registry=self.registry, project=self.project, full_feature_names=full_feature_names, + include_feature_view_version_metadata=include_feature_view_version_metadata, ) def retrieve_online_documents( @@ -2532,13 +2714,15 @@ def retrieve_online_documents( ) feature_view_set = set() for _feature in features: - feature_view_name = _feature.split(":")[0] - feature_view = self.get_feature_view(feature_view_name) + fv_name, _, _ = utils._parse_feature_ref(_feature) + feature_view = self.get_feature_view(fv_name) feature_view_set.add(feature_view.name) if len(feature_view_set) > 1: raise ValueError("Document retrieval only supports a single feature view.") requested_features = [ - f.split(":")[1] for f in features if isinstance(f, str) and ":" in f + utils._parse_feature_ref(f)[2] + for f in features + if isinstance(f, str) and ":" in f ] requested_feature_view_name = list(feature_view_set)[0] for feature_view in available_feature_views: @@ -2597,7 +2781,10 @@ def _doc_feature(x): online_features_response=online_features_response, data=requested_features_data, ) - return OnlineResponse(online_features_response) + feature_types = { + f.name: f.dtype.to_value_type() for f in requested_feature_view.features + } + return OnlineResponse(online_features_response, feature_types=feature_types) def retrieve_online_documents_v2( self, @@ -2612,6 +2799,7 @@ def retrieve_online_documents_v2( text_weight: float = 0.5, image_weight: float = 0.5, combine_strategy: str = "weighted_sum", + include_feature_view_version_metadata: bool = False, ) -> OnlineResponse: """ Retrieves the top k closest document features. Note, embeddings are a subset of features. @@ -2733,18 +2921,20 @@ def retrieve_online_documents_v2( ) feature_view_set = set() for feature in features: - feature_view_name = feature.split(":")[0] - if feature_view_name in [fv.name for fv in available_odfv_views]: + fv_name, _, _ = utils._parse_feature_ref(feature) + if fv_name in [fv.name for fv in available_odfv_views]: feature_view: Union[OnDemandFeatureView, FeatureView] = ( - self.get_on_demand_feature_view(feature_view_name) + self.get_on_demand_feature_view(fv_name) ) else: - feature_view = self.get_feature_view(feature_view_name) + feature_view = self.get_feature_view(fv_name) feature_view_set.add(feature_view.name) if len(feature_view_set) > 1: raise ValueError("Document retrieval only supports a single feature view.") requested_features = [ - f.split(":")[1] for f in features if isinstance(f, str) and ":" in f + utils._parse_feature_ref(f)[2] + for f in features + if isinstance(f, str) and ":" in f ] if len(available_feature_views) == 0: available_feature_views.extend(available_odfv_views) # type: ignore[arg-type] @@ -2764,6 +2954,7 @@ def retrieve_online_documents_v2( top_k, distance_metric, query_string, + include_feature_view_version_metadata, ) def _retrieve_from_online_store( @@ -2828,6 +3019,7 @@ def _retrieve_from_online_store_v2( top_k: int, distance_metric: Optional[str], query_string: Optional[str], + include_feature_view_version_metadata: bool = False, ) -> OnlineResponse: """ Search and return document features from the online document store. @@ -2844,6 +3036,7 @@ def _retrieve_from_online_store_v2( top_k=top_k, distance_metric=distance_metric, query_string=query_string, + include_feature_view_version_metadata=include_feature_view_version_metadata, ) entity_key_dict: Dict[str, List[ValueProto]] = {} @@ -2881,26 +3074,23 @@ def _retrieve_from_online_store_v2( online_features_response.metadata.feature_names.val.extend( features_to_request ) - return OnlineResponse(online_features_response) + feature_types = {f.name: f.dtype.to_value_type() for f in table.features} + return OnlineResponse(online_features_response, feature_types=feature_types) table_entity_values, idxs, output_len = utils._get_unique_entities_from_values( entity_key_dict, ) - feature_data = utils._convert_rows_to_protobuf( - requested_features=features_to_request, - read_rows=list(zip(datevals, list_of_feature_dicts)), - ) - online_features_response = GetOnlineFeaturesResponse(results=[]) utils._populate_response_from_feature_data( - feature_data=feature_data, + requested_features=features_to_request, + read_rows=list(zip(datevals, list_of_feature_dicts)), indexes=idxs, online_features_response=online_features_response, full_feature_names=False, - requested_features=features_to_request, table=table, output_len=output_len, + include_feature_view_version_metadata=include_feature_view_version_metadata, ) utils._populate_result_rows_from_columnar( @@ -2908,7 +3098,8 @@ def _retrieve_from_online_store_v2( data=entity_key_dict, ) - return OnlineResponse(online_features_response) + feature_types = {f.name: f.dtype.to_value_type() for f in table.features} + return OnlineResponse(online_features_response, feature_types=feature_types) def serve( self, @@ -3255,18 +3446,25 @@ def _print_materialization_log( def _validate_feature_views(feature_views: List[BaseFeatureView]): - """Verify feature views have case-insensitively unique names""" - fv_names = set() + """Verify feature views have case-insensitively unique names across all types. + + This validates that no two feature views (of any type: FeatureView, + StreamFeatureView, OnDemandFeatureView) share the same case-insensitive name. + This is critical because get_online_features uses get_any_feature_view which + resolves names in a fixed order, potentially returning the wrong feature view. + """ + fv_by_name: Dict[str, BaseFeatureView] = {} for fv in feature_views: case_insensitive_fv_name = fv.name.lower() - if case_insensitive_fv_name in fv_names: - raise ValueError( - f"More than one feature view with name {case_insensitive_fv_name} found. " - f"Please ensure that all feature view names are case-insensitively unique. " - f"It may be necessary to ignore certain files in your feature repository by using a .feastignore file." + if case_insensitive_fv_name in fv_by_name: + existing_fv = fv_by_name[case_insensitive_fv_name] + raise ConflictingFeatureViewNames( + fv.name, + existing_type=type(existing_fv).__name__, + new_type=type(fv).__name__, ) else: - fv_names.add(case_insensitive_fv_name) + fv_by_name[case_insensitive_fv_name] = fv def _validate_data_sources(data_sources: List[DataSource]): diff --git a/sdk/python/feast/feature_view.py b/sdk/python/feast/feature_view.py index a9406657a51..3863634ac80 100644 --- a/sdk/python/feast/feature_view.py +++ b/sdk/python/feast/feature_view.py @@ -26,6 +26,11 @@ from feast.entity import Entity from feast.feature_view_projection import FeatureViewProjection from feast.field import Field +from feast.proto_utils import ( + mode_to_string, + serialize_data_source, + transformation_to_proto, +) from feast.protos.feast.core.FeatureView_pb2 import FeatureView as FeatureViewProto from feast.protos.feast.core.FeatureView_pb2 import ( FeatureViewMeta as FeatureViewMetaProto, @@ -36,12 +41,10 @@ from feast.protos.feast.core.FeatureView_pb2 import ( MaterializationInterval as MaterializationIntervalProto, ) -from feast.protos.feast.core.Transformation_pb2 import ( - FeatureTransformationV2 as FeatureTransformationProto, -) from feast.transformation.mode import TransformationMode from feast.types import from_value_type from feast.value_type import ValueType +from feast.version_utils import normalize_version_string warnings.simplefilter("once", DeprecationWarning) @@ -71,9 +74,8 @@ class FeatureView(BaseFeatureView): ttl: The amount of time this group of features lives. A ttl of 0 indicates that this group of features lives forever. Note that large ttl's or a ttl of 0 can result in extremely computationally intensive queries. - batch_source: The batch source of data where this group of features - is stored. This is optional ONLY if a push source is specified as the - stream_source, since push sources contain their own batch sources. + batch_source: Optional batch source of data where this group of features + is stored. If no source is provided, this will be None. stream_source: The stream source of data where this group of features is stored. schema: The schema of the feature view, including feature, timestamp, and entity columns. If not specified, can be inferred from the underlying data source. @@ -95,7 +97,7 @@ class FeatureView(BaseFeatureView): name: str entities: List[str] ttl: Optional[timedelta] - batch_source: DataSource + batch_source: Optional[DataSource] stream_source: Optional[DataSource] source_views: Optional[List["FeatureView"]] entity_columns: List[Field] @@ -107,12 +109,13 @@ class FeatureView(BaseFeatureView): owner: str materialization_intervals: List[Tuple[datetime, datetime]] mode: Optional[Union["TransformationMode", str]] + enable_validation: bool def __init__( self, *, name: str, - source: Union[DataSource, "FeatureView", List["FeatureView"]], + source: Optional[Union[DataSource, "FeatureView", List["FeatureView"]]] = None, sink_source: Optional[DataSource] = None, schema: Optional[List[Field]] = None, entities: Optional[List[Entity]] = None, @@ -123,14 +126,17 @@ def __init__( tags: Optional[Dict[str, str]] = None, owner: str = "", mode: Optional[Union["TransformationMode", str]] = None, + enable_validation: bool = False, + version: str = "latest", ): """ Creates a FeatureView object. Args: name: The unique name of the feature view. - source: The source of data for this group of features. May be a stream source, or a batch source. - If a stream source, the source should contain a batch_source for backfills & batch materialization. + source (optional): The source of data for this group of features. May be a stream source, + a batch source, a FeatureView, or a list of FeatureViews. If None, the feature view + has no associated data source. schema (optional): The schema of the feature view, including feature, timestamp, and entity columns. # TODO: clarify that schema is only useful here... @@ -148,11 +154,19 @@ def __init__( primary maintainer. mode (optional): The transformation mode for feature transformations. Only meaningful when transformations are applied. Choose from TransformationMode enum values. + enable_validation (optional): If True, enables schema validation during materialization + to check that data conforms to the declared feature types. Default is False. + version (optional): Version string for definition management. Controls which historical + snapshot is active after ``feast apply``. Only one version can be active per feature + view name per project. For concurrent multi-version testing, use separate projects + or distinct feature view names. Default is "latest". Raises: ValueError: A field mapping conflicts with an Entity or a Feature. """ self.name = name + self.version = version + self.enable_validation = enable_validation self.entities = [e.name for e in entities] if entities else [DUMMY_ENTITY_NAME] self.ttl = ttl schema = schema or [] @@ -163,7 +177,9 @@ def __init__( self.data_source: Optional[DataSource] = None self.source_views: List[FeatureView] = [] - if isinstance(source, DataSource): + if source is None: + pass # data_source remains None, source_views remains [] + elif isinstance(source, DataSource): self.data_source = source elif isinstance(source, FeatureView): self.source_views = [source] @@ -192,11 +208,14 @@ def __init__( elif self.data_source: # Batch source definition self.batch_source = self.data_source - else: + elif self.source_views: # Derived view source definition if not sink_source: raise ValueError("Derived FeatureView must specify `sink_source`.") self.batch_source = sink_source + else: + # source=None - no batch source + self.batch_source = None # Initialize features and entity columns. features: List[Field] = [] @@ -279,6 +298,10 @@ def __copy__(self): online=self.online, offline=self.offline, sink_source=self.batch_source if self.source_views else None, + enable_validation=self.enable_validation, + version=self.version, + description=self.description, + owner=self.owner, ) # This is deliberately set outside of the FV initialization as we do not have the Entity objects. @@ -288,6 +311,28 @@ def __copy__(self): fv.projection = copy.copy(self.projection) return fv + def _schema_or_udf_changed(self, other: "BaseFeatureView") -> bool: + """Check for FeatureView schema/UDF changes.""" + if super()._schema_or_udf_changed(other): + return True + + if not isinstance(other, FeatureView): + return True + + # Schema-related fields + if sorted(self.entities) != sorted(other.entities): + return True + if sorted(self.entity_columns) != sorted(other.entity_columns): + return True + if self.source_views != other.source_views: + return True + + # Skip UDF-related data source fields: batch_source, stream_source + # (treat as deployment configuration, not schema changes) + # Skip configuration: ttl, online, offline, enable_validation + # Skip metadata: materialization_intervals (excluded in current equality) + return False + def __eq__(self, other): if not isinstance(other, FeatureView): raise TypeError( @@ -307,6 +352,9 @@ def __eq__(self, other): or sorted(self.entity_columns) != sorted(other.entity_columns) or self.source_views != other.source_views or self.materialization_intervals != other.materialization_intervals + or self.enable_validation != other.enable_validation + or normalize_version_string(self.version) + != normalize_version_string(other.version) ): return False @@ -414,15 +462,9 @@ def to_proto_spec( ) -> FeatureViewSpecProto: ttl_duration = self.get_ttl_duration() - batch_source_proto = None - if self.batch_source: - batch_source_proto = self.batch_source.to_proto() - batch_source_proto.data_source_class_type = f"{self.batch_source.__class__.__module__}.{self.batch_source.__class__.__name__}" + batch_source_proto = serialize_data_source(self.batch_source) + stream_source_proto = serialize_data_source(self.stream_source) - stream_source_proto = None - if self.stream_source: - stream_source_proto = self.stream_source.to_proto() - stream_source_proto.data_source_class_type = f"{self.stream_source.__class__.__module__}.{self.stream_source.__class__.__name__}" source_view_protos = None if self.source_views: source_view_protos = [ @@ -431,30 +473,8 @@ def to_proto_spec( feature_transformation_proto = None if hasattr(self, "feature_transformation") and self.feature_transformation: - from feast.protos.feast.core.Transformation_pb2 import ( - SubstraitTransformationV2 as SubstraitTransformationProto, - ) - from feast.protos.feast.core.Transformation_pb2 import ( - UserDefinedFunctionV2 as UserDefinedFunctionProto, - ) - - transformation_proto = self.feature_transformation.to_proto() - - if isinstance(transformation_proto, UserDefinedFunctionProto): - feature_transformation_proto = FeatureTransformationProto( - user_defined_function=transformation_proto, - ) - elif isinstance(transformation_proto, SubstraitTransformationProto): - feature_transformation_proto = FeatureTransformationProto( - substrait_transformation=transformation_proto, - ) - - mode_str = "" - if self.mode: - mode_str = ( - self.mode.value - if isinstance(self.mode, TransformationMode) - else self.mode + feature_transformation_proto = transformation_to_proto( + self.feature_transformation ) return FeatureViewSpecProto( @@ -472,7 +492,9 @@ def to_proto_spec( stream_source=stream_source_proto, source_views=source_view_protos, feature_transformation=feature_transformation_proto, - mode=mode_str, + mode=mode_to_string(self.mode), + enable_validation=self.enable_validation, + version=self.version, ) def to_proto_meta(self): @@ -486,6 +508,8 @@ def to_proto_meta(self): interval_proto.start_time.FromDatetime(interval[0]) interval_proto.end_time.FromDatetime(interval[1]) meta.materialization_intervals.append(interval_proto) + if self.current_version_number is not None: + meta.current_version_number = self.current_version_number return meta def get_ttl_duration(self): @@ -642,6 +666,20 @@ def _from_proto_internal( f"Entities: {feature_view.entities} vs Entity Columns: {feature_view.entity_columns}" ) + # Restore enable_validation from proto field. + feature_view.enable_validation = feature_view_proto.spec.enable_validation + + # Restore version fields. + spec_version = feature_view_proto.spec.version + feature_view.version = spec_version or "latest" + cvn = feature_view_proto.meta.current_version_number + if cvn > 0: + feature_view.current_version_number = cvn + elif cvn == 0 and spec_version and spec_version.lower() != "latest": + feature_view.current_version_number = 0 + else: + feature_view.current_version_number = None + # FeatureViewProjections are not saved in the FeatureView proto. # Create the default projection. feature_view.projection = FeatureViewProjection.from_feature_view_definition( diff --git a/sdk/python/feast/feature_view_projection.py b/sdk/python/feast/feature_view_projection.py index 70415e9ed3a..a19afda458e 100644 --- a/sdk/python/feast/feature_view_projection.py +++ b/sdk/python/feast/feature_view_projection.py @@ -47,9 +47,13 @@ class FeatureViewProjection: date_partition_column: Optional[str] = None created_timestamp_column: Optional[str] = None batch_source: Optional[DataSource] = None + version_tag: Optional[int] = None def name_to_use(self): - return self.name_alias or self.name + base = self.name_alias or self.name + if self.version_tag is not None: + return f"{base}@v{self.version_tag}" + return base def to_proto(self) -> FeatureViewProjectionProto: batch_source = None @@ -70,6 +74,9 @@ def to_proto(self) -> FeatureViewProjectionProto: for feature in self.features: feature_reference_proto.feature_columns.append(feature.to_proto()) + if self.version_tag is not None: + feature_reference_proto.version_tag = self.version_tag + return feature_reference_proto @staticmethod @@ -93,24 +100,25 @@ def from_proto(proto: FeatureViewProjectionProto) -> "FeatureViewProjection": for feature_column in proto.feature_columns: feature_view_projection.features.append(Field.from_proto(feature_column)) + if proto.HasField("version_tag"): + feature_view_projection.version_tag = proto.version_tag + return feature_view_projection @staticmethod def from_feature_view_definition(feature_view: "FeatureView"): # TODO need to implement this for StreamFeatureViews - if getattr(feature_view, "batch_source", None): + batch_source = getattr(feature_view, "batch_source", None) + if batch_source: return FeatureViewProjection( name=feature_view.name, name_alias=None, features=feature_view.features, desired_features=[], - timestamp_field=feature_view.batch_source.created_timestamp_column - or None, - created_timestamp_column=feature_view.batch_source.created_timestamp_column - or None, - date_partition_column=feature_view.batch_source.date_partition_column - or None, - batch_source=feature_view.batch_source or None, + timestamp_field=batch_source.created_timestamp_column or None, + created_timestamp_column=batch_source.created_timestamp_column or None, + date_partition_column=batch_source.date_partition_column or None, + batch_source=batch_source or None, ) else: return FeatureViewProjection( diff --git a/sdk/python/feast/feature_view_utils.py b/sdk/python/feast/feature_view_utils.py index 704a5a3d7b9..0b599f4777c 100644 --- a/sdk/python/feast/feature_view_utils.py +++ b/sdk/python/feast/feature_view_utils.py @@ -136,6 +136,8 @@ def resolve_feature_view_source( if not is_derived_view: # Regular feature view - use its batch_source directly + if feature_view.batch_source is None: + raise ValueError(f"Feature view '{feature_view.name}' has no batch_source.") return FeatureViewSourceInfo( data_source=feature_view.batch_source, source_type="batch_source", @@ -178,8 +180,13 @@ def resolve_feature_view_source( if hasattr(parent_view, "source_views") and parent_view.source_views: # Parent is also a derived view - recursively find original source original_source_view = find_original_source_view(parent_view) + original_batch_source = original_source_view.batch_source + if original_batch_source is None: + raise ValueError( + f"Original source view '{original_source_view.name}' has no batch_source." + ) return FeatureViewSourceInfo( - data_source=original_source_view.batch_source, + data_source=original_batch_source, source_type="original_source", has_transformation=view_has_transformation, transformation_func=transformation_func, @@ -229,8 +236,13 @@ def resolve_feature_view_source_with_fallback( elif hasattr(feature_view, "source_views") and feature_view.source_views: # Try the original source view as last resort original_view = find_original_source_view(feature_view) + original_view_batch_source = original_view.batch_source + if original_view_batch_source is None: + raise ValueError( + f"Original source view '{original_view.name}' has no batch_source." + ) return FeatureViewSourceInfo( - data_source=original_view.batch_source, + data_source=original_view_batch_source, source_type="fallback_original_source", has_transformation=has_transformation(feature_view), transformation_func=get_transformation_function(feature_view), diff --git a/sdk/python/feast/field.py b/sdk/python/feast/field.py index 27552878afc..e155836467b 100644 --- a/sdk/python/feast/field.py +++ b/sdk/python/feast/field.py @@ -12,15 +12,19 @@ # See the License for the specific language governing permissions and # limitations under the License. +import json from typing import Dict, Optional from typeguard import typechecked from feast.feature import Feature from feast.protos.feast.core.Feature_pb2 import FeatureSpecV2 as FieldProto -from feast.types import FeastType, from_value_type +from feast.types import FeastType, Struct, from_value_type from feast.value_type import ValueType +STRUCT_SCHEMA_TAG = "feast:struct_schema" +NESTED_COLLECTION_INNER_TYPE_TAG = "feast:nested_inner_type" + @typechecked class Field: @@ -115,13 +119,26 @@ def __str__(self): def to_proto(self) -> FieldProto: """Converts a Field object to its protobuf representation.""" + from feast.types import Array, Set + value_type = self.dtype.to_value_type() vector_search_metric = self.vector_search_metric or "" + tags = dict(self.tags) + # Persist Struct field schema in tags + if isinstance(self.dtype, Struct): + tags[STRUCT_SCHEMA_TAG] = _serialize_struct_schema(self.dtype) + elif isinstance(self.dtype, Array) and isinstance(self.dtype.base_type, Struct): + tags[STRUCT_SCHEMA_TAG] = _serialize_struct_schema(self.dtype.base_type) + # Persist nested collection type info in tags + if isinstance(self.dtype, (Array, Set)) and isinstance( + self.dtype.base_type, (Array, Set) + ): + tags[NESTED_COLLECTION_INNER_TYPE_TAG] = _feast_type_to_str(self.dtype) return FieldProto( name=self.name, value_type=value_type.value, description=self.description, - tags=self.tags, + tags=tags, vector_index=self.vector_index, vector_length=self.vector_length, vector_search_metric=vector_search_metric, @@ -136,13 +153,37 @@ def from_proto(cls, field_proto: FieldProto): field_proto: FieldProto protobuf object """ value_type = ValueType(field_proto.value_type) + tags = dict(field_proto.tags) vector_search_metric = getattr(field_proto, "vector_search_metric", "") vector_index = getattr(field_proto, "vector_index", False) vector_length = getattr(field_proto, "vector_length", 0) + + # Reconstruct Struct type from persisted schema in tags + from feast.types import Array + + internal_tags = {STRUCT_SCHEMA_TAG, NESTED_COLLECTION_INNER_TYPE_TAG} + dtype: FeastType + if value_type == ValueType.STRUCT and STRUCT_SCHEMA_TAG in tags: + dtype = _deserialize_struct_schema(tags[STRUCT_SCHEMA_TAG]) + user_tags = {k: v for k, v in tags.items() if k not in internal_tags} + elif value_type == ValueType.STRUCT_LIST and STRUCT_SCHEMA_TAG in tags: + inner_struct = _deserialize_struct_schema(tags[STRUCT_SCHEMA_TAG]) + dtype = Array(inner_struct) + user_tags = {k: v for k, v in tags.items() if k not in internal_tags} + elif ( + value_type in (ValueType.VALUE_LIST, ValueType.VALUE_SET) + and NESTED_COLLECTION_INNER_TYPE_TAG in tags + ): + dtype = _str_to_feast_type(tags[NESTED_COLLECTION_INNER_TYPE_TAG]) + user_tags = {k: v for k, v in tags.items() if k not in internal_tags} + else: + dtype = from_value_type(value_type=value_type) + user_tags = {k: v for k, v in tags.items() if k not in internal_tags} + return cls( name=field_proto.name, - dtype=from_value_type(value_type=value_type), - tags=dict(field_proto.tags), + dtype=dtype, + tags=user_tags, description=field_proto.description, vector_index=vector_index, vector_length=vector_length, @@ -163,3 +204,86 @@ def from_feature(cls, feature: Feature): description=feature.description, tags=feature.labels, ) + + +def _feast_type_to_str(feast_type: FeastType) -> str: + """Convert a FeastType to a string representation for serialization.""" + from feast.types import ( + Array, + PrimitiveFeastType, + Set, + ) + + if isinstance(feast_type, PrimitiveFeastType): + return feast_type.name + elif isinstance(feast_type, Struct): + nested = { + name: _feast_type_to_str(ft) for name, ft in feast_type.fields.items() + } + return json.dumps({"__struct__": nested}) + elif isinstance(feast_type, Array): + return f"Array({_feast_type_to_str(feast_type.base_type)})" + elif isinstance(feast_type, Set): + return f"Set({_feast_type_to_str(feast_type.base_type)})" + else: + return str(feast_type) + + +def _str_to_feast_type(type_str: str) -> FeastType: + """Convert a string representation back to a FeastType.""" + from feast.types import ( + Array, + PrimitiveFeastType, + Set, + ) + + # Check if it's an Array type + if type_str.startswith("Array(") and type_str.endswith(")"): + inner = type_str[6:-1] + base_type = _str_to_feast_type(inner) + return Array(base_type) + + # Check if it's a Set type + if type_str.startswith("Set(") and type_str.endswith(")"): + inner = type_str[4:-1] + base_type = _str_to_feast_type(inner) + return Set(base_type) + + # Check if it's a nested Struct (JSON encoded) + if type_str.startswith("{"): + try: + parsed = json.loads(type_str) + if "__struct__" in parsed: + fields = { + name: _str_to_feast_type(ft_str) + for name, ft_str in parsed["__struct__"].items() + } + return Struct(fields) + except (json.JSONDecodeError, TypeError): + pass + + # Must be a PrimitiveFeastType name + try: + return PrimitiveFeastType[type_str] + except KeyError: + raise ValueError( + f"Unknown FeastType: {type_str!r}. " + f"Valid primitive types: {[t.name for t in PrimitiveFeastType]}" + ) + + +def _serialize_struct_schema(struct_type: Struct) -> str: + """Serialize a Struct's field schema to a JSON string for tag storage.""" + schema_dict = {} + for name, feast_type in struct_type.fields.items(): + schema_dict[name] = _feast_type_to_str(feast_type) + return json.dumps(schema_dict) + + +def _deserialize_struct_schema(schema_str: str) -> Struct: + """Deserialize a JSON string from tags back to a Struct type.""" + schema_dict = json.loads(schema_str) + fields = {} + for name, type_str in schema_dict.items(): + fields[name] = _str_to_feast_type(type_str) + return Struct(fields) diff --git a/sdk/python/feast/inference.py b/sdk/python/feast/inference.py index f5f234b7301..16023e3dac6 100644 --- a/sdk/python/feast/inference.py +++ b/sdk/python/feast/inference.py @@ -221,6 +221,9 @@ def _infer_features_and_entities( fv, join_keys, run_inference_for_features, config ) + if fv.batch_source is None: + return + entity_columns: List[Field] = fv.entity_columns if fv.entity_columns else [] columns_to_exclude = { fv.batch_source.timestamp_field, diff --git a/sdk/python/feast/infra/compute_engines/aws_lambda/lambda_engine.py b/sdk/python/feast/infra/compute_engines/aws_lambda/lambda_engine.py index 9e2d217875b..b223328893d 100644 --- a/sdk/python/feast/infra/compute_engines/aws_lambda/lambda_engine.py +++ b/sdk/python/feast/infra/compute_engines/aws_lambda/lambda_engine.py @@ -193,7 +193,7 @@ def _materialize_one( offline_job = self.offline_store.pull_latest_from_table_or_query( config=self.repo_config, - data_source=feature_view.batch_source, + data_source=feature_view.batch_source, # type: ignore[arg-type] join_key_columns=join_key_columns, feature_name_columns=feature_name_columns, timestamp_field=timestamp_field, diff --git a/sdk/python/feast/infra/compute_engines/backends/factory.py b/sdk/python/feast/infra/compute_engines/backends/factory.py index ffe969f3003..91ece19b329 100644 --- a/sdk/python/feast/infra/compute_engines/backends/factory.py +++ b/sdk/python/feast/infra/compute_engines/backends/factory.py @@ -24,9 +24,10 @@ def from_name(name: str) -> DataFrameBackend: @staticmethod def infer_from_entity_df(entity_df) -> Optional[DataFrameBackend]: if ( - not entity_df - or isinstance(entity_df, pyarrow.Table) + entity_df is None or isinstance(entity_df, pd.DataFrame) + or isinstance(entity_df, pyarrow.Table) + or (isinstance(entity_df, str) and not entity_df) ): return PandasBackend() diff --git a/sdk/python/feast/infra/compute_engines/backends/polars_backend.py b/sdk/python/feast/infra/compute_engines/backends/polars_backend.py index 92e348c3652..118b0b8eab7 100644 --- a/sdk/python/feast/infra/compute_engines/backends/polars_backend.py +++ b/sdk/python/feast/infra/compute_engines/backends/polars_backend.py @@ -7,6 +7,8 @@ class PolarsBackend(DataFrameBackend): + _POLARS_FUNC_MAP = {"nunique": "n_unique"} + def columns(self, df: pl.DataFrame) -> list[str]: return df.columns @@ -21,7 +23,7 @@ def join(self, left: pl.DataFrame, right: pl.DataFrame, on, how) -> pl.DataFrame def groupby_agg(self, df: pl.DataFrame, group_keys, agg_ops) -> pl.DataFrame: agg_exprs = [ - getattr(pl.col(col), func)().alias(alias) + getattr(pl.col(col), self._POLARS_FUNC_MAP.get(func, func))().alias(alias) for alias, (func, col) in agg_ops.items() ] return df.groupby(group_keys).agg(agg_exprs) diff --git a/sdk/python/feast/infra/compute_engines/kubernetes/k8s_engine.py b/sdk/python/feast/infra/compute_engines/kubernetes/k8s_engine.py index 0dcff09f027..2f041301be7 100644 --- a/sdk/python/feast/infra/compute_engines/kubernetes/k8s_engine.py +++ b/sdk/python/feast/infra/compute_engines/kubernetes/k8s_engine.py @@ -145,7 +145,7 @@ def _materialize_one( offline_job = self.offline_store.pull_latest_from_table_or_query( config=self.repo_config, - data_source=feature_view.batch_source, + data_source=feature_view.batch_source, # type: ignore[arg-type] join_key_columns=join_key_columns, feature_name_columns=feature_name_columns, timestamp_field=timestamp_field, diff --git a/sdk/python/feast/infra/compute_engines/local/feature_builder.py b/sdk/python/feast/infra/compute_engines/local/feature_builder.py index 3463c0e074b..754a00db76f 100644 --- a/sdk/python/feast/infra/compute_engines/local/feature_builder.py +++ b/sdk/python/feast/infra/compute_engines/local/feature_builder.py @@ -1,3 +1,4 @@ +import logging from typing import Union from feast.aggregation import aggregation_specs_to_agg_ops @@ -16,6 +17,9 @@ LocalValidationNode, ) from feast.infra.registry.base_registry import BaseRegistry +from feast.types import PrimitiveFeastType, from_feast_to_pyarrow_type + +logger = logging.getLogger(__name__) class LocalFeatureBuilder(FeatureBuilder): @@ -88,7 +92,36 @@ def build_transformation_node(self, view, input_nodes): return node def build_validation_node(self, view, input_node): - validation_config = view.validation_config + validation_config = getattr(view, "validation_config", None) or {} + + if not validation_config.get("columns") and hasattr(view, "features"): + columns = {} + json_columns = set() + for feature in view.features: + try: + columns[feature.name] = from_feast_to_pyarrow_type(feature.dtype) + except (ValueError, KeyError): + logger.debug( + "Could not resolve PyArrow type for feature '%s' " + "(dtype=%s), skipping type check for this column.", + feature.name, + feature.dtype, + ) + columns[feature.name] = None + # Track which columns are Json type for content validation + if ( + isinstance(feature.dtype, PrimitiveFeastType) + and feature.dtype.name == "JSON" + ): + json_columns.add(feature.name) + if columns: + validation_config = {**validation_config, "columns": columns} + if json_columns: + validation_config = { + **validation_config, + "json_columns": json_columns, + } + node = LocalValidationNode( "validate", validation_config, self.backend, inputs=[input_node] ) diff --git a/sdk/python/feast/infra/compute_engines/local/nodes.py b/sdk/python/feast/infra/compute_engines/local/nodes.py index 985a089daae..db65761a5e2 100644 --- a/sdk/python/feast/infra/compute_engines/local/nodes.py +++ b/sdk/python/feast/infra/compute_engines/local/nodes.py @@ -1,5 +1,7 @@ +import json +import logging from datetime import datetime, timedelta -from typing import List, Optional, Union +from typing import List, Optional, Set, Union import pyarrow as pa @@ -19,6 +21,8 @@ ) from feast.utils import _convert_arrow_to_proto +logger = logging.getLogger(__name__) + ENTITY_TS_ALIAS = "__entity_event_timestamp" @@ -236,15 +240,114 @@ def __init__( def execute(self, context: ExecutionContext) -> ArrowTableValue: input_table = self.get_single_table(context).data - df = self.backend.from_arrow(input_table) - # Placeholder for actual validation logic + if self.validation_config: - print(f"[Validation: {self.name}] Passed.") - result = self.backend.to_arrow(df) - output = ArrowTableValue(result) + self._validate_schema(input_table) + + output = ArrowTableValue(input_table) context.node_outputs[self.name] = output return output + def _validate_schema(self, table: pa.Table): + """Validate that the input table conforms to the expected schema. + + Checks that all expected columns are present, that their types + are compatible with the declared Feast types, and that Json columns + contain well-formed JSON. Logs warnings for type mismatches but + raises on missing columns or invalid JSON content. + """ + expected_columns = self.validation_config.get("columns", {}) + if not expected_columns: + logger.debug( + "[Validation: %s] No column schema to validate against.", + self.name, + ) + return + + actual_columns = set(table.column_names) + expected_names = set(expected_columns.keys()) + + missing = expected_names - actual_columns + if missing: + raise ValueError( + f"[Validation: {self.name}] Missing expected columns: {missing}. " + f"Actual columns: {sorted(actual_columns)}" + ) + + for col_name, expected_type in expected_columns.items(): + actual_type = table.schema.field(col_name).type + if expected_type is not None and actual_type != expected_type: + # PyArrow map columns and struct columns are compatible + # with the Feast Map type — skip warning for these cases + if pa.types.is_map(expected_type) and ( + pa.types.is_map(actual_type) + or pa.types.is_struct(actual_type) + or pa.types.is_large_list(actual_type) + or pa.types.is_list(actual_type) + ): + continue + + # JSON type (large_string) is compatible with string types + if pa.types.is_large_string(expected_type) and ( + pa.types.is_string(actual_type) + or pa.types.is_large_string(actual_type) + ): + continue + + # Struct type — expected struct is compatible with actual + # struct or map representations + if pa.types.is_struct(expected_type) and ( + pa.types.is_struct(actual_type) + or pa.types.is_map(actual_type) + or pa.types.is_list(actual_type) + ): + continue + + logger.warning( + "[Validation: %s] Column '%s' type mismatch: expected %s, got %s", + self.name, + col_name, + expected_type, + actual_type, + ) + + # Validate JSON well-formedness for declared Json columns + json_columns: Set[str] = self.validation_config.get("json_columns", set()) + for col_name in json_columns: + if col_name not in actual_columns: + continue + + column = table.column(col_name) + invalid_count = 0 + first_error = None + first_error_row = None + + for i in range(len(column)): + value = column[i] + if not value.is_valid: + continue + + str_value = value.as_py() + if not isinstance(str_value, str): + continue + + try: + json.loads(str_value) + except (json.JSONDecodeError, TypeError) as e: + invalid_count += 1 + if first_error is None: + first_error = str(e) + first_error_row = i + + if invalid_count > 0: + raise ValueError( + f"[Validation: {self.name}] Column '{col_name}' declared as Json " + f"contains {invalid_count} invalid JSON value(s). " + f"First error at row {first_error_row}: {first_error}" + ) + + logger.debug("[Validation: %s] Schema validation passed.", self.name) + class LocalOutputNode(LocalNode): def __init__( diff --git a/sdk/python/feast/infra/compute_engines/ray/compute.py b/sdk/python/feast/infra/compute_engines/ray/compute.py index a5c1b3caab5..fa8f9747f3b 100644 --- a/sdk/python/feast/infra/compute_engines/ray/compute.py +++ b/sdk/python/feast/infra/compute_engines/ray/compute.py @@ -163,7 +163,7 @@ def _materialize_from_offline_store( # Pull data from offline store retrieval_job = self.offline_store.pull_latest_from_table_or_query( config=self.repo_config, - data_source=feature_view.batch_source, + data_source=feature_view.batch_source, # type: ignore[arg-type] join_key_columns=join_key_columns, feature_name_columns=feature_name_columns, timestamp_field=timestamp_field, diff --git a/sdk/python/feast/infra/compute_engines/ray/feature_builder.py b/sdk/python/feast/infra/compute_engines/ray/feature_builder.py index 274fe87599c..a9830162c1e 100644 --- a/sdk/python/feast/infra/compute_engines/ray/feature_builder.py +++ b/sdk/python/feast/infra/compute_engines/ray/feature_builder.py @@ -17,8 +17,10 @@ RayJoinNode, RayReadNode, RayTransformationNode, + RayValidationNode, RayWriteNode, ) +from feast.types import PrimitiveFeastType, from_feast_to_pyarrow_type if TYPE_CHECKING: from feast.infra.compute_engines.ray.config import RayComputeEngineConfig @@ -174,11 +176,36 @@ def build_output_nodes(self, view, final_node): def build_validation_node(self, view, input_node): """Build the validation node for feature validation.""" - # TODO: Implement validation logic - logger.warning( - "Feature validation is not yet implemented for Ray compute engine." + expected_columns = {} + json_columns: set = set() + if hasattr(view, "features"): + for feature in view.features: + try: + expected_columns[feature.name] = from_feast_to_pyarrow_type( + feature.dtype + ) + except (ValueError, KeyError): + logger.debug( + "Could not resolve PyArrow type for feature '%s' " + "(dtype=%s), skipping type check for this column.", + feature.name, + feature.dtype, + ) + expected_columns[feature.name] = None + if ( + isinstance(feature.dtype, PrimitiveFeastType) + and feature.dtype.name == "JSON" + ): + json_columns.add(feature.name) + + node = RayValidationNode( + f"{view.name}:validate", + expected_columns=expected_columns, + json_columns=json_columns, + inputs=[input_node], ) - return input_node + self.nodes.append(node) + return node def _build(self, view, input_nodes: Optional[List[DAGNode]]) -> DAGNode: has_physical_source = (hasattr(view, "batch_source") and view.batch_source) or ( diff --git a/sdk/python/feast/infra/compute_engines/ray/nodes.py b/sdk/python/feast/infra/compute_engines/ray/nodes.py index 89694a57e2d..5b16f3edd05 100644 --- a/sdk/python/feast/infra/compute_engines/ray/nodes.py +++ b/sdk/python/feast/infra/compute_engines/ray/nodes.py @@ -1,6 +1,7 @@ +import json import logging from datetime import datetime, timedelta, timezone -from typing import Dict, List, Optional, Union +from typing import Dict, List, Optional, Set, Union import dill import pandas as pd @@ -460,9 +461,7 @@ def _execute_standard_aggregation(self, dataset: Dataset) -> DAGValue: # Convert aggregations to Ray's groupby format agg_dict = {} for agg in self.aggregations: - feature_name = f"{agg.function}_{agg.column}" - if agg.time_window: - feature_name += f"_{int(agg.time_window.total_seconds())}s" + feature_name = agg.resolved_name(agg.time_window) if agg.function == "count": agg_dict[feature_name] = (agg.column, "count") @@ -478,6 +477,8 @@ def _execute_standard_aggregation(self, dataset: Dataset) -> DAGValue: agg_dict[feature_name] = (agg.column, "std") elif agg.function == "var": agg_dict[feature_name] = (agg.column, "var") + elif agg.function == "count_distinct": + agg_dict[feature_name] = (agg.column, "nunique") else: raise ValueError(f"Unknown aggregation function: {agg.function}.") @@ -532,6 +533,8 @@ def _fallback_pandas_aggregation(self, dataset: Dataset, agg_dict: dict) -> Data result = grouped[column].std() elif function == "var": result = grouped[column].var() + elif function == "nunique": + result = grouped[column].nunique() else: raise ValueError(f"Unknown aggregation function: {function}.") @@ -847,3 +850,127 @@ def write_batch_with_serialized_artifacts(batch: pd.DataFrame) -> pd.DataFrame: ), }, ) + + +class RayValidationNode(DAGNode): + """ + Ray node for validating feature data against the declared schema. + + Checks that all expected columns are present and logs warnings for + type mismatches. Validation runs once on the first batch to avoid + per-batch overhead; the full dataset is passed through unchanged. + """ + + def __init__( + self, + name: str, + expected_columns: Dict[str, Optional[pa.DataType]], + json_columns: Optional[Set[str]] = None, + inputs: Optional[List[DAGNode]] = None, + ): + super().__init__(name, inputs=inputs) + self.expected_columns = expected_columns + self.json_columns = json_columns or set() + + def execute(self, context: ExecutionContext) -> DAGValue: + input_value = self.get_single_input_value(context) + dataset = input_value.data + + if not self.expected_columns: + context.node_outputs[self.name] = input_value + return input_value + + expected_names = set(self.expected_columns.keys()) + + schema = dataset.schema() + actual_columns = set(schema.names) + + missing = expected_names - actual_columns + if missing: + raise ValueError( + f"[Validation: {self.name}] Missing expected columns: {missing}. " + f"Actual columns: {sorted(actual_columns)}" + ) + + for col_name, expected_type in self.expected_columns.items(): + if expected_type is None: + continue + actual_field = schema.field(col_name) + actual_type = actual_field.type + if actual_type != expected_type: + # Map type compatibility + if pa.types.is_map(expected_type) and ( + pa.types.is_map(actual_type) + or pa.types.is_struct(actual_type) + or pa.types.is_list(actual_type) + ): + continue + + # JSON type compatibility (large_string / string) + if pa.types.is_large_string(expected_type) and ( + pa.types.is_string(actual_type) + or pa.types.is_large_string(actual_type) + ): + continue + + # Struct type compatibility + if pa.types.is_struct(expected_type) and ( + pa.types.is_struct(actual_type) + or pa.types.is_map(actual_type) + or pa.types.is_list(actual_type) + ): + continue + + logger.warning( + "[Validation: %s] Column '%s' type mismatch: expected %s, got %s", + self.name, + col_name, + expected_type, + actual_type, + ) + + # Validate JSON well-formedness for declared Json columns + if self.json_columns: + try: + first_batch = dataset.take_batch(1000) + except Exception: + logger.debug( + "[Validation: %s] Could not sample batch for JSON validation.", + self.name, + ) + first_batch = None + + if first_batch is not None: + for col_name in self.json_columns: + if col_name not in first_batch: + continue + + values = first_batch[col_name] + invalid_count = 0 + first_error = None + first_error_row = None + + for i, value in enumerate(values): + if value is None: + continue + if not isinstance(value, str): + continue + try: + json.loads(value) + except (json.JSONDecodeError, TypeError) as e: + invalid_count += 1 + if first_error is None: + first_error = str(e) + first_error_row = i + + if invalid_count > 0: + raise ValueError( + f"[Validation: {self.name}] Column '{col_name}' declared " + f"as Json contains {invalid_count} invalid JSON value(s) " + f"in sampled batch. First error at row {first_error_row}: " + f"{first_error}" + ) + + logger.debug("[Validation: %s] Schema validation passed.", self.name) + context.node_outputs[self.name] = input_value + return input_value diff --git a/sdk/python/feast/infra/compute_engines/snowflake/snowflake_engine.py b/sdk/python/feast/infra/compute_engines/snowflake/snowflake_engine.py index 7441cb0f18c..d0a1152eb55 100644 --- a/sdk/python/feast/infra/compute_engines/snowflake/snowflake_engine.py +++ b/sdk/python/feast/infra/compute_engines/snowflake/snowflake_engine.py @@ -226,13 +226,14 @@ def _materialize_one( timestamp_field, created_timestamp_column, ) = _get_column_names(feature_view, entities) + assert feature_view.batch_source is not None # guaranteed by _get_column_names job_id = f"{feature_view.name}-{start_date}-{end_date}" try: offline_job = self.offline_store.pull_latest_from_table_or_query( config=self.repo_config, - data_source=feature_view.batch_source, + data_source=feature_view.batch_source, # type: ignore[arg-type] join_key_columns=join_key_columns, feature_name_columns=feature_name_columns, timestamp_field=timestamp_field, @@ -341,6 +342,7 @@ def generate_snowflake_materialization_query( feature_batch: list, project: str, ) -> str: + assert feature_view.batch_source is not None if feature_view.batch_source.created_timestamp_column: fv_created_str = f',"{feature_view.batch_source.created_timestamp_column}"' else: @@ -406,6 +408,7 @@ def materialize_to_snowflake_online_store( project: str, ) -> None: assert_snowflake_feature_names(feature_view) + assert feature_view.batch_source is not None feature_names_str = '", "'.join( [feature.name for feature in feature_view.features] @@ -467,6 +470,7 @@ def materialize_to_external_online_store( feature_view: Union[StreamFeatureView, FeatureView], pbar: tqdm, ) -> None: + assert feature_view.batch_source is not None feature_names = [feature.name for feature in feature_view.features] with GetSnowflakeConnection(repo_config.batch_engine) as conn: diff --git a/sdk/python/feast/infra/compute_engines/spark/compute.py b/sdk/python/feast/infra/compute_engines/spark/compute.py index e6ec58dd74d..b6c7dc30d55 100644 --- a/sdk/python/feast/infra/compute_engines/spark/compute.py +++ b/sdk/python/feast/infra/compute_engines/spark/compute.py @@ -162,7 +162,7 @@ def _materialize_from_offline_store( SparkRetrievalJob, self.offline_store.pull_latest_from_table_or_query( config=self.repo_config, - data_source=feature_view.batch_source, + data_source=feature_view.batch_source, # type: ignore[arg-type] join_key_columns=join_key_columns, feature_name_columns=feature_name_columns, timestamp_field=timestamp_field, diff --git a/sdk/python/feast/infra/compute_engines/spark/feature_builder.py b/sdk/python/feast/infra/compute_engines/spark/feature_builder.py index 11a3c1587f6..94f29220513 100644 --- a/sdk/python/feast/infra/compute_engines/spark/feature_builder.py +++ b/sdk/python/feast/infra/compute_engines/spark/feature_builder.py @@ -1,3 +1,4 @@ +import logging from typing import Union from pyspark.sql import SparkSession @@ -12,9 +13,14 @@ SparkJoinNode, SparkReadNode, SparkTransformationNode, + SparkValidationNode, SparkWriteNode, + from_feast_to_spark_type, ) from feast.infra.registry.base_registry import BaseRegistry +from feast.types import PrimitiveFeastType + +logger = logging.getLogger(__name__) class SparkFeatureBuilder(FeatureBuilder): @@ -115,4 +121,30 @@ def build_output_nodes(self, view, input_node): return node def build_validation_node(self, view, input_node): - pass + expected_columns = {} + json_columns: set = set() + if hasattr(view, "features"): + for feature in view.features: + spark_type = from_feast_to_spark_type(feature.dtype) + if spark_type is None: + logger.debug( + "Could not resolve Spark type for feature '%s' " + "(dtype=%s), skipping type check for this column.", + feature.name, + feature.dtype, + ) + expected_columns[feature.name] = spark_type + if ( + isinstance(feature.dtype, PrimitiveFeastType) + and feature.dtype.name == "JSON" + ): + json_columns.add(feature.name) + + node = SparkValidationNode( + f"{view.name}:validate", + expected_columns=expected_columns, + json_columns=json_columns, + inputs=[input_node], + ) + self.nodes.append(node) + return node diff --git a/sdk/python/feast/infra/compute_engines/spark/nodes.py b/sdk/python/feast/infra/compute_engines/spark/nodes.py index 124ce65ff90..5a8c4368fc5 100644 --- a/sdk/python/feast/infra/compute_engines/spark/nodes.py +++ b/sdk/python/feast/infra/compute_engines/spark/nodes.py @@ -1,10 +1,28 @@ +import json +import logging from datetime import datetime, timedelta -from typing import Callable, List, Optional, Union, cast +from typing import Callable, Dict, List, Optional, Set, Union, cast import pandas as pd from pyspark.sql import DataFrame, SparkSession, Window from pyspark.sql import functions as F from pyspark.sql.pandas.types import from_arrow_schema +from pyspark.sql.types import ( + ArrayType, + BinaryType, + BooleanType, + DoubleType, + FloatType, + IntegerType, + LongType, + MapType, + StringType, + StructType, + TimestampType, +) +from pyspark.sql.types import ( + DataType as SparkDataType, +) from feast import BatchFeatureView, StreamFeatureView from feast.aggregation import Aggregation @@ -29,6 +47,103 @@ infer_event_timestamp_from_entity_df, ) +logger = logging.getLogger(__name__) + + +def from_feast_to_spark_type(feast_type) -> Optional[SparkDataType]: + """Convert a Feast type to a PySpark DataType. + + Returns None if the Feast type cannot be mapped. + """ + from feast.types import ( + Array, + PrimitiveFeastType, + Set, + Struct, + ) + + if isinstance(feast_type, Struct): + from pyspark.sql.types import StructField + + spark_fields = [] + for name, ftype in feast_type.fields.items(): + spark_type = from_feast_to_spark_type(ftype) + if spark_type is None: + return None + spark_fields.append(StructField(name, spark_type, nullable=True)) + return StructType(spark_fields) + + if isinstance(feast_type, PrimitiveFeastType): + mapping = { + PrimitiveFeastType.BYTES: BinaryType(), + PrimitiveFeastType.STRING: StringType(), + PrimitiveFeastType.INT32: IntegerType(), + PrimitiveFeastType.INT64: LongType(), + PrimitiveFeastType.FLOAT64: DoubleType(), + PrimitiveFeastType.FLOAT32: FloatType(), + PrimitiveFeastType.BOOL: BooleanType(), + PrimitiveFeastType.UNIX_TIMESTAMP: TimestampType(), + PrimitiveFeastType.MAP: MapType(StringType(), StringType()), + PrimitiveFeastType.JSON: StringType(), + } + return mapping.get(feast_type) + + if isinstance(feast_type, Array): + base_type = feast_type.base_type + if isinstance(base_type, Struct): + inner = from_feast_to_spark_type(base_type) + return ArrayType(inner) if inner else None + if isinstance(base_type, PrimitiveFeastType): + if base_type == PrimitiveFeastType.MAP: + return ArrayType(MapType(StringType(), StringType())) + inner = from_feast_to_spark_type(base_type) + return ArrayType(inner) if inner else None + + if isinstance(feast_type, Set): + inner = from_feast_to_spark_type(feast_type.base_type) + return ArrayType(inner) if inner else None + + return None + + +def _spark_types_compatible(expected: SparkDataType, actual: SparkDataType) -> bool: + """Check if two Spark types are compatible for validation purposes. + + Exact match is always compatible. Beyond that, we allow common + representations that arise from different data source encodings. + """ + if expected == actual: + return True + + # Map ↔ Struct: data sources may encode maps as structs or vice versa + if isinstance(expected, MapType) and isinstance(actual, (MapType, StructType)): + return True + if isinstance(expected, StructType) and isinstance(actual, (StructType, MapType)): + return True + + # Json (StringType) is always compatible with StringType + if isinstance(expected, StringType) and isinstance(actual, StringType): + return True + + # Integer widening: IntegerType ↔ LongType + if isinstance(expected, (IntegerType, LongType)) and isinstance( + actual, (IntegerType, LongType) + ): + return True + + # Float widening: FloatType ↔ DoubleType + if isinstance(expected, (FloatType, DoubleType)) and isinstance( + actual, (FloatType, DoubleType) + ): + return True + + # Array compatibility: compare element types + if isinstance(expected, ArrayType) and isinstance(actual, ArrayType): + return _spark_types_compatible(expected.elementType, actual.elementType) + + return False + + ENTITY_TS_ALIAS = "__entity_event_timestamp" @@ -196,7 +311,7 @@ def _execute_tiled_aggregation(self, input_df: DataFrame) -> DAGValue: expected_columns = entity_keys + [self.timestamp_col] for time_window, window_aggs in aggs_by_window.items(): for agg in window_aggs: - feature_name = f"{agg.function}_{agg.column}_{int(time_window.total_seconds())}s" + feature_name = agg.resolved_name(time_window) if feature_name not in expected_columns: expected_columns.append(feature_name) @@ -256,12 +371,11 @@ def _execute_standard_aggregation(self, input_df: DataFrame) -> DAGValue: """Execute standard Spark aggregation (existing logic).""" agg_exprs = [] for agg in self.aggregations: - func = getattr(F, agg.function) - expr = func(agg.column).alias( - f"{agg.function}_{agg.column}_{int(agg.time_window.total_seconds())}s" - if agg.time_window - else f"{agg.function}_{agg.column}" - ) + if agg.function == "count_distinct": + func_expr = F.countDistinct(agg.column) + else: + func_expr = getattr(F, agg.function)(agg.column) + expr = func_expr.alias(agg.resolved_name(agg.time_window)) agg_exprs.append(expr) if any(agg.time_window for agg in self.aggregations): @@ -510,3 +624,107 @@ def execute(self, context: ExecutionContext) -> DAGValue: return DAGValue( data=transformed_df, format=DAGFormat.SPARK, metadata={"transformed": True} ) + + +class SparkValidationNode(DAGNode): + """ + Spark node for validating feature data against the declared schema. + + Checks that all expected columns are present in the Spark DataFrame, + validates column types using native Spark types, and checks JSON + well-formedness for Json columns. + """ + + def __init__( + self, + name: str, + expected_columns: Dict[str, Optional[SparkDataType]], + json_columns: Optional[Set[str]] = None, + inputs: Optional[List[DAGNode]] = None, + ): + super().__init__(name, inputs=inputs) + self.expected_columns = expected_columns + self.json_columns = json_columns or set() + + def execute(self, context: ExecutionContext) -> DAGValue: + input_value = self.get_single_input_value(context) + input_value.assert_format(DAGFormat.SPARK) + spark_df: DataFrame = input_value.data + + if not self.expected_columns: + context.node_outputs[self.name] = input_value + return input_value + + self._validate_schema(spark_df) + + logger.debug("[Validation: %s] Schema validation passed.", self.name) + context.node_outputs[self.name] = input_value + return input_value + + def _validate_schema(self, spark_df: DataFrame): + """Validate the Spark DataFrame against the expected schema. + + Checks for missing columns, type mismatches using native Spark types, + and JSON well-formedness for declared Json columns. + """ + actual_columns = set(spark_df.columns) + expected_names = set(self.expected_columns.keys()) + + missing = expected_names - actual_columns + if missing: + raise ValueError( + f"[Validation: {self.name}] Missing expected columns: {missing}. " + f"Actual columns: {sorted(actual_columns)}" + ) + + # Type validation using native Spark types + schema = spark_df.schema + for col_name, expected_type in self.expected_columns.items(): + if expected_type is None: + continue + try: + actual_field = schema[col_name] + except (KeyError, IndexError): + continue + actual_type = actual_field.dataType + if not _spark_types_compatible(expected_type, actual_type): + logger.warning( + "[Validation: %s] Column '%s' type mismatch: expected %s, got %s", + self.name, + col_name, + expected_type.simpleString(), + actual_type.simpleString(), + ) + + # Validate JSON well-formedness for declared Json columns + if self.json_columns: + sample_rows = spark_df.limit(1000).collect() + for col_name in self.json_columns: + if col_name not in actual_columns: + continue + + invalid_count = 0 + first_error = None + first_error_row = None + + for i, row in enumerate(sample_rows): + value = row[col_name] + if value is None: + continue + if not isinstance(value, str): + continue + try: + json.loads(value) + except (json.JSONDecodeError, TypeError) as e: + invalid_count += 1 + if first_error is None: + first_error = str(e) + first_error_row = i + + if invalid_count > 0: + raise ValueError( + f"[Validation: {self.name}] Column '{col_name}' declared as " + f"Json contains {invalid_count} invalid JSON value(s) in " + f"sampled rows. First error at row {first_error_row}: " + f"{first_error}" + ) diff --git a/sdk/python/feast/infra/contrib/grpc_server.py b/sdk/python/feast/infra/contrib/grpc_server.py index b6ed6cb25d4..4c042051225 100644 --- a/sdk/python/feast/infra/contrib/grpc_server.py +++ b/sdk/python/feast/infra/contrib/grpc_server.py @@ -1,11 +1,11 @@ import logging import threading +from collections.abc import Mapping from concurrent import futures from typing import Optional, Union import grpc import pandas as pd -from grpc_health.v1 import health, health_pb2_grpc from feast.data_source import PushMode from feast.errors import FeatureServiceNotFoundException, PushSourceNotFoundException @@ -34,6 +34,20 @@ def parse(features): return pd.DataFrame.from_dict(df) +def parse_typed(typed_features): + df = {} + for key, value in typed_features.items(): + val_case = value.WhichOneof("val") + if val_case is None or val_case == "null_val": + df[key] = [None] + else: + raw = getattr(value, val_case) + if hasattr(raw, "val"): + raw = dict(raw.val) if isinstance(raw.val, Mapping) else list(raw.val) + df[key] = [raw] + return pd.DataFrame.from_dict(df) + + class GrpcFeatureServer(GrpcFeatureServerServicer): fs: FeatureStore @@ -49,7 +63,17 @@ def __init__(self, fs: FeatureStore, registry_ttl_sec: int = 5): def Push(self, request, context): try: - df = parse(request.features) + if request.features and request.typed_features: + context.set_code(grpc.StatusCode.INVALID_ARGUMENT) + context.set_details( + "Only one of features or typed_features may be set, not both" + ) + return PushResponse(status=False) + df = ( + parse_typed(request.typed_features) + if request.typed_features + else parse(request.features) + ) if request.to == "offline": to = PushMode.OFFLINE elif request.to == "online": @@ -62,7 +86,7 @@ def Push(self, request, context): f"'online_and_offline']." ) self.fs.push( - push_source_name=request.push_source_name, + push_source_name=request.stream_feature_view, df=df, allow_registry_cache=request.allow_registry_cache, to=to, @@ -84,7 +108,17 @@ def WriteToOnlineStore(self, request, context): "write_to_online_store is deprecated. Please consider using Push instead" ) try: - df = parse(request.features) + if request.features and request.typed_features: + context.set_code(grpc.StatusCode.INVALID_ARGUMENT) + context.set_details( + "Only one of features or typed_features may be set, not both" + ) + return WriteToOnlineStoreResponse(status=False) + df = ( + parse_typed(request.typed_features) + if request.typed_features + else parse(request.features) + ) self.fs.write_to_online_store( feature_view_name=request.feature_view_name, df=df, @@ -94,7 +128,7 @@ def WriteToOnlineStore(self, request, context): logger.exception(str(e)) context.set_code(grpc.StatusCode.INTERNAL) context.set_details(str(e)) - return PushResponse(status=False) + return WriteToOnlineStoreResponse(status=False) return WriteToOnlineStoreResponse(status=True) def GetOnlineFeatures(self, request: GetOnlineFeaturesRequest, context): @@ -136,6 +170,8 @@ def get_grpc_server( max_workers: int, registry_ttl_sec: int, ): + from grpc_health.v1 import health, health_pb2_grpc + logger.info(f"Initializing gRPC server on {address}") server = grpc.server(futures.ThreadPoolExecutor(max_workers=max_workers)) add_GrpcFeatureServerServicer_to_server( diff --git a/sdk/python/feast/infra/feature_servers/base_config.py b/sdk/python/feast/infra/feature_servers/base_config.py index b13e23d035e..df324dc57d3 100644 --- a/sdk/python/feast/infra/feature_servers/base_config.py +++ b/sdk/python/feast/infra/feature_servers/base_config.py @@ -37,12 +37,62 @@ class FeatureLoggingConfig(FeastConfigBaseModel): """Timeout for adding new log item to the queue.""" +class MetricsConfig(FeastConfigBaseModel): + """Prometheus metrics configuration. + + Follows the same pattern as ``FeatureLoggingConfig``: a single + ``enabled`` flag controls global on/off, and per-category booleans + allow fine-grained suppression. Can also be enabled at runtime via + the ``feast serve --metrics`` CLI flag — either option is sufficient. + """ + + enabled: StrictBool = False + """Whether Prometheus metrics collection and the metrics HTTP server + (default port 8000) should be enabled.""" + + resource: StrictBool = True + """Emit CPU and memory usage gauges (feast_feature_server_cpu_usage, + feast_feature_server_memory_usage).""" + + request: StrictBool = True + """Emit per-endpoint request counters and latency histograms + (feast_feature_server_request_total, + feast_feature_server_request_latency_seconds).""" + + online_features: StrictBool = True + """Emit online feature retrieval metrics + (feast_online_features_request_total, + feast_online_features_entity_count, + feast_feature_server_online_store_read_duration_seconds, + feast_feature_server_transformation_duration_seconds, + feast_feature_server_write_transformation_duration_seconds). + ODFV transformation metrics additionally require track_metrics=True + on the OnDemandFeatureView definition.""" + + push: StrictBool = True + """Emit push/write request counters + (feast_push_request_total).""" + + materialization: StrictBool = True + """Emit materialization success/failure counters and duration histograms + (feast_materialization_result_total, + feast_materialization_duration_seconds).""" + + freshness: StrictBool = True + """Emit per-feature-view freshness gauges + (feast_feature_freshness_seconds).""" + + class BaseFeatureServerConfig(FeastConfigBaseModel): """Base Feature Server config that should be extended""" enabled: StrictBool = False """Whether the feature server should be launched.""" + metrics: Optional[MetricsConfig] = None + """Prometheus metrics configuration. Set ``metrics.enabled: true`` or + pass the ``feast serve --metrics`` CLI flag to activate.""" + feature_logging: Optional[FeatureLoggingConfig] = None """ Feature logging configuration """ diff --git a/sdk/python/feast/infra/feature_servers/multicloud/Dockerfile b/sdk/python/feast/infra/feature_servers/multicloud/Dockerfile index 352f1db9318..2834f98ca10 100644 --- a/sdk/python/feast/infra/feature_servers/multicloud/Dockerfile +++ b/sdk/python/feast/infra/feature_servers/multicloud/Dockerfile @@ -1,6 +1,11 @@ -FROM registry.access.redhat.com/ubi9/python-311:1 +FROM registry.access.redhat.com/ubi9/python-312-minimal:1 + +USER 0 +RUN microdnf install -y gcc libpq-devel python3.12-devel && microdnf clean all +USER 1001 COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv +ENV UV_CACHE_DIR=/tmp/uv-cache COPY requirements.txt requirements.txt RUN uv pip install -r requirements.txt diff --git a/sdk/python/feast/infra/feature_servers/multicloud/Dockerfile.dev b/sdk/python/feast/infra/feature_servers/multicloud/Dockerfile.dev index 2e163ccbaf4..4d85b621192 100644 --- a/sdk/python/feast/infra/feature_servers/multicloud/Dockerfile.dev +++ b/sdk/python/feast/infra/feature_servers/multicloud/Dockerfile.dev @@ -1,14 +1,15 @@ -FROM registry.access.redhat.com/ubi9/python-311:1 +FROM registry.access.redhat.com/ubi9/python-312-minimal:1 USER 0 +RUN microdnf install -y npm git gcc libpq-devel python3.12-devel && microdnf clean all RUN npm install -g yarn yalc && rm -rf .npm -USER default +USER 1001 -COPY --chown=default .git ${APP_ROOT}/src/.git -COPY --chown=default pyproject.toml README.md Makefile ${APP_ROOT}/src/ -COPY --chown=default protos ${APP_ROOT}/src/protos -COPY --chown=default ui ${APP_ROOT}/src/ui -COPY --chown=default sdk/python ${APP_ROOT}/src/sdk/python +COPY --chown=1001:0 .git ${APP_ROOT}/src/.git +COPY --chown=1001:0 pyproject.toml README.md Makefile ${APP_ROOT}/src/ +COPY --chown=1001:0 protos ${APP_ROOT}/src/protos +COPY --chown=1001:0 ui ${APP_ROOT}/src/ui +COPY --chown=1001:0 sdk/python ${APP_ROOT}/src/sdk/python WORKDIR ${APP_ROOT}/src/ui RUN npm install && \ @@ -27,7 +28,8 @@ RUN yalc add @feast-dev/feast-ui && \ WORKDIR ${APP_ROOT}/src COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv -RUN uv pip install --require-hashes --no-deps -r sdk/python/requirements/py3.11-minimal-requirements.txt +ENV UV_CACHE_DIR=/tmp/uv-cache +RUN uv pip install --require-hashes --no-deps -r sdk/python/requirements/py3.12-minimal-requirements.txt RUN uv pip install --no-deps -e .[minimal] # modify permissions to support running with a random uid diff --git a/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.binary b/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.binary index d37c4a1d06f..55e3f50c17c 100644 --- a/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.binary +++ b/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.binary @@ -2,11 +2,11 @@ FROM yarn-builder:latest # This section only necessary when building from local feast source ... e.g. ".[minimal]" ######################## -COPY --chown=default .git ${APP_ROOT}/src/.git -COPY --chown=default pyproject.toml README.md Makefile ${APP_ROOT}/src/ -COPY --chown=default protos ${APP_ROOT}/src/protos -COPY --chown=default ui ${APP_ROOT}/src/ui -COPY --chown=default sdk/python ${APP_ROOT}/src/sdk/python +COPY --chown=1001:0 .git ${APP_ROOT}/src/.git +COPY --chown=1001:0 pyproject.toml README.md Makefile ${APP_ROOT}/src/ +COPY --chown=1001:0 protos ${APP_ROOT}/src/protos +COPY --chown=1001:0 ui ${APP_ROOT}/src/ui +COPY --chown=1001:0 sdk/python ${APP_ROOT}/src/sdk/python WORKDIR ${APP_ROOT}/src/ui ENV NPM_TOKEN= diff --git a/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.binary.release b/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.binary.release index d490a4ae5bc..741bc7e09c9 100644 --- a/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.binary.release +++ b/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.binary.release @@ -1,4 +1,4 @@ -FROM registry.access.redhat.com/ubi9/python-311:1 +FROM registry.access.redhat.com/ubi9/python-312-minimal:1 COPY requirements.txt requirements.txt RUN source /tmp/hermeto.env && \ diff --git a/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.builder.yarn b/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.builder.yarn index 1cac1bc4d90..abac1329033 100644 --- a/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.builder.yarn +++ b/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.builder.yarn @@ -1,5 +1,6 @@ -FROM registry.access.redhat.com/ubi9/python-311:1 +FROM registry.access.redhat.com/ubi9/python-312-minimal:1 USER 0 +RUN microdnf install -y npm git && microdnf clean all RUN npm install -g yarn yalc && rm -rf .npm USER 1001 diff --git a/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.builder.yum b/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.builder.yum index 0a19017f1d4..14fdbae4b5b 100644 --- a/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.builder.yum +++ b/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.builder.yum @@ -1,10 +1,10 @@ -FROM registry.access.redhat.com/ubi9/python-311:1 +FROM registry.access.redhat.com/ubi9/python-312-minimal:1 ARG RELEASE ENV IBIS_VERSION="9.5.0" USER 0 -RUN yum install -y ninja-build llvm-devel cmake llvm-toolset ncurses-devel rust cargo +RUN microdnf install -y ninja-build llvm-devel cmake llvm-toolset ncurses-devel rust cargo npm git && microdnf clean all RUN if [[ -z "$RELEASE" ]] ; then npm install -g yarn yalc && rm -rf .npm ; fi USER 1001 diff --git a/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.sdist b/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.sdist index 5c62bdec22a..e6e32718667 100644 --- a/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.sdist +++ b/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.sdist @@ -13,6 +13,7 @@ ENV THIRD_PARTY_PATH=/tmp/hermeto-generic-output/deps/generic # unecessary for konflux build ENV RPM_PATH=/tmp/hermeto-rpm-output/deps/rpm/x86_64 USER 0 +RUN microdnf install -y shadow-utils && microdnf clean all RUN useradd mockbuild RUN groupadd mock RUN usermod -G mock mockbuild @@ -71,7 +72,7 @@ RUN mkdir ${APP_ROOT}/src/arrow ${ARROW_HOME} ${APP_ROOT}/src/arrow-build && \ ARROW_ZLIB_URL="${THIRD_PARTY_PATH}/zlib-1.3.1.tar.gz" \ ARROW_ZSTD_URL="${THIRD_PARTY_PATH}/zstd-1.5.6.tar.gz" \ && \ - cmake \ + cmake -G Ninja \ -DCMAKE_INSTALL_PREFIX=$ARROW_HOME \ -DARROW_COMPUTE=ON \ -DARROW_ACERO=ON \ @@ -130,11 +131,11 @@ RUN source /tmp/hermeto.env && \ # This section only necessary when building from local feast source ... e.g. ".[minimal]" ######################## -COPY --chown=default .git ${APP_ROOT}/src/.git -COPY --chown=default pyproject.toml README.md Makefile ${APP_ROOT}/src/ -COPY --chown=default protos ${APP_ROOT}/src/protos -COPY --chown=default ui ${APP_ROOT}/src/ui -COPY --chown=default sdk/python ${APP_ROOT}/src/sdk/python +COPY --chown=1001:0 .git ${APP_ROOT}/src/.git +COPY --chown=1001:0 pyproject.toml README.md Makefile ${APP_ROOT}/src/ +COPY --chown=1001:0 protos ${APP_ROOT}/src/protos +COPY --chown=1001:0 ui ${APP_ROOT}/src/ui +COPY --chown=1001:0 sdk/python ${APP_ROOT}/src/sdk/python WORKDIR ${APP_ROOT}/src/ui ENV NPM_TOKEN= diff --git a/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.sdist.release b/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.sdist.release index 946b6407626..11c4b5c7af4 100644 --- a/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.sdist.release +++ b/sdk/python/feast/infra/feature_servers/multicloud/offline/Dockerfile.sdist.release @@ -1,4 +1,4 @@ -FROM registry.access.redhat.com/ubi9/python-311:1 +FROM registry.access.redhat.com/ubi9/python-312-minimal:1 ENV APACHE_ARROW_VERSION="17.0.0" ENV MILVUS_LITE_VERSION="2.4.12" @@ -13,6 +13,7 @@ ENV THIRD_PARTY_PATH=/tmp/hermeto-generic-output/deps/generic # unecessary for konflux build ENV RPM_PATH=/tmp/hermeto-rpm-output/deps/rpm/x86_64 USER 0 +RUN microdnf install -y shadow-utils && microdnf clean all RUN useradd mockbuild RUN groupadd mock RUN usermod -G mock mockbuild @@ -71,7 +72,7 @@ RUN mkdir ${APP_ROOT}/src/arrow ${ARROW_HOME} ${APP_ROOT}/src/arrow-build && \ ARROW_ZLIB_URL="${THIRD_PARTY_PATH}/zlib-1.3.1.tar.gz" \ ARROW_ZSTD_URL="${THIRD_PARTY_PATH}/zstd-1.5.6.tar.gz" \ && \ - cmake \ + cmake -G Ninja \ -DCMAKE_INSTALL_PREFIX=$ARROW_HOME \ -DARROW_COMPUTE=ON \ -DARROW_ACERO=ON \ diff --git a/sdk/python/feast/infra/feature_servers/multicloud/offline/offline-binary-build.sh b/sdk/python/feast/infra/feature_servers/multicloud/offline/offline-binary-build.sh index 8d8ca4ba5f1..7f2820057b0 100755 --- a/sdk/python/feast/infra/feature_servers/multicloud/offline/offline-binary-build.sh +++ b/sdk/python/feast/infra/feature_servers/multicloud/offline/offline-binary-build.sh @@ -44,9 +44,9 @@ hermeto fetch-deps \ "sdk/python/feast/infra/feature_servers/multicloud/requirements.txt" ], "requirements_build_files": [ -"sdk/python/requirements/py3.11-minimal-requirements.txt", -"sdk/python/requirements/py3.11-minimal-sdist-requirements.txt", -"sdk/python/requirements/py3.11-minimal-sdist-requirements-build.txt" +"sdk/python/requirements/py3.12-minimal-requirements.txt", +"sdk/python/requirements/py3.12-minimal-sdist-requirements.txt", +"sdk/python/requirements/py3.12-minimal-sdist-requirements-build.txt" ], "allow_binary": "true" }' diff --git a/sdk/python/feast/infra/feature_servers/multicloud/offline/offline-binary-release-build.sh b/sdk/python/feast/infra/feature_servers/multicloud/offline/offline-binary-release-build.sh index 8462cef705b..4571324972a 100755 --- a/sdk/python/feast/infra/feature_servers/multicloud/offline/offline-binary-release-build.sh +++ b/sdk/python/feast/infra/feature_servers/multicloud/offline/offline-binary-release-build.sh @@ -19,9 +19,9 @@ hermeto fetch-deps \ "sdk/python/feast/infra/feature_servers/multicloud/requirements.txt" ], "requirements_build_files": [ -"sdk/python/requirements/py3.11-minimal-requirements.txt", -"sdk/python/requirements/py3.11-minimal-sdist-requirements.txt", -"sdk/python/requirements/py3.11-minimal-sdist-requirements-build.txt" +"sdk/python/requirements/py3.12-minimal-requirements.txt", +"sdk/python/requirements/py3.12-minimal-sdist-requirements.txt", +"sdk/python/requirements/py3.12-minimal-sdist-requirements-build.txt" ], "allow_binary": "true" }' diff --git a/sdk/python/feast/infra/feature_servers/multicloud/offline/offline-build.sh b/sdk/python/feast/infra/feature_servers/multicloud/offline/offline-build.sh index c84774f497c..f66035e75c1 100755 --- a/sdk/python/feast/infra/feature_servers/multicloud/offline/offline-build.sh +++ b/sdk/python/feast/infra/feature_servers/multicloud/offline/offline-build.sh @@ -55,8 +55,8 @@ hermeto fetch-deps \ "sdk/python/feast/infra/feature_servers/multicloud/requirements.txt" ], "requirements_build_files": [ -"sdk/python/requirements/py3.11-minimal-sdist-requirements.txt", -"sdk/python/requirements/py3.11-minimal-sdist-requirements-build.txt" +"sdk/python/requirements/py3.12-minimal-sdist-requirements.txt", +"sdk/python/requirements/py3.12-minimal-sdist-requirements-build.txt" ], "allow_binary": "false" }' diff --git a/sdk/python/feast/infra/feature_servers/multicloud/offline/offline-release-build.sh b/sdk/python/feast/infra/feature_servers/multicloud/offline/offline-release-build.sh index 49df0eae600..0ea10d2f24e 100755 --- a/sdk/python/feast/infra/feature_servers/multicloud/offline/offline-release-build.sh +++ b/sdk/python/feast/infra/feature_servers/multicloud/offline/offline-release-build.sh @@ -30,8 +30,8 @@ hermeto fetch-deps \ "sdk/python/feast/infra/feature_servers/multicloud/requirements.txt" ], "requirements_build_files": [ -"sdk/python/requirements/py3.11-minimal-sdist-requirements.txt", -"sdk/python/requirements/py3.11-minimal-sdist-requirements-build.txt" +"sdk/python/requirements/py3.12-minimal-sdist-requirements.txt", +"sdk/python/requirements/py3.12-minimal-sdist-requirements-build.txt" ], "allow_binary": "false" }' diff --git a/sdk/python/feast/infra/feature_servers/multicloud/requirements.txt b/sdk/python/feast/infra/feature_servers/multicloud/requirements.txt index 634f73c78df..18fc3a66969 100644 --- a/sdk/python/feast/infra/feature_servers/multicloud/requirements.txt +++ b/sdk/python/feast/infra/feature_servers/multicloud/requirements.txt @@ -1,2 +1,2 @@ # keep VERSION on line #2, this is critical to release CI -feast[minimal] == 0.60.0 +feast[minimal] == 0.62.0 diff --git a/sdk/python/feast/infra/key_encoding_utils.py b/sdk/python/feast/infra/key_encoding_utils.py index 3e9ba70d3ba..10a9934ad6a 100644 --- a/sdk/python/feast/infra/key_encoding_utils.py +++ b/sdk/python/feast/infra/key_encoding_utils.py @@ -57,15 +57,20 @@ def serialize_entity_key_prefix( This encoding is a partial implementation of serialize_entity_key, only operating on the keys of entities, and not the values. """ - sorted_keys = sorted(entity_keys) + # Fast path optimization for single entity + if len(entity_keys) == 1: + sorted_keys = [entity_keys[0]] + else: + sorted_keys = sorted(entity_keys) output: List[bytes] = [] if entity_key_serialization_version > 2: output.append(struct.pack(" 2: - output.append(struct.pack(" 2: output.append(struct.pack(" 2: - output.append(struct.pack(" 2: + output.append(struct.pack(" Optional["FastApiMCP"]: """Add MCP support to the FastAPI app if enabled in configuration.""" if not MCP_AVAILABLE: @@ -40,8 +44,29 @@ def add_mcp_support_to_app(app, store: FeatureStore, config) -> Optional["FastAp description="Feast Feature Store MCP Server - Access feature store data and operations through MCP", ) - # Mount the MCP server to the FastAPI app - mcp.mount() + transport = getattr(config, "mcp_transport", "sse") + if transport == "http": + mount_http = getattr(mcp, "mount_http", None) + if mount_http is None: + raise McpTransportNotSupportedError( + "mcp_transport=http requires fastapi_mcp with FastApiMCP.mount_http(). " + "Upgrade fastapi_mcp (or install feast[mcp]) to a newer version." + ) + mount_http() + elif transport == "sse": + mount_sse = getattr(mcp, "mount_sse", None) + if mount_sse is not None: + mount_sse() + else: + logger.warning( + "transport sse not supported, fallback to the deprecated mount()." + ) + mcp.mount() + else: + # Defensive guard for programmatic callers. + raise McpTransportNotSupportedError( + f"Unsupported mcp_transport={transport!r}. Expected 'sse' or 'http'." + ) logger.info( "MCP support has been enabled for the Feast feature server at /mcp endpoint" @@ -53,6 +78,8 @@ def add_mcp_support_to_app(app, store: FeatureStore, config) -> Optional["FastAp return mcp + except McpTransportNotSupportedError: + raise except Exception as e: - logger.error(f"Failed to initialize MCP integration: {e}") + logger.error(f"Failed to initialize MCP integration: {e}", exc_info=True) return None diff --git a/sdk/python/feast/infra/offline_stores/bigquery.py b/sdk/python/feast/infra/offline_stores/bigquery.py index 2c4bc8cdbc3..948cfcf1ff0 100644 --- a/sdk/python/feast/infra/offline_stores/bigquery.py +++ b/sdk/python/feast/infra/offline_stores/bigquery.py @@ -161,6 +161,14 @@ def pull_latest_from_table_or_query( project=project_id, location=config.offline_store.location, ) + timestamp_filter = get_timestamp_filter_sql( + start_date, + end_date, + timestamp_field, + date_partition_column=data_source.date_partition_column, + quote_fields=False, + cast_style="timestamp_func", + ) query = f""" SELECT {field_string} @@ -169,7 +177,7 @@ def pull_latest_from_table_or_query( SELECT {field_string}, ROW_NUMBER() OVER({partition_by_join_key_string} ORDER BY {timestamp_desc_string}) AS _feast_row FROM {from_expression} - WHERE {timestamp_field} BETWEEN TIMESTAMP('{start_date}') AND TIMESTAMP('{end_date}') + WHERE {timestamp_filter} ) WHERE _feast_row = 1 """ @@ -216,6 +224,7 @@ def pull_all_from_table_or_query( start_date, end_date, timestamp_field, + date_partition_column=data_source.date_partition_column, quote_fields=False, cast_style="timestamp_func", ) @@ -416,7 +425,7 @@ def offline_write_batch( ) if table.schema != pa_schema: - table = table.cast(pa_schema) + table = offline_utils.cast_arrow_table_to_schema(table, pa_schema) project_id = ( config.offline_store.billing_project_id or config.offline_store.project_id ) @@ -833,12 +842,17 @@ def arrow_schema_to_bq_schema(arrow_schema: pyarrow.Schema) -> List[SchemaField] bq_schema = [] for field in arrow_schema: - if pyarrow.types.is_list(field.type): + if pyarrow.types.is_struct(field.type) or pyarrow.types.is_map(field.type): + detected_mode = "NULLABLE" + detected_type = "STRING" + elif pyarrow.types.is_list(field.type): detected_mode = "REPEATED" - detected_type = _ARROW_SCALAR_IDS_TO_BQ[field.type.value_type.id] + detected_type = _ARROW_SCALAR_IDS_TO_BQ.get( + field.type.value_type.id, "STRING" + ) else: detected_mode = "NULLABLE" - detected_type = _ARROW_SCALAR_IDS_TO_BQ[field.type.id] + detected_type = _ARROW_SCALAR_IDS_TO_BQ.get(field.type.id, "STRING") bq_schema.append( SchemaField(name=field.name, field_type=detected_type, mode=detected_mode) @@ -924,6 +938,12 @@ def arrow_schema_to_bq_schema(arrow_schema: pyarrow.Schema) -> List[SchemaField] {% if featureview.ttl == 0 %}{% else %} AND {{ featureview.timestamp_field }} >= '{{ featureview.min_event_timestamp }}' {% endif %} + {% if featureview.date_partition_column %} + AND {{ featureview.date_partition_column | backticks }} <= '{{ featureview.max_event_timestamp[:10] }}' + {% if featureview.min_event_timestamp %} + AND {{ featureview.date_partition_column | backticks }} >= '{{ featureview.min_event_timestamp[:10] }}' + {% endif %} + {% endif %} ), {{ featureview.name }}__base AS ( diff --git a/sdk/python/feast/infra/offline_stores/bigquery_source.py b/sdk/python/feast/infra/offline_stores/bigquery_source.py index 1dda7af928f..69e42e3fd09 100644 --- a/sdk/python/feast/infra/offline_stores/bigquery_source.py +++ b/sdk/python/feast/infra/offline_stores/bigquery_source.py @@ -34,6 +34,7 @@ def __init__( table: Optional[str] = None, created_timestamp_column: Optional[str] = "", field_mapping: Optional[Dict[str, str]] = None, + date_partition_column: Optional[str] = None, query: Optional[str] = None, description: Optional[str] = "", tags: Optional[Dict[str, str]] = None, @@ -52,6 +53,7 @@ def __init__( created_timestamp_column (optional): Timestamp column when row was created, used for deduplicating rows. field_mapping (optional): A dictionary mapping of column names in this data source to feature names in a feature table or view. Only used for feature columns, not entities or timestamp columns. + date_partition_column (optional): Timestamp column used for partitioning. query (optional): The query to be executed to obtain the features. Exactly one of 'table' and 'query' must be specified. description (optional): A human-readable description. @@ -78,6 +80,7 @@ def __init__( timestamp_field=timestamp_field, created_timestamp_column=created_timestamp_column, field_mapping=field_mapping, + date_partition_column=date_partition_column, description=description, tags=tags, owner=owner, @@ -117,6 +120,7 @@ def from_proto(data_source: DataSourceProto): table=data_source.bigquery_options.table, timestamp_field=data_source.timestamp_field, created_timestamp_column=data_source.created_timestamp_column, + date_partition_column=data_source.date_partition_column, query=data_source.bigquery_options.query, description=data_source.description, tags=dict(data_source.tags), @@ -134,6 +138,7 @@ def _to_proto_impl(self) -> DataSourceProto: owner=self.owner, timestamp_field=self.timestamp_field, created_timestamp_column=self.created_timestamp_column, + date_partition_column=self.date_partition_column, ) return data_source_proto diff --git a/sdk/python/feast/infra/offline_stores/contrib/athena_offline_store/tests/data_source.py b/sdk/python/feast/infra/offline_stores/contrib/athena_offline_store/tests/data_source.py index b43c874ddc3..08dbbbf978d 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/athena_offline_store/tests/data_source.py +++ b/sdk/python/feast/infra/offline_stores/contrib/athena_offline_store/tests/data_source.py @@ -16,7 +16,7 @@ ) from feast.infra.utils import aws_utils from feast.repo_config import FeastConfigBaseModel -from tests.integration.feature_repos.universal.data_source_creator import ( +from tests.universal.feature_repos.universal.data_source_creator import ( DataSourceCreator, ) diff --git a/sdk/python/feast/infra/offline_stores/contrib/athena_repo_configuration.py b/sdk/python/feast/infra/offline_stores/contrib/athena_repo_configuration.py index 09bc6ce961c..9fa7472af62 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/athena_repo_configuration.py +++ b/sdk/python/feast/infra/offline_stores/contrib/athena_repo_configuration.py @@ -1,7 +1,7 @@ from feast.infra.offline_stores.contrib.athena_offline_store.tests.data_source import ( AthenaDataSourceCreator, ) -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) diff --git a/sdk/python/feast/infra/offline_stores/contrib/clickhouse_offline_store/clickhouse.py b/sdk/python/feast/infra/offline_stores/contrib/clickhouse_offline_store/clickhouse.py index 5e8cf3d9053..79958960c85 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/clickhouse_offline_store/clickhouse.py +++ b/sdk/python/feast/infra/offline_stores/contrib/clickhouse_offline_store/clickhouse.py @@ -31,6 +31,7 @@ from feast.infra.utils.clickhouse.clickhouse_config import ClickhouseConfig from feast.infra.utils.clickhouse.connection_utils import get_client from feast.saved_dataset import SavedDatasetStorage +from feast.utils import compute_non_entity_date_range class ClickhouseOfflineStoreConfig(ClickhouseConfig): @@ -43,15 +44,25 @@ def get_historical_features( config: RepoConfig, feature_views: List[FeatureView], feature_refs: List[str], - entity_df: Union[pd.DataFrame, str], + entity_df: Optional[Union[pd.DataFrame, str]], registry: BaseRegistry, project: str, full_feature_names: bool = False, + **kwargs, ) -> RetrievalJob: assert isinstance(config.offline_store, ClickhouseOfflineStoreConfig) for fv in feature_views: assert isinstance(fv.batch_source, ClickhouseSource) + # Handle non-entity retrieval mode + if entity_df is None: + start_date, end_date = compute_non_entity_date_range( + feature_views, + start_date=kwargs.get("start_date"), + end_date=kwargs.get("end_date"), + ) + entity_df = pd.DataFrame({"event_timestamp": [end_date]}) + entity_schema = _get_entity_schema(entity_df, config) entity_df_event_timestamp_col = ( diff --git a/sdk/python/feast/infra/offline_stores/contrib/clickhouse_offline_store/tests/data_source.py b/sdk/python/feast/infra/offline_stores/contrib/clickhouse_offline_store/tests/data_source.py index 4234c46eb3f..4c6068fd6bd 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/clickhouse_offline_store/tests/data_source.py +++ b/sdk/python/feast/infra/offline_stores/contrib/clickhouse_offline_store/tests/data_source.py @@ -17,7 +17,7 @@ ) from feast.infra.utils.clickhouse.clickhouse_config import ClickhouseConfig from feast.infra.utils.clickhouse.connection_utils import get_client -from tests.integration.feature_repos.universal.data_source_creator import ( +from tests.universal.feature_repos.universal.data_source_creator import ( DataSourceCreator, ) @@ -118,6 +118,18 @@ def teardown(self): pass +def _make_offline_store_config(clickhouse_container): + """Build a ClickhouseOfflineStoreConfig pointing at the test container.""" + return ClickhouseOfflineStoreConfig( + type="clickhouse", + host=clickhouse_container.get_container_host_ip(), + port=clickhouse_container.get_exposed_port(8123), + database=CLICKHOUSE_OFFLINE_DB, + user=CLICKHOUSE_USER, + password=CLICKHOUSE_PASSWORD, + ) + + def test_get_client_with_additional_params(clickhouse_container): """ Test that get_client works with a real ClickHouse container and properly passes @@ -142,3 +154,71 @@ def test_get_client_with_additional_params(clickhouse_container): # Verify the send_receive_timeout was applied assert client.timeout._read == 60 + + +def test_non_entity_retrieval(clickhouse_container): + """Integration test: get_historical_features with entity_df=None returns real data.""" + from datetime import datetime, timedelta, timezone + from unittest.mock import MagicMock + + from feast.feature_view import FeatureView, Field + from feast.infra.offline_stores.contrib.clickhouse_offline_store.clickhouse import ( + ClickhouseOfflineStore, + df_to_clickhouse_table, + ) + from feast.repo_config import RepoConfig + from feast.types import Float32 + + offline_config = _make_offline_store_config(clickhouse_container) + repo_config = RepoConfig( + project="test_project", + registry="test_registry", + provider="local", + offline_store=offline_config, + ) + + # Seed a feature table with real data + now = datetime.now(tz=timezone.utc) + feature_df = pd.DataFrame( + { + "event_timestamp": [now - timedelta(hours=2), now - timedelta(hours=1)], + "feature_value": [1.0, 2.0], + } + ) + table_name = "test_non_entity_features" + client = get_client(offline_config) + client.command(f"DROP TABLE IF EXISTS {table_name}") + df_to_clickhouse_table(offline_config, feature_df, table_name, "event_timestamp") + + source = ClickhouseSource( + name=table_name, + table=table_name, + timestamp_field="event_timestamp", + ) + fv = FeatureView( + name="test_fv", + entities=[], + ttl=timedelta(days=1), + source=source, + schema=[Field(name="feature_value", dtype=Float32)], + ) + + registry = MagicMock() + registry.list_on_demand_feature_views.return_value = [] + + job = ClickhouseOfflineStore.get_historical_features( + config=repo_config, + feature_views=[fv], + feature_refs=["test_fv:feature_value"], + entity_df=None, + registry=registry, + project="test_project", + end_date=now, + ) + + result_df = job.to_df() + assert len(result_df) > 0 + assert "feature_value" in result_df.columns + + # Cleanup + client.command(f"DROP TABLE IF EXISTS {table_name}") diff --git a/sdk/python/feast/infra/offline_stores/contrib/clickhouse_repo_configuration.py b/sdk/python/feast/infra/offline_stores/contrib/clickhouse_repo_configuration.py index 5c9d4461b16..6874bc9a3fc 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/clickhouse_repo_configuration.py +++ b/sdk/python/feast/infra/offline_stores/contrib/clickhouse_repo_configuration.py @@ -1,8 +1,8 @@ from feast.infra.offline_stores.contrib.clickhouse_offline_store.tests.data_source import ( ClickhouseDataSourceCreator, ) -from tests.integration.feature_repos.repo_configuration import REDIS_CONFIG -from tests.integration.feature_repos.universal.online_store.redis import ( +from tests.universal.feature_repos.repo_configuration import REDIS_CONFIG +from tests.universal.feature_repos.universal.online_store.redis import ( RedisOnlineStoreCreator, ) diff --git a/sdk/python/feast/infra/offline_stores/contrib/couchbase_columnar_repo_configuration.py b/sdk/python/feast/infra/offline_stores/contrib/couchbase_columnar_repo_configuration.py index 745a074a757..3ce308a00cf 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/couchbase_columnar_repo_configuration.py +++ b/sdk/python/feast/infra/offline_stores/contrib/couchbase_columnar_repo_configuration.py @@ -1,11 +1,11 @@ from feast.infra.offline_stores.contrib.couchbase_offline_store.tests.data_source import ( CouchbaseColumnarDataSourceCreator, ) -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) -from tests.integration.feature_repos.repo_configuration import REDIS_CONFIG -from tests.integration.feature_repos.universal.online_store.redis import ( +from tests.universal.feature_repos.repo_configuration import REDIS_CONFIG +from tests.universal.feature_repos.universal.online_store.redis import ( RedisOnlineStoreCreator, ) diff --git a/sdk/python/feast/infra/offline_stores/contrib/couchbase_offline_store/tests/data_source.py b/sdk/python/feast/infra/offline_stores/contrib/couchbase_offline_store/tests/data_source.py index c23a8301a76..c9491accd59 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/couchbase_offline_store/tests/data_source.py +++ b/sdk/python/feast/infra/offline_stores/contrib/couchbase_offline_store/tests/data_source.py @@ -23,7 +23,7 @@ ) from feast.infra.utils.couchbase.couchbase_utils import normalize_timestamp from feast.repo_config import FeastConfigBaseModel -from tests.integration.feature_repos.universal.data_source_creator import ( +from tests.universal.feature_repos.universal.data_source_creator import ( DataSourceCreator, ) diff --git a/sdk/python/feast/infra/offline_stores/contrib/mssql_offline_store/tests/data_source.py b/sdk/python/feast/infra/offline_stores/contrib/mssql_offline_store/tests/data_source.py index 9c87b8d7520..a2c89c11056 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/mssql_offline_store/tests/data_source.py +++ b/sdk/python/feast/infra/offline_stores/contrib/mssql_offline_store/tests/data_source.py @@ -15,7 +15,7 @@ MsSqlServerSource, ) from feast.saved_dataset import SavedDatasetStorage -from tests.integration.feature_repos.universal.data_source_creator import ( +from tests.universal.feature_repos.universal.data_source_creator import ( DataSourceCreator, ) diff --git a/sdk/python/feast/infra/offline_stores/contrib/mssql_repo_configuration.py b/sdk/python/feast/infra/offline_stores/contrib/mssql_repo_configuration.py index 50d636ba909..e64693b7494 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/mssql_repo_configuration.py +++ b/sdk/python/feast/infra/offline_stores/contrib/mssql_repo_configuration.py @@ -1,8 +1,8 @@ from feast.infra.offline_stores.contrib.mssql_offline_store.tests.data_source import ( MsSqlDataSourceCreator, ) -from tests.integration.feature_repos.repo_configuration import REDIS_CONFIG -from tests.integration.feature_repos.universal.online_store.redis import ( +from tests.universal.feature_repos.repo_configuration import REDIS_CONFIG +from tests.universal.feature_repos.universal.online_store.redis import ( RedisOnlineStoreCreator, ) diff --git a/sdk/python/feast/infra/offline_stores/contrib/oracle_offline_store/__init__.py b/sdk/python/feast/infra/offline_stores/contrib/oracle_offline_store/__init__.py new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/sdk/python/feast/infra/offline_stores/contrib/oracle_offline_store/__init__.py @@ -0,0 +1 @@ + diff --git a/sdk/python/feast/infra/offline_stores/contrib/oracle_offline_store/oracle.py b/sdk/python/feast/infra/offline_stores/contrib/oracle_offline_store/oracle.py new file mode 100644 index 00000000000..43c37f8ec10 --- /dev/null +++ b/sdk/python/feast/infra/offline_stores/contrib/oracle_offline_store/oracle.py @@ -0,0 +1,308 @@ +from datetime import datetime +from pathlib import Path +from typing import Any, Callable, List, Literal, Optional, Union + +import ibis +import pandas as pd +import pyarrow +from ibis.expr.types import Table +from pydantic import StrictInt, StrictStr, model_validator + +from feast.data_source import DataSource +from feast.feature_logging import LoggingConfig, LoggingSource +from feast.feature_view import FeatureView +from feast.infra.offline_stores.contrib.oracle_offline_store.oracle_source import ( + OracleSource, +) +from feast.infra.offline_stores.ibis import ( + get_historical_features_ibis, + offline_write_batch_ibis, + pull_all_from_table_or_query_ibis, + pull_latest_from_table_or_query_ibis, + write_logged_features_ibis, +) +from feast.infra.offline_stores.offline_store import OfflineStore, RetrievalJob +from feast.infra.registry.base_registry import BaseRegistry +from feast.repo_config import FeastConfigBaseModel, RepoConfig +from feast.utils import compute_non_entity_date_range + + +def get_ibis_connection(config: RepoConfig): + """Create an ibis Oracle connection from the offline store config.""" + offline_config = config.offline_store + assert isinstance(offline_config, OracleOfflineStoreConfig) + + kwargs = {} + if offline_config.service_name: + kwargs["service_name"] = offline_config.service_name + if offline_config.sid: + kwargs["sid"] = offline_config.sid + if offline_config.database: + kwargs["database"] = offline_config.database + if offline_config.dsn: + kwargs["dsn"] = offline_config.dsn + + return ibis.oracle.connect( + user=offline_config.user, + password=offline_config.password, + host=offline_config.host, + port=offline_config.port, + **kwargs, + ) + + +def _read_oracle_table(con, data_source: DataSource) -> Table: + """Read an Oracle table via ibis. + + Column names are returned exactly as Oracle stores them. The user is + expected to reference columns using the same casing shown by Oracle + (e.g. ``USER_ID`` for unquoted identifiers, ``CamelCase`` for quoted). + """ + assert isinstance(data_source, OracleSource) + table = con.table(data_source.table_ref) + + # Cast Oracle DATE columns (ibis date → timestamp) to preserve time. + casts = {} + for col_name in table.columns: + if table[col_name].type().is_date(): + casts[col_name] = table[col_name].cast("timestamp") + if casts: + table = table.mutate(**casts) + + return table + + +def _build_data_source_reader(config: RepoConfig, con=None): + """Build a reader that returns Oracle-backend ibis tables.""" + if con is None: + con = get_ibis_connection(config) + + def _read_data_source(data_source: DataSource, repo_path: str = "") -> Table: + return _read_oracle_table(con, data_source) + + return _read_data_source + + +def _build_data_source_writer(config: RepoConfig, con=None): + """Build a function that writes data to an Oracle table via ibis.""" + if con is None: + con = get_ibis_connection(config) + + def _write_data_source( + table: Table, + data_source: DataSource, + repo_path: str = "", + mode: str = "append", + allow_overwrite: bool = False, + ): + assert isinstance(data_source, OracleSource) + table_ref = data_source.table_ref + + if mode == "overwrite": + if not allow_overwrite: + raise ValueError( + f"Table '{table_ref}' already exists. " + f"Set allow_overwrite=True to truncate and replace data." + ) + con.truncate_table(table_ref) + + con.insert(table_name=table_ref, obj=table.to_pandas()) + + return _write_data_source + + +class OracleOfflineStoreConfig(FeastConfigBaseModel): + """Offline store config for Oracle Database""" + + type: Literal["oracle"] = "oracle" + """Offline store type selector""" + + user: StrictStr + """Oracle database user""" + + password: StrictStr + """Oracle database password""" + + host: StrictStr = "localhost" + """Oracle database host""" + + port: StrictInt = 1521 + """Oracle database port""" + + service_name: Optional[StrictStr] = None + """Oracle service name (mutually exclusive with sid and dsn)""" + + sid: Optional[StrictStr] = None + """Oracle SID (mutually exclusive with service_name and dsn)""" + + database: Optional[StrictStr] = None + """Oracle database name""" + + dsn: Optional[StrictStr] = None + """Oracle DSN string (mutually exclusive with service_name and sid)""" + + @model_validator(mode="after") + def _validate_connection_params(self): + exclusive = [ + f for f in ("service_name", "sid", "dsn") if getattr(self, f) is not None + ] + if len(exclusive) > 1: + raise ValueError( + f"Only one of 'service_name', 'sid', or 'dsn' may be set, " + f"but got: {', '.join(exclusive)}" + ) + return self + + +def _build_entity_df_from_feature_sources( + con, + feature_views: List[FeatureView], + start_date: datetime, + end_date: datetime, +) -> pd.DataFrame: + """Build a synthetic entity DataFrame by scanning each feature source within a date range.""" + entity_dfs = [] + for fv in feature_views: + source = fv.batch_source + assert source is not None, f"Feature view '{fv.name}' has no batch_source" + table = _read_oracle_table(con, source) + ts_col = source.timestamp_field + join_keys = [e.name for e in fv.entity_columns] + cols = join_keys + [ts_col] + sub = table.filter( + (table[ts_col] >= ibis.literal(start_date)) + & (table[ts_col] <= ibis.literal(end_date)) + ).select(cols) + sub = sub.rename({"event_timestamp": ts_col}) + entity_dfs.append(sub.execute()) + + return pd.concat(entity_dfs, ignore_index=True).drop_duplicates() + + +class OracleOfflineStore(OfflineStore): + @staticmethod + def pull_latest_from_table_or_query( + config: RepoConfig, + data_source: DataSource, + join_key_columns: List[str], + feature_name_columns: List[str], + timestamp_field: str, + created_timestamp_column: Optional[str], + start_date: datetime, + end_date: datetime, + ) -> RetrievalJob: + con = get_ibis_connection(config) + + return pull_latest_from_table_or_query_ibis( + config=config, + data_source=data_source, + join_key_columns=join_key_columns, + feature_name_columns=feature_name_columns, + timestamp_field=timestamp_field, + created_timestamp_column=created_timestamp_column, + start_date=start_date, + end_date=end_date, + data_source_reader=_build_data_source_reader(config, con=con), + data_source_writer=_build_data_source_writer(config, con=con), + ) + + @staticmethod + def get_historical_features( + config: RepoConfig, + feature_views: List[FeatureView], + feature_refs: List[str], + entity_df: Optional[Union[pd.DataFrame, str]], + registry: BaseRegistry, + project: str, + full_feature_names: bool = False, + **kwargs, + ) -> RetrievalJob: + if not feature_views: + raise ValueError("feature_views must not be empty") + + # Single connection reused across the entire call. + con = get_ibis_connection(config) + + # Handle non-entity retrieval mode (start_date/end_date only) + if entity_df is None: + start_date, end_date = compute_non_entity_date_range( + feature_views, + start_date=kwargs.get("start_date"), + end_date=kwargs.get("end_date"), + ) + entity_df = _build_entity_df_from_feature_sources( + con, feature_views, start_date, end_date + ) + + # If entity_df is a SQL string, execute it to get a DataFrame + if isinstance(entity_df, str): + entity_df = con.sql(entity_df).execute() + + return get_historical_features_ibis( + config=config, + feature_views=feature_views, + feature_refs=feature_refs, + entity_df=entity_df, + registry=registry, + project=project, + full_feature_names=full_feature_names, + data_source_reader=_build_data_source_reader(config, con=con), + data_source_writer=_build_data_source_writer(config, con=con), + ) + + @staticmethod + def pull_all_from_table_or_query( + config: RepoConfig, + data_source: DataSource, + join_key_columns: List[str], + feature_name_columns: List[str], + timestamp_field: str, + created_timestamp_column: Optional[str] = None, + start_date: Optional[datetime] = None, + end_date: Optional[datetime] = None, + ) -> RetrievalJob: + con = get_ibis_connection(config) + + return pull_all_from_table_or_query_ibis( + config=config, + data_source=data_source, + join_key_columns=join_key_columns, + feature_name_columns=feature_name_columns, + timestamp_field=timestamp_field, + created_timestamp_column=created_timestamp_column, + start_date=start_date, + end_date=end_date, + data_source_reader=_build_data_source_reader(config, con=con), + data_source_writer=_build_data_source_writer(config, con=con), + ) + + @staticmethod + def offline_write_batch( + config: RepoConfig, + feature_view: FeatureView, + table: pyarrow.Table, + progress: Optional[Callable[[int], Any]], + ): + offline_write_batch_ibis( + config=config, + feature_view=feature_view, + table=table, + progress=progress, + data_source_writer=_build_data_source_writer(config), + ) + + @staticmethod + def write_logged_features( + config: RepoConfig, + data: Union[pyarrow.Table, Path], + source: LoggingSource, + logging_config: LoggingConfig, + registry: BaseRegistry, + ): + write_logged_features_ibis( + config=config, + data=data, + source=source, + logging_config=logging_config, + registry=registry, + ) diff --git a/sdk/python/feast/infra/offline_stores/contrib/oracle_offline_store/oracle_source.py b/sdk/python/feast/infra/offline_stores/contrib/oracle_offline_store/oracle_source.py new file mode 100644 index 00000000000..cb2de89538e --- /dev/null +++ b/sdk/python/feast/infra/offline_stores/contrib/oracle_offline_store/oracle_source.py @@ -0,0 +1,193 @@ +import json +from typing import Callable, Dict, Iterable, Optional, Tuple + +from feast import type_map +from feast.data_source import DataSource +from feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto +from feast.repo_config import RepoConfig +from feast.value_type import ValueType + + +class OracleOptions: + """ + DataSource Oracle options used to source features from an Oracle database. + """ + + def __init__( + self, + table_ref: Optional[str], + ): + self._table_ref = table_ref + + @property + def table_ref(self): + """Returns the table ref of this Oracle source""" + return self._table_ref + + @table_ref.setter + def table_ref(self, table_ref): + """Sets the table ref of this Oracle source""" + self._table_ref = table_ref + + @classmethod + def from_proto( + cls, oracle_options_proto: DataSourceProto.CustomSourceOptions + ) -> "OracleOptions": + """ + Creates an OracleOptions from a protobuf representation. + + Args: + oracle_options_proto: A protobuf representation of a DataSource + + Returns: + An OracleOptions object based on the protobuf + """ + options = json.loads(oracle_options_proto.configuration) + return cls(table_ref=options.get("table_ref")) + + def to_proto(self) -> DataSourceProto.CustomSourceOptions: + """ + Converts an OracleOptions object to its protobuf representation. + + Returns: + CustomSourceOptions protobuf + """ + return DataSourceProto.CustomSourceOptions( + configuration=json.dumps({"table_ref": self._table_ref}).encode("utf-8") + ) + + +class OracleSource(DataSource): + """An OracleSource defines a data source backed by an Oracle database table.""" + + def source_type(self) -> DataSourceProto.SourceType.ValueType: + return DataSourceProto.CUSTOM_SOURCE + + def __init__( + self, + name: str, + table_ref: Optional[str] = None, + event_timestamp_column: Optional[str] = None, + created_timestamp_column: Optional[str] = "", + field_mapping: Optional[Dict[str, str]] = None, + date_partition_column: Optional[str] = "", + description: Optional[str] = None, + tags: Optional[Dict[str, str]] = None, + owner: Optional[str] = None, + ): + """Creates an OracleSource object. + + Args: + name: Name of the source, which should be unique within a project. + table_ref: The table reference (e.g., "TRANSACTION_FEATURES" or "SCHEMA.TABLE"). + event_timestamp_column: Event timestamp column for point-in-time joins. + created_timestamp_column: Timestamp column indicating when the row was created + (used for deduplicating rows). + field_mapping: A dictionary mapping column names in this data source to feature + names in a feature table or view. + date_partition_column: The date partition column. + description: A human-readable description. + tags: A dictionary of key-value pairs to store arbitrary metadata. + owner: The owner of the data source, typically the email of the primary maintainer. + """ + self._oracle_options = OracleOptions(table_ref=table_ref) + + super().__init__( + created_timestamp_column=created_timestamp_column, + field_mapping=field_mapping, + date_partition_column=date_partition_column, + description=description, + tags=tags, + owner=owner, + name=name, + timestamp_field=event_timestamp_column, + ) + + def __eq__(self, other): + if not isinstance(other, OracleSource): + raise TypeError( + "Comparisons should only involve OracleSource class objects." + ) + + return ( + self.name == other.name + and self._oracle_options.table_ref == other._oracle_options.table_ref + and self.timestamp_field == other.timestamp_field + and self.created_timestamp_column == other.created_timestamp_column + and self.field_mapping == other.field_mapping + ) + + def __hash__(self): + return hash( + ( + self.name, + self._oracle_options.table_ref, + self.timestamp_field, + self.created_timestamp_column, + ) + ) + + @property + def table_ref(self): + return self._oracle_options.table_ref + + @property + def oracle_options(self): + """Returns the Oracle options of this data source""" + return self._oracle_options + + @oracle_options.setter + def oracle_options(self, oracle_options): + """Sets the Oracle options of this data source""" + self._oracle_options = oracle_options + + @staticmethod + def from_proto(data_source: DataSourceProto): + options = json.loads(data_source.custom_options.configuration) + return OracleSource( + name=data_source.name, + field_mapping=dict(data_source.field_mapping), + table_ref=options.get("table_ref"), + event_timestamp_column=data_source.timestamp_field, + created_timestamp_column=data_source.created_timestamp_column, + date_partition_column=data_source.date_partition_column, + ) + + def _to_proto_impl(self) -> DataSourceProto: + data_source_proto = DataSourceProto( + type=DataSourceProto.CUSTOM_SOURCE, + data_source_class_type="feast.infra.offline_stores.contrib.oracle_offline_store.oracle_source.OracleSource", + field_mapping=self.field_mapping, + custom_options=self._oracle_options.to_proto(), + ) + + data_source_proto.timestamp_field = self.timestamp_field + data_source_proto.created_timestamp_column = self.created_timestamp_column + data_source_proto.date_partition_column = self.date_partition_column + data_source_proto.name = self.name + return data_source_proto + + def get_table_query_string(self) -> str: + """Returns a string that can directly be used to reference this table in SQL""" + return f"{self.table_ref}" + + def validate(self, config: RepoConfig): + """Validates the Oracle data source by checking the table exists.""" + self.get_table_column_names_and_types(config) + + @staticmethod + def source_datatype_to_feast_value_type() -> Callable[[str], ValueType]: + return type_map.oracle_to_feast_value_type + + def get_table_column_names_and_types( + self, config: RepoConfig + ) -> Iterable[Tuple[str, str]]: + from feast.infra.offline_stores.contrib.oracle_offline_store.oracle import ( + get_ibis_connection, + ) + + con = get_ibis_connection(config) + + schema = con.get_schema(self.table_ref) + + return [(col_name, str(col_type)) for col_name, col_type in schema.items()] diff --git a/sdk/python/feast/infra/offline_stores/contrib/postgres_offline_store/postgres.py b/sdk/python/feast/infra/offline_stores/contrib/postgres_offline_store/postgres.py index 7c65b649046..50e48208647 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/postgres_offline_store/postgres.py +++ b/sdk/python/feast/infra/offline_stores/contrib/postgres_offline_store/postgres.py @@ -1,6 +1,6 @@ import contextlib from dataclasses import asdict -from datetime import datetime, timedelta, timezone +from datetime import datetime, timezone from enum import Enum from typing import ( Any, @@ -46,7 +46,7 @@ from feast.repo_config import RepoConfig from feast.saved_dataset import SavedDatasetStorage from feast.type_map import pg_type_code_to_arrow -from feast.utils import _utc_now, make_tzaware +from feast.utils import compute_non_entity_date_range from .postgres_source import PostgreSQLSource @@ -129,43 +129,17 @@ def get_historical_features( assert isinstance(config.offline_store, PostgreSQLOfflineStoreConfig) for fv in feature_views: assert isinstance(fv.batch_source, PostgreSQLSource) - start_date: Optional[datetime] = kwargs.get("start_date", None) - end_date: Optional[datetime] = kwargs.get("end_date", None) + start_date: Optional[datetime] = kwargs.get("start_date") + end_date: Optional[datetime] = kwargs.get("end_date") # Handle non-entity retrieval mode if entity_df is None: - # Default to current time if end_date not provided - if end_date is None: - end_date = _utc_now() - else: - end_date = make_tzaware(end_date) - - # Calculate start_date from TTL if not provided - - if start_date is None: - # Find the maximum TTL across all feature views to ensure we capture enough data - max_ttl_seconds = 0 - for fv in feature_views: - if fv.ttl and isinstance(fv.ttl, timedelta): - ttl_seconds = int(fv.ttl.total_seconds()) - max_ttl_seconds = max(max_ttl_seconds, ttl_seconds) - - if max_ttl_seconds > 0: - # Start from (end_date - max_ttl) to ensure we capture all relevant features - start_date = end_date - timedelta(seconds=max_ttl_seconds) - else: - # If no TTL is set, default to 30 days before end_date - start_date = end_date - timedelta(days=30) - else: - start_date = make_tzaware(start_date) - - entity_df = pd.DataFrame( - { - "event_timestamp": pd.date_range( - start=start_date, end=end_date, freq="1s", tz=timezone.utc - )[:1] # Just one row - } + start_date, end_date = compute_non_entity_date_range( + feature_views, + start_date=start_date, + end_date=end_date, ) + entity_df = pd.DataFrame({"event_timestamp": [end_date]}) entity_schema = _get_entity_schema(entity_df, config) @@ -173,11 +147,18 @@ def get_historical_features( offline_utils.infer_event_timestamp_from_entity_df(entity_schema) ) - entity_df_event_timestamp_range = _get_entity_df_event_timestamp_range( - entity_df, - entity_df_event_timestamp_col, - config, - ) + # In non-entity mode, use the actual requested range so that + # min_event_timestamp (= range[0] - TTL) doesn't clip the window. + # The synthetic entity_df only has end_date, which would wrongly + # set min_event_timestamp to end_date - TTL instead of start_date - TTL. + if start_date is not None and end_date is not None: + entity_df_event_timestamp_range = (start_date, end_date) + else: + entity_df_event_timestamp_range = _get_entity_df_event_timestamp_range( + entity_df, + entity_df_event_timestamp_col, + config, + ) @contextlib.contextmanager def query_generator() -> Iterator[str]: diff --git a/sdk/python/feast/infra/offline_stores/contrib/postgres_offline_store/tests/data_source.py b/sdk/python/feast/infra/offline_stores/contrib/postgres_offline_store/tests/data_source.py index c94b04329e0..273ae22cf54 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/postgres_offline_store/tests/data_source.py +++ b/sdk/python/feast/infra/offline_stores/contrib/postgres_offline_store/tests/data_source.py @@ -14,10 +14,10 @@ ) from feast.infra.utils.postgres.connection_utils import df_to_postgres_table from feast.infra.utils.postgres.postgres_config import PostgreSQLConfig -from tests.integration.feature_repos.universal.data_source_creator import ( +from tests.universal.feature_repos.universal.data_source_creator import ( DataSourceCreator, ) -from tests.integration.feature_repos.universal.online_store_creator import ( +from tests.universal.feature_repos.universal.online_store_creator import ( OnlineStoreCreator, ) @@ -85,6 +85,7 @@ def __init__( db_schema="public", user=self.container.env["POSTGRES_USER"], password=self.container.env["POSTGRES_PASSWORD"], + sslmode="disable", ) def create_data_source( @@ -124,6 +125,7 @@ def create_online_store(self) -> PostgreSQLOnlineStoreConfig: # type: ignore db_schema="feature_store", user=POSTGRES_USER, password=POSTGRES_PASSWORD, + sslmode="disable", ) def create_saved_dataset_destination(self): diff --git a/sdk/python/feast/infra/offline_stores/contrib/postgres_repo_configuration.py b/sdk/python/feast/infra/offline_stores/contrib/postgres_repo_configuration.py index 2fa08bf47ad..4595fb89836 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/postgres_repo_configuration.py +++ b/sdk/python/feast/infra/offline_stores/contrib/postgres_repo_configuration.py @@ -1,8 +1,8 @@ from feast.infra.offline_stores.contrib.postgres_offline_store.tests.data_source import ( PostgreSQLDataSourceCreator, ) -from tests.integration.feature_repos.repo_configuration import REDIS_CONFIG -from tests.integration.feature_repos.universal.online_store.redis import ( +from tests.universal.feature_repos.repo_configuration import REDIS_CONFIG +from tests.universal.feature_repos.universal.online_store.redis import ( RedisOnlineStoreCreator, ) diff --git a/sdk/python/feast/infra/offline_stores/contrib/ray_offline_store/ray.py b/sdk/python/feast/infra/offline_stores/contrib/ray_offline_store/ray.py index bc7c60733b4..47785ccea29 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/ray_offline_store/ray.py +++ b/sdk/python/feast/infra/offline_stores/contrib/ray_offline_store/ray.py @@ -1,7 +1,7 @@ import logging import os import uuid -from datetime import datetime, timedelta +from datetime import datetime from pathlib import Path from typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Union @@ -59,7 +59,12 @@ feast_value_type_to_pandas_type, pa_to_feast_value_type, ) -from feast.utils import _get_column_names, make_df_tzaware, make_tzaware +from feast.utils import ( + _get_column_names, + compute_non_entity_date_range, + make_df_tzaware, + make_tzaware, +) logger = logging.getLogger(__name__) # Remote storage URI schemes supported by the Ray offline store @@ -1203,37 +1208,6 @@ def schema(self) -> pa.Schema: return pa.Table.from_pandas(df).schema -def _compute_non_entity_dates_ray( - feature_views: List[FeatureView], - start_date_opt: Optional[datetime], - end_date_opt: Optional[datetime], -) -> Tuple[datetime, datetime]: - # Why: derive bounded time window when no entity_df is provided using explicit dates or max TTL fallback - end_date = ( - make_tzaware(end_date_opt) if end_date_opt else make_tzaware(datetime.utcnow()) - ) - if start_date_opt is None: - max_ttl_seconds = 0 - for fv in feature_views: - if getattr(fv, "ttl", None): - try: - ttl_val = fv.ttl - if isinstance(ttl_val, timedelta): - max_ttl_seconds = max( - max_ttl_seconds, int(ttl_val.total_seconds()) - ) - except Exception: - pass - start_date = ( - end_date - timedelta(seconds=max_ttl_seconds) - if max_ttl_seconds > 0 - else end_date - timedelta(days=30) - ) - else: - start_date = make_tzaware(start_date_opt) - return start_date, end_date - - def _make_filter_range(timestamp_field: str, start_date: datetime, end_date: datetime): # Why: factory function for time-range filtering in Ray map_batches def _filter_range(batch: pd.DataFrame) -> pd.Series: @@ -2067,8 +2041,10 @@ def get_historical_features( # Non-entity mode: derive entity set from feature sources within a bounded time window # Preserves distinct (entity_keys, event_timestamp) combinations for proper PIT joins # This handles cases where multiple transactions per entity ID exist - start_date, end_date = _compute_non_entity_dates_ray( - feature_views, kwargs.get("start_date"), kwargs.get("end_date") + start_date, end_date = compute_non_entity_date_range( + feature_views, + start_date=kwargs.get("start_date"), + end_date=kwargs.get("end_date"), ) per_view_entity_ds: List[Dataset] = [] all_join_keys: List[str] = [] @@ -2168,7 +2144,7 @@ def get_historical_features( # Build reverse field mapping to get actual source column names reverse_field_mapping = {} - if fv.batch_source.field_mapping: + if fv.batch_source is not None and fv.batch_source.field_mapping: reverse_field_mapping = { v: k for k, v in fv.batch_source.field_mapping.items() } diff --git a/sdk/python/feast/infra/offline_stores/contrib/ray_offline_store/tests/test_ray_integration.py b/sdk/python/feast/infra/offline_stores/contrib/ray_offline_store/tests/test_ray_integration.py deleted file mode 100644 index 0420054b8fb..00000000000 --- a/sdk/python/feast/infra/offline_stores/contrib/ray_offline_store/tests/test_ray_integration.py +++ /dev/null @@ -1,271 +0,0 @@ -from datetime import timedelta - -import pandas as pd -import pytest - -from feast.utils import _utc_now -from tests.integration.feature_repos.repo_configuration import ( - construct_universal_feature_views, -) -from tests.integration.feature_repos.universal.entities import driver - - -@pytest.mark.integration -@pytest.mark.universal_offline_stores -def test_ray_offline_store_basic_write_and_read(environment, universal_data_sources): - """Test basic write and read functionality with Ray offline store.""" - store = environment.feature_store - _, _, data_sources = universal_data_sources - feature_views = construct_universal_feature_views(data_sources) - driver_fv = feature_views.driver - store.apply([driver(), driver_fv]) - - now = _utc_now() - ts = pd.Timestamp(now).round("ms") - - # Write data to offline store - df_to_write = pd.DataFrame.from_dict( - { - "event_timestamp": [ts, ts], - "driver_id": [1001, 1002], - "conv_rate": [0.1, 0.2], - "acc_rate": [0.9, 0.8], - "avg_daily_trips": [10, 20], - "created": [ts, ts], - }, - ) - - store.write_to_offline_store( - driver_fv.name, df_to_write, allow_registry_cache=False - ) - - # Read data back - entity_df = pd.DataFrame({"driver_id": [1001, 1002], "event_timestamp": [ts, ts]}) - - result_df = store.get_historical_features( - entity_df=entity_df, - features=[ - "driver_stats:conv_rate", - "driver_stats:acc_rate", - "driver_stats:avg_daily_trips", - ], - full_feature_names=False, - ).to_df() - - assert len(result_df) == 2 - assert "conv_rate" in result_df.columns - assert "acc_rate" in result_df.columns - assert "avg_daily_trips" in result_df.columns - - -@pytest.mark.integration -@pytest.mark.universal_offline_stores -@pytest.mark.parametrize("full_feature_names", [True, False], ids=lambda v: f"full:{v}") -def test_ray_offline_store_historical_features( - environment, universal_data_sources, full_feature_names -): - """Test historical features retrieval with Ray offline store.""" - store = environment.feature_store - - (entities, datasets, data_sources) = universal_data_sources - feature_views = construct_universal_feature_views(data_sources) - - entity_df_with_request_data = datasets.entity_df.copy(deep=True) - entity_df_with_request_data["val_to_add"] = [ - i for i in range(len(entity_df_with_request_data)) - ] - - store.apply( - [ - driver(), - *feature_views.values(), - ] - ) - - job = store.get_historical_features( - entity_df=entity_df_with_request_data, - features=[ - "driver_stats:conv_rate", - "driver_stats:avg_daily_trips", - "customer_profile:current_balance", - "conv_rate_plus_100:conv_rate_plus_100", - ], - full_feature_names=full_feature_names, - ) - - # Test DataFrame conversion - result_df = job.to_df() - assert len(result_df) > 0 - assert "event_timestamp" in result_df.columns - - # Test Arrow conversion - result_table = job.to_arrow().to_pandas() - assert len(result_table) > 0 - assert "event_timestamp" in result_table.columns - - -@pytest.mark.integration -@pytest.mark.universal_offline_stores -def test_ray_offline_store_persist(environment, universal_data_sources): - """Test dataset persistence with Ray offline store.""" - store = environment.feature_store - - (entities, datasets, data_sources) = universal_data_sources - feature_views = construct_universal_feature_views(data_sources) - - entity_df_with_request_data = datasets.entity_df.copy(deep=True) - entity_df_with_request_data["val_to_add"] = [ - i for i in range(len(entity_df_with_request_data)) - ] - - store.apply( - [ - driver(), - *feature_views.values(), - ] - ) - - job = store.get_historical_features( - entity_df=entity_df_with_request_data, - features=[ - "driver_stats:conv_rate", - "customer_profile:current_balance", - ], - full_feature_names=False, - ) - - # Test persisting the dataset - from feast.saved_dataset import SavedDatasetFileStorage - - storage = SavedDatasetFileStorage(path="data/test_saved_dataset.parquet") - saved_path = job.persist(storage, allow_overwrite=True) - - assert saved_path == "data/test_saved_dataset.parquet" - - # Verify the saved dataset exists - import os - - assert os.path.exists(saved_path) - - -@pytest.mark.integration -@pytest.mark.universal_offline_stores -def test_ray_offline_store_non_entity_mode_basic(environment, universal_data_sources): - """Test historical features retrieval without entity_df (non-entity mode). - - This tests the basic functionality where entity_df=None and start_date/end_date - are provided to retrieve all features within the time range. - """ - store = environment.feature_store - - (entities, datasets, data_sources) = universal_data_sources - feature_views = construct_universal_feature_views(data_sources) - - store.apply( - [ - driver(), - feature_views.driver, - ] - ) - - # Use the environment's start and end dates for the query - start_date = environment.start_date - end_date = environment.end_date - - # Non-entity mode: entity_df=None with start_date and end_date - result_df = store.get_historical_features( - entity_df=None, - features=[ - "driver_stats:conv_rate", - "driver_stats:acc_rate", - "driver_stats:avg_daily_trips", - ], - full_feature_names=False, - start_date=start_date, - end_date=end_date, - ).to_df() - - # Verify data was retrieved - assert len(result_df) > 0, "Non-entity mode should return data" - assert "conv_rate" in result_df.columns - assert "acc_rate" in result_df.columns - assert "avg_daily_trips" in result_df.columns - assert "event_timestamp" in result_df.columns - assert "driver_id" in result_df.columns - - # Verify timestamps are within the requested range - result_df["event_timestamp"] = pd.to_datetime( - result_df["event_timestamp"], utc=True - ) - assert (result_df["event_timestamp"] >= start_date).all() - assert (result_df["event_timestamp"] <= end_date).all() - - -@pytest.mark.integration -@pytest.mark.universal_offline_stores -def test_ray_offline_store_non_entity_mode_preserves_multiple_timestamps( - environment, universal_data_sources -): - """Test that non-entity mode preserves multiple transactions per entity ID. - - This is a regression test for the fix that ensures distinct (entity_key, event_timestamp) - combinations are preserved, not just distinct entity keys. This is critical for - proper point-in-time joins when an entity has multiple transactions. - """ - store = environment.feature_store - - (entities, datasets, data_sources) = universal_data_sources - feature_views = construct_universal_feature_views(data_sources) - - store.apply( - [ - driver(), - feature_views.driver, - ] - ) - - now = _utc_now() - ts1 = pd.Timestamp(now - timedelta(hours=2)).round("ms") - ts2 = pd.Timestamp(now - timedelta(hours=1)).round("ms") - ts3 = pd.Timestamp(now).round("ms") - - # Write data with multiple timestamps for the same entity (driver_id=9001) - df_to_write = pd.DataFrame.from_dict( - { - "event_timestamp": [ts1, ts2, ts3], - "driver_id": [9001, 9001, 9001], # Same entity, different timestamps - "conv_rate": [0.1, 0.2, 0.3], - "acc_rate": [0.9, 0.8, 0.7], - "avg_daily_trips": [10, 20, 30], - "created": [ts1, ts2, ts3], - }, - ) - - store.write_to_offline_store( - feature_views.driver.name, df_to_write, allow_registry_cache=False - ) - - # Query without entity_df - should get all 3 rows for driver_id=9001 - result_df = store.get_historical_features( - entity_df=None, - features=[ - "driver_stats:conv_rate", - "driver_stats:acc_rate", - ], - full_feature_names=False, - start_date=ts1 - timedelta(minutes=1), - end_date=ts3 + timedelta(minutes=1), - ).to_df() - - # Filter to just our test entity - result_df = result_df[result_df["driver_id"] == 9001] - - # Verify we got all 3 rows with different timestamps (not just 1 row) - assert len(result_df) == 3, ( - f"Expected 3 rows for driver_id=9001 (one per timestamp), got {len(result_df)}" - ) - - # Verify the feature values are correct for each timestamp - result_df = result_df.sort_values("event_timestamp").reset_index(drop=True) - assert list(result_df["conv_rate"]) == [0.1, 0.2, 0.3] - assert list(result_df["acc_rate"]) == [0.9, 0.8, 0.7] diff --git a/sdk/python/feast/infra/offline_stores/contrib/ray_repo_configuration.py b/sdk/python/feast/infra/offline_stores/contrib/ray_repo_configuration.py index 6e1fa66b102..fcab38a0eb9 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/ray_repo_configuration.py +++ b/sdk/python/feast/infra/offline_stores/contrib/ray_repo_configuration.py @@ -15,10 +15,10 @@ ) from feast.repo_config import FeastConfigBaseModel from feast.saved_dataset import SavedDatasetStorage -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) -from tests.integration.feature_repos.universal.data_source_creator import ( +from tests.universal.feature_repos.universal.data_source_creator import ( DataSourceCreator, ) diff --git a/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/spark.py b/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/spark.py index af83d303504..c7ed40ccc02 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/spark.py +++ b/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/spark.py @@ -3,7 +3,7 @@ import uuid import warnings from dataclasses import asdict, dataclass -from datetime import datetime, timedelta, timezone +from datetime import datetime, timezone from typing import ( TYPE_CHECKING, Any, @@ -52,7 +52,7 @@ from feast.repo_config import FeastConfigBaseModel, RepoConfig from feast.saved_dataset import SavedDatasetStorage from feast.type_map import spark_schema_to_np_dtypes -from feast.utils import _get_fields_with_aliases +from feast.utils import _get_fields_with_aliases, compute_non_entity_date_range # Make sure spark warning doesn't raise more than once. warnings.simplefilter("once", RuntimeWarning) @@ -183,8 +183,11 @@ def get_historical_features( # This makes date-range retrievals possible without enumerating entities upfront; sources remain bounded by time. non_entity_mode = entity_df is None if non_entity_mode: - # Why: derive bounded time window without requiring entities; uses max TTL fallback to constrain scans. - start_date, end_date = _compute_non_entity_dates(feature_views, kwargs) + start_date, end_date = compute_non_entity_date_range( + feature_views, + start_date=kwargs.get("start_date"), + end_date=kwargs.get("end_date"), + ) entity_df_event_timestamp_range = (start_date, end_date) # Build query contexts so we can reuse entity names and per-view table info consistently. @@ -619,29 +622,6 @@ def get_spark_session_or_start_new_with_repoconfig( return spark_session -def _compute_non_entity_dates( - feature_views: List[FeatureView], kwargs: Dict[str, Any] -) -> Tuple[datetime, datetime]: - # Why: bounds the scan window when no entity_df is provided using explicit dates or max TTL fallback. - start_date_opt = cast(Optional[datetime], kwargs.get("start_date")) - end_date_opt = cast(Optional[datetime], kwargs.get("end_date")) - end_date: datetime = end_date_opt or datetime.now(timezone.utc) - - if start_date_opt is None: - max_ttl_seconds = 0 - for fv in feature_views: - if fv.ttl and isinstance(fv.ttl, timedelta): - max_ttl_seconds = max(max_ttl_seconds, int(fv.ttl.total_seconds())) - start_date: datetime = ( - end_date - timedelta(seconds=max_ttl_seconds) - if max_ttl_seconds > 0 - else end_date - timedelta(days=30) - ) - else: - start_date = start_date_opt - return (start_date, end_date) - - def _gather_all_entities( fv_query_contexts: List[offline_utils.FeatureViewQueryContext], ) -> List[str]: diff --git a/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/tests/data_source.py b/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/tests/data_source.py index b723037f1f3..e25ebd4e1df 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/tests/data_source.py +++ b/sdk/python/feast/infra/offline_stores/contrib/spark_offline_store/tests/data_source.py @@ -17,7 +17,7 @@ SavedDatasetSparkStorage, SparkSource, ) -from tests.integration.feature_repos.universal.data_source_creator import ( +from tests.universal.feature_repos.universal.data_source_creator import ( DataSourceCreator, ) diff --git a/sdk/python/feast/infra/offline_stores/contrib/spark_repo_configuration.py b/sdk/python/feast/infra/offline_stores/contrib/spark_repo_configuration.py index ec414f202ae..aaf56d51981 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/spark_repo_configuration.py +++ b/sdk/python/feast/infra/offline_stores/contrib/spark_repo_configuration.py @@ -1,8 +1,8 @@ from feast.infra.offline_stores.contrib.spark_offline_store.tests.data_source import ( SparkDataSourceCreator, ) -from tests.integration.feature_repos.repo_configuration import REDIS_CONFIG -from tests.integration.feature_repos.universal.online_store.redis import ( +from tests.universal.feature_repos.repo_configuration import REDIS_CONFIG +from tests.universal.feature_repos.universal.online_store.redis import ( RedisOnlineStoreCreator, ) diff --git a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/test_config/manual_tests.py b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/test_config/manual_tests.py index a31d368ea11..d658d0d0eb9 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/test_config/manual_tests.py +++ b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/test_config/manual_tests.py @@ -1,7 +1,7 @@ from feast.infra.offline_stores.contrib.trino_offline_store.tests.data_source import ( TrinoSourceCreator, ) -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) diff --git a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/tests/data_source.py b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/tests/data_source.py index c8fc15a6350..9a297a32e1e 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/tests/data_source.py +++ b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/tests/data_source.py @@ -20,7 +20,7 @@ TrinoSource, ) from feast.repo_config import FeastConfigBaseModel -from tests.integration.feature_repos.universal.data_source_creator import ( +from tests.universal.feature_repos.universal.data_source_creator import ( DataSourceCreator, ) diff --git a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino.py b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino.py index 62f94f54073..33190bd4635 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino.py +++ b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino.py @@ -116,7 +116,7 @@ def to_trino_auth(self): model_cls = CLASSES_BY_AUTH_TYPE[auth_type]["auth_model"] model = model_cls(**self.config) - return trino_auth_cls(**model.dict()) + return trino_auth_cls(**model.model_dump()) class TrinoOfflineStoreConfig(FeastConfigBaseModel): diff --git a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino_queries.py b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino_queries.py index 3a26583af24..302745fc0e9 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino_queries.py +++ b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino_queries.py @@ -9,6 +9,7 @@ import pandas as pd import pyarrow as pa import trino +import trino.auth from trino.dbapi import Cursor from trino.exceptions import TrinoQueryError @@ -37,7 +38,7 @@ def __init__( http_scheme: str, verify: bool, extra_credential: Optional[str], - auth: Optional[trino.Authentication], + auth: Optional[trino.auth.Authentication], ): self.host = host self.port = port @@ -106,7 +107,9 @@ def execute(self) -> Results: self.execution_time = end_time - start_time self.status = QueryStatus.COMPLETED - return Results(data=rows, columns=self._cursor._query.columns) + query = self._cursor._query + assert query is not None, "Cursor query should not be None after execute" + return Results(data=rows, columns=query.columns) except TrinoQueryError as error: self.status = QueryStatus.ERROR raise error diff --git a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino_type_map.py b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino_type_map.py index e5afa3f3ab3..a11298e9b81 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino_type_map.py +++ b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino_type_map.py @@ -69,6 +69,15 @@ def pa_to_trino_value_type(pa_type_as_str: str) -> str: if pa_type_as_str.startswith("decimal"): return trino_type.format(pa_type_as_str) + if pa_type_as_str.startswith("map<"): + return trino_type.format("varchar") + + if pa_type_as_str == "large_string": + return trino_type.format("varchar") + + if pa_type_as_str.startswith("struct<"): + return trino_type.format("varchar") + type_map = { "null": "null", "bool": "boolean", diff --git a/sdk/python/feast/infra/offline_stores/contrib/trino_repo_configuration.py b/sdk/python/feast/infra/offline_stores/contrib/trino_repo_configuration.py index 198227095d5..64a5507876c 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/trino_repo_configuration.py +++ b/sdk/python/feast/infra/offline_stores/contrib/trino_repo_configuration.py @@ -1,8 +1,8 @@ from feast.infra.offline_stores.contrib.trino_offline_store.tests.data_source import ( TrinoSourceCreator, ) -from tests.integration.feature_repos.repo_configuration import REDIS_CONFIG -from tests.integration.feature_repos.universal.online_store.redis import ( +from tests.universal.feature_repos.repo_configuration import REDIS_CONFIG +from tests.universal.feature_repos.universal.online_store.redis import ( RedisOnlineStoreCreator, ) diff --git a/sdk/python/feast/infra/offline_stores/dask.py b/sdk/python/feast/infra/offline_stores/dask.py index 809fbf4091d..be430f87c90 100644 --- a/sdk/python/feast/infra/offline_stores/dask.py +++ b/sdk/python/feast/infra/offline_stores/dask.py @@ -1,6 +1,6 @@ import os import uuid -from datetime import datetime, timedelta, timezone +from datetime import datetime, timezone from pathlib import Path from typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Union @@ -37,7 +37,10 @@ from feast.on_demand_feature_view import OnDemandFeatureView from feast.repo_config import FeastConfigBaseModel, RepoConfig from feast.saved_dataset import SavedDatasetStorage -from feast.utils import _get_requested_feature_views_to_features_dict, make_tzaware +from feast.utils import ( + _get_requested_feature_views_to_features_dict, + compute_non_entity_date_range, +) # DaskRetrievalJob will cast string objects to string[pyarrow] from dask version 2023.7.1 # This is not the desired behavior for our use case, so we set the convert-string option to False @@ -143,36 +146,14 @@ def get_historical_features( for fv in feature_views: assert isinstance(fv.batch_source, FileSource) - # Allow non-entity mode using start/end timestamps to enable bounded retrievals without an input entity_df. - # This synthesizes a minimal entity_df solely to drive the existing join and metadata plumbing without - # incurring source scans here; actual pushdowns can be layered in follow-ups if needed. - start_date: Optional[datetime] = kwargs.get("start_date", None) - end_date: Optional[datetime] = kwargs.get("end_date", None) non_entity_mode = entity_df is None if non_entity_mode: - # Default end_date to current time (UTC) to keep behavior predictable without extra parameters. - end_date = ( - make_tzaware(end_date) if end_date else datetime.now(timezone.utc) + start_date, end_date = compute_non_entity_date_range( + feature_views, + start_date=kwargs.get("start_date"), + end_date=kwargs.get("end_date"), ) - - # When start_date is not provided, choose a conservative lower bound using max TTL, otherwise fall back. - if start_date is None: - max_ttl_seconds = 0 - for fv in feature_views: - if fv.ttl and isinstance(fv.ttl, timedelta): - max_ttl_seconds = max( - max_ttl_seconds, int(fv.ttl.total_seconds()) - ) - if max_ttl_seconds > 0: - start_date = end_date - timedelta(seconds=max_ttl_seconds) - else: - # Keep default window bounded to avoid unbounded scans by default. - start_date = end_date - timedelta(days=30) - start_date = make_tzaware(start_date) - - # Minimal synthetic entity_df: one timestamp row; join keys are not materialized here on purpose to avoid - # accidental dependence on specific feature view schemas at this layer. entity_df = pd.DataFrame( {DEFAULT_ENTITY_DF_EVENT_TIMESTAMP_COL: [end_date]} ) @@ -656,7 +637,10 @@ def _field_mapping( full_feature_names: bool, ) -> Tuple[dd.DataFrame, str]: # Rename columns by the field mapping dictionary if it exists - if feature_view.batch_source.field_mapping: + if ( + feature_view.batch_source is not None + and feature_view.batch_source.field_mapping + ): df_to_join = _run_dask_field_mapping( df_to_join, feature_view.batch_source.field_mapping ) diff --git a/sdk/python/feast/infra/offline_stores/file_source.py b/sdk/python/feast/infra/offline_stores/file_source.py index 02d40ad770b..76460a73e5c 100644 --- a/sdk/python/feast/infra/offline_stores/file_source.py +++ b/sdk/python/feast/infra/offline_stores/file_source.py @@ -1,3 +1,4 @@ +import logging from pathlib import Path from typing import Callable, Dict, Iterable, List, Optional, Tuple, Union from urllib.parse import urlparse @@ -24,6 +25,8 @@ from feast.saved_dataset import SavedDatasetStorage from feast.value_type import ValueType +logger = logging.getLogger(__name__) + @typechecked class FileSource(DataSource): @@ -151,8 +154,43 @@ def _to_proto_impl(self) -> DataSourceProto: return data_source_proto def validate(self, config: RepoConfig): - # TODO: validate a FileSource - pass + """Validate that the file source exists and is readable. + + Checks that the path resolves to an existing Parquet or Delta file + and that the declared timestamp column is present in the schema. + """ + from feast.infra.offline_stores.file_source import FileSource + + uri = self.path + repo_path = config.repo_path if hasattr(config, "repo_path") else None + resolved = FileSource.get_uri_for_file_path(repo_path, uri) + + try: + filesystem, path = FileSystem.from_uri(resolved) + file_info = filesystem.get_file_info(path) + if file_info.type == pyarrow.fs.FileType.NotFound: + raise FileNotFoundError(f"FileSource path does not exist: {resolved}") + except Exception as e: + logger.warning("Could not validate FileSource path '%s': %s", resolved, e) + return + + try: + if isinstance(self.file_options.file_format, DeltaFormat): + return + pq_dataset = ParquetDataset(path, filesystem=filesystem) + schema = pq_dataset.schema + if self.timestamp_field and self.timestamp_field not in schema.names: + logger.warning( + "Timestamp field '%s' not found in FileSource schema at '%s'. " + "Available columns: %s", + self.timestamp_field, + resolved, + schema.names, + ) + except Exception as e: + logger.warning( + "Could not read schema from FileSource '%s': %s", resolved, e + ) @staticmethod def source_datatype_to_feast_value_type() -> Callable[[str], ValueType]: diff --git a/sdk/python/feast/infra/offline_stores/hybrid_offline_store.py b/sdk/python/feast/infra/offline_stores/hybrid_offline_store.py index b37877276c9..a52f560952a 100644 --- a/sdk/python/feast/infra/offline_stores/hybrid_offline_store.py +++ b/sdk/python/feast/infra/offline_stores/hybrid_offline_store.py @@ -72,6 +72,8 @@ def _get_offline_store_for_feature_view( self, feature_view: FeatureView, config: RepoConfig ) -> OfflineStore: self._initialize_offline_stores(config) + if feature_view.batch_source is None: + raise ValueError(f"Feature view '{feature_view.name}' has no batch_source.") source_type = feature_view.batch_source.source_type() store_key = self.get_source_key_from_type(source_type) if store_key is None: diff --git a/sdk/python/feast/infra/offline_stores/ibis.py b/sdk/python/feast/infra/offline_stores/ibis.py index 9d8891036fe..e7e94af31e4 100644 --- a/sdk/python/feast/infra/offline_stores/ibis.py +++ b/sdk/python/feast/infra/offline_stores/ibis.py @@ -130,7 +130,7 @@ def _generate_row_id( else: all_entities.extend([e.name for e in fv.entity_columns]) - r = ibis.literal("") + r = ibis.literal("_") for e in set(all_entities): r = r.concat(entity_table[e].cast("string")) # type: ignore @@ -174,6 +174,10 @@ def get_historical_features_ibis( def read_fv( feature_view: FeatureView, feature_refs: List[str], full_feature_names: bool ) -> Tuple: + if feature_view.batch_source is None: + raise ValueError( + f"Feature view '{feature_view.name}' has no batch_source and cannot be queried." + ) fv_table: Table = data_source_reader( feature_view.batch_source, str(config.repo_path) ) @@ -193,7 +197,7 @@ def read_fv( } ) - full_name_prefix = feature_view.projection.name_alias or feature_view.name + full_name_prefix = feature_view.projection.name_to_use() feature_refs = [ fr.split(":")[1] @@ -201,13 +205,16 @@ def read_fv( if fr.startswith(f"{full_name_prefix}:") ] + # Use base name (without version) for column naming + base_name_prefix = feature_view.projection.name_alias or feature_view.name + if full_feature_names: fv_table = fv_table.rename( - {f"{full_name_prefix}__{feature}": feature for feature in feature_refs} + {f"{base_name_prefix}__{feature}": feature for feature in feature_refs} ) feature_refs = [ - f"{full_name_prefix}__{feature}" for feature in feature_refs + f"{base_name_prefix}__{feature}" for feature in feature_refs ] return ( @@ -335,6 +342,8 @@ def offline_write_batch_ibis( progress: Optional[Callable[[int], Any]], data_source_writer: Callable[[pyarrow.Table, DataSource, str], None], ): + if feature_view.batch_source is None: + raise ValueError(f"Feature view '{feature_view.name}' has no batch_source.") pa_schema, column_names = get_pyarrow_schema_from_batch_source( config, feature_view.batch_source ) @@ -383,7 +392,7 @@ def point_in_time_join( ) in feature_tables: all_entities.extend(join_key_map.values()) - r = ibis.literal("") + r = ibis.literal("_") for e in set(all_entities): r = r.concat(entity_table[e].cast("string")) # type: ignore @@ -413,7 +422,7 @@ def point_in_time_join( else: alias = "".join(random.choices(string.ascii_uppercase, k=10)) - feature_table = feature_table.alias(alias=alias).sql( + feature_table = feature_table.alias(alias).sql( f"SELECT *, {event_expire_timestamp_fn(timestamp_field, ttl)} AS event_expire_timestamp FROM {alias}" ) diff --git a/sdk/python/feast/infra/offline_stores/offline_store.py b/sdk/python/feast/infra/offline_stores/offline_store.py index 5961c1f4292..8887a5a7d0c 100644 --- a/sdk/python/feast/infra/offline_stores/offline_store.py +++ b/sdk/python/feast/infra/offline_stores/offline_store.py @@ -154,17 +154,59 @@ def to_arrow( """ features_table = self._to_arrow_internal(timeout=timeout) if self.on_demand_feature_views: + # Build a mapping of ODFV name to requested feature names + # This ensures we only return the features that were explicitly requested + odfv_feature_refs: Dict[str, set[str]] = {} + try: + metadata = self.metadata + except NotImplementedError: + metadata = None + + if metadata and metadata.features: + for feature_ref in metadata.features: + if ":" in feature_ref: + view_name, feature_name = feature_ref.split(":", 1) + # Check if this view_name matches any of the ODFVs + for odfv in self.on_demand_feature_views: + if ( + odfv.name == view_name + or odfv.projection.name_to_use() == view_name + ): + if view_name not in odfv_feature_refs: + odfv_feature_refs[view_name] = set() + # Store the feature name in the format that will appear in transformed_arrow + expected_col_name = ( + f"{odfv.projection.name_to_use()}__{feature_name}" + if self.full_feature_names + else feature_name + ) + odfv_feature_refs[view_name].add(expected_col_name) + for odfv in self.on_demand_feature_views: transformed_arrow = odfv.transform_arrow( features_table, self.full_feature_names ) + # Determine which columns to include from this ODFV + # If we have metadata with requested features, filter to only those + # Otherwise, include all columns (backward compatibility) + requested_features_for_odfv = ( + odfv_feature_refs.get(odfv.name) + if odfv.name in odfv_feature_refs + else odfv_feature_refs.get(odfv.projection.name_to_use()) + ) + for col in transformed_arrow.column_names: if col.startswith("__index"): continue - features_table = features_table.append_column( - col, transformed_arrow[col] - ) + # Only append the column if it was requested, or if we don't have feature metadata + if ( + requested_features_for_odfv is None + or col in requested_features_for_odfv + ): + features_table = features_table.append_column( + col, transformed_arrow[col] + ) if validation_reference: if not flags_helper.is_test(): diff --git a/sdk/python/feast/infra/offline_stores/offline_utils.py b/sdk/python/feast/infra/offline_stores/offline_utils.py index abd7ad4fe35..5664e6f45a6 100644 --- a/sdk/python/feast/infra/offline_stores/offline_utils.py +++ b/sdk/python/feast/infra/offline_stores/offline_utils.py @@ -1,3 +1,4 @@ +import logging import uuid from dataclasses import asdict, dataclass from datetime import datetime, timedelta, timezone @@ -21,6 +22,7 @@ from feast.repo_config import RepoConfig from feast.type_map import feast_value_type_to_pa from feast.utils import _get_requested_feature_views_to_features_dict, to_naive_utc +from feast.value_type import ValueType DEFAULT_ENTITY_DF_EVENT_TIMESTAMP_COL = "event_timestamp" @@ -118,6 +120,10 @@ def get_feature_view_query_context( query_context = [] for feature_view, features in feature_views_to_feature_map.items(): + if feature_view.batch_source is None: + raise ValueError( + f"Feature view '{feature_view.name}' has no batch_source and cannot be queried." + ) reverse_field_mapping = { v: k for k, v in feature_view.batch_source.field_mapping.items() } @@ -237,6 +243,37 @@ def get_offline_store_from_config(offline_store_config: Any) -> OfflineStore: return offline_store_class() +_PA_BASIC_TYPES = { + "int32": pa.int32(), + "int64": pa.int64(), + "double": pa.float64(), + "float": pa.float32(), + "string": pa.string(), + "binary": pa.binary(), + "bool": pa.bool_(), + "large_string": pa.large_string(), + "null": pa.null(), +} + + +def _parse_pa_type_str(pa_type_str: str) -> pa.DataType: + """Parse a PyArrow type string to preserve inner element types for nested lists.""" + pa_type_str = pa_type_str.strip() + if pa_type_str.startswith("list"): + inner = pa_type_str[len("list Tuple[pa.Schema, List[str]]: @@ -246,20 +283,48 @@ def get_pyarrow_schema_from_batch_source( pa_schema = [] column_names = [] for column_name, column_type in column_names_and_types: - pa_schema.append( - ( - column_name, - feast_value_type_to_pa( - batch_source.source_datatype_to_feast_value_type()(column_type), - timestamp_unit=timestamp_unit, - ), - ) - ) + value_type = batch_source.source_datatype_to_feast_value_type()(column_type) + if value_type in (ValueType.VALUE_LIST, ValueType.VALUE_SET): + pa_type = _parse_pa_type_str(column_type) + else: + pa_type = feast_value_type_to_pa(value_type, timestamp_unit=timestamp_unit) + pa_schema.append((column_name, pa_type)) column_names.append(column_name) return pa.schema(pa_schema), column_names +def cast_arrow_table_to_schema(table: pa.Table, pa_schema: pa.Schema) -> pa.Table: + """Cast a PyArrow table to match the target schema, handling struct/map → string. + + PyArrow cannot natively cast struct or map columns to string. When a + SQL-based offline store (BigQuery, Snowflake, Redshift) stores complex + Feast types (Map, Struct) as VARCHAR/STRING, the target schema will have + string fields while the input table may have struct/map fields (e.g. when + the caller provides Python dicts). This function serialises those columns + to JSON strings so the subsequent cast succeeds. + """ + import json as _json + + for i, field in enumerate(table.schema): + target_type = pa_schema.field(field.name).type + is_complex_source = pa.types.is_struct(field.type) or pa.types.is_map( + field.type + ) + is_string_target = pa.types.is_string(target_type) or pa.types.is_large_string( + target_type + ) + if is_complex_source and is_string_target: + col = table.column(i) + json_arr = pa.array( + [_json.dumps(v.as_py()) if v.is_valid else None for v in col], + type=target_type, + ) + table = table.set_column(i, field.name, json_arr) + + return table.cast(pa_schema) + + def enclose_in_backticks(value): # Check if the input is a list if isinstance(value, list): diff --git a/sdk/python/feast/infra/offline_stores/redshift.py b/sdk/python/feast/infra/offline_stores/redshift.py index 4ed8e6309c4..900dfcfab80 100644 --- a/sdk/python/feast/infra/offline_stores/redshift.py +++ b/sdk/python/feast/infra/offline_stores/redshift.py @@ -353,7 +353,7 @@ def offline_write_batch( ) if table.schema != pa_schema: - table = table.cast(pa_schema) + table = offline_utils.cast_arrow_table_to_schema(table, pa_schema) redshift_options = feature_view.batch_source.redshift_options redshift_client = aws_utils.get_redshift_data_client( diff --git a/sdk/python/feast/infra/offline_stores/remote.py b/sdk/python/feast/infra/offline_stores/remote.py index e0a1df573d4..4e48f225f16 100644 --- a/sdk/python/feast/infra/offline_stores/remote.py +++ b/sdk/python/feast/infra/offline_stores/remote.py @@ -12,7 +12,7 @@ import pyarrow.parquet from pyarrow import Schema from pyarrow._flight import FlightCallOptions, FlightDescriptor, Ticket -from pydantic import StrictInt, StrictStr +from pydantic import Field, StrictInt, StrictStr from feast import OnDemandFeatureView from feast.arrow_error_handler import arrow_client_error_handling_decorator @@ -42,6 +42,10 @@ class FeastFlightClient(fl.FlightClient): + def __init__(self, *args, connection_retries: int = 3, **kwargs): + super().__init__(*args, **kwargs) + self._connection_retries = max(0, connection_retries) + @arrow_client_error_handling_decorator def get_flight_info( self, descriptor: FlightDescriptor, options: FlightCallOptions = None @@ -71,7 +75,12 @@ def list_actions(self, options: FlightCallOptions = None): def build_arrow_flight_client( - scheme: str, host: str, port, auth_config: AuthConfig, cert: str = "" + scheme: str, + host: str, + port, + auth_config: AuthConfig, + cert: str = "", + connection_retries: int = 3, ): arrow_scheme = "grpc+tcp" if scheme == "https": @@ -88,10 +97,17 @@ def build_arrow_flight_client( if auth_config.type != AuthType.NONE.value: middlewares = [FlightAuthInterceptorFactory(auth_config)] return FeastFlightClient( - f"{arrow_scheme}://{host}:{port}", middleware=middlewares, **kwargs + f"{arrow_scheme}://{host}:{port}", + middleware=middlewares, + connection_retries=connection_retries, + **kwargs, ) - return FeastFlightClient(f"{arrow_scheme}://{host}:{port}", **kwargs) + return FeastFlightClient( + f"{arrow_scheme}://{host}:{port}", + connection_retries=connection_retries, + **kwargs, + ) class RemoteOfflineStoreConfig(FeastConfigBaseModel): @@ -109,6 +125,9 @@ class RemoteOfflineStoreConfig(FeastConfigBaseModel): """ str: Path to the public certificate when the offline server starts in TLS(SSL) mode. This may be needed if the offline server started with a self-signed certificate, typically this file ends with `*.crt`, `*.cer`, or `*.pem`. If type is 'remote', then this configuration is needed to connect to remote offline server in TLS mode. """ + connection_retries: int = Field(default=3, ge=0) + """ int: Number of retries for transient Arrow Flight errors with exponential backoff (default 3). """ + class RemoteRetrievalJob(RetrievalJob): def __init__( @@ -207,6 +226,7 @@ def get_historical_features( port=config.offline_store.port, auth_config=config.auth_config, cert=config.offline_store.cert, + connection_retries=config.offline_store.connection_retries, ) feature_view_names = [fv.name for fv in feature_views] @@ -257,6 +277,7 @@ def pull_all_from_table_or_query( port=config.offline_store.port, auth_config=config.auth_config, cert=config.offline_store.cert, + connection_retries=config.offline_store.connection_retries, ) api_parameters = { @@ -295,6 +316,7 @@ def pull_latest_from_table_or_query( config.offline_store.port, config.auth_config, cert=config.offline_store.cert, + connection_retries=config.offline_store.connection_retries, ) api_parameters = { @@ -334,6 +356,7 @@ def write_logged_features( config.offline_store.port, config.auth_config, config.offline_store.cert, + connection_retries=config.offline_store.connection_retries, ) api_parameters = { @@ -364,6 +387,7 @@ def offline_write_batch( config.offline_store.port, config.auth_config, config.offline_store.cert, + connection_retries=config.offline_store.connection_retries, ) feature_view_names = [feature_view.name] @@ -396,6 +420,7 @@ def validate_data_source( config.offline_store.port, config.auth_config, config.offline_store.cert, + connection_retries=config.offline_store.connection_retries, ) api_parameters = { @@ -421,6 +446,7 @@ def get_table_column_names_and_types_from_data_source( config.offline_store.port, config.auth_config, config.offline_store.cert, + connection_retries=config.offline_store.connection_retries, ) api_parameters = { diff --git a/sdk/python/feast/infra/offline_stores/snowflake.py b/sdk/python/feast/infra/offline_stores/snowflake.py index 1140d8562b2..7226c908d13 100644 --- a/sdk/python/feast/infra/offline_stores/snowflake.py +++ b/sdk/python/feast/infra/offline_stores/snowflake.py @@ -409,7 +409,7 @@ def offline_write_batch( ) if table.schema != pa_schema: - table = table.cast(pa_schema) + table = offline_utils.cast_arrow_table_to_schema(table, pa_schema) with GetSnowflakeConnection(config.offline_store) as conn: snowflake_conn = conn diff --git a/sdk/python/feast/infra/online_stores/cassandra_online_store/cassandra_repo_configuration.py b/sdk/python/feast/infra/online_stores/cassandra_online_store/cassandra_repo_configuration.py index a1d619646f7..d206395fcf5 100644 --- a/sdk/python/feast/infra/online_stores/cassandra_online_store/cassandra_repo_configuration.py +++ b/sdk/python/feast/infra/online_stores/cassandra_online_store/cassandra_repo_configuration.py @@ -14,10 +14,10 @@ # limitations under the License. # -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) -from tests.integration.feature_repos.universal.online_store.cassandra import ( +from tests.universal.feature_repos.universal.online_store.cassandra import ( CassandraOnlineStoreCreator, ) diff --git a/sdk/python/feast/infra/online_stores/couchbase_online_store/couchbase_repo_configuration.py b/sdk/python/feast/infra/online_stores/couchbase_online_store/couchbase_repo_configuration.py index e099e6ae1b5..6637c4555ad 100644 --- a/sdk/python/feast/infra/online_stores/couchbase_online_store/couchbase_repo_configuration.py +++ b/sdk/python/feast/infra/online_stores/couchbase_online_store/couchbase_repo_configuration.py @@ -1,7 +1,7 @@ -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) -from tests.integration.feature_repos.universal.online_store.couchbase import ( +from tests.universal.feature_repos.universal.online_store.couchbase import ( CouchbaseOnlineStoreCreator, ) diff --git a/sdk/python/feast/infra/online_stores/dynamodb.py b/sdk/python/feast/infra/online_stores/dynamodb.py index 0353e2c2d72..814058c77e5 100644 --- a/sdk/python/feast/infra/online_stores/dynamodb.py +++ b/sdk/python/feast/infra/online_stores/dynamodb.py @@ -16,6 +16,7 @@ import itertools import logging from collections import OrderedDict, defaultdict +from concurrent.futures import ThreadPoolExecutor from datetime import datetime from typing import Any, Callable, Dict, List, Literal, Optional, Sequence, Tuple, Union @@ -76,6 +77,10 @@ class DynamoDBOnlineStoreConfig(FeastConfigBaseModel): session_based_auth: bool = False """AWS session based client authentication""" + max_read_workers: int = 10 + """Maximum number of parallel threads for batch read operations. + Higher values improve throughput for large batch reads but increase resource usage.""" + max_pool_connections: int = 50 """Max number of connections for async Dynamodb operations. Increase for high-throughput workloads.""" @@ -479,33 +484,71 @@ def online_read( online_config.endpoint_url, online_config.session_based_auth, ) - table_instance = dynamodb_resource.Table( - _get_table_name(online_config, config, table) - ) + table_name = _get_table_name(online_config, config, table) batch_size = online_config.batch_size entity_ids = self._to_entity_ids(config, entity_keys) - entity_ids_iter = iter(entity_ids) - result: List[Tuple[Optional[datetime], Optional[Dict[str, ValueProto]]]] = [] + # Split entity_ids into batches upfront + batches: List[List[str]] = [] + entity_ids_iter = iter(entity_ids) while True: batch = list(itertools.islice(entity_ids_iter, batch_size)) - - # No more items to insert - if len(batch) == 0: + if not batch: break + batches.append(batch) + + if not batches: + return [] + + # For single batch, no parallelization overhead needed + if len(batches) == 1: batch_entity_ids = self._to_resource_batch_get_payload( - online_config, table_instance.name, batch + online_config, table_name, batches[0] ) - response = dynamodb_resource.batch_get_item( - RequestItems=batch_entity_ids, + response = dynamodb_resource.batch_get_item(RequestItems=batch_entity_ids) + return self._process_batch_get_response(table_name, response, batches[0]) + + # Execute batch requests in parallel for multiple batches + # Note: boto3 clients ARE thread-safe, so we can share a single client + # https://docs.aws.amazon.com/boto3/latest/guide/clients.html#multithreading-or-multiprocessing-with-clients + dynamodb_client = self._get_dynamodb_client( + online_config.region, + online_config.endpoint_url, + online_config.session_based_auth, + ) + + def fetch_batch(batch: List[str]) -> Dict[str, Any]: + batch_entity_ids = self._to_client_batch_get_payload( + online_config, table_name, batch ) + return dynamodb_client.batch_get_item(RequestItems=batch_entity_ids) + + # Use ThreadPoolExecutor for parallel I/O + max_workers = min(len(batches), online_config.max_read_workers) + with ThreadPoolExecutor(max_workers=max_workers) as executor: + responses = list(executor.map(fetch_batch, batches)) + + # Process responses and merge results in order + # Client responses need deserialization (unlike resource responses) + if self._type_deserializer is None: + self._type_deserializer = TypeDeserializer() + deserialize = self._type_deserializer.deserialize + + def to_tbl_resp(raw_client_response): + return { + "entity_id": deserialize(raw_client_response["entity_id"]), + "event_ts": deserialize(raw_client_response["event_ts"]), + "values": deserialize(raw_client_response["values"]), + } + + result: List[Tuple[Optional[datetime], Optional[Dict[str, ValueProto]]]] = [] + for batch, response in zip(batches, responses): batch_result = self._process_batch_get_response( - table_instance.name, - response, - batch, + table_name, response, batch, to_tbl_response=to_tbl_resp ) result.extend(batch_result) + return result async def online_read_async( @@ -945,6 +988,12 @@ def _extract_list_values(self, value_proto: ValueProto) -> list: return list(value_proto.bool_list_val.val) elif value_proto.HasField("bytes_list_val"): return list(value_proto.bytes_list_val.val) + elif value_proto.HasField("map_list_val"): + return list(value_proto.map_list_val.val) + elif value_proto.HasField("json_list_val"): + return list(value_proto.json_list_val.val) + elif value_proto.HasField("struct_list_val"): + return list(value_proto.struct_list_val.val) return [] def _set_list_values( @@ -965,6 +1014,12 @@ def _set_list_values( result.bool_list_val.val.extend(values) elif template.HasField("bytes_list_val"): result.bytes_list_val.val.extend(values) + elif template.HasField("map_list_val"): + result.map_list_val.val.extend(values) + elif template.HasField("json_list_val"): + result.json_list_val.val.extend(values) + elif template.HasField("struct_list_val"): + result.struct_list_val.val.extend(values) async def _update_item_with_expression_async( self, diff --git a/sdk/python/feast/infra/online_stores/elasticsearch_online_store/elasticsearch.py b/sdk/python/feast/infra/online_stores/elasticsearch_online_store/elasticsearch.py index 7e8e533281d..b78d003ac25 100644 --- a/sdk/python/feast/infra/online_stores/elasticsearch_online_store/elasticsearch.py +++ b/sdk/python/feast/infra/online_stores/elasticsearch_online_store/elasticsearch.py @@ -279,8 +279,7 @@ def retrieve_online_documents( requested_features: List[str], embedding: List[float], top_k: int, - *args, - **kwargs, + distance_metric: Optional[str] = None, ) -> List[ Tuple[ Optional[datetime], @@ -349,6 +348,7 @@ def retrieve_online_documents_v2( top_k: int, distance_metric: Optional[str] = None, query_string: Optional[str] = None, + include_feature_view_version_metadata: bool = False, ) -> List[ Tuple[ Optional[datetime], diff --git a/sdk/python/feast/infra/online_stores/elasticsearch_online_store/elasticsearch_repo_configuration.py b/sdk/python/feast/infra/online_stores/elasticsearch_online_store/elasticsearch_repo_configuration.py index 4d1f2c3ca18..46e8ba7742e 100644 --- a/sdk/python/feast/infra/online_stores/elasticsearch_online_store/elasticsearch_repo_configuration.py +++ b/sdk/python/feast/infra/online_stores/elasticsearch_online_store/elasticsearch_repo_configuration.py @@ -1,7 +1,7 @@ -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) -from tests.integration.feature_repos.universal.online_store.elasticsearch import ( +from tests.universal.feature_repos.universal.online_store.elasticsearch import ( ElasticSearchOnlineStoreCreator, ) diff --git a/sdk/python/feast/infra/online_stores/faiss_online_store.py b/sdk/python/feast/infra/online_stores/faiss_online_store.py index 4b666f60f40..3e3d92cde6d 100644 --- a/sdk/python/feast/infra/online_stores/faiss_online_store.py +++ b/sdk/python/feast/infra/online_stores/faiss_online_store.py @@ -176,7 +176,7 @@ def retrieve_online_documents( self, config: RepoConfig, table: FeatureView, - requested_featres: List[str], + requested_features: List[str], embedding: List[float], top_k: int, distance_metric: Optional[str] = None, diff --git a/sdk/python/feast/infra/online_stores/hazelcast_online_store/hazelcast_repo_configuration.py b/sdk/python/feast/infra/online_stores/hazelcast_online_store/hazelcast_repo_configuration.py index 5b3ea6e307b..6157f362120 100644 --- a/sdk/python/feast/infra/online_stores/hazelcast_online_store/hazelcast_repo_configuration.py +++ b/sdk/python/feast/infra/online_stores/hazelcast_online_store/hazelcast_repo_configuration.py @@ -14,10 +14,10 @@ # limitations under the License. # -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) -from tests.integration.feature_repos.universal.online_store.hazelcast import ( +from tests.universal.feature_repos.universal.online_store.hazelcast import ( HazelcastOnlineStoreCreator, ) diff --git a/sdk/python/feast/infra/online_stores/hbase_online_store/hbase_repo_configuration.py b/sdk/python/feast/infra/online_stores/hbase_online_store/hbase_repo_configuration.py index 4e32a654b55..d6089c0e3b4 100644 --- a/sdk/python/feast/infra/online_stores/hbase_online_store/hbase_repo_configuration.py +++ b/sdk/python/feast/infra/online_stores/hbase_online_store/hbase_repo_configuration.py @@ -1,7 +1,7 @@ -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) -from tests.integration.feature_repos.universal.online_store.hbase import ( +from tests.universal.feature_repos.universal.online_store.hbase import ( HbaseOnlineStoreCreator, ) diff --git a/sdk/python/feast/infra/online_stores/helpers.py b/sdk/python/feast/infra/online_stores/helpers.py index b657bd44d00..40e0f50a62c 100644 --- a/sdk/python/feast/infra/online_stores/helpers.py +++ b/sdk/python/feast/infra/online_stores/helpers.py @@ -70,3 +70,15 @@ def _to_naive_utc(ts: datetime) -> datetime: return ts else: return ts.astimezone(tz=timezone.utc).replace(tzinfo=None) + + +def compute_table_id(project: str, table: Any, enable_versioning: bool = False) -> str: + """Build the online-store table name, appending a version suffix when versioning is enabled.""" + name = table.name + if enable_versioning: + version = getattr(table.projection, "version_tag", None) + if version is None: + version = getattr(table, "current_version_number", None) + if version is not None and version > 0: + name = f"{table.name}_v{version}" + return f"{project}_{name}" diff --git a/sdk/python/feast/infra/online_stores/hybrid_online_store/hybrid_online_store_repo_configuration.py b/sdk/python/feast/infra/online_stores/hybrid_online_store/hybrid_online_store_repo_configuration.py index 90a65a092d0..3d016ce7d5e 100644 --- a/sdk/python/feast/infra/online_stores/hybrid_online_store/hybrid_online_store_repo_configuration.py +++ b/sdk/python/feast/infra/online_stores/hybrid_online_store/hybrid_online_store_repo_configuration.py @@ -16,10 +16,10 @@ # It enables running integration tests with multiple online store backends. # Update this file if you add more backends or change test setup. -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) -from tests.integration.feature_repos.universal.online_store.hybrid_online_store import ( +from tests.universal.feature_repos.universal.online_store.hybrid_online_store import ( HybridOnlineStoreCreator, ) diff --git a/sdk/python/feast/infra/online_stores/ikv_online_store/ikv.py b/sdk/python/feast/infra/online_stores/ikv_online_store/ikv.py deleted file mode 100644 index c8f0ad65c99..00000000000 --- a/sdk/python/feast/infra/online_stores/ikv_online_store/ikv.py +++ /dev/null @@ -1,311 +0,0 @@ -from datetime import datetime, timezone -from typing import ( - Any, - Callable, - Dict, - Iterator, - List, - Literal, - Optional, - Sequence, - Tuple, -) - -from google.protobuf.timestamp_pb2 import Timestamp -from ikvpy.client import IKVReader, IKVWriter -from ikvpy.clientoptions import ClientOptions, ClientOptionsBuilder -from ikvpy.document import IKVDocument, IKVDocumentBuilder -from ikvpy.factory import create_new_reader, create_new_writer -from pydantic import StrictStr - -from feast import Entity, FeatureView, utils -from feast.infra.online_stores.helpers import compute_entity_id -from feast.infra.online_stores.online_store import OnlineStore -from feast.protos.feast.types.EntityKey_pb2 import EntityKey as EntityKeyProto -from feast.protos.feast.types.Value_pb2 import Value as ValueProto -from feast.repo_config import FeastConfigBaseModel, RepoConfig - -PRIMARY_KEY_FIELD_NAME: str = "_entity_key" -EVENT_CREATION_TIMESTAMP_FIELD_NAME: str = "_event_timestamp" -CREATION_TIMESTAMP_FIELD_NAME: str = "_created_timestamp" - - -class IKVOnlineStoreConfig(FeastConfigBaseModel): - """Online store config for IKV store""" - - type: Literal["ikv"] = "ikv" - """Online store type selector""" - - account_id: StrictStr - """(Required) IKV account id""" - - account_passkey: StrictStr - """(Required) IKV account passkey""" - - store_name: StrictStr - """(Required) IKV store name""" - - mount_directory: Optional[StrictStr] = None - """(Required only for reader) IKV mount point i.e. directory for storing IKV data locally.""" - - -class IKVOnlineStore(OnlineStore): - """ - IKV (inlined.io key value) store implementation of the online store interface. - """ - - # lazy initialization - _reader: Optional[IKVReader] = None - _writer: Optional[IKVWriter] = None - - def online_write_batch( - self, - config: RepoConfig, - table: FeatureView, - data: List[ - Tuple[EntityKeyProto, Dict[str, ValueProto], datetime, Optional[datetime]] - ], - progress: Optional[Callable[[int], Any]], - ) -> None: - """ - Writes a batch of feature rows to the online store. - - If a tz-naive timestamp is passed to this method, it is assumed to be UTC. - - Args: - config: The config for the current feature store. - table: Feature view to which these feature rows correspond. - data: A list of quadruplets containing feature data. Each quadruplet contains an entity - key, a dict containing feature values, an event timestamp for the row, and the created - timestamp for the row if it exists. - progress: Function to be called once a batch of rows is written to the online store, used - to show progress. - """ - self._init_writer(config=config) - assert self._writer is not None - - for entity_key, features, event_timestamp, _ in data: - entity_id: str = compute_entity_id( - entity_key, - entity_key_serialization_version=config.entity_key_serialization_version, - ) - document: IKVDocument = IKVOnlineStore._create_document( - entity_id, table, features, event_timestamp - ) - self._writer.upsert_fields(document) - if progress: - progress(1) - - def online_read( - self, - config: RepoConfig, - table: FeatureView, - entity_keys: List[EntityKeyProto], - requested_features: Optional[List[str]] = None, - ) -> List[Tuple[Optional[datetime], Optional[Dict[str, ValueProto]]]]: - """ - Reads features values for the given entity keys. - - Args: - config: The config for the current feature store. - table: The feature view whose feature values should be read. - entity_keys: The list of entity keys for which feature values should be read. - requested_features: The list of features that should be read. - - Returns: - A list of the same length as entity_keys. Each item in the list is a tuple where the first - item is the event timestamp for the row, and the second item is a dict mapping feature names - to values, which are returned in proto format. - """ - self._init_reader(config=config) - - if not len(entity_keys): - return [] - - # create IKV primary keys - primary_keys = [ - compute_entity_id(ek, config.entity_key_serialization_version) - for ek in entity_keys - ] - - # create IKV field names - if requested_features is None: - requested_features = [] - - field_names: List[Optional[str]] = [None] * (1 + len(requested_features)) - field_names[0] = EVENT_CREATION_TIMESTAMP_FIELD_NAME - for i, fn in enumerate(requested_features): - field_names[i + 1] = IKVOnlineStore._create_ikv_field_name(table, fn) - - assert self._reader is not None - value_iter = self._reader.multiget_bytes_values( - bytes_primary_keys=[], - str_primary_keys=primary_keys, - field_names=field_names, - ) - - # decode results - return [ - IKVOnlineStore._decode_fields_for_primary_key( - requested_features, value_iter - ) - for _ in range(0, len(primary_keys)) - ] - - @staticmethod - def _decode_fields_for_primary_key( - requested_features: List[str], value_iter: Iterator[Optional[bytes]] - ) -> Tuple[Optional[datetime], Optional[Dict[str, ValueProto]]]: - # decode timestamp - dt: Optional[datetime] = None - dt_bytes = next(value_iter) - if dt_bytes: - proto_timestamp = Timestamp() - proto_timestamp.ParseFromString(dt_bytes) - dt = datetime.fromtimestamp(proto_timestamp.seconds, tz=timezone.utc) - - # decode other features - features = {} - for requested_feature in requested_features: - value_proto_bytes: Optional[bytes] = next(value_iter) - if value_proto_bytes: - value_proto = ValueProto() - value_proto.ParseFromString(value_proto_bytes) - features[requested_feature] = value_proto - - return dt, features - - def update( - self, - config: RepoConfig, - tables_to_delete: Sequence[FeatureView], - tables_to_keep: Sequence[FeatureView], - entities_to_delete: Sequence[Entity], - entities_to_keep: Sequence[Entity], - partial: bool, - ): - """ - Reconciles cloud resources with the specified set of Feast objects. - - Args: - config: The config for the current feature store. - tables_to_delete: Feature views whose corresponding infrastructure should be deleted. - tables_to_keep: Feature views whose corresponding infrastructure should not be deleted, and - may need to be updated. - entities_to_delete: Entities whose corresponding infrastructure should be deleted. - entities_to_keep: Entities whose corresponding infrastructure should not be deleted, and - may need to be updated. - partial: If true, tables_to_delete and tables_to_keep are not exhaustive lists, so - infrastructure corresponding to other feature views should be not be touched. - """ - self._init_writer(config=config) - assert self._writer is not None - - # note: we assume tables_to_keep does not overlap with tables_to_delete - - for feature_view in tables_to_delete: - # each field in an IKV document is prefixed by the feature-view's name - self._writer.drop_fields_by_name_prefix([feature_view.name]) - - def teardown( - self, - config: RepoConfig, - tables: Sequence[FeatureView], - entities: Sequence[Entity], - ): - """ - Tears down all cloud resources for the specified set of Feast objects. - - Args: - config: The config for the current feature store. - tables: Feature views whose corresponding infrastructure should be deleted. - entities: Entities whose corresponding infrastructure should be deleted. - """ - self._init_writer(config=config) - assert self._writer is not None - - # drop fields corresponding to this feature-view - for feature_view in tables: - self._writer.drop_fields_by_name_prefix([feature_view.name]) - - # shutdown clients - self._writer.shutdown() - self._writer = None - - if self._reader is not None: - self._reader.shutdown() - self._reader = None - - @staticmethod - def _create_ikv_field_name(feature_view: FeatureView, feature_name: str) -> str: - return "{}_{}".format(feature_view.name, feature_name) - - @staticmethod - def _create_document( - entity_id: str, - feature_view: FeatureView, - values: Dict[str, ValueProto], - event_timestamp: datetime, - ) -> IKVDocument: - """Converts feast key-value pairs into an IKV document.""" - - # initialie builder by inserting primary key and row creation timestamp - event_timestamp_seconds = int(utils.make_tzaware(event_timestamp).timestamp()) - event_timestamp_seconds_proto = Timestamp() - event_timestamp_seconds_proto.seconds = event_timestamp_seconds - - # event_timestamp_str: str = utils.make_tzaware(event_timestamp).isoformat() - builder = ( - IKVDocumentBuilder() - .put_string_field(PRIMARY_KEY_FIELD_NAME, entity_id) - .put_bytes_field( - EVENT_CREATION_TIMESTAMP_FIELD_NAME, - event_timestamp_seconds_proto.SerializeToString(), - ) - ) - - for feature_name, feature_value in values.items(): - field_name = IKVOnlineStore._create_ikv_field_name( - feature_view, feature_name - ) - builder.put_bytes_field(field_name, feature_value.SerializeToString()) - - return builder.build() - - def _init_writer(self, config: RepoConfig): - """Initializes ikv writer client.""" - # initialize writer - if self._writer is None: - online_config = config.online_store - assert isinstance(online_config, IKVOnlineStoreConfig) - client_options = IKVOnlineStore._config_to_client_options(online_config) - - self._writer = create_new_writer(client_options) - self._writer.startup() # blocking operation - - def _init_reader(self, config: RepoConfig): - """Initializes ikv reader client.""" - # initialize reader - if self._reader is None: - online_config = config.online_store - assert isinstance(online_config, IKVOnlineStoreConfig) - client_options = IKVOnlineStore._config_to_client_options(online_config) - - if online_config.mount_directory and len(online_config.mount_directory) > 0: - self._reader = create_new_reader(client_options) - self._reader.startup() # blocking operation - - @staticmethod - def _config_to_client_options(config: IKVOnlineStoreConfig) -> ClientOptions: - """Utility for IKVOnlineStoreConfig to IKV ClientOptions conversion.""" - builder = ( - ClientOptionsBuilder() - .with_account_id(config.account_id) - .with_account_passkey(config.account_passkey) - .with_store_name(config.store_name) - ) - - if config.mount_directory and len(config.mount_directory) > 0: - builder = builder.with_mount_directory(config.mount_directory) - - return builder.build() diff --git a/sdk/python/feast/infra/online_stores/milvus_online_store/milvus.py b/sdk/python/feast/infra/online_stores/milvus_online_store/milvus.py index 42a8f359107..ee2534684cc 100644 --- a/sdk/python/feast/infra/online_stores/milvus_online_store/milvus.py +++ b/sdk/python/feast/infra/online_stores/milvus_online_store/milvus.py @@ -56,6 +56,12 @@ PROTO_VALUE_TO_VALUE_TYPE_MAP["int64_list_val"]: DataType.FLOAT_VECTOR, PROTO_VALUE_TO_VALUE_TYPE_MAP["double_list_val"]: DataType.FLOAT_VECTOR, PROTO_VALUE_TO_VALUE_TYPE_MAP["bool_list_val"]: DataType.BINARY_VECTOR, + PROTO_VALUE_TO_VALUE_TYPE_MAP["map_val"]: DataType.VARCHAR, + PROTO_VALUE_TO_VALUE_TYPE_MAP["map_list_val"]: DataType.VARCHAR, + PROTO_VALUE_TO_VALUE_TYPE_MAP["json_val"]: DataType.VARCHAR, + PROTO_VALUE_TO_VALUE_TYPE_MAP["json_list_val"]: DataType.VARCHAR, + PROTO_VALUE_TO_VALUE_TYPE_MAP["struct_val"]: DataType.VARCHAR, + PROTO_VALUE_TO_VALUE_TYPE_MAP["struct_list_val"]: DataType.VARCHAR, } FEAST_PRIMITIVE_TO_MILVUS_TYPE_MAPPING: Dict[ @@ -81,6 +87,10 @@ FEAST_PRIMITIVE_TO_MILVUS_TYPE_MAPPING[feast_type] = DataType.VARCHAR elif base_value_type == ValueType.BOOL: FEAST_PRIMITIVE_TO_MILVUS_TYPE_MAPPING[feast_type] = DataType.BINARY_VECTOR + elif isinstance(feast_type, ComplexFeastType): + milvus_type = PROTO_TO_MILVUS_TYPE_MAPPING.get(value_type) + if milvus_type: + FEAST_PRIMITIVE_TO_MILVUS_TYPE_MAPPING[feast_type] = milvus_type class MilvusOnlineStoreConfig(FeastConfigBaseModel, VectorStoreConfig): @@ -173,6 +183,8 @@ def _get_or_create_collection( fields_to_add = [f for f in table.schema if f.name not in fields_to_exclude] for field in fields_to_add: dtype = FEAST_PRIMITIVE_TO_MILVUS_TYPE_MAPPING.get(field.dtype) + if dtype is None and isinstance(field.dtype, ComplexFeastType): + dtype = DataType.VARCHAR if dtype: if dtype == DataType.FLOAT_VECTOR: fields.append( @@ -433,6 +445,19 @@ def online_read( "double_list_val", ]: getattr(val, proto_attr).val.extend(field_value) + elif proto_attr in [ + "map_val", + "map_list_val", + "struct_val", + "struct_list_val", + "json_list_val", + ]: + if isinstance(field_value, str) and field_value: + try: + proto_bytes = base64.b64decode(field_value) + val.ParseFromString(proto_bytes) + except Exception: + setattr(val, "string_val", field_value) else: setattr(val, proto_attr, field_value) else: @@ -497,6 +522,7 @@ def retrieve_online_documents_v2( top_k: int, distance_metric: Optional[str] = None, query_string: Optional[str] = None, + include_feature_view_version_metadata: bool = False, ) -> List[ Tuple[ Optional[datetime], diff --git a/sdk/python/feast/infra/online_stores/milvus_online_store/milvus_repo_configuration.py b/sdk/python/feast/infra/online_stores/milvus_online_store/milvus_repo_configuration.py index 174c0b53737..5fbabe17898 100644 --- a/sdk/python/feast/infra/online_stores/milvus_online_store/milvus_repo_configuration.py +++ b/sdk/python/feast/infra/online_stores/milvus_online_store/milvus_repo_configuration.py @@ -1,8 +1,8 @@ -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) -from tests.integration.feature_repos.repo_configuration import MILVUS_CONFIG -from tests.integration.feature_repos.universal.online_store.milvus import ( +from tests.universal.feature_repos.repo_configuration import MILVUS_CONFIG +from tests.universal.feature_repos.universal.online_store.milvus import ( MilvusOnlineStoreCreator, ) diff --git a/sdk/python/feast/infra/online_stores/mongodb_online_store/__init__.py b/sdk/python/feast/infra/online_stores/mongodb_online_store/__init__.py new file mode 100644 index 00000000000..84b2dfd763e --- /dev/null +++ b/sdk/python/feast/infra/online_stores/mongodb_online_store/__init__.py @@ -0,0 +1,3 @@ +from .mongodb import MongoDBOnlineStore, MongoDBOnlineStoreConfig + +__all__ = ["MongoDBOnlineStore", "MongoDBOnlineStoreConfig"] diff --git a/sdk/python/feast/infra/online_stores/mongodb_online_store/mongodb.py b/sdk/python/feast/infra/online_stores/mongodb_online_store/mongodb.py new file mode 100644 index 00000000000..3e7a3db84c8 --- /dev/null +++ b/sdk/python/feast/infra/online_stores/mongodb_online_store/mongodb.py @@ -0,0 +1,498 @@ +from __future__ import annotations + +from datetime import datetime +from logging import getLogger +from typing import Any, Callable, Dict, List, Literal, Optional, Sequence, Tuple + +try: + from pymongo import AsyncMongoClient, MongoClient, UpdateOne + from pymongo.asynchronous.collection import AsyncCollection + from pymongo.collection import Collection + from pymongo.driver_info import DriverInfo +except ImportError as e: + from feast.errors import FeastExtrasDependencyImportError + + raise FeastExtrasDependencyImportError("mongodb", str(e)) + +import feast.version +from feast.entity import Entity +from feast.feature_view import FeatureView +from feast.infra.key_encoding_utils import serialize_entity_key +from feast.infra.online_stores.online_store import OnlineStore +from feast.infra.supported_async_methods import SupportedAsyncMethods +from feast.protos.feast.types.EntityKey_pb2 import EntityKey as EntityKeyProto +from feast.protos.feast.types.Value_pb2 import Value as ValueProto +from feast.repo_config import FeastConfigBaseModel, RepoConfig +from feast.type_map import ( + feast_value_type_to_python_type, + python_values_to_proto_values, +) + +logger = getLogger(__name__) + +DRIVER_METADATA = DriverInfo(name="Feast", version=feast.version.get_version()) + + +class MongoDBOnlineStoreConfig(FeastConfigBaseModel): + """MongoDB configuration. + + For a description of kwargs that may be passed to MongoClient, + see https://pymongo.readthedocs.io/en/stable/api/pymongo/mongo_client.html + """ + + type: Literal["mongodb"] = "mongodb" + """Online store type selector""" + connection_string: str = "mongodb://localhost:27017" + database_name: str = ( + "features" # todo - consider removing, and using repo_config.project + ) + collection_suffix: str = "latest" + client_kwargs: Dict[str, Any] = {} + + +class MongoDBOnlineStore(OnlineStore): + """ + MongoDB implementation of Feast OnlineStore. + + Schema: + _id: serialized_entity_key (bytes) + features: { .: } + event_timestamps: { "": datetime } + created_timestamp: datetime + + For example: + { + "_id": b"", + "features": { + "driver_stats": { + "rating": 4.91, + "trips_last_7d": 132, + }, + "pricing": { + "surge_multiplier": 1.2 + }, + }, + "event_timestamps": { + "driver_stats": "2026-01-01 12:00:00+00:00", + "pricing": "2026-01-21 12:00:00+00:00" + }, + "created_timestamp": "2026-01-21 12:00:00+00:00" + } + """ + + _client: Optional[MongoClient] = None + _collection: Optional[Collection] = None + _client_async: Optional[AsyncMongoClient] = None + _collection_async: Optional[AsyncCollection] = None + + @staticmethod + def _build_write_ops( + config: RepoConfig, + table: FeatureView, + data: List[ + Tuple[EntityKeyProto, Dict[str, ValueProto], datetime, Optional[datetime]] + ], + ) -> List[UpdateOne]: + """Build the list of UpdateOne upsert operations shared by the sync and async write paths. + + For each row in *data* this method: + + 1. Serializes the entity key to bytes using ``serialize_entity_key``. + 2. Converts every ``ValueProto`` feature value to its native Python type + via ``feast_value_type_to_python_type``. + 3. Constructs a ``$set`` update document that writes feature values under + ``features..``, the per-view event + timestamp under ``event_timestamps.``, and the + row-level ``created_timestamp``. + 4. Wraps that in a ``UpdateOne`` with ``upsert=True`` so that existing + entity documents are updated in-place and new ones are created on first + write. + + The caller is responsible for executing the returned operations via + ``collection.bulk_write(ops, ordered=False)`` (sync) or + ``await collection.bulk_write(ops, ordered=False)`` (async). + """ + ops = [] + for entity_key, proto_values, event_timestamp, created_timestamp in data: + entity_id = serialize_entity_key( + entity_key, + entity_key_serialization_version=config.entity_key_serialization_version, + ) + feature_updates = { + f"features.{table.name}.{field}": feast_value_type_to_python_type(val) + for field, val in proto_values.items() + } + update = { + "$set": { + **feature_updates, + f"event_timestamps.{table.name}": event_timestamp, + "created_timestamp": created_timestamp, + }, + } + ops.append( + UpdateOne( + filter={"_id": entity_id}, + update=update, + upsert=True, + ) + ) + return ops + + def online_write_batch( + self, + config: RepoConfig, + table: FeatureView, + data: List[ + Tuple[EntityKeyProto, Dict[str, ValueProto], datetime, Optional[datetime]] + ], + progress: Optional[Callable[[int], Any]] = None, + ) -> None: + """ + Writes a batch of feature values to the online store. + + data: + [ + ( + entity_key_bytes, + { feature_ref: ValueProto }, + event_timestamp, + created_timestamp, + ) + ] + """ + clxn = self._get_collection(config) + ops = self._build_write_ops(config, table, data) + if ops: + clxn.bulk_write(ops, ordered=False) + if progress: + progress(len(data)) + + def online_read( + self, + config: RepoConfig, + table: FeatureView, + entity_keys: List[EntityKeyProto], + requested_features: Optional[List[str]] = None, + ) -> List[Tuple[Optional[datetime], Optional[Dict[str, ValueProto]]]]: + """ + Read features for a batch of entities. + + Args: + config: Feast repo configuration + table: FeatureView to read from + entity_keys: List of entity keys to read + requested_features: Optional list of specific features to read + + Returns: + List of tuples (event_timestamp, feature_dict) for each entity key + """ + clxn = self._get_collection(config) + + ids = [ + serialize_entity_key( + key, + entity_key_serialization_version=config.entity_key_serialization_version, + ) + for key in entity_keys + ] + + query_filter = {"_id": {"$in": ids}} + projection = { + "_id": 1, + f"event_timestamps.{table.name}": 1, + } + if requested_features: + projection.update( + {f"features.{table.name}.{x}": 1 for x in requested_features} + ) + else: + projection[f"features.{table.name}"] = 1 + + cursor = clxn.find(query_filter, projection=projection) + docs = {doc["_id"]: doc for doc in cursor} + + return self._convert_raw_docs_to_proto(ids, docs, table) + + def update( + self, + config: RepoConfig, + tables_to_delete: Sequence[FeatureView], + tables_to_keep: Sequence[FeatureView], + entities_to_delete: Sequence[Entity], + entities_to_keep: Sequence[Entity], + partial: bool, + ): + """Prepare or update online store. + + With MongoDB, we have a loose schema and lazy creation so there is little to do here. + Nothing needs to be pre-created for the entities and tables to keep. + + The OnlineStore is a single Collection with the following Document shape. + { + "_id": "", + "features": { + "": { + "": value + } + } + } + We remove any feature views named in tables_to_delete. + The Entities are serialized in the _id. No schema needs be adjusted. + """ + if not isinstance(config.online_store, MongoDBOnlineStoreConfig): + raise RuntimeError(f"{config.online_store.type = }. It must be mongodb.") + + clxn = self._get_collection(repo_config=config) + + if tables_to_delete: + unset_fields = {} + for fv in tables_to_delete: + unset_fields[f"features.{fv.name}"] = "" + unset_fields[f"event_timestamps.{fv.name}"] = "" + + clxn.update_many({}, {"$unset": unset_fields}) + + # Note: entities_to_delete contains Entity definitions (metadata), not entity instances. + # Like other online stores, we don't need to do anything with entities_to_delete here. + + def teardown( + self, + config: RepoConfig, + tables: Sequence[FeatureView], + entities: Sequence[Entity], + ): + """ + Drop the backing collection and close the client. + + As in update, MongoDB requires very little here. + """ + if not isinstance(config.online_store, MongoDBOnlineStoreConfig): + raise RuntimeError(f"{config.online_store.type = }. It must be mongodb.") + clxn = self._get_collection(repo_config=config) + clxn.drop() + if self._client: + self._client.close() + self._client = None + self._collection = None + + async def close(self) -> None: + """Close the async MongoDB client and release its resources.""" + if self._client_async is not None: + await self._client_async.close() + self._client_async = None + self._collection_async = None + + # ------------------------------------------------------------------ + # Helpers + # ------------------------------------------------------------------ + + def _get_client(self, config: RepoConfig): + """Returns a connection to the server.""" + online_store_config = config.online_store + if not isinstance(online_store_config, MongoDBOnlineStoreConfig): + raise ValueError( + f"config.online_store should be MongoDBOnlineStoreConfig, got {online_store_config}" + ) + if self._client is None: + online_config = config.online_store + self._client = MongoClient( + online_config.connection_string, + driver=DRIVER_METADATA, + **online_config.client_kwargs, + ) + return self._client + + def _get_collection(self, repo_config: RepoConfig) -> Collection: + """Returns a connection to the online store collection.""" + if self._collection is None: + self._client = self._get_client(repo_config) + assert self._client is not None + online_config = repo_config.online_store + db = self._client[online_config.database_name] + clxn_name = f"{repo_config.project}_{online_config.collection_suffix}" + self._collection = db[clxn_name] + return self._collection + + async def _get_client_async(self, config: RepoConfig) -> AsyncMongoClient: + """Returns an async MongoDB client.""" + if self._client_async is None: + online_config = config.online_store + if not isinstance(online_config, MongoDBOnlineStoreConfig): + raise ValueError( + f"config.online_store should be MongoDBOnlineStoreConfig, got {online_config}" + ) + self._client_async = AsyncMongoClient( + online_config.connection_string, + driver=DRIVER_METADATA, + **online_config.client_kwargs, + ) + return self._client_async + + async def _get_collection_async(self, repo_config: RepoConfig) -> AsyncCollection: + """Returns an async connection to the online store collection.""" + if self._collection_async is None: + self._client_async = await self._get_client_async(repo_config) + assert self._client_async is not None + online_config = repo_config.online_store + db = self._client_async[online_config.database_name] + clxn_name = f"{repo_config.project}_{online_config.collection_suffix}" + self._collection_async = db[clxn_name] + return self._collection_async + + @property + def async_supported(self) -> SupportedAsyncMethods: + """Indicates that this online store supports async operations.""" + return SupportedAsyncMethods(read=True, write=True) + + @staticmethod + def _convert_raw_docs_to_proto( + ids: list[bytes], docs: dict[bytes, Any], table: FeatureView + ) -> List[Tuple[Optional[datetime], Optional[dict[str, ValueProto]]]]: + """Optimized converting values in documents retrieved from MongoDB (BSON) into ValueProto types. + + The conversion itself is done in feast.type_map.python_values_to_proto_values. + The issue we have is that it is column-oriented, expecting a list of proto values with a single type. + MongoDB lookups are row-oriented. Plus, we need to ensure ordering of ids. + So we transform twice to minimize calls to the python/proto converter. + + Luckily, the table, a FeatureView, provides a map from feature name to proto type + so we don't have to infer types for each feature value. + + Args: + ids: sorted list of the serialized entity ids requested. + docs: results of collection find. + table: The FeatureView of the read, providing the types. + Returns: + List of tuples (event_timestamp, feature_dict) for each entity key + """ + feature_type_map = { + feature.name: feature.dtype.to_value_type() for feature in table.features + } + + # Step 1: Extract raw values column-wise (aligned by ordered ids) + # We need to maintain alignment, so we append None for missing features + raw_feature_columns: Dict[str, List[Any]] = { + feature_name: [] for feature_name in feature_type_map + } + + for entity_id in ids: + doc = docs.get(entity_id) + feature_dict = doc.get("features", {}).get(table.name, {}) if doc else {} + + # For each expected feature, append its value or None + for feature_name in feature_type_map: + raw_feature_columns[feature_name].append( + feature_dict.get(feature_name, None) + ) + + # Step 2: Convert per feature + proto_feature_columns = {} + for feature_name, raw_values in raw_feature_columns.items(): + proto_feature_columns[feature_name] = python_values_to_proto_values( + raw_values, + feature_type=feature_type_map[feature_name], + ) + + # Step 3: Reassemble row-wise + results: List[Tuple[Optional[datetime], Optional[Dict[str, ValueProto]]]] = [] + + for i, entity_id in enumerate(ids): + doc = docs.get(entity_id) + + if doc is None: + results.append((None, None)) + continue + + # Entity document exists (written by some other feature view), but + # this specific feature view was never written → treat as not found. + fv_features = doc.get("features", {}).get(table.name) + if fv_features is None: + results.append((None, None)) + continue + + ts = doc.get("event_timestamps", {}).get(table.name) + + row_features = { + feature_name: proto_feature_columns[feature_name][i] + for feature_name in proto_feature_columns + } + + results.append((ts, row_features)) + return results + + async def online_read_async( + self, + config: RepoConfig, + table: FeatureView, + entity_keys: List[EntityKeyProto], + requested_features: Optional[List[str]] = None, + ) -> List[Tuple[Optional[datetime], Optional[Dict[str, ValueProto]]]]: + """ + Asynchronously reads feature values from the online store. + + Args: + config: Feast repo configuration + table: FeatureView to read from + entity_keys: List of entity keys to read + requested_features: Optional list of specific features to read + + Returns: + List of tuples (event_timestamp, feature_dict) for each entity key + """ + clxn = await self._get_collection_async(config) + + # Serialize entity keys + ids = [ + serialize_entity_key( + entity_key, + entity_key_serialization_version=config.entity_key_serialization_version, + ) + for entity_key in entity_keys + ] + + query_filter = {"_id": {"$in": ids}} + projection = { + "_id": 1, + f"event_timestamps.{table.name}": 1, + } + if requested_features: + projection.update( + {f"features.{table.name}.{x}": 1 for x in requested_features} + ) + else: + projection[f"features.{table.name}"] = 1 + + cursor = clxn.find(query_filter, projection=projection) + docs = {doc["_id"]: doc async for doc in cursor} + + # Convert to proto format + return self._convert_raw_docs_to_proto(ids, docs, table) + + async def online_write_batch_async( + self, + config: RepoConfig, + table: FeatureView, + data: List[ + Tuple[EntityKeyProto, Dict[str, ValueProto], datetime, Optional[datetime]] + ], + progress: Optional[Callable[[int], Any]] = None, + ) -> None: + """ + Asynchronously writes a batch of feature values to the online store. + + Args: + config: Feast repo configuration + table: FeatureView to write to + data: List of tuples (entity_key, features, event_ts, created_ts) + progress: Optional progress callback + """ + clxn = await self._get_collection_async(config) + ops = self._build_write_ops(config, table, data) + if ops: + await clxn.bulk_write(ops, ordered=False) + if progress: + progress(len(data)) + + +# TODO +# - Vector Search (requires atlas image in testcontainers or similar) diff --git a/sdk/python/feast/infra/online_stores/mongodb_online_store/mongodb_repo_configuration.py b/sdk/python/feast/infra/online_stores/mongodb_online_store/mongodb_repo_configuration.py new file mode 100644 index 00000000000..c621902ba54 --- /dev/null +++ b/sdk/python/feast/infra/online_stores/mongodb_online_store/mongodb_repo_configuration.py @@ -0,0 +1,13 @@ +from tests.universal.feature_repos.integration_test_repo_config import ( + IntegrationTestRepoConfig, +) +from tests.universal.feature_repos.universal.online_store.mongodb import ( + MongoDBOnlineStoreCreator, +) + +FULL_REPO_CONFIGS = [ + IntegrationTestRepoConfig( + online_store="mongodb", + online_store_creator=MongoDBOnlineStoreCreator, + ), +] diff --git a/sdk/python/feast/infra/online_stores/mysql_online_store/mysql.py b/sdk/python/feast/infra/online_stores/mysql_online_store/mysql.py index 2172f3aa359..415184ea248 100644 --- a/sdk/python/feast/infra/online_stores/mysql_online_store/mysql.py +++ b/sdk/python/feast/infra/online_stores/mysql_online_store/mysql.py @@ -10,6 +10,7 @@ from feast import Entity, FeatureView, RepoConfig from feast.infra.key_encoding_utils import serialize_entity_key +from feast.infra.online_stores.helpers import compute_table_id from feast.infra.online_stores.online_store import OnlineStore from feast.protos.feast.types.EntityKey_pb2 import EntityKey as EntityKeyProto from feast.protos.feast.types.Value_pb2 import Value as ValueProto @@ -70,6 +71,7 @@ def online_write_batch( cur = conn.cursor() project = config.project + versioning = config.registry.enable_online_feature_view_versioning batch_write = config.online_store.batch_write if not batch_write: @@ -92,6 +94,7 @@ def online_write_batch( table, timestamp, val, + versioning, ) conn.commit() if progress: @@ -124,7 +127,9 @@ def online_write_batch( if len(insert_values) >= batch_size: try: - self._execute_batch(cur, project, table, insert_values) + self._execute_batch( + cur, project, table, insert_values, versioning + ) conn.commit() if progress: progress(len(insert_values)) @@ -135,7 +140,7 @@ def online_write_batch( if insert_values: try: - self._execute_batch(cur, project, table, insert_values) + self._execute_batch(cur, project, table, insert_values, versioning) conn.commit() if progress: progress(len(insert_values)) @@ -143,9 +148,12 @@ def online_write_batch( conn.rollback() raise e - def _execute_batch(self, cur, project, table, insert_values): - sql = f""" - INSERT INTO {_table_id(project, table)} + def _execute_batch( + self, cur, project, table, insert_values, enable_versioning=False + ): + table_name = _table_id(project, table, enable_versioning) + stmt = f""" + INSERT INTO {table_name} (entity_key, feature_name, value, event_ts, created_ts) values (%s, %s, %s, %s, %s) ON DUPLICATE KEY UPDATE @@ -154,22 +162,29 @@ def _execute_batch(self, cur, project, table, insert_values): created_ts = VALUES(created_ts); """ try: - cur.executemany(sql, insert_values) + cur.executemany(stmt, insert_values) except Exception as e: - # Log SQL info for debugging without leaking sensitive data first_sample = insert_values[0] if insert_values else None raise RuntimeError( - f"Failed to execute batch insert into table '{_table_id(project, table)}' " + f"Failed to execute batch insert into table '{table_name}' " f"(rows={len(insert_values)}, sample={first_sample}): {e}" ) from e @staticmethod def write_to_table( - created_ts, cur, entity_key_bin, feature_name, project, table, timestamp, val + created_ts, + cur, + entity_key_bin, + feature_name, + project, + table, + timestamp, + val, + enable_versioning=False, ) -> None: cur.execute( f""" - INSERT INTO {_table_id(project, table)} + INSERT INTO {_table_id(project, table, enable_versioning)} (entity_key, feature_name, value, event_ts, created_ts) values (%s, %s, %s, %s, %s) ON DUPLICATE KEY UPDATE @@ -204,6 +219,7 @@ def online_read( result: List[Tuple[Optional[datetime], Optional[Dict[str, Any]]]] = [] project = config.project + versioning = config.registry.enable_online_feature_view_versioning for entity_key in entity_keys: entity_key_bin = serialize_entity_key( entity_key, @@ -211,7 +227,7 @@ def online_read( ).hex() cur.execute( - f"SELECT feature_name, value, event_ts FROM {_table_id(project, table)} WHERE entity_key = %s", + f"SELECT feature_name, value, event_ts FROM {_table_id(project, table, versioning)} WHERE entity_key = %s", (entity_key_bin,), ) @@ -243,10 +259,11 @@ def update( conn = self._get_conn(config) cur = conn.cursor() project = config.project + versioning = config.registry.enable_online_feature_view_versioning # We don't create any special state for the entities in this implementation. for table in tables_to_keep: - table_name = _table_id(project, table) + table_name = _table_id(project, table, versioning) index_name = f"{table_name}_ek" cur.execute( f"""CREATE TABLE IF NOT EXISTS {table_name} (entity_key VARCHAR(512), @@ -269,7 +286,10 @@ def update( ) for table in tables_to_delete: - _drop_table_and_index(cur, project, table) + if versioning: + _drop_all_version_tables(cur, project, table) + else: + _drop_table_and_index(cur, _table_id(project, table)) def teardown( self, @@ -280,16 +300,30 @@ def teardown( conn = self._get_conn(config) cur = conn.cursor() project = config.project + versioning = config.registry.enable_online_feature_view_versioning for table in tables: - _drop_table_and_index(cur, project, table) + if versioning: + _drop_all_version_tables(cur, project, table) + else: + _drop_table_and_index(cur, _table_id(project, table)) -def _drop_table_and_index(cur: Cursor, project: str, table: FeatureView) -> None: - table_name = _table_id(project, table) - cur.execute(f"DROP INDEX {table_name}_ek ON {table_name};") +def _drop_table_and_index(cur: Cursor, table_name: str) -> None: cur.execute(f"DROP TABLE IF EXISTS {table_name}") -def _table_id(project: str, table: FeatureView) -> str: - return f"{project}_{table.name}" +def _drop_all_version_tables(cur: Cursor, project: str, table: FeatureView) -> None: + """Drop the base table and all versioned tables (e.g. _v1, _v2, ...).""" + base = f"{project}_{table.name}" + cur.execute( + "SELECT table_name FROM information_schema.tables " + "WHERE table_schema = DATABASE() AND (table_name = %s OR table_name REGEXP %s)", + (base, f"^{base}_v[0-9]+$"), + ) + for (name,) in cur.fetchall(): + _drop_table_and_index(cur, name) + + +def _table_id(project: str, table: FeatureView, enable_versioning: bool = False) -> str: + return compute_table_id(project, table, enable_versioning) diff --git a/sdk/python/feast/infra/online_stores/mysql_online_store/mysql_repo_configuration.py b/sdk/python/feast/infra/online_stores/mysql_online_store/mysql_repo_configuration.py index e5a1c0114c3..2944768097e 100644 --- a/sdk/python/feast/infra/online_stores/mysql_online_store/mysql_repo_configuration.py +++ b/sdk/python/feast/infra/online_stores/mysql_online_store/mysql_repo_configuration.py @@ -1,7 +1,7 @@ -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) -from tests.integration.feature_repos.universal.online_store.mysql import ( +from tests.universal.feature_repos.universal.online_store.mysql import ( BatchWriteMySQLOnlineStoreCreator, MySQLOnlineStoreCreator, ) diff --git a/sdk/python/feast/infra/online_stores/online_store.py b/sdk/python/feast/infra/online_stores/online_store.py index b77185229d5..41555ccfb2b 100644 --- a/sdk/python/feast/infra/online_stores/online_store.py +++ b/sdk/python/feast/infra/online_stores/online_store.py @@ -18,6 +18,7 @@ from feast import Entity, utils from feast.batch_feature_view import BatchFeatureView +from feast.errors import VersionedOnlineReadNotSupported from feast.feature_service import FeatureService from feast.feature_view import FeatureView from feast.infra.infra_object import InfraObject @@ -30,6 +31,7 @@ from feast.protos.feast.types.Value_pb2 import Value as ValueProto from feast.repo_config import RepoConfig from feast.stream_feature_view import StreamFeatureView +from feast.value_type import ValueType class OnlineStore(ABC): @@ -154,6 +156,7 @@ def get_online_features( registry: BaseRegistry, project: str, full_feature_names: bool = False, + include_feature_view_version_metadata: bool = False, ) -> OnlineResponse: if isinstance(entity_rows, list): columnar: Dict[str, List[Any]] = {k: [] for k in entity_rows[0].keys()} @@ -185,6 +188,21 @@ def get_online_features( native_entity_values=True, ) + # Check for versioned reads on unsupported stores + self._check_versioned_read_support(grouped_refs) + _track_read = False + try: + from feast.metrics import _config as _metrics_config + + _track_read = _metrics_config.online_features + except Exception: + pass + + if _track_read: + import time as _time + + _read_start = _time.monotonic() + for table, requested_features in grouped_refs: # Get the correct set of entity values with the correct join keys. table_entity_values, idxs, output_len = utils._get_unique_entities( @@ -203,33 +221,68 @@ def get_online_features( requested_features=requested_features, ) - feature_data = utils._convert_rows_to_protobuf( - requested_features, read_rows - ) - - # Populate the result_rows with the Features from the OnlineStore inplace. utils._populate_response_from_feature_data( - feature_data, + requested_features, + read_rows, idxs, online_features_response, full_feature_names, - requested_features, table, output_len, + include_feature_view_version_metadata, ) + if _track_read: + from feast.metrics import track_online_store_read + + track_online_store_read(_time.monotonic() - _read_start) + + feature_types = self._build_feature_types(grouped_refs) + if requested_on_demand_feature_views: utils._augment_response_with_on_demand_transforms( online_features_response, feature_refs, requested_on_demand_feature_views, full_feature_names, + feature_types=feature_types, ) utils._drop_unneeded_columns( online_features_response, requested_result_row_names ) - return OnlineResponse(online_features_response) + return OnlineResponse(online_features_response, feature_types=feature_types) + + def _check_versioned_read_support(self, grouped_refs): + """Raise an error if versioned reads are attempted on unsupported stores.""" + from feast.infra.online_stores.sqlite import SqliteOnlineStore + + supported_types: list[type] = [SqliteOnlineStore] + try: + from feast.infra.online_stores.mysql_online_store.mysql import ( + MySQLOnlineStore, + ) + + supported_types.append(MySQLOnlineStore) + except ImportError: + pass + try: + from feast.infra.online_stores.postgres_online_store.postgres import ( + PostgreSQLOnlineStore, + ) + + supported_types.append(PostgreSQLOnlineStore) + except ImportError: + pass + + if isinstance(self, tuple(supported_types)): + return + for table, _ in grouped_refs: + version_tag = getattr(table.projection, "version_tag", None) + if version_tag is not None: + raise VersionedOnlineReadNotSupported( + self.__class__.__name__, version_tag + ) async def get_online_features_async( self, @@ -242,6 +295,7 @@ async def get_online_features_async( registry: BaseRegistry, project: str, full_feature_names: bool = False, + include_feature_view_version_metadata: bool = False, ) -> OnlineResponse: if isinstance(entity_rows, list): columnar: Dict[str, List[Any]] = {k: [] for k in entity_rows[0].keys()} @@ -273,6 +327,9 @@ async def get_online_features_async( native_entity_values=True, ) + # Check for versioned reads on unsupported stores + self._check_versioned_read_support(grouped_refs) + async def query_table(table, requested_features): # Get the correct set of entity values with the correct join keys. table_entity_values, idxs, output_len = utils._get_unique_entities( @@ -293,6 +350,19 @@ async def query_table(table, requested_features): return idxs, read_rows, output_len + _track_read = False + try: + from feast.metrics import _config as _metrics_config + + _track_read = _metrics_config.online_features + except Exception: + pass + + if _track_read: + import time as _time + + _read_start = _time.monotonic() + all_responses = await asyncio.gather( *[ query_table(table, requested_features) @@ -303,33 +373,56 @@ async def query_table(table, requested_features): for (idxs, read_rows, output_len), (table, requested_features) in zip( all_responses, grouped_refs ): - feature_data = utils._convert_rows_to_protobuf( - requested_features, read_rows - ) - - # Populate the result_rows with the Features from the OnlineStore inplace. utils._populate_response_from_feature_data( - feature_data, + requested_features, + read_rows, idxs, online_features_response, full_feature_names, - requested_features, table, output_len, + include_feature_view_version_metadata, ) + if _track_read: + from feast.metrics import track_online_store_read + + track_online_store_read(_time.monotonic() - _read_start) + + feature_types = self._build_feature_types(grouped_refs) + if requested_on_demand_feature_views: utils._augment_response_with_on_demand_transforms( online_features_response, feature_refs, requested_on_demand_feature_views, full_feature_names, + feature_types=feature_types, ) utils._drop_unneeded_columns( online_features_response, requested_result_row_names ) - return OnlineResponse(online_features_response) + return OnlineResponse(online_features_response, feature_types=feature_types) + + @staticmethod + def _build_feature_types( + grouped_refs: List, + ) -> Dict[str, ValueType]: + """Build a mapping of feature names to ValueType from grouped feature view refs. + + Includes both bare names and prefixed names (feature_view__feature) so that + lookups succeed regardless of the full_feature_names setting. + """ + feature_types: Dict[str, ValueType] = {} + for table, requested_features in grouped_refs: + table_name = table.projection.name_to_use() + for field in table.features: + if field.name in requested_features: + vtype = field.dtype.to_value_type() + feature_types[field.name] = vtype + feature_types[f"{table_name}__{field.name}"] = vtype + return feature_types @abstractmethod def update( @@ -436,6 +529,7 @@ def retrieve_online_documents_v2( top_k: int, distance_metric: Optional[str] = None, query_string: Optional[str] = None, + include_feature_view_version_metadata: bool = False, ) -> List[ Tuple[ Optional[datetime], diff --git a/sdk/python/feast/infra/online_stores/postgres_online_store/pgvector_repo_configuration.py b/sdk/python/feast/infra/online_stores/postgres_online_store/pgvector_repo_configuration.py index 26b05613158..927c424f207 100644 --- a/sdk/python/feast/infra/online_stores/postgres_online_store/pgvector_repo_configuration.py +++ b/sdk/python/feast/infra/online_stores/postgres_online_store/pgvector_repo_configuration.py @@ -1,7 +1,7 @@ -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) -from tests.integration.feature_repos.universal.online_store.postgres import ( +from tests.universal.feature_repos.universal.online_store.postgres import ( PGVectorOnlineStoreCreator, ) diff --git a/sdk/python/feast/infra/online_stores/postgres_online_store/postgres.py b/sdk/python/feast/infra/online_stores/postgres_online_store/postgres.py index 0f7cb87856f..4a79349e91c 100644 --- a/sdk/python/feast/infra/online_stores/postgres_online_store/postgres.py +++ b/sdk/python/feast/infra/online_stores/postgres_online_store/postgres.py @@ -22,7 +22,7 @@ from feast import Entity, FeatureView, ValueType from feast.infra.key_encoding_utils import get_list_val_str, serialize_entity_key -from feast.infra.online_stores.helpers import _to_naive_utc +from feast.infra.online_stores.helpers import _to_naive_utc, compute_table_id from feast.infra.online_stores.online_store import OnlineStore from feast.infra.online_stores.vector_store import VectorStoreConfig from feast.infra.utils.postgres.connection_utils import ( @@ -152,7 +152,15 @@ def online_write_batch( event_ts = EXCLUDED.event_ts, created_ts = EXCLUDED.created_ts; """ - ).format(sql.Identifier(_table_id(config.project, table))) + ).format( + sql.Identifier( + _table_id( + config.project, + table, + config.registry.enable_online_feature_view_versioning, + ) + ) + ) # Push data into the online store with self._get_conn(config) as conn, conn.cursor() as cur: @@ -214,7 +222,13 @@ def _construct_query_and_params( FROM {} WHERE entity_key = ANY(%s) AND feature_name = ANY(%s); """ ).format( - sql.Identifier(_table_id(config.project, table)), + sql.Identifier( + _table_id( + config.project, + table, + config.registry.enable_online_feature_view_versioning, + ) + ), ) params = (keys, requested_features) else: @@ -224,7 +238,13 @@ def _construct_query_and_params( FROM {} WHERE entity_key = ANY(%s); """ ).format( - sql.Identifier(_table_id(config.project, table)), + sql.Identifier( + _table_id( + config.project, + table, + config.registry.enable_online_feature_view_versioning, + ) + ), ) params = (keys, []) return query, params @@ -304,12 +324,16 @@ def update( ), ) + versioning = config.registry.enable_online_feature_view_versioning for table in tables_to_delete: - table_name = _table_id(project, table) - cur.execute(_drop_table_and_index(table_name)) + if versioning: + _drop_all_version_tables(cur, project, table, schema_name) + else: + table_name = _table_id(project, table) + cur.execute(_drop_table_and_index(table_name)) for table in tables_to_keep: - table_name = _table_id(project, table) + table_name = _table_id(project, table, versioning) if config.online_store.vector_enabled: vector_value_type = "vector" else: @@ -363,11 +387,16 @@ def teardown( entities: Sequence[Entity], ): project = config.project + schema_name = config.online_store.db_schema or config.online_store.user + versioning = config.registry.enable_online_feature_view_versioning try: with self._get_conn(config) as conn, conn.cursor() as cur: for table in tables: - table_name = _table_id(project, table) - cur.execute(_drop_table_and_index(table_name)) + if versioning: + _drop_all_version_tables(cur, project, table, schema_name) + else: + table_name = _table_id(project, table) + cur.execute(_drop_table_and_index(table_name)) conn.commit() except Exception: logging.exception("Teardown failed") @@ -432,7 +461,9 @@ def retrieve_online_documents( ] ] = [] with self._get_conn(config, autocommit=True) as conn, conn.cursor() as cur: - table_name = _table_id(project, table) + table_name = _table_id( + project, table, config.registry.enable_online_feature_view_versioning + ) # Search query template to find the top k items that are closest to the given embedding # SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5; @@ -488,6 +519,7 @@ def retrieve_online_documents_v2( top_k: int, distance_metric: Optional[str] = None, query_string: Optional[str] = None, + include_feature_view_version_metadata: bool = False, ) -> List[ Tuple[ Optional[datetime], @@ -532,7 +564,11 @@ def retrieve_online_documents_v2( and feature.name in requested_features ] - table_name = _table_id(config.project, table) + table_name = _table_id( + config.project, + table, + config.registry.enable_online_feature_view_versioning, + ) with self._get_conn(config, autocommit=True) as conn, conn.cursor() as cur: query = None @@ -543,50 +579,114 @@ def retrieve_online_documents_v2( tsquery_str = " & ".join(query_string.split()) query = sql.SQL( """ + WITH vector_candidates AS ( + SELECT entity_key, + MIN(vector_value {distance_metric_sql} %s::vector) as distance + FROM {table_name} + WHERE vector_value IS NOT NULL + GROUP BY entity_key + ORDER BY distance + LIMIT {top_k} + ), + text_candidates AS ( + SELECT entity_key, + MAX(ts_rank(to_tsvector('english', value_text), to_tsquery('english', %s))) as text_rank + FROM {table_name} + WHERE feature_name = ANY(%s) + AND to_tsvector('english', value_text) @@ to_tsquery('english', %s) + GROUP BY entity_key + ORDER BY text_rank DESC + LIMIT {top_k} + ), + all_candidates AS ( + SELECT entity_key FROM vector_candidates + UNION + SELECT entity_key FROM text_candidates + ), + scored AS ( + SELECT + ac.entity_key, + COALESCE(vc.distance, + (SELECT MIN(t.vector_value {distance_metric_sql} %s::vector) + FROM {table_name} t + WHERE t.entity_key = ac.entity_key AND t.vector_value IS NOT NULL) + ) as distance, + COALESCE(tc.text_rank, + COALESCE( + (SELECT MAX(ts_rank(to_tsvector('english', ft.value_text), to_tsquery('english', %s))) + FROM {table_name} ft + WHERE ft.entity_key = ac.entity_key AND ft.feature_name = ANY(%s) AND ft.value_text IS NOT NULL), + 0 + ) + ) as text_rank + FROM all_candidates ac + LEFT JOIN vector_candidates vc ON ac.entity_key = vc.entity_key + LEFT JOIN text_candidates tc ON ac.entity_key = tc.entity_key + ORDER BY text_rank DESC, distance + LIMIT {top_k} + ) SELECT - entity_key, - feature_name, - value, - vector_value, - vector_value {distance_metric_sql} %s::vector as distance, - ts_rank(to_tsvector('english', value_text), to_tsquery('english', %s)) as text_rank, - event_ts, - created_ts - FROM {table_name} - WHERE feature_name = ANY(%s) AND to_tsvector('english', value_text) @@ to_tsquery('english', %s) - ORDER BY distance - LIMIT {top_k} + t1.entity_key, + t1.feature_name, + t1.value, + t1.vector_value, + s.distance, + s.text_rank, + t1.event_ts, + t1.created_ts + FROM {table_name} t1 + INNER JOIN scored s ON t1.entity_key = s.entity_key + WHERE t1.feature_name = ANY(%s) + ORDER BY s.text_rank DESC, s.distance """ ).format( distance_metric_sql=sql.SQL(distance_metric_sql), table_name=sql.Identifier(table_name), top_k=sql.Literal(top_k), ) - params = (embedding, tsquery_str, string_fields, tsquery_str) - + params = ( + embedding, + tsquery_str, + string_fields, + tsquery_str, + embedding, + tsquery_str, + string_fields, + requested_features, + ) elif embedding is not None: # Case 2: Vector Search Only query = sql.SQL( """ + WITH vector_matches AS ( + SELECT entity_key, + MIN(vector_value {distance_metric_sql} %s::vector) as distance + FROM {table_name} + WHERE vector_value IS NOT NULL + GROUP BY entity_key + ORDER BY distance + LIMIT {top_k} + ) SELECT - entity_key, - feature_name, - value, - vector_value, - vector_value {distance_metric_sql} %s::vector as distance, - NULL as text_rank, -- Keep consistent columns - event_ts, - created_ts - FROM {table_name} - ORDER BY distance - LIMIT {top_k} + t1.entity_key, + t1.feature_name, + t1.value, + t1.vector_value, + t2.distance, + NULL as text_rank, + t1.event_ts, + t1.created_ts + FROM {table_name} t1 + INNER JOIN vector_matches t2 ON t1.entity_key = t2.entity_key + WHERE t1.feature_name = ANY(%s) + ORDER BY t2.distance """ ).format( distance_metric_sql=sql.SQL(distance_metric_sql), table_name=sql.Identifier(table_name), top_k=sql.Literal(top_k), ) - params = (embedding,) + params = (embedding, requested_features) elif query_string is not None and string_fields: # Case 3: Text Search Only @@ -686,9 +786,10 @@ def retrieve_online_documents_v2( sorted_entities = sorted( entities_dict.values(), key=lambda x: ( - x["vector_distance"] if embedding is not None else x["text_rank"] + (-x["text_rank"], x["vector_distance"]) + if query_string is not None + else (x["vector_distance"],) ), - reverse=(embedding is None), )[:top_k] result: List[ @@ -728,8 +829,8 @@ def retrieve_online_documents_v2( return result -def _table_id(project: str, table: FeatureView) -> str: - return f"{project}_{table.name}" +def _table_id(project: str, table: FeatureView, enable_versioning: bool = False) -> str: + return compute_table_id(project, table, enable_versioning) def _drop_table_and_index(table_name): @@ -742,3 +843,23 @@ def _drop_table_and_index(table_name): sql.Identifier(table_name), sql.Identifier(f"{table_name}_ek"), ) + + +def _drop_all_version_tables( + cur, project: str, table: FeatureView, schema_name: Optional[str] = None +) -> None: + """Drop the base table and all versioned tables (e.g. _v1, _v2, ...).""" + base = f"{project}_{table.name}" + if schema_name: + cur.execute( + "SELECT tablename FROM pg_tables " + "WHERE schemaname = %s AND (tablename = %s OR tablename ~ %s)", + (schema_name, base, f"^{base}_v[0-9]+$"), + ) + else: + cur.execute( + "SELECT tablename FROM pg_tables WHERE tablename = %s OR tablename ~ %s", + (base, f"^{base}_v[0-9]+$"), + ) + for (name,) in cur.fetchall(): + cur.execute(_drop_table_and_index(name)) diff --git a/sdk/python/feast/infra/online_stores/postgres_online_store/postgres_repo_configuration.py b/sdk/python/feast/infra/online_stores/postgres_online_store/postgres_repo_configuration.py index ea975ec808f..b28abf955ef 100644 --- a/sdk/python/feast/infra/online_stores/postgres_online_store/postgres_repo_configuration.py +++ b/sdk/python/feast/infra/online_stores/postgres_online_store/postgres_repo_configuration.py @@ -1,7 +1,7 @@ -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) -from tests.integration.feature_repos.universal.online_store.postgres import ( +from tests.universal.feature_repos.universal.online_store.postgres import ( PostgresOnlineStoreCreator, ) diff --git a/sdk/python/feast/infra/online_stores/qdrant_online_store/qdrant_repo_configuration.py b/sdk/python/feast/infra/online_stores/qdrant_online_store/qdrant_repo_configuration.py index eee77bb8775..0cae0fae62c 100644 --- a/sdk/python/feast/infra/online_stores/qdrant_online_store/qdrant_repo_configuration.py +++ b/sdk/python/feast/infra/online_stores/qdrant_online_store/qdrant_repo_configuration.py @@ -1,7 +1,7 @@ -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) -from tests.integration.feature_repos.universal.online_store.qdrant import ( +from tests.universal.feature_repos.universal.online_store.qdrant import ( QdrantOnlineStoreCreator, ) diff --git a/sdk/python/feast/infra/online_stores/redis.py b/sdk/python/feast/infra/online_stores/redis.py index 9a4e908810d..aeeb540b910 100644 --- a/sdk/python/feast/infra/online_stores/redis.py +++ b/sdk/python/feast/infra/online_stores/redis.py @@ -372,14 +372,11 @@ def _convert_redis_values_to_protobuf( redis_values: List[List[ByteString]], feature_view: str, requested_features: List[str], - ): - result: List[Tuple[Optional[datetime], Optional[Dict[str, ValueProto]]]] = [] - for values in redis_values: - features = self._get_features_for_entity( - values, feature_view, requested_features - ) - result.append(features) - return result + ) -> List[Tuple[Optional[datetime], Optional[Dict[str, ValueProto]]]]: + return [ + self._get_features_for_entity(values, feature_view, requested_features) + for values in redis_values + ] def online_read( self, @@ -445,21 +442,21 @@ def _get_features_for_entity( res_val = dict(zip(requested_features, values)) res_ts = Timestamp() - ts_val = res_val.pop(f"_ts:{feature_view}") + ts_key = f"_ts:{feature_view}" + ts_val = res_val.pop(ts_key) if ts_val: - res_ts.ParseFromString(bytes(ts_val)) + res_ts.ParseFromString(ts_val) - res = {} + res: Dict[str, ValueProto] = {} for feature_name, val_bin in res_val.items(): val = ValueProto() if val_bin: - val.ParseFromString(bytes(val_bin)) + val.ParseFromString(val_bin) res[feature_name] = val if not res: return None, None - else: - # reconstruct full timestamp including nanos - total_seconds = res_ts.seconds + res_ts.nanos / 1_000_000_000.0 - timestamp = datetime.fromtimestamp(total_seconds, tz=timezone.utc) - return timestamp, res + + total_seconds = res_ts.seconds + res_ts.nanos / 1_000_000_000.0 + timestamp = datetime.fromtimestamp(total_seconds, tz=timezone.utc) + return timestamp, res diff --git a/sdk/python/feast/infra/online_stores/remote.py b/sdk/python/feast/infra/online_stores/remote.py index 1111e0e6c62..9bead1fcb9d 100644 --- a/sdk/python/feast/infra/online_stores/remote.py +++ b/sdk/python/feast/infra/online_stores/remote.py @@ -13,6 +13,7 @@ # limitations under the License. import json import logging +import uuid as uuid_module from collections import defaultdict from datetime import datetime from typing import Any, Callable, Dict, List, Literal, Optional, Sequence, Tuple @@ -38,6 +39,17 @@ logger = logging.getLogger(__name__) +def _json_safe(val: Any) -> Any: + """Convert uuid.UUID objects and sets to JSON-serializable form.""" + if isinstance(val, uuid_module.UUID): + return str(val) + if isinstance(val, set): + return [str(v) if isinstance(v, uuid_module.UUID) else v for v in val] + if isinstance(val, list): + return [str(v) if isinstance(v, uuid_module.UUID) else v for v in val] + return val + + class RemoteOnlineStoreConfig(FeastConfigBaseModel): """Remote Online store config for remote online store""" @@ -70,6 +82,56 @@ class RemoteOnlineStore(OnlineStore): remote online store implementation wrapper to communicate with feast online server. """ + @staticmethod + def _proto_value_to_transport_value(proto_value: ValueProto) -> Any: + """ + Convert a proto Value to a JSON-serializable Python value suitable for + HTTP transport. Unlike ``feast_value_type_to_python_type``, this keeps + ``json_val`` as a raw string so the receiving server can reconstruct a + DataFrame whose column types match the original (string for JSON, dict + for Map/Struct). Parsing JSON strings into dicts would cause PyArrow to + infer a struct column on the server, which can crash with complex nested + types (lists inside dicts). + """ + val_attr = proto_value.WhichOneof("val") + if val_attr is None: + return None + + # Keep JSON values as raw strings for correct DataFrame reconstruction. + # Parsing them into dicts causes PyArrow to infer struct columns on the + # server whose nested lists round-trip as numpy arrays, breaking + # json.dumps during proto conversion. + if val_attr == "json_val": + return getattr(proto_value, val_attr) + if val_attr == "json_list_val": + return list(getattr(proto_value, val_attr).val) + + # Nested collection types use feast_value_type_to_python_type + # which handles recursive conversion of RepeatedValue protos. + if val_attr in ("list_val", "set_val"): + return feast_value_type_to_python_type(proto_value) + + # Map/Struct types are converted to Python dicts by + # feast_value_type_to_python_type. Serialise them to JSON strings + # so the server-side DataFrame gets VARCHAR columns instead of + # PyArrow struct columns that can crash with complex nested types. + if val_attr in ("map_val", "struct_val"): + return json.dumps(feast_value_type_to_python_type(proto_value)) + if val_attr in ("map_list_val", "struct_list_val"): + return [json.dumps(v) for v in feast_value_type_to_python_type(proto_value)] + + # UUID types are stored as strings in proto — return them directly + # to avoid feast_value_type_to_python_type converting to uuid.UUID + # objects which are not JSON-serializable. + if val_attr in ("uuid_val", "time_uuid_val"): + return getattr(proto_value, val_attr) + if val_attr in ("uuid_list_val", "time_uuid_list_val"): + return list(getattr(proto_value, val_attr).val) + if val_attr in ("uuid_set_val", "time_uuid_set_val"): + return list(getattr(proto_value, val_attr).val) + + return feast_value_type_to_python_type(proto_value) + def online_write_batch( self, config: RepoConfig, @@ -93,14 +155,14 @@ def online_write_batch( for join_key, entity_value_proto in zip( entity_key_proto.join_keys, entity_key_proto.entity_values ): - columnar_data[join_key].append( - feast_value_type_to_python_type(entity_value_proto) - ) + val = feast_value_type_to_python_type(entity_value_proto) + columnar_data[join_key].append(_json_safe(val)) - # Populate feature values + # Populate feature values – use transport-safe conversion that + # preserves JSON strings instead of parsing them into dicts. for feature_name, feature_value_proto in feature_values_proto.items(): columnar_data[feature_name].append( - feast_value_type_to_python_type(feature_value_proto) + self._proto_value_to_transport_value(feature_value_proto) ) # Populate timestamps @@ -147,6 +209,12 @@ def online_read( logger.debug("Able to retrieve the online features from feature server.") response_json = json.loads(response.text) event_ts = self._get_event_ts(response_json) + # Build feature name -> ValueType mapping so we can reconstruct + # complex types (nested collections, sets, etc.) that cannot be + # inferred from raw JSON values alone. + feature_type_map: Dict[str, ValueType] = { + f.name: f.dtype.to_value_type() for f in table.features + } # Iterating over results and converting the API results in column format to row format. result_tuples: List[ Tuple[Optional[datetime], Optional[Dict[str, ValueProto]]] @@ -166,13 +234,16 @@ def online_read( ] == "PRESENT" ): + feature_value_type = feature_type_map.get( + feature_name, ValueType.UNKNOWN + ) message = python_values_to_proto_values( [ response_json["results"][index]["values"][ feature_value_index ] ], - ValueType.UNKNOWN, + feature_value_type, ) feature_values_dict[feature_name] = message[0] else: @@ -265,6 +336,7 @@ def retrieve_online_documents_v2( top_k: int, distance_metric: Optional[str] = None, query_string: Optional[str] = None, + include_feature_view_version_metadata: bool = False, ) -> List[ Tuple[ Optional[datetime], @@ -418,7 +490,7 @@ def _construct_online_read_api_json_request( entity_keys: List[EntityKeyProto], table: FeatureView, requested_features: Optional[List[str]] = None, - ) -> str: + ) -> dict: api_requested_features = [] if requested_features is not None: for requested_feature in requested_features: @@ -432,13 +504,10 @@ def _construct_online_read_api_json_request( getattr(row.entity_values[0], row.entity_values[0].WhichOneof("val")) ) - req_body = json.dumps( - { - "features": api_requested_features, - "entities": {entity_key: entity_values}, - } - ) - return req_body + return { + "features": api_requested_features, + "entities": {entity_key: entity_values}, + } def _construct_online_documents_api_json_request( self, @@ -447,21 +516,18 @@ def _construct_online_documents_api_json_request( embedding: Optional[List[float]] = None, top_k: Optional[int] = None, distance_metric: Optional[str] = "L2", - ) -> str: + ) -> dict: api_requested_features = [] if requested_features is not None: for requested_feature in requested_features: api_requested_features.append(f"{table.name}:{requested_feature}") - req_body = json.dumps( - { - "features": api_requested_features, - "query": embedding, - "top_k": top_k, - "distance_metric": distance_metric, - } - ) - return req_body + return { + "features": api_requested_features, + "query": embedding, + "top_k": top_k, + "distance_metric": distance_metric, + } def _construct_online_documents_v2_api_json_request( self, @@ -472,23 +538,20 @@ def _construct_online_documents_v2_api_json_request( distance_metric: Optional[str] = None, query_string: Optional[str] = None, api_version: Optional[int] = 2, - ) -> str: + ) -> dict: api_requested_features = [] if requested_features is not None: for requested_feature in requested_features: api_requested_features.append(f"{table.name}:{requested_feature}") - req_body = json.dumps( - { - "features": api_requested_features, - "query": embedding, - "top_k": top_k, - "distance_metric": distance_metric, - "query_string": query_string, - "api_version": api_version, - } - ) - return req_body + return { + "features": api_requested_features, + "query": embedding, + "top_k": top_k, + "distance_metric": distance_metric, + "query_string": query_string, + "api_version": api_version, + } def _get_event_ts(self, response_json) -> datetime: event_ts = "" @@ -574,33 +637,33 @@ async def close(self) -> None: @rest_error_handling_decorator def get_remote_online_features( - session: requests.Session, config: RepoConfig, req_body: str + session: requests.Session, config: RepoConfig, req_body: dict ) -> requests.Response: if config.online_store.cert: return session.post( f"{config.online_store.path}/get-online-features", - data=req_body, + json=req_body, verify=config.online_store.cert, ) else: return session.post( - f"{config.online_store.path}/get-online-features", data=req_body + f"{config.online_store.path}/get-online-features", json=req_body ) @rest_error_handling_decorator def get_remote_online_documents( - session: requests.Session, config: RepoConfig, req_body: str + session: requests.Session, config: RepoConfig, req_body: dict ) -> requests.Response: if config.online_store.cert: return session.post( f"{config.online_store.path}/retrieve-online-documents", - data=req_body, + json=req_body, verify=config.online_store.cert, ) else: return session.post( - f"{config.online_store.path}/retrieve-online-documents", data=req_body + f"{config.online_store.path}/retrieve-online-documents", json=req_body ) diff --git a/sdk/python/feast/infra/online_stores/singlestore_online_store/singlestore_repo_configuration.py b/sdk/python/feast/infra/online_stores/singlestore_online_store/singlestore_repo_configuration.py index 2debe0f0ee1..1e5379974c2 100644 --- a/sdk/python/feast/infra/online_stores/singlestore_online_store/singlestore_repo_configuration.py +++ b/sdk/python/feast/infra/online_stores/singlestore_online_store/singlestore_repo_configuration.py @@ -1,7 +1,7 @@ -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) -from tests.integration.feature_repos.universal.online_store.singlestore import ( +from tests.universal.feature_repos.universal.online_store.singlestore import ( SingleStoreOnlineStoreCreator, ) diff --git a/sdk/python/feast/infra/online_stores/snowflake.py b/sdk/python/feast/infra/online_stores/snowflake.py index f294dcad96b..d2df674ed94 100644 --- a/sdk/python/feast/infra/online_stores/snowflake.py +++ b/sdk/python/feast/infra/online_stores/snowflake.py @@ -1,4 +1,3 @@ -import itertools import os from binascii import hexlify from datetime import datetime @@ -168,20 +167,26 @@ def online_read( requested_features = requested_features if requested_features else [] + # Pre-compute serialized entity keys to avoid redundant serialization + serialized_entity_keys = [ + serialize_entity_key( + entity_key, + entity_key_serialization_version=config.entity_key_serialization_version, + ) + for entity_key in entity_keys + ] + entity_fetch_str = ",".join( [ ( "TO_BINARY(" + hexlify( - serialize_entity_key( - combo[0], - entity_key_serialization_version=config.entity_key_serialization_version, - ) - + bytes(combo[1], encoding="utf-8") + serialized_entity_key + bytes(feature, encoding="utf-8") ).__str__()[1:] + ")" ) - for combo in itertools.product(entity_keys, requested_features) + for serialized_entity_key in serialized_entity_keys + for feature in requested_features ] ) @@ -197,11 +202,7 @@ def online_read( """ df = execute_snowflake_statement(conn, query).fetch_pandas_all() - for entity_key in entity_keys: - entity_key_bin = serialize_entity_key( - entity_key, - entity_key_serialization_version=config.entity_key_serialization_version, - ) + for entity_key_bin in serialized_entity_keys: res = {} res_ts = None for index, row in df[df["entity_key"] == entity_key_bin].iterrows(): diff --git a/sdk/python/feast/infra/online_stores/sqlite.py b/sdk/python/feast/infra/online_stores/sqlite.py index 461277631f5..009e9a8c405 100644 --- a/sdk/python/feast/infra/online_stores/sqlite.py +++ b/sdk/python/feast/infra/online_stores/sqlite.py @@ -42,6 +42,7 @@ serialize_entity_key, serialize_f32, ) +from feast.infra.online_stores.helpers import compute_table_id from feast.infra.online_stores.online_store import OnlineStore from feast.infra.online_stores.vector_store import VectorStoreConfig from feast.protos.feast.core.InfraObject_pb2 import InfraObject as InfraObjectProto @@ -174,7 +175,11 @@ def online_write_batch( if created_ts is not None: created_ts = to_naive_utc(created_ts) - table_name = _table_id(project, table) + table_name = _table_id( + project, + table, + config.registry.enable_online_feature_view_versioning, + ) for feature_name, val in values.items(): if config.online_store.vector_enabled: if ( @@ -254,7 +259,7 @@ def online_read( # Fetch all entities in one go cur.execute( f"SELECT entity_key, feature_name, value, event_ts " - f"FROM {_table_id(config.project, table)} " + f"FROM {_table_id(config.project, table, config.registry.enable_online_feature_view_versioning)} " f"WHERE entity_key IN ({','.join('?' * len(entity_keys))}) " f"ORDER BY entity_key", serialized_entity_keys, @@ -263,11 +268,7 @@ def online_read( rows = { k: list(group) for k, group in itertools.groupby(rows, key=lambda r: r[0]) } - for entity_key in entity_keys: - entity_key_bin = serialize_entity_key( - entity_key, - entity_key_serialization_version=config.entity_key_serialization_version, - ) + for entity_key_bin in serialized_entity_keys: res = {} res_ts = None for _, feature_name, val_bin, ts in rows.get(entity_key_bin, []): @@ -298,16 +299,19 @@ def update( conn = self._get_conn(config) project = config.project + versioning = config.registry.enable_online_feature_view_versioning for table in tables_to_keep: conn.execute( - f"CREATE TABLE IF NOT EXISTS {_table_id(project, table)} (entity_key BLOB, feature_name TEXT, value BLOB, vector_value BLOB, event_ts timestamp, created_ts timestamp, PRIMARY KEY(entity_key, feature_name))" + f"CREATE TABLE IF NOT EXISTS {_table_id(project, table, versioning)} (entity_key BLOB, feature_name TEXT, value BLOB, vector_value BLOB, event_ts timestamp, created_ts timestamp, PRIMARY KEY(entity_key, feature_name))" ) conn.execute( - f"CREATE INDEX IF NOT EXISTS {_table_id(project, table)}_ek ON {_table_id(project, table)} (entity_key);" + f"CREATE INDEX IF NOT EXISTS {_table_id(project, table, versioning)}_ek ON {_table_id(project, table, versioning)} (entity_key);" ) for table in tables_to_delete: - conn.execute(f"DROP TABLE IF EXISTS {_table_id(project, table)}") + conn.execute( + f"DROP TABLE IF EXISTS {_table_id(project, table, versioning)}" + ) def plan( self, config: RepoConfig, desired_registry_proto: RegistryProto @@ -317,7 +321,11 @@ def plan( infra_objects: List[InfraObject] = [ SqliteTable( path=self._get_db_path(config), - name=_table_id(project, FeatureView.from_proto(view)), + name=_table_id( + project, + FeatureView.from_proto(view), + config.registry.enable_online_feature_view_versioning, + ), ) for view in [ *desired_registry_proto.feature_views, @@ -379,7 +387,9 @@ def retrieve_online_documents( # Convert the embedding to a binary format instead of using SerializeToString() query_embedding_bin = serialize_f32(embedding, vector_field_length) - table_name = _table_id(project, table) + table_name = _table_id( + project, table, config.registry.enable_online_feature_view_versioning + ) vector_field = _get_vector_field(table) cur.execute( @@ -468,6 +478,7 @@ def retrieve_online_documents_v2( top_k: int, distance_metric: Optional[str] = None, query_string: Optional[str] = None, + include_feature_view_version_metadata: bool = False, ) -> List[ Tuple[ Optional[datetime], @@ -503,7 +514,9 @@ def retrieve_online_documents_v2( _get_feature_view_vector_field_metadata(table), "vector_length", 512 ) - table_name = _table_id(config.project, table) + table_name = _table_id( + config.project, table, config.registry.enable_online_feature_view_versioning + ) vector_field = _get_vector_field(table) if online_store.vector_enabled: @@ -703,8 +716,8 @@ def _initialize_conn( return db -def _table_id(project: str, table: FeatureView) -> str: - return f"{project}_{table.name}" +def _table_id(project: str, table: FeatureView, enable_versioning: bool = False) -> str: + return compute_table_id(project, table, enable_versioning) class SqliteTable(InfraObject): diff --git a/sdk/python/feast/infra/passthrough_provider.py b/sdk/python/feast/infra/passthrough_provider.py index 2f960a02822..20334e53a2e 100644 --- a/sdk/python/feast/infra/passthrough_provider.py +++ b/sdk/python/feast/infra/passthrough_provider.py @@ -247,6 +247,7 @@ def get_online_features( registry: BaseRegistry, project: str, full_feature_names: bool = False, + include_feature_view_version_metadata: bool = False, ) -> OnlineResponse: return self.online_store.get_online_features( config=config, @@ -255,6 +256,7 @@ def get_online_features( registry=registry, project=project, full_feature_names=full_feature_names, + include_feature_view_version_metadata=include_feature_view_version_metadata, ) async def get_online_features_async( @@ -268,6 +270,7 @@ async def get_online_features_async( registry: BaseRegistry, project: str, full_feature_names: bool = False, + include_feature_view_version_metadata: bool = False, ) -> OnlineResponse: return await self.online_store.get_online_features_async( config=config, @@ -276,6 +279,7 @@ async def get_online_features_async( registry=registry, project=project, full_feature_names=full_feature_names, + include_feature_view_version_metadata=include_feature_view_version_metadata, ) async def online_read_async( @@ -322,6 +326,7 @@ def retrieve_online_documents_v2( top_k: int, distance_metric: Optional[str] = None, query_string: Optional[str] = None, + include_feature_view_version_metadata: bool = False, ) -> List: result = [] if self.online_store: @@ -333,6 +338,7 @@ def retrieve_online_documents_v2( top_k, distance_metric, query_string, + include_feature_view_version_metadata, ) return result @@ -364,7 +370,10 @@ def _prep_rows_to_write_for_ingestion( # Note: A dictionary mapping of column names in this data # source to feature names in a feature table or view. Only used for feature # columns, not entity or timestamp columns. - if hasattr(feature_view, "batch_source"): + if ( + hasattr(feature_view, "batch_source") + and feature_view.batch_source is not None + ): if feature_view.batch_source.field_mapping is not None: table = _run_pyarrow_field_mapping( table, feature_view.batch_source.field_mapping @@ -410,7 +419,10 @@ async def ingest_df_async( ) def ingest_df_to_offline_store(self, feature_view: FeatureView, table: pa.Table): - if feature_view.batch_source.field_mapping is not None: + if ( + feature_view.batch_source is not None + and feature_view.batch_source.field_mapping is not None + ): table = _run_pyarrow_field_mapping( table, feature_view.batch_source.field_mapping ) @@ -482,8 +494,12 @@ def get_historical_features( def retrieve_saved_dataset( self, config: RepoConfig, dataset: SavedDataset ) -> RetrievalJob: + from feast.utils import _strip_version_from_ref + feature_name_columns = [ - ref.replace(":", "__") if dataset.full_feature_names else ref.split(":")[1] + _strip_version_from_ref(ref).replace(":", "__") + if dataset.full_feature_names + else ref.split(":")[1] for ref in dataset.features ] diff --git a/sdk/python/feast/infra/provider.py b/sdk/python/feast/infra/provider.py index c2879c1e2db..9bdf681fb69 100644 --- a/sdk/python/feast/infra/provider.py +++ b/sdk/python/feast/infra/provider.py @@ -316,6 +316,7 @@ def get_online_features( registry: BaseRegistry, project: str, full_feature_names: bool = False, + include_feature_view_version_metadata: bool = False, ) -> OnlineResponse: pass @@ -331,6 +332,7 @@ async def get_online_features_async( registry: BaseRegistry, project: str, full_feature_names: bool = False, + include_feature_view_version_metadata: bool = False, ) -> OnlineResponse: pass @@ -468,6 +470,7 @@ def retrieve_online_documents_v2( top_k: int, distance_metric: Optional[str] = None, query_string: Optional[str] = None, + include_feature_view_version_metadata: bool = False, ) -> List[ Tuple[ Optional[datetime], diff --git a/sdk/python/feast/infra/registry/base_registry.py b/sdk/python/feast/infra/registry/base_registry.py index 24e9f36fbd2..da4f291bc44 100644 --- a/sdk/python/feast/infra/registry/base_registry.py +++ b/sdk/python/feast/infra/registry/base_registry.py @@ -24,6 +24,10 @@ from feast.base_feature_view import BaseFeatureView from feast.data_source import DataSource from feast.entity import Entity +from feast.errors import ( + ConflictingFeatureViewNames, + FeatureViewNotFoundException, +) from feast.feature_service import FeatureService from feast.feature_view import FeatureView from feast.infra.infra_object import Infra @@ -251,7 +255,11 @@ def list_feature_services( # Feature view operations @abstractmethod def apply_feature_view( - self, feature_view: BaseFeatureView, project: str, commit: bool = True + self, + feature_view: BaseFeatureView, + project: str, + commit: bool = True, + no_promote: bool = False, ): """ Registers a single feature view with Feast @@ -260,9 +268,67 @@ def apply_feature_view( feature_view: Feature view that will be registered project: Feast project that this feature view belongs to commit: Whether the change should be persisted immediately + no_promote: If True, save a new version snapshot without promoting + it to the active definition. The new version is accessible only + via explicit @v reads. """ raise NotImplementedError + def _ensure_feature_view_name_is_unique( + self, + feature_view: BaseFeatureView, + project: str, + allow_cache: bool = False, + ): + """ + Validates that no feature view name conflict exists across feature view types. + Raises ConflictingFeatureViewNames if a different type already uses the name. + + This is a defense-in-depth check for direct apply_feature_view() calls. + The primary validation happens in _validate_all_feature_views() during feast plan/apply. + """ + name = feature_view.name + new_type = type(feature_view).__name__ + + def _check_conflict(getter, not_found_exc, existing_type: str): + try: + getter(name, project, allow_cache=allow_cache) + raise ConflictingFeatureViewNames(name, existing_type, new_type) + except not_found_exc: + pass + + # Check StreamFeatureView before FeatureView since StreamFeatureView is a subclass + # Note: All getters raise FeatureViewNotFoundException (not type-specific exceptions) + if isinstance(feature_view, StreamFeatureView): + _check_conflict( + self.get_feature_view, FeatureViewNotFoundException, "FeatureView" + ) + _check_conflict( + self.get_on_demand_feature_view, + FeatureViewNotFoundException, + "OnDemandFeatureView", + ) + elif isinstance(feature_view, FeatureView): + _check_conflict( + self.get_stream_feature_view, + FeatureViewNotFoundException, + "StreamFeatureView", + ) + _check_conflict( + self.get_on_demand_feature_view, + FeatureViewNotFoundException, + "OnDemandFeatureView", + ) + elif isinstance(feature_view, OnDemandFeatureView): + _check_conflict( + self.get_feature_view, FeatureViewNotFoundException, "FeatureView" + ) + _check_conflict( + self.get_stream_feature_view, + FeatureViewNotFoundException, + "StreamFeatureView", + ) + @abstractmethod def delete_feature_view(self, name: str, project: str, commit: bool = True): """ @@ -432,6 +498,46 @@ def list_all_feature_views( """ raise NotImplementedError + def list_feature_view_versions( + self, name: str, project: str + ) -> List[Dict[str, Any]]: + """ + List version history for a feature view. + + Args: + name: Name of feature view + project: Feast project that this feature view belongs to + + Returns: + List of version records with version, version_number, feature_view_type, + created_timestamp, and version_id. + """ + raise NotImplementedError( + "list_feature_view_versions is not implemented for this registry" + ) + + def get_feature_view_by_version( + self, name: str, project: str, version_number: int, allow_cache: bool = False + ) -> BaseFeatureView: + """ + Retrieve a feature view snapshot for a specific version number. + + Args: + name: Name of feature view + project: Feast project that this feature view belongs to + version_number: The version number to retrieve + allow_cache: Whether to allow returning from a cached registry + + Returns: + The feature view snapshot at the specified version. + + Raises: + FeatureViewVersionNotFound: if the version doesn't exist. + """ + raise NotImplementedError( + "get_feature_view_by_version is not implemented for this registry" + ) + @abstractmethod def apply_materialization( self, diff --git a/sdk/python/feast/infra/registry/caching_registry.py b/sdk/python/feast/infra/registry/caching_registry.py index ce346272af9..ad6714d9796 100644 --- a/sdk/python/feast/infra/registry/caching_registry.py +++ b/sdk/python/feast/infra/registry/caching_registry.py @@ -5,7 +5,7 @@ from abc import abstractmethod from datetime import timedelta from threading import Lock -from typing import List, Optional +from typing import Any, Dict, List, Optional from feast.base_feature_view import BaseFeatureView from feast.data_source import DataSource @@ -424,6 +424,13 @@ def list_projects( return proto_registry_utils.list_projects(self.cached_registry_proto, tags) return self._list_projects(tags) + def list_feature_view_versions( + self, name: str, project: str + ) -> List[Dict[str, Any]]: + raise NotImplementedError( + "list_feature_view_versions is not implemented for this registry" + ) + def refresh(self, project: Optional[str] = None): try: self.cached_registry_proto = self.proto() diff --git a/sdk/python/feast/infra/registry/proto_registry_utils.py b/sdk/python/feast/infra/registry/proto_registry_utils.py index 26a5b7e1689..82b7f3e8aaa 100644 --- a/sdk/python/feast/infra/registry/proto_registry_utils.py +++ b/sdk/python/feast/infra/registry/proto_registry_utils.py @@ -10,6 +10,7 @@ EntityNotFoundException, FeatureServiceNotFoundException, FeatureViewNotFoundException, + FeatureViewVersionNotFound, PermissionObjectNotFoundException, ProjectObjectNotFoundException, SavedDatasetNotFound, @@ -147,6 +148,49 @@ def get_any_feature_view( raise FeatureViewNotFoundException(name, project) +def get_feature_view_by_version( + registry_proto: RegistryProto, name: str, project: str, version_number: int +) -> BaseFeatureView: + """Retrieve a feature view snapshot for a specific version from version history.""" + from feast.protos.feast.core.FeatureView_pb2 import ( + FeatureView as FeatureViewProto, + ) + from feast.protos.feast.core.OnDemandFeatureView_pb2 import ( + OnDemandFeatureView as OnDemandFeatureViewProto, + ) + from feast.protos.feast.core.StreamFeatureView_pb2 import ( + StreamFeatureView as StreamFeatureViewProto, + ) + from feast.version_utils import version_tag + + for record in registry_proto.feature_view_version_history.records: + if ( + record.feature_view_name == name + and record.project_id == project + and record.version_number == version_number + ): + if record.feature_view_type == "feature_view": + fv_proto = FeatureViewProto.FromString(record.feature_view_proto) + fv = FeatureView.from_proto(fv_proto) + elif record.feature_view_type == "stream_feature_view": + sfv_proto = StreamFeatureViewProto.FromString(record.feature_view_proto) + fv = StreamFeatureView.from_proto(sfv_proto) + elif record.feature_view_type == "on_demand_feature_view": + odfv_proto = OnDemandFeatureViewProto.FromString( + record.feature_view_proto + ) + fv = OnDemandFeatureView.from_proto(odfv_proto) + else: + raise ValueError( + f"Unknown feature view type: {record.feature_view_type}" + ) + + fv.current_version_number = version_number + return fv + + raise FeatureViewVersionNotFound(name, version_tag(version_number), project) + + def get_feature_view( registry_proto: RegistryProto, name: str, project: str ) -> FeatureView: diff --git a/sdk/python/feast/infra/registry/registry.py b/sdk/python/feast/infra/registry/registry.py index ff9c1f405a1..76da6ad831d 100644 --- a/sdk/python/feast/infra/registry/registry.py +++ b/sdk/python/feast/infra/registry/registry.py @@ -31,6 +31,8 @@ EntityNotFoundException, FeatureServiceNotFoundException, FeatureViewNotFoundException, + FeatureViewPinConflict, + FeatureViewVersionNotFound, PermissionNotFoundException, ProjectNotFoundException, ProjectObjectNotFoundException, @@ -48,12 +50,18 @@ from feast.permissions.permission import Permission from feast.project import Project from feast.project_metadata import ProjectMetadata +from feast.protos.feast.core.FeatureViewVersion_pb2 import FeatureViewVersionRecord from feast.protos.feast.core.Registry_pb2 import Registry as RegistryProto from feast.repo_config import RegistryConfig from feast.repo_contents import RepoContents from feast.saved_dataset import SavedDataset, ValidationReference from feast.stream_feature_view import StreamFeatureView from feast.utils import _utc_now +from feast.version_utils import ( + generate_version_id, + parse_version, + version_tag, +) REGISTRY_SCHEMA_VERSION = "1" @@ -221,6 +229,12 @@ def __init__( else False ) + self.enable_online_versioning = ( + registry_config.enable_online_feature_view_versioning + if registry_config is not None + else False + ) + self.cache_mode = ( registry_config.cache_mode if registry_config is not None else "sync" ) @@ -470,8 +484,197 @@ def get_entity(self, name: str, project: str, allow_cache: bool = False) -> Enti ) return proto_registry_utils.get_entity(registry_proto, name, project) + def _infer_fv_type_string(self, feature_view) -> str: + if isinstance(feature_view, StreamFeatureView): + return "stream_feature_view" + elif isinstance(feature_view, FeatureView): + return "feature_view" + elif isinstance(feature_view, OnDemandFeatureView): + return "on_demand_feature_view" + else: + raise ValueError(f"Unexpected feature view type: {type(feature_view)}") + + def _proto_class_for_type(self, fv_type: str): + from feast.protos.feast.core.FeatureView_pb2 import ( + FeatureView as FeatureViewProto, + ) + from feast.protos.feast.core.OnDemandFeatureView_pb2 import ( + OnDemandFeatureView as OnDemandFeatureViewProto, + ) + from feast.protos.feast.core.StreamFeatureView_pb2 import ( + StreamFeatureView as StreamFeatureViewProto, + ) + + if fv_type == "stream_feature_view": + return StreamFeatureViewProto, StreamFeatureView + elif fv_type == "feature_view": + return FeatureViewProto, FeatureView + elif fv_type == "on_demand_feature_view": + return OnDemandFeatureViewProto, OnDemandFeatureView + else: + raise ValueError(f"Unknown feature view type: {fv_type}") + + def _next_version_number(self, name: str, project: str) -> int: + history = self.cached_registry_proto.feature_view_version_history + max_ver = -1 + for record in history.records: + if record.feature_view_name == name and record.project_id == project: + if record.version_number > max_ver: + max_ver = record.version_number + return max_ver + 1 + + def _get_version_record( + self, name: str, project: str, version_number: int + ) -> Optional[FeatureViewVersionRecord]: + history = self.cached_registry_proto.feature_view_version_history + for record in history.records: + if ( + record.feature_view_name == name + and record.project_id == project + and record.version_number == version_number + ): + return record + return None + + def _update_metadata_fields( + self, existing_proto: Any, updated_fv: BaseFeatureView + ) -> None: + """Update non-version-significant fields without creating new version.""" + from feast.feature_view import FeatureView + + # Metadata fields + existing_proto.spec.description = updated_fv.description + existing_proto.spec.tags.clear() + existing_proto.spec.tags.update(updated_fv.tags) + existing_proto.spec.owner = updated_fv.owner + if hasattr(existing_proto.spec, "version") and hasattr(updated_fv, "version"): + existing_proto.spec.version = getattr(updated_fv, "version") + + # Configuration fields (FeatureView) + if ( + hasattr(existing_proto.spec, "ttl") + and hasattr(updated_fv, "ttl") + and updated_fv.ttl + ): + if isinstance(updated_fv, FeatureView): + ttl_duration = updated_fv.get_ttl_duration() + if ttl_duration: + existing_proto.spec.ttl.CopyFrom(ttl_duration) + if hasattr(existing_proto.spec, "online") and hasattr(updated_fv, "online"): + existing_proto.spec.online = getattr(updated_fv, "online") + if hasattr(existing_proto.spec, "offline") and hasattr(updated_fv, "offline"): + existing_proto.spec.offline = getattr(updated_fv, "offline") + if hasattr(existing_proto.spec, "enable_validation") and hasattr( + updated_fv, "enable_validation" + ): + existing_proto.spec.enable_validation = getattr( + updated_fv, "enable_validation" + ) + + # OnDemandFeatureView configuration + if hasattr(existing_proto.spec, "write_to_online_store") and hasattr( + updated_fv, "write_to_online_store" + ): + existing_proto.spec.write_to_online_store = getattr( + updated_fv, "write_to_online_store" + ) + if hasattr(existing_proto.spec, "singleton") and hasattr( + updated_fv, "singleton" + ): + existing_proto.spec.singleton = getattr(updated_fv, "singleton") + + # Data sources (treat as configuration) + if ( + hasattr(existing_proto.spec, "batch_source") + and hasattr(updated_fv, "batch_source") + and updated_fv.batch_source + ): + existing_proto.spec.batch_source.CopyFrom( + updated_fv.batch_source.to_proto() + ) + if ( + hasattr(existing_proto.spec, "stream_source") + and hasattr(updated_fv, "stream_source") + and updated_fv.stream_source + ): + existing_proto.spec.stream_source.CopyFrom( + updated_fv.stream_source.to_proto() + ) + + # Update or clear version pin + if hasattr(existing_proto.meta, "current_version_number") and hasattr( + updated_fv, "current_version_number" + ): + if updated_fv.current_version_number is not None: + existing_proto.meta.current_version_number = ( + updated_fv.current_version_number + ) + else: + # Unpin: reset to proto default (0). + # from_proto interprets cvn=0 with spec.version="latest" as None. + existing_proto.meta.current_version_number = 0 + + # Update timestamp + existing_proto.meta.last_updated_timestamp.FromDatetime(_utc_now()) + + def _save_version_record( + self, + name: str, + project: str, + version_number: int, + fv_type: str, + proto_bytes: bytes, + ): + now = _utc_now() + record = FeatureViewVersionRecord( + feature_view_name=name, + project_id=project, + version_number=version_number, + feature_view_type=fv_type, + feature_view_proto=proto_bytes, + description="", + version_id=generate_version_id(), + ) + record.created_timestamp.FromDatetime(now) + self.cached_registry_proto.feature_view_version_history.records.append(record) + + def list_feature_view_versions( + self, name: str, project: str + ) -> List[Dict[str, Any]]: + history = self.cached_registry_proto.feature_view_version_history + results = [] + for record in history.records: + if record.feature_view_name == name and record.project_id == project: + results.append( + { + "version": version_tag(record.version_number), + "version_number": record.version_number, + "feature_view_type": record.feature_view_type, + "created_timestamp": record.created_timestamp.ToDatetime(), + "version_id": record.version_id, + } + ) + results.sort(key=lambda r: r["version_number"]) + return results + + def get_feature_view_by_version( + self, name: str, project: str, version_number: int, allow_cache: bool = False + ) -> BaseFeatureView: + record = self._get_version_record(name, project, version_number) + if record is None: + raise FeatureViewVersionNotFound(name, version_tag(version_number), project) + proto_class, python_class = self._proto_class_for_type(record.feature_view_type) + snap_proto = proto_class.FromString(record.feature_view_proto) + fv = python_class.from_proto(snap_proto) + fv.current_version_number = version_number + return fv + def apply_feature_view( - self, feature_view: BaseFeatureView, project: str, commit: bool = True + self, + feature_view: BaseFeatureView, + project: str, + commit: bool = True, + no_promote: bool = False, ): feature_view.ensure_valid() @@ -480,6 +683,73 @@ def apply_feature_view( feature_view.created_timestamp = now feature_view.last_updated_timestamp = now + fv_type_str = self._infer_fv_type_string(feature_view) + is_latest, pin_version = parse_version(feature_view.version) + + if not is_latest: + # Explicit version: check if it exists (pin/revert) or not (forward declaration). + # Note: The file registry is last-write-wins for true concurrent races — + # this is a pre-existing limitation for all file registry operations. + # For multi-client environments, use the SQL registry. + record = self._get_version_record(feature_view.name, project, pin_version) + + if record is not None: + # Version exists → pin/revert to that snapshot + # Check that the user hasn't also modified the definition. + # Compare user's FV (with version="latest") against active FV. + self._prepare_registry_for_changes(project) + try: + active_fv = proto_registry_utils.get_any_feature_view( + self.cached_registry_proto, feature_view.name, project + ) + user_fv_copy = feature_view.__copy__() + user_fv_copy.version = "latest" + active_fv.version = "latest" + # Clear metadata that differs due to registry state + user_fv_copy.created_timestamp = active_fv.created_timestamp + user_fv_copy.last_updated_timestamp = ( + active_fv.last_updated_timestamp + ) + user_fv_copy.current_version_number = ( + active_fv.current_version_number + ) + if hasattr(active_fv, "materialization_intervals"): + user_fv_copy.materialization_intervals = ( + active_fv.materialization_intervals + ) + if user_fv_copy != active_fv: + raise FeatureViewPinConflict( + feature_view.name, version_tag(pin_version) + ) + except FeatureViewNotFoundException: + pass + + proto_class, python_class = self._proto_class_for_type( + record.feature_view_type + ) + snap_proto = proto_class.FromString(record.feature_view_proto) + restored_fv = python_class.from_proto(snap_proto) + restored_fv.version = feature_view.version + restored_fv.current_version_number = pin_version + restored_fv.last_updated_timestamp = now + # Apply the restored FV using the standard path below + feature_view = restored_fv + else: + # Version doesn't exist → forward declaration: create it + feature_view.current_version_number = pin_version + feature_view_proto = feature_view.to_proto() + feature_view_proto.spec.project = project + snapshot_proto_bytes = feature_view_proto.SerializeToString() + self._prepare_registry_for_changes(project) + self._save_version_record( + feature_view.name, + project, + pin_version, + fv_type_str, + snapshot_proto_bytes, + ) + # Fall through to apply the FV as active (with current_version_number set) + feature_view_proto = feature_view.to_proto() feature_view_proto.spec.project = project self._prepare_registry_for_changes(project) @@ -502,6 +772,7 @@ def apply_feature_view( else: raise ValueError(f"Unexpected feature view type: {type(feature_view)}") + old_proto_bytes = None for idx, existing_feature_view_proto in enumerate( existing_feature_views_of_same_type ): @@ -509,12 +780,22 @@ def apply_feature_view( existing_feature_view_proto.spec.name == feature_view_proto.spec.name and existing_feature_view_proto.spec.project == project ): - if ( - feature_view.__class__.from_proto(existing_feature_view_proto) - == feature_view - ): + existing_feature_view = feature_view.__class__.from_proto( + existing_feature_view_proto + ) + if not feature_view._schema_or_udf_changed(existing_feature_view): + # Update non-version-significant fields in place + self._update_metadata_fields( + existing_feature_view_proto, feature_view + ) + if commit: + self.commit() return else: + old_proto_bytes = existing_feature_view_proto.SerializeToString() + # Save a copy before deletion for no_promote restore + existing_proto_copy = type(existing_feature_view_proto)() + existing_proto_copy.CopyFrom(existing_feature_view_proto) existing_feature_view = type(feature_view).from_proto( existing_feature_view_proto ) @@ -530,6 +811,54 @@ def apply_feature_view( del existing_feature_views_of_same_type[idx] break + # Version history tracking + if is_latest: + if old_proto_bytes is not None: + # FV changed: save old as a version if first time, then save new + next_ver = self._next_version_number(feature_view.name, project) + if next_ver == 0: + self._save_version_record( + feature_view.name, project, 0, fv_type_str, old_proto_bytes + ) + next_ver = 1 + + if no_promote: + # Save version snapshot but keep the old active definition + no_promote_fv = feature_view.__copy__() + no_promote_fv.current_version_number = next_ver + no_promote_proto = no_promote_fv.to_proto() + no_promote_proto.spec.project = project + no_promote_proto_bytes = no_promote_proto.SerializeToString() + self._save_version_record( + feature_view.name, + project, + next_ver, + fv_type_str, + no_promote_proto_bytes, + ) + # Re-insert the old active definition (was deleted above) + existing_feature_views_of_same_type.append(existing_proto_copy) + if commit: + self.commit() + return + + feature_view.current_version_number = next_ver + feature_view_proto = feature_view.to_proto() + feature_view_proto.spec.project = project + new_proto_bytes = feature_view_proto.SerializeToString() + self._save_version_record( + feature_view.name, project, next_ver, fv_type_str, new_proto_bytes + ) + else: + # New FV: save as v0 + feature_view.current_version_number = 0 + feature_view_proto = feature_view.to_proto() + feature_view_proto.spec.project = project + new_proto_bytes = feature_view_proto.SerializeToString() + self._save_version_record( + feature_view.name, project, 0, fv_type_str, new_proto_bytes + ) + existing_feature_views_of_same_type.append(feature_view_proto) if commit: self.commit() @@ -706,6 +1035,7 @@ def delete_feature_view(self, name: str, project: str, commit: bool = True): self._prepare_registry_for_changes(project) assert self.cached_registry_proto + found = False for idx, existing_feature_view_proto in enumerate( self.cached_registry_proto.feature_views ): @@ -714,35 +1044,48 @@ def delete_feature_view(self, name: str, project: str, commit: bool = True): and existing_feature_view_proto.spec.project == project ): del self.cached_registry_proto.feature_views[idx] - if commit: - self.commit() - return + found = True + break - for idx, existing_on_demand_feature_view_proto in enumerate( - self.cached_registry_proto.on_demand_feature_views - ): - if ( - existing_on_demand_feature_view_proto.spec.name == name - and existing_on_demand_feature_view_proto.spec.project == project + if not found: + for idx, existing_on_demand_feature_view_proto in enumerate( + self.cached_registry_proto.on_demand_feature_views ): - del self.cached_registry_proto.on_demand_feature_views[idx] - if commit: - self.commit() - return + if ( + existing_on_demand_feature_view_proto.spec.name == name + and existing_on_demand_feature_view_proto.spec.project == project + ): + del self.cached_registry_proto.on_demand_feature_views[idx] + found = True + break - for idx, existing_stream_feature_view_proto in enumerate( - self.cached_registry_proto.stream_feature_views - ): - if ( - existing_stream_feature_view_proto.spec.name == name - and existing_stream_feature_view_proto.spec.project == project + if not found: + for idx, existing_stream_feature_view_proto in enumerate( + self.cached_registry_proto.stream_feature_views ): - del self.cached_registry_proto.stream_feature_views[idx] - if commit: - self.commit() - return + if ( + existing_stream_feature_view_proto.spec.name == name + and existing_stream_feature_view_proto.spec.project == project + ): + del self.cached_registry_proto.stream_feature_views[idx] + found = True + break + + if not found: + raise FeatureViewNotFoundException(name, project) - raise FeatureViewNotFoundException(name, project) + # Clean up version history for the deleted feature view + history = self.cached_registry_proto.feature_view_version_history + indices_to_remove = [ + i + for i, record in enumerate(history.records) + if record.feature_view_name == name and record.project_id == project + ] + for i in reversed(indices_to_remove): + del history.records[i] + + if commit: + self.commit() def delete_entity(self, name: str, project: str, commit: bool = True): self._prepare_registry_for_changes(project) diff --git a/sdk/python/feast/infra/registry/remote.py b/sdk/python/feast/infra/registry/remote.py index 8fc0db55c27..c553a55f754 100644 --- a/sdk/python/feast/infra/registry/remote.py +++ b/sdk/python/feast/infra/registry/remote.py @@ -217,7 +217,11 @@ def list_feature_services( ] def apply_feature_view( - self, feature_view: BaseFeatureView, project: str, commit: bool = True + self, + feature_view: BaseFeatureView, + project: str, + commit: bool = True, + no_promote: bool = False, ): if isinstance(feature_view, StreamFeatureView): arg_name = "stream_feature_view" diff --git a/sdk/python/feast/infra/registry/snowflake.py b/sdk/python/feast/infra/registry/snowflake.py index 12299572f04..68bf376e650 100644 --- a/sdk/python/feast/infra/registry/snowflake.py +++ b/sdk/python/feast/infra/registry/snowflake.py @@ -259,8 +259,18 @@ def apply_feature_service( ) def apply_feature_view( - self, feature_view: BaseFeatureView, project: str, commit: bool = True + self, + feature_view: BaseFeatureView, + project: str, + commit: bool = True, + no_promote: bool = False, ): + if no_promote: + raise NotImplementedError( + "Feature view versioning (no_promote) is not supported by the Snowflake registry. " + "Use the SQL registry or file registry for versioning support." + ) + feature_view.ensure_valid() fv_table_str = self._infer_fv_table(feature_view) fv_column_name = fv_table_str[:-1] return self._apply_object( diff --git a/sdk/python/feast/infra/registry/sql.py b/sdk/python/feast/infra/registry/sql.py index 103b1f6c0a6..ae09c8e52b6 100644 --- a/sdk/python/feast/infra/registry/sql.py +++ b/sdk/python/feast/infra/registry/sql.py @@ -11,6 +11,7 @@ BigInteger, Column, Index, + Integer, LargeBinary, MetaData, String, @@ -18,21 +19,26 @@ Text, create_engine, delete, + func, insert, select, update, ) from sqlalchemy.engine import Engine +from sqlalchemy.exc import IntegrityError from feast import utils from feast.base_feature_view import BaseFeatureView from feast.data_source import DataSource from feast.entity import Entity from feast.errors import ( + ConcurrentVersionConflict, DataSourceObjectNotFoundException, EntityNotFoundException, FeatureServiceNotFoundException, FeatureViewNotFoundException, + FeatureViewPinConflict, + FeatureViewVersionNotFound, PermissionNotFoundException, ProjectNotFoundException, ProjectObjectNotFoundException, @@ -71,6 +77,11 @@ from feast.saved_dataset import SavedDataset, ValidationReference from feast.stream_feature_view import StreamFeatureView from feast.utils import _utc_now +from feast.version_utils import ( + generate_version_id, + parse_version, + version_tag, +) metadata = MetaData() @@ -199,6 +210,24 @@ Index("idx_permissions_project_id", permissions.c.project_id) +feature_view_version_history = Table( + "feature_view_version_history", + metadata, + Column("feature_view_name", String(255), primary_key=True), + Column("project_id", String(255), primary_key=True), + Column("version_number", Integer, primary_key=True), + Column("feature_view_type", String(50), nullable=False), + Column("feature_view_proto", LargeBinary, nullable=False), + Column("created_timestamp", BigInteger, nullable=False), + Column("description", Text, nullable=True), + Column("version_id", String(36), nullable=False), +) + +Index( + "idx_fv_version_history_project_id", + feature_view_version_history.c.project_id, +) + class FeastMetadataKeys(Enum): LAST_UPDATED_TIMESTAMP = "last_updated_timestamp" @@ -266,6 +295,9 @@ def __init__( registry_config.thread_pool_executor_worker_count ) self.purge_feast_metadata = registry_config.purge_feast_metadata + self.enable_online_versioning = ( + registry_config.enable_online_feature_view_versioning + ) super().__init__( project=project, cache_ttl_seconds=registry_config.cache_ttl_seconds, @@ -301,15 +333,21 @@ def _sync_feast_metadata_to_projects_table(self): # Find object in feast_metadata_projects but not in projects projects_to_sync = set(feast_metadata_projects.keys()) - set(projects_set) for project_name in projects_to_sync: - self.apply_project( - Project( - name=project_name, - created_timestamp=datetime.fromtimestamp( - feast_metadata_projects[project_name], tz=timezone.utc + try: + self.apply_project( + Project( + name=project_name, + created_timestamp=datetime.fromtimestamp( + feast_metadata_projects[project_name], tz=timezone.utc + ), ), - ), - commit=True, - ) + commit=True, + ) + except IntegrityError: + logger.info( + "Project %s already created in projects table by another process.", + project_name, + ) if self.purge_feast_metadata: with self.write_engine.begin() as conn: @@ -330,6 +368,7 @@ def teardown(self): saved_datasets, validation_references, permissions, + feature_view_version_history, }: with self.write_engine.begin() as conn: stmt = delete(t) @@ -522,17 +561,36 @@ def delete_entity(self, name: str, project: str, commit: bool = True): ) def delete_feature_view(self, name: str, project: str, commit: bool = True): - deleted_count = 0 - for table in { - feature_views, - on_demand_feature_views, - stream_feature_views, - }: - deleted_count += self._delete_object( - table, name, project, "feature_view_name", None + with self.write_engine.begin() as conn: + deleted_count = 0 + for table in { + feature_views, + on_demand_feature_views, + stream_feature_views, + }: + stmt = delete(table).where( + table.c.feature_view_name == name, + table.c.project_id == project, + ) + rows = conn.execute(stmt) + deleted_count += rows.rowcount + if deleted_count == 0: + raise FeatureViewNotFoundException(name, project) + # Clean up version history in the same transaction + stmt = delete(feature_view_version_history).where( + feature_view_version_history.c.feature_view_name == name, + feature_view_version_history.c.project_id == project, ) - if deleted_count == 0: - raise FeatureViewNotFoundException(name, project) + conn.execute(stmt) + + self.apply_project( + self.get_project(name=project, allow_cache=False), commit=True + ) + if not self.purge_feast_metadata: + with self.write_engine.begin() as conn: + self._set_last_updated_metadata(_utc_now(), project, conn) + if self.cache_mode == "sync": + self.refresh() def delete_feature_service(self, name: str, project: str, commit: bool = True): return self._delete_object( @@ -575,14 +633,229 @@ def apply_data_source( ) def apply_feature_view( - self, feature_view: BaseFeatureView, project: str, commit: bool = True + self, + feature_view: BaseFeatureView, + project: str, + commit: bool = True, + no_promote: bool = False, ): + feature_view.ensure_valid() + self._ensure_feature_view_name_is_unique(feature_view, project) fv_table = self._infer_fv_table(feature_view) + fv_type_str = self._infer_fv_type_string(feature_view) - return self._apply_object( + is_latest, pin_version = parse_version(feature_view.version) + + if not is_latest: + # Explicit version: check if it exists (pin/revert) or not (forward declaration) + snapshot = self._get_version_snapshot( + feature_view.name, project, pin_version + ) + + if snapshot is not None: + # Version exists → pin/revert to that snapshot + # Check that the user hasn't also modified the definition. + # Compare user's FV (with version="latest") against active FV. + try: + active_fv = self._get_any_feature_view(feature_view.name, project) + user_fv_copy = feature_view.__copy__() + user_fv_copy.version = "latest" + active_fv.version = "latest" + # Clear metadata that differs due to registry state + user_fv_copy.created_timestamp = active_fv.created_timestamp + user_fv_copy.last_updated_timestamp = ( + active_fv.last_updated_timestamp + ) + user_fv_copy.current_version_number = ( + active_fv.current_version_number + ) + if hasattr(active_fv, "materialization_intervals"): + user_fv_copy.materialization_intervals = ( + active_fv.materialization_intervals + ) + if user_fv_copy != active_fv: + raise FeatureViewPinConflict( + feature_view.name, version_tag(pin_version) + ) + except FeatureViewNotFoundException: + pass + + snap_type, snap_proto_bytes = snapshot + proto_class, python_class = self._proto_class_for_type(snap_type) + snap_proto = proto_class.FromString(snap_proto_bytes) + restored_fv = python_class.from_proto(snap_proto) + restored_fv.version = feature_view.version + restored_fv.current_version_number = pin_version + return self._apply_object( + fv_table, + project, + "feature_view_name", + restored_fv, + "feature_view_proto", + ) + else: + # Version doesn't exist → forward declaration: create it + feature_view.current_version_number = pin_version + snapshot_proto = feature_view.to_proto() + snapshot_proto.spec.project = project + snapshot_proto_bytes = snapshot_proto.SerializeToString() + try: + self._save_version_snapshot( + feature_view.name, + project, + pin_version, + fv_type_str, + snapshot_proto_bytes, + ) + except IntegrityError: + raise ConcurrentVersionConflict( + f"Version v{pin_version} of '{feature_view.name}' was just created by " + f"another concurrent apply. Pull latest and retry." + ) + # Apply the FV as active + return self._apply_object( + fv_table, + project, + "feature_view_name", + feature_view, + "feature_view_proto", + ) + + # Normal (latest) apply: snapshot old version if changed, then save new + # First check if the FV already exists so we can snapshot the old one. + # Use write_engine for both reads to avoid read replica lag issues. + old_proto_bytes = None + with self.write_engine.begin() as conn: + stmt = select(fv_table).where( + fv_table.c.feature_view_name == feature_view.name, + fv_table.c.project_id == project, + ) + row = conn.execute(stmt).first() + if row: + old_proto_bytes = row._mapping["feature_view_proto"] + + # Apply the object (handles idempotency check internally) + # We need to detect if _apply_object actually made a change + # by checking before/after + self._apply_object( fv_table, project, "feature_view_name", feature_view, "feature_view_proto" ) + # After apply, read the current proto to see if it changed + with self.write_engine.begin() as conn: + stmt = select(fv_table).where( + fv_table.c.feature_view_name == feature_view.name, + fv_table.c.project_id == project, + ) + row = conn.execute(stmt).first() + if row: + new_proto_bytes = row._mapping["feature_view_proto"] + else: + return # shouldn't happen + + if old_proto_bytes is not None: + # Deserialize both versions to compare schema/UDF changes + proto_class, fv_class = self._proto_class_for_type(fv_type_str) + old_proto = proto_class.FromString(old_proto_bytes) + new_proto = proto_class.FromString(new_proto_bytes) + + old_fv = fv_class.from_proto(old_proto) + new_fv = fv_class.from_proto(new_proto) + + if not new_fv._schema_or_udf_changed(old_fv): + # No version-significant change, skip version creation + return + + # Something changed (or new FV). Save version snapshot(s). + if old_proto_bytes is not None: + # Snapshot the old version first (if not already in history) + next_ver = self._get_next_version_number(feature_view.name, project) + if next_ver == 0: + # First time versioning: save old as v0 + self._save_version_snapshot( + feature_view.name, + project, + 0, + fv_type_str, + old_proto_bytes, + ) + next_ver = 1 + + # Retry loop: if a concurrent apply claimed the same version number, + # re-read MAX+1 and try again. The client said "latest" so the + # exact number doesn't matter. + max_retries = 3 + for attempt in range(max_retries): + # Update current_version_number before saving snapshot + feature_view.current_version_number = next_ver + snapshot_proto = feature_view.to_proto() + snapshot_proto.spec.project = project + snapshot_proto_bytes = snapshot_proto.SerializeToString() + + try: + # Save new as next version (with correct current_version_number) + self._save_version_snapshot( + feature_view.name, + project, + next_ver, + fv_type_str, + snapshot_proto_bytes, + ) + break + except IntegrityError: + if attempt == max_retries - 1: + raise ConcurrentVersionConflict( + f"Failed to assign version for '{feature_view.name}' after " + f"{max_retries} attempts due to concurrent applies. " + f"Please retry." + ) + # Re-read the next available version number + next_ver = self._get_next_version_number(feature_view.name, project) + + if no_promote: + # Save version snapshot but skip updating the active row. + # The new version is accessible only via explicit @v reads. + return + + # Re-serialize with updated version number + with self.write_engine.begin() as conn: + update_stmt = ( + update(fv_table) + .where( + fv_table.c.feature_view_name == feature_view.name, + fv_table.c.project_id == project, + ) + .values( + feature_view_proto=snapshot_proto_bytes, + ) + ) + conn.execute(update_stmt) + else: + # New FV: save as v0 + feature_view.current_version_number = 0 + snapshot_proto = feature_view.to_proto() + snapshot_proto.spec.project = project + snapshot_proto_bytes = snapshot_proto.SerializeToString() + self._save_version_snapshot( + feature_view.name, + project, + 0, + fv_type_str, + snapshot_proto_bytes, + ) + with self.write_engine.begin() as conn: + update_stmt = ( + update(fv_table) + .where( + fv_table.c.feature_view_name == feature_view.name, + fv_table.c.project_id == project, + ) + .values( + feature_view_proto=snapshot_proto_bytes, + ) + ) + conn.execute(update_stmt) + def apply_feature_service( self, feature_service: FeatureService, project: str, commit: bool = True ): @@ -821,6 +1094,118 @@ def _infer_fv_classes(self, feature_view): raise ValueError(f"Unexpected feature view type: {type(feature_view)}") return python_class, proto_class + def _infer_fv_type_string(self, feature_view) -> str: + if isinstance(feature_view, StreamFeatureView): + return "stream_feature_view" + elif isinstance(feature_view, FeatureView): + return "feature_view" + elif isinstance(feature_view, OnDemandFeatureView): + return "on_demand_feature_view" + else: + raise ValueError(f"Unexpected feature view type: {type(feature_view)}") + + def _proto_class_for_type(self, fv_type: str): + if fv_type == "stream_feature_view": + return StreamFeatureViewProto, StreamFeatureView + elif fv_type == "feature_view": + return FeatureViewProto, FeatureView + elif fv_type == "on_demand_feature_view": + return OnDemandFeatureViewProto, OnDemandFeatureView + else: + raise ValueError(f"Unknown feature view type: {fv_type}") + + def _get_next_version_number(self, name: str, project: str) -> int: + with self.write_engine.begin() as conn: + stmt = select( + func.coalesce( + func.max(feature_view_version_history.c.version_number) + 1, 0 + ) + ).where( + feature_view_version_history.c.feature_view_name == name, + feature_view_version_history.c.project_id == project, + ) + result = conn.execute(stmt).scalar() + return result or 0 + + def _save_version_snapshot( + self, + name: str, + project: str, + version_number: int, + fv_type: str, + proto_bytes: bytes, + ): + now = int(_utc_now().timestamp()) + vid = generate_version_id() + with self.write_engine.begin() as conn: + stmt = insert(feature_view_version_history).values( + feature_view_name=name, + project_id=project, + version_number=version_number, + feature_view_type=fv_type, + feature_view_proto=proto_bytes, + created_timestamp=now, + description="", + version_id=vid, + ) + conn.execute(stmt) + + def _get_version_snapshot( + self, name: str, project: str, version_number: int + ) -> Optional[tuple]: + with self.read_engine.begin() as conn: + stmt = select(feature_view_version_history).where( + feature_view_version_history.c.feature_view_name == name, + feature_view_version_history.c.project_id == project, + feature_view_version_history.c.version_number == version_number, + ) + row = conn.execute(stmt).first() + if row: + return ( + row._mapping["feature_view_type"], + row._mapping["feature_view_proto"], + ) + return None + + def get_feature_view_by_version( + self, name: str, project: str, version_number: int, allow_cache: bool = False + ) -> BaseFeatureView: + snapshot = self._get_version_snapshot(name, project, version_number) + if snapshot is None: + raise FeatureViewVersionNotFound(name, version_tag(version_number), project) + snap_type, snap_proto_bytes = snapshot + proto_class, python_class = self._proto_class_for_type(snap_type) + snap_proto = proto_class.FromString(snap_proto_bytes) + fv = python_class.from_proto(snap_proto) + fv.current_version_number = version_number + return fv + + def list_feature_view_versions( + self, name: str, project: str + ) -> List[Dict[str, Any]]: + with self.read_engine.begin() as conn: + stmt = ( + select(feature_view_version_history) + .where( + feature_view_version_history.c.feature_view_name == name, + feature_view_version_history.c.project_id == project, + ) + .order_by(feature_view_version_history.c.version_number) + ) + rows = conn.execute(stmt).all() + return [ + { + "version": version_tag(row._mapping["version_number"]), + "version_number": row._mapping["version_number"], + "feature_view_type": row._mapping["feature_view_type"], + "created_timestamp": datetime.fromtimestamp( + row._mapping["created_timestamp"], tz=timezone.utc + ), + "version_id": row._mapping["version_id"], + } + for row in rows + ] + def get_user_metadata( self, project: str, feature_view: BaseFeatureView ) -> Optional[bytes]: @@ -995,10 +1380,16 @@ def _apply_object( "last_updated_timestamp": update_time, "project_id": project, } - insert_stmt = insert(table).values( - values, - ) - conn.execute(insert_stmt) + try: + with conn.begin_nested(): + conn.execute(insert(table).values(values)) + except IntegrityError: + logger.info( + "Object %s in project %s already created by another " + "process, skipping.", + name, + project, + ) if not isinstance(obj, Project): self.apply_project( @@ -1028,8 +1419,15 @@ def _maybe_init_project_metadata(self, project): "last_updated_timestamp": update_time, "project_id": project, } - insert_stmt = insert(feast_metadata).values(values) - conn.execute(insert_stmt) + try: + with conn.begin_nested(): + conn.execute(insert(feast_metadata).values(values)) + except IntegrityError: + logger.info( + "Project metadata for %s already initialized by " + "another process.", + project, + ) def _delete_object( self, diff --git a/sdk/python/feast/infra/transformation_servers/Dockerfile b/sdk/python/feast/infra/transformation_servers/Dockerfile index 6e66aaebeae..b0880e960e1 100644 --- a/sdk/python/feast/infra/transformation_servers/Dockerfile +++ b/sdk/python/feast/infra/transformation_servers/Dockerfile @@ -15,7 +15,7 @@ COPY pyproject.toml pyproject.toml COPY README.md README.md # Install dependencies -RUN --mount=source=.git,target=.git,type=bind uv pip install --system --no-cache-dir '.[gcp,aws]' +RUN --mount=source=.git,target=.git,type=bind uv pip install --system --no-cache-dir '.[gcp,aws,grpcio]' # Start feature transformation server CMD [ "python", "app.py" ] diff --git a/sdk/python/feast/infra/utils/postgres/postgres_config.py b/sdk/python/feast/infra/utils/postgres/postgres_config.py index a4ebb456ef1..60099ede999 100644 --- a/sdk/python/feast/infra/utils/postgres/postgres_config.py +++ b/sdk/python/feast/infra/utils/postgres/postgres_config.py @@ -21,7 +21,7 @@ class PostgreSQLConfig(FeastConfigBaseModel): db_schema: StrictStr = "public" user: StrictStr password: StrictStr - sslmode: Optional[StrictStr] = None + sslmode: Optional[StrictStr] = "require" sslkey_path: Optional[StrictStr] = None sslcert_path: Optional[StrictStr] = None sslrootcert_path: Optional[StrictStr] = None diff --git a/sdk/python/feast/infra/utils/snowflake/snowpark/snowflake_udfs.py b/sdk/python/feast/infra/utils/snowflake/snowpark/snowflake_udfs.py index 277d8e18946..23026d79109 100644 --- a/sdk/python/feast/infra/utils/snowflake/snowpark/snowflake_udfs.py +++ b/sdk/python/feast/infra/utils/snowflake/snowpark/snowflake_udfs.py @@ -23,6 +23,8 @@ HANDLER = 'feast.infra.utils.snowflake.snowpark.snowflake_udfs.feast_snowflake_binary_to_bytes_proto' IMPORTS = ('@feast_stage/feast.zip'); """ + + # ValueType.BYTES = 1 @vectorized(input=pandas.DataFrame) def feast_snowflake_binary_to_bytes_proto(df): @@ -46,6 +48,8 @@ def feast_snowflake_binary_to_bytes_proto(df): HANDLER = 'feast.infra.utils.snowflake.snowpark.snowflake_udfs.feast_snowflake_varchar_to_string_proto' IMPORTS = ('@feast_stage/feast.zip'); """ + + # ValueType.STRING = 2 @vectorized(input=pandas.DataFrame) def feast_snowflake_varchar_to_string_proto(df): @@ -69,6 +73,8 @@ def feast_snowflake_varchar_to_string_proto(df): HANDLER = 'feast.infra.utils.snowflake.snowpark.snowflake_udfs.feast_snowflake_array_bytes_to_list_bytes_proto' IMPORTS = ('@feast_stage/feast.zip'); """ + + # ValueType.STRING_LIST = 12 @vectorized(input=pandas.DataFrame) def feast_snowflake_array_bytes_to_list_bytes_proto(df): @@ -243,6 +249,8 @@ def feast_snowflake_array_timestamp_to_list_unix_timestamp_proto(df): HANDLER = 'feast.infra.utils.snowflake.snowpark.snowflake_udfs.feast_snowflake_number_to_int32_proto' IMPORTS = ('@feast_stage/feast.zip'); """ + + # ValueType.INT32 = 3 @vectorized(input=pandas.DataFrame) def feast_snowflake_number_to_int32_proto(df): @@ -266,6 +274,8 @@ def feast_snowflake_number_to_int32_proto(df): HANDLER = 'feast.infra.utils.snowflake.snowpark.snowflake_udfs.feast_snowflake_number_to_int64_proto' IMPORTS = ('@feast_stage/feast.zip'); """ + + # ValueType.INT64 = 4 @vectorized(input=pandas.DataFrame) def feast_snowflake_number_to_int64_proto(df): @@ -291,6 +301,8 @@ def feast_snowflake_number_to_int64_proto(df): HANDLER = 'feast.infra.utils.snowflake.snowpark.snowflake_udfs.feast_snowflake_float_to_double_proto' IMPORTS = ('@feast_stage/feast.zip'); """ + + # ValueType.FLOAT = 5 & ValueType.DOUBLE = 6 @vectorized(input=pandas.DataFrame) def feast_snowflake_float_to_double_proto(df): @@ -314,6 +326,8 @@ def feast_snowflake_float_to_double_proto(df): HANDLER = 'feast.infra.utils.snowflake.snowpark.snowflake_udfs.feast_snowflake_boolean_to_bool_boolean_proto' IMPORTS = ('@feast_stage/feast.zip'); """ + + # ValueType.BOOL = 7 @vectorized(input=pandas.DataFrame) def feast_snowflake_boolean_to_bool_boolean_proto(df): @@ -337,6 +351,8 @@ def feast_snowflake_boolean_to_bool_boolean_proto(df): HANDLER = 'feast.infra.utils.snowflake.snowpark.snowflake_udfs.feast_snowflake_timestamp_to_unix_timestamp_proto' IMPORTS = ('@feast_stage/feast.zip'); """ + + # ValueType.UNIX_TIMESTAMP = 8 @vectorized(input=pandas.DataFrame) def feast_snowflake_timestamp_to_unix_timestamp_proto(df): @@ -363,6 +379,8 @@ def feast_snowflake_timestamp_to_unix_timestamp_proto(df): HANDLER = 'feast.infra.utils.snowflake.snowpark.snowflake_udfs.feast_serialize_entity_keys' IMPORTS = ('@feast_stage/feast.zip') """ + + # converts 1 to n many entity keys to a single binary for lookups @vectorized(input=pandas.DataFrame) def feast_serialize_entity_keys(df): @@ -410,6 +428,8 @@ def feast_serialize_entity_keys(df): HANDLER = 'feast.infra.utils.snowflake.snowpark.snowflake_udfs.feast_entity_key_proto_to_string' IMPORTS = ('@feast_stage/feast.zip') """ + + # converts 1 to n many entity keys to a single binary for lookups @vectorized(input=pandas.DataFrame) def feast_entity_key_proto_to_string(df): diff --git a/sdk/python/feast/metrics.py b/sdk/python/feast/metrics.py new file mode 100644 index 00000000000..7786af6f2f5 --- /dev/null +++ b/sdk/python/feast/metrics.py @@ -0,0 +1,514 @@ +# Copyright 2025 The Feast Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Centralized Prometheus metrics for the Feast feature server. + +All metrics are defined here to provide a single source of truth. +Instrumentation is **opt-in**: metric recording is gated behind a +``_config`` object whose flags are only set when +``start_metrics_server()`` is called (i.e. when the feature server is +started with ``--metrics`` or ``metrics.enabled: true`` in the YAML). + +Each metric category can be individually toggled via the ``metrics`` +sub-block in ``feature_store.yaml``. When disabled, helpers +short-circuit with a fast attribute check and do zero work. + +Multiprocess support +-------------------- +Gunicorn pre-forks worker processes, so every worker gets its own copy +of the in-process metric state. To aggregate across workers we use +``prometheus_client``'s multiprocess mode: + +1. ``PROMETHEUS_MULTIPROCESS_DIR`` is set (to a temp dir if the user + has not already set it) **before** any metric objects are created. +2. Gauges specify ``multiprocess_mode`` so they aggregate correctly. +3. The metrics HTTP server uses ``MultiProcessCollector`` to read all + workers' metric files. +4. Gunicorn hooks (``post_worker_init``, ``child_exit``) are wired up + in ``feature_server.py`` to start per-worker monitoring and to + clean up dead-worker files. +""" + +import atexit +import logging +import os +import shutil +import tempfile +import threading +import time +from contextlib import contextmanager +from dataclasses import dataclass +from datetime import datetime, timezone +from typing import TYPE_CHECKING, Optional + +import psutil + +if TYPE_CHECKING: + from feast.feature_store import FeatureStore + +logger = logging.getLogger(__name__) + +# --------------------------------------------------------------------------- +# Multiprocess directory setup — MUST happen before prometheus_client import +# so that metric values are stored in shared files rather than in-process +# memory (required for Gunicorn pre-fork workers). +# --------------------------------------------------------------------------- +_prometheus_mp_dir: Optional[str] = None +_owns_mp_dir: bool = False +_owner_pid: Optional[int] = None + +if "PROMETHEUS_MULTIPROCESS_DIR" not in os.environ: + _prometheus_mp_dir = tempfile.mkdtemp(prefix="feast_metrics_") + os.environ["PROMETHEUS_MULTIPROCESS_DIR"] = _prometheus_mp_dir + _owns_mp_dir = True + _owner_pid = os.getpid() +else: + _prometheus_mp_dir = os.environ["PROMETHEUS_MULTIPROCESS_DIR"] + +# prometheus_client uses two different env var names: +# - PROMETHEUS_MULTIPROCESS_DIR (for value storage in prometheus_client.values) +# - PROMETHEUS_MULTIPROC_DIR (for MultiProcessCollector) +# Both must point to the same directory. +if "PROMETHEUS_MULTIPROC_DIR" not in os.environ: + os.environ["PROMETHEUS_MULTIPROC_DIR"] = _prometheus_mp_dir + + +def _cleanup_multiprocess_dir(): + # Only the process that created the directory may remove it. + # Forked Gunicorn workers inherit _owns_mp_dir=True but have a + # different PID; letting them delete the shared directory would + # break metrics for sibling workers and the metrics HTTP server. + if ( + _owns_mp_dir + and _owner_pid == os.getpid() + and _prometheus_mp_dir + and os.path.isdir(_prometheus_mp_dir) + ): + shutil.rmtree(_prometheus_mp_dir, ignore_errors=True) + + +atexit.register(_cleanup_multiprocess_dir) + +# Now safe to import prometheus_client — it will detect the env var. +from prometheus_client import Counter, Gauge, Histogram # noqa: E402 + + +# --------------------------------------------------------------------------- +# Per-category runtime flags +# --------------------------------------------------------------------------- +@dataclass +class _MetricsFlags: + """Runtime toggle for each metric category. + + All flags default to ``False`` (disabled). ``start_metrics_server`` + flips them on according to the user's ``MetricsConfig``. + """ + + enabled: bool = False + resource: bool = False + request: bool = False + online_features: bool = False + push: bool = False + materialization: bool = False + freshness: bool = False + + +_config = _MetricsFlags() + + +def build_metrics_flags(metrics_config: Optional[object] = None) -> _MetricsFlags: + """Build ``_MetricsFlags`` from a ``MetricsConfig`` object. + + If *metrics_config* is ``None`` (e.g. metrics activated purely via + ``--metrics`` CLI with no YAML block), every category defaults to + enabled. Otherwise the per-category booleans are respected. + """ + if metrics_config is None: + return _MetricsFlags( + enabled=True, + resource=True, + request=True, + online_features=True, + push=True, + materialization=True, + freshness=True, + ) + return _MetricsFlags( + enabled=True, + resource=getattr(metrics_config, "resource", True), + request=getattr(metrics_config, "request", True), + online_features=getattr(metrics_config, "online_features", True), + push=getattr(metrics_config, "push", True), + materialization=getattr(metrics_config, "materialization", True), + freshness=getattr(metrics_config, "freshness", True), + ) + + +# --------------------------------------------------------------------------- +# Resource metrics — multiprocess_mode="liveall" so each live worker +# reports its own CPU/memory with a ``pid`` label. +# --------------------------------------------------------------------------- +cpu_usage_gauge = Gauge( + "feast_feature_server_cpu_usage", + "CPU usage percentage of the Feast feature server process", + multiprocess_mode="liveall", +) +memory_usage_gauge = Gauge( + "feast_feature_server_memory_usage", + "Memory usage percentage of the Feast feature server process", + multiprocess_mode="liveall", +) + +# --------------------------------------------------------------------------- +# HTTP request metrics (Counters & Histograms aggregate automatically) +# --------------------------------------------------------------------------- +request_count = Counter( + "feast_feature_server_request_total", + "Total number of requests to the Feast feature server", + ["endpoint", "status"], +) +request_latency = Histogram( + "feast_feature_server_request_latency_seconds", + "Latency of requests to the Feast feature server in seconds", + ["endpoint", "feature_count", "feature_view_count"], + buckets=(0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0), +) + +# --------------------------------------------------------------------------- +# Online feature retrieval metrics +# --------------------------------------------------------------------------- +online_features_request_count = Counter( + "feast_online_features_request_total", + "Total online feature retrieval requests", +) +online_features_entity_count = Histogram( + "feast_online_features_entity_count", + "Number of entity rows per online feature request", + buckets=(1, 5, 10, 25, 50, 100, 250, 500, 1000), +) + +# --------------------------------------------------------------------------- +# Push / write metrics +# --------------------------------------------------------------------------- +push_request_count = Counter( + "feast_push_request_total", + "Total push requests to the feature store", + ["push_source", "mode"], +) + +# --------------------------------------------------------------------------- +# Materialization metrics +# --------------------------------------------------------------------------- +materialization_result_total = Counter( + "feast_materialization_result_total", + "Total materialization runs per feature view", + ["feature_view", "status"], +) +materialization_duration_seconds = Histogram( + "feast_materialization_duration_seconds", + "Duration of materialization per feature view in seconds", + ["feature_view"], + buckets=(1.0, 5.0, 10.0, 30.0, 60.0, 120.0, 300.0, 600.0, 1800.0, 3600.0), +) + +# --------------------------------------------------------------------------- +# Sub-request timing — online store reads and ODFV transformations +# --------------------------------------------------------------------------- +online_store_read_duration_seconds = Histogram( + "feast_feature_server_online_store_read_duration_seconds", + "Duration of the online store read phase in seconds (covers all table reads including parallel async)", + buckets=(0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0), +) +transformation_duration_seconds = Histogram( + "feast_feature_server_transformation_duration_seconds", + "Duration of on-demand feature view transformations on read in seconds", + ["odfv_name", "mode"], + buckets=(0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0), +) +write_transformation_duration_seconds = Histogram( + "feast_feature_server_write_transformation_duration_seconds", + "Duration of on-demand feature view transformations on write in seconds", + ["odfv_name", "mode"], + buckets=(0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0), +) + +# --------------------------------------------------------------------------- +# Feature freshness metrics — "max" shows the worst-case staleness across +# processes (freshness is identical regardless of which process computes it). +# --------------------------------------------------------------------------- +feature_freshness_seconds = Gauge( + "feast_feature_freshness_seconds", + "Seconds since the most recent materialization end time per feature view", + ["feature_view", "project"], + multiprocess_mode="max", +) + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- + + +class RequestMetricsContext: + """Mutable label holder yielded by :func:`track_request_latency`. + + Callers that need to resolve labels *inside* the ``with`` block + (e.g. ``/get-online-features`` where the feature count is only + known after ``_get_features`` succeeds) can set the attributes + on the yielded object and they will be picked up in ``finally``. + """ + + __slots__ = ("feature_count", "feature_view_count") + + def __init__(self, feature_count: str = "", feature_view_count: str = ""): + self.feature_count = feature_count + self.feature_view_count = feature_view_count + + +@contextmanager +def track_request_latency( + endpoint: str, feature_count: str = "", feature_view_count: str = "" +): + """Context manager that records endpoint latency and increments request count. + + Yields a :class:`RequestMetricsContext` whose ``feature_count`` and + ``feature_view_count`` attributes can be updated inside the block. + The final values are used when recording the histogram and counter + in ``finally``, so labels are accurate even when they depend on + work done inside the block. + + Gated by the ``request`` category flag. + """ + ctx = RequestMetricsContext(feature_count, feature_view_count) + if not _config.request: + yield ctx + return + + start = time.monotonic() + status_label = "success" + try: + yield ctx + except Exception: + status_label = "error" + raise + finally: + elapsed = time.monotonic() - start + request_latency.labels( + endpoint=endpoint, + feature_count=ctx.feature_count, + feature_view_count=ctx.feature_view_count, + ).observe(elapsed) + request_count.labels(endpoint=endpoint, status=status_label).inc() + + +def track_online_features_entities(entity_count: int): + """Record the number of entity rows in an online feature request.""" + if not _config.online_features: + return + online_features_request_count.inc() + online_features_entity_count.observe(entity_count) + + +def track_push(push_source: str, mode: str): + """Increment the push request counter.""" + if not _config.push: + return + push_request_count.labels(push_source=push_source, mode=mode).inc() + + +def track_online_store_read(duration_seconds: float): + """Record the duration of the online store read phase.""" + if not _config.online_features: + return + online_store_read_duration_seconds.observe(duration_seconds) + + +def track_transformation(odfv_name: str, mode: str, duration_seconds: float): + """Record the duration of an on-demand feature view read-path transformation.""" + if not _config.online_features: + return + transformation_duration_seconds.labels(odfv_name=odfv_name, mode=mode).observe( + duration_seconds + ) + + +def track_write_transformation(odfv_name: str, mode: str, duration_seconds: float): + """Record the duration of an on-demand feature view write-path transformation.""" + if not _config.online_features: + return + write_transformation_duration_seconds.labels( + odfv_name=odfv_name, mode=mode + ).observe(duration_seconds) + + +def track_materialization( + feature_view_name: str, success: bool, duration_seconds: float +): + """Record materialization outcome and duration for a single feature view.""" + if not _config.materialization: + return + status = "success" if success else "failure" + materialization_result_total.labels( + feature_view=feature_view_name, status=status + ).inc() + materialization_duration_seconds.labels(feature_view=feature_view_name).observe( + duration_seconds + ) + + +def update_feature_freshness( + store: "FeatureStore", +) -> None: + """ + Compute and set the freshness gauge for every feature view in the registry. + + Freshness = now - most_recent_end_time (from materialization_intervals). + A higher value means the feature data is more stale. + """ + try: + feature_views = store.list_feature_views(allow_cache=True) + now = datetime.now(tz=timezone.utc) + for fv in feature_views: + end_time = fv.most_recent_end_time + if end_time is not None: + if end_time.tzinfo is None: + end_time = end_time.replace(tzinfo=timezone.utc) + staleness = (now - end_time).total_seconds() + feature_freshness_seconds.labels( + feature_view=fv.name, project=store.project + ).set(staleness) + except Exception: + logger.debug("Failed to update feature freshness metrics", exc_info=True) + + +def monitor_resources(interval: int = 5): + """Background thread target that updates CPU and memory usage gauges.""" + logger.debug("Starting resource monitoring with interval %d seconds", interval) + p = psutil.Process() + logger.debug("PID is %d", p.pid) + while True: + with p.oneshot(): + cpu_usage = p.cpu_percent() + memory_usage = p.memory_percent() + logger.debug("CPU usage: %s%%, Memory usage: %s%%", cpu_usage, memory_usage) + cpu_usage_gauge.set(cpu_usage) + memory_usage_gauge.set(memory_usage) + time.sleep(interval) + + +def monitor_freshness(store: "FeatureStore", interval: int = 30): + """Background thread target that periodically updates feature freshness gauges.""" + logger.debug( + "Starting feature freshness monitoring with interval %d seconds", interval + ) + while True: + update_feature_freshness(store) + time.sleep(interval) + + +# --------------------------------------------------------------------------- +# Gunicorn multiprocess helpers +# --------------------------------------------------------------------------- + + +def mark_process_dead(pid: int): + """Clean up metric files for a dead Gunicorn worker. + + Called from the Gunicorn ``child_exit`` hook so that stale worker + data no longer appears in scraped output. + """ + if not _config.enabled: + return + try: + from prometheus_client import multiprocess + + multiprocess.mark_process_dead(pid) + except Exception: + logger.debug("Failed to mark process %d as dead", pid, exc_info=True) + + +def init_worker_monitoring(): + """Start resource monitoring inside a Gunicorn worker process. + + Called from the ``post_worker_init`` hook so that each worker + tracks its own CPU/memory independently of the master. + """ + if _config.resource: + t = threading.Thread(target=monitor_resources, args=(5,), daemon=True) + t.start() + + +def start_metrics_server( + store: "FeatureStore", + port: int = 8000, + metrics_config: Optional["_MetricsFlags"] = None, + start_resource_monitoring: bool = True, +): + """ + Start the Prometheus metrics HTTP server and background monitoring threads. + + Uses ``MultiProcessCollector`` so that metrics from all Gunicorn + workers are correctly aggregated when Prometheus scrapes port *port*. + + Args: + store: The FeatureStore instance (used for freshness checks). + port: TCP port for the Prometheus HTTP endpoint. + metrics_config: Optional pre-built ``_MetricsFlags``. When + ``None`` every category defaults to **enabled**. + start_resource_monitoring: Whether to start the CPU/memory + monitoring thread. Set to ``False`` when Gunicorn will + fork workers — the ``post_worker_init`` hook starts + per-worker monitoring instead. + """ + global _config + + if metrics_config is not None: + _config = metrics_config + else: + _config = _MetricsFlags( + enabled=True, + resource=True, + request=True, + online_features=True, + push=True, + materialization=True, + freshness=True, + ) + + from prometheus_client import CollectorRegistry, make_wsgi_app + from prometheus_client.multiprocess import MultiProcessCollector + + registry = CollectorRegistry() + MultiProcessCollector(registry) + + from wsgiref.simple_server import make_server + + httpd = make_server("", port, make_wsgi_app(registry)) + metrics_thread = threading.Thread(target=httpd.serve_forever, daemon=True) + metrics_thread.start() + logger.info( + "Prometheus metrics server started on port %d (multiprocess-safe)", port + ) + + if _config.resource and start_resource_monitoring: + resource_thread = threading.Thread( + target=monitor_resources, args=(5,), daemon=True + ) + resource_thread.start() + + if _config.freshness: + freshness_thread = threading.Thread( + target=monitor_freshness, args=(store, 30), daemon=True + ) + freshness_thread.start() diff --git a/sdk/python/feast/offline_server.py b/sdk/python/feast/offline_server.py index bcdf808868b..ffe648e8749 100644 --- a/sdk/python/feast/offline_server.py +++ b/sdk/python/feast/offline_server.py @@ -15,6 +15,7 @@ from feast import FeatureStore, FeatureView, utils from feast.arrow_error_handler import arrow_server_error_handling_decorator from feast.data_source import DataSource +from feast.errors import FeatureViewNotFoundException from feast.feature_logging import FeatureServiceLoggingSource from feast.feature_view import DUMMY_ENTITY_NAME from feast.infra.offline_stores.offline_utils import get_offline_store_from_config @@ -199,7 +200,7 @@ def get_feature_view_by_name( ) fv = fv.with_projection(p) return fv - except Exception: + except FeatureViewNotFoundException: try: return self.store.registry.get_stream_feature_view( name=fv_name, project=project diff --git a/sdk/python/feast/on_demand_feature_view.py b/sdk/python/feast/on_demand_feature_view.py index 7ead26cb984..530a96065a8 100644 --- a/sdk/python/feast/on_demand_feature_view.py +++ b/sdk/python/feast/on_demand_feature_view.py @@ -1,5 +1,6 @@ import copy import functools +import uuid import warnings from types import FunctionType from typing import Any, List, Optional, Union, cast @@ -16,6 +17,7 @@ from feast.feature_view import DUMMY_ENTITY_NAME, FeatureView from feast.feature_view_projection import FeatureViewProjection from feast.field import Field, from_value_type +from feast.proto_utils import transformation_to_proto from feast.protos.feast.core.OnDemandFeatureView_pb2 import ( OnDemandFeatureView as OnDemandFeatureViewProto, ) @@ -24,9 +26,6 @@ OnDemandFeatureViewSpec, OnDemandSource, ) -from feast.protos.feast.core.Transformation_pb2 import ( - FeatureTransformationV2 as FeatureTransformationProto, -) from feast.protos.feast.core.Transformation_pb2 import ( UserDefinedFunctionV2 as UserDefinedFunctionProto, ) @@ -37,6 +36,7 @@ from feast.transformation.substrait_transformation import SubstraitTransformation from feast.utils import _utc_now from feast.value_type import ValueType +from feast.version_utils import normalize_version_string warnings.simplefilter("once", DeprecationWarning) OnDemandSourceType = Union[FeatureView, FeatureViewProjection, RequestSource] @@ -133,6 +133,8 @@ class OnDemandFeatureView(BaseFeatureView): maintainer. """ + _TRACK_METRICS_TAG = "feast:track_metrics" + name: str entities: Optional[List[str]] features: List[Field] @@ -145,6 +147,7 @@ class OnDemandFeatureView(BaseFeatureView): owner: str write_to_online_store: bool singleton: bool + track_metrics: bool udf: Optional[FunctionType] udf_string: Optional[str] aggregations: List[Aggregation] @@ -165,7 +168,9 @@ def __init__( # noqa: C901 owner: str = "", write_to_online_store: bool = False, singleton: bool = False, + track_metrics: bool = False, aggregations: Optional[List[Aggregation]] = None, + version: str = "latest", ): """ Creates an OnDemandFeatureView object. @@ -191,6 +196,11 @@ def __init__( # noqa: C901 the online store for faster retrieval. singleton (optional): A boolean that indicates whether the transformation is executed on a singleton (only applicable when mode="python"). + track_metrics (optional): Whether to emit Prometheus timing metrics + (``feast_feature_server_transformation_duration_seconds``) for + this ODFV. Defaults to ``False``. Set to ``True`` to opt in + to per-ODFV transformation duration tracking when the server + is started with metrics enabled. aggregations (optional): List of aggregations to apply before transformation. """ super().__init__( @@ -201,6 +211,7 @@ def __init__( # noqa: C901 owner=owner, ) + self.version = version schema = schema or [] self.entities = [e.name for e in entities] if entities else [DUMMY_ENTITY_NAME] self.sources = sources @@ -257,6 +268,7 @@ def __init__( # noqa: C901 raise ValueError( ODFVErrorMessages.singleton_mode_requires_python(self.mode) ) + self.track_metrics = track_metrics self.aggregations = aggregations or [] def _add_source_to_collections(self, odfv_source: OnDemandSourceType) -> None: @@ -320,6 +332,8 @@ def __copy__(self): owner=self.owner, write_to_online_store=self.write_to_online_store, singleton=self.singleton, + version=self.version, + track_metrics=self.track_metrics, ) fv.entities = self.entities fv.features = self.features @@ -328,6 +342,49 @@ def __copy__(self): return fv + def _schema_or_udf_changed(self, other: "BaseFeatureView") -> bool: + """Check for OnDemandFeatureView schema/UDF changes.""" + if super()._schema_or_udf_changed(other): + return True + + if not isinstance(other, OnDemandFeatureView): + return True + + # UDF/transformation changes + # Handle None cases for feature_transformation + if ( + self.feature_transformation is None + and other.feature_transformation is not None + ): + return True + if ( + self.feature_transformation is not None + and other.feature_transformation is None + ): + return True + if ( + self.feature_transformation is not None + and other.feature_transformation is not None + and self.feature_transformation != other.feature_transformation + ): + return True + if self.mode != other.mode: + return True + if ( + self.source_feature_view_projections + != other.source_feature_view_projections + ): + return True + if self.source_request_sources != other.source_request_sources: + return True + if sorted(self.entity_columns) != sorted(other.entity_columns): + return True + if self.aggregations != other.aggregations: + return True + + # Skip configuration: write_to_online_store, singleton + return False + def __eq__(self, other): if not isinstance(other, OnDemandFeatureView): raise TypeError( @@ -347,7 +404,10 @@ def __eq__(self, other): or self.write_to_online_store != other.write_to_online_store or sorted(self.entity_columns) != sorted(other.entity_columns) or self.singleton != other.singleton + or self.track_metrics != other.track_metrics or self.aggregations != other.aggregations + or normalize_version_string(self.version) + != normalize_version_string(other.version) ): return False @@ -458,6 +518,8 @@ def to_proto(self) -> OnDemandFeatureViewProto: meta.created_timestamp.FromDatetime(self.created_timestamp) if self.last_updated_timestamp: meta.last_updated_timestamp.FromDatetime(self.last_updated_timestamp) + if self.current_version_number is not None: + meta.current_version_number = self.current_version_number sources = {} for source_name, fv_projection in self.source_feature_view_projections.items(): sources[source_name] = OnDemandSource( @@ -471,29 +533,17 @@ def to_proto(self) -> OnDemandFeatureViewProto: request_data_source=request_sources.to_proto() ) - user_defined_function_proto = cast( - UserDefinedFunctionProto, - self.feature_transformation.to_proto() - if isinstance( - self.feature_transformation, - (PandasTransformation, PythonTransformation), - ) - else None, - ) + feature_transformation = transformation_to_proto(self.feature_transformation) - substrait_transformation_proto = ( - self.feature_transformation.to_proto() - if isinstance(self.feature_transformation, SubstraitTransformation) - else None - ) + tags = dict(self.tags) if self.tags else {} + if self.track_metrics: + tags[self._TRACK_METRICS_TAG] = "true" + else: + tags.pop(self._TRACK_METRICS_TAG, None) - feature_transformation = FeatureTransformationProto( - user_defined_function=user_defined_function_proto, - substrait_transformation=substrait_transformation_proto, - ) spec = OnDemandFeatureViewSpec( name=self.name, - entities=self.entities if self.entities else None, + entities=self.entities or None, entity_columns=[ field.to_proto() for field in self.entity_columns if self.entity_columns ], @@ -502,11 +552,12 @@ def to_proto(self) -> OnDemandFeatureViewProto: feature_transformation=feature_transformation, mode=self.mode, description=self.description, - tags=self.tags, + tags=tags, owner=self.owner, write_to_online_store=self.write_to_online_store, - singleton=self.singleton if self.singleton else False, + singleton=self.singleton or False, aggregations=self.aggregations, + version=self.version, ) return OnDemandFeatureViewProto(spec=spec, meta=meta) @@ -539,6 +590,13 @@ def from_proto( on_demand_feature_view_proto ) + # Extract track_metrics from proto tags and strip the internal key + # so it doesn't leak into user-facing self.tags. + proto_tags = dict(on_demand_feature_view_proto.spec.tags) + track_metrics = ( + proto_tags.pop(cls._TRACK_METRICS_TAG, "false").lower() == "true" + ) + # Create the OnDemandFeatureView object on_demand_feature_view_obj = cls( name=on_demand_feature_view_proto.spec.name, @@ -547,10 +605,11 @@ def from_proto( feature_transformation=transformation, mode=on_demand_feature_view_proto.spec.mode or "pandas", description=on_demand_feature_view_proto.spec.description, - tags=dict(on_demand_feature_view_proto.spec.tags), + tags=proto_tags, owner=on_demand_feature_view_proto.spec.owner, write_to_online_store=optional_fields["write_to_online_store"], singleton=optional_fields["singleton"], + track_metrics=track_metrics, aggregations=optional_fields["aggregations"], ) @@ -564,6 +623,17 @@ def from_proto( on_demand_feature_view_obj ) + # Restore version fields. + spec_version = on_demand_feature_view_proto.spec.version + on_demand_feature_view_obj.version = spec_version or "latest" + cvn = on_demand_feature_view_proto.meta.current_version_number + if cvn > 0: + on_demand_feature_view_obj.current_version_number = cvn + elif cvn == 0 and spec_version and spec_version.lower() != "latest": + on_demand_feature_view_obj.current_version_number = 0 + else: + on_demand_feature_view_obj.current_version_number = None + # Set timestamps if present cls._set_timestamps_from_proto( on_demand_feature_view_proto, on_demand_feature_view_obj @@ -1093,6 +1163,9 @@ def _get_sample_values_by_type(self) -> dict[ValueType, list[Any]]: # Special binary types ValueType.PDF_BYTES: [pdf_sample], ValueType.IMAGE_BYTES: [image_sample], + # UUID types + ValueType.UUID: [uuid.uuid4()], + ValueType.TIME_UUID: [uuid.uuid1()], # List types ValueType.BYTES_LIST: [[b"hello world"]], ValueType.STRING_LIST: [["hello world"]], @@ -1102,6 +1175,19 @@ def _get_sample_values_by_type(self) -> dict[ValueType, list[Any]]: ValueType.FLOAT_LIST: [[1.0]], ValueType.BOOL_LIST: [[True]], ValueType.UNIX_TIMESTAMP_LIST: [[_utc_now()]], + ValueType.UUID_LIST: [[uuid.uuid4(), uuid.uuid4()]], + ValueType.TIME_UUID_LIST: [[uuid.uuid1(), uuid.uuid1()]], + # Set types + ValueType.BYTES_SET: [{b"hello world", b"foo bar"}], + ValueType.STRING_SET: [{"hello world", "foo bar"}], + ValueType.INT32_SET: [{1, 2}], + ValueType.INT64_SET: [{1, 2}], + ValueType.DOUBLE_SET: [{1.0, 2.0}], + ValueType.FLOAT_SET: [{1.0, 2.0}], + ValueType.BOOL_SET: [{True, False}], + ValueType.UNIX_TIMESTAMP_SET: [{_utc_now()}], + ValueType.UUID_SET: [{uuid.uuid4(), uuid.uuid4()}], + ValueType.TIME_UUID_SET: [{uuid.uuid1(), uuid.uuid1()}], } @staticmethod @@ -1138,7 +1224,9 @@ def on_demand_feature_view( owner: str = "", write_to_online_store: bool = False, singleton: bool = False, + track_metrics: bool = False, explode: bool = False, + version: str = "latest", ): """ Creates an OnDemandFeatureView object with the given user function as udf. @@ -1160,6 +1248,8 @@ def on_demand_feature_view( the online store for faster retrieval. singleton (optional): A boolean that indicates whether the transformation is executed on a singleton (only applicable when mode="python"). + track_metrics (optional): Whether to emit Prometheus timing metrics for this ODFV. + Defaults to False. Set to True to opt in when the server is started with metrics. explode (optional): A boolean that indicates whether the transformation explodes the input data into multiple rows. """ @@ -1184,8 +1274,10 @@ def decorator(user_function): write_to_online_store=write_to_online_store, entities=entities, singleton=singleton, + track_metrics=track_metrics, udf=user_function, udf_string=udf_string, + version=version, ) functools.update_wrapper( wrapper=on_demand_feature_view_obj, wrapped=user_function diff --git a/sdk/python/feast/online_response.py b/sdk/python/feast/online_response.py index 2491a28badc..7b6b4806e4d 100644 --- a/sdk/python/feast/online_response.py +++ b/sdk/python/feast/online_response.py @@ -12,7 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import TYPE_CHECKING, Any, Dict, List, TypeAlias, Union +import uuid as uuid_module +from typing import TYPE_CHECKING, Any, Dict, List, Optional, TypeAlias, Union import pandas as pd import pyarrow as pa @@ -21,6 +22,7 @@ from feast.protos.feast.serving.ServingService_pb2 import GetOnlineFeaturesResponse from feast.torch_wrapper import get_torch from feast.type_map import feast_value_type_to_python_type +from feast.value_type import ValueType if TYPE_CHECKING: import torch @@ -37,14 +39,20 @@ class OnlineResponse: Defines an online response in feast. """ - def __init__(self, online_response_proto: GetOnlineFeaturesResponse): + def __init__( + self, + online_response_proto: GetOnlineFeaturesResponse, + feature_types: Optional[Dict[str, ValueType]] = None, + ): """ Construct a native online response from its protobuf version. Args: online_response_proto: GetOnlineResponse proto object to construct from. + feature_types: Optional mapping of feature names to ValueType for type-aware deserialization. """ self.proto = online_response_proto + self._feature_types = feature_types or {} # Delete DUMMY_ENTITY_ID from proto if it exists for idx, val in enumerate(self.proto.metadata.feature_names.val): if val == DUMMY_ENTITY_ID: @@ -65,8 +73,10 @@ def to_dict(self, include_event_timestamps: bool = False) -> Dict[str, Any]: for feature_ref, feature_vector in zip( self.proto.metadata.feature_names.val, self.proto.results ): + feature_type = self._feature_types.get(feature_ref) response[feature_ref] = [ - feast_value_type_to_python_type(v) for v in feature_vector.values + feast_value_type_to_python_type(v, feature_type) + for v in feature_vector.values ] if include_event_timestamps: @@ -94,8 +104,9 @@ def to_arrow(self, include_event_timestamps: bool = False) -> pa.Table: Args: include_event_timestamps: bool Optionally include feature timestamps in the table """ - - return pa.Table.from_pydict(self.to_dict(include_event_timestamps)) + result = self.to_dict(include_event_timestamps) + result = _convert_uuids_for_arrow(result) + return pa.Table.from_pydict(result) def to_tensor( self, @@ -140,3 +151,31 @@ def to_tensor( values # Return as-is for strings or unsupported types ) return tensor_dict + + +def _convert_uuids_for_arrow(result: Dict[str, List[Any]]) -> Dict[str, List[Any]]: + """Convert uuid.UUID objects and sets to Arrow-compatible types.""" + for key, values in result.items(): + first_valid = next((v for v in values if v is not None), None) + if isinstance(first_valid, uuid_module.UUID): + result[key] = [ + str(v) if isinstance(v, uuid_module.UUID) else v for v in values + ] + elif isinstance(first_valid, list): + inner = next((e for e in first_valid if e is not None), None) + if isinstance(inner, uuid_module.UUID): + result[key] = [ + [str(e) if isinstance(e, uuid_module.UUID) else e for e in v] + if isinstance(v, list) + else v + for v in values + ] + elif isinstance(first_valid, set): + inner = next((e for e in first_valid if e is not None), None) + if isinstance(inner, uuid_module.UUID): + result[key] = [ + [str(e) for e in v] if isinstance(v, set) else v for v in values + ] + else: + result[key] = [list(v) if isinstance(v, set) else v for v in values] + return result diff --git a/sdk/python/feast/permissions/auth/oidc_token_parser.py b/sdk/python/feast/permissions/auth/oidc_token_parser.py index ffff7e7ad34..7940c9d7525 100644 --- a/sdk/python/feast/permissions/auth/oidc_token_parser.py +++ b/sdk/python/feast/permissions/auth/oidc_token_parser.py @@ -1,5 +1,6 @@ import logging import os +import ssl from typing import Optional from unittest.mock import Mock @@ -21,8 +22,13 @@ class OidcTokenParser(TokenParser): """ - A `TokenParser` to use an OIDC server to retrieve the user details. - Server settings are retrieved from the `auth` configurationof the Feature store. + A ``TokenParser`` to use an OIDC server to retrieve the user details. + Server settings are retrieved from the ``auth`` configuration of the Feature store. + + Incoming tokens that contain a ``kubernetes.io`` claim (i.e. Kubernetes + service-account tokens) are handled via a lightweight TokenReview that + extracts only the namespace — no RBAC queries needed. All other tokens + follow the standard OIDC/Keycloak JWKS validation path. """ _auth_config: OidcAuthConfig @@ -30,8 +36,11 @@ class OidcTokenParser(TokenParser): def __init__(self, auth_config: OidcAuthConfig): self._auth_config = auth_config self.oidc_discovery_service = OIDCDiscoveryService( - self._auth_config.auth_discovery_url + self._auth_config.auth_discovery_url, + verify_ssl=self._auth_config.verify_ssl, + ca_cert_path=self._auth_config.ca_cert_path, ) + self._k8s_auth_api = None async def _validate_token(self, access_token: str): """ @@ -50,79 +59,201 @@ async def _validate_token(self, access_token: str): await oauth_2_scheme(request=request) + @staticmethod + def _extract_username_or_raise_error(data: dict) -> str: + """Extract the username from the decoded JWT. Raises if missing — identity is mandatory. + + Checks ``preferred_username`` first (Keycloak default), then falls back + to ``upn`` (Azure AD / Entra ID). + """ + if "preferred_username" in data: + return data["preferred_username"] + if "upn" in data: + return data["upn"] + raise AuthenticationError( + "Missing preferred_username or upn field in access token." + ) + + @staticmethod + def _extract_claim(data: dict, *keys: str, expected_type: type = list): + """Walk *keys* into *data* and return the leaf value, or ``expected_type()`` if any key is missing or the wrong type.""" + node = data + path = ".".join(keys) + for key in keys: + if not isinstance(node, dict) or key not in node: + logger.debug( + f"Missing {key} in access token claim path '{path}'. Defaulting to {expected_type()}." + ) + return expected_type() + node = node[key] + if not isinstance(node, expected_type): + logger.debug( + f"Expected {expected_type.__name__} at '{path}', got {type(node).__name__}. Defaulting to {expected_type()}." + ) + return expected_type() + return node + + @staticmethod + def _is_ssl_error(exc: BaseException) -> bool: + """Walk the exception chain looking for SSL-related errors.""" + current: Optional[BaseException] = exc + while current is not None: + if isinstance(current, ssl.SSLError): + return True + current = current.__cause__ or current.__context__ + return False + + def _decode_token(self, access_token: str) -> dict: + """Fetch the JWKS signing key and decode + verify the JWT.""" + optional_custom_headers = {"User-agent": "custom-user-agent"} + ssl_ctx = ssl.create_default_context() + if not self._auth_config.verify_ssl: + ssl_ctx.check_hostname = False + ssl_ctx.verify_mode = ssl.CERT_NONE + elif self._auth_config.ca_cert_path and os.path.exists( + self._auth_config.ca_cert_path + ): + ssl_ctx.load_verify_locations(self._auth_config.ca_cert_path) + jwks_client = PyJWKClient( + self.oidc_discovery_service.get_jwks_url(), + headers=optional_custom_headers, + ssl_context=ssl_ctx, + ) + signing_key = jwks_client.get_signing_key_from_jwt(access_token) + return jwt.decode( + access_token, + signing_key.key, + algorithms=["RS256"], + audience="account", + options={ + "verify_aud": False, + "verify_signature": True, + "verify_exp": True, + }, + leeway=10, # accepts tokens generated up to 10 seconds in the past, in case of clock skew + ) + async def user_details_from_access_token(self, access_token: str) -> User: """ - Validate the access token then decode it to extract the user credential and roles. + Validate the access token then decode it to extract the user credentials, + roles, and groups. + + A single unverified decode is performed upfront for lightweight routing: + intra-server communication, Kubernetes SA tokens (identified by the + ``kubernetes.io`` claim), or standard OIDC/Keycloak JWKS validation. Returns: - User: Current user, with associated roles. + User: Current user, with associated roles, groups, or namespaces. Raises: AuthenticationError if any error happens. """ + try: + unverified = jwt.decode(access_token, options={"verify_signature": False}) + except jwt.exceptions.DecodeError as e: + raise AuthenticationError(f"Failed to decode token: {e}") - # check if intra server communication - user = self._get_intra_comm_user(access_token) + user = self._get_intra_comm_user(unverified) if user: return user + if isinstance(unverified.get("kubernetes.io"), dict): + logger.debug("Detected kubernetes.io claim — validating via TokenReview") + try: + return await self._validate_k8s_sa_token_and_extract_namespace( + access_token + ) + except AuthenticationError: + raise + except Exception as e: + logger.error(f"Kubernetes token validation failed: {e}") + raise AuthenticationError(f"Kubernetes token validation failed: {e}") + + # Standard OIDC / Keycloak flow try: await self._validate_token(access_token) logger.debug("Token successfully validated.") except Exception as e: + if self._is_ssl_error(e): + logger.error( + "OIDC provider SSL certificate verification failed. " + "If using a self-signed certificate, set verify_ssl: false " + "or provide a CA certificate via ca_cert_path." + ) logger.error(f"Token validation failed: {e}") raise AuthenticationError(f"Invalid token: {e}") - optional_custom_headers = {"User-agent": "custom-user-agent"} - jwks_client = PyJWKClient( - self.oidc_discovery_service.get_jwks_url(), headers=optional_custom_headers - ) - try: - signing_key = jwks_client.get_signing_key_from_jwt(access_token) - data = jwt.decode( - access_token, - signing_key.key, - algorithms=["RS256"], - audience="account", - options={ - "verify_aud": False, - "verify_signature": True, - "verify_exp": True, - }, - leeway=10, # accepts tokens generated up to 10 seconds in the past, in case of clock skew - ) + data = self._decode_token(access_token) - if "preferred_username" not in data: - raise AuthenticationError( - "Missing preferred_username field in access token." - ) - current_user = data["preferred_username"] - - if "resource_access" not in data: - logger.warning("Missing resource_access field in access token.") - client_id = self._auth_config.client_id - if client_id not in data["resource_access"]: - logger.warning( - f"Missing resource_access.{client_id} field in access token. Defaulting to empty roles." + current_user = self._extract_username_or_raise_error(data) + roles = ( + self._extract_claim( + data, "resource_access", self._auth_config.client_id, "roles" ) - roles = [] - else: - roles = data["resource_access"][client_id]["roles"] + if self._auth_config.client_id + else [] + ) + groups = self._extract_claim(data, "groups") - logger.info(f"Extracted user {current_user} and roles {roles}") - return User(username=current_user, roles=roles) - except jwt.exceptions.InvalidTokenError: + logger.info( + f"Extracted user {current_user} with roles {roles}, groups {groups}" + ) + return User( + username=current_user, + roles=roles, + groups=groups, + ) + except jwt.exceptions.PyJWTError as e: + if self._is_ssl_error(e): + logger.error( + "OIDC JWKS endpoint SSL certificate verification failed. " + "If using a self-signed certificate, set verify_ssl: false " + "or provide a CA certificate via ca_cert_path." + ) logger.exception("Exception while parsing the token:") raise AuthenticationError("Invalid token.") - def _get_intra_comm_user(self, access_token: str) -> Optional[User]: + async def _validate_k8s_sa_token_and_extract_namespace( + self, access_token: str + ) -> User: + """Validate a K8s SA token via TokenReview and extract the namespace. + + Lightweight alternative to full KubernetesTokenParser — only validates + the token and extracts the namespace from the authenticated identity. + No RBAC queries (RoleBindings, ClusterRoleBindings) are performed, + so the server SA needs only ``tokenreviews/create`` permission. + """ + from kubernetes import client, config + + if self._k8s_auth_api is None: + config.load_incluster_config() + self._k8s_auth_api = client.AuthenticationV1Api() + + token_review = client.V1TokenReview( + spec=client.V1TokenReviewSpec(token=access_token) + ) + auth_api: client.AuthenticationV1Api = self._k8s_auth_api + response = auth_api.create_token_review(token_review) + + if not response.status.authenticated: + raise AuthenticationError( + f"Kubernetes token validation failed: {response.status.error}" + ) + + username = getattr(response.status.user, "username", "") or "" + namespaces = [] + if username.startswith("system:serviceaccount:") and username.count(":") >= 3: + namespaces.append(username.split(":")[2]) + + logger.info(f"SA token validated — user: {username}, namespaces: {namespaces}") + return User(username=username, roles=[], groups=[], namespaces=namespaces) + + @staticmethod + def _get_intra_comm_user(decoded_token: dict) -> Optional[User]: intra_communication_base64 = os.getenv("INTRA_COMMUNICATION_BASE64") if intra_communication_base64: - decoded_token = jwt.decode( - access_token, options={"verify_signature": False} - ) if "preferred_username" in decoded_token: preferred_username: str = decoded_token["preferred_username"] if ( diff --git a/sdk/python/feast/permissions/auth_model.py b/sdk/python/feast/permissions/auth_model.py index 3690d62b728..aa38c0d8937 100644 --- a/sdk/python/feast/permissions/auth_model.py +++ b/sdk/python/feast/permissions/auth_model.py @@ -1,63 +1,68 @@ -# -------------------------------------------------------------------- -# Extends OIDC client auth model with an optional `token` field. -# Works on Pydantic v2-only. -# -# Accepted credential sets (exactly **one** of): -# 1 pre-issued `token` -# 2 `client_secret` (client-credentials flow) -# 3 `username` + `password` + `client_secret` (ROPG) -# -------------------------------------------------------------------- from __future__ import annotations -from typing import Literal, Optional +from typing import Literal, Optional, Tuple from pydantic import ConfigDict, model_validator from feast.repo_config import FeastConfigBaseModel +def _check_mutually_exclusive(**groups: Tuple[object, ...]) -> None: + """Validate that at most one named group is configured, and completely. + + Each *group* is a tuple of field values. + A group is **active** only when *all* its values are truthy. + A group is **partial** (error) when *any* but not *all* values are truthy. + At most one active group may exist. + """ + partial = [name for name, vals in groups.items() if any(vals) and not all(vals)] + if partial: + raise ValueError( + f"Incomplete configuration for '{partial[0]}': " + f"configure all of these fields together, or none at all. " + f"Check the documentation for valid credential combinations." + ) + active = [name for name, vals in groups.items() if all(vals)] + if len(active) > 1: + raise ValueError( + f"Only one of [{', '.join(groups)}] may be set, " + f"but got: {', '.join(active)}" + ) + + class AuthConfig(FeastConfigBaseModel): type: Literal["oidc", "kubernetes", "no_auth"] = "no_auth" class OidcAuthConfig(AuthConfig): auth_discovery_url: str - client_id: str + client_id: Optional[str] = None + verify_ssl: bool = True + ca_cert_path: str = "" class OidcClientAuthConfig(OidcAuthConfig): - # any **one** of the four fields below is sufficient + auth_discovery_url: Optional[str] = None # type: ignore[assignment] + client_id: Optional[str] = None + username: Optional[str] = None password: Optional[str] = None client_secret: Optional[str] = None - token: Optional[str] = None # pre-issued `token` + token: Optional[str] = None + token_env_var: Optional[str] = None @model_validator(mode="after") def _validate_credentials(self): - """Enforce exactly one valid credential set.""" - has_user_pass = bool(self.username) and bool(self.password) - has_secret = bool(self.client_secret) - has_token = bool(self.token) - - # 1 static token - if has_token and not (has_user_pass or has_secret): - return self - - # 2 client_credentials - if has_secret and not has_user_pass and not has_token: - return self - - # 3 ROPG - if has_user_pass and has_secret and not has_token: - return self - - raise ValueError( - "Invalid OIDC client auth combination: " - "provide either\n" - " • token\n" - " • client_secret (without username/password)\n" - " • username + password + client_secret" + network = (self.client_secret, self.auth_discovery_url, self.client_id) + if self.username or self.password: + network += (self.username, self.password) + + _check_mutually_exclusive( + token=(self.token,), + token_env_var=(self.token_env_var,), + client_credentials=network, ) + return self class NoAuthConfig(AuthConfig): @@ -65,7 +70,6 @@ class NoAuthConfig(AuthConfig): class KubernetesAuthConfig(AuthConfig): - # Optional user token for users (not service accounts) user_token: Optional[str] = None model_config = ConfigDict(arbitrary_types_allowed=True, extra="allow") diff --git a/sdk/python/feast/permissions/client/oidc_authentication_client_manager.py b/sdk/python/feast/permissions/client/oidc_authentication_client_manager.py index e7db600cab5..84a0c0115c9 100644 --- a/sdk/python/feast/permissions/client/oidc_authentication_client_manager.py +++ b/sdk/python/feast/permissions/client/oidc_authentication_client_manager.py @@ -1,5 +1,6 @@ import logging import os +from typing import Optional import jwt import requests @@ -10,6 +11,8 @@ logger = logging.getLogger(__name__) +SA_TOKEN_PATH = "/var/run/secrets/kubernetes.io/serviceaccount/token" + class OidcAuthClientManager(AuthenticationClientManager): def __init__(self, auth_config: OidcClientAuthConfig): @@ -17,24 +20,66 @@ def __init__(self, auth_config: OidcClientAuthConfig): def get_token(self): intra_communication_base64 = os.getenv("INTRA_COMMUNICATION_BASE64") - # If intra server communication call if intra_communication_base64: payload = { - "preferred_username": f"{intra_communication_base64}", # Subject claim + "preferred_username": f"{intra_communication_base64}", } - return jwt.encode(payload, "") - # Fetch the token endpoint from the discovery URL - token_endpoint = OIDCDiscoveryService( - self.auth_config.auth_discovery_url - ).get_token_url() - - # 1) pre-issued JWT supplied in config - if getattr(self.auth_config, "token", None): + if self.auth_config.token: return self.auth_config.token + elif self.auth_config.token_env_var: + env_token = os.getenv(self.auth_config.token_env_var) + if env_token: + return env_token + else: + raise PermissionError( + f"token_env_var='{self.auth_config.token_env_var}' is configured " + f"but the environment variable is not set or is empty." + ) + elif self.auth_config.client_secret: + return self._fetch_token_from_idp() + else: + env_token = os.getenv("FEAST_OIDC_TOKEN") + if env_token: + return env_token + + sa_token = self._read_sa_token() + if sa_token: + return sa_token + + raise PermissionError( + "No OIDC token source configured. Provide one of: " + "'token', 'token_env_var', 'client_secret' (with " + "'auth_discovery_url' and 'client_id'), set the " + "FEAST_OIDC_TOKEN environment variable, or run inside " + "a Kubernetes pod with a mounted service account token." + ) + + @staticmethod + def _read_sa_token() -> Optional[str]: + """Read the Kubernetes service account token from the standard mount path.""" + if os.path.isfile(SA_TOKEN_PATH): + with open(SA_TOKEN_PATH) as f: + token = f.read().strip() + if token: + return token + return None + + def _fetch_token_from_idp(self) -> str: + """Obtain an access token via client_credentials or ROPG flow.""" + if self.auth_config.auth_discovery_url is None: + raise ValueError( + "auth_discovery_url is required for IDP token fetch " + "(client_credentials or ROPG flow)." + ) + discovery = OIDCDiscoveryService( + self.auth_config.auth_discovery_url, + verify_ssl=self.auth_config.verify_ssl, + ca_cert_path=self.auth_config.ca_cert_path, + ) + token_endpoint = discovery.get_token_url() - # 2) client_credentials if self.auth_config.client_secret and not ( self.auth_config.username and self.auth_config.password ): @@ -43,7 +88,6 @@ def get_token(self): "client_id": self.auth_config.client_id, "client_secret": self.auth_config.client_secret, } - # 3) ROPG (username + password + client_secret) else: token_request_body = { "grant_type": "password", @@ -52,11 +96,15 @@ def get_token(self): "username": self.auth_config.username, "password": self.auth_config.password, } - headers = {"Content-Type": "application/x-www-form-urlencoded"} + headers = {"Content-Type": "application/x-www-form-urlencoded"} token_response = requests.post( - token_endpoint, data=token_request_body, headers=headers + token_endpoint, + data=token_request_body, + headers=headers, + verify=discovery._get_verify(), ) + if token_response.status_code == 200: access_token = token_response.json()["access_token"] if not access_token: diff --git a/sdk/python/feast/permissions/oidc_service.py b/sdk/python/feast/permissions/oidc_service.py index 73d0ec8f1b7..48edccd3d44 100644 --- a/sdk/python/feast/permissions/oidc_service.py +++ b/sdk/python/feast/permissions/oidc_service.py @@ -1,9 +1,15 @@ +import os + import requests class OIDCDiscoveryService: - def __init__(self, discovery_url: str): + def __init__( + self, discovery_url: str, verify_ssl: bool = True, ca_cert_path: str = "" + ): self.discovery_url = discovery_url + self._verify_ssl = verify_ssl + self._ca_cert_path = ca_cert_path self._discovery_data = None # Initialize it lazily. @property @@ -13,9 +19,16 @@ def discovery_data(self): self._discovery_data = self._fetch_discovery_data() return self._discovery_data + def _get_verify(self): + if not self._verify_ssl: + return False + if self._ca_cert_path and os.path.exists(self._ca_cert_path): + return self._ca_cert_path + return True + def _fetch_discovery_data(self) -> dict: try: - response = requests.get(self.discovery_url) + response = requests.get(self.discovery_url, verify=self._get_verify()) response.raise_for_status() return response.json() except requests.RequestException as e: diff --git a/sdk/python/feast/proto_json.py b/sdk/python/feast/proto_json.py index 487dc4284f3..d663e316b03 100644 --- a/sdk/python/feast/proto_json.py +++ b/sdk/python/feast/proto_json.py @@ -63,6 +63,12 @@ def to_json_object(printer: _Printer, message: ProtoMessage) -> JsonObject: # to JSON. The parse back result will be different from original message. if which is None or which == "null_val": return None + elif which in ("list_val", "set_val"): + # Nested collection: RepeatedValue containing Values + repeated = getattr(message, which) + value = [ + printer._MessageToJsonObject(inner_val) for inner_val in repeated.val + ] elif "_list_" in which: value = list(getattr(message, which).val) else: @@ -86,6 +92,19 @@ def from_json_object( if len(value) == 0: # Clear will mark the struct as modified so it will be created even if there are no values message.int64_list_val.Clear() + elif isinstance(value[0], list) or ( + value[0] is None and any(isinstance(v, list) for v in value) + ): + # Nested collection (list of lists). + # Check any() to handle cases where the first element is None + # (empty inner collections round-trip through proto as None). + # Default to list_val since JSON transport loses the + # outer/inner set distinction. + rv = RepeatedValue() + for inner in value: + inner_val = rv.val.add() + from_json_object(parser, inner, inner_val) + message.list_val.CopyFrom(rv) elif isinstance(value[0], bool): message.bool_list_val.val.extend(value) elif isinstance(value[0], str): diff --git a/sdk/python/feast/proto_utils.py b/sdk/python/feast/proto_utils.py new file mode 100644 index 00000000000..a81a9fd6c23 --- /dev/null +++ b/sdk/python/feast/proto_utils.py @@ -0,0 +1,101 @@ +# Copyright 2019 The Feast Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Utility functions for protobuf serialization of Feast objects. +""" + +from typing import TYPE_CHECKING, Any, Optional, Union + +from google.protobuf.message import Message + +from feast.protos.feast.core.Transformation_pb2 import ( + FeatureTransformationV2 as FeatureTransformationProto, +) +from feast.protos.feast.core.Transformation_pb2 import ( + SubstraitTransformationV2 as SubstraitTransformationProto, +) +from feast.protos.feast.core.Transformation_pb2 import ( + UserDefinedFunctionV2 as UserDefinedFunctionProto, +) + +if TYPE_CHECKING: + from feast.data_source import DataSource + from feast.transformation.mode import TransformationMode + + +def serialize_data_source(source: Optional["DataSource"]) -> Optional[Message]: + """Serialize a data source to proto with class type annotation. + + Args: + source: The data source to serialize, or None. + + Returns: + The serialized proto with data_source_class_type set, or None if source is None. + """ + if source is None: + return None + proto = source.to_proto() + proto.data_source_class_type = ( + f"{source.__class__.__module__}.{source.__class__.__name__}" + ) + return proto + + +def transformation_to_proto( + transformation: Optional[Any], +) -> Optional[FeatureTransformationProto]: + """Convert a transformation to FeatureTransformationProto. + + Args: + transformation: The transformation object with a to_proto() method. + + Returns: + A FeatureTransformationProto wrapping the transformation, or None. + """ + if transformation is None: + return None + + if not hasattr(transformation, "to_proto"): + return None + + transformation_proto = transformation.to_proto() + + if isinstance(transformation_proto, UserDefinedFunctionProto): + return FeatureTransformationProto( + user_defined_function=transformation_proto, + ) + elif isinstance(transformation_proto, SubstraitTransformationProto): + return FeatureTransformationProto( + substrait_transformation=transformation_proto, + ) + return None + + +def mode_to_string(mode: Optional[Union["TransformationMode", str]]) -> str: + """Convert mode to string value. + + Args: + mode: A TransformationMode enum or string, or None. + + Returns: + The string representation of the mode, or empty string if None. + """ + from feast.transformation.mode import TransformationMode + + if mode is None: + return "" + if isinstance(mode, TransformationMode): + return mode.value + return mode diff --git a/sdk/python/feast/protos/feast/core/Aggregation_pb2.py b/sdk/python/feast/protos/feast/core/Aggregation_pb2.py index 922f8f40aa2..44013acd55d 100644 --- a/sdk/python/feast/protos/feast/core/Aggregation_pb2.py +++ b/sdk/python/feast/protos/feast/core/Aggregation_pb2.py @@ -15,7 +15,7 @@ from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x66\x65\x61st/core/Aggregation.proto\x12\nfeast.core\x1a\x1egoogle/protobuf/duration.proto\"\x92\x01\n\x0b\x41ggregation\x12\x0e\n\x06\x63olumn\x18\x01 \x01(\t\x12\x10\n\x08\x66unction\x18\x02 \x01(\t\x12.\n\x0btime_window\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x31\n\x0eslide_interval\x18\x04 \x01(\x0b\x32\x19.google.protobuf.DurationBU\n\x10\x66\x65\x61st.proto.coreB\x10\x41ggregationProtoZ/github.com/feast-dev/feast/go/protos/feast/coreb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x66\x65\x61st/core/Aggregation.proto\x12\nfeast.core\x1a\x1egoogle/protobuf/duration.proto\"\xa0\x01\n\x0b\x41ggregation\x12\x0e\n\x06\x63olumn\x18\x01 \x01(\t\x12\x10\n\x08\x66unction\x18\x02 \x01(\t\x12.\n\x0btime_window\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x31\n\x0eslide_interval\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x0c\n\x04name\x18\x05 \x01(\tBU\n\x10\x66\x65\x61st.proto.coreB\x10\x41ggregationProtoZ/github.com/feast-dev/feast/go/protos/feast/coreb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -24,5 +24,5 @@ _globals['DESCRIPTOR']._options = None _globals['DESCRIPTOR']._serialized_options = b'\n\020feast.proto.coreB\020AggregationProtoZ/github.com/feast-dev/feast/go/protos/feast/core' _globals['_AGGREGATION']._serialized_start=77 - _globals['_AGGREGATION']._serialized_end=223 + _globals['_AGGREGATION']._serialized_end=237 # @@protoc_insertion_point(module_scope) diff --git a/sdk/python/feast/protos/feast/core/Aggregation_pb2.pyi b/sdk/python/feast/protos/feast/core/Aggregation_pb2.pyi index ceb8b1f8131..4c6bd7c089c 100644 --- a/sdk/python/feast/protos/feast/core/Aggregation_pb2.pyi +++ b/sdk/python/feast/protos/feast/core/Aggregation_pb2.pyi @@ -22,12 +22,14 @@ class Aggregation(google.protobuf.message.Message): FUNCTION_FIELD_NUMBER: builtins.int TIME_WINDOW_FIELD_NUMBER: builtins.int SLIDE_INTERVAL_FIELD_NUMBER: builtins.int + NAME_FIELD_NUMBER: builtins.int column: builtins.str function: builtins.str @property def time_window(self) -> google.protobuf.duration_pb2.Duration: ... @property def slide_interval(self) -> google.protobuf.duration_pb2.Duration: ... + name: builtins.str def __init__( self, *, @@ -35,8 +37,9 @@ class Aggregation(google.protobuf.message.Message): function: builtins.str = ..., time_window: google.protobuf.duration_pb2.Duration | None = ..., slide_interval: google.protobuf.duration_pb2.Duration | None = ..., + name: builtins.str = ..., ) -> None: ... def HasField(self, field_name: typing_extensions.Literal["slide_interval", b"slide_interval", "time_window", b"time_window"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["column", b"column", "function", b"function", "slide_interval", b"slide_interval", "time_window", b"time_window"]) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["column", b"column", "function", b"function", "name", b"name", "slide_interval", b"slide_interval", "time_window", b"time_window"]) -> None: ... global___Aggregation = Aggregation diff --git a/sdk/python/feast/protos/feast/core/DatastoreTable_pb2.pyi b/sdk/python/feast/protos/feast/core/DatastoreTable_pb2.pyi index 7b5a629eb7a..6339a97536e 100644 --- a/sdk/python/feast/protos/feast/core/DatastoreTable_pb2.pyi +++ b/sdk/python/feast/protos/feast/core/DatastoreTable_pb2.pyi @@ -1,19 +1,19 @@ """ @generated by mypy-protobuf. Do not edit manually! isort:skip_file - -* Copyright 2021 The Feast Authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* https://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and + +* Copyright 2021 The Feast Authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and * limitations under the License. """ import builtins diff --git a/sdk/python/feast/protos/feast/core/Entity_pb2.pyi b/sdk/python/feast/protos/feast/core/Entity_pb2.pyi index a5924a13451..025817edfee 100644 --- a/sdk/python/feast/protos/feast/core/Entity_pb2.pyi +++ b/sdk/python/feast/protos/feast/core/Entity_pb2.pyi @@ -1,19 +1,19 @@ """ @generated by mypy-protobuf. Do not edit manually! isort:skip_file - -* Copyright 2020 The Feast Authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* https://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and + +* Copyright 2020 The Feast Authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and * limitations under the License. """ import builtins diff --git a/sdk/python/feast/protos/feast/core/FeatureViewProjection_pb2.py b/sdk/python/feast/protos/feast/core/FeatureViewProjection_pb2.py index b47d4fe392f..9a51148f32c 100644 --- a/sdk/python/feast/protos/feast/core/FeatureViewProjection_pb2.py +++ b/sdk/python/feast/protos/feast/core/FeatureViewProjection_pb2.py @@ -16,7 +16,7 @@ from feast.protos.feast.core import DataSource_pb2 as feast_dot_core_dot_DataSource__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n&feast/core/FeatureViewProjection.proto\x12\nfeast.core\x1a\x18\x66\x65\x61st/core/Feature.proto\x1a\x1b\x66\x65\x61st/core/DataSource.proto\"\xba\x03\n\x15\x46\x65\x61tureViewProjection\x12\x19\n\x11\x66\x65\x61ture_view_name\x18\x01 \x01(\t\x12\x1f\n\x17\x66\x65\x61ture_view_name_alias\x18\x03 \x01(\t\x12\x32\n\x0f\x66\x65\x61ture_columns\x18\x02 \x03(\x0b\x32\x19.feast.core.FeatureSpecV2\x12G\n\x0cjoin_key_map\x18\x04 \x03(\x0b\x32\x31.feast.core.FeatureViewProjection.JoinKeyMapEntry\x12\x17\n\x0ftimestamp_field\x18\x05 \x01(\t\x12\x1d\n\x15\x64\x61te_partition_column\x18\x06 \x01(\t\x12 \n\x18\x63reated_timestamp_column\x18\x07 \x01(\t\x12,\n\x0c\x62\x61tch_source\x18\x08 \x01(\x0b\x32\x16.feast.core.DataSource\x12-\n\rstream_source\x18\t \x01(\x0b\x32\x16.feast.core.DataSource\x1a\x31\n\x0fJoinKeyMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42Z\n\x10\x66\x65\x61st.proto.coreB\x15\x46\x65\x61tureReferenceProtoZ/github.com/feast-dev/feast/go/protos/feast/coreb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n&feast/core/FeatureViewProjection.proto\x12\nfeast.core\x1a\x18\x66\x65\x61st/core/Feature.proto\x1a\x1b\x66\x65\x61st/core/DataSource.proto\"\xe4\x03\n\x15\x46\x65\x61tureViewProjection\x12\x19\n\x11\x66\x65\x61ture_view_name\x18\x01 \x01(\t\x12\x1f\n\x17\x66\x65\x61ture_view_name_alias\x18\x03 \x01(\t\x12\x32\n\x0f\x66\x65\x61ture_columns\x18\x02 \x03(\x0b\x32\x19.feast.core.FeatureSpecV2\x12G\n\x0cjoin_key_map\x18\x04 \x03(\x0b\x32\x31.feast.core.FeatureViewProjection.JoinKeyMapEntry\x12\x17\n\x0ftimestamp_field\x18\x05 \x01(\t\x12\x1d\n\x15\x64\x61te_partition_column\x18\x06 \x01(\t\x12 \n\x18\x63reated_timestamp_column\x18\x07 \x01(\t\x12,\n\x0c\x62\x61tch_source\x18\x08 \x01(\x0b\x32\x16.feast.core.DataSource\x12-\n\rstream_source\x18\t \x01(\x0b\x32\x16.feast.core.DataSource\x12\x18\n\x0bversion_tag\x18\n \x01(\x05H\x00\x88\x01\x01\x1a\x31\n\x0fJoinKeyMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x0e\n\x0c_version_tagBZ\n\x10\x66\x65\x61st.proto.coreB\x15\x46\x65\x61tureReferenceProtoZ/github.com/feast-dev/feast/go/protos/feast/coreb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -27,7 +27,7 @@ _globals['_FEATUREVIEWPROJECTION_JOINKEYMAPENTRY']._options = None _globals['_FEATUREVIEWPROJECTION_JOINKEYMAPENTRY']._serialized_options = b'8\001' _globals['_FEATUREVIEWPROJECTION']._serialized_start=110 - _globals['_FEATUREVIEWPROJECTION']._serialized_end=552 - _globals['_FEATUREVIEWPROJECTION_JOINKEYMAPENTRY']._serialized_start=503 - _globals['_FEATUREVIEWPROJECTION_JOINKEYMAPENTRY']._serialized_end=552 + _globals['_FEATUREVIEWPROJECTION']._serialized_end=594 + _globals['_FEATUREVIEWPROJECTION_JOINKEYMAPENTRY']._serialized_start=529 + _globals['_FEATUREVIEWPROJECTION_JOINKEYMAPENTRY']._serialized_end=578 # @@protoc_insertion_point(module_scope) diff --git a/sdk/python/feast/protos/feast/core/FeatureViewProjection_pb2.pyi b/sdk/python/feast/protos/feast/core/FeatureViewProjection_pb2.pyi index 72426f55c9f..6fd1010f2e4 100644 --- a/sdk/python/feast/protos/feast/core/FeatureViewProjection_pb2.pyi +++ b/sdk/python/feast/protos/feast/core/FeatureViewProjection_pb2.pyi @@ -49,6 +49,7 @@ class FeatureViewProjection(google.protobuf.message.Message): CREATED_TIMESTAMP_COLUMN_FIELD_NUMBER: builtins.int BATCH_SOURCE_FIELD_NUMBER: builtins.int STREAM_SOURCE_FIELD_NUMBER: builtins.int + VERSION_TAG_FIELD_NUMBER: builtins.int feature_view_name: builtins.str """The feature view name""" feature_view_name_alias: builtins.str @@ -68,6 +69,8 @@ class FeatureViewProjection(google.protobuf.message.Message): @property def stream_source(self) -> feast.core.DataSource_pb2.DataSource: """Streaming DataSource from where this view can consume "online" feature data.""" + version_tag: builtins.int + """Optional version tag for version-qualified feature references (e.g., @v2).""" def __init__( self, *, @@ -80,8 +83,10 @@ class FeatureViewProjection(google.protobuf.message.Message): created_timestamp_column: builtins.str = ..., batch_source: feast.core.DataSource_pb2.DataSource | None = ..., stream_source: feast.core.DataSource_pb2.DataSource | None = ..., + version_tag: builtins.int | None = ..., ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["batch_source", b"batch_source", "stream_source", b"stream_source"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["batch_source", b"batch_source", "created_timestamp_column", b"created_timestamp_column", "date_partition_column", b"date_partition_column", "feature_columns", b"feature_columns", "feature_view_name", b"feature_view_name", "feature_view_name_alias", b"feature_view_name_alias", "join_key_map", b"join_key_map", "stream_source", b"stream_source", "timestamp_field", b"timestamp_field"]) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["_version_tag", b"_version_tag", "batch_source", b"batch_source", "stream_source", b"stream_source", "version_tag", b"version_tag"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["_version_tag", b"_version_tag", "batch_source", b"batch_source", "created_timestamp_column", b"created_timestamp_column", "date_partition_column", b"date_partition_column", "feature_columns", b"feature_columns", "feature_view_name", b"feature_view_name", "feature_view_name_alias", b"feature_view_name_alias", "join_key_map", b"join_key_map", "stream_source", b"stream_source", "timestamp_field", b"timestamp_field", "version_tag", b"version_tag"]) -> None: ... + def WhichOneof(self, oneof_group: typing_extensions.Literal["_version_tag", b"_version_tag"]) -> typing_extensions.Literal["version_tag"] | None: ... global___FeatureViewProjection = FeatureViewProjection diff --git a/sdk/python/feast/protos/feast/core/FeatureViewVersion_pb2.py b/sdk/python/feast/protos/feast/core/FeatureViewVersion_pb2.py new file mode 100644 index 00000000000..88bc21c2a8f --- /dev/null +++ b/sdk/python/feast/protos/feast/core/FeatureViewVersion_pb2.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: feast/core/FeatureViewVersion.proto +# Protobuf Python Version: 4.25.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n#feast/core/FeatureViewVersion.proto\x12\nfeast.core\x1a\x1fgoogle/protobuf/timestamp.proto\"\xf8\x01\n\x18\x46\x65\x61tureViewVersionRecord\x12\x19\n\x11\x66\x65\x61ture_view_name\x18\x01 \x01(\t\x12\x12\n\nproject_id\x18\x02 \x01(\t\x12\x16\n\x0eversion_number\x18\x03 \x01(\x05\x12\x19\n\x11\x66\x65\x61ture_view_type\x18\x04 \x01(\t\x12\x1a\n\x12\x66\x65\x61ture_view_proto\x18\x05 \x01(\x0c\x12\x35\n\x11\x63reated_timestamp\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x13\n\x0b\x64\x65scription\x18\x07 \x01(\t\x12\x12\n\nversion_id\x18\x08 \x01(\t\"R\n\x19\x46\x65\x61tureViewVersionHistory\x12\x35\n\x07records\x18\x01 \x03(\x0b\x32$.feast.core.FeatureViewVersionRecordB\\\n\x10\x66\x65\x61st.proto.coreB\x17\x46\x65\x61tureViewVersionProtoZ/github.com/feast-dev/feast/go/protos/feast/coreb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'feast.core.FeatureViewVersion_pb2', _globals) +if _descriptor._USE_C_DESCRIPTORS == False: + _globals['DESCRIPTOR']._options = None + _globals['DESCRIPTOR']._serialized_options = b'\n\020feast.proto.coreB\027FeatureViewVersionProtoZ/github.com/feast-dev/feast/go/protos/feast/core' + _globals['_FEATUREVIEWVERSIONRECORD']._serialized_start=85 + _globals['_FEATUREVIEWVERSIONRECORD']._serialized_end=333 + _globals['_FEATUREVIEWVERSIONHISTORY']._serialized_start=335 + _globals['_FEATUREVIEWVERSIONHISTORY']._serialized_end=417 +# @@protoc_insertion_point(module_scope) diff --git a/sdk/python/feast/protos/feast/core/FeatureViewVersion_pb2.pyi b/sdk/python/feast/protos/feast/core/FeatureViewVersion_pb2.pyi new file mode 100644 index 00000000000..a6dba9d53d4 --- /dev/null +++ b/sdk/python/feast/protos/feast/core/FeatureViewVersion_pb2.pyi @@ -0,0 +1,87 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file + +Copyright 2024 The Feast Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +""" +import builtins +import collections.abc +import google.protobuf.descriptor +import google.protobuf.internal.containers +import google.protobuf.message +import google.protobuf.timestamp_pb2 +import sys + +if sys.version_info >= (3, 8): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +class FeatureViewVersionRecord(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + FEATURE_VIEW_NAME_FIELD_NUMBER: builtins.int + PROJECT_ID_FIELD_NUMBER: builtins.int + VERSION_NUMBER_FIELD_NUMBER: builtins.int + FEATURE_VIEW_TYPE_FIELD_NUMBER: builtins.int + FEATURE_VIEW_PROTO_FIELD_NUMBER: builtins.int + CREATED_TIMESTAMP_FIELD_NUMBER: builtins.int + DESCRIPTION_FIELD_NUMBER: builtins.int + VERSION_ID_FIELD_NUMBER: builtins.int + feature_view_name: builtins.str + project_id: builtins.str + version_number: builtins.int + feature_view_type: builtins.str + """"feature_view" | "stream_feature_view" | "on_demand_feature_view" """ + feature_view_proto: builtins.bytes + """serialized FV proto snapshot""" + @property + def created_timestamp(self) -> google.protobuf.timestamp_pb2.Timestamp: ... + description: builtins.str + version_id: builtins.str + """auto-generated UUID for unique identification""" + def __init__( + self, + *, + feature_view_name: builtins.str = ..., + project_id: builtins.str = ..., + version_number: builtins.int = ..., + feature_view_type: builtins.str = ..., + feature_view_proto: builtins.bytes = ..., + created_timestamp: google.protobuf.timestamp_pb2.Timestamp | None = ..., + description: builtins.str = ..., + version_id: builtins.str = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["created_timestamp", b"created_timestamp"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["created_timestamp", b"created_timestamp", "description", b"description", "feature_view_name", b"feature_view_name", "feature_view_proto", b"feature_view_proto", "feature_view_type", b"feature_view_type", "project_id", b"project_id", "version_id", b"version_id", "version_number", b"version_number"]) -> None: ... + +global___FeatureViewVersionRecord = FeatureViewVersionRecord + +class FeatureViewVersionHistory(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + RECORDS_FIELD_NUMBER: builtins.int + @property + def records(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___FeatureViewVersionRecord]: ... + def __init__( + self, + *, + records: collections.abc.Iterable[global___FeatureViewVersionRecord] | None = ..., + ) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["records", b"records"]) -> None: ... + +global___FeatureViewVersionHistory = FeatureViewVersionHistory diff --git a/sdk/python/feast/protos/feast/core/FeatureViewVersion_pb2_grpc.py b/sdk/python/feast/protos/feast/core/FeatureViewVersion_pb2_grpc.py new file mode 100644 index 00000000000..2daafffebfc --- /dev/null +++ b/sdk/python/feast/protos/feast/core/FeatureViewVersion_pb2_grpc.py @@ -0,0 +1,4 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + diff --git a/sdk/python/feast/protos/feast/core/FeatureView_pb2.py b/sdk/python/feast/protos/feast/core/FeatureView_pb2.py index 9a59255375f..43995d4aa72 100644 --- a/sdk/python/feast/protos/feast/core/FeatureView_pb2.py +++ b/sdk/python/feast/protos/feast/core/FeatureView_pb2.py @@ -19,7 +19,7 @@ from feast.protos.feast.core import Transformation_pb2 as feast_dot_core_dot_Transformation__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x66\x65\x61st/core/FeatureView.proto\x12\nfeast.core\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1b\x66\x65\x61st/core/DataSource.proto\x1a\x18\x66\x65\x61st/core/Feature.proto\x1a\x1f\x66\x65\x61st/core/Transformation.proto\"c\n\x0b\x46\x65\x61tureView\x12)\n\x04spec\x18\x01 \x01(\x0b\x32\x1b.feast.core.FeatureViewSpec\x12)\n\x04meta\x18\x02 \x01(\x0b\x32\x1b.feast.core.FeatureViewMeta\"\xd4\x04\n\x0f\x46\x65\x61tureViewSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x10\n\x08\x65ntities\x18\x03 \x03(\t\x12+\n\x08\x66\x65\x61tures\x18\x04 \x03(\x0b\x32\x19.feast.core.FeatureSpecV2\x12\x33\n\x04tags\x18\x05 \x03(\x0b\x32%.feast.core.FeatureViewSpec.TagsEntry\x12&\n\x03ttl\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12,\n\x0c\x62\x61tch_source\x18\x07 \x01(\x0b\x32\x16.feast.core.DataSource\x12\x0e\n\x06online\x18\x08 \x01(\x08\x12-\n\rstream_source\x18\t \x01(\x0b\x32\x16.feast.core.DataSource\x12\x13\n\x0b\x64\x65scription\x18\n \x01(\t\x12\r\n\x05owner\x18\x0b \x01(\t\x12\x31\n\x0e\x65ntity_columns\x18\x0c \x03(\x0b\x32\x19.feast.core.FeatureSpecV2\x12\x0f\n\x07offline\x18\r \x01(\x08\x12\x31\n\x0csource_views\x18\x0e \x03(\x0b\x32\x1b.feast.core.FeatureViewSpec\x12\x43\n\x16\x66\x65\x61ture_transformation\x18\x0f \x01(\x0b\x32#.feast.core.FeatureTransformationV2\x12\x0c\n\x04mode\x18\x10 \x01(\t\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xcc\x01\n\x0f\x46\x65\x61tureViewMeta\x12\x35\n\x11\x63reated_timestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12:\n\x16last_updated_timestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x46\n\x19materialization_intervals\x18\x03 \x03(\x0b\x32#.feast.core.MaterializationInterval\"w\n\x17MaterializationInterval\x12.\n\nstart_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"@\n\x0f\x46\x65\x61tureViewList\x12-\n\x0c\x66\x65\x61tureviews\x18\x01 \x03(\x0b\x32\x17.feast.core.FeatureViewBU\n\x10\x66\x65\x61st.proto.coreB\x10\x46\x65\x61tureViewProtoZ/github.com/feast-dev/feast/go/protos/feast/coreb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x66\x65\x61st/core/FeatureView.proto\x12\nfeast.core\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1b\x66\x65\x61st/core/DataSource.proto\x1a\x18\x66\x65\x61st/core/Feature.proto\x1a\x1f\x66\x65\x61st/core/Transformation.proto\"c\n\x0b\x46\x65\x61tureView\x12)\n\x04spec\x18\x01 \x01(\x0b\x32\x1b.feast.core.FeatureViewSpec\x12)\n\x04meta\x18\x02 \x01(\x0b\x32\x1b.feast.core.FeatureViewMeta\"\x80\x05\n\x0f\x46\x65\x61tureViewSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x10\n\x08\x65ntities\x18\x03 \x03(\t\x12+\n\x08\x66\x65\x61tures\x18\x04 \x03(\x0b\x32\x19.feast.core.FeatureSpecV2\x12\x33\n\x04tags\x18\x05 \x03(\x0b\x32%.feast.core.FeatureViewSpec.TagsEntry\x12&\n\x03ttl\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12,\n\x0c\x62\x61tch_source\x18\x07 \x01(\x0b\x32\x16.feast.core.DataSource\x12\x0e\n\x06online\x18\x08 \x01(\x08\x12-\n\rstream_source\x18\t \x01(\x0b\x32\x16.feast.core.DataSource\x12\x13\n\x0b\x64\x65scription\x18\n \x01(\t\x12\r\n\x05owner\x18\x0b \x01(\t\x12\x31\n\x0e\x65ntity_columns\x18\x0c \x03(\x0b\x32\x19.feast.core.FeatureSpecV2\x12\x0f\n\x07offline\x18\r \x01(\x08\x12\x31\n\x0csource_views\x18\x0e \x03(\x0b\x32\x1b.feast.core.FeatureViewSpec\x12\x43\n\x16\x66\x65\x61ture_transformation\x18\x0f \x01(\x0b\x32#.feast.core.FeatureTransformationV2\x12\x0c\n\x04mode\x18\x10 \x01(\t\x12\x19\n\x11\x65nable_validation\x18\x11 \x01(\x08\x12\x0f\n\x07version\x18\x12 \x01(\t\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x80\x02\n\x0f\x46\x65\x61tureViewMeta\x12\x35\n\x11\x63reated_timestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12:\n\x16last_updated_timestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x46\n\x19materialization_intervals\x18\x03 \x03(\x0b\x32#.feast.core.MaterializationInterval\x12\x1e\n\x16\x63urrent_version_number\x18\x04 \x01(\x05\x12\x12\n\nversion_id\x18\x05 \x01(\t\"w\n\x17MaterializationInterval\x12.\n\nstart_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12,\n\x08\x65nd_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"@\n\x0f\x46\x65\x61tureViewList\x12-\n\x0c\x66\x65\x61tureviews\x18\x01 \x03(\x0b\x32\x17.feast.core.FeatureViewBU\n\x10\x66\x65\x61st.proto.coreB\x10\x46\x65\x61tureViewProtoZ/github.com/feast-dev/feast/go/protos/feast/coreb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -32,13 +32,13 @@ _globals['_FEATUREVIEW']._serialized_start=197 _globals['_FEATUREVIEW']._serialized_end=296 _globals['_FEATUREVIEWSPEC']._serialized_start=299 - _globals['_FEATUREVIEWSPEC']._serialized_end=895 - _globals['_FEATUREVIEWSPEC_TAGSENTRY']._serialized_start=852 - _globals['_FEATUREVIEWSPEC_TAGSENTRY']._serialized_end=895 - _globals['_FEATUREVIEWMETA']._serialized_start=898 - _globals['_FEATUREVIEWMETA']._serialized_end=1102 - _globals['_MATERIALIZATIONINTERVAL']._serialized_start=1104 - _globals['_MATERIALIZATIONINTERVAL']._serialized_end=1223 - _globals['_FEATUREVIEWLIST']._serialized_start=1225 - _globals['_FEATUREVIEWLIST']._serialized_end=1289 + _globals['_FEATUREVIEWSPEC']._serialized_end=939 + _globals['_FEATUREVIEWSPEC_TAGSENTRY']._serialized_start=896 + _globals['_FEATUREVIEWSPEC_TAGSENTRY']._serialized_end=939 + _globals['_FEATUREVIEWMETA']._serialized_start=942 + _globals['_FEATUREVIEWMETA']._serialized_end=1198 + _globals['_MATERIALIZATIONINTERVAL']._serialized_start=1200 + _globals['_MATERIALIZATIONINTERVAL']._serialized_end=1319 + _globals['_FEATUREVIEWLIST']._serialized_start=1321 + _globals['_FEATUREVIEWLIST']._serialized_end=1385 # @@protoc_insertion_point(module_scope) diff --git a/sdk/python/feast/protos/feast/core/FeatureView_pb2.pyi b/sdk/python/feast/protos/feast/core/FeatureView_pb2.pyi index a7115be8459..a62e275260f 100644 --- a/sdk/python/feast/protos/feast/core/FeatureView_pb2.pyi +++ b/sdk/python/feast/protos/feast/core/FeatureView_pb2.pyi @@ -58,7 +58,7 @@ class FeatureView(google.protobuf.message.Message): global___FeatureView = FeatureView class FeatureViewSpec(google.protobuf.message.Message): - """Next available id: 17 + """Next available id: 19 TODO(adchia): refactor common fields from this and ODFV into separate metadata proto """ @@ -95,6 +95,8 @@ class FeatureViewSpec(google.protobuf.message.Message): SOURCE_VIEWS_FIELD_NUMBER: builtins.int FEATURE_TRANSFORMATION_FIELD_NUMBER: builtins.int MODE_FIELD_NUMBER: builtins.int + ENABLE_VALIDATION_FIELD_NUMBER: builtins.int + VERSION_FIELD_NUMBER: builtins.int name: builtins.str """Name of the feature view. Must be unique. Not updated.""" project: builtins.str @@ -117,14 +119,18 @@ class FeatureViewSpec(google.protobuf.message.Message): """ @property def batch_source(self) -> feast.core.DataSource_pb2.DataSource: - """Batch/Offline DataSource where this view can retrieve offline feature data.""" + """Batch/Offline DataSource where this view can retrieve offline feature data. + Optional: if not set, the feature view has no associated batch data source (e.g. purely derived views). + """ online: builtins.bool """Whether these features should be served online or not This is also used to determine whether the features should be written to the online store """ @property def stream_source(self) -> feast.core.DataSource_pb2.DataSource: - """Streaming DataSource from where this view can consume "online" feature data.""" + """Streaming DataSource from where this view can consume "online" feature data. + Optional: only required for streaming feature views. + """ description: builtins.str """Description of the feature view.""" owner: builtins.str @@ -141,6 +147,10 @@ class FeatureViewSpec(google.protobuf.message.Message): """Feature transformation for batch feature views""" mode: builtins.str """The transformation mode (e.g., "python", "pandas", "spark", "sql", "ray")""" + enable_validation: builtins.bool + """Whether schema validation is enabled during materialization""" + version: builtins.str + """User-specified version pin (e.g. "latest", "v2", "version2")""" def __init__( self, *, @@ -160,9 +170,11 @@ class FeatureViewSpec(google.protobuf.message.Message): source_views: collections.abc.Iterable[global___FeatureViewSpec] | None = ..., feature_transformation: feast.core.Transformation_pb2.FeatureTransformationV2 | None = ..., mode: builtins.str = ..., + enable_validation: builtins.bool = ..., + version: builtins.str = ..., ) -> None: ... def HasField(self, field_name: typing_extensions.Literal["batch_source", b"batch_source", "feature_transformation", b"feature_transformation", "stream_source", b"stream_source", "ttl", b"ttl"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["batch_source", b"batch_source", "description", b"description", "entities", b"entities", "entity_columns", b"entity_columns", "feature_transformation", b"feature_transformation", "features", b"features", "mode", b"mode", "name", b"name", "offline", b"offline", "online", b"online", "owner", b"owner", "project", b"project", "source_views", b"source_views", "stream_source", b"stream_source", "tags", b"tags", "ttl", b"ttl"]) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["batch_source", b"batch_source", "description", b"description", "enable_validation", b"enable_validation", "entities", b"entities", "entity_columns", b"entity_columns", "feature_transformation", b"feature_transformation", "features", b"features", "mode", b"mode", "name", b"name", "offline", b"offline", "online", b"online", "owner", b"owner", "project", b"project", "source_views", b"source_views", "stream_source", b"stream_source", "tags", b"tags", "ttl", b"ttl", "version", b"version"]) -> None: ... global___FeatureViewSpec = FeatureViewSpec @@ -172,6 +184,8 @@ class FeatureViewMeta(google.protobuf.message.Message): CREATED_TIMESTAMP_FIELD_NUMBER: builtins.int LAST_UPDATED_TIMESTAMP_FIELD_NUMBER: builtins.int MATERIALIZATION_INTERVALS_FIELD_NUMBER: builtins.int + CURRENT_VERSION_NUMBER_FIELD_NUMBER: builtins.int + VERSION_ID_FIELD_NUMBER: builtins.int @property def created_timestamp(self) -> google.protobuf.timestamp_pb2.Timestamp: """Time where this Feature View is created""" @@ -181,15 +195,21 @@ class FeatureViewMeta(google.protobuf.message.Message): @property def materialization_intervals(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___MaterializationInterval]: """List of pairs (start_time, end_time) for which this feature view has been materialized.""" + current_version_number: builtins.int + """The current version number of this feature view in the version history.""" + version_id: builtins.str + """Auto-generated UUID identifying this specific version.""" def __init__( self, *, created_timestamp: google.protobuf.timestamp_pb2.Timestamp | None = ..., last_updated_timestamp: google.protobuf.timestamp_pb2.Timestamp | None = ..., materialization_intervals: collections.abc.Iterable[global___MaterializationInterval] | None = ..., + current_version_number: builtins.int = ..., + version_id: builtins.str = ..., ) -> None: ... def HasField(self, field_name: typing_extensions.Literal["created_timestamp", b"created_timestamp", "last_updated_timestamp", b"last_updated_timestamp"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["created_timestamp", b"created_timestamp", "last_updated_timestamp", b"last_updated_timestamp", "materialization_intervals", b"materialization_intervals"]) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["created_timestamp", b"created_timestamp", "current_version_number", b"current_version_number", "last_updated_timestamp", b"last_updated_timestamp", "materialization_intervals", b"materialization_intervals", "version_id", b"version_id"]) -> None: ... global___FeatureViewMeta = FeatureViewMeta diff --git a/sdk/python/feast/protos/feast/core/OnDemandFeatureView_pb2.py b/sdk/python/feast/protos/feast/core/OnDemandFeatureView_pb2.py index 5b8ec9b11f6..629c02c3a5f 100644 --- a/sdk/python/feast/protos/feast/core/OnDemandFeatureView_pb2.py +++ b/sdk/python/feast/protos/feast/core/OnDemandFeatureView_pb2.py @@ -21,7 +21,7 @@ from feast.protos.feast.core import Aggregation_pb2 as feast_dot_core_dot_Aggregation__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n$feast/core/OnDemandFeatureView.proto\x12\nfeast.core\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1c\x66\x65\x61st/core/FeatureView.proto\x1a&feast/core/FeatureViewProjection.proto\x1a\x18\x66\x65\x61st/core/Feature.proto\x1a\x1b\x66\x65\x61st/core/DataSource.proto\x1a\x1f\x66\x65\x61st/core/Transformation.proto\x1a\x1c\x66\x65\x61st/core/Aggregation.proto\"{\n\x13OnDemandFeatureView\x12\x31\n\x04spec\x18\x01 \x01(\x0b\x32#.feast.core.OnDemandFeatureViewSpec\x12\x31\n\x04meta\x18\x02 \x01(\x0b\x32#.feast.core.OnDemandFeatureViewMeta\"\xbf\x05\n\x17OnDemandFeatureViewSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12+\n\x08\x66\x65\x61tures\x18\x03 \x03(\x0b\x32\x19.feast.core.FeatureSpecV2\x12\x41\n\x07sources\x18\x04 \x03(\x0b\x32\x30.feast.core.OnDemandFeatureViewSpec.SourcesEntry\x12\x42\n\x15user_defined_function\x18\x05 \x01(\x0b\x32\x1f.feast.core.UserDefinedFunctionB\x02\x18\x01\x12\x43\n\x16\x66\x65\x61ture_transformation\x18\n \x01(\x0b\x32#.feast.core.FeatureTransformationV2\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t\x12;\n\x04tags\x18\x07 \x03(\x0b\x32-.feast.core.OnDemandFeatureViewSpec.TagsEntry\x12\r\n\x05owner\x18\x08 \x01(\t\x12\x0c\n\x04mode\x18\x0b \x01(\t\x12\x1d\n\x15write_to_online_store\x18\x0c \x01(\x08\x12\x10\n\x08\x65ntities\x18\r \x03(\t\x12\x31\n\x0e\x65ntity_columns\x18\x0e \x03(\x0b\x32\x19.feast.core.FeatureSpecV2\x12\x11\n\tsingleton\x18\x0f \x01(\x08\x12-\n\x0c\x61ggregations\x18\x10 \x03(\x0b\x32\x17.feast.core.Aggregation\x1aJ\n\x0cSourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12)\n\x05value\x18\x02 \x01(\x0b\x32\x1a.feast.core.OnDemandSource:\x02\x38\x01\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x8c\x01\n\x17OnDemandFeatureViewMeta\x12\x35\n\x11\x63reated_timestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12:\n\x16last_updated_timestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"\xc8\x01\n\x0eOnDemandSource\x12/\n\x0c\x66\x65\x61ture_view\x18\x01 \x01(\x0b\x32\x17.feast.core.FeatureViewH\x00\x12\x44\n\x17\x66\x65\x61ture_view_projection\x18\x03 \x01(\x0b\x32!.feast.core.FeatureViewProjectionH\x00\x12\x35\n\x13request_data_source\x18\x02 \x01(\x0b\x32\x16.feast.core.DataSourceH\x00\x42\x08\n\x06source\"H\n\x13UserDefinedFunction\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04\x62ody\x18\x02 \x01(\x0c\x12\x11\n\tbody_text\x18\x03 \x01(\t:\x02\x18\x01\"X\n\x17OnDemandFeatureViewList\x12=\n\x14ondemandfeatureviews\x18\x01 \x03(\x0b\x32\x1f.feast.core.OnDemandFeatureViewB]\n\x10\x66\x65\x61st.proto.coreB\x18OnDemandFeatureViewProtoZ/github.com/feast-dev/feast/go/protos/feast/coreb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n$feast/core/OnDemandFeatureView.proto\x12\nfeast.core\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1c\x66\x65\x61st/core/FeatureView.proto\x1a&feast/core/FeatureViewProjection.proto\x1a\x18\x66\x65\x61st/core/Feature.proto\x1a\x1b\x66\x65\x61st/core/DataSource.proto\x1a\x1f\x66\x65\x61st/core/Transformation.proto\x1a\x1c\x66\x65\x61st/core/Aggregation.proto\"{\n\x13OnDemandFeatureView\x12\x31\n\x04spec\x18\x01 \x01(\x0b\x32#.feast.core.OnDemandFeatureViewSpec\x12\x31\n\x04meta\x18\x02 \x01(\x0b\x32#.feast.core.OnDemandFeatureViewMeta\"\xd0\x05\n\x17OnDemandFeatureViewSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12+\n\x08\x66\x65\x61tures\x18\x03 \x03(\x0b\x32\x19.feast.core.FeatureSpecV2\x12\x41\n\x07sources\x18\x04 \x03(\x0b\x32\x30.feast.core.OnDemandFeatureViewSpec.SourcesEntry\x12\x42\n\x15user_defined_function\x18\x05 \x01(\x0b\x32\x1f.feast.core.UserDefinedFunctionB\x02\x18\x01\x12\x43\n\x16\x66\x65\x61ture_transformation\x18\n \x01(\x0b\x32#.feast.core.FeatureTransformationV2\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t\x12;\n\x04tags\x18\x07 \x03(\x0b\x32-.feast.core.OnDemandFeatureViewSpec.TagsEntry\x12\r\n\x05owner\x18\x08 \x01(\t\x12\x0c\n\x04mode\x18\x0b \x01(\t\x12\x1d\n\x15write_to_online_store\x18\x0c \x01(\x08\x12\x10\n\x08\x65ntities\x18\r \x03(\t\x12\x31\n\x0e\x65ntity_columns\x18\x0e \x03(\x0b\x32\x19.feast.core.FeatureSpecV2\x12\x11\n\tsingleton\x18\x0f \x01(\x08\x12-\n\x0c\x61ggregations\x18\x10 \x03(\x0b\x32\x17.feast.core.Aggregation\x12\x0f\n\x07version\x18\x11 \x01(\t\x1aJ\n\x0cSourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12)\n\x05value\x18\x02 \x01(\x0b\x32\x1a.feast.core.OnDemandSource:\x02\x38\x01\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xc0\x01\n\x17OnDemandFeatureViewMeta\x12\x35\n\x11\x63reated_timestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12:\n\x16last_updated_timestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1e\n\x16\x63urrent_version_number\x18\x03 \x01(\x05\x12\x12\n\nversion_id\x18\x04 \x01(\t\"\xc8\x01\n\x0eOnDemandSource\x12/\n\x0c\x66\x65\x61ture_view\x18\x01 \x01(\x0b\x32\x17.feast.core.FeatureViewH\x00\x12\x44\n\x17\x66\x65\x61ture_view_projection\x18\x03 \x01(\x0b\x32!.feast.core.FeatureViewProjectionH\x00\x12\x35\n\x13request_data_source\x18\x02 \x01(\x0b\x32\x16.feast.core.DataSourceH\x00\x42\x08\n\x06source\"H\n\x13UserDefinedFunction\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04\x62ody\x18\x02 \x01(\x0c\x12\x11\n\tbody_text\x18\x03 \x01(\t:\x02\x18\x01\"X\n\x17OnDemandFeatureViewList\x12=\n\x14ondemandfeatureviews\x18\x01 \x03(\x0b\x32\x1f.feast.core.OnDemandFeatureViewB]\n\x10\x66\x65\x61st.proto.coreB\x18OnDemandFeatureViewProtoZ/github.com/feast-dev/feast/go/protos/feast/coreb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -40,17 +40,17 @@ _globals['_ONDEMANDFEATUREVIEW']._serialized_start=273 _globals['_ONDEMANDFEATUREVIEW']._serialized_end=396 _globals['_ONDEMANDFEATUREVIEWSPEC']._serialized_start=399 - _globals['_ONDEMANDFEATUREVIEWSPEC']._serialized_end=1102 - _globals['_ONDEMANDFEATUREVIEWSPEC_SOURCESENTRY']._serialized_start=983 - _globals['_ONDEMANDFEATUREVIEWSPEC_SOURCESENTRY']._serialized_end=1057 - _globals['_ONDEMANDFEATUREVIEWSPEC_TAGSENTRY']._serialized_start=1059 - _globals['_ONDEMANDFEATUREVIEWSPEC_TAGSENTRY']._serialized_end=1102 - _globals['_ONDEMANDFEATUREVIEWMETA']._serialized_start=1105 - _globals['_ONDEMANDFEATUREVIEWMETA']._serialized_end=1245 - _globals['_ONDEMANDSOURCE']._serialized_start=1248 - _globals['_ONDEMANDSOURCE']._serialized_end=1448 - _globals['_USERDEFINEDFUNCTION']._serialized_start=1450 - _globals['_USERDEFINEDFUNCTION']._serialized_end=1522 - _globals['_ONDEMANDFEATUREVIEWLIST']._serialized_start=1524 - _globals['_ONDEMANDFEATUREVIEWLIST']._serialized_end=1612 + _globals['_ONDEMANDFEATUREVIEWSPEC']._serialized_end=1119 + _globals['_ONDEMANDFEATUREVIEWSPEC_SOURCESENTRY']._serialized_start=1000 + _globals['_ONDEMANDFEATUREVIEWSPEC_SOURCESENTRY']._serialized_end=1074 + _globals['_ONDEMANDFEATUREVIEWSPEC_TAGSENTRY']._serialized_start=1076 + _globals['_ONDEMANDFEATUREVIEWSPEC_TAGSENTRY']._serialized_end=1119 + _globals['_ONDEMANDFEATUREVIEWMETA']._serialized_start=1122 + _globals['_ONDEMANDFEATUREVIEWMETA']._serialized_end=1314 + _globals['_ONDEMANDSOURCE']._serialized_start=1317 + _globals['_ONDEMANDSOURCE']._serialized_end=1517 + _globals['_USERDEFINEDFUNCTION']._serialized_start=1519 + _globals['_USERDEFINEDFUNCTION']._serialized_end=1591 + _globals['_ONDEMANDFEATUREVIEWLIST']._serialized_start=1593 + _globals['_ONDEMANDFEATUREVIEWLIST']._serialized_end=1681 # @@protoc_insertion_point(module_scope) diff --git a/sdk/python/feast/protos/feast/core/OnDemandFeatureView_pb2.pyi b/sdk/python/feast/protos/feast/core/OnDemandFeatureView_pb2.pyi index c424c442ee7..42fd91f7725 100644 --- a/sdk/python/feast/protos/feast/core/OnDemandFeatureView_pb2.pyi +++ b/sdk/python/feast/protos/feast/core/OnDemandFeatureView_pb2.pyi @@ -59,7 +59,7 @@ class OnDemandFeatureView(google.protobuf.message.Message): global___OnDemandFeatureView = OnDemandFeatureView class OnDemandFeatureViewSpec(google.protobuf.message.Message): - """Next available id: 9""" + """Next available id: 18""" DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -110,6 +110,7 @@ class OnDemandFeatureViewSpec(google.protobuf.message.Message): ENTITY_COLUMNS_FIELD_NUMBER: builtins.int SINGLETON_FIELD_NUMBER: builtins.int AGGREGATIONS_FIELD_NUMBER: builtins.int + VERSION_FIELD_NUMBER: builtins.int name: builtins.str """Name of the feature view. Must be unique. Not updated.""" project: builtins.str @@ -144,6 +145,8 @@ class OnDemandFeatureViewSpec(google.protobuf.message.Message): @property def aggregations(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[feast.core.Aggregation_pb2.Aggregation]: """Aggregation definitions""" + version: builtins.str + """User-specified version pin (e.g. "latest", "v2", "version2")""" def __init__( self, *, @@ -162,9 +165,10 @@ class OnDemandFeatureViewSpec(google.protobuf.message.Message): entity_columns: collections.abc.Iterable[feast.core.Feature_pb2.FeatureSpecV2] | None = ..., singleton: builtins.bool = ..., aggregations: collections.abc.Iterable[feast.core.Aggregation_pb2.Aggregation] | None = ..., + version: builtins.str = ..., ) -> None: ... def HasField(self, field_name: typing_extensions.Literal["feature_transformation", b"feature_transformation", "user_defined_function", b"user_defined_function"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["aggregations", b"aggregations", "description", b"description", "entities", b"entities", "entity_columns", b"entity_columns", "feature_transformation", b"feature_transformation", "features", b"features", "mode", b"mode", "name", b"name", "owner", b"owner", "project", b"project", "singleton", b"singleton", "sources", b"sources", "tags", b"tags", "user_defined_function", b"user_defined_function", "write_to_online_store", b"write_to_online_store"]) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["aggregations", b"aggregations", "description", b"description", "entities", b"entities", "entity_columns", b"entity_columns", "feature_transformation", b"feature_transformation", "features", b"features", "mode", b"mode", "name", b"name", "owner", b"owner", "project", b"project", "singleton", b"singleton", "sources", b"sources", "tags", b"tags", "user_defined_function", b"user_defined_function", "version", b"version", "write_to_online_store", b"write_to_online_store"]) -> None: ... global___OnDemandFeatureViewSpec = OnDemandFeatureViewSpec @@ -173,20 +177,28 @@ class OnDemandFeatureViewMeta(google.protobuf.message.Message): CREATED_TIMESTAMP_FIELD_NUMBER: builtins.int LAST_UPDATED_TIMESTAMP_FIELD_NUMBER: builtins.int + CURRENT_VERSION_NUMBER_FIELD_NUMBER: builtins.int + VERSION_ID_FIELD_NUMBER: builtins.int @property def created_timestamp(self) -> google.protobuf.timestamp_pb2.Timestamp: """Time where this Feature View is created""" @property def last_updated_timestamp(self) -> google.protobuf.timestamp_pb2.Timestamp: """Time where this Feature View is last updated""" + current_version_number: builtins.int + """The current version number of this feature view in the version history.""" + version_id: builtins.str + """Auto-generated UUID identifying this specific version.""" def __init__( self, *, created_timestamp: google.protobuf.timestamp_pb2.Timestamp | None = ..., last_updated_timestamp: google.protobuf.timestamp_pb2.Timestamp | None = ..., + current_version_number: builtins.int = ..., + version_id: builtins.str = ..., ) -> None: ... def HasField(self, field_name: typing_extensions.Literal["created_timestamp", b"created_timestamp", "last_updated_timestamp", b"last_updated_timestamp"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["created_timestamp", b"created_timestamp", "last_updated_timestamp", b"last_updated_timestamp"]) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["created_timestamp", b"created_timestamp", "current_version_number", b"current_version_number", "last_updated_timestamp", b"last_updated_timestamp", "version_id", b"version_id"]) -> None: ... global___OnDemandFeatureViewMeta = OnDemandFeatureViewMeta diff --git a/sdk/python/feast/protos/feast/core/Project_pb2.pyi b/sdk/python/feast/protos/feast/core/Project_pb2.pyi index 3196304a19b..e3cce2ec425 100644 --- a/sdk/python/feast/protos/feast/core/Project_pb2.pyi +++ b/sdk/python/feast/protos/feast/core/Project_pb2.pyi @@ -1,19 +1,19 @@ """ @generated by mypy-protobuf. Do not edit manually! isort:skip_file - -* Copyright 2020 The Feast Authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* https://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and + +* Copyright 2020 The Feast Authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and * limitations under the License. """ import builtins diff --git a/sdk/python/feast/protos/feast/core/Registry_pb2.py b/sdk/python/feast/protos/feast/core/Registry_pb2.py index 671958d80c7..04c4e700597 100644 --- a/sdk/python/feast/protos/feast/core/Registry_pb2.py +++ b/sdk/python/feast/protos/feast/core/Registry_pb2.py @@ -25,9 +25,10 @@ from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 from feast.protos.feast.core import Permission_pb2 as feast_dot_core_dot_Permission__pb2 from feast.protos.feast.core import Project_pb2 as feast_dot_core_dot_Project__pb2 +from feast.protos.feast.core import FeatureViewVersion_pb2 as feast_dot_core_dot_FeatureViewVersion__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19\x66\x65\x61st/core/Registry.proto\x12\nfeast.core\x1a\x17\x66\x65\x61st/core/Entity.proto\x1a\x1f\x66\x65\x61st/core/FeatureService.proto\x1a\x1d\x66\x65\x61st/core/FeatureTable.proto\x1a\x1c\x66\x65\x61st/core/FeatureView.proto\x1a\x1c\x66\x65\x61st/core/InfraObject.proto\x1a$feast/core/OnDemandFeatureView.proto\x1a\"feast/core/StreamFeatureView.proto\x1a\x1b\x66\x65\x61st/core/DataSource.proto\x1a\x1d\x66\x65\x61st/core/SavedDataset.proto\x1a\"feast/core/ValidationProfile.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1b\x66\x65\x61st/core/Permission.proto\x1a\x18\x66\x65\x61st/core/Project.proto\"\xff\x05\n\x08Registry\x12$\n\x08\x65ntities\x18\x01 \x03(\x0b\x32\x12.feast.core.Entity\x12\x30\n\x0e\x66\x65\x61ture_tables\x18\x02 \x03(\x0b\x32\x18.feast.core.FeatureTable\x12.\n\rfeature_views\x18\x06 \x03(\x0b\x32\x17.feast.core.FeatureView\x12,\n\x0c\x64\x61ta_sources\x18\x0c \x03(\x0b\x32\x16.feast.core.DataSource\x12@\n\x17on_demand_feature_views\x18\x08 \x03(\x0b\x32\x1f.feast.core.OnDemandFeatureView\x12;\n\x14stream_feature_views\x18\x0e \x03(\x0b\x32\x1d.feast.core.StreamFeatureView\x12\x34\n\x10\x66\x65\x61ture_services\x18\x07 \x03(\x0b\x32\x1a.feast.core.FeatureService\x12\x30\n\x0esaved_datasets\x18\x0b \x03(\x0b\x32\x18.feast.core.SavedDataset\x12>\n\x15validation_references\x18\r \x03(\x0b\x32\x1f.feast.core.ValidationReference\x12 \n\x05infra\x18\n \x01(\x0b\x32\x11.feast.core.Infra\x12\x39\n\x10project_metadata\x18\x0f \x03(\x0b\x32\x1b.feast.core.ProjectMetadataB\x02\x18\x01\x12\x1f\n\x17registry_schema_version\x18\x03 \x01(\t\x12\x12\n\nversion_id\x18\x04 \x01(\t\x12\x30\n\x0clast_updated\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12+\n\x0bpermissions\x18\x10 \x03(\x0b\x32\x16.feast.core.Permission\x12%\n\x08projects\x18\x11 \x03(\x0b\x32\x13.feast.core.Project\"8\n\x0fProjectMetadata\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x14\n\x0cproject_uuid\x18\x02 \x01(\tBR\n\x10\x66\x65\x61st.proto.coreB\rRegistryProtoZ/github.com/feast-dev/feast/go/protos/feast/coreb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19\x66\x65\x61st/core/Registry.proto\x12\nfeast.core\x1a\x17\x66\x65\x61st/core/Entity.proto\x1a\x1f\x66\x65\x61st/core/FeatureService.proto\x1a\x1d\x66\x65\x61st/core/FeatureTable.proto\x1a\x1c\x66\x65\x61st/core/FeatureView.proto\x1a\x1c\x66\x65\x61st/core/InfraObject.proto\x1a$feast/core/OnDemandFeatureView.proto\x1a\"feast/core/StreamFeatureView.proto\x1a\x1b\x66\x65\x61st/core/DataSource.proto\x1a\x1d\x66\x65\x61st/core/SavedDataset.proto\x1a\"feast/core/ValidationProfile.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1b\x66\x65\x61st/core/Permission.proto\x1a\x18\x66\x65\x61st/core/Project.proto\x1a#feast/core/FeatureViewVersion.proto\"\xcc\x06\n\x08Registry\x12$\n\x08\x65ntities\x18\x01 \x03(\x0b\x32\x12.feast.core.Entity\x12\x30\n\x0e\x66\x65\x61ture_tables\x18\x02 \x03(\x0b\x32\x18.feast.core.FeatureTable\x12.\n\rfeature_views\x18\x06 \x03(\x0b\x32\x17.feast.core.FeatureView\x12,\n\x0c\x64\x61ta_sources\x18\x0c \x03(\x0b\x32\x16.feast.core.DataSource\x12@\n\x17on_demand_feature_views\x18\x08 \x03(\x0b\x32\x1f.feast.core.OnDemandFeatureView\x12;\n\x14stream_feature_views\x18\x0e \x03(\x0b\x32\x1d.feast.core.StreamFeatureView\x12\x34\n\x10\x66\x65\x61ture_services\x18\x07 \x03(\x0b\x32\x1a.feast.core.FeatureService\x12\x30\n\x0esaved_datasets\x18\x0b \x03(\x0b\x32\x18.feast.core.SavedDataset\x12>\n\x15validation_references\x18\r \x03(\x0b\x32\x1f.feast.core.ValidationReference\x12 \n\x05infra\x18\n \x01(\x0b\x32\x11.feast.core.Infra\x12\x39\n\x10project_metadata\x18\x0f \x03(\x0b\x32\x1b.feast.core.ProjectMetadataB\x02\x18\x01\x12\x1f\n\x17registry_schema_version\x18\x03 \x01(\t\x12\x12\n\nversion_id\x18\x04 \x01(\t\x12\x30\n\x0clast_updated\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12+\n\x0bpermissions\x18\x10 \x03(\x0b\x32\x16.feast.core.Permission\x12%\n\x08projects\x18\x11 \x03(\x0b\x32\x13.feast.core.Project\x12K\n\x1c\x66\x65\x61ture_view_version_history\x18\x12 \x01(\x0b\x32%.feast.core.FeatureViewVersionHistory\"8\n\x0fProjectMetadata\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x14\n\x0cproject_uuid\x18\x02 \x01(\tBR\n\x10\x66\x65\x61st.proto.coreB\rRegistryProtoZ/github.com/feast-dev/feast/go/protos/feast/coreb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -37,8 +38,8 @@ _globals['DESCRIPTOR']._serialized_options = b'\n\020feast.proto.coreB\rRegistryProtoZ/github.com/feast-dev/feast/go/protos/feast/core' _globals['_REGISTRY'].fields_by_name['project_metadata']._options = None _globals['_REGISTRY'].fields_by_name['project_metadata']._serialized_options = b'\030\001' - _globals['_REGISTRY']._serialized_start=449 - _globals['_REGISTRY']._serialized_end=1216 - _globals['_PROJECTMETADATA']._serialized_start=1218 - _globals['_PROJECTMETADATA']._serialized_end=1274 + _globals['_REGISTRY']._serialized_start=486 + _globals['_REGISTRY']._serialized_end=1330 + _globals['_PROJECTMETADATA']._serialized_start=1332 + _globals['_PROJECTMETADATA']._serialized_end=1388 # @@protoc_insertion_point(module_scope) diff --git a/sdk/python/feast/protos/feast/core/Registry_pb2.pyi b/sdk/python/feast/protos/feast/core/Registry_pb2.pyi index ad09878b77f..29bd76323e3 100644 --- a/sdk/python/feast/protos/feast/core/Registry_pb2.pyi +++ b/sdk/python/feast/protos/feast/core/Registry_pb2.pyi @@ -22,6 +22,7 @@ import feast.core.DataSource_pb2 import feast.core.Entity_pb2 import feast.core.FeatureService_pb2 import feast.core.FeatureTable_pb2 +import feast.core.FeatureViewVersion_pb2 import feast.core.FeatureView_pb2 import feast.core.InfraObject_pb2 import feast.core.OnDemandFeatureView_pb2 @@ -44,7 +45,7 @@ else: DESCRIPTOR: google.protobuf.descriptor.FileDescriptor class Registry(google.protobuf.message.Message): - """Next id: 18""" + """Next id: 19""" DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -64,6 +65,7 @@ class Registry(google.protobuf.message.Message): LAST_UPDATED_FIELD_NUMBER: builtins.int PERMISSIONS_FIELD_NUMBER: builtins.int PROJECTS_FIELD_NUMBER: builtins.int + FEATURE_VIEW_VERSION_HISTORY_FIELD_NUMBER: builtins.int @property def entities(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[feast.core.Entity_pb2.Entity]: ... @property @@ -97,6 +99,8 @@ class Registry(google.protobuf.message.Message): def permissions(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[feast.core.Permission_pb2.Permission]: ... @property def projects(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[feast.core.Project_pb2.Project]: ... + @property + def feature_view_version_history(self) -> feast.core.FeatureViewVersion_pb2.FeatureViewVersionHistory: ... def __init__( self, *, @@ -116,9 +120,10 @@ class Registry(google.protobuf.message.Message): last_updated: google.protobuf.timestamp_pb2.Timestamp | None = ..., permissions: collections.abc.Iterable[feast.core.Permission_pb2.Permission] | None = ..., projects: collections.abc.Iterable[feast.core.Project_pb2.Project] | None = ..., + feature_view_version_history: feast.core.FeatureViewVersion_pb2.FeatureViewVersionHistory | None = ..., ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["infra", b"infra", "last_updated", b"last_updated"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["data_sources", b"data_sources", "entities", b"entities", "feature_services", b"feature_services", "feature_tables", b"feature_tables", "feature_views", b"feature_views", "infra", b"infra", "last_updated", b"last_updated", "on_demand_feature_views", b"on_demand_feature_views", "permissions", b"permissions", "project_metadata", b"project_metadata", "projects", b"projects", "registry_schema_version", b"registry_schema_version", "saved_datasets", b"saved_datasets", "stream_feature_views", b"stream_feature_views", "validation_references", b"validation_references", "version_id", b"version_id"]) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["feature_view_version_history", b"feature_view_version_history", "infra", b"infra", "last_updated", b"last_updated"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["data_sources", b"data_sources", "entities", b"entities", "feature_services", b"feature_services", "feature_tables", b"feature_tables", "feature_view_version_history", b"feature_view_version_history", "feature_views", b"feature_views", "infra", b"infra", "last_updated", b"last_updated", "on_demand_feature_views", b"on_demand_feature_views", "permissions", b"permissions", "project_metadata", b"project_metadata", "projects", b"projects", "registry_schema_version", b"registry_schema_version", "saved_datasets", b"saved_datasets", "stream_feature_views", b"stream_feature_views", "validation_references", b"validation_references", "version_id", b"version_id"]) -> None: ... global___Registry = Registry diff --git a/sdk/python/feast/protos/feast/core/StreamFeatureView_pb2.py b/sdk/python/feast/protos/feast/core/StreamFeatureView_pb2.py index f64c2852aa9..3c87e635b92 100644 --- a/sdk/python/feast/protos/feast/core/StreamFeatureView_pb2.py +++ b/sdk/python/feast/protos/feast/core/StreamFeatureView_pb2.py @@ -21,7 +21,7 @@ from feast.protos.feast.core import Transformation_pb2 as feast_dot_core_dot_Transformation__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"feast/core/StreamFeatureView.proto\x12\nfeast.core\x1a\x1egoogle/protobuf/duration.proto\x1a$feast/core/OnDemandFeatureView.proto\x1a\x1c\x66\x65\x61st/core/FeatureView.proto\x1a\x18\x66\x65\x61st/core/Feature.proto\x1a\x1b\x66\x65\x61st/core/DataSource.proto\x1a\x1c\x66\x65\x61st/core/Aggregation.proto\x1a\x1f\x66\x65\x61st/core/Transformation.proto\"o\n\x11StreamFeatureView\x12/\n\x04spec\x18\x01 \x01(\x0b\x32!.feast.core.StreamFeatureViewSpec\x12)\n\x04meta\x18\x02 \x01(\x0b\x32\x1b.feast.core.FeatureViewMeta\"\xf3\x05\n\x15StreamFeatureViewSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x10\n\x08\x65ntities\x18\x03 \x03(\t\x12+\n\x08\x66\x65\x61tures\x18\x04 \x03(\x0b\x32\x19.feast.core.FeatureSpecV2\x12\x31\n\x0e\x65ntity_columns\x18\x05 \x03(\x0b\x32\x19.feast.core.FeatureSpecV2\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t\x12\x39\n\x04tags\x18\x07 \x03(\x0b\x32+.feast.core.StreamFeatureViewSpec.TagsEntry\x12\r\n\x05owner\x18\x08 \x01(\t\x12&\n\x03ttl\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12,\n\x0c\x62\x61tch_source\x18\n \x01(\x0b\x32\x16.feast.core.DataSource\x12-\n\rstream_source\x18\x0b \x01(\x0b\x32\x16.feast.core.DataSource\x12\x0e\n\x06online\x18\x0c \x01(\x08\x12\x42\n\x15user_defined_function\x18\r \x01(\x0b\x32\x1f.feast.core.UserDefinedFunctionB\x02\x18\x01\x12\x0c\n\x04mode\x18\x0e \x01(\t\x12-\n\x0c\x61ggregations\x18\x0f \x03(\x0b\x32\x17.feast.core.Aggregation\x12\x17\n\x0ftimestamp_field\x18\x10 \x01(\t\x12\x43\n\x16\x66\x65\x61ture_transformation\x18\x11 \x01(\x0b\x32#.feast.core.FeatureTransformationV2\x12\x15\n\renable_tiling\x18\x12 \x01(\x08\x12\x32\n\x0ftiling_hop_size\x18\x13 \x01(\x0b\x32\x19.google.protobuf.Duration\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42[\n\x10\x66\x65\x61st.proto.coreB\x16StreamFeatureViewProtoZ/github.com/feast-dev/feast/go/protos/feast/coreb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"feast/core/StreamFeatureView.proto\x12\nfeast.core\x1a\x1egoogle/protobuf/duration.proto\x1a$feast/core/OnDemandFeatureView.proto\x1a\x1c\x66\x65\x61st/core/FeatureView.proto\x1a\x18\x66\x65\x61st/core/Feature.proto\x1a\x1b\x66\x65\x61st/core/DataSource.proto\x1a\x1c\x66\x65\x61st/core/Aggregation.proto\x1a\x1f\x66\x65\x61st/core/Transformation.proto\"o\n\x11StreamFeatureView\x12/\n\x04spec\x18\x01 \x01(\x0b\x32!.feast.core.StreamFeatureViewSpec\x12)\n\x04meta\x18\x02 \x01(\x0b\x32\x1b.feast.core.FeatureViewMeta\"\x9f\x06\n\x15StreamFeatureViewSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07project\x18\x02 \x01(\t\x12\x10\n\x08\x65ntities\x18\x03 \x03(\t\x12+\n\x08\x66\x65\x61tures\x18\x04 \x03(\x0b\x32\x19.feast.core.FeatureSpecV2\x12\x31\n\x0e\x65ntity_columns\x18\x05 \x03(\x0b\x32\x19.feast.core.FeatureSpecV2\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t\x12\x39\n\x04tags\x18\x07 \x03(\x0b\x32+.feast.core.StreamFeatureViewSpec.TagsEntry\x12\r\n\x05owner\x18\x08 \x01(\t\x12&\n\x03ttl\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12,\n\x0c\x62\x61tch_source\x18\n \x01(\x0b\x32\x16.feast.core.DataSource\x12-\n\rstream_source\x18\x0b \x01(\x0b\x32\x16.feast.core.DataSource\x12\x0e\n\x06online\x18\x0c \x01(\x08\x12\x42\n\x15user_defined_function\x18\r \x01(\x0b\x32\x1f.feast.core.UserDefinedFunctionB\x02\x18\x01\x12\x0c\n\x04mode\x18\x0e \x01(\t\x12-\n\x0c\x61ggregations\x18\x0f \x03(\x0b\x32\x17.feast.core.Aggregation\x12\x17\n\x0ftimestamp_field\x18\x10 \x01(\t\x12\x43\n\x16\x66\x65\x61ture_transformation\x18\x11 \x01(\x0b\x32#.feast.core.FeatureTransformationV2\x12\x15\n\renable_tiling\x18\x12 \x01(\x08\x12\x32\n\x0ftiling_hop_size\x18\x13 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x19\n\x11\x65nable_validation\x18\x14 \x01(\x08\x12\x0f\n\x07version\x18\x15 \x01(\t\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42[\n\x10\x66\x65\x61st.proto.coreB\x16StreamFeatureViewProtoZ/github.com/feast-dev/feast/go/protos/feast/coreb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -36,7 +36,7 @@ _globals['_STREAMFEATUREVIEW']._serialized_start=268 _globals['_STREAMFEATUREVIEW']._serialized_end=379 _globals['_STREAMFEATUREVIEWSPEC']._serialized_start=382 - _globals['_STREAMFEATUREVIEWSPEC']._serialized_end=1137 - _globals['_STREAMFEATUREVIEWSPEC_TAGSENTRY']._serialized_start=1094 - _globals['_STREAMFEATUREVIEWSPEC_TAGSENTRY']._serialized_end=1137 + _globals['_STREAMFEATUREVIEWSPEC']._serialized_end=1181 + _globals['_STREAMFEATUREVIEWSPEC_TAGSENTRY']._serialized_start=1138 + _globals['_STREAMFEATUREVIEWSPEC_TAGSENTRY']._serialized_end=1181 # @@protoc_insertion_point(module_scope) diff --git a/sdk/python/feast/protos/feast/core/StreamFeatureView_pb2.pyi b/sdk/python/feast/protos/feast/core/StreamFeatureView_pb2.pyi index 160a59b35df..b4ab6a9a016 100644 --- a/sdk/python/feast/protos/feast/core/StreamFeatureView_pb2.pyi +++ b/sdk/python/feast/protos/feast/core/StreamFeatureView_pb2.pyi @@ -59,7 +59,7 @@ class StreamFeatureView(google.protobuf.message.Message): global___StreamFeatureView = StreamFeatureView class StreamFeatureViewSpec(google.protobuf.message.Message): - """Next available id: 20""" + """Next available id: 22""" DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -97,6 +97,8 @@ class StreamFeatureViewSpec(google.protobuf.message.Message): FEATURE_TRANSFORMATION_FIELD_NUMBER: builtins.int ENABLE_TILING_FIELD_NUMBER: builtins.int TILING_HOP_SIZE_FIELD_NUMBER: builtins.int + ENABLE_VALIDATION_FIELD_NUMBER: builtins.int + VERSION_FIELD_NUMBER: builtins.int name: builtins.str """Name of the feature view. Must be unique. Not updated.""" project: builtins.str @@ -152,6 +154,10 @@ class StreamFeatureViewSpec(google.protobuf.message.Message): """Hop size for tiling (e.g., 5 minutes). Determines the granularity of pre-aggregated tiles. If not specified, defaults to 5 minutes. Only used when enable_tiling is true. """ + enable_validation: builtins.bool + """Whether schema validation is enabled during materialization""" + version: builtins.str + """User-specified version pin (e.g. "latest", "v2", "version2")""" def __init__( self, *, @@ -174,8 +180,10 @@ class StreamFeatureViewSpec(google.protobuf.message.Message): feature_transformation: feast.core.Transformation_pb2.FeatureTransformationV2 | None = ..., enable_tiling: builtins.bool = ..., tiling_hop_size: google.protobuf.duration_pb2.Duration | None = ..., + enable_validation: builtins.bool = ..., + version: builtins.str = ..., ) -> None: ... def HasField(self, field_name: typing_extensions.Literal["batch_source", b"batch_source", "feature_transformation", b"feature_transformation", "stream_source", b"stream_source", "tiling_hop_size", b"tiling_hop_size", "ttl", b"ttl", "user_defined_function", b"user_defined_function"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["aggregations", b"aggregations", "batch_source", b"batch_source", "description", b"description", "enable_tiling", b"enable_tiling", "entities", b"entities", "entity_columns", b"entity_columns", "feature_transformation", b"feature_transformation", "features", b"features", "mode", b"mode", "name", b"name", "online", b"online", "owner", b"owner", "project", b"project", "stream_source", b"stream_source", "tags", b"tags", "tiling_hop_size", b"tiling_hop_size", "timestamp_field", b"timestamp_field", "ttl", b"ttl", "user_defined_function", b"user_defined_function"]) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["aggregations", b"aggregations", "batch_source", b"batch_source", "description", b"description", "enable_tiling", b"enable_tiling", "enable_validation", b"enable_validation", "entities", b"entities", "entity_columns", b"entity_columns", "feature_transformation", b"feature_transformation", "features", b"features", "mode", b"mode", "name", b"name", "online", b"online", "owner", b"owner", "project", b"project", "stream_source", b"stream_source", "tags", b"tags", "tiling_hop_size", b"tiling_hop_size", "timestamp_field", b"timestamp_field", "ttl", b"ttl", "user_defined_function", b"user_defined_function", "version", b"version"]) -> None: ... global___StreamFeatureViewSpec = StreamFeatureViewSpec diff --git a/sdk/python/feast/protos/feast/serving/GrpcServer_pb2.py b/sdk/python/feast/protos/feast/serving/GrpcServer_pb2.py index dcf91563185..586938289ae 100644 --- a/sdk/python/feast/protos/feast/serving/GrpcServer_pb2.py +++ b/sdk/python/feast/protos/feast/serving/GrpcServer_pb2.py @@ -13,9 +13,10 @@ from feast.protos.feast.serving import ServingService_pb2 as feast_dot_serving_dot_ServingService__pb2 +from feast.protos.feast.types import Value_pb2 as feast_dot_types_dot_Value__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1e\x66\x65\x61st/serving/GrpcServer.proto\x1a\"feast/serving/ServingService.proto\"\xb3\x01\n\x0bPushRequest\x12,\n\x08\x66\x65\x61tures\x18\x01 \x03(\x0b\x32\x1a.PushRequest.FeaturesEntry\x12\x1b\n\x13stream_feature_view\x18\x02 \x01(\t\x12\x1c\n\x14\x61llow_registry_cache\x18\x03 \x01(\x08\x12\n\n\x02to\x18\x04 \x01(\t\x1a/\n\rFeaturesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x1e\n\x0cPushResponse\x12\x0e\n\x06status\x18\x01 \x01(\x08\"\xc1\x01\n\x19WriteToOnlineStoreRequest\x12:\n\x08\x66\x65\x61tures\x18\x01 \x03(\x0b\x32(.WriteToOnlineStoreRequest.FeaturesEntry\x12\x19\n\x11\x66\x65\x61ture_view_name\x18\x02 \x01(\t\x12\x1c\n\x14\x61llow_registry_cache\x18\x03 \x01(\x08\x1a/\n\rFeaturesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\",\n\x1aWriteToOnlineStoreResponse\x12\x0e\n\x06status\x18\x01 \x01(\x08\x32\xf1\x01\n\x11GrpcFeatureServer\x12%\n\x04Push\x12\x0c.PushRequest\x1a\r.PushResponse\"\x00\x12M\n\x12WriteToOnlineStore\x12\x1a.WriteToOnlineStoreRequest\x1a\x1b.WriteToOnlineStoreResponse\x12\x66\n\x11GetOnlineFeatures\x12\'.feast.serving.GetOnlineFeaturesRequest\x1a(.feast.serving.GetOnlineFeaturesResponseB]\n\x13\x66\x65\x61st.proto.servingB\x12GrpcServerAPIProtoZ2github.com/feast-dev/feast/go/protos/feast/servingb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1e\x66\x65\x61st/serving/GrpcServer.proto\x1a\"feast/serving/ServingService.proto\x1a\x17\x66\x65\x61st/types/Value.proto\"\xb6\x02\n\x0bPushRequest\x12,\n\x08\x66\x65\x61tures\x18\x01 \x03(\x0b\x32\x1a.PushRequest.FeaturesEntry\x12\x1b\n\x13stream_feature_view\x18\x02 \x01(\t\x12\x1c\n\x14\x61llow_registry_cache\x18\x03 \x01(\x08\x12\n\n\x02to\x18\x04 \x01(\t\x12\x37\n\x0etyped_features\x18\x05 \x03(\x0b\x32\x1f.PushRequest.TypedFeaturesEntry\x1a/\n\rFeaturesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1aH\n\x12TypedFeaturesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.feast.types.Value:\x02\x38\x01\"\x1e\n\x0cPushResponse\x12\x0e\n\x06status\x18\x01 \x01(\x08\"\xd2\x02\n\x19WriteToOnlineStoreRequest\x12:\n\x08\x66\x65\x61tures\x18\x01 \x03(\x0b\x32(.WriteToOnlineStoreRequest.FeaturesEntry\x12\x19\n\x11\x66\x65\x61ture_view_name\x18\x02 \x01(\t\x12\x1c\n\x14\x61llow_registry_cache\x18\x03 \x01(\x08\x12\x45\n\x0etyped_features\x18\x04 \x03(\x0b\x32-.WriteToOnlineStoreRequest.TypedFeaturesEntry\x1a/\n\rFeaturesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1aH\n\x12TypedFeaturesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.feast.types.Value:\x02\x38\x01\",\n\x1aWriteToOnlineStoreResponse\x12\x0e\n\x06status\x18\x01 \x01(\x08\x32\xf1\x01\n\x11GrpcFeatureServer\x12%\n\x04Push\x12\x0c.PushRequest\x1a\r.PushResponse\"\x00\x12M\n\x12WriteToOnlineStore\x12\x1a.WriteToOnlineStoreRequest\x1a\x1b.WriteToOnlineStoreResponse\x12\x66\n\x11GetOnlineFeatures\x12\'.feast.serving.GetOnlineFeaturesRequest\x1a(.feast.serving.GetOnlineFeaturesResponseB]\n\x13\x66\x65\x61st.proto.servingB\x12GrpcServerAPIProtoZ2github.com/feast-dev/feast/go/protos/feast/servingb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -25,20 +26,28 @@ _globals['DESCRIPTOR']._serialized_options = b'\n\023feast.proto.servingB\022GrpcServerAPIProtoZ2github.com/feast-dev/feast/go/protos/feast/serving' _globals['_PUSHREQUEST_FEATURESENTRY']._options = None _globals['_PUSHREQUEST_FEATURESENTRY']._serialized_options = b'8\001' + _globals['_PUSHREQUEST_TYPEDFEATURESENTRY']._options = None + _globals['_PUSHREQUEST_TYPEDFEATURESENTRY']._serialized_options = b'8\001' _globals['_WRITETOONLINESTOREREQUEST_FEATURESENTRY']._options = None _globals['_WRITETOONLINESTOREREQUEST_FEATURESENTRY']._serialized_options = b'8\001' - _globals['_PUSHREQUEST']._serialized_start=71 - _globals['_PUSHREQUEST']._serialized_end=250 - _globals['_PUSHREQUEST_FEATURESENTRY']._serialized_start=203 - _globals['_PUSHREQUEST_FEATURESENTRY']._serialized_end=250 - _globals['_PUSHRESPONSE']._serialized_start=252 - _globals['_PUSHRESPONSE']._serialized_end=282 - _globals['_WRITETOONLINESTOREREQUEST']._serialized_start=285 - _globals['_WRITETOONLINESTOREREQUEST']._serialized_end=478 - _globals['_WRITETOONLINESTOREREQUEST_FEATURESENTRY']._serialized_start=203 - _globals['_WRITETOONLINESTOREREQUEST_FEATURESENTRY']._serialized_end=250 - _globals['_WRITETOONLINESTORERESPONSE']._serialized_start=480 - _globals['_WRITETOONLINESTORERESPONSE']._serialized_end=524 - _globals['_GRPCFEATURESERVER']._serialized_start=527 - _globals['_GRPCFEATURESERVER']._serialized_end=768 + _globals['_WRITETOONLINESTOREREQUEST_TYPEDFEATURESENTRY']._options = None + _globals['_WRITETOONLINESTOREREQUEST_TYPEDFEATURESENTRY']._serialized_options = b'8\001' + _globals['_PUSHREQUEST']._serialized_start=96 + _globals['_PUSHREQUEST']._serialized_end=406 + _globals['_PUSHREQUEST_FEATURESENTRY']._serialized_start=285 + _globals['_PUSHREQUEST_FEATURESENTRY']._serialized_end=332 + _globals['_PUSHREQUEST_TYPEDFEATURESENTRY']._serialized_start=334 + _globals['_PUSHREQUEST_TYPEDFEATURESENTRY']._serialized_end=406 + _globals['_PUSHRESPONSE']._serialized_start=408 + _globals['_PUSHRESPONSE']._serialized_end=438 + _globals['_WRITETOONLINESTOREREQUEST']._serialized_start=441 + _globals['_WRITETOONLINESTOREREQUEST']._serialized_end=779 + _globals['_WRITETOONLINESTOREREQUEST_FEATURESENTRY']._serialized_start=285 + _globals['_WRITETOONLINESTOREREQUEST_FEATURESENTRY']._serialized_end=332 + _globals['_WRITETOONLINESTOREREQUEST_TYPEDFEATURESENTRY']._serialized_start=334 + _globals['_WRITETOONLINESTOREREQUEST_TYPEDFEATURESENTRY']._serialized_end=406 + _globals['_WRITETOONLINESTORERESPONSE']._serialized_start=781 + _globals['_WRITETOONLINESTORERESPONSE']._serialized_end=825 + _globals['_GRPCFEATURESERVER']._serialized_start=828 + _globals['_GRPCFEATURESERVER']._serialized_end=1069 # @@protoc_insertion_point(module_scope) diff --git a/sdk/python/feast/protos/feast/serving/GrpcServer_pb2.pyi b/sdk/python/feast/protos/feast/serving/GrpcServer_pb2.pyi index 54964f46e58..a83cd87a16e 100644 --- a/sdk/python/feast/protos/feast/serving/GrpcServer_pb2.pyi +++ b/sdk/python/feast/protos/feast/serving/GrpcServer_pb2.pyi @@ -4,6 +4,7 @@ isort:skip_file """ import builtins import collections.abc +import feast.types.Value_pb2 import google.protobuf.descriptor import google.protobuf.internal.containers import google.protobuf.message @@ -34,15 +35,35 @@ class PushRequest(google.protobuf.message.Message): ) -> None: ... def ClearField(self, field_name: typing_extensions.Literal["key", b"key", "value", b"value"]) -> None: ... + class TypedFeaturesEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + @property + def value(self) -> feast.types.Value_pb2.Value: ... + def __init__( + self, + *, + key: builtins.str = ..., + value: feast.types.Value_pb2.Value | None = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["value", b"value"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["key", b"key", "value", b"value"]) -> None: ... + FEATURES_FIELD_NUMBER: builtins.int STREAM_FEATURE_VIEW_FIELD_NUMBER: builtins.int ALLOW_REGISTRY_CACHE_FIELD_NUMBER: builtins.int TO_FIELD_NUMBER: builtins.int + TYPED_FEATURES_FIELD_NUMBER: builtins.int @property def features(self) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: ... stream_feature_view: builtins.str allow_registry_cache: builtins.bool to: builtins.str + @property + def typed_features(self) -> google.protobuf.internal.containers.MessageMap[builtins.str, feast.types.Value_pb2.Value]: ... def __init__( self, *, @@ -50,8 +71,9 @@ class PushRequest(google.protobuf.message.Message): stream_feature_view: builtins.str = ..., allow_registry_cache: builtins.bool = ..., to: builtins.str = ..., + typed_features: collections.abc.Mapping[builtins.str, feast.types.Value_pb2.Value] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["allow_registry_cache", b"allow_registry_cache", "features", b"features", "stream_feature_view", b"stream_feature_view", "to", b"to"]) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["allow_registry_cache", b"allow_registry_cache", "features", b"features", "stream_feature_view", b"stream_feature_view", "to", b"to", "typed_features", b"typed_features"]) -> None: ... global___PushRequest = PushRequest @@ -87,21 +109,42 @@ class WriteToOnlineStoreRequest(google.protobuf.message.Message): ) -> None: ... def ClearField(self, field_name: typing_extensions.Literal["key", b"key", "value", b"value"]) -> None: ... + class TypedFeaturesEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.str + @property + def value(self) -> feast.types.Value_pb2.Value: ... + def __init__( + self, + *, + key: builtins.str = ..., + value: feast.types.Value_pb2.Value | None = ..., + ) -> None: ... + def HasField(self, field_name: typing_extensions.Literal["value", b"value"]) -> builtins.bool: ... + def ClearField(self, field_name: typing_extensions.Literal["key", b"key", "value", b"value"]) -> None: ... + FEATURES_FIELD_NUMBER: builtins.int FEATURE_VIEW_NAME_FIELD_NUMBER: builtins.int ALLOW_REGISTRY_CACHE_FIELD_NUMBER: builtins.int + TYPED_FEATURES_FIELD_NUMBER: builtins.int @property def features(self) -> google.protobuf.internal.containers.ScalarMap[builtins.str, builtins.str]: ... feature_view_name: builtins.str allow_registry_cache: builtins.bool + @property + def typed_features(self) -> google.protobuf.internal.containers.MessageMap[builtins.str, feast.types.Value_pb2.Value]: ... def __init__( self, *, features: collections.abc.Mapping[builtins.str, builtins.str] | None = ..., feature_view_name: builtins.str = ..., allow_registry_cache: builtins.bool = ..., + typed_features: collections.abc.Mapping[builtins.str, feast.types.Value_pb2.Value] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["allow_registry_cache", b"allow_registry_cache", "feature_view_name", b"feature_view_name", "features", b"features"]) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["allow_registry_cache", b"allow_registry_cache", "feature_view_name", b"feature_view_name", "features", b"features", "typed_features", b"typed_features"]) -> None: ... global___WriteToOnlineStoreRequest = WriteToOnlineStoreRequest diff --git a/sdk/python/feast/protos/feast/serving/ServingService_pb2.py b/sdk/python/feast/protos/feast/serving/ServingService_pb2.py index fa866640577..82ade7eb988 100644 --- a/sdk/python/feast/protos/feast/serving/ServingService_pb2.py +++ b/sdk/python/feast/protos/feast/serving/ServingService_pb2.py @@ -16,7 +16,7 @@ from feast.protos.feast.types import Value_pb2 as feast_dot_types_dot_Value__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"feast/serving/ServingService.proto\x12\rfeast.serving\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17\x66\x65\x61st/types/Value.proto\"\x1c\n\x1aGetFeastServingInfoRequest\".\n\x1bGetFeastServingInfoResponse\x12\x0f\n\x07version\x18\x01 \x01(\t\"E\n\x12\x46\x65\x61tureReferenceV2\x12\x19\n\x11\x66\x65\x61ture_view_name\x18\x01 \x01(\t\x12\x14\n\x0c\x66\x65\x61ture_name\x18\x02 \x01(\t\"\xfd\x02\n\x1aGetOnlineFeaturesRequestV2\x12\x33\n\x08\x66\x65\x61tures\x18\x04 \x03(\x0b\x32!.feast.serving.FeatureReferenceV2\x12H\n\x0b\x65ntity_rows\x18\x02 \x03(\x0b\x32\x33.feast.serving.GetOnlineFeaturesRequestV2.EntityRow\x12\x0f\n\x07project\x18\x05 \x01(\t\x1a\xce\x01\n\tEntityRow\x12-\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12O\n\x06\x66ields\x18\x02 \x03(\x0b\x32?.feast.serving.GetOnlineFeaturesRequestV2.EntityRow.FieldsEntry\x1a\x41\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.feast.types.Value:\x02\x38\x01\"\x1a\n\x0b\x46\x65\x61tureList\x12\x0b\n\x03val\x18\x01 \x03(\t\"\xc8\x03\n\x18GetOnlineFeaturesRequest\x12\x19\n\x0f\x66\x65\x61ture_service\x18\x01 \x01(\tH\x00\x12.\n\x08\x66\x65\x61tures\x18\x02 \x01(\x0b\x32\x1a.feast.serving.FeatureListH\x00\x12G\n\x08\x65ntities\x18\x03 \x03(\x0b\x32\x35.feast.serving.GetOnlineFeaturesRequest.EntitiesEntry\x12\x1a\n\x12\x66ull_feature_names\x18\x04 \x01(\x08\x12T\n\x0frequest_context\x18\x05 \x03(\x0b\x32;.feast.serving.GetOnlineFeaturesRequest.RequestContextEntry\x1aK\n\rEntitiesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12)\n\x05value\x18\x02 \x01(\x0b\x32\x1a.feast.types.RepeatedValue:\x02\x38\x01\x1aQ\n\x13RequestContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12)\n\x05value\x18\x02 \x01(\x0b\x32\x1a.feast.types.RepeatedValue:\x02\x38\x01\x42\x06\n\x04kind\"\xd2\x02\n\x19GetOnlineFeaturesResponse\x12\x42\n\x08metadata\x18\x01 \x01(\x0b\x32\x30.feast.serving.GetOnlineFeaturesResponseMetadata\x12G\n\x07results\x18\x02 \x03(\x0b\x32\x36.feast.serving.GetOnlineFeaturesResponse.FeatureVector\x12\x0e\n\x06status\x18\x03 \x01(\x08\x1a\x97\x01\n\rFeatureVector\x12\"\n\x06values\x18\x01 \x03(\x0b\x32\x12.feast.types.Value\x12,\n\x08statuses\x18\x02 \x03(\x0e\x32\x1a.feast.serving.FieldStatus\x12\x34\n\x10\x65vent_timestamps\x18\x03 \x03(\x0b\x32\x1a.google.protobuf.Timestamp\"V\n!GetOnlineFeaturesResponseMetadata\x12\x31\n\rfeature_names\x18\x01 \x01(\x0b\x32\x1a.feast.serving.FeatureList*[\n\x0b\x46ieldStatus\x12\x0b\n\x07INVALID\x10\x00\x12\x0b\n\x07PRESENT\x10\x01\x12\x0e\n\nNULL_VALUE\x10\x02\x12\r\n\tNOT_FOUND\x10\x03\x12\x13\n\x0fOUTSIDE_MAX_AGE\x10\x04\x32\xe6\x01\n\x0eServingService\x12l\n\x13GetFeastServingInfo\x12).feast.serving.GetFeastServingInfoRequest\x1a*.feast.serving.GetFeastServingInfoResponse\x12\x66\n\x11GetOnlineFeatures\x12\'.feast.serving.GetOnlineFeaturesRequest\x1a(.feast.serving.GetOnlineFeaturesResponseBZ\n\x13\x66\x65\x61st.proto.servingB\x0fServingAPIProtoZ2github.com/feast-dev/feast/go/protos/feast/servingb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"feast/serving/ServingService.proto\x12\rfeast.serving\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17\x66\x65\x61st/types/Value.proto\"\x1c\n\x1aGetFeastServingInfoRequest\".\n\x1bGetFeastServingInfoResponse\x12\x0f\n\x07version\x18\x01 \x01(\t\"E\n\x12\x46\x65\x61tureReferenceV2\x12\x19\n\x11\x66\x65\x61ture_view_name\x18\x01 \x01(\t\x12\x14\n\x0c\x66\x65\x61ture_name\x18\x02 \x01(\t\"\xfd\x02\n\x1aGetOnlineFeaturesRequestV2\x12\x33\n\x08\x66\x65\x61tures\x18\x04 \x03(\x0b\x32!.feast.serving.FeatureReferenceV2\x12H\n\x0b\x65ntity_rows\x18\x02 \x03(\x0b\x32\x33.feast.serving.GetOnlineFeaturesRequestV2.EntityRow\x12\x0f\n\x07project\x18\x05 \x01(\t\x1a\xce\x01\n\tEntityRow\x12-\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12O\n\x06\x66ields\x18\x02 \x03(\x0b\x32?.feast.serving.GetOnlineFeaturesRequestV2.EntityRow.FieldsEntry\x1a\x41\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.feast.types.Value:\x02\x38\x01\"\x1a\n\x0b\x46\x65\x61tureList\x12\x0b\n\x03val\x18\x01 \x03(\t\"\xf7\x03\n\x18GetOnlineFeaturesRequest\x12\x19\n\x0f\x66\x65\x61ture_service\x18\x01 \x01(\tH\x00\x12.\n\x08\x66\x65\x61tures\x18\x02 \x01(\x0b\x32\x1a.feast.serving.FeatureListH\x00\x12G\n\x08\x65ntities\x18\x03 \x03(\x0b\x32\x35.feast.serving.GetOnlineFeaturesRequest.EntitiesEntry\x12\x1a\n\x12\x66ull_feature_names\x18\x04 \x01(\x08\x12T\n\x0frequest_context\x18\x05 \x03(\x0b\x32;.feast.serving.GetOnlineFeaturesRequest.RequestContextEntry\x12-\n%include_feature_view_version_metadata\x18\x06 \x01(\x08\x1aK\n\rEntitiesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12)\n\x05value\x18\x02 \x01(\x0b\x32\x1a.feast.types.RepeatedValue:\x02\x38\x01\x1aQ\n\x13RequestContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12)\n\x05value\x18\x02 \x01(\x0b\x32\x1a.feast.types.RepeatedValue:\x02\x38\x01\x42\x06\n\x04kind\"\xd2\x02\n\x19GetOnlineFeaturesResponse\x12\x42\n\x08metadata\x18\x01 \x01(\x0b\x32\x30.feast.serving.GetOnlineFeaturesResponseMetadata\x12G\n\x07results\x18\x02 \x03(\x0b\x32\x36.feast.serving.GetOnlineFeaturesResponse.FeatureVector\x12\x0e\n\x06status\x18\x03 \x01(\x08\x1a\x97\x01\n\rFeatureVector\x12\"\n\x06values\x18\x01 \x03(\x0b\x32\x12.feast.types.Value\x12,\n\x08statuses\x18\x02 \x03(\x0e\x32\x1a.feast.serving.FieldStatus\x12\x34\n\x10\x65vent_timestamps\x18\x03 \x03(\x0b\x32\x1a.google.protobuf.Timestamp\"4\n\x13\x46\x65\x61tureViewMetadata\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\x05\"\x99\x01\n!GetOnlineFeaturesResponseMetadata\x12\x31\n\rfeature_names\x18\x01 \x01(\x0b\x32\x1a.feast.serving.FeatureList\x12\x41\n\x15\x66\x65\x61ture_view_metadata\x18\x02 \x03(\x0b\x32\".feast.serving.FeatureViewMetadata*[\n\x0b\x46ieldStatus\x12\x0b\n\x07INVALID\x10\x00\x12\x0b\n\x07PRESENT\x10\x01\x12\x0e\n\nNULL_VALUE\x10\x02\x12\r\n\tNOT_FOUND\x10\x03\x12\x13\n\x0fOUTSIDE_MAX_AGE\x10\x04\x32\xe6\x01\n\x0eServingService\x12l\n\x13GetFeastServingInfo\x12).feast.serving.GetFeastServingInfoRequest\x1a*.feast.serving.GetFeastServingInfoResponse\x12\x66\n\x11GetOnlineFeatures\x12\'.feast.serving.GetOnlineFeaturesRequest\x1a(.feast.serving.GetOnlineFeaturesResponseBZ\n\x13\x66\x65\x61st.proto.servingB\x0fServingAPIProtoZ2github.com/feast-dev/feast/go/protos/feast/servingb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -30,8 +30,8 @@ _globals['_GETONLINEFEATURESREQUEST_ENTITIESENTRY']._serialized_options = b'8\001' _globals['_GETONLINEFEATURESREQUEST_REQUESTCONTEXTENTRY']._options = None _globals['_GETONLINEFEATURESREQUEST_REQUESTCONTEXTENTRY']._serialized_options = b'8\001' - _globals['_FIELDSTATUS']._serialized_start=1560 - _globals['_FIELDSTATUS']._serialized_end=1651 + _globals['_FIELDSTATUS']._serialized_start=1729 + _globals['_FIELDSTATUS']._serialized_end=1820 _globals['_GETFEASTSERVINGINFOREQUEST']._serialized_start=111 _globals['_GETFEASTSERVINGINFOREQUEST']._serialized_end=139 _globals['_GETFEASTSERVINGINFORESPONSE']._serialized_start=141 @@ -47,17 +47,19 @@ _globals['_FEATURELIST']._serialized_start=644 _globals['_FEATURELIST']._serialized_end=670 _globals['_GETONLINEFEATURESREQUEST']._serialized_start=673 - _globals['_GETONLINEFEATURESREQUEST']._serialized_end=1129 - _globals['_GETONLINEFEATURESREQUEST_ENTITIESENTRY']._serialized_start=963 - _globals['_GETONLINEFEATURESREQUEST_ENTITIESENTRY']._serialized_end=1038 - _globals['_GETONLINEFEATURESREQUEST_REQUESTCONTEXTENTRY']._serialized_start=1040 - _globals['_GETONLINEFEATURESREQUEST_REQUESTCONTEXTENTRY']._serialized_end=1121 - _globals['_GETONLINEFEATURESRESPONSE']._serialized_start=1132 - _globals['_GETONLINEFEATURESRESPONSE']._serialized_end=1470 - _globals['_GETONLINEFEATURESRESPONSE_FEATUREVECTOR']._serialized_start=1319 - _globals['_GETONLINEFEATURESRESPONSE_FEATUREVECTOR']._serialized_end=1470 - _globals['_GETONLINEFEATURESRESPONSEMETADATA']._serialized_start=1472 - _globals['_GETONLINEFEATURESRESPONSEMETADATA']._serialized_end=1558 - _globals['_SERVINGSERVICE']._serialized_start=1654 - _globals['_SERVINGSERVICE']._serialized_end=1884 + _globals['_GETONLINEFEATURESREQUEST']._serialized_end=1176 + _globals['_GETONLINEFEATURESREQUEST_ENTITIESENTRY']._serialized_start=1010 + _globals['_GETONLINEFEATURESREQUEST_ENTITIESENTRY']._serialized_end=1085 + _globals['_GETONLINEFEATURESREQUEST_REQUESTCONTEXTENTRY']._serialized_start=1087 + _globals['_GETONLINEFEATURESREQUEST_REQUESTCONTEXTENTRY']._serialized_end=1168 + _globals['_GETONLINEFEATURESRESPONSE']._serialized_start=1179 + _globals['_GETONLINEFEATURESRESPONSE']._serialized_end=1517 + _globals['_GETONLINEFEATURESRESPONSE_FEATUREVECTOR']._serialized_start=1366 + _globals['_GETONLINEFEATURESRESPONSE_FEATUREVECTOR']._serialized_end=1517 + _globals['_FEATUREVIEWMETADATA']._serialized_start=1519 + _globals['_FEATUREVIEWMETADATA']._serialized_end=1571 + _globals['_GETONLINEFEATURESRESPONSEMETADATA']._serialized_start=1574 + _globals['_GETONLINEFEATURESRESPONSEMETADATA']._serialized_end=1727 + _globals['_SERVINGSERVICE']._serialized_start=1823 + _globals['_SERVINGSERVICE']._serialized_end=2053 # @@protoc_insertion_point(module_scope) diff --git a/sdk/python/feast/protos/feast/serving/ServingService_pb2.pyi b/sdk/python/feast/protos/feast/serving/ServingService_pb2.pyi index 3c5e57ae45a..1804ce0428e 100644 --- a/sdk/python/feast/protos/feast/serving/ServingService_pb2.pyi +++ b/sdk/python/feast/protos/feast/serving/ServingService_pb2.pyi @@ -253,6 +253,7 @@ class GetOnlineFeaturesRequest(google.protobuf.message.Message): ENTITIES_FIELD_NUMBER: builtins.int FULL_FEATURE_NAMES_FIELD_NUMBER: builtins.int REQUEST_CONTEXT_FIELD_NUMBER: builtins.int + INCLUDE_FEATURE_VIEW_VERSION_METADATA_FIELD_NUMBER: builtins.int feature_service: builtins.str @property def features(self) -> global___FeatureList: ... @@ -268,6 +269,8 @@ class GetOnlineFeaturesRequest(google.protobuf.message.Message): (was moved to dedicated parameter to avoid unnecessary separation logic on serving side) A map of variable name -> list of values """ + include_feature_view_version_metadata: builtins.bool + """Whether to include feature view version metadata in the response""" def __init__( self, *, @@ -276,9 +279,10 @@ class GetOnlineFeaturesRequest(google.protobuf.message.Message): entities: collections.abc.Mapping[builtins.str, feast.types.Value_pb2.RepeatedValue] | None = ..., full_feature_names: builtins.bool = ..., request_context: collections.abc.Mapping[builtins.str, feast.types.Value_pb2.RepeatedValue] | None = ..., + include_feature_view_version_metadata: builtins.bool = ..., ) -> None: ... def HasField(self, field_name: typing_extensions.Literal["feature_service", b"feature_service", "features", b"features", "kind", b"kind"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["entities", b"entities", "feature_service", b"feature_service", "features", b"features", "full_feature_names", b"full_feature_names", "kind", b"kind", "request_context", b"request_context"]) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["entities", b"entities", "feature_service", b"feature_service", "features", b"features", "full_feature_names", b"full_feature_names", "include_feature_view_version_metadata", b"include_feature_view_version_metadata", "kind", b"kind", "request_context", b"request_context"]) -> None: ... def WhichOneof(self, oneof_group: typing_extensions.Literal["kind", b"kind"]) -> typing_extensions.Literal["feature_service", "features"] | None: ... global___GetOnlineFeaturesRequest = GetOnlineFeaturesRequest @@ -330,18 +334,43 @@ class GetOnlineFeaturesResponse(google.protobuf.message.Message): global___GetOnlineFeaturesResponse = GetOnlineFeaturesResponse +class FeatureViewMetadata(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAME_FIELD_NUMBER: builtins.int + VERSION_FIELD_NUMBER: builtins.int + name: builtins.str + """Feature view name (e.g., "driver_stats")""" + version: builtins.int + """Version number (e.g., 2)""" + def __init__( + self, + *, + name: builtins.str = ..., + version: builtins.int = ..., + ) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["name", b"name", "version", b"version"]) -> None: ... + +global___FeatureViewMetadata = FeatureViewMetadata + class GetOnlineFeaturesResponseMetadata(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor FEATURE_NAMES_FIELD_NUMBER: builtins.int + FEATURE_VIEW_METADATA_FIELD_NUMBER: builtins.int + @property + def feature_names(self) -> global___FeatureList: + """Clean feature names without @v2 syntax""" @property - def feature_names(self) -> global___FeatureList: ... + def feature_view_metadata(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___FeatureViewMetadata]: + """Only populated when requested""" def __init__( self, *, feature_names: global___FeatureList | None = ..., + feature_view_metadata: collections.abc.Iterable[global___FeatureViewMetadata] | None = ..., ) -> None: ... def HasField(self, field_name: typing_extensions.Literal["feature_names", b"feature_names"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["feature_names", b"feature_names"]) -> None: ... + def ClearField(self, field_name: typing_extensions.Literal["feature_names", b"feature_names", "feature_view_metadata", b"feature_view_metadata"]) -> None: ... global___GetOnlineFeaturesResponseMetadata = GetOnlineFeaturesResponseMetadata diff --git a/sdk/python/feast/protos/feast/types/Value_pb2.py b/sdk/python/feast/protos/feast/types/Value_pb2.py index 2ab1d2cc8fb..3f6e55d3005 100644 --- a/sdk/python/feast/protos/feast/types/Value_pb2.py +++ b/sdk/python/feast/protos/feast/types/Value_pb2.py @@ -14,7 +14,7 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17\x66\x65\x61st/types/Value.proto\x12\x0b\x66\x65\x61st.types\"\xb0\x03\n\tValueType\"\xa2\x03\n\x04\x45num\x12\x0b\n\x07INVALID\x10\x00\x12\t\n\x05\x42YTES\x10\x01\x12\n\n\x06STRING\x10\x02\x12\t\n\x05INT32\x10\x03\x12\t\n\x05INT64\x10\x04\x12\n\n\x06\x44OUBLE\x10\x05\x12\t\n\x05\x46LOAT\x10\x06\x12\x08\n\x04\x42OOL\x10\x07\x12\x12\n\x0eUNIX_TIMESTAMP\x10\x08\x12\x0e\n\nBYTES_LIST\x10\x0b\x12\x0f\n\x0bSTRING_LIST\x10\x0c\x12\x0e\n\nINT32_LIST\x10\r\x12\x0e\n\nINT64_LIST\x10\x0e\x12\x0f\n\x0b\x44OUBLE_LIST\x10\x0f\x12\x0e\n\nFLOAT_LIST\x10\x10\x12\r\n\tBOOL_LIST\x10\x11\x12\x17\n\x13UNIX_TIMESTAMP_LIST\x10\x12\x12\x08\n\x04NULL\x10\x13\x12\x07\n\x03MAP\x10\x14\x12\x0c\n\x08MAP_LIST\x10\x15\x12\r\n\tBYTES_SET\x10\x16\x12\x0e\n\nSTRING_SET\x10\x17\x12\r\n\tINT32_SET\x10\x18\x12\r\n\tINT64_SET\x10\x19\x12\x0e\n\nDOUBLE_SET\x10\x1a\x12\r\n\tFLOAT_SET\x10\x1b\x12\x0c\n\x08\x42OOL_SET\x10\x1c\x12\x16\n\x12UNIX_TIMESTAMP_SET\x10\x1d\"\xe0\x08\n\x05Value\x12\x13\n\tbytes_val\x18\x01 \x01(\x0cH\x00\x12\x14\n\nstring_val\x18\x02 \x01(\tH\x00\x12\x13\n\tint32_val\x18\x03 \x01(\x05H\x00\x12\x13\n\tint64_val\x18\x04 \x01(\x03H\x00\x12\x14\n\ndouble_val\x18\x05 \x01(\x01H\x00\x12\x13\n\tfloat_val\x18\x06 \x01(\x02H\x00\x12\x12\n\x08\x62ool_val\x18\x07 \x01(\x08H\x00\x12\x1c\n\x12unix_timestamp_val\x18\x08 \x01(\x03H\x00\x12\x30\n\x0e\x62ytes_list_val\x18\x0b \x01(\x0b\x32\x16.feast.types.BytesListH\x00\x12\x32\n\x0fstring_list_val\x18\x0c \x01(\x0b\x32\x17.feast.types.StringListH\x00\x12\x30\n\x0eint32_list_val\x18\r \x01(\x0b\x32\x16.feast.types.Int32ListH\x00\x12\x30\n\x0eint64_list_val\x18\x0e \x01(\x0b\x32\x16.feast.types.Int64ListH\x00\x12\x32\n\x0f\x64ouble_list_val\x18\x0f \x01(\x0b\x32\x17.feast.types.DoubleListH\x00\x12\x30\n\x0e\x66loat_list_val\x18\x10 \x01(\x0b\x32\x16.feast.types.FloatListH\x00\x12.\n\rbool_list_val\x18\x11 \x01(\x0b\x32\x15.feast.types.BoolListH\x00\x12\x39\n\x17unix_timestamp_list_val\x18\x12 \x01(\x0b\x32\x16.feast.types.Int64ListH\x00\x12%\n\x08null_val\x18\x13 \x01(\x0e\x32\x11.feast.types.NullH\x00\x12#\n\x07map_val\x18\x14 \x01(\x0b\x32\x10.feast.types.MapH\x00\x12,\n\x0cmap_list_val\x18\x15 \x01(\x0b\x32\x14.feast.types.MapListH\x00\x12.\n\rbytes_set_val\x18\x16 \x01(\x0b\x32\x15.feast.types.BytesSetH\x00\x12\x30\n\x0estring_set_val\x18\x17 \x01(\x0b\x32\x16.feast.types.StringSetH\x00\x12.\n\rint32_set_val\x18\x18 \x01(\x0b\x32\x15.feast.types.Int32SetH\x00\x12.\n\rint64_set_val\x18\x19 \x01(\x0b\x32\x15.feast.types.Int64SetH\x00\x12\x30\n\x0e\x64ouble_set_val\x18\x1a \x01(\x0b\x32\x16.feast.types.DoubleSetH\x00\x12.\n\rfloat_set_val\x18\x1b \x01(\x0b\x32\x15.feast.types.FloatSetH\x00\x12,\n\x0c\x62ool_set_val\x18\x1c \x01(\x0b\x32\x14.feast.types.BoolSetH\x00\x12\x37\n\x16unix_timestamp_set_val\x18\x1d \x01(\x0b\x32\x15.feast.types.Int64SetH\x00\x42\x05\n\x03val\"\x18\n\tBytesList\x12\x0b\n\x03val\x18\x01 \x03(\x0c\"\x19\n\nStringList\x12\x0b\n\x03val\x18\x01 \x03(\t\"\x18\n\tInt32List\x12\x0b\n\x03val\x18\x01 \x03(\x05\"\x18\n\tInt64List\x12\x0b\n\x03val\x18\x01 \x03(\x03\"\x19\n\nDoubleList\x12\x0b\n\x03val\x18\x01 \x03(\x01\"\x18\n\tFloatList\x12\x0b\n\x03val\x18\x01 \x03(\x02\"\x17\n\x08\x42oolList\x12\x0b\n\x03val\x18\x01 \x03(\x08\"\x17\n\x08\x42ytesSet\x12\x0b\n\x03val\x18\x01 \x03(\x0c\"\x18\n\tStringSet\x12\x0b\n\x03val\x18\x01 \x03(\t\"\x17\n\x08Int32Set\x12\x0b\n\x03val\x18\x01 \x03(\x05\"\x17\n\x08Int64Set\x12\x0b\n\x03val\x18\x01 \x03(\x03\"\x18\n\tDoubleSet\x12\x0b\n\x03val\x18\x01 \x03(\x01\"\x17\n\x08\x46loatSet\x12\x0b\n\x03val\x18\x01 \x03(\x02\"\x16\n\x07\x42oolSet\x12\x0b\n\x03val\x18\x01 \x03(\x08\"m\n\x03Map\x12&\n\x03val\x18\x01 \x03(\x0b\x32\x19.feast.types.Map.ValEntry\x1a>\n\x08ValEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.feast.types.Value:\x02\x38\x01\"(\n\x07MapList\x12\x1d\n\x03val\x18\x01 \x03(\x0b\x32\x10.feast.types.Map\"0\n\rRepeatedValue\x12\x1f\n\x03val\x18\x01 \x03(\x0b\x32\x12.feast.types.Value*\x10\n\x04Null\x12\x08\n\x04NULL\x10\x00\x42Q\n\x11\x66\x65\x61st.proto.typesB\nValueProtoZ0github.com/feast-dev/feast/go/protos/feast/typesb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17\x66\x65\x61st/types/Value.proto\x12\x0b\x66\x65\x61st.types\"\x92\x05\n\tValueType\"\x84\x05\n\x04\x45num\x12\x0b\n\x07INVALID\x10\x00\x12\t\n\x05\x42YTES\x10\x01\x12\n\n\x06STRING\x10\x02\x12\t\n\x05INT32\x10\x03\x12\t\n\x05INT64\x10\x04\x12\n\n\x06\x44OUBLE\x10\x05\x12\t\n\x05\x46LOAT\x10\x06\x12\x08\n\x04\x42OOL\x10\x07\x12\x12\n\x0eUNIX_TIMESTAMP\x10\x08\x12\x0e\n\nBYTES_LIST\x10\x0b\x12\x0f\n\x0bSTRING_LIST\x10\x0c\x12\x0e\n\nINT32_LIST\x10\r\x12\x0e\n\nINT64_LIST\x10\x0e\x12\x0f\n\x0b\x44OUBLE_LIST\x10\x0f\x12\x0e\n\nFLOAT_LIST\x10\x10\x12\r\n\tBOOL_LIST\x10\x11\x12\x17\n\x13UNIX_TIMESTAMP_LIST\x10\x12\x12\x08\n\x04NULL\x10\x13\x12\x07\n\x03MAP\x10\x14\x12\x0c\n\x08MAP_LIST\x10\x15\x12\r\n\tBYTES_SET\x10\x16\x12\x0e\n\nSTRING_SET\x10\x17\x12\r\n\tINT32_SET\x10\x18\x12\r\n\tINT64_SET\x10\x19\x12\x0e\n\nDOUBLE_SET\x10\x1a\x12\r\n\tFLOAT_SET\x10\x1b\x12\x0c\n\x08\x42OOL_SET\x10\x1c\x12\x16\n\x12UNIX_TIMESTAMP_SET\x10\x1d\x12\x08\n\x04JSON\x10 \x12\r\n\tJSON_LIST\x10!\x12\n\n\x06STRUCT\x10\"\x12\x0f\n\x0bSTRUCT_LIST\x10#\x12\x08\n\x04UUID\x10$\x12\r\n\tTIME_UUID\x10%\x12\r\n\tUUID_LIST\x10&\x12\x12\n\x0eTIME_UUID_LIST\x10\'\x12\x0c\n\x08UUID_SET\x10(\x12\x11\n\rTIME_UUID_SET\x10)\x12\x0e\n\nVALUE_LIST\x10*\x12\r\n\tVALUE_SET\x10+\x12\x0b\n\x07\x44\x45\x43IMAL\x10,\x12\x10\n\x0c\x44\x45\x43IMAL_LIST\x10-\x12\x0f\n\x0b\x44\x45\x43IMAL_SET\x10.\"\xd8\r\n\x05Value\x12\x13\n\tbytes_val\x18\x01 \x01(\x0cH\x00\x12\x14\n\nstring_val\x18\x02 \x01(\tH\x00\x12\x13\n\tint32_val\x18\x03 \x01(\x05H\x00\x12\x13\n\tint64_val\x18\x04 \x01(\x03H\x00\x12\x14\n\ndouble_val\x18\x05 \x01(\x01H\x00\x12\x13\n\tfloat_val\x18\x06 \x01(\x02H\x00\x12\x12\n\x08\x62ool_val\x18\x07 \x01(\x08H\x00\x12\x1c\n\x12unix_timestamp_val\x18\x08 \x01(\x03H\x00\x12\x30\n\x0e\x62ytes_list_val\x18\x0b \x01(\x0b\x32\x16.feast.types.BytesListH\x00\x12\x32\n\x0fstring_list_val\x18\x0c \x01(\x0b\x32\x17.feast.types.StringListH\x00\x12\x30\n\x0eint32_list_val\x18\r \x01(\x0b\x32\x16.feast.types.Int32ListH\x00\x12\x30\n\x0eint64_list_val\x18\x0e \x01(\x0b\x32\x16.feast.types.Int64ListH\x00\x12\x32\n\x0f\x64ouble_list_val\x18\x0f \x01(\x0b\x32\x17.feast.types.DoubleListH\x00\x12\x30\n\x0e\x66loat_list_val\x18\x10 \x01(\x0b\x32\x16.feast.types.FloatListH\x00\x12.\n\rbool_list_val\x18\x11 \x01(\x0b\x32\x15.feast.types.BoolListH\x00\x12\x39\n\x17unix_timestamp_list_val\x18\x12 \x01(\x0b\x32\x16.feast.types.Int64ListH\x00\x12%\n\x08null_val\x18\x13 \x01(\x0e\x32\x11.feast.types.NullH\x00\x12#\n\x07map_val\x18\x14 \x01(\x0b\x32\x10.feast.types.MapH\x00\x12,\n\x0cmap_list_val\x18\x15 \x01(\x0b\x32\x14.feast.types.MapListH\x00\x12.\n\rbytes_set_val\x18\x16 \x01(\x0b\x32\x15.feast.types.BytesSetH\x00\x12\x30\n\x0estring_set_val\x18\x17 \x01(\x0b\x32\x16.feast.types.StringSetH\x00\x12.\n\rint32_set_val\x18\x18 \x01(\x0b\x32\x15.feast.types.Int32SetH\x00\x12.\n\rint64_set_val\x18\x19 \x01(\x0b\x32\x15.feast.types.Int64SetH\x00\x12\x30\n\x0e\x64ouble_set_val\x18\x1a \x01(\x0b\x32\x16.feast.types.DoubleSetH\x00\x12.\n\rfloat_set_val\x18\x1b \x01(\x0b\x32\x15.feast.types.FloatSetH\x00\x12,\n\x0c\x62ool_set_val\x18\x1c \x01(\x0b\x32\x14.feast.types.BoolSetH\x00\x12\x37\n\x16unix_timestamp_set_val\x18\x1d \x01(\x0b\x32\x15.feast.types.Int64SetH\x00\x12\x12\n\x08json_val\x18 \x01(\tH\x00\x12\x30\n\rjson_list_val\x18! \x01(\x0b\x32\x17.feast.types.StringListH\x00\x12&\n\nstruct_val\x18\" \x01(\x0b\x32\x10.feast.types.MapH\x00\x12/\n\x0fstruct_list_val\x18# \x01(\x0b\x32\x14.feast.types.MapListH\x00\x12\x12\n\x08uuid_val\x18$ \x01(\tH\x00\x12\x17\n\rtime_uuid_val\x18% \x01(\tH\x00\x12\x30\n\ruuid_list_val\x18& \x01(\x0b\x32\x17.feast.types.StringListH\x00\x12\x35\n\x12time_uuid_list_val\x18\' \x01(\x0b\x32\x17.feast.types.StringListH\x00\x12.\n\x0cuuid_set_val\x18( \x01(\x0b\x32\x16.feast.types.StringSetH\x00\x12\x33\n\x11time_uuid_set_val\x18) \x01(\x0b\x32\x16.feast.types.StringSetH\x00\x12.\n\x08list_val\x18* \x01(\x0b\x32\x1a.feast.types.RepeatedValueH\x00\x12-\n\x07set_val\x18+ \x01(\x0b\x32\x1a.feast.types.RepeatedValueH\x00\x12\x15\n\x0b\x64\x65\x63imal_val\x18, \x01(\tH\x00\x12\x33\n\x10\x64\x65\x63imal_list_val\x18- \x01(\x0b\x32\x17.feast.types.StringListH\x00\x12\x31\n\x0f\x64\x65\x63imal_set_val\x18. \x01(\x0b\x32\x16.feast.types.StringSetH\x00\x42\x05\n\x03val\"\x18\n\tBytesList\x12\x0b\n\x03val\x18\x01 \x03(\x0c\"\x19\n\nStringList\x12\x0b\n\x03val\x18\x01 \x03(\t\"\x18\n\tInt32List\x12\x0b\n\x03val\x18\x01 \x03(\x05\"\x18\n\tInt64List\x12\x0b\n\x03val\x18\x01 \x03(\x03\"\x19\n\nDoubleList\x12\x0b\n\x03val\x18\x01 \x03(\x01\"\x18\n\tFloatList\x12\x0b\n\x03val\x18\x01 \x03(\x02\"\x17\n\x08\x42oolList\x12\x0b\n\x03val\x18\x01 \x03(\x08\"\x17\n\x08\x42ytesSet\x12\x0b\n\x03val\x18\x01 \x03(\x0c\"\x18\n\tStringSet\x12\x0b\n\x03val\x18\x01 \x03(\t\"\x17\n\x08Int32Set\x12\x0b\n\x03val\x18\x01 \x03(\x05\"\x17\n\x08Int64Set\x12\x0b\n\x03val\x18\x01 \x03(\x03\"\x18\n\tDoubleSet\x12\x0b\n\x03val\x18\x01 \x03(\x01\"\x17\n\x08\x46loatSet\x12\x0b\n\x03val\x18\x01 \x03(\x02\"\x16\n\x07\x42oolSet\x12\x0b\n\x03val\x18\x01 \x03(\x08\"m\n\x03Map\x12&\n\x03val\x18\x01 \x03(\x0b\x32\x19.feast.types.Map.ValEntry\x1a>\n\x08ValEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.feast.types.Value:\x02\x38\x01\"(\n\x07MapList\x12\x1d\n\x03val\x18\x01 \x03(\x0b\x32\x10.feast.types.Map\"0\n\rRepeatedValue\x12\x1f\n\x03val\x18\x01 \x03(\x0b\x32\x12.feast.types.Value*\x10\n\x04Null\x12\x08\n\x04NULL\x10\x00\x42Q\n\x11\x66\x65\x61st.proto.typesB\nValueProtoZ0github.com/feast-dev/feast/go/protos/feast/typesb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -24,48 +24,48 @@ _globals['DESCRIPTOR']._serialized_options = b'\n\021feast.proto.typesB\nValueProtoZ0github.com/feast-dev/feast/go/protos/feast/types' _globals['_MAP_VALENTRY']._options = None _globals['_MAP_VALENTRY']._serialized_options = b'8\001' - _globals['_NULL']._serialized_start=2160 - _globals['_NULL']._serialized_end=2176 + _globals['_NULL']._serialized_start=3018 + _globals['_NULL']._serialized_end=3034 _globals['_VALUETYPE']._serialized_start=41 - _globals['_VALUETYPE']._serialized_end=473 + _globals['_VALUETYPE']._serialized_end=699 _globals['_VALUETYPE_ENUM']._serialized_start=55 - _globals['_VALUETYPE_ENUM']._serialized_end=473 - _globals['_VALUE']._serialized_start=476 - _globals['_VALUE']._serialized_end=1596 - _globals['_BYTESLIST']._serialized_start=1598 - _globals['_BYTESLIST']._serialized_end=1622 - _globals['_STRINGLIST']._serialized_start=1624 - _globals['_STRINGLIST']._serialized_end=1649 - _globals['_INT32LIST']._serialized_start=1651 - _globals['_INT32LIST']._serialized_end=1675 - _globals['_INT64LIST']._serialized_start=1677 - _globals['_INT64LIST']._serialized_end=1701 - _globals['_DOUBLELIST']._serialized_start=1703 - _globals['_DOUBLELIST']._serialized_end=1728 - _globals['_FLOATLIST']._serialized_start=1730 - _globals['_FLOATLIST']._serialized_end=1754 - _globals['_BOOLLIST']._serialized_start=1756 - _globals['_BOOLLIST']._serialized_end=1779 - _globals['_BYTESSET']._serialized_start=1781 - _globals['_BYTESSET']._serialized_end=1804 - _globals['_STRINGSET']._serialized_start=1806 - _globals['_STRINGSET']._serialized_end=1830 - _globals['_INT32SET']._serialized_start=1832 - _globals['_INT32SET']._serialized_end=1855 - _globals['_INT64SET']._serialized_start=1857 - _globals['_INT64SET']._serialized_end=1880 - _globals['_DOUBLESET']._serialized_start=1882 - _globals['_DOUBLESET']._serialized_end=1906 - _globals['_FLOATSET']._serialized_start=1908 - _globals['_FLOATSET']._serialized_end=1931 - _globals['_BOOLSET']._serialized_start=1933 - _globals['_BOOLSET']._serialized_end=1955 - _globals['_MAP']._serialized_start=1957 - _globals['_MAP']._serialized_end=2066 - _globals['_MAP_VALENTRY']._serialized_start=2004 - _globals['_MAP_VALENTRY']._serialized_end=2066 - _globals['_MAPLIST']._serialized_start=2068 - _globals['_MAPLIST']._serialized_end=2108 - _globals['_REPEATEDVALUE']._serialized_start=2110 - _globals['_REPEATEDVALUE']._serialized_end=2158 + _globals['_VALUETYPE_ENUM']._serialized_end=699 + _globals['_VALUE']._serialized_start=702 + _globals['_VALUE']._serialized_end=2454 + _globals['_BYTESLIST']._serialized_start=2456 + _globals['_BYTESLIST']._serialized_end=2480 + _globals['_STRINGLIST']._serialized_start=2482 + _globals['_STRINGLIST']._serialized_end=2507 + _globals['_INT32LIST']._serialized_start=2509 + _globals['_INT32LIST']._serialized_end=2533 + _globals['_INT64LIST']._serialized_start=2535 + _globals['_INT64LIST']._serialized_end=2559 + _globals['_DOUBLELIST']._serialized_start=2561 + _globals['_DOUBLELIST']._serialized_end=2586 + _globals['_FLOATLIST']._serialized_start=2588 + _globals['_FLOATLIST']._serialized_end=2612 + _globals['_BOOLLIST']._serialized_start=2614 + _globals['_BOOLLIST']._serialized_end=2637 + _globals['_BYTESSET']._serialized_start=2639 + _globals['_BYTESSET']._serialized_end=2662 + _globals['_STRINGSET']._serialized_start=2664 + _globals['_STRINGSET']._serialized_end=2688 + _globals['_INT32SET']._serialized_start=2690 + _globals['_INT32SET']._serialized_end=2713 + _globals['_INT64SET']._serialized_start=2715 + _globals['_INT64SET']._serialized_end=2738 + _globals['_DOUBLESET']._serialized_start=2740 + _globals['_DOUBLESET']._serialized_end=2764 + _globals['_FLOATSET']._serialized_start=2766 + _globals['_FLOATSET']._serialized_end=2789 + _globals['_BOOLSET']._serialized_start=2791 + _globals['_BOOLSET']._serialized_end=2813 + _globals['_MAP']._serialized_start=2815 + _globals['_MAP']._serialized_end=2924 + _globals['_MAP_VALENTRY']._serialized_start=2862 + _globals['_MAP_VALENTRY']._serialized_end=2924 + _globals['_MAPLIST']._serialized_start=2926 + _globals['_MAPLIST']._serialized_end=2966 + _globals['_REPEATEDVALUE']._serialized_start=2968 + _globals['_REPEATEDVALUE']._serialized_end=3016 # @@protoc_insertion_point(module_scope) diff --git a/sdk/python/feast/protos/feast/types/Value_pb2.pyi b/sdk/python/feast/protos/feast/types/Value_pb2.pyi index 0e10849ebad..c0b7bada7bb 100644 --- a/sdk/python/feast/protos/feast/types/Value_pb2.pyi +++ b/sdk/python/feast/protos/feast/types/Value_pb2.pyi @@ -16,44 +16,46 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ -import builtins -import collections.abc -import google.protobuf.descriptor -import google.protobuf.internal.containers -import google.protobuf.internal.enum_type_wrapper -import google.protobuf.message + +from collections import abc as _abc +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +import builtins as _builtins import sys -import typing +import typing as _typing if sys.version_info >= (3, 10): - import typing as typing_extensions + from typing import TypeAlias as _TypeAlias else: - import typing_extensions + from typing_extensions import TypeAlias as _TypeAlias -DESCRIPTOR: google.protobuf.descriptor.FileDescriptor +DESCRIPTOR: _descriptor.FileDescriptor class _Null: - ValueType = typing.NewType("ValueType", builtins.int) - V: typing_extensions.TypeAlias = ValueType + ValueType = _typing.NewType("ValueType", _builtins.int) + V: _TypeAlias = ValueType # noqa: Y015 -class _NullEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_Null.ValueType], builtins.type): # noqa: F821 - DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor +class _NullEnumTypeWrapper(_enum_type_wrapper._EnumTypeWrapper[_Null.ValueType], _builtins.type): + DESCRIPTOR: _descriptor.EnumDescriptor NULL: _Null.ValueType # 0 class Null(_Null, metaclass=_NullEnumTypeWrapper): ... NULL: Null.ValueType # 0 -global___Null = Null +Global___Null: _TypeAlias = Null # noqa: Y015 -class ValueType(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class ValueType(_message.Message): + DESCRIPTOR: _descriptor.Descriptor class _Enum: - ValueType = typing.NewType("ValueType", builtins.int) - V: typing_extensions.TypeAlias = ValueType + ValueType = _typing.NewType("ValueType", _builtins.int) + V: _TypeAlias = ValueType # noqa: Y015 - class _EnumEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ValueType._Enum.ValueType], builtins.type): # noqa: F821 - DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + class _EnumEnumTypeWrapper(_enum_type_wrapper._EnumTypeWrapper[ValueType._Enum.ValueType], _builtins.type): + DESCRIPTOR: _descriptor.EnumDescriptor INVALID: ValueType._Enum.ValueType # 0 BYTES: ValueType._Enum.ValueType # 1 STRING: ValueType._Enum.ValueType # 2 @@ -82,6 +84,21 @@ class ValueType(google.protobuf.message.Message): FLOAT_SET: ValueType._Enum.ValueType # 27 BOOL_SET: ValueType._Enum.ValueType # 28 UNIX_TIMESTAMP_SET: ValueType._Enum.ValueType # 29 + JSON: ValueType._Enum.ValueType # 32 + JSON_LIST: ValueType._Enum.ValueType # 33 + STRUCT: ValueType._Enum.ValueType # 34 + STRUCT_LIST: ValueType._Enum.ValueType # 35 + UUID: ValueType._Enum.ValueType # 36 + TIME_UUID: ValueType._Enum.ValueType # 37 + UUID_LIST: ValueType._Enum.ValueType # 38 + TIME_UUID_LIST: ValueType._Enum.ValueType # 39 + UUID_SET: ValueType._Enum.ValueType # 40 + TIME_UUID_SET: ValueType._Enum.ValueType # 41 + VALUE_LIST: ValueType._Enum.ValueType # 42 + VALUE_SET: ValueType._Enum.ValueType # 43 + DECIMAL: ValueType._Enum.ValueType # 44 + DECIMAL_LIST: ValueType._Enum.ValueType # 45 + DECIMAL_SET: ValueType._Enum.ValueType # 46 class Enum(_Enum, metaclass=_EnumEnumTypeWrapper): ... INVALID: ValueType.Enum.ValueType # 0 @@ -112,397 +129,510 @@ class ValueType(google.protobuf.message.Message): FLOAT_SET: ValueType.Enum.ValueType # 27 BOOL_SET: ValueType.Enum.ValueType # 28 UNIX_TIMESTAMP_SET: ValueType.Enum.ValueType # 29 + JSON: ValueType.Enum.ValueType # 32 + JSON_LIST: ValueType.Enum.ValueType # 33 + STRUCT: ValueType.Enum.ValueType # 34 + STRUCT_LIST: ValueType.Enum.ValueType # 35 + UUID: ValueType.Enum.ValueType # 36 + TIME_UUID: ValueType.Enum.ValueType # 37 + UUID_LIST: ValueType.Enum.ValueType # 38 + TIME_UUID_LIST: ValueType.Enum.ValueType # 39 + UUID_SET: ValueType.Enum.ValueType # 40 + TIME_UUID_SET: ValueType.Enum.ValueType # 41 + VALUE_LIST: ValueType.Enum.ValueType # 42 + VALUE_SET: ValueType.Enum.ValueType # 43 + DECIMAL: ValueType.Enum.ValueType # 44 + DECIMAL_LIST: ValueType.Enum.ValueType # 45 + DECIMAL_SET: ValueType.Enum.ValueType # 46 def __init__( self, ) -> None: ... -global___ValueType = ValueType - -class Value(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor - - BYTES_VAL_FIELD_NUMBER: builtins.int - STRING_VAL_FIELD_NUMBER: builtins.int - INT32_VAL_FIELD_NUMBER: builtins.int - INT64_VAL_FIELD_NUMBER: builtins.int - DOUBLE_VAL_FIELD_NUMBER: builtins.int - FLOAT_VAL_FIELD_NUMBER: builtins.int - BOOL_VAL_FIELD_NUMBER: builtins.int - UNIX_TIMESTAMP_VAL_FIELD_NUMBER: builtins.int - BYTES_LIST_VAL_FIELD_NUMBER: builtins.int - STRING_LIST_VAL_FIELD_NUMBER: builtins.int - INT32_LIST_VAL_FIELD_NUMBER: builtins.int - INT64_LIST_VAL_FIELD_NUMBER: builtins.int - DOUBLE_LIST_VAL_FIELD_NUMBER: builtins.int - FLOAT_LIST_VAL_FIELD_NUMBER: builtins.int - BOOL_LIST_VAL_FIELD_NUMBER: builtins.int - UNIX_TIMESTAMP_LIST_VAL_FIELD_NUMBER: builtins.int - NULL_VAL_FIELD_NUMBER: builtins.int - MAP_VAL_FIELD_NUMBER: builtins.int - MAP_LIST_VAL_FIELD_NUMBER: builtins.int - BYTES_SET_VAL_FIELD_NUMBER: builtins.int - STRING_SET_VAL_FIELD_NUMBER: builtins.int - INT32_SET_VAL_FIELD_NUMBER: builtins.int - INT64_SET_VAL_FIELD_NUMBER: builtins.int - DOUBLE_SET_VAL_FIELD_NUMBER: builtins.int - FLOAT_SET_VAL_FIELD_NUMBER: builtins.int - BOOL_SET_VAL_FIELD_NUMBER: builtins.int - UNIX_TIMESTAMP_SET_VAL_FIELD_NUMBER: builtins.int - bytes_val: builtins.bytes - string_val: builtins.str - int32_val: builtins.int - int64_val: builtins.int - double_val: builtins.float - float_val: builtins.float - bool_val: builtins.bool - unix_timestamp_val: builtins.int - @property - def bytes_list_val(self) -> global___BytesList: ... - @property - def string_list_val(self) -> global___StringList: ... - @property - def int32_list_val(self) -> global___Int32List: ... - @property - def int64_list_val(self) -> global___Int64List: ... - @property - def double_list_val(self) -> global___DoubleList: ... - @property - def float_list_val(self) -> global___FloatList: ... - @property - def bool_list_val(self) -> global___BoolList: ... - @property - def unix_timestamp_list_val(self) -> global___Int64List: ... - null_val: global___Null.ValueType - @property - def map_val(self) -> global___Map: ... - @property - def map_list_val(self) -> global___MapList: ... - @property - def bytes_set_val(self) -> global___BytesSet: ... - @property - def string_set_val(self) -> global___StringSet: ... - @property - def int32_set_val(self) -> global___Int32Set: ... - @property - def int64_set_val(self) -> global___Int64Set: ... - @property - def double_set_val(self) -> global___DoubleSet: ... - @property - def float_set_val(self) -> global___FloatSet: ... - @property - def bool_set_val(self) -> global___BoolSet: ... - @property - def unix_timestamp_set_val(self) -> global___Int64Set: ... +Global___ValueType: _TypeAlias = ValueType # noqa: Y015 + +@_typing.final +class Value(_message.Message): + DESCRIPTOR: _descriptor.Descriptor + + BYTES_VAL_FIELD_NUMBER: _builtins.int + STRING_VAL_FIELD_NUMBER: _builtins.int + INT32_VAL_FIELD_NUMBER: _builtins.int + INT64_VAL_FIELD_NUMBER: _builtins.int + DOUBLE_VAL_FIELD_NUMBER: _builtins.int + FLOAT_VAL_FIELD_NUMBER: _builtins.int + BOOL_VAL_FIELD_NUMBER: _builtins.int + UNIX_TIMESTAMP_VAL_FIELD_NUMBER: _builtins.int + BYTES_LIST_VAL_FIELD_NUMBER: _builtins.int + STRING_LIST_VAL_FIELD_NUMBER: _builtins.int + INT32_LIST_VAL_FIELD_NUMBER: _builtins.int + INT64_LIST_VAL_FIELD_NUMBER: _builtins.int + DOUBLE_LIST_VAL_FIELD_NUMBER: _builtins.int + FLOAT_LIST_VAL_FIELD_NUMBER: _builtins.int + BOOL_LIST_VAL_FIELD_NUMBER: _builtins.int + UNIX_TIMESTAMP_LIST_VAL_FIELD_NUMBER: _builtins.int + NULL_VAL_FIELD_NUMBER: _builtins.int + MAP_VAL_FIELD_NUMBER: _builtins.int + MAP_LIST_VAL_FIELD_NUMBER: _builtins.int + BYTES_SET_VAL_FIELD_NUMBER: _builtins.int + STRING_SET_VAL_FIELD_NUMBER: _builtins.int + INT32_SET_VAL_FIELD_NUMBER: _builtins.int + INT64_SET_VAL_FIELD_NUMBER: _builtins.int + DOUBLE_SET_VAL_FIELD_NUMBER: _builtins.int + FLOAT_SET_VAL_FIELD_NUMBER: _builtins.int + BOOL_SET_VAL_FIELD_NUMBER: _builtins.int + UNIX_TIMESTAMP_SET_VAL_FIELD_NUMBER: _builtins.int + JSON_VAL_FIELD_NUMBER: _builtins.int + JSON_LIST_VAL_FIELD_NUMBER: _builtins.int + STRUCT_VAL_FIELD_NUMBER: _builtins.int + STRUCT_LIST_VAL_FIELD_NUMBER: _builtins.int + UUID_VAL_FIELD_NUMBER: _builtins.int + TIME_UUID_VAL_FIELD_NUMBER: _builtins.int + UUID_LIST_VAL_FIELD_NUMBER: _builtins.int + TIME_UUID_LIST_VAL_FIELD_NUMBER: _builtins.int + UUID_SET_VAL_FIELD_NUMBER: _builtins.int + TIME_UUID_SET_VAL_FIELD_NUMBER: _builtins.int + LIST_VAL_FIELD_NUMBER: _builtins.int + SET_VAL_FIELD_NUMBER: _builtins.int + DECIMAL_VAL_FIELD_NUMBER: _builtins.int + DECIMAL_LIST_VAL_FIELD_NUMBER: _builtins.int + DECIMAL_SET_VAL_FIELD_NUMBER: _builtins.int + bytes_val: _builtins.bytes + string_val: _builtins.str + int32_val: _builtins.int + int64_val: _builtins.int + double_val: _builtins.float + float_val: _builtins.float + bool_val: _builtins.bool + unix_timestamp_val: _builtins.int + null_val: Global___Null.ValueType + json_val: _builtins.str + uuid_val: _builtins.str + time_uuid_val: _builtins.str + decimal_val: _builtins.str + @_builtins.property + def bytes_list_val(self) -> Global___BytesList: ... + @_builtins.property + def string_list_val(self) -> Global___StringList: ... + @_builtins.property + def int32_list_val(self) -> Global___Int32List: ... + @_builtins.property + def int64_list_val(self) -> Global___Int64List: ... + @_builtins.property + def double_list_val(self) -> Global___DoubleList: ... + @_builtins.property + def float_list_val(self) -> Global___FloatList: ... + @_builtins.property + def bool_list_val(self) -> Global___BoolList: ... + @_builtins.property + def unix_timestamp_list_val(self) -> Global___Int64List: ... + @_builtins.property + def map_val(self) -> Global___Map: ... + @_builtins.property + def map_list_val(self) -> Global___MapList: ... + @_builtins.property + def bytes_set_val(self) -> Global___BytesSet: ... + @_builtins.property + def string_set_val(self) -> Global___StringSet: ... + @_builtins.property + def int32_set_val(self) -> Global___Int32Set: ... + @_builtins.property + def int64_set_val(self) -> Global___Int64Set: ... + @_builtins.property + def double_set_val(self) -> Global___DoubleSet: ... + @_builtins.property + def float_set_val(self) -> Global___FloatSet: ... + @_builtins.property + def bool_set_val(self) -> Global___BoolSet: ... + @_builtins.property + def unix_timestamp_set_val(self) -> Global___Int64Set: ... + @_builtins.property + def json_list_val(self) -> Global___StringList: ... + @_builtins.property + def struct_val(self) -> Global___Map: ... + @_builtins.property + def struct_list_val(self) -> Global___MapList: ... + @_builtins.property + def uuid_list_val(self) -> Global___StringList: ... + @_builtins.property + def time_uuid_list_val(self) -> Global___StringList: ... + @_builtins.property + def uuid_set_val(self) -> Global___StringSet: ... + @_builtins.property + def time_uuid_set_val(self) -> Global___StringSet: ... + @_builtins.property + def list_val(self) -> Global___RepeatedValue: ... + @_builtins.property + def set_val(self) -> Global___RepeatedValue: ... + @_builtins.property + def decimal_list_val(self) -> Global___StringList: ... + @_builtins.property + def decimal_set_val(self) -> Global___StringSet: ... def __init__( self, *, - bytes_val: builtins.bytes = ..., - string_val: builtins.str = ..., - int32_val: builtins.int = ..., - int64_val: builtins.int = ..., - double_val: builtins.float = ..., - float_val: builtins.float = ..., - bool_val: builtins.bool = ..., - unix_timestamp_val: builtins.int = ..., - bytes_list_val: global___BytesList | None = ..., - string_list_val: global___StringList | None = ..., - int32_list_val: global___Int32List | None = ..., - int64_list_val: global___Int64List | None = ..., - double_list_val: global___DoubleList | None = ..., - float_list_val: global___FloatList | None = ..., - bool_list_val: global___BoolList | None = ..., - unix_timestamp_list_val: global___Int64List | None = ..., - null_val: global___Null.ValueType = ..., - map_val: global___Map | None = ..., - map_list_val: global___MapList | None = ..., - bytes_set_val: global___BytesSet | None = ..., - string_set_val: global___StringSet | None = ..., - int32_set_val: global___Int32Set | None = ..., - int64_set_val: global___Int64Set | None = ..., - double_set_val: global___DoubleSet | None = ..., - float_set_val: global___FloatSet | None = ..., - bool_set_val: global___BoolSet | None = ..., - unix_timestamp_set_val: global___Int64Set | None = ..., + bytes_val: _builtins.bytes = ..., + string_val: _builtins.str = ..., + int32_val: _builtins.int = ..., + int64_val: _builtins.int = ..., + double_val: _builtins.float = ..., + float_val: _builtins.float = ..., + bool_val: _builtins.bool = ..., + unix_timestamp_val: _builtins.int = ..., + bytes_list_val: Global___BytesList | None = ..., + string_list_val: Global___StringList | None = ..., + int32_list_val: Global___Int32List | None = ..., + int64_list_val: Global___Int64List | None = ..., + double_list_val: Global___DoubleList | None = ..., + float_list_val: Global___FloatList | None = ..., + bool_list_val: Global___BoolList | None = ..., + unix_timestamp_list_val: Global___Int64List | None = ..., + null_val: Global___Null.ValueType = ..., + map_val: Global___Map | None = ..., + map_list_val: Global___MapList | None = ..., + bytes_set_val: Global___BytesSet | None = ..., + string_set_val: Global___StringSet | None = ..., + int32_set_val: Global___Int32Set | None = ..., + int64_set_val: Global___Int64Set | None = ..., + double_set_val: Global___DoubleSet | None = ..., + float_set_val: Global___FloatSet | None = ..., + bool_set_val: Global___BoolSet | None = ..., + unix_timestamp_set_val: Global___Int64Set | None = ..., + json_val: _builtins.str = ..., + json_list_val: Global___StringList | None = ..., + struct_val: Global___Map | None = ..., + struct_list_val: Global___MapList | None = ..., + uuid_val: _builtins.str = ..., + time_uuid_val: _builtins.str = ..., + uuid_list_val: Global___StringList | None = ..., + time_uuid_list_val: Global___StringList | None = ..., + uuid_set_val: Global___StringSet | None = ..., + time_uuid_set_val: Global___StringSet | None = ..., + list_val: Global___RepeatedValue | None = ..., + set_val: Global___RepeatedValue | None = ..., + decimal_val: _builtins.str = ..., + decimal_list_val: Global___StringList | None = ..., + decimal_set_val: Global___StringSet | None = ..., ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["bool_list_val", b"bool_list_val", "bool_set_val", b"bool_set_val", "bool_val", b"bool_val", "bytes_list_val", b"bytes_list_val", "bytes_set_val", b"bytes_set_val", "bytes_val", b"bytes_val", "double_list_val", b"double_list_val", "double_set_val", b"double_set_val", "double_val", b"double_val", "float_list_val", b"float_list_val", "float_set_val", b"float_set_val", "float_val", b"float_val", "int32_list_val", b"int32_list_val", "int32_set_val", b"int32_set_val", "int32_val", b"int32_val", "int64_list_val", b"int64_list_val", "int64_set_val", b"int64_set_val", "int64_val", b"int64_val", "map_list_val", b"map_list_val", "map_val", b"map_val", "null_val", b"null_val", "string_list_val", b"string_list_val", "string_set_val", b"string_set_val", "string_val", b"string_val", "unix_timestamp_list_val", b"unix_timestamp_list_val", "unix_timestamp_set_val", b"unix_timestamp_set_val", "unix_timestamp_val", b"unix_timestamp_val", "val", b"val"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["bool_list_val", b"bool_list_val", "bool_set_val", b"bool_set_val", "bool_val", b"bool_val", "bytes_list_val", b"bytes_list_val", "bytes_set_val", b"bytes_set_val", "bytes_val", b"bytes_val", "double_list_val", b"double_list_val", "double_set_val", b"double_set_val", "double_val", b"double_val", "float_list_val", b"float_list_val", "float_set_val", b"float_set_val", "float_val", b"float_val", "int32_list_val", b"int32_list_val", "int32_set_val", b"int32_set_val", "int32_val", b"int32_val", "int64_list_val", b"int64_list_val", "int64_set_val", b"int64_set_val", "int64_val", b"int64_val", "map_list_val", b"map_list_val", "map_val", b"map_val", "null_val", b"null_val", "string_list_val", b"string_list_val", "string_set_val", b"string_set_val", "string_val", b"string_val", "unix_timestamp_list_val", b"unix_timestamp_list_val", "unix_timestamp_set_val", b"unix_timestamp_set_val", "unix_timestamp_val", b"unix_timestamp_val", "val", b"val"]) -> None: ... - def WhichOneof(self, oneof_group: typing_extensions.Literal["val", b"val"]) -> typing_extensions.Literal["bytes_val", "string_val", "int32_val", "int64_val", "double_val", "float_val", "bool_val", "unix_timestamp_val", "bytes_list_val", "string_list_val", "int32_list_val", "int64_list_val", "double_list_val", "float_list_val", "bool_list_val", "unix_timestamp_list_val", "null_val", "map_val", "map_list_val", "bytes_set_val", "string_set_val", "int32_set_val", "int64_set_val", "double_set_val", "float_set_val", "bool_set_val", "unix_timestamp_set_val"] | None: ... - -global___Value = Value - -class BytesList(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor - - VAL_FIELD_NUMBER: builtins.int - @property - def val(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.bytes]: ... + _HasFieldArgType: _TypeAlias = _typing.Literal["bool_list_val", b"bool_list_val", "bool_set_val", b"bool_set_val", "bool_val", b"bool_val", "bytes_list_val", b"bytes_list_val", "bytes_set_val", b"bytes_set_val", "bytes_val", b"bytes_val", "decimal_list_val", b"decimal_list_val", "decimal_set_val", b"decimal_set_val", "decimal_val", b"decimal_val", "double_list_val", b"double_list_val", "double_set_val", b"double_set_val", "double_val", b"double_val", "float_list_val", b"float_list_val", "float_set_val", b"float_set_val", "float_val", b"float_val", "int32_list_val", b"int32_list_val", "int32_set_val", b"int32_set_val", "int32_val", b"int32_val", "int64_list_val", b"int64_list_val", "int64_set_val", b"int64_set_val", "int64_val", b"int64_val", "json_list_val", b"json_list_val", "json_val", b"json_val", "list_val", b"list_val", "map_list_val", b"map_list_val", "map_val", b"map_val", "null_val", b"null_val", "set_val", b"set_val", "string_list_val", b"string_list_val", "string_set_val", b"string_set_val", "string_val", b"string_val", "struct_list_val", b"struct_list_val", "struct_val", b"struct_val", "time_uuid_list_val", b"time_uuid_list_val", "time_uuid_set_val", b"time_uuid_set_val", "time_uuid_val", b"time_uuid_val", "unix_timestamp_list_val", b"unix_timestamp_list_val", "unix_timestamp_set_val", b"unix_timestamp_set_val", "unix_timestamp_val", b"unix_timestamp_val", "uuid_list_val", b"uuid_list_val", "uuid_set_val", b"uuid_set_val", "uuid_val", b"uuid_val", "val", b"val"] # noqa: Y015 + def HasField(self, field_name: _HasFieldArgType) -> _builtins.bool: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["bool_list_val", b"bool_list_val", "bool_set_val", b"bool_set_val", "bool_val", b"bool_val", "bytes_list_val", b"bytes_list_val", "bytes_set_val", b"bytes_set_val", "bytes_val", b"bytes_val", "decimal_list_val", b"decimal_list_val", "decimal_set_val", b"decimal_set_val", "decimal_val", b"decimal_val", "double_list_val", b"double_list_val", "double_set_val", b"double_set_val", "double_val", b"double_val", "float_list_val", b"float_list_val", "float_set_val", b"float_set_val", "float_val", b"float_val", "int32_list_val", b"int32_list_val", "int32_set_val", b"int32_set_val", "int32_val", b"int32_val", "int64_list_val", b"int64_list_val", "int64_set_val", b"int64_set_val", "int64_val", b"int64_val", "json_list_val", b"json_list_val", "json_val", b"json_val", "list_val", b"list_val", "map_list_val", b"map_list_val", "map_val", b"map_val", "null_val", b"null_val", "set_val", b"set_val", "string_list_val", b"string_list_val", "string_set_val", b"string_set_val", "string_val", b"string_val", "struct_list_val", b"struct_list_val", "struct_val", b"struct_val", "time_uuid_list_val", b"time_uuid_list_val", "time_uuid_set_val", b"time_uuid_set_val", "time_uuid_val", b"time_uuid_val", "unix_timestamp_list_val", b"unix_timestamp_list_val", "unix_timestamp_set_val", b"unix_timestamp_set_val", "unix_timestamp_val", b"unix_timestamp_val", "uuid_list_val", b"uuid_list_val", "uuid_set_val", b"uuid_set_val", "uuid_val", b"uuid_val", "val", b"val"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... + _WhichOneofReturnType_val: _TypeAlias = _typing.Literal["bytes_val", "string_val", "int32_val", "int64_val", "double_val", "float_val", "bool_val", "unix_timestamp_val", "bytes_list_val", "string_list_val", "int32_list_val", "int64_list_val", "double_list_val", "float_list_val", "bool_list_val", "unix_timestamp_list_val", "null_val", "map_val", "map_list_val", "bytes_set_val", "string_set_val", "int32_set_val", "int64_set_val", "double_set_val", "float_set_val", "bool_set_val", "unix_timestamp_set_val", "json_val", "json_list_val", "struct_val", "struct_list_val", "uuid_val", "time_uuid_val", "uuid_list_val", "time_uuid_list_val", "uuid_set_val", "time_uuid_set_val", "list_val", "set_val", "decimal_val", "decimal_list_val", "decimal_set_val"] # noqa: Y015 + _WhichOneofArgType_val: _TypeAlias = _typing.Literal["val", b"val"] # noqa: Y015 + def WhichOneof(self, oneof_group: _WhichOneofArgType_val) -> _WhichOneofReturnType_val | None: ... + +Global___Value: _TypeAlias = Value # noqa: Y015 + +@_typing.final +class BytesList(_message.Message): + DESCRIPTOR: _descriptor.Descriptor + + VAL_FIELD_NUMBER: _builtins.int + @_builtins.property + def val(self) -> _containers.RepeatedScalarFieldContainer[_builtins.bytes]: ... def __init__( self, *, - val: collections.abc.Iterable[builtins.bytes] | None = ..., + val: _abc.Iterable[_builtins.bytes] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["val", b"val"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["val", b"val"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___BytesList = BytesList +Global___BytesList: _TypeAlias = BytesList # noqa: Y015 -class StringList(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class StringList(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - VAL_FIELD_NUMBER: builtins.int - @property - def val(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: ... + VAL_FIELD_NUMBER: _builtins.int + @_builtins.property + def val(self) -> _containers.RepeatedScalarFieldContainer[_builtins.str]: ... def __init__( self, *, - val: collections.abc.Iterable[builtins.str] | None = ..., + val: _abc.Iterable[_builtins.str] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["val", b"val"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["val", b"val"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___StringList = StringList +Global___StringList: _TypeAlias = StringList # noqa: Y015 -class Int32List(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class Int32List(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - VAL_FIELD_NUMBER: builtins.int - @property - def val(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: ... + VAL_FIELD_NUMBER: _builtins.int + @_builtins.property + def val(self) -> _containers.RepeatedScalarFieldContainer[_builtins.int]: ... def __init__( self, *, - val: collections.abc.Iterable[builtins.int] | None = ..., + val: _abc.Iterable[_builtins.int] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["val", b"val"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["val", b"val"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___Int32List = Int32List +Global___Int32List: _TypeAlias = Int32List # noqa: Y015 -class Int64List(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class Int64List(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - VAL_FIELD_NUMBER: builtins.int - @property - def val(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: ... + VAL_FIELD_NUMBER: _builtins.int + @_builtins.property + def val(self) -> _containers.RepeatedScalarFieldContainer[_builtins.int]: ... def __init__( self, *, - val: collections.abc.Iterable[builtins.int] | None = ..., + val: _abc.Iterable[_builtins.int] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["val", b"val"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["val", b"val"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___Int64List = Int64List +Global___Int64List: _TypeAlias = Int64List # noqa: Y015 -class DoubleList(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class DoubleList(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - VAL_FIELD_NUMBER: builtins.int - @property - def val(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.float]: ... + VAL_FIELD_NUMBER: _builtins.int + @_builtins.property + def val(self) -> _containers.RepeatedScalarFieldContainer[_builtins.float]: ... def __init__( self, *, - val: collections.abc.Iterable[builtins.float] | None = ..., + val: _abc.Iterable[_builtins.float] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["val", b"val"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["val", b"val"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___DoubleList = DoubleList +Global___DoubleList: _TypeAlias = DoubleList # noqa: Y015 -class FloatList(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class FloatList(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - VAL_FIELD_NUMBER: builtins.int - @property - def val(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.float]: ... + VAL_FIELD_NUMBER: _builtins.int + @_builtins.property + def val(self) -> _containers.RepeatedScalarFieldContainer[_builtins.float]: ... def __init__( self, *, - val: collections.abc.Iterable[builtins.float] | None = ..., + val: _abc.Iterable[_builtins.float] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["val", b"val"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["val", b"val"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___FloatList = FloatList +Global___FloatList: _TypeAlias = FloatList # noqa: Y015 -class BoolList(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class BoolList(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - VAL_FIELD_NUMBER: builtins.int - @property - def val(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.bool]: ... + VAL_FIELD_NUMBER: _builtins.int + @_builtins.property + def val(self) -> _containers.RepeatedScalarFieldContainer[_builtins.bool]: ... def __init__( self, *, - val: collections.abc.Iterable[builtins.bool] | None = ..., + val: _abc.Iterable[_builtins.bool] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["val", b"val"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["val", b"val"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___BoolList = BoolList +Global___BoolList: _TypeAlias = BoolList # noqa: Y015 -class BytesSet(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class BytesSet(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - VAL_FIELD_NUMBER: builtins.int - @property - def val(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.bytes]: ... + VAL_FIELD_NUMBER: _builtins.int + @_builtins.property + def val(self) -> _containers.RepeatedScalarFieldContainer[_builtins.bytes]: ... def __init__( self, *, - val: collections.abc.Iterable[builtins.bytes] | None = ..., + val: _abc.Iterable[_builtins.bytes] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["val", b"val"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["val", b"val"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___BytesSet = BytesSet +Global___BytesSet: _TypeAlias = BytesSet # noqa: Y015 -class StringSet(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class StringSet(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - VAL_FIELD_NUMBER: builtins.int - @property - def val(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: ... + VAL_FIELD_NUMBER: _builtins.int + @_builtins.property + def val(self) -> _containers.RepeatedScalarFieldContainer[_builtins.str]: ... def __init__( self, *, - val: collections.abc.Iterable[builtins.str] | None = ..., + val: _abc.Iterable[_builtins.str] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["val", b"val"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["val", b"val"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___StringSet = StringSet +Global___StringSet: _TypeAlias = StringSet # noqa: Y015 -class Int32Set(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class Int32Set(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - VAL_FIELD_NUMBER: builtins.int - @property - def val(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: ... + VAL_FIELD_NUMBER: _builtins.int + @_builtins.property + def val(self) -> _containers.RepeatedScalarFieldContainer[_builtins.int]: ... def __init__( self, *, - val: collections.abc.Iterable[builtins.int] | None = ..., + val: _abc.Iterable[_builtins.int] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["val", b"val"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["val", b"val"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___Int32Set = Int32Set +Global___Int32Set: _TypeAlias = Int32Set # noqa: Y015 -class Int64Set(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class Int64Set(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - VAL_FIELD_NUMBER: builtins.int - @property - def val(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: ... + VAL_FIELD_NUMBER: _builtins.int + @_builtins.property + def val(self) -> _containers.RepeatedScalarFieldContainer[_builtins.int]: ... def __init__( self, *, - val: collections.abc.Iterable[builtins.int] | None = ..., + val: _abc.Iterable[_builtins.int] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["val", b"val"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["val", b"val"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___Int64Set = Int64Set +Global___Int64Set: _TypeAlias = Int64Set # noqa: Y015 -class DoubleSet(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class DoubleSet(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - VAL_FIELD_NUMBER: builtins.int - @property - def val(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.float]: ... + VAL_FIELD_NUMBER: _builtins.int + @_builtins.property + def val(self) -> _containers.RepeatedScalarFieldContainer[_builtins.float]: ... def __init__( self, *, - val: collections.abc.Iterable[builtins.float] | None = ..., + val: _abc.Iterable[_builtins.float] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["val", b"val"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["val", b"val"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___DoubleSet = DoubleSet +Global___DoubleSet: _TypeAlias = DoubleSet # noqa: Y015 -class FloatSet(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class FloatSet(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - VAL_FIELD_NUMBER: builtins.int - @property - def val(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.float]: ... + VAL_FIELD_NUMBER: _builtins.int + @_builtins.property + def val(self) -> _containers.RepeatedScalarFieldContainer[_builtins.float]: ... def __init__( self, *, - val: collections.abc.Iterable[builtins.float] | None = ..., + val: _abc.Iterable[_builtins.float] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["val", b"val"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["val", b"val"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___FloatSet = FloatSet +Global___FloatSet: _TypeAlias = FloatSet # noqa: Y015 -class BoolSet(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class BoolSet(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - VAL_FIELD_NUMBER: builtins.int - @property - def val(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.bool]: ... + VAL_FIELD_NUMBER: _builtins.int + @_builtins.property + def val(self) -> _containers.RepeatedScalarFieldContainer[_builtins.bool]: ... def __init__( self, *, - val: collections.abc.Iterable[builtins.bool] | None = ..., + val: _abc.Iterable[_builtins.bool] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["val", b"val"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["val", b"val"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___BoolSet = BoolSet +Global___BoolSet: _TypeAlias = BoolSet # noqa: Y015 -class Map(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class Map(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - class ValEntry(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor + @_typing.final + class ValEntry(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - KEY_FIELD_NUMBER: builtins.int - VALUE_FIELD_NUMBER: builtins.int - key: builtins.str - @property - def value(self) -> global___Value: ... + KEY_FIELD_NUMBER: _builtins.int + VALUE_FIELD_NUMBER: _builtins.int + key: _builtins.str + @_builtins.property + def value(self) -> Global___Value: ... def __init__( self, *, - key: builtins.str = ..., - value: global___Value | None = ..., + key: _builtins.str = ..., + value: Global___Value | None = ..., ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["value", b"value"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["key", b"key", "value", b"value"]) -> None: ... - - VAL_FIELD_NUMBER: builtins.int - @property - def val(self) -> google.protobuf.internal.containers.MessageMap[builtins.str, global___Value]: ... + _HasFieldArgType: _TypeAlias = _typing.Literal["value", b"value"] # noqa: Y015 + def HasField(self, field_name: _HasFieldArgType) -> _builtins.bool: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["key", b"key", "value", b"value"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... + + VAL_FIELD_NUMBER: _builtins.int + @_builtins.property + def val(self) -> _containers.MessageMap[_builtins.str, Global___Value]: ... def __init__( self, *, - val: collections.abc.Mapping[builtins.str, global___Value] | None = ..., + val: _abc.Mapping[_builtins.str, Global___Value] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["val", b"val"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["val", b"val"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___Map = Map +Global___Map: _TypeAlias = Map # noqa: Y015 -class MapList(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor +@_typing.final +class MapList(_message.Message): + DESCRIPTOR: _descriptor.Descriptor - VAL_FIELD_NUMBER: builtins.int - @property - def val(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___Map]: ... + VAL_FIELD_NUMBER: _builtins.int + @_builtins.property + def val(self) -> _containers.RepeatedCompositeFieldContainer[Global___Map]: ... def __init__( self, *, - val: collections.abc.Iterable[global___Map] | None = ..., + val: _abc.Iterable[Global___Map] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["val", b"val"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["val", b"val"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___MapList = MapList +Global___MapList: _TypeAlias = MapList # noqa: Y015 -class RepeatedValue(google.protobuf.message.Message): +@_typing.final +class RepeatedValue(_message.Message): """This is to avoid an issue of being unable to specify `repeated value` in oneofs or maps In JSON "val" field can be omitted """ - DESCRIPTOR: google.protobuf.descriptor.Descriptor + DESCRIPTOR: _descriptor.Descriptor - VAL_FIELD_NUMBER: builtins.int - @property - def val(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___Value]: ... + VAL_FIELD_NUMBER: _builtins.int + @_builtins.property + def val(self) -> _containers.RepeatedCompositeFieldContainer[Global___Value]: ... def __init__( self, *, - val: collections.abc.Iterable[global___Value] | None = ..., + val: _abc.Iterable[Global___Value] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["val", b"val"]) -> None: ... + _ClearFieldArgType: _TypeAlias = _typing.Literal["val", b"val"] # noqa: Y015 + def ClearField(self, field_name: _ClearFieldArgType) -> None: ... -global___RepeatedValue = RepeatedValue +Global___RepeatedValue: _TypeAlias = RepeatedValue # noqa: Y015 diff --git a/sdk/python/feast/repo_config.py b/sdk/python/feast/repo_config.py index 72cd46ba0ab..208307dc5d5 100644 --- a/sdk/python/feast/repo_config.py +++ b/sdk/python/feast/repo_config.py @@ -58,7 +58,6 @@ "feast.infra.online_stores.contrib.cassandra_online_store.cassandra_online_store.CassandraOnlineStore": "feast.infra.online_stores.cassandra_online_store.cassandra_online_store.CassandraOnlineStore", "feast.infra.online_stores.contrib.mysql_online_store.mysql.MySQLOnlineStore": "feast.infra.online_stores.mysql_online_store.mysql.MySQLOnlineStore", "feast.infra.online_stores.contrib.hazelcast_online_store.hazelcast_online_store.HazelcastOnlineStore": "feast.infra.online_stores.hazelcast_online_store.hazelcast_online_store.HazelcastOnlineStore", - "feast.infra.online_stores.contrib.ikv_online_store.ikv.IKVOnlineStore": "feast.infra.online_stores.ikv_online_store.ikv.IKVOnlineStore", "feast.infra.online_stores.contrib.elasticsearch.ElasticSearchOnlineStore": "feast.infra.online_stores.elasticsearch_online_store.elasticsearch.ElasticSearchOnlineStore", "feast.infra.online_stores.contrib.singlestore_online_store.singlestore.SingleStoreOnlineStore": "feast.infra.online_stores.singlestore_online_store.singlestore.SingleStoreOnlineStore", "feast.infra.online_stores.contrib.qdrant.QdrantOnlineStore": "feast.infra.online_stores.qdrant_online_store.qdrant.QdrantOnlineStore", @@ -77,13 +76,13 @@ "cassandra": "feast.infra.online_stores.cassandra_online_store.cassandra_online_store.CassandraOnlineStore", "mysql": "feast.infra.online_stores.mysql_online_store.mysql.MySQLOnlineStore", "hazelcast": "feast.infra.online_stores.hazelcast_online_store.hazelcast_online_store.HazelcastOnlineStore", - "ikv": "feast.infra.online_stores.ikv_online_store.ikv.IKVOnlineStore", "elasticsearch": "feast.infra.online_stores.elasticsearch_online_store.elasticsearch.ElasticSearchOnlineStore", "remote": "feast.infra.online_stores.remote.RemoteOnlineStore", "singlestore": "feast.infra.online_stores.singlestore_online_store.singlestore.SingleStoreOnlineStore", "qdrant": "feast.infra.online_stores.qdrant_online_store.qdrant.QdrantOnlineStore", "couchbase.online": "feast.infra.online_stores.couchbase_online_store.couchbase.CouchbaseOnlineStore", "milvus": "feast.infra.online_stores.milvus_online_store.milvus.MilvusOnlineStore", + "mongodb": "feast.infra.online_stores.mongodb_online_store.MongoDBOnlineStore", "hybrid": "feast.infra.online_stores.hybrid_online_store.hybrid_online_store.HybridOnlineStore", **LEGACY_ONLINE_STORE_CLASS_FOR_TYPE, } @@ -104,6 +103,7 @@ "couchbase.offline": "feast.infra.offline_stores.contrib.couchbase_offline_store.couchbase.CouchbaseColumnarOfflineStore", "clickhouse": "feast.infra.offline_stores.contrib.clickhouse_offline_store.clickhouse.ClickhouseOfflineStore", "ray": "feast.infra.offline_stores.contrib.ray_offline_store.ray.RayOfflineStore", + "oracle": "feast.infra.offline_stores.contrib.oracle_offline_store.oracle.OracleOfflineStore", } FEATURE_SERVER_CONFIG_CLASS_FOR_TYPE = { @@ -120,6 +120,24 @@ "oidc_client": "feast.permissions.auth_model.OidcClientAuthConfig", } +_OIDC_CLIENT_KEYS = frozenset( + {"client_secret", "token", "token_env_var", "username", "password"} +) + + +def _is_oidc_client_config(auth_dict: dict) -> bool: + """Decide whether an OIDC auth dict should be routed to OidcClientAuthConfig. + + True when the dict carries any client-credential key, or when it is a bare + ``{"type": "oidc"}`` dict with no server-side keys (auth_discovery_url / + client_id), which signals token-passthrough via FEAST_OIDC_TOKEN. + """ + if auth_dict.get("type") != AuthType.OIDC.value: + return False + has_client_keys = bool(_OIDC_CLIENT_KEYS & auth_dict.keys()) + has_server_keys = "auth_discovery_url" in auth_dict + return has_client_keys or not has_server_keys + class FeastBaseModel(BaseModel): """Feast Pydantic Configuration Class""" @@ -167,6 +185,12 @@ class RegistryConfig(FeastBaseModel): Once this is set to True, it cannot be reverted back to False. Reverting back to False will only reset the project but not all the projects""" + enable_online_feature_view_versioning: StrictBool = False + """ bool: Enable versioned online store tables and version-qualified reads + (e.g., 'fv@v2:feature'). When True, each schema version gets its own + online store table and can be queried independently. Version history + tracking in the registry is always active regardless of this setting. """ + @field_validator("path") def validate_path(cls, path: str, values: ValidationInfo) -> str: if values.data.get("registry_type") == "sql": @@ -401,26 +425,12 @@ def offline_store(self): def auth_config(self): if not self._auth: if isinstance(self.auth, Dict): - # treat this auth block as *client-side* OIDC when it matches - # 1) ROPG – username + password + client_secret - # 2) client-credentials – client_secret only - # 3) static token – token - is_oidc_client = self.auth.get("type") == AuthType.OIDC.value and ( - ( - "username" in self.auth - and "password" in self.auth - and "client_secret" in self.auth - ) # 1 - or ( - "client_secret" in self.auth - and "username" not in self.auth - and "password" not in self.auth - ) # 2 - or ("token" in self.auth) # 3 + config_type = ( + "oidc_client" + if _is_oidc_client_config(self.auth) + else self.auth.get("type") ) - self._auth = get_auth_config_from_type( - "oidc_client" if is_oidc_client else self.auth.get("type") - )(**self.auth) + self._auth = get_auth_config_from_type(config_type)(**self.auth) elif isinstance(self.auth, str): self._auth = get_auth_config_from_type(self.auth)() elif self.auth: diff --git a/sdk/python/feast/repo_operations.py b/sdk/python/feast/repo_operations.py index fa5d297752a..28fe86602ad 100644 --- a/sdk/python/feast/repo_operations.py +++ b/sdk/python/feast/repo_operations.py @@ -92,9 +92,9 @@ def get_repo_files(repo_root: Path) -> List[Path]: ".git", ".feastignore", ".venv", - ".pytest_cache", - "__pycache__", - ".ipynb_checkpoints", + "**/.ipynb_checkpoints", + "**/.pytest_cache", + "**/__pycache__", ] ignore_files = get_ignore_files(repo_root, ignore_paths) @@ -164,8 +164,9 @@ def parse_repo(repo_root: Path) -> RepoContents: # Handle batch sources defined with feature views. batch_source = obj.batch_source - assert batch_source - if not any((batch_source is ds) for ds in res.data_sources): + if batch_source is not None and not any( + (batch_source is ds) for ds in res.data_sources + ): res.data_sources.append(batch_source) # Handle stream sources defined with feature views. @@ -180,10 +181,10 @@ def parse_repo(repo_root: Path) -> RepoContents: # Handle batch sources defined with feature views. batch_source = obj.batch_source - if not any((batch_source is ds) for ds in res.data_sources): + if batch_source is not None and not any( + (batch_source is ds) for ds in res.data_sources + ): res.data_sources.append(batch_source) - - # Handle stream sources defined with feature views. assert obj.stream_source stream_source = obj.stream_source if not any((stream_source is ds) for ds in res.data_sources): @@ -195,7 +196,9 @@ def parse_repo(repo_root: Path) -> RepoContents: # Handle batch sources defined with feature views. batch_source = obj.batch_source - if not any((batch_source is ds) for ds in res.data_sources): + if batch_source is not None and not any( + (batch_source is ds) for ds in res.data_sources + ): res.data_sources.append(batch_source) elif isinstance(obj, Entity) and not any( (obj is entity) for entity in res.entities @@ -234,7 +237,9 @@ def plan( # TODO: When we support multiple projects in a single repo, we should filter repo contents by project if not skip_source_validation: provider = store._get_provider() - data_sources = [t.batch_source for t in repo.feature_views] + data_sources = [ + t.batch_source for t in repo.feature_views if t.batch_source is not None + ] # Make sure the data source used by this feature view is supported by Feast for data_source in data_sources: provider.validate_data_source(store.config, data_source) @@ -342,10 +347,13 @@ def apply_total_with_repo_instance( repo: RepoContents, skip_source_validation: bool, skip_feature_view_validation: bool = False, + no_promote: bool = False, ): if not skip_source_validation: provider = store._get_provider() - data_sources = [t.batch_source for t in repo.feature_views] + data_sources = [ + t.batch_source for t in repo.feature_views if t.batch_source is not None + ] # Make sure the data source used by this feature view is supported by Feast for data_source in data_sources: provider.validate_data_source(store.config, data_source) @@ -377,7 +385,11 @@ def apply_total_with_repo_instance( # Apply phase store._apply_diffs( - registry_diff, infra_diff, new_infra, progress_ctx=progress_ctx + registry_diff, + infra_diff, + new_infra, + progress_ctx=progress_ctx, + no_promote=no_promote, ) click.echo(infra_diff.to_string()) else: @@ -387,6 +399,7 @@ def apply_total_with_repo_instance( objects_to_delete=all_to_delete, partial=False, skip_feature_view_validation=skip_feature_view_validation, + no_promote=no_promote, ) log_infra_changes(views_to_keep, views_to_delete) finally: @@ -434,6 +447,7 @@ def apply_total( repo_path: Path, skip_source_validation: bool, skip_feature_view_validation: bool = False, + no_promote: bool = False, ): os.chdir(repo_path) repo = _get_repo_contents(repo_path, repo_config.project, repo_config) @@ -455,6 +469,7 @@ def apply_total( repo, skip_source_validation, skip_feature_view_validation, + no_promote=no_promote, ) diff --git a/sdk/python/feast/stream_feature_view.py b/sdk/python/feast/stream_feature_view.py index d30db29b299..2773484ecbb 100644 --- a/sdk/python/feast/stream_feature_view.py +++ b/sdk/python/feast/stream_feature_view.py @@ -12,10 +12,12 @@ from feast import flags_helper, utils from feast.aggregation import Aggregation +from feast.base_feature_view import BaseFeatureView from feast.data_source import DataSource from feast.entity import Entity from feast.feature_view import FeatureView from feast.field import Field +from feast.proto_utils import mode_to_string, serialize_data_source from feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto from feast.protos.feast.core.OnDemandFeatureView_pb2 import ( UserDefinedFunction as UserDefinedFunctionProto, @@ -120,6 +122,8 @@ def __init__( stream_engine: Optional[Dict[str, Any]] = None, enable_tiling: bool = False, tiling_hop_size: Optional[timedelta] = None, + enable_validation: bool = False, + version: str = "latest", ): if not flags_helper.is_test(): warnings.warn( @@ -183,6 +187,8 @@ def __init__( source=source, # type: ignore[arg-type] mode=mode, sink_source=sink_source, + enable_validation=enable_validation, + version=version, ) def get_feature_transformation(self) -> Optional[Transformation]: @@ -203,6 +209,35 @@ def get_feature_transformation(self) -> Optional[Transformation]: f"Unsupported transformation mode: {self.mode} for StreamFeatureView" ) + def _schema_or_udf_changed(self, other: "BaseFeatureView") -> bool: + """Check for StreamFeatureView schema/UDF changes.""" + if super()._schema_or_udf_changed(other): + return True + + if not isinstance(other, StreamFeatureView): + return True + + # UDF changes + if self.udf and other.udf: + self_code = getattr(self.udf, "__code__", None) + other_code = getattr(other.udf, "__code__", None) + if self_code and other_code: + if self_code.co_code != other_code.co_code: + return True + elif self.udf != other.udf: # One is None + return True + + if self.udf_string != other.udf_string: + return True + if self.aggregations != other.aggregations: + return True + if self.timestamp_field != other.timestamp_field: + return True + if self.mode != other.mode: + return True + + return False + def __eq__(self, other): if not isinstance(other, StreamFeatureView): raise TypeError("Comparisons should only involve StreamFeatureViews") @@ -233,15 +268,8 @@ def to_proto(self): meta = self.to_proto_meta() ttl_duration = self.get_ttl_duration() - batch_source_proto = None - if self.batch_source: - batch_source_proto = self.batch_source.to_proto() - batch_source_proto.data_source_class_type = f"{self.batch_source.__class__.__module__}.{self.batch_source.__class__.__name__}" - - stream_source_proto = None - if self.stream_source: - stream_source_proto = self.stream_source.to_proto() - stream_source_proto.data_source_class_type = f"{self.stream_source.__class__.__module__}.{self.stream_source.__class__.__name__}" + batch_source_proto = serialize_data_source(self.batch_source) + stream_source_proto = serialize_data_source(self.stream_source) udf_proto, feature_transformation = None, None if self.udf: @@ -260,10 +288,6 @@ def to_proto(self): user_defined_function=udf_proto_v2, ) - mode = ( - self.mode.value if isinstance(self.mode, TransformationMode) else self.mode - ) - # Serialize tiling configuration tiling_hop_size_duration = None if self.tiling_hop_size is not None: @@ -282,13 +306,15 @@ def to_proto(self): owner=self.owner, ttl=ttl_duration, online=self.online, - batch_source=batch_source_proto or None, - stream_source=stream_source_proto or None, + batch_source=batch_source_proto, + stream_source=stream_source_proto, timestamp_field=self.timestamp_field, aggregations=[agg.to_proto() for agg in self.aggregations], - mode=mode, + mode=mode_to_string(self.mode), enable_tiling=self.enable_tiling, tiling_hop_size=tiling_hop_size_duration, + enable_validation=self.enable_validation, + version=self.version, ) return StreamFeatureViewProto(spec=spec, meta=meta) @@ -350,6 +376,8 @@ def from_proto(cls, sfv_proto): and sfv_proto.spec.tiling_hop_size.ToNanoseconds() != 0 else None ), + enable_validation=sfv_proto.spec.enable_validation, + version=sfv_proto.spec.version or "latest", ) if batch_source: @@ -358,6 +386,16 @@ def from_proto(cls, sfv_proto): if stream_source: stream_feature_view.stream_source = stream_source + # Restore current_version_number from meta. + spec_version = sfv_proto.spec.version + cvn = sfv_proto.meta.current_version_number + if cvn > 0: + stream_feature_view.current_version_number = cvn + elif cvn == 0 and spec_version and spec_version.lower() != "latest": + stream_feature_view.current_version_number = 0 + else: + stream_feature_view.current_version_number = None + stream_feature_view.entities = list(sfv_proto.spec.entities) stream_feature_view.features = [ @@ -403,6 +441,8 @@ def __copy__(self): udf=self.udf, udf_string=self.udf_string, feature_transformation=self.feature_transformation, + enable_validation=self.enable_validation, + version=self.version, ) fv.entities = self.entities fv.features = copy.copy(self.features) @@ -428,6 +468,8 @@ def stream_feature_view( aggregations: Optional[List[Aggregation]] = None, mode: Optional[str] = "spark", timestamp_field: Optional[str] = "", + enable_validation: bool = False, + version: str = "latest", ): """ Creates an StreamFeatureView object with the given user function as udf. @@ -459,6 +501,8 @@ def decorator(user_function): aggregations=aggregations, mode=mode, timestamp_field=timestamp_field, + enable_validation=enable_validation, + version=version, ) functools.update_wrapper(wrapper=stream_feature_view_obj, wrapped=user_function) return stream_feature_view_obj diff --git a/sdk/python/feast/templates/athena/feature_repo/test_workflow.py b/sdk/python/feast/templates/athena/feature_repo/test_workflow.py index 8d6479da80e..8bbdb07f161 100644 --- a/sdk/python/feast/templates/athena/feature_repo/test_workflow.py +++ b/sdk/python/feast/templates/athena/feature_repo/test_workflow.py @@ -50,6 +50,7 @@ def test_end_to_end(): ], online=True, source=driver_hourly_stats, + version="latest", ) # apply repository diff --git a/sdk/python/feast/templates/aws/feature_repo/feature_definitions.py b/sdk/python/feast/templates/aws/feature_repo/feature_definitions.py index dd5a9c925b7..8d4faf4c74c 100644 --- a/sdk/python/feast/templates/aws/feature_repo/feature_definitions.py +++ b/sdk/python/feast/templates/aws/feature_repo/feature_definitions.py @@ -57,6 +57,7 @@ # Tags are user defined key/value pairs that are attached to each # feature view tags={"team": "driver_performance"}, + version="latest", ) # Define a request data source which encodes features / information only @@ -119,6 +120,7 @@ def transformed_conv_rate(inputs: pd.DataFrame) -> pd.DataFrame: online=True, source=driver_stats_push_source, # Changed from above tags={"team": "driver_performance"}, + version="latest", ) diff --git a/sdk/python/feast/templates/cassandra/feature_repo/feature_definitions.py b/sdk/python/feast/templates/cassandra/feature_repo/feature_definitions.py index 131f1bcaa61..21b2985409e 100644 --- a/sdk/python/feast/templates/cassandra/feature_repo/feature_definitions.py +++ b/sdk/python/feast/templates/cassandra/feature_repo/feature_definitions.py @@ -52,6 +52,7 @@ # Tags are user defined key/value pairs that are attached to each # feature view tags={"team": "driver_performance"}, + version="latest", ) # Define a request data source which encodes features / information only @@ -114,6 +115,7 @@ def transformed_conv_rate(inputs: pd.DataFrame) -> pd.DataFrame: online=True, source=driver_stats_push_source, # Changed from above tags={"team": "driver_performance"}, + version="latest", ) diff --git a/sdk/python/feast/templates/couchbase/feature_repo/feature_definitions.py b/sdk/python/feast/templates/couchbase/feature_repo/feature_definitions.py index 363ba3c4664..802f251ca5a 100644 --- a/sdk/python/feast/templates/couchbase/feature_repo/feature_definitions.py +++ b/sdk/python/feast/templates/couchbase/feature_repo/feature_definitions.py @@ -47,6 +47,7 @@ # Tags are user defined key/value pairs that are attached to each # feature view tags={"team": "driver_performance"}, + version="latest", ) # Define a request data source which encodes features / information only @@ -109,6 +110,7 @@ def transformed_conv_rate(inputs: pd.DataFrame) -> pd.DataFrame: online=True, source=driver_stats_push_source, # Changed from above tags={"team": "driver_performance"}, + version="latest", ) diff --git a/sdk/python/feast/templates/gcp/feature_repo/feature_definitions.py b/sdk/python/feast/templates/gcp/feature_repo/feature_definitions.py index 81e06c72018..5eda02ea5d2 100644 --- a/sdk/python/feast/templates/gcp/feature_repo/feature_definitions.py +++ b/sdk/python/feast/templates/gcp/feature_repo/feature_definitions.py @@ -61,6 +61,7 @@ # Tags are user defined key/value pairs that are attached to each # feature view tags={"team": "driver_performance"}, + version="latest", ) # Define a request data source which encodes features / information only @@ -123,6 +124,7 @@ def transformed_conv_rate(inputs: pd.DataFrame) -> pd.DataFrame: online=True, source=driver_stats_push_source, # Changed from above tags={"team": "driver_performance"}, + version="latest", ) diff --git a/sdk/python/feast/templates/hazelcast/feature_repo/feature_definitions.py b/sdk/python/feast/templates/hazelcast/feature_repo/feature_definitions.py index 131f1bcaa61..21b2985409e 100644 --- a/sdk/python/feast/templates/hazelcast/feature_repo/feature_definitions.py +++ b/sdk/python/feast/templates/hazelcast/feature_repo/feature_definitions.py @@ -52,6 +52,7 @@ # Tags are user defined key/value pairs that are attached to each # feature view tags={"team": "driver_performance"}, + version="latest", ) # Define a request data source which encodes features / information only @@ -114,6 +115,7 @@ def transformed_conv_rate(inputs: pd.DataFrame) -> pd.DataFrame: online=True, source=driver_stats_push_source, # Changed from above tags={"team": "driver_performance"}, + version="latest", ) diff --git a/sdk/python/feast/templates/hbase/feature_repo/feature_definitions.py b/sdk/python/feast/templates/hbase/feature_repo/feature_definitions.py index 131f1bcaa61..21b2985409e 100644 --- a/sdk/python/feast/templates/hbase/feature_repo/feature_definitions.py +++ b/sdk/python/feast/templates/hbase/feature_repo/feature_definitions.py @@ -52,6 +52,7 @@ # Tags are user defined key/value pairs that are attached to each # feature view tags={"team": "driver_performance"}, + version="latest", ) # Define a request data source which encodes features / information only @@ -114,6 +115,7 @@ def transformed_conv_rate(inputs: pd.DataFrame) -> pd.DataFrame: online=True, source=driver_stats_push_source, # Changed from above tags={"team": "driver_performance"}, + version="latest", ) diff --git a/sdk/python/feast/templates/local/feature_repo/feature_definitions.py b/sdk/python/feast/templates/local/feature_repo/feature_definitions.py index e2fd0a891cf..74199b42072 100644 --- a/sdk/python/feast/templates/local/feature_repo/feature_definitions.py +++ b/sdk/python/feast/templates/local/feature_repo/feature_definitions.py @@ -17,7 +17,7 @@ from feast.feature_logging import LoggingConfig from feast.infra.offline_stores.file_source import FileLoggingDestination from feast.on_demand_feature_view import on_demand_feature_view -from feast.types import Float32, Float64, Int64 +from feast.types import Float32, Float64, Int64, Json, Map, String, Struct # Define a project for the feature repo project = Project(name="%PROJECT_NAME%", description="A project for driver statistics") @@ -52,12 +52,27 @@ Field(name="conv_rate", dtype=Float32), Field(name="acc_rate", dtype=Float32), Field(name="avg_daily_trips", dtype=Int64, description="Average daily trips"), + Field( + name="driver_metadata", + dtype=Map, + description="Driver metadata as key-value pairs", + ), + Field( + name="driver_config", dtype=Json, description="Driver configuration as JSON" + ), + Field( + name="driver_profile", + dtype=Struct({"name": String, "age": String}), + description="Driver profile as a typed struct", + ), ], online=True, source=driver_stats_source, # Tags are user defined key/value pairs that are attached to each # feature view tags={"team": "driver_performance"}, + enable_validation=True, + version="latest", ) # Define a request data source which encodes features / information only @@ -119,10 +134,14 @@ def transformed_conv_rate(inputs: pd.DataFrame) -> pd.DataFrame: Field(name="conv_rate", dtype=Float32), Field(name="acc_rate", dtype=Float32), Field(name="avg_daily_trips", dtype=Int64), + Field(name="driver_metadata", dtype=Map), + Field(name="driver_config", dtype=Json), + Field(name="driver_profile", dtype=Struct({"name": String, "age": String})), ], online=True, source=driver_stats_push_source, # Changed from above tags={"team": "driver_performance"}, + version="latest", ) diff --git a/sdk/python/feast/templates/local/feature_repo/test_workflow.py b/sdk/python/feast/templates/local/feature_repo/test_workflow.py index eebeb113115..82175972321 100644 --- a/sdk/python/feast/templates/local/feature_repo/test_workflow.py +++ b/sdk/python/feast/templates/local/feature_repo/test_workflow.py @@ -1,3 +1,4 @@ +import json import subprocess from datetime import datetime @@ -45,6 +46,11 @@ def run_demo(): "conv_rate": [1.0], "acc_rate": [1.0], "avg_daily_trips": [1000], + "driver_metadata": [{"vehicle_type": "truck", "rating": "5.0"}], + "driver_config": [ + json.dumps({"max_distance_km": 500, "preferred_zones": ["north"]}) + ], + "driver_profile": [{"name": "driver_1001_updated", "age": "30"}], } ) print(event_df) @@ -115,6 +121,9 @@ def fetch_online_features(store, source: str = ""): else: features_to_fetch = [ "driver_hourly_stats:acc_rate", + "driver_hourly_stats:driver_metadata", + "driver_hourly_stats:driver_config", + "driver_hourly_stats:driver_profile", "transformed_conv_rate:conv_rate_plus_val1", "transformed_conv_rate:conv_rate_plus_val2", ] diff --git a/sdk/python/feast/templates/milvus/feature_repo/feature_definitions.py b/sdk/python/feast/templates/milvus/feature_repo/feature_definitions.py index e2fd0a891cf..31f3af3c26d 100644 --- a/sdk/python/feast/templates/milvus/feature_repo/feature_definitions.py +++ b/sdk/python/feast/templates/milvus/feature_repo/feature_definitions.py @@ -58,6 +58,7 @@ # Tags are user defined key/value pairs that are attached to each # feature view tags={"team": "driver_performance"}, + version="latest", ) # Define a request data source which encodes features / information only @@ -123,6 +124,7 @@ def transformed_conv_rate(inputs: pd.DataFrame) -> pd.DataFrame: online=True, source=driver_stats_push_source, # Changed from above tags={"team": "driver_performance"}, + version="latest", ) diff --git a/sdk/python/feast/templates/postgres/bootstrap.py b/sdk/python/feast/templates/postgres/bootstrap.py index 6ed13e4e39a..37daacb0df0 100644 --- a/sdk/python/feast/templates/postgres/bootstrap.py +++ b/sdk/python/feast/templates/postgres/bootstrap.py @@ -29,11 +29,25 @@ def bootstrap(): postgres_schema = click.prompt("Postgres schema", default="public") postgres_user = click.prompt("Postgres user") postgres_password = click.prompt("Postgres password", hide_input=True) + postgres_sslmode = click.prompt( + "Postgres sslmode (disable, allow, prefer, require, verify-ca, verify-full)", + default="require", + ) if click.confirm( 'Should I upload example data to Postgres (overwriting "feast_driver_hourly_stats" table)?', default=True, ): + config = PostgreSQLConfig( + host=postgres_host, + port=int(postgres_port), + database=postgres_database, + db_schema=postgres_schema, + user=postgres_user, + password=postgres_password, + sslmode=postgres_sslmode, + ) + db_connection = psycopg.connect( conninfo=( f"postgresql://{postgres_user}" @@ -42,6 +56,7 @@ def bootstrap(): f":{int(postgres_port)}" f"/{postgres_database}" ), + sslmode=postgres_sslmode, options=f"-c search_path={postgres_schema}", ) @@ -49,14 +64,7 @@ def bootstrap(): cur.execute('DROP TABLE IF EXISTS "feast_driver_hourly_stats"') df_to_postgres_table( - config=PostgreSQLConfig( - host=postgres_host, - port=int(postgres_port), - database=postgres_database, - db_schema=postgres_schema, - user=postgres_user, - password=postgres_password, - ), + config=config, df=driver_df, table_name="feast_driver_hourly_stats", ) @@ -67,6 +75,7 @@ def bootstrap(): replace_str_in_file(config_file, "DB_SCHEMA", postgres_schema) replace_str_in_file(config_file, "DB_USERNAME", postgres_user) replace_str_in_file(config_file, "DB_PASSWORD", postgres_password) + replace_str_in_file(config_file, "DB_SSLMODE", postgres_sslmode) if __name__ == "__main__": diff --git a/sdk/python/feast/templates/postgres/feature_repo/feature_definitions.py b/sdk/python/feast/templates/postgres/feature_repo/feature_definitions.py index 0d1783e1e5e..073f18e43f5 100644 --- a/sdk/python/feast/templates/postgres/feature_repo/feature_definitions.py +++ b/sdk/python/feast/templates/postgres/feature_repo/feature_definitions.py @@ -44,6 +44,7 @@ # Tags are user defined key/value pairs that are attached to each # feature view tags={"team": "driver_performance"}, + version="latest", ) # Define a request data source which encodes features / information only @@ -106,6 +107,7 @@ def transformed_conv_rate(inputs: pd.DataFrame) -> pd.DataFrame: online=True, source=driver_stats_push_source, # Changed from above tags={"team": "driver_performance"}, + version="latest", ) diff --git a/sdk/python/feast/templates/postgres/feature_repo/feature_store.yaml b/sdk/python/feast/templates/postgres/feature_repo/feature_store.yaml index a2fc2f51b61..ed80a5ff3e9 100644 --- a/sdk/python/feast/templates/postgres/feature_repo/feature_store.yaml +++ b/sdk/python/feast/templates/postgres/feature_repo/feature_store.yaml @@ -2,7 +2,7 @@ project: my_project provider: local registry: registry_type: sql - path: postgresql://DB_USERNAME:DB_PASSWORD@DB_HOST:DB_PORT/DB_NAME + path: postgresql://DB_USERNAME:DB_PASSWORD@DB_HOST:DB_PORT/DB_NAME?sslmode=DB_SSLMODE cache_ttl_seconds: 60 sqlalchemy_config_kwargs: echo: false @@ -15,6 +15,7 @@ online_store: db_schema: DB_SCHEMA user: DB_USERNAME password: DB_PASSWORD + sslmode: DB_SSLMODE offline_store: type: postgres host: DB_HOST @@ -23,4 +24,5 @@ offline_store: db_schema: DB_SCHEMA user: DB_USERNAME password: DB_PASSWORD + sslmode: DB_SSLMODE entity_key_serialization_version: 3 diff --git a/sdk/python/feast/templates/pytorch_nlp/feature_repo/example_repo.py b/sdk/python/feast/templates/pytorch_nlp/feature_repo/example_repo.py index ee49bea2899..80d1b9aa7bd 100644 --- a/sdk/python/feast/templates/pytorch_nlp/feature_repo/example_repo.py +++ b/sdk/python/feast/templates/pytorch_nlp/feature_repo/example_repo.py @@ -96,6 +96,7 @@ online=True, source=sentiment_source, tags={"team": "nlp", "domain": "sentiment_analysis"}, + version="latest", ) # Feature view for user-level aggregations @@ -123,6 +124,7 @@ online=True, source=sentiment_source, tags={"team": "nlp", "domain": "user_behavior"}, + version="latest", ) # Request source for real-time inference diff --git a/sdk/python/feast/templates/ray/feature_repo/feature_definitions.py b/sdk/python/feast/templates/ray/feature_repo/feature_definitions.py index 0b2df66de34..046ecb03ac7 100644 --- a/sdk/python/feast/templates/ray/feature_repo/feature_definitions.py +++ b/sdk/python/feast/templates/ray/feature_repo/feature_definitions.py @@ -59,6 +59,7 @@ online=True, source=driver_hourly_stats, tags={"team": "driver_performance", "processing": "ray"}, + version="latest", ) customer_daily_profile_view = FeatureView( @@ -73,6 +74,7 @@ online=True, source=customer_daily_profile, tags={"team": "customer_analytics", "processing": "ray"}, + version="latest", ) diff --git a/sdk/python/feast/templates/snowflake/feature_repo/driver_repo.py b/sdk/python/feast/templates/snowflake/feature_repo/driver_repo.py index dd05dac8455..7526d096ef5 100644 --- a/sdk/python/feast/templates/snowflake/feature_repo/driver_repo.py +++ b/sdk/python/feast/templates/snowflake/feature_repo/driver_repo.py @@ -64,6 +64,7 @@ # Tags are user defined key/value pairs that are attached to each # feature view tags={"team": "driver_performance"}, + version="latest", ) # Define a request data source which encodes features / information only @@ -126,6 +127,7 @@ def transformed_conv_rate(inputs: pd.DataFrame) -> pd.DataFrame: online=True, source=driver_stats_push_source, # Changed from above tags={"team": "driver_performance"}, + version="latest", ) diff --git a/sdk/python/feast/templates/spark/feature_repo/feature_definitions.py b/sdk/python/feast/templates/spark/feature_repo/feature_definitions.py index 8ad48f53fc4..e89d9b0fc1e 100644 --- a/sdk/python/feast/templates/spark/feature_repo/feature_definitions.py +++ b/sdk/python/feast/templates/spark/feature_repo/feature_definitions.py @@ -54,6 +54,7 @@ online=True, source=driver_hourly_stats, tags={}, + version="latest", ) customer_daily_profile_view = FeatureView( name="customer_daily_profile", @@ -67,6 +68,7 @@ online=True, source=customer_daily_profile, tags={}, + version="latest", ) driver_stats_fs = FeatureService( diff --git a/sdk/python/feast/type_map.py b/sdk/python/feast/type_map.py index b7b97b0a29a..691a398c8ef 100644 --- a/sdk/python/feast/type_map.py +++ b/sdk/python/feast/type_map.py @@ -15,6 +15,7 @@ import decimal import json import logging +import uuid as uuid_module from collections import defaultdict from datetime import datetime, timezone from typing import ( @@ -52,6 +53,7 @@ Int64Set, Map, MapList, + RepeatedValue, StringList, StringSet, ) @@ -67,7 +69,10 @@ logger = logging.getLogger(__name__) -def feast_value_type_to_python_type(field_value_proto: ProtoValue) -> Any: +def feast_value_type_to_python_type( + field_value_proto: ProtoValue, + feature_type: Optional[ValueType] = None, +) -> Any: """ Converts field value Proto to Dict and returns each field's Feast Value Type value in their respective Python value. @@ -83,6 +88,34 @@ def feast_value_type_to_python_type(field_value_proto: ProtoValue) -> Any: return None val = getattr(field_value_proto, val_attr) + # Handle JSON types — stored as strings but returned as parsed Python objects + if val_attr == "json_val": + try: + return json.loads(val) + except (json.JSONDecodeError, TypeError): + return val + elif val_attr == "json_list_val": + result = [] + for v in val.val: + if isinstance(v, str): + try: + result.append(json.loads(v)) + except (json.JSONDecodeError, TypeError): + result.append(v) + else: + result.append(v) + return result + + # Handle nested collection types (list_val, set_val) + if val_attr in ("list_val", "set_val"): + return _handle_nested_collection_value(val) + + # Handle Struct types — stored using Map proto, returned as dicts + if val_attr == "struct_val": + return _handle_map_value(val) + elif val_attr == "struct_list_val": + return _handle_map_list_value(val) + # Handle Map and MapList types FIRST (before generic list processing) if val_attr == "map_val": return _handle_map_value(val) @@ -124,6 +157,34 @@ def feast_value_type_to_python_type(field_value_proto: ProtoValue) -> Any: elif val_attr.endswith("_set_val") and val_attr != "unix_timestamp_set_val": val = set(val) + # Convert UUID values to uuid.UUID objects + if val_attr in ("uuid_val", "time_uuid_val"): + return uuid_module.UUID(val) if isinstance(val, str) else val + if val_attr in ("uuid_list_val", "time_uuid_list_val"): + return [uuid_module.UUID(v) if isinstance(v, str) else v for v in val] + if val_attr in ("uuid_set_val", "time_uuid_set_val"): + return {uuid_module.UUID(v) if isinstance(v, str) else v for v in val} + + # Convert DECIMAL values to decimal.Decimal objects + if val_attr == "decimal_val": + return decimal.Decimal(val) if isinstance(val, str) else val + if val_attr == "decimal_list_val": + return [decimal.Decimal(v) if isinstance(v, str) else v for v in val] + if val_attr == "decimal_set_val": + return {decimal.Decimal(v) if isinstance(v, str) else v for v in val} + + # Backward compatibility: handle UUIDs stored as string_val/string_list_val with feature_type hint + if feature_type in (ValueType.UUID, ValueType.TIME_UUID) and isinstance(val, str): + return uuid_module.UUID(val) + if feature_type in (ValueType.UUID_LIST, ValueType.TIME_UUID_LIST) and isinstance( + val, list + ): + return [uuid_module.UUID(v) if isinstance(v, str) else v for v in val] + if feature_type in (ValueType.UUID_SET, ValueType.TIME_UUID_SET) and isinstance( + val, set + ): + return {uuid_module.UUID(v) if isinstance(v, str) else v for v in val} + return val @@ -150,6 +211,18 @@ def _handle_map_list_value(map_list_message) -> List[Dict[str, Any]]: return result +def _handle_nested_collection_value(repeated_value) -> List[Any]: + """Handle nested collection proto (RepeatedValue containing Values). + + Each inner Value is itself a list/set proto. We recursively convert + each inner Value to a Python list/set via feast_value_type_to_python_type. + """ + result = [] + for inner_value in repeated_value.val: + result.append(feast_value_type_to_python_type(inner_value)) + return result + + def feast_value_type_to_pandas_type(value_type: ValueType) -> Any: value_type_to_pandas_type: Dict[ValueType, str] = { ValueType.FLOAT: "float", @@ -160,9 +233,12 @@ def feast_value_type_to_pandas_type(value_type: ValueType) -> Any: ValueType.BYTES: "bytes", ValueType.BOOL: "bool", ValueType.UNIX_TIMESTAMP: "datetime64[ns]", + ValueType.UUID: "str", + ValueType.TIME_UUID: "str", + ValueType.DECIMAL: "object", } if ( - value_type.name == "MAP" + value_type.name in ("MAP", "JSON", "STRUCT", "VALUE_LIST", "VALUE_SET") or value_type.name.endswith("_LIST") or value_type.name.endswith("_SET") ): @@ -223,6 +299,8 @@ def python_type_to_feast_value_type( "datetime64[ns, utc]": ValueType.UNIX_TIMESTAMP, "date": ValueType.UNIX_TIMESTAMP, "category": ValueType.STRING, + "uuid": ValueType.UUID, + "decimal": ValueType.DECIMAL, } if type_name in type_map: @@ -255,8 +333,9 @@ def python_type_to_feast_value_type( if not recurse: raise ValueError( f"Value type for field {name} is {type(value)} but " - f"recursion is not allowed. Array types can only be one level " - f"deep." + f"recursion is not allowed. Nested collection types cannot be " + f"inferred automatically; use an explicit Field dtype instead " + f"(e.g., dtype=Array(Array(Int32)))." ) # This is the final type which we infer from the list @@ -375,6 +454,31 @@ def _convert_value_type_str_to_value_type(type_str: str) -> ValueType: "FLOAT_LIST": ValueType.FLOAT_LIST, "BOOL_LIST": ValueType.BOOL_LIST, "UNIX_TIMESTAMP_LIST": ValueType.UNIX_TIMESTAMP_LIST, + "MAP": ValueType.MAP, + "MAP_LIST": ValueType.MAP_LIST, + "JSON": ValueType.JSON, + "JSON_LIST": ValueType.JSON_LIST, + "STRUCT": ValueType.STRUCT, + "STRUCT_LIST": ValueType.STRUCT_LIST, + "BYTES_SET": ValueType.BYTES_SET, + "STRING_SET": ValueType.STRING_SET, + "INT32_SET": ValueType.INT32_SET, + "INT64_SET": ValueType.INT64_SET, + "DOUBLE_SET": ValueType.DOUBLE_SET, + "FLOAT_SET": ValueType.FLOAT_SET, + "BOOL_SET": ValueType.BOOL_SET, + "UNIX_TIMESTAMP_SET": ValueType.UNIX_TIMESTAMP_SET, + "UUID": ValueType.UUID, + "TIME_UUID": ValueType.TIME_UUID, + "UUID_LIST": ValueType.UUID_LIST, + "TIME_UUID_LIST": ValueType.TIME_UUID_LIST, + "UUID_SET": ValueType.UUID_SET, + "TIME_UUID_SET": ValueType.TIME_UUID_SET, + "VALUE_LIST": ValueType.VALUE_LIST, + "VALUE_SET": ValueType.VALUE_SET, + "DECIMAL": ValueType.DECIMAL, + "DECIMAL_LIST": ValueType.DECIMAL_LIST, + "DECIMAL_SET": ValueType.DECIMAL_SET, } return type_map.get(type_str, ValueType.STRING) @@ -406,6 +510,21 @@ def _type_err(item, dtype): ValueType.STRING_LIST: (StringList, "string_list_val", [np.str_, str]), ValueType.BOOL_LIST: (BoolList, "bool_list_val", [np.bool_, bool]), ValueType.BYTES_LIST: (BytesList, "bytes_list_val", [np.bytes_, bytes]), + ValueType.UUID_LIST: ( + StringList, + "uuid_list_val", + [np.str_, str, uuid_module.UUID], + ), + ValueType.TIME_UUID_LIST: ( + StringList, + "time_uuid_list_val", + [np.str_, str, uuid_module.UUID], + ), + ValueType.DECIMAL_LIST: ( + StringList, + "decimal_list_val", + [np.str_, str, decimal.Decimal], + ), } PYTHON_SET_VALUE_TYPE_TO_PROTO_VALUE: Dict[ @@ -431,6 +550,17 @@ def _type_err(item, dtype): ValueType.STRING_SET: (StringSet, "string_set_val", [np.str_, str]), ValueType.BOOL_SET: (BoolSet, "bool_set_val", [np.bool_, bool]), ValueType.BYTES_SET: (BytesSet, "bytes_set_val", [np.bytes_, bytes]), + ValueType.UUID_SET: (StringSet, "uuid_set_val", [np.str_, str, uuid_module.UUID]), + ValueType.TIME_UUID_SET: ( + StringSet, + "time_uuid_set_val", + [np.str_, str, uuid_module.UUID], + ), + ValueType.DECIMAL_SET: ( + StringSet, + "decimal_set_val", + [np.str_, str, decimal.Decimal], + ), } PYTHON_SCALAR_VALUE_TYPE_TO_PROTO_VALUE: Dict[ @@ -456,6 +586,9 @@ def _type_err(item, dtype): ValueType.BYTES: ("bytes_val", lambda x: x, {bytes}), ValueType.IMAGE_BYTES: ("bytes_val", lambda x: x, {bytes}), ValueType.BOOL: ("bool_val", lambda x: x, {bool, np.bool_, int, np.int_}), + ValueType.UUID: ("uuid_val", lambda x: str(x), {str, uuid_module.UUID}), + ValueType.TIME_UUID: ("time_uuid_val", lambda x: str(x), {str, uuid_module.UUID}), + ValueType.DECIMAL: ("decimal_val", lambda x: str(x), {decimal.Decimal, str}), } @@ -483,6 +616,105 @@ def _python_datetime_to_int_timestamp( return int_timestamps +def _convert_timestamp_collection_to_proto( + values: List[Any], + proto_field: str, + proto_type: type, +) -> List[ProtoValue]: + """Convert timestamp collection values (list or set) to proto. + + Args: + values: List of timestamp collections to convert. + proto_field: The proto field name (e.g., 'unix_timestamp_list_val'). + proto_type: The proto type class (e.g., Int64List). + + Returns: + List of ProtoValue with converted timestamps. + """ + result = [] + for value in values: + if value is not None: + result.append( + ProtoValue( + **{ + proto_field: proto_type( + val=_python_datetime_to_int_timestamp(value) + ) + } # type: ignore + ) + ) + else: + result.append(ProtoValue()) + return result + + +def _convert_bool_collection_to_proto( + values: List[Any], + proto_field: str, + proto_type: type, +) -> List[ProtoValue]: + """Convert boolean collection values (list or set) to proto. + + ProtoValue does not support direct conversion of np.bool_, so we need to + explicitly convert each element to Python bool. + + Args: + values: List of boolean collections to convert. + proto_field: The proto field name (e.g., 'bool_list_val'). + proto_type: The proto type class (e.g., BoolList). + + Returns: + List of ProtoValue with converted booleans. + """ + result = [] + for value in values: + if value is not None: + result.append( + ProtoValue(**{proto_field: proto_type(val=[bool(e) for e in value])}) # type: ignore + ) + else: + result.append(ProtoValue()) + return result + + +def _validate_collection_item_types( + sample: Any, + valid_types: List[Type], + feast_value_type: ValueType, +) -> None: + """Validate that collection items match expected types. + + Args: + sample: A sample collection value to check. + valid_types: List of valid Python types for items. + feast_value_type: The Feast value type for error messages. + + Raises: + TypeError: If any item in sample is not a valid type. + """ + if sample is None: + return + if all(type(item) in valid_types for item in sample): + return + + # to_numpy() upcasts INT32/INT64 with NULL to Float64 automatically + int_collection_types = [ + ValueType.INT32_LIST, + ValueType.INT64_LIST, + ValueType.INT32_SET, + ValueType.INT64_SET, + ] + for item in sample: + if type(item) not in valid_types: + if feast_value_type in int_collection_types: + # Check if the float values are due to NULL upcast + if not any(np.isnan(i) for i in sample if isinstance(i, float)): + logger.error( + f"{feast_value_type.name} has NULL values. to_numpy() upcasts to Float64 automatically." + ) + raise _type_err(item, valid_types[0]) + + def _python_set_to_proto_values( feast_value_type: ValueType, values: List[Any] ) -> List[ProtoValue]: @@ -505,25 +737,20 @@ def _python_set_to_proto_values( ) # Convert set to list for proto (proto doesn't have native set type) - # We store unique values in a repeated field - def convert_set_to_list(value): + def convert_set_to_list(value: Any) -> Any: if value is None: return None - # If it's already a set, convert to list if isinstance(value, set): return list(value) - # If it's a list/tuple/ndarray, remove duplicates - elif isinstance(value, (list, tuple, np.ndarray)): + if isinstance(value, (list, tuple, np.ndarray)): return list(set(value)) - else: - return value + return value converted_values = [convert_set_to_list(v) for v in values] sample = next(filter(_non_empty_value, converted_values), None) # Bytes to array type conversion if isinstance(sample, (bytes, bytearray)): - # Bytes of an array containing elements of bytes not supported if feast_value_type == ValueType.BYTES_SET: raise _type_err(sample, ValueType.BYTES_SET) @@ -541,241 +768,395 @@ def convert_set_to_list(value): for list_item in json_values ] return [ - ( - ProtoValue(**{set_field_name: set_proto_type(val=v)}) # type: ignore - if v is not None - else ProtoValue() - ) + ProtoValue(**{set_field_name: set_proto_type(val=v)}) # type: ignore[arg-type] + if v is not None + else ProtoValue() for v in json_values ] raise _type_err(sample, set_valid_types[0]) - if sample is not None and not all(type(item) in set_valid_types for item in sample): - for item in sample: - if type(item) not in set_valid_types: - if feast_value_type in [ - ValueType.INT32_SET, - ValueType.INT64_SET, - ]: - if not any(np.isnan(item) for item in sample): - logger.error("Set of Int32 or Int64 type has NULL values.") - raise _type_err(item, set_valid_types[0]) + # Validate item types using shared helper + _validate_collection_item_types(sample, set_valid_types, feast_value_type) + # Handle special types using shared helpers if feast_value_type == ValueType.UNIX_TIMESTAMP_SET: - result = [] - for value in converted_values: - if value is not None: - result.append( - ProtoValue( - unix_timestamp_set_val=Int64Set( - val=_python_datetime_to_int_timestamp(value) # type: ignore - ) - ) - ) - else: - result.append(ProtoValue()) - return result + return _convert_timestamp_collection_to_proto( + converted_values, "unix_timestamp_set_val", Int64Set + ) if feast_value_type == ValueType.BOOL_SET: - result = [] - for value in converted_values: - if value is not None: - result.append( - ProtoValue( - **{ - set_field_name: set_proto_type( - val=[bool(e) for e in value] # type: ignore - ) - } - ) + return _convert_bool_collection_to_proto( + converted_values, set_field_name, set_proto_type + ) + + if feast_value_type in (ValueType.UUID_SET, ValueType.TIME_UUID_SET): + # uuid.UUID objects must be converted to str for StringSet proto. + return [ + ( + ProtoValue( + **{set_field_name: set_proto_type(val=[str(e) for e in value])} # type: ignore[arg-type, misc] ) - else: - result.append(ProtoValue()) - return result + if value is not None + else ProtoValue() + ) + for value in converted_values + ] + + if feast_value_type == ValueType.DECIMAL_SET: + # decimal.Decimal objects must be converted to str for StringSet proto. + return [ + ( + ProtoValue( + **{set_field_name: set_proto_type(val=[str(e) for e in value])} # type: ignore[arg-type, misc] + ) + if value is not None + else ProtoValue() + ) + for value in converted_values + ] + + # Generic set conversion return [ - ( - ProtoValue(**{set_field_name: set_proto_type(val=value)}) # type: ignore - if value is not None - else ProtoValue() - ) + ProtoValue(**{set_field_name: set_proto_type(val=value)}) # type: ignore[arg-type] + if value is not None + else ProtoValue() for value in converted_values ] -def _python_value_to_proto_value( - feast_value_type: ValueType, values: List[Any] +def _convert_list_values_to_proto( + feast_value_type: ValueType, + values: List[Any], + sample: Any, ) -> List[ProtoValue]: - """ - Converts a Python (native, pandas) value to a Feast Proto Value based - on a provided value type + """Convert list-type values to proto. Args: - feast_value_type: The target value type - values: List of Values that will be converted + feast_value_type: The target list value type. + values: List of list values to convert. + sample: First non-empty value for type checking. Returns: - List of Feast Value Proto + List of ProtoValue. """ - # Handle Map and MapList types first - if feast_value_type == ValueType.MAP: + if feast_value_type not in PYTHON_LIST_VALUE_TYPE_TO_PROTO_VALUE: + raise Exception(f"Unsupported list type: {feast_value_type}") + + proto_type, field_name, valid_types = PYTHON_LIST_VALUE_TYPE_TO_PROTO_VALUE[ + feast_value_type + ] + + # Bytes to array type conversion + if isinstance(sample, (bytes, bytearray)): + if feast_value_type == ValueType.BYTES_LIST: + raise _type_err(sample, ValueType.BYTES_LIST) + + json_sample = json.loads(sample) + if isinstance(json_sample, list): + json_values = [json.loads(value) for value in values] + if feast_value_type == ValueType.BOOL_LIST: + json_values = [ + [bool(item) for item in list_item] for list_item in json_values + ] + return [ + ProtoValue(**{field_name: proto_type(val=v)}) # type: ignore[arg-type] + for v in json_values + ] + raise _type_err(sample, valid_types[0]) + + # Validate item types using shared helper + _validate_collection_item_types(sample, valid_types, feast_value_type) + + # Handle special types using shared helpers + if feast_value_type == ValueType.UNIX_TIMESTAMP_LIST: + return _convert_timestamp_collection_to_proto( + values, "unix_timestamp_list_val", Int64List + ) + if feast_value_type == ValueType.BOOL_LIST: + return _convert_bool_collection_to_proto(values, field_name, proto_type) + + if feast_value_type in (ValueType.UUID_LIST, ValueType.TIME_UUID_LIST): + # uuid.UUID objects must be converted to str for StringList proto. return [ - ProtoValue(map_val=_python_dict_to_map_proto(value)) - if value is not None - else ProtoValue() + ( + ProtoValue( + **{field_name: proto_type(val=[str(e) for e in value])} # type: ignore[arg-type, misc] + ) + if value is not None + else ProtoValue() + ) for value in values ] - if feast_value_type == ValueType.MAP_LIST: + if feast_value_type == ValueType.DECIMAL_LIST: + # decimal.Decimal objects must be converted to str for StringList proto. + return [ + ( + ProtoValue( + **{field_name: proto_type(val=[str(e) for e in value])} # type: ignore[arg-type, misc] + ) + if value is not None + else ProtoValue() + ) + for value in values + ] + + # Generic list conversion + return [ + ProtoValue(**{field_name: proto_type(val=value)}) # type: ignore[arg-type] + if value is not None + else ProtoValue() + for value in values + ] + + +def _convert_scalar_values_to_proto( + feast_value_type: ValueType, + values: List[Any], + sample: Any, +) -> List[ProtoValue]: + """Convert scalar-type values to proto. + + Args: + feast_value_type: The target scalar value type. + values: List of scalar values to convert. + sample: First non-empty value for type checking. + + Returns: + List of ProtoValue. + """ + if sample is None: + # All input values are None + return [ProtoValue()] * len(values) + + if feast_value_type == ValueType.UNIX_TIMESTAMP: + int_timestamps = _python_datetime_to_int_timestamp(values) + return [ProtoValue(unix_timestamp_val=ts) for ts in int_timestamps] # type: ignore + + field_name, func, valid_scalar_types = PYTHON_SCALAR_VALUE_TYPE_TO_PROTO_VALUE[ + feast_value_type + ] + + # Validate scalar types + if valid_scalar_types: + if (sample == 0 or sample == 0.0) and feast_value_type != ValueType.BOOL: + # Numpy converts 0 to int, but column type may be float + allowed_types = {np.int64, int, np.float64, float, decimal.Decimal} + assert type(sample) in allowed_types, ( + f"Type `{type(sample)}` not in {allowed_types}" + ) + else: + assert type(sample) in valid_scalar_types, ( + f"Type `{type(sample)}` not in {valid_scalar_types}" + ) + + # Handle BOOL specially due to np.bool_ conversion requirement + if feast_value_type == ValueType.BOOL: return [ - ProtoValue(map_list_val=_python_list_to_map_list_proto(value)) - if value is not None + ProtoValue( + **{field_name: func(bool(value) if type(value) is np.bool_ else value)} + ) # type: ignore + if not pd.isnull(value) else ProtoValue() for value in values ] - # ToDo: make a better sample for type checks (more than one element) - sample = next(filter(_non_empty_value, values), None) # first not empty value + # Generic scalar conversion + out = [] + for value in values: + if isinstance(value, ProtoValue): + out.append(value) + elif not pd.isnull(value): + out.append(ProtoValue(**{field_name: func(value)})) + else: + out.append(ProtoValue()) + return out - # Detect list type and handle separately - if "list" in feast_value_type.name.lower(): - # Feature can be list but None is still valid - if feast_value_type in PYTHON_LIST_VALUE_TYPE_TO_PROTO_VALUE: - proto_type, field_name, valid_types = PYTHON_LIST_VALUE_TYPE_TO_PROTO_VALUE[ - feast_value_type - ] - # Bytes to array type conversion - if isinstance(sample, (bytes, bytearray)): - # Bytes of an array containing elements of bytes not supported - if feast_value_type == ValueType.BYTES_LIST: - raise _type_err(sample, ValueType.BYTES_LIST) - - json_sample = json.loads(sample) - if isinstance(json_sample, list): - json_values = [json.loads(value) for value in values] - if feast_value_type == ValueType.BOOL_LIST: - json_values = [ - [bool(item) for item in list_item] - for list_item in json_values - ] - return [ - ProtoValue(**{field_name: proto_type(val=v)}) # type: ignore - for v in json_values - ] - raise _type_err(sample, valid_types[0]) - - if sample is not None and not all( - type(item) in valid_types for item in sample - ): - # to_numpy() in utils._convert_arrow_to_proto() upcasts values of type Array of INT32 or INT64 with NULL values to Float64 automatically. - for item in sample: - if type(item) not in valid_types: - if feast_value_type in [ - ValueType.INT32_LIST, - ValueType.INT64_LIST, - ]: - if not any(np.isnan(item) for item in sample): - logger.error( - "Array of Int32 or Int64 type has NULL values. to_numpy() upcasts to Float64 automatically." - ) - raise _type_err(item, valid_types[0]) - - if feast_value_type == ValueType.UNIX_TIMESTAMP_LIST: - result = [] - for value in values: - if value is not None: - # ProtoValue does actually accept `np.int_` but the typing complains. - result.append( - ProtoValue( - unix_timestamp_list_val=Int64List( - val=_python_datetime_to_int_timestamp(value) # type: ignore - ) - ) - ) - else: - result.append(ProtoValue()) - return result - if feast_value_type == ValueType.BOOL_LIST: - # ProtoValue does not support conversion of np.bool_ so we need to convert it to support np.bool_. - result = [] - for value in values: - if value is not None: - result.append( - ProtoValue( - **{field_name: proto_type(val=[bool(e) for e in value])} # type: ignore - ) - ) - else: - result.append(ProtoValue()) - return result - return [ - ( - ProtoValue(**{field_name: proto_type(val=value)}) # type: ignore - if value is not None - else ProtoValue() - ) - for value in values - ] +def _python_value_to_proto_value( + feast_value_type: ValueType, values: List[Any] +) -> List[ProtoValue]: + """ + Converts a Python (native, pandas) value to a Feast Proto Value based + on a provided value type. - # Detect set type and handle separately - if "set" in feast_value_type.name.lower(): - return _python_set_to_proto_values(feast_value_type, values) + Args: + feast_value_type: The target value type + values: List of Values that will be converted - # Handle scalar types below - else: - if sample is None: - # all input values are None - return [ProtoValue()] * len(values) - - if feast_value_type == ValueType.UNIX_TIMESTAMP: - int_timestamps = _python_datetime_to_int_timestamp(values) - # ProtoValue does actually accept `np.int_` but the typing complains. - return [ProtoValue(unix_timestamp_val=ts) for ts in int_timestamps] # type: ignore - - ( - field_name, - func, - valid_scalar_types, - ) = PYTHON_SCALAR_VALUE_TYPE_TO_PROTO_VALUE[feast_value_type] - if valid_scalar_types: - if (sample == 0 or sample == 0.0) and feast_value_type != ValueType.BOOL: - # Numpy convert 0 to int. However, in the feature view definition, the type of column may be a float. - # So, if value is 0, type validation must pass if scalar_types are either int or float. - allowed_types = {np.int64, int, np.float64, float, decimal.Decimal} - assert type(sample) in allowed_types, ( - f"Type `{type(sample)}` not in {allowed_types}" - ) + Returns: + List of Feast Value Proto + """ + # Handle nested collection types (VALUE_LIST, VALUE_SET) + if feast_value_type in (ValueType.VALUE_LIST, ValueType.VALUE_SET): + return _convert_nested_collection_to_proto(feast_value_type, values) + + # Handle Map types + if feast_value_type == ValueType.MAP: + result = [] + for value in values: + if value is None: + result.append(ProtoValue()) else: - assert type(sample) in valid_scalar_types, ( - f"Type `{type(sample)}` not in {valid_scalar_types}" - ) - if feast_value_type == ValueType.BOOL: - # ProtoValue does not support conversion of np.bool_ so we need to convert it to support np.bool_. - return [ - ( - ProtoValue( - **{ - field_name: func( - bool(value) if type(value) is np.bool_ else value # type: ignore - ) - } + if isinstance(value, str): + value = json.loads(value) + if not isinstance(value, dict): + raise TypeError( + f"Expected dict for MAP type, got {type(value).__name__}: {value!r}" + ) + result.append(ProtoValue(map_val=_python_dict_to_map_proto(value))) + return result + + if feast_value_type == ValueType.MAP_LIST: + result = [] + for value in values: + if value is None: + result.append(ProtoValue()) + else: + if isinstance(value, str): + value = json.loads(value) + if not isinstance(value, list): + raise TypeError( + f"Expected list for MAP_LIST type, got {type(value).__name__}: {value!r}" ) - if not pd.isnull(value) - else ProtoValue() + result.append( + ProtoValue(map_list_val=_python_list_to_map_list_proto(value)) ) - for value in values - ] - if feast_value_type in PYTHON_SCALAR_VALUE_TYPE_TO_PROTO_VALUE: - out = [] - for value in values: - if isinstance(value, ProtoValue): - out.append(value) - elif not pd.isnull(value): - out.append(ProtoValue(**{field_name: func(value)})) + return result + + # Handle JSON type — serialize Python objects as JSON strings + if feast_value_type == ValueType.JSON: + result = [] + for value in values: + if value is None: + result.append(ProtoValue()) + else: + if isinstance(value, str): + try: + json.loads(value) + except (json.JSONDecodeError, TypeError) as e: + raise ValueError( + f"Invalid JSON string for JSON type: {e}" + ) from e + json_str = value else: - out.append(ProtoValue()) - return out + json_str = json.dumps(value) + result.append(ProtoValue(json_val=json_str)) + return result - raise Exception(f"Unsupported data type: ${str(type(values[0]))}") + if feast_value_type == ValueType.JSON_LIST: + result = [] + for value in values: + if value is None: + result.append(ProtoValue()) + else: + json_strings = [] + for v in value: + if isinstance(v, str): + try: + json.loads(v) + except (json.JSONDecodeError, TypeError) as e: + raise ValueError( + f"Invalid JSON string in JSON_LIST: {e}" + ) from e + json_strings.append(v) + else: + json_strings.append(json.dumps(v)) + result.append(ProtoValue(json_list_val=StringList(val=json_strings))) + return result + + # Handle Struct type — reuses Map proto for storage + if feast_value_type == ValueType.STRUCT: + result = [] + for value in values: + if value is None: + result.append(ProtoValue()) + else: + if isinstance(value, str): + value = json.loads(value) + if not isinstance(value, dict): + value = ( + dict(value) + if hasattr(value, "items") + else {"_value": str(value)} + ) + result.append(ProtoValue(struct_val=_python_dict_to_map_proto(value))) + return result + + if feast_value_type == ValueType.STRUCT_LIST: + result = [] + for value in values: + if value is None: + result.append(ProtoValue()) + else: + if isinstance(value, str): + value = json.loads(value) + result.append( + ProtoValue(struct_list_val=_python_list_to_map_list_proto(value)) + ) + return result + + # Get sample for type checking + sample = next(filter(_non_empty_value, values), None) + + # Dispatch to appropriate converter based on type category + type_name_lower = feast_value_type.name.lower() + + if "list" in type_name_lower: + return _convert_list_values_to_proto(feast_value_type, values, sample) + + if "set" in type_name_lower: + return _python_set_to_proto_values(feast_value_type, values) + + # Scalar types + if ( + feast_value_type in PYTHON_SCALAR_VALUE_TYPE_TO_PROTO_VALUE + or feast_value_type == ValueType.UNIX_TIMESTAMP + ): + return _convert_scalar_values_to_proto(feast_value_type, values, sample) + + raise Exception(f"Unsupported data type: {feast_value_type}") + + +def _convert_nested_collection_to_proto( + feast_value_type: ValueType, values: List[Any] +) -> List[ProtoValue]: + """Convert nested collection values (list-of-lists, list-of-sets, etc.) to proto.""" + val_attr = "list_val" if feast_value_type == ValueType.VALUE_LIST else "set_val" + + result = [] + for value in values: + if value is None: + result.append(ProtoValue()) + else: + inner_values = [] + for inner_collection in value: + if inner_collection is None: + inner_values.append(ProtoValue()) + else: + inner_list = list(inner_collection) + if len(inner_list) == 0: + # Empty inner collection: store as empty ProtoValue + inner_values.append(ProtoValue()) + elif any( + isinstance(item, (list, set, tuple, np.ndarray)) + for item in inner_list + ): + # Deeper nesting (3+ levels): recurse using VALUE_LIST + inner_proto = _convert_nested_collection_to_proto( + ValueType.VALUE_LIST, [inner_list] + ) + inner_values.append(inner_proto[0]) + else: + # Leaf level: wrap as a single list-typed Value + proto_vals = python_values_to_proto_values( + [inner_list], ValueType.UNKNOWN + ) + inner_values.append(proto_vals[0]) + repeated = RepeatedValue(val=inner_values) + proto = ProtoValue() + getattr(proto, val_attr).CopyFrom(repeated) + result.append(proto) + return result def _python_dict_to_map_proto(python_dict: Dict[str, Any]) -> Map: @@ -866,6 +1247,12 @@ def python_values_to_proto_values( "unix_timestamp_list_val": ValueType.UNIX_TIMESTAMP_LIST, "map_val": ValueType.MAP, "map_list_val": ValueType.MAP_LIST, + "json_val": ValueType.JSON, + "json_list_val": ValueType.JSON_LIST, + "struct_val": ValueType.STRUCT, + "struct_list_val": ValueType.STRUCT_LIST, + "list_val": ValueType.VALUE_LIST, + "set_val": ValueType.VALUE_SET, "int32_set_val": ValueType.INT32_SET, "int64_set_val": ValueType.INT64_SET, "double_set_val": ValueType.DOUBLE_SET, @@ -874,6 +1261,15 @@ def python_values_to_proto_values( "bytes_set_val": ValueType.BYTES_SET, "bool_set_val": ValueType.BOOL_SET, "unix_timestamp_set_val": ValueType.UNIX_TIMESTAMP_SET, + "uuid_set_val": ValueType.UUID_SET, + "time_uuid_set_val": ValueType.TIME_UUID_SET, + "uuid_val": ValueType.UUID, + "time_uuid_val": ValueType.TIME_UUID, + "uuid_list_val": ValueType.UUID_LIST, + "time_uuid_list_val": ValueType.TIME_UUID_LIST, + "decimal_val": ValueType.DECIMAL, + "decimal_list_val": ValueType.DECIMAL_LIST, + "decimal_set_val": ValueType.DECIMAL_SET, } VALUE_TYPE_TO_PROTO_VALUE_MAP: Dict[ValueType, str] = { @@ -901,10 +1297,20 @@ def pa_to_feast_value_type(pa_type_as_str: str) -> ValueType: is_list = False if pa_type_as_str.startswith("list", "") + inner_str = pa_type_as_str[len("list ValueType: "BOOL": ValueType.BOOL, "BOOLEAN": ValueType.BOOL, # legacy sql data type "NULL": ValueType.NULL, + "JSON": ValueType.JSON, + "STRUCT": ValueType.STRUCT, + "RECORD": ValueType.STRUCT, } value_type = type_map.get(bq_type_as_str, ValueType.STRING) @@ -974,6 +1383,7 @@ def mssql_to_feast_value_type(mssql_type_as_str: str) -> ValueType: "nchar": ValueType.STRING, "nvarchar": ValueType.STRING, "nvarchar(max)": ValueType.STRING, + "json": ValueType.JSON, "real": ValueType.FLOAT, "smallint": ValueType.INT32, "tinyint": ValueType.INT32, @@ -987,6 +1397,61 @@ def mssql_to_feast_value_type(mssql_type_as_str: str) -> ValueType: return type_map[mssql_type_as_str.lower()] +def oracle_to_feast_value_type(oracle_type_as_str: str) -> ValueType: + """Convert an Oracle/ibis type string to a Feast ValueType. + + Handles type strings returned by ibis schema introspection for the + Oracle backend (e.g. "int64", "float64", "string", "timestamp", "decimal") + as well as Oracle native type names. + """ + type_str = oracle_type_as_str.lower().strip() + + # Handle parameterized types like "decimal(10, 2)" + if "(" in type_str: + type_str = type_str.split("(")[0].strip() + + type_map: Dict[str, ValueType] = { + # Ibis types returned by Oracle backend + "int8": ValueType.INT32, + "int16": ValueType.INT32, + "int32": ValueType.INT32, + "int64": ValueType.INT64, + "float16": ValueType.FLOAT, + "float32": ValueType.FLOAT, + "float64": ValueType.DOUBLE, + "decimal": ValueType.DOUBLE, + "string": ValueType.STRING, + "binary": ValueType.BYTES, + "boolean": ValueType.BOOL, + "timestamp": ValueType.UNIX_TIMESTAMP, + "date": ValueType.UNIX_TIMESTAMP, + "time": ValueType.UNIX_TIMESTAMP, + "null": ValueType.NULL, + # Oracle native type names + "number": ValueType.DOUBLE, + "varchar2": ValueType.STRING, + "nvarchar2": ValueType.STRING, + "char": ValueType.STRING, + "nchar": ValueType.STRING, + "clob": ValueType.STRING, + "nclob": ValueType.STRING, + "blob": ValueType.BYTES, + "raw": ValueType.BYTES, + "long raw": ValueType.BYTES, + "long": ValueType.STRING, + "integer": ValueType.INT32, + "smallint": ValueType.INT32, + "float": ValueType.DOUBLE, + "double precision": ValueType.DOUBLE, + "real": ValueType.FLOAT, + "binary_float": ValueType.FLOAT, + "binary_double": ValueType.DOUBLE, + "interval": ValueType.UNIX_TIMESTAMP, + } + + return type_map.get(type_str, ValueType.STRING) + + def pa_to_mssql_type(pa_type: "pyarrow.DataType") -> str: # PyArrow types: https://arrow.apache.org/docs/python/api/datatypes.html # MS Sql types: https://docs.microsoft.com/en-us/sql/t-sql/data-types/data-types-transact-sql?view=sql-server-ver16 @@ -1003,6 +1468,13 @@ def pa_to_mssql_type(pa_type: "pyarrow.DataType") -> str: if pa_type_as_str.startswith("decimal"): return pa_type_as_str + if pa_type_as_str.startswith("map<"): + return "nvarchar(max)" + if pa_type_as_str == "large_string": + return "nvarchar(max)" + if pa_type_as_str.startswith("struct<") or pa_type_as_str.startswith("struct{"): + return "nvarchar(max)" + # We have to take into account how arrow types map to parquet types as well. # For example, null type maps to int32 in parquet, so we have to use int4 in Redshift. # Other mappings have also been adjusted accordingly. @@ -1043,7 +1515,8 @@ def redshift_to_feast_value_type(redshift_type_as_str: str) -> ValueType: "varchar": ValueType.STRING, "timestamp": ValueType.UNIX_TIMESTAMP, "timestamptz": ValueType.UNIX_TIMESTAMP, - "super": ValueType.BYTES, + "super": ValueType.MAP, + "json": ValueType.JSON, # skip date, geometry, hllsketch, time, timetz } @@ -1064,6 +1537,10 @@ def snowflake_type_to_feast_value_type(snowflake_type: str) -> ValueType: "TIMESTAMP_TZ": ValueType.UNIX_TIMESTAMP, "TIMESTAMP_LTZ": ValueType.UNIX_TIMESTAMP, "TIMESTAMP_NTZ": ValueType.UNIX_TIMESTAMP, + "VARIANT": ValueType.MAP, + "OBJECT": ValueType.MAP, + "ARRAY": ValueType.STRING_LIST, + "JSON": ValueType.JSON, } return type_map[snowflake_type] @@ -1086,6 +1563,15 @@ def _convert_value_name_to_snowflake_udf(value_name: str, project_name: str) -> "FLOAT_LIST": f"feast_{project_name}_snowflake_array_float_to_list_double_proto", "BOOL_LIST": f"feast_{project_name}_snowflake_array_boolean_to_list_bool_proto", "UNIX_TIMESTAMP_LIST": f"feast_{project_name}_snowflake_array_timestamp_to_list_unix_timestamp_proto", + "UUID": f"feast_{project_name}_snowflake_varchar_to_string_proto", + "TIME_UUID": f"feast_{project_name}_snowflake_varchar_to_string_proto", + "UUID_LIST": f"feast_{project_name}_snowflake_array_varchar_to_list_string_proto", + "TIME_UUID_LIST": f"feast_{project_name}_snowflake_array_varchar_to_list_string_proto", + "UUID_SET": f"feast_{project_name}_snowflake_array_varchar_to_list_string_proto", + "TIME_UUID_SET": f"feast_{project_name}_snowflake_array_varchar_to_list_string_proto", + "DECIMAL": f"feast_{project_name}_snowflake_varchar_to_string_proto", + "DECIMAL_LIST": f"feast_{project_name}_snowflake_array_varchar_to_list_string_proto", + "DECIMAL_SET": f"feast_{project_name}_snowflake_array_varchar_to_list_string_proto", } return name_map[value_name].upper() @@ -1110,6 +1596,15 @@ def pa_to_redshift_value_type(pa_type: "pyarrow.DataType") -> str: if pa_type_as_str.startswith("list"): return "super" + if pa_type_as_str.startswith("map<"): + return "super" + + if pa_type_as_str == "large_string": + return "super" + + if pa_type_as_str.startswith("struct<"): + return "super" + # We have to take into account how arrow types map to parquet types as well. # For example, null type maps to int32 in parquet, so we have to use int4 in Redshift. # Other mappings have also been adjusted accordingly. @@ -1146,8 +1641,7 @@ def _non_empty_value(value: Any) -> bool: def spark_to_feast_value_type(spark_type_as_str: str) -> ValueType: - # TODO not all spark types are convertible - # Current non-convertible types: interval, map, struct, structfield, binary + # Current non-convertible types: interval, struct, structfield, binary type_map: Dict[str, ValueType] = { "null": ValueType.UNKNOWN, "byte": ValueType.BYTES, @@ -1173,14 +1667,24 @@ def spark_to_feast_value_type(spark_type_as_str: str) -> ValueType: "array": ValueType.UNIX_TIMESTAMP_LIST, "array": ValueType.UNIX_TIMESTAMP_LIST, } - if spark_type_as_str.startswith("decimal"): - spark_type_as_str = "decimal" - if spark_type_as_str.startswith("array Iterator[np.dtype]: @@ -1207,6 +1711,12 @@ def arrow_to_pg_type(t_str: str) -> str: try: if t_str.startswith("timestamp") or t_str.startswith("datetime"): return "timestamptz" if "tz=" in t_str else "timestamp" + if t_str.startswith("map<"): + return "jsonb" + if t_str == "large_string": + return "jsonb" + if t_str.startswith("struct<") or t_str.startswith("struct{"): + return "jsonb" return { "null": "null", "bool": "boolean", @@ -1265,8 +1775,12 @@ def pg_type_to_feast_value_type(type_str: str) -> ValueType: "timestamp with time zone[]": ValueType.UNIX_TIMESTAMP_LIST, "numeric[]": ValueType.DOUBLE_LIST, "numeric": ValueType.DOUBLE, - "uuid": ValueType.STRING, - "uuid[]": ValueType.STRING_LIST, + "uuid": ValueType.UUID, + "uuid[]": ValueType.UUID_LIST, + "json": ValueType.MAP, + "jsonb": ValueType.MAP, + "json[]": ValueType.MAP_LIST, + "jsonb[]": ValueType.MAP_LIST, } value = ( type_map[type_str.lower()] @@ -1300,7 +1814,28 @@ def feast_value_type_to_pa( ValueType.BYTES_LIST: pyarrow.list_(pyarrow.binary()), ValueType.BOOL_LIST: pyarrow.list_(pyarrow.bool_()), ValueType.UNIX_TIMESTAMP_LIST: pyarrow.list_(pyarrow.timestamp(timestamp_unit)), + ValueType.MAP: pyarrow.map_(pyarrow.string(), pyarrow.string()), + ValueType.MAP_LIST: pyarrow.list_( + pyarrow.map_(pyarrow.string(), pyarrow.string()) + ), + ValueType.JSON: pyarrow.large_string(), + ValueType.JSON_LIST: pyarrow.list_(pyarrow.large_string()), + ValueType.STRUCT: pyarrow.struct([]), + ValueType.STRUCT_LIST: pyarrow.list_(pyarrow.struct([])), + # Placeholder: inner type is unknown from ValueType alone. + # Callers needing accurate inner types should use from_feast_to_pyarrow_type() with a FeastType. + ValueType.VALUE_LIST: pyarrow.list_(pyarrow.list_(pyarrow.string())), + ValueType.VALUE_SET: pyarrow.list_(pyarrow.list_(pyarrow.string())), ValueType.NULL: pyarrow.null(), + ValueType.UUID: pyarrow.string(), + ValueType.TIME_UUID: pyarrow.string(), + ValueType.UUID_LIST: pyarrow.list_(pyarrow.string()), + ValueType.TIME_UUID_LIST: pyarrow.list_(pyarrow.string()), + ValueType.UUID_SET: pyarrow.list_(pyarrow.string()), + ValueType.TIME_UUID_SET: pyarrow.list_(pyarrow.string()), + ValueType.DECIMAL: pyarrow.string(), + ValueType.DECIMAL_LIST: pyarrow.list_(pyarrow.string()), + ValueType.DECIMAL_SET: pyarrow.list_(pyarrow.string()), } return type_map[feast_type] @@ -1380,7 +1915,9 @@ def athena_to_feast_value_type(athena_type_as_str: str) -> ValueType: "varchar": ValueType.STRING, "string": ValueType.STRING, "timestamp": ValueType.UNIX_TIMESTAMP, - # skip date,decimal,array,map,struct + "json": ValueType.JSON, + "struct": ValueType.STRUCT, + "map": ValueType.MAP, } return type_map[athena_type_as_str.lower()] @@ -1398,6 +1935,18 @@ def pa_to_athena_value_type(pa_type: "pyarrow.DataType") -> str: if pa_type_as_str.startswith("python_values_to_proto_values"): return pa_type_as_str + if pa_type_as_str.startswith("list"): + return "array" + + if pa_type_as_str.startswith("map<"): + return "string" + + if pa_type_as_str == "large_string": + return "string" + + if pa_type_as_str.startswith("struct<"): + return "string" + # We have to take into account how arrow types map to parquet types as well. # For example, null type maps to int32 in parquet, so we have to use int4 in Redshift. # Other mappings have also been adjusted accordingly. @@ -1439,7 +1988,7 @@ def cb_columnar_type_to_feast_value_type(type_str: str) -> ValueType: "object": ValueType.UNKNOWN, "array": ValueType.UNKNOWN, "multiset": ValueType.UNKNOWN, - "uuid": ValueType.STRING, + "uuid": ValueType.UUID, } value = ( type_map[type_str.lower()] @@ -1465,8 +2014,12 @@ def convert_scalar_column( return series.astype("boolean") elif value_type == ValueType.STRING: return series.astype("string") + elif value_type in [ValueType.UUID, ValueType.TIME_UUID]: + return series.astype("string") elif value_type == ValueType.UNIX_TIMESTAMP: return pd.to_datetime(series, unit="s", errors="coerce") + elif value_type in (ValueType.JSON, ValueType.STRUCT, ValueType.MAP): + return series else: return series.astype(target_pandas_type) @@ -1482,6 +2035,18 @@ def convert_array_column(series: pd.Series, value_type: ValueType) -> pd.Series: ValueType.STRING_LIST: object, ValueType.BYTES_LIST: object, ValueType.UNIX_TIMESTAMP_LIST: "datetime64[s]", + ValueType.UUID_LIST: object, + ValueType.TIME_UUID_LIST: object, + ValueType.BYTES_SET: object, + ValueType.STRING_SET: object, + ValueType.INT32_SET: np.int32, + ValueType.INT64_SET: np.int64, + ValueType.FLOAT_SET: np.float32, + ValueType.DOUBLE_SET: np.float64, + ValueType.BOOL_SET: np.bool_, + ValueType.UNIX_TIMESTAMP_SET: "datetime64[s]", + ValueType.UUID_SET: object, + ValueType.TIME_UUID_SET: object, } target_dtype = base_type_map.get(value_type, object) diff --git a/sdk/python/feast/types.py b/sdk/python/feast/types.py index 922b3cce0ac..0a97037811b 100644 --- a/sdk/python/feast/types.py +++ b/sdk/python/feast/types.py @@ -25,6 +25,9 @@ "BYTES": "BYTES", "PDF_BYTES": "PDF_BYTES", "IMAGE_BYTES": "IMAGE_BYTES", + "UUID": "UUID", + "TIME_UUID": "TIME_UUID", + "DECIMAL": "DECIMAL", "STRING": "STRING", "INT32": "INT32", "INT64": "INT64", @@ -33,6 +36,7 @@ "BOOL": "BOOL", "UNIX_TIMESTAMP": "UNIX_TIMESTAMP", "MAP": "MAP", + "JSON": "JSON", } @@ -85,6 +89,10 @@ class PrimitiveFeastType(Enum): PDF_BYTES = 9 IMAGE_BYTES = 10 MAP = 11 + JSON = 12 + UUID = 13 + TIME_UUID = 14 + DECIMAL = 15 def to_value_type(self) -> ValueType: """ @@ -118,6 +126,10 @@ def __hash__(self): Float64 = PrimitiveFeastType.FLOAT64 UnixTimestamp = PrimitiveFeastType.UNIX_TIMESTAMP Map = PrimitiveFeastType.MAP +Json = PrimitiveFeastType.JSON +Uuid = PrimitiveFeastType.UUID +TimeUuid = PrimitiveFeastType.TIME_UUID +Decimal = PrimitiveFeastType.DECIMAL SUPPORTED_BASE_TYPES = [ Invalid, @@ -132,6 +144,10 @@ def __hash__(self): Float64, UnixTimestamp, Map, + Json, + Uuid, + TimeUuid, + Decimal, ] PRIMITIVE_FEAST_TYPES_TO_STRING = { @@ -147,6 +163,10 @@ def __hash__(self): "FLOAT64": "Float64", "UNIX_TIMESTAMP": "UnixTimestamp", "MAP": "Map", + "JSON": "Json", + "UUID": "Uuid", + "TIME_UUID": "TimeUuid", + "DECIMAL": "Decimal", } @@ -160,8 +180,12 @@ class Array(ComplexFeastType): base_type: Union[PrimitiveFeastType, ComplexFeastType] - def __init__(self, base_type: Union[PrimitiveFeastType, ComplexFeastType]): - if base_type not in SUPPORTED_BASE_TYPES: + def __init__(self, base_type: Union[PrimitiveFeastType, "ComplexFeastType"]): + # Allow Struct, Array, and Set as base types for nested collections + if ( + not isinstance(base_type, (Struct, Array, Set)) + and base_type not in SUPPORTED_BASE_TYPES + ): raise ValueError( f"Type {type(base_type)} is currently not supported as a base type for Array." ) @@ -169,11 +193,23 @@ def __init__(self, base_type: Union[PrimitiveFeastType, ComplexFeastType]): self.base_type = base_type def to_value_type(self) -> ValueType: + if isinstance(self.base_type, Struct): + return ValueType.STRUCT_LIST + if isinstance(self.base_type, (Array, Set)): + return ValueType.VALUE_LIST assert isinstance(self.base_type, PrimitiveFeastType) value_type_name = PRIMITIVE_FEAST_TYPES_TO_VALUE_TYPES[self.base_type.name] value_type_list_name = value_type_name + "_LIST" return ValueType[value_type_list_name] + def __eq__(self, other): + if isinstance(other, Array): + return self.base_type == other.base_type + return False + + def __hash__(self): + return hash(("Array", hash(self.base_type))) + def __str__(self): return f"Array({self.base_type})" @@ -189,25 +225,84 @@ class Set(ComplexFeastType): base_type: Union[PrimitiveFeastType, ComplexFeastType] def __init__(self, base_type: Union[PrimitiveFeastType, ComplexFeastType]): - # Sets do not support MAP as a base type - supported_set_types = [t for t in SUPPORTED_BASE_TYPES if t != Map] - if base_type not in supported_set_types: - raise ValueError( - f"Type {type(base_type)} is currently not supported as a base type for Set." - ) + # Allow Array and Set as base types for nested collections + if not isinstance(base_type, (Array, Set)): + # Sets do not support MAP as a base type + supported_set_types = [t for t in SUPPORTED_BASE_TYPES if t not in (Map,)] + if base_type not in supported_set_types: + raise ValueError( + f"Type {type(base_type)} is currently not supported as a base type for Set." + ) self.base_type = base_type def to_value_type(self) -> ValueType: + if isinstance(self.base_type, (Array, Set)): + return ValueType.VALUE_SET assert isinstance(self.base_type, PrimitiveFeastType) value_type_name = PRIMITIVE_FEAST_TYPES_TO_VALUE_TYPES[self.base_type.name] value_type_set_name = value_type_name + "_SET" return ValueType[value_type_set_name] + def __eq__(self, other): + if isinstance(other, Set): + return self.base_type == other.base_type + return False + + def __hash__(self): + return hash(("Set", hash(self.base_type))) + def __str__(self): return f"Set({self.base_type})" +class Struct(ComplexFeastType): + """ + A Struct represents a structured type with named, typed fields. + + Attributes: + fields: A dictionary mapping field names to their FeastTypes. + """ + + fields: Dict[str, Union[PrimitiveFeastType, "ComplexFeastType"]] + + def __init__( + self, fields: Dict[str, Union[PrimitiveFeastType, "ComplexFeastType"]] + ): + if not fields: + raise ValueError("Struct must have at least one field.") + self.fields = fields + + def to_value_type(self) -> ValueType: + return ValueType.STRUCT + + def to_pyarrow_type(self) -> pyarrow.DataType: + pa_fields = [] + for name, feast_type in self.fields.items(): + pa_type = from_feast_to_pyarrow_type(feast_type) + pa_fields.append(pyarrow.field(name, pa_type)) + return pyarrow.struct(pa_fields) + + def __str__(self): + field_strs = ", ".join( + f"{name}: {ftype}" for name, ftype in self.fields.items() + ) + return f"Struct({{{field_strs}}})" + + def __eq__(self, other): + if isinstance(other, Struct): + return self.fields == other.fields + return False + + def __hash__(self): + return hash( + ( + "Struct", + tuple((k, hash(v)) for k, v in sorted(self.fields.items())), + ) + ) + + FeastType = Union[ComplexFeastType, PrimitiveFeastType] VALUE_TYPES_TO_FEAST_TYPES: Dict["ValueType", FeastType] = { @@ -232,6 +327,8 @@ def __str__(self): ValueType.UNIX_TIMESTAMP_LIST: Array(UnixTimestamp), ValueType.MAP: Map, ValueType.MAP_LIST: Array(Map), + ValueType.JSON: Json, + ValueType.JSON_LIST: Array(Json), ValueType.BYTES_SET: Set(Bytes), ValueType.STRING_SET: Set(String), ValueType.INT32_SET: Set(Int32), @@ -240,6 +337,15 @@ def __str__(self): ValueType.FLOAT_SET: Set(Float32), ValueType.BOOL_SET: Set(Bool), ValueType.UNIX_TIMESTAMP_SET: Set(UnixTimestamp), + ValueType.UUID: Uuid, + ValueType.TIME_UUID: TimeUuid, + ValueType.UUID_LIST: Array(Uuid), + ValueType.TIME_UUID_LIST: Array(TimeUuid), + ValueType.UUID_SET: Set(Uuid), + ValueType.TIME_UUID_SET: Set(TimeUuid), + ValueType.DECIMAL: Decimal, + ValueType.DECIMAL_LIST: Array(Decimal), + ValueType.DECIMAL_SET: Set(Decimal), } FEAST_TYPES_TO_PYARROW_TYPES = { @@ -251,6 +357,11 @@ def __str__(self): Float64: pyarrow.float64(), # Note: datetime only supports microseconds https://github.com/python/cpython/blob/3.8/Lib/datetime.py#L1559 UnixTimestamp: pyarrow.timestamp("us", tz=_utc_now().tzname()), + Map: pyarrow.map_(pyarrow.string(), pyarrow.string()), + Json: pyarrow.large_string(), + Uuid: pyarrow.string(), + TimeUuid: pyarrow.string(), + Decimal: pyarrow.string(), } FEAST_VECTOR_TYPES: List[Union[ValueType, PrimitiveFeastType, ComplexFeastType]] = [ @@ -279,12 +390,29 @@ def from_feast_to_pyarrow_type(feast_type: FeastType) -> pyarrow.DataType: assert isinstance(feast_type, (ComplexFeastType, PrimitiveFeastType)), ( f"Expected FeastType, got {type(feast_type)}" ) + if isinstance(feast_type, Struct): + return feast_type.to_pyarrow_type() if isinstance(feast_type, PrimitiveFeastType): if feast_type in FEAST_TYPES_TO_PYARROW_TYPES: return FEAST_TYPES_TO_PYARROW_TYPES[feast_type] - elif isinstance(feast_type, ComplexFeastType): - # Handle the case when feast_type is an instance of ComplexFeastType - pass + elif isinstance(feast_type, Array): + base_type = feast_type.base_type + if isinstance(base_type, Struct): + return pyarrow.list_(base_type.to_pyarrow_type()) + if isinstance(base_type, (Array, Set)): + return pyarrow.list_(from_feast_to_pyarrow_type(base_type)) + if isinstance(base_type, PrimitiveFeastType): + if base_type == Map: + return pyarrow.list_(pyarrow.map_(pyarrow.string(), pyarrow.string())) + if base_type in FEAST_TYPES_TO_PYARROW_TYPES: + return pyarrow.list_(FEAST_TYPES_TO_PYARROW_TYPES[base_type]) + elif isinstance(feast_type, Set): + base_type = feast_type.base_type + if isinstance(base_type, (Array, Set)): + return pyarrow.list_(from_feast_to_pyarrow_type(base_type)) + if isinstance(base_type, PrimitiveFeastType): + if base_type in FEAST_TYPES_TO_PYARROW_TYPES: + return pyarrow.list_(FEAST_TYPES_TO_PYARROW_TYPES[base_type]) raise ValueError(f"Could not convert Feast type {feast_type} to PyArrow type.") @@ -304,6 +432,21 @@ def from_value_type( if value_type in VALUE_TYPES_TO_FEAST_TYPES: return VALUE_TYPES_TO_FEAST_TYPES[value_type] + # Struct types cannot be looked up from the dict because they require + # field definitions. Return a default placeholder Struct that can be + # enriched later from Field tags / schema metadata. + if value_type == ValueType.STRUCT: + return Struct({"_value": String}) + if value_type == ValueType.STRUCT_LIST: + return Array(Struct({"_value": String})) + + # Nested collection types use placeholder inner types. + # Real inner type is restored from Field tags during deserialization. + if value_type == ValueType.VALUE_LIST: + return Array(Array(String)) + if value_type == ValueType.VALUE_SET: + return Set(Array(String)) + raise ValueError(f"Could not convert value type {value_type} to FeastType.") @@ -322,6 +465,18 @@ def from_feast_type( Raises: ValueError: The conversion could not be performed. """ + # Handle Struct types directly since they are not in the dict + if isinstance(feast_type, Struct): + return ValueType.STRUCT + if isinstance(feast_type, Array) and isinstance(feast_type.base_type, Struct): + return ValueType.STRUCT_LIST + + # Handle nested collection types + if isinstance(feast_type, Array) and isinstance(feast_type.base_type, (Array, Set)): + return ValueType.VALUE_LIST + if isinstance(feast_type, Set) and isinstance(feast_type.base_type, (Array, Set)): + return ValueType.VALUE_SET + if feast_type in VALUE_TYPES_TO_FEAST_TYPES.values(): return list(VALUE_TYPES_TO_FEAST_TYPES.keys())[ list(VALUE_TYPES_TO_FEAST_TYPES.values()).index(feast_type) diff --git a/sdk/python/feast/utils.py b/sdk/python/feast/utils.py index ebdd56929bb..3f9fcc6525b 100644 --- a/sdk/python/feast/utils.py +++ b/sdk/python/feast/utils.py @@ -4,7 +4,7 @@ import typing import warnings from collections import Counter, defaultdict -from datetime import datetime, timezone +from datetime import datetime, timedelta, timezone from pathlib import Path from typing import ( Any, @@ -45,7 +45,7 @@ from feast.protos.feast.types.Value_pb2 import RepeatedValue as RepeatedValueProto from feast.protos.feast.types.Value_pb2 import Value as ValueProto from feast.type_map import python_values_to_proto_values -from feast.types import ComplexFeastType, PrimitiveFeastType, from_feast_to_pyarrow_type +from feast.types import ComplexFeastType, PrimitiveFeastType from feast.value_type import ValueType from feast.version import get_version @@ -60,6 +60,55 @@ USER_AGENT = "{}/{}".format(APPLICATION_NAME, get_version()) +def _parse_feature_ref(ref: str) -> Tuple[str, Optional[int], str]: + """Parse 'fv_name@version:feature' into (fv_name, version_number, feature_name). + + If no @version is present, version_number is None (meaning 'latest'). + Examples: + 'driver_stats:trips' -> ('driver_stats', None, 'trips') + 'driver_stats@v2:trips' -> ('driver_stats', 2, 'trips') + 'driver_stats@latest:trips' -> ('driver_stats', None, 'trips') + """ + import re + + colon_idx = ref.find(":") + if colon_idx < 0: + raise ValueError( + f"Invalid feature reference '{ref}'. Expected format: ':' " + f"or '@:'" + ) + + fv_part = ref[:colon_idx] + feature_name = ref[colon_idx + 1 :] + + at_idx = fv_part.find("@") + if at_idx < 0: + return (fv_part, None, feature_name) + + fv_name = fv_part[:at_idx] + version_str = fv_part[at_idx + 1 :] + + if not version_str or version_str.lower() == "latest": + return (fv_name, None, feature_name) + + # Parse version number from formats like "v2", "V2" + match = re.match(r"^[vV](\d+)$", version_str) + if not match: + # Not a recognized version format — treat entire fv_part as the name + return (fv_part, None, feature_name) + + return (fv_name, int(match.group(1)), feature_name) + + +def _strip_version_from_ref(ref: str) -> str: + """Strip @version from a feature reference, returning 'fv_name:feature'. + + Used to produce clean refs for output column naming. + """ + fv_name, _, feature_name = _parse_feature_ref(ref) + return f"{fv_name}:{feature_name}" + + def get_user_agent(): return USER_AGENT @@ -72,6 +121,37 @@ def make_tzaware(t: datetime) -> datetime: return t +def compute_non_entity_date_range( + feature_views: List["FeatureView"], + start_date: Optional[datetime] = None, + end_date: Optional[datetime] = None, + default_window_days: int = 30, +) -> Tuple[datetime, datetime]: + if end_date is None: + end_date = datetime.now(tz=timezone.utc) + else: + end_date = make_tzaware(end_date) + + if start_date is None: + max_ttl_seconds = max( + ( + int(fv.ttl.total_seconds()) + for fv in feature_views + if fv.ttl and isinstance(fv.ttl, timedelta) + ), + default=0, + ) + start_date = end_date - timedelta( + seconds=max_ttl_seconds + if max_ttl_seconds > 0 + else default_window_days * 86400 + ) + else: + start_date = make_tzaware(start_date) + + return start_date, end_date + + def make_df_tzaware(t: pd.DataFrame) -> pd.DataFrame: """Make all datetime type columns tzaware; leave everything else intact.""" df = t.copy() # don't modify incoming dataframe inplace @@ -118,9 +198,12 @@ def _get_requested_feature_views_to_features_dict( ) for ref in feature_refs: - ref_parts = ref.split(":") - feature_view_from_ref = ref_parts[0] - feature_from_ref = ref_parts[1] + fv_name, version_num, feature_from_ref = _parse_feature_ref(ref) + # Build the key that matches projection.name_to_use() + if version_num is not None: + feature_view_from_ref = f"{fv_name}@v{version_num}" + else: + feature_view_from_ref = fv_name found = False for fv in feature_views: @@ -152,6 +235,11 @@ def _get_column_names( and reverse-mapped created timestamp column that will be passed into the query to the offline store. """ + if feature_view.batch_source is None: + raise ValueError( + f"Feature view '{feature_view.name}' has no batch_source and cannot be used for offline retrieval." + ) + # if we have mapped fields, use the original field names in the call to the offline store timestamp_field = feature_view.batch_source.timestamp_field @@ -265,6 +353,58 @@ def _coerce_datetime(ts): return ts +def _columns_to_proto_values( + table: pyarrow.RecordBatch, + columns: List[Tuple[str, ValueType]], + allow_missing: bool = False, +) -> Dict[str, List[ValueProto]]: + """Convert table columns to proto values dict. + + Args: + table: PyArrow RecordBatch containing the data. + columns: List of (column_name, value_type) tuples to convert. + allow_missing: If True, skip columns not found in table. If False, raise ValueError. + + Returns: + Dict mapping column names to lists of ValueProto. + """ + result: Dict[str, List[ValueProto]] = {} + for column, value_type in columns: + if column in table.column_names: + result[column] = python_values_to_proto_values( + table.column(column).to_numpy(zero_copy_only=False), value_type + ) + elif not allow_missing: + raise ValueError(f"Column {column} not found in table") + return result + + +def _build_entity_keys( + num_rows: int, + join_keys: Dict[str, ValueType], + proto_values: Dict[str, List[ValueProto]], +) -> List[EntityKeyProto]: + """Build entity key protos for each row. + + Args: + num_rows: Number of rows to generate entity keys for. + join_keys: Dict mapping join key names to their value types. + proto_values: Dict mapping column names to lists of ValueProto values. + + Returns: + List of EntityKeyProto, one per row. + """ + return [ + EntityKeyProto( + join_keys=list(join_keys.keys()), + entity_values=[ + proto_values[k][idx] for k in join_keys if k in proto_values + ], + ) + for idx in range(num_rows) + ] + + def _convert_arrow_to_proto( table: Union[pyarrow.Table, pyarrow.RecordBatch], feature_view: Union["FeatureView", "BaseFeatureView", "OnDemandFeatureView"], @@ -290,25 +430,21 @@ def _convert_arrow_fv_to_proto( if isinstance(table, pyarrow.Table): table = table.to_batches()[0] + if feature_view.batch_source is None: + raise ValueError( + f"Feature view '{feature_view.name}' has no batch_source and cannot be converted to proto." + ) + # TODO: This will break if the feature view has aggregations or transformations columns = [ (field.name, field.dtype.to_value_type()) for field in feature_view.features ] + list(join_keys.items()) - proto_values_by_column = { - column: python_values_to_proto_values( - table.column(column).to_numpy(zero_copy_only=False), value_type - ) - for column, value_type in columns - } + proto_values_by_column = _columns_to_proto_values( + table, columns, allow_missing=False + ) - entity_keys = [ - EntityKeyProto( - join_keys=join_keys, - entity_values=[proto_values_by_column[k][idx] for k in join_keys], - ) - for idx in range(table.num_rows) - ] + entity_keys = _build_entity_keys(table.num_rows, join_keys, proto_values_by_column) # Serialize the features per row feature_dict = { @@ -356,62 +492,36 @@ def _convert_arrow_odfv_to_proto( (field.name, field.dtype.to_value_type()) for field in feature_view.features ] + list(join_keys.items()) - proto_values_by_column = { - column: python_values_to_proto_values( - table.column(column).to_numpy(zero_copy_only=False), value_type - ) - for column, value_type in columns - if column in table.column_names - } + # Convert columns that exist in the table + proto_values_by_column = _columns_to_proto_values( + table, columns, allow_missing=True + ) - # Ensure join keys are included in proto_values_by_column, but check if they exist first + # Ensure join keys are included, creating null values if missing from table for join_key, value_type in join_keys.items(): if join_key not in proto_values_by_column: - # Check if the join key exists in the table before trying to access it if join_key in table.column_names: proto_values_by_column[join_key] = python_values_to_proto_values( table.column(join_key).to_numpy(zero_copy_only=False), value_type ) else: - # Create null/default values if the join key isn't in the table - null_column = [None] * table.num_rows + # Create null proto values directly (no need to build a PyArrow array) proto_values_by_column[join_key] = python_values_to_proto_values( - null_column, value_type + [None] * table.num_rows, value_type ) - # Adding On Demand Features + # Cache column names set to avoid recreating list in loop + column_names = {c[0] for c in columns} + + # Adding On Demand Features that are missing from proto_values for feature in feature_view.features: - if ( - feature.name in [c[0] for c in columns] - and feature.name not in proto_values_by_column - ): - # initializing the column as null - null_column = pyarrow.array( - [None] * table.num_rows, - type=from_feast_to_pyarrow_type(feature.dtype), - ) - updated_table = pyarrow.RecordBatch.from_arrays( - table.columns + [null_column], - schema=table.schema.append( - pyarrow.field(feature.name, null_column.type) # type: ignore[attr-defined] - ), - ) + if feature.name in column_names and feature.name not in proto_values_by_column: + # Create null proto values directly (more efficient than building PyArrow array) proto_values_by_column[feature.name] = python_values_to_proto_values( - updated_table.column(feature.name).to_numpy(zero_copy_only=False), - feature.dtype.to_value_type(), + [None] * table.num_rows, feature.dtype.to_value_type() ) - entity_keys = [ - EntityKeyProto( - join_keys=join_keys, - entity_values=[ - proto_values_by_column[k][idx] - for k in join_keys - if k in proto_values_by_column - ], - ) - for idx in range(table.num_rows) - ] + entity_keys = _build_entity_keys(table.num_rows, join_keys, proto_values_by_column) # Serialize the features per row feature_dict = { @@ -420,7 +530,7 @@ def _convert_arrow_odfv_to_proto( if feature.name in proto_values_by_column } if feature_view.write_to_online_store: - table_columns = [col.name for col in table.schema] + table_columns = {col.name for col in table.schema} for feature in feature_view.schema: if feature.name not in feature_dict and feature.name in table_columns: feature_dict[feature.name] = proto_values_by_column[feature.name] @@ -428,11 +538,10 @@ def _convert_arrow_odfv_to_proto( features = [dict(zip(feature_dict, vars)) for vars in zip(*feature_dict.values())] # We need to artificially add event_timestamps and created_timestamps - event_timestamps = [] - timestamp_values = pd.to_datetime([_utc_now() for i in range(table.num_rows)]) - - for val in timestamp_values: - event_timestamps.append(_coerce_datetime(val)) + now = _utc_now() + event_timestamps = [ + _coerce_datetime(pd.Timestamp(now)) for _ in range(table.num_rows) + ] # setting them equivalent created_timestamps = event_timestamps @@ -467,7 +576,7 @@ def _validate_feature_refs(feature_refs: List[str], full_feature_names: bool = F ref for ref, occurrences in Counter(feature_refs).items() if occurrences > 1 ] else: - feature_names = [ref.split(":")[1] for ref in feature_refs] + feature_names = [_parse_feature_ref(ref)[2] for ref in feature_refs] collided_feature_names = [ ref for ref, occurrences in Counter(feature_names).items() @@ -514,7 +623,12 @@ def _group_feature_refs( on_demand_view_features = defaultdict(set) for ref in features: - view_name, feat_name = ref.split(":") + fv_name, version_num, feat_name = _parse_feature_ref(ref) + # Build the key that matches projection.name_to_use() + if version_num is not None: + view_name = f"{fv_name}@v{version_num}" + else: + view_name = fv_name if view_name in view_index: if hasattr(view_index[view_name], "write_to_online_store"): tmp_feat_name = [ @@ -551,30 +665,6 @@ def _group_feature_refs( return fvs_result, odfvs_result -def construct_response_feature_vector( - values_vector: Iterable[Any], - statuses_vector: Iterable[Any], - timestamp_vector: Iterable[Any], - mapping_indexes: Iterable[List[int]], - output_len: int, -) -> GetOnlineFeaturesResponse.FeatureVector: - values_output: Iterable[Any] = [None] * output_len - statuses_output: Iterable[Any] = [None] * output_len - timestamp_output: Iterable[Any] = [None] * output_len - - for i, destinations in enumerate(mapping_indexes): - for idx in destinations: - values_output[idx] = values_vector[i] # type: ignore[index] - statuses_output[idx] = statuses_vector[i] # type: ignore[index] - timestamp_output[idx] = timestamp_vector[i] # type: ignore[index] - - return GetOnlineFeaturesResponse.FeatureVector( - values=values_output, - statuses=statuses_output, - event_timestamps=timestamp_output, - ) - - def _apply_aggregations_to_response( response_data: Union[pyarrow.Table, Dict[str, List[Any]]], aggregations, @@ -636,6 +726,7 @@ def _augment_response_with_on_demand_transforms( feature_refs: List[str], requested_on_demand_feature_views: List["OnDemandFeatureView"], full_feature_names: bool, + feature_types: Optional[Dict[str, "ValueType"]] = None, ): """Computes on demand feature values and adds them to the result rows. @@ -658,7 +749,7 @@ def _augment_response_with_on_demand_transforms( odfv_feature_refs = defaultdict(list) for feature_ref in feature_refs: - view_name, feature_name = feature_ref.split(":") + view_name, _, feature_name = _parse_feature_ref(feature_ref) if view_name in requested_odfv_feature_names: odfv_feature_refs[view_name].append( f"{requested_odfv_map[view_name].projection.name_to_use()}__{feature_name}" @@ -666,15 +757,33 @@ def _augment_response_with_on_demand_transforms( else feature_name ) - initial_response = OnlineResponse(online_features_response) + initial_response = OnlineResponse( + online_features_response, feature_types=feature_types + ) initial_response_arrow: Optional[pyarrow.Table] = None initial_response_dict: Optional[Dict[str, List[Any]]] = None + def _is_metrics_active(): + try: + from feast.metrics import _config + + return _config.online_features + except Exception: + return False + + _metrics_active = _is_metrics_active() + # Apply on demand transformations and augment the result rows odfv_result_names = set() for odfv_name, _feature_refs in odfv_feature_refs.items(): odfv = requested_odfv_map[odfv_name] if not odfv.write_to_online_store: + _should_track = _metrics_active and getattr(odfv, "track_metrics", False) + if _should_track: + import time as _time + + _transform_start = _time.monotonic() + # Apply aggregations if configured. if odfv.aggregations: if odfv.mode == "python": @@ -695,11 +804,12 @@ def _augment_response_with_on_demand_transforms( odfv.entities, odfv.mode, ) + continue # Apply transformation. Note: aggregations and transformation configs are mutually exclusive # TODO: Fix to make it work for having both aggregation and transformation # ticket: https://github.com/feast-dev/feast/issues/5689 - elif odfv.mode == "python": + if odfv.mode == "python": if initial_response_dict is None: initial_response_dict = initial_response.to_dict() transformed_features_dict: Dict[str, List[Any]] = odfv.transform_dict( @@ -716,6 +826,13 @@ def _augment_response_with_on_demand_transforms( f"Invalid OnDemandFeatureMode: {odfv.mode}. Expected one of 'pandas', 'python', or 'substrait'." ) + if _should_track: + from feast.metrics import track_transformation + + track_transformation( + odfv_name, odfv.mode, _time.monotonic() - _transform_start + ) + transformed_features = ( transformed_features_dict if odfv.mode == "python" @@ -775,13 +892,20 @@ def _get_entity_maps( ) -> Tuple[Dict[str, str], Dict[str, ValueType], Set[str]]: # TODO(felixwang9817): Support entities that have different types for different feature views. entities = registry.list_entities(project, allow_cache=True) + + entity_by_name: Dict[str, "Entity"] = {entity.name: entity for entity in entities} + entity_name_to_join_key_map: Dict[str, str] = {} entity_type_map: Dict[str, ValueType] = {} for entity in entities: entity_name_to_join_key_map[entity.name] = entity.join_key for feature_view in feature_views: for entity_name in feature_view.entities: - entity = registry.get_entity(entity_name, project, allow_cache=True) + entity = entity_by_name.get(entity_name) + if entity is None: + from feast.errors import EntityNotFoundException + + raise EntityNotFoundException(entity_name, project=project) # User directly uses join_key as the entity reference in the entity_rows for the # entity mapping case. entity_name = feature_view.projection.join_key_map.get( @@ -984,98 +1108,6 @@ def ensure_request_data_values_exist( raise RequestDataNotFoundInEntityRowsException(feature_names=missing_features) -def _populate_response_from_feature_data( - feature_data: Iterable[ - Tuple[ - Iterable[Timestamp], Iterable["FieldStatus.ValueType"], Iterable[ValueProto] - ] - ], - indexes: Iterable[List[int]], - online_features_response: GetOnlineFeaturesResponse, - full_feature_names: bool, - requested_features: Iterable[str], - table: "FeatureView", - output_len: int, -): - """Populate the GetOnlineFeaturesResponse with feature data. - - This method assumes that `_read_from_online_store` returns data for each - combination of Entities in `entity_rows` in the same order as they - are provided. - - Args: - feature_data: A list of data in Protobuf form which was retrieved from the OnlineStore. - indexes: A list of indexes which should be the same length as `feature_data`. Each list - of indexes corresponds to a set of result rows in `online_features_response`. - online_features_response: The object to populate. - full_feature_names: A boolean that provides the option to add the feature view prefixes to the feature names, - changing them from the format "feature" to "feature_view__feature" (e.g., "daily_transactions" changes to - "customer_fv__daily_transactions"). - requested_features: The names of the features in `feature_data`. This should be ordered in the same way as the - data in `feature_data`. - table: The FeatureView that `feature_data` was retrieved from. - output_len: The number of result rows in `online_features_response`. - """ - # Add the feature names to the response. - table_name = table.projection.name_to_use() - requested_feature_refs = [ - f"{table_name}__{feature_name}" if full_feature_names else feature_name - for feature_name in requested_features - ] - online_features_response.metadata.feature_names.val.extend(requested_feature_refs) - - # Process each feature vector in a single pass - for timestamp_vector, statuses_vector, values_vector in feature_data: - response_vector = construct_response_feature_vector( - values_vector, statuses_vector, timestamp_vector, indexes, output_len - ) - online_features_response.results.append(response_vector) - - -def _populate_response_from_feature_data_v2( - feature_data: Iterable[ - Tuple[ - Iterable[Timestamp], Iterable["FieldStatus.ValueType"], Iterable[ValueProto] - ] - ], - indexes: Iterable[List[int]], - online_features_response: GetOnlineFeaturesResponse, - requested_features: Iterable[str], - output_len: int, -): - """Populate the GetOnlineFeaturesResponse with feature data. - - This method assumes that `_read_from_online_store` returns data for each - combination of Entities in `entity_rows` in the same order as they - are provided. - - Args: - feature_data: A list of data in Protobuf form which was retrieved from the OnlineStore. - indexes: A list of indexes which should be the same length as `feature_data`. Each list - of indexes corresponds to a set of result rows in `online_features_response`. - online_features_response: The object to populate. - full_feature_names: A boolean that provides the option to add the feature view prefixes to the feature names, - changing them from the format "feature" to "feature_view__feature" (e.g., "daily_transactions" changes to - "customer_fv__daily_transactions"). - requested_features: The names of the features in `feature_data`. This should be ordered in the same way as the - data in `feature_data`. - output_len: The number of result rows in `online_features_response`. - """ - # Add the feature names to the response. - requested_feature_refs = [(feature_name) for feature_name in requested_features] - online_features_response.metadata.feature_names.val.extend(requested_feature_refs) - - timestamps, statuses, values = zip(*feature_data) - - # Populate the result with data fetched from the OnlineStore - # which is guaranteed to be aligned with `requested_features`. - for timestamp_vector, statuses_vector, values_vector in feature_data: - response_vector = construct_response_feature_vector( - values_vector, statuses_vector, timestamp_vector, indexes, output_len - ) - online_features_response.results.append(response_vector) - - def _convert_entity_key_to_proto_to_dict( entity_key_vals: List[EntityKeyProto], ) -> Dict[str, List[ValueProto]]: @@ -1172,16 +1204,47 @@ def _get_feature_views_to_use( if isinstance(features, FeatureService): feature_views = [ - (projection.name, projection) + (projection.name, None, projection) for projection in features.feature_view_projections ] else: assert features is not None - feature_views = [(feature.split(":")[0], None) for feature in features] # type: ignore[misc] + # Parse version-qualified refs: 'fv@v2:feat' -> ('fv', 2, None) + parsed = [] + seen = set() + for feature in features: + fv_name, version_num, _ = _parse_feature_ref(feature) + key = (fv_name, version_num) + if key not in seen: + seen.add(key) + parsed.append((fv_name, version_num, None)) + feature_views = parsed # type: ignore[assignment] fvs_to_use, od_fvs_to_use = [], [] - for name, projection in feature_views: - fv = registry.get_any_feature_view(name, project, allow_cache) + for name, version_num, projection in feature_views: + if version_num is not None: + if not getattr(registry, "enable_online_versioning", False): + raise ValueError( + f"Version-qualified ref '{name}@v{version_num}' not supported: " + f"online versioning is disabled. Set 'enable_online_feature_view_versioning: true' " + f"under 'registry' in feature_store.yaml." + ) + # Version-qualified reference: look up the specific version snapshot + try: + fv = registry.get_feature_view_by_version( + name, project, version_num, allow_cache + ) + except NotImplementedError: + # Fall back for v0 on registries that don't implement versioned lookup + if version_num == 0: + fv = registry.get_any_feature_view(name, project, allow_cache) + else: + raise + # Set version_tag on the projection so name_to_use() returns versioned key + if hasattr(fv, "projection") and fv.projection is not None: + fv.projection.version_tag = version_num + else: + fv = registry.get_any_feature_view(name, project, allow_cache) if isinstance(fv, OnDemandFeatureView): od_fvs_to_use.append( @@ -1213,9 +1276,11 @@ def _get_feature_views_to_use( ): fv.entities = [] # type: ignore[attr-defined] fv.entity_columns = [] # type: ignore[attr-defined] - fvs_to_use.append( - fv.with_projection(copy.copy(projection)) if projection else fv - ) + if projection: + fv = fv.with_projection(copy.copy(projection)) + if version_num is not None: + fv.projection.version_tag = version_num + fvs_to_use.append(fv) return (fvs_to_use, od_fvs_to_use) @@ -1257,13 +1322,20 @@ def _get_online_request_context( requested_on_demand_feature_views, ) - requested_result_row_names = { - feat_ref.replace(":", "__") for feat_ref in _feature_refs - } - if not full_feature_names: - requested_result_row_names = { - name.rpartition("__")[-1] for name in requested_result_row_names - } + # Build expected result names, including version tag when present so + # multi-version queries (e.g. fv@v1:feat, fv@v2:feat) match the response. + requested_result_row_names = set() + for feat_ref in _feature_refs: + fv_name, version_num, feature_name = _parse_feature_ref(feat_ref) + if full_feature_names: + if version_num is not None: + requested_result_row_names.add( + f"{fv_name}@v{version_num}__{feature_name}" + ) + else: + requested_result_row_names.add(f"{fv_name}__{feature_name}") + else: + requested_result_row_names.add(feature_name) feature_views = list(view for view, _ in grouped_refs) @@ -1409,36 +1481,99 @@ def _get_entity_key_protos( return entity_key_protos -def _convert_rows_to_protobuf( +def _populate_response_from_feature_data( requested_features: List[str], read_rows: List[Tuple[Optional[datetime], Optional[Dict[str, ValueProto]]]], -) -> List[Tuple[List[Timestamp], List["FieldStatus.ValueType"], List[ValueProto]]]: - # Pre-calculate the length to avoid repeated calculations - n_rows = len(read_rows) + indexes: Iterable[List[int]], + online_features_response: GetOnlineFeaturesResponse, + full_feature_names: bool, + table: "FeatureView", + output_len: int, + include_feature_view_version_metadata: bool = False, +): + """Populate the GetOnlineFeaturesResponse from raw online_read rows. + + Converts raw rows from the OnlineStore into protobuf FeatureVectors and + appends them to the response. This method assumes that ``online_read`` + returns data for each unique entity in the same order as ``indexes``. + + Args: + requested_features: The names of the features to extract from + each row. Determines the order of FeatureVectors in the response. + read_rows: Raw output from ``OnlineStore.online_read`` — a list of + ``(event_timestamp, feature_dict)`` tuples, one per unique entity. + ``feature_dict`` may be ``None`` when the entity is not found. + indexes: A tuple of lists that maps each unique entity (by position + in ``read_rows``) to one or more output positions in the response. + Used to fan-out deduplicated reads back to the original request rows. + online_features_response: The protobuf response object to populate. + full_feature_names: If True, feature names are prefixed with the + feature view name (e.g. ``"driver_fv__trips_today"``). + table: The FeatureView that ``read_rows`` was retrieved from. + output_len: Total number of result rows in the response. + include_feature_view_version_metadata: If True, version metadata + for the feature view is added to the response. + """ + n_features = len(requested_features) + + table_name = table.projection.name_to_use() + clean_table_name = table.projection.name_alias or table.projection.name + feature_refs = [ + f"{table_name}__{fn}" if full_feature_names else fn for fn in requested_features + ] + online_features_response.metadata.feature_names.val.extend(feature_refs) + + if include_feature_view_version_metadata: + existing_names = [ + fvm.name for fvm in online_features_response.metadata.feature_view_metadata + ] + if clean_table_name not in existing_names: + fv_metadata = online_features_response.metadata.feature_view_metadata.add() + fv_metadata.name = clean_table_name + fv_metadata.version = getattr(table, "current_version_number", 0) or 0 - # Create single instances of commonly used values null_value = ValueProto() - null_status = FieldStatus.NOT_FOUND - null_timestamp = Timestamp() - present_status = FieldStatus.PRESENT - - requested_features_vectors = [] - for feature_name in requested_features: - ts_vector = [null_timestamp] * n_rows - status_vector = [null_status] * n_rows - value_vector = [null_value] * n_rows - for idx, read_row in enumerate(read_rows): - row_ts_proto = Timestamp() - row_ts, feature_data = read_row - # TODO (Ly): reuse whatever timestamp if row_ts is None? - if row_ts is not None: - row_ts_proto.FromDatetime(row_ts) - ts_vector[idx] = row_ts_proto - if (feature_data is not None) and (feature_name in feature_data): - status_vector[idx] = present_status - value_vector[idx] = feature_data[feature_name] - requested_features_vectors.append((ts_vector, status_vector, value_vector)) - return requested_features_vectors + null_ts = Timestamp() + PRESENT = FieldStatus.PRESENT + NOT_FOUND = FieldStatus.NOT_FOUND + + row_ts_protos = [] + for row_ts, _ in read_rows: + ts = Timestamp() + if row_ts is not None: + ts.FromDatetime(row_ts) + row_ts_protos.append(ts) + + ts_template = [null_ts] * output_len + indexes_tuple = tuple(indexes) + for row_idx, destinations in enumerate(indexes_tuple): + ts = row_ts_protos[row_idx] + for out_idx in destinations: + ts_template[out_idx] = ts + + feat_values = [[null_value] * output_len for _ in range(n_features)] + feat_statuses = [[NOT_FOUND] * output_len for _ in range(n_features)] + + feat_idx_map = {name: i for i, name in enumerate(requested_features)} + for row_idx, destinations in enumerate(indexes_tuple): + _, feature_data = read_rows[row_idx] + if feature_data is None: + continue + for feat_name, feat_val in feature_data.items(): + f_idx = feat_idx_map.get(feat_name) + if f_idx is not None: + for out_idx in destinations: + feat_values[f_idx][out_idx] = feat_val + feat_statuses[f_idx][out_idx] = PRESENT + + for f_idx in range(n_features): + online_features_response.results.append( + GetOnlineFeaturesResponse.FeatureVector( + values=feat_values[f_idx], + statuses=feat_statuses[f_idx], + event_timestamps=list(ts_template), + ) + ) def has_all_tags( diff --git a/sdk/python/feast/value_type.py b/sdk/python/feast/value_type.py index bdd47952dc6..f09ae948d9b 100644 --- a/sdk/python/feast/value_type.py +++ b/sdk/python/feast/value_type.py @@ -67,6 +67,21 @@ class ValueType(enum.Enum): UNIX_TIMESTAMP_SET = 29 PDF_BYTES = 30 IMAGE_BYTES = 31 + JSON = 32 + JSON_LIST = 33 + STRUCT = 34 + STRUCT_LIST = 35 + UUID = 36 + TIME_UUID = 37 + UUID_LIST = 38 + TIME_UUID_LIST = 39 + UUID_SET = 40 + TIME_UUID_SET = 41 + VALUE_LIST = 42 + VALUE_SET = 43 + DECIMAL = 44 + DECIMAL_LIST = 45 + DECIMAL_SET = 46 ListType = Union[ diff --git a/sdk/python/feast/version_utils.py b/sdk/python/feast/version_utils.py new file mode 100644 index 00000000000..5811e89e936 --- /dev/null +++ b/sdk/python/feast/version_utils.py @@ -0,0 +1,51 @@ +import re +import uuid +from typing import Tuple + +LATEST_VERSION = "latest" +_VERSION_PATTERN = re.compile(r"^v(?:ersion)?(\d+)$", re.IGNORECASE) + + +def parse_version(version: str) -> Tuple[bool, int]: + """Parse a version string into (is_latest, version_number). + + Accepts "latest", "vN", or "versionN" (case-insensitive). + Returns (True, 0) for "latest", (False, N) for pinned versions. + + Raises: + ValueError: If the version string is invalid. + """ + if not version or version.lower() == LATEST_VERSION: + return True, 0 + + match = _VERSION_PATTERN.match(version) + if not match: + raise ValueError( + f"Invalid version string '{version}'. " + f"Expected 'latest', 'vN', or 'versionN' (e.g. 'v2', 'version3')." + ) + return False, int(match.group(1)) + + +def normalize_version_string(version: str) -> str: + """Normalize a version string for comparison. + + Empty string and "latest" both normalize to "latest". + "v2" and "version2" both normalize to "v2". + """ + if not version or version.lower() == LATEST_VERSION: + return LATEST_VERSION + is_latest, num = parse_version(version) + if is_latest: + return LATEST_VERSION + return version_tag(num) + + +def version_tag(n: int) -> str: + """Convert an integer version number to the canonical short form 'vN'.""" + return f"v{n}" + + +def generate_version_id() -> str: + """Generate a UUID for a version record.""" + return str(uuid.uuid4()) diff --git a/sdk/python/pytest.ini b/sdk/python/pytest.ini index 31640e509d7..1ad76b978e4 100644 --- a/sdk/python/pytest.ini +++ b/sdk/python/pytest.ini @@ -20,6 +20,7 @@ markers = slow: Tests taking >30 seconds cloud: Tests requiring cloud credentials local_only: Tests that run entirely locally + xdist_group: Group tests to run in the same xdist worker timeout = 300 timeout_method = thread diff --git a/sdk/python/requirements/py3.10-ci-requirements.txt b/sdk/python/requirements/py3.10-ci-requirements.txt index 03ecb497a30..4a5a8e1e77a 100644 --- a/sdk/python/requirements/py3.10-ci-requirements.txt +++ b/sdk/python/requirements/py3.10-ci-requirements.txt @@ -1,8 +1,8 @@ # This file was autogenerated by uv via the following command: # uv pip compile -p 3.10 --no-strip-extras pyproject.toml --extra ci --generate-hashes --output-file sdk/python/requirements/py3.10-ci-requirements.txt -accelerate==1.12.0 \ - --hash=sha256:3e2091cd341423207e2f084a6654b1efcd250dc326f2a37d6dde446e07cabb11 \ - --hash=sha256:70988c352feb481887077d2ab845125024b2a137a5090d6d7a32b57d03a45df6 +accelerate==1.13.0 \ + --hash=sha256:cf1a3efb96c18f7b152eb0fa7490f3710b19c3f395699358f08decca2b8b62e0 \ + --hash=sha256:d631b4e0f5b3de4aff2d7e9e6857d164810dfc3237d54d017f075122d057b236 # via docling-ibm-models aiobotocore==2.23.1 \ --hash=sha256:a59f2a78629b97d52f10936b79c73de64e481a8c44a62c1871f088df6c1afc4f \ @@ -12,127 +12,127 @@ aiohappyeyeballs==2.6.1 \ --hash=sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558 \ --hash=sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8 # via aiohttp -aiohttp==3.13.3 \ - --hash=sha256:01ad2529d4b5035578f5081606a465f3b814c542882804e2e8cda61adf5c71bf \ - --hash=sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c \ - --hash=sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c \ - --hash=sha256:084911a532763e9d3dd95adf78a78f4096cd5f58cdc18e6fdbc1b58417a45423 \ - --hash=sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f \ - --hash=sha256:0db318f7a6f065d84cb1e02662c526294450b314a02bd9e2a8e67f0d8564ce40 \ - --hash=sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2 \ - --hash=sha256:1449ceddcdbcf2e0446957863af03ebaaa03f94c090f945411b61269e2cb5daf \ - --hash=sha256:147e422fd1223005c22b4fe080f5d93ced44460f5f9c105406b753612b587821 \ - --hash=sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64 \ - --hash=sha256:215a685b6fbbfcf71dfe96e3eba7a6f58f10da1dfdf4889c7dd856abe430dca7 \ - --hash=sha256:2712039939ec963c237286113c68dbad80a82a4281543f3abf766d9d73228998 \ - --hash=sha256:27234ef6d85c914f9efeb77ff616dbf4ad2380be0cda40b4db086ffc7ddd1b7d \ - --hash=sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea \ - --hash=sha256:2b8d8ddba8f95ba17582226f80e2de99c7a7948e66490ef8d947e272a93e9463 \ - --hash=sha256:2ba0eea45eb5cc3172dbfc497c066f19c41bac70963ea1a67d51fc92e4cf9a80 \ - --hash=sha256:2be0e9ccf23e8a94f6f0650ce06042cefc6ac703d0d7ab6c7a917289f2539ad4 \ - --hash=sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767 \ - --hash=sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43 \ - --hash=sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592 \ - --hash=sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a \ - --hash=sha256:31a83ea4aead760dfcb6962efb1d861db48c34379f2ff72db9ddddd4cda9ea2e \ - --hash=sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687 \ - --hash=sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8 \ - --hash=sha256:37239e9f9a7ea9ac5bf6b92b0260b01f8a22281996da609206a84df860bc1261 \ - --hash=sha256:37da61e244d1749798c151421602884db5270faf479cf0ef03af0ff68954c9dd \ - --hash=sha256:3b61b7169ababd7802f9568ed96142616a9118dd2be0d1866e920e77ec8fa92a \ - --hash=sha256:3d9908a48eb7416dc1f4524e69f1d32e5d90e3981e4e37eb0aa1cd18f9cfa2a4 \ - --hash=sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587 \ - --hash=sha256:4021b51936308aeea0367b8f006dc999ca02bc118a0cc78c303f50a2ff6afb91 \ - --hash=sha256:40c5e40ecc29ba010656c18052b877a1c28f84344825efa106705e835c28530f \ - --hash=sha256:425c126c0dc43861e22cb1c14ba4c8e45d09516d0a3ae0a3f7494b79f5f233a3 \ - --hash=sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344 \ - --hash=sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6 \ - --hash=sha256:49a03727c1bba9a97d3e93c9f93ca03a57300f484b6e935463099841261195d3 \ - --hash=sha256:4ae5b5a0e1926e504c81c5b84353e7a5516d8778fbbff00429fe7b05bb25cbce \ - --hash=sha256:4e239d501f73d6db1522599e14b9b321a7e3b1de66ce33d53a765d975e9f4808 \ - --hash=sha256:56339a36b9f1fc708260c76c87e593e2afb30d26de9ae1eb445b5e051b98a7a1 \ - --hash=sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29 \ - --hash=sha256:5b179331a481cb5529fca8b432d8d3c7001cb217513c94cd72d668d1248688a3 \ - --hash=sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b \ - --hash=sha256:5d2d94f1f5fcbe40838ac51a6ab5704a6f9ea42e72ceda48de5e6b898521da51 \ - --hash=sha256:5dff64413671b0d3e7d5918ea490bdccb97a4ad29b3f311ed423200b2203e01c \ - --hash=sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926 \ - --hash=sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64 \ - --hash=sha256:642f752c3eb117b105acbd87e2c143de710987e09860d674e068c4c2c441034f \ - --hash=sha256:65d2ccb7eabee90ce0503c17716fc77226be026dcc3e65cce859a30db715025b \ - --hash=sha256:693781c45a4033d31d4187d2436f5ac701e7bbfe5df40d917736108c1cc7436e \ - --hash=sha256:694976222c711d1d00ba131904beb60534f93966562f64440d0c9d41b8cdb440 \ - --hash=sha256:697753042d57f4bf7122cab985bf15d0cef23c770864580f5af4f52023a56bd6 \ - --hash=sha256:69c56fbc1993fa17043e24a546959c0178fe2b5782405ad4559e6c13975c15e3 \ - --hash=sha256:6de499a1a44e7de70735d0b39f67c8f25eb3d91eb3103be99ca0fa882cdd987d \ - --hash=sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415 \ - --hash=sha256:75ca857eba4e20ce9f546cd59c7007b33906a4cd48f2ff6ccf1ccfc3b646f279 \ - --hash=sha256:7a4a94eb787e606d0a09404b9c38c113d3b099d508021faa615d70a0131907ce \ - --hash=sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603 \ - --hash=sha256:7bfdc049127717581866fa4708791220970ce291c23e28ccf3922c700740fdc0 \ - --hash=sha256:7e63f210bc1b57ef699035f2b4b6d9ce096b5914414a49b0997c839b2bd2223c \ - --hash=sha256:7f9120f7093c2a32d9647abcaf21e6ad275b4fbec5b55969f978b1a97c7c86bf \ - --hash=sha256:8057c98e0c8472d8846b9c79f56766bcc57e3e8ac7bfd510482332366c56c591 \ - --hash=sha256:80dd4c21b0f6237676449c6baaa1039abae86b91636b6c91a7f8e61c87f89540 \ - --hash=sha256:81e97251d9298386c2b7dbeb490d3d1badbdc69107fb8c9299dd04eb39bddc0e \ - --hash=sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26 \ - --hash=sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a \ - --hash=sha256:859bd3f2156e81dd01432f5849fc73e2243d4a487c4fd26609b1299534ee1845 \ - --hash=sha256:87797e645d9d8e222e04160ee32aa06bc5c163e8499f24db719e7852ec23093a \ - --hash=sha256:87b9aab6d6ed88235aa2970294f496ff1a1f9adcd724d800e9b952395a80ffd9 \ - --hash=sha256:8a60e60746623925eab7d25823329941aee7242d559baa119ca2b253c88a7bd6 \ - --hash=sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba \ - --hash=sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df \ - --hash=sha256:947c26539750deeaee933b000fb6517cc770bbd064bad6033f1cff4803881e43 \ - --hash=sha256:96d604498a7c782cb15a51c406acaea70d8c027ee6b90c569baa6e7b93073679 \ - --hash=sha256:988a8c5e317544fdf0d39871559e67b6341065b87fceac641108c2096d5506b7 \ - --hash=sha256:9a9dc347e5a3dc7dfdbc1f82da0ef29e388ddb2ed281bfce9dd8248a313e62b7 \ - --hash=sha256:9ae8dd55c8e6c4257eae3a20fd2c8f41edaea5992ed67156642493b8daf3cecc \ - --hash=sha256:9af5e68ee47d6534d36791bbe9b646d2a7c7deb6fc24d7943628edfbb3581f29 \ - --hash=sha256:9b174f267b5cfb9a7dba9ee6859cecd234e9a681841eb85068059bc867fb8f02 \ - --hash=sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984 \ - --hash=sha256:9d4c940f02f49483b18b079d1c27ab948721852b281f8b015c058100e9421dd1 \ - --hash=sha256:9ebf57d09e131f5323464bd347135a88622d1c0976e88ce15b670e7ad57e4bd6 \ - --hash=sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632 \ - --hash=sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56 \ - --hash=sha256:a2212ad43c0833a873d0fb3c63fa1bacedd4cf6af2fee62bf4b739ceec3ab239 \ - --hash=sha256:a45530014d7a1e09f4a55f4f43097ba0fd155089372e105e4bff4ca76cb1b168 \ - --hash=sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88 \ - --hash=sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc \ - --hash=sha256:af71fff7bac6bb7508956696dce8f6eec2bbb045eceb40343944b1ae62b5ef11 \ - --hash=sha256:b04be762396457bef43f3597c991e192ee7da460a4953d7e647ee4b1c28e7046 \ - --hash=sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0 \ - --hash=sha256:b1a6102b4d3ebc07dad44fbf07b45bb600300f15b552ddf1851b5390202ea2e3 \ - --hash=sha256:b46020d11d23fe16551466c77823df9cc2f2c1e63cc965daf67fa5eec6ca1877 \ - --hash=sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1 \ - --hash=sha256:b903a4dfee7d347e2d87697d0713be59e0b87925be030c9178c5faa58ea58d5c \ - --hash=sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25 \ - --hash=sha256:b99281b0704c103d4e11e72a76f1b543d4946fea7dd10767e7e1b5f00d4e5704 \ - --hash=sha256:bae5c2ed2eae26cc382020edad80d01f36cb8e746da40b292e68fec40421dc6a \ - --hash=sha256:bb4f7475e359992b580559e008c598091c45b5088f28614e855e42d39c2f1033 \ - --hash=sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1 \ - --hash=sha256:bfc1cc2fe31a6026a8a88e4ecfb98d7f6b1fec150cfd708adbfd1d2f42257c29 \ - --hash=sha256:c014c7ea7fb775dd015b2d3137378b7be0249a448a1612268b5a90c2d81de04d \ - --hash=sha256:c048058117fd649334d81b4b526e94bde3ccaddb20463a815ced6ecbb7d11160 \ - --hash=sha256:c0e2d366af265797506f0283487223146af57815b388623f0357ef7eac9b209d \ - --hash=sha256:c19b90316ad3b24c69cd78d5c9b4f3aa4497643685901185b65166293d36a00f \ - --hash=sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f \ - --hash=sha256:c6b8568a3bb5819a0ad087f16d40e5a3fb6099f39ea1d5625a3edc1e923fc538 \ - --hash=sha256:d32764c6c9aafb7fb55366a224756387cd50bfa720f32b88e0e6fa45b27dcf29 \ - --hash=sha256:d5a372fd5afd301b3a89582817fdcdb6c34124787c70dbcc616f259013e7eef7 \ - --hash=sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72 \ - --hash=sha256:dca68018bf48c251ba17c72ed479f4dafe9dbd5a73707ad8d28a38d11f3d42af \ - --hash=sha256:de2c184bb1fe2cbd2cefba613e9db29a5ab559323f994b6737e370d3da0ac455 \ - --hash=sha256:e3531d63d3bdfa7e3ac5e9b27b2dd7ec9df3206a98e0b3445fa906f233264c57 \ - --hash=sha256:e50a2e1404f063427c9d027378472316201a2290959a295169bcf25992d04558 \ - --hash=sha256:e636b3c5f61da31a92bf0d91da83e58fdfa96f178ba682f11d24f31944cdd28c \ - --hash=sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808 \ - --hash=sha256:f33ed1a2bf1997a36661874b017f5c4b760f41266341af36febaf271d179f6d7 \ - --hash=sha256:f76c1e3fe7d7c8afad7ed193f89a292e1999608170dcc9751a7462a87dfd5bc0 \ - --hash=sha256:f9444f105664c4ce47a2a7171a2418bce5b7bae45fb610f4e2c36045d85911d3 \ - --hash=sha256:fc290605db2a917f6e81b0e1e0796469871f5af381ce15c604a3c5c7e51cb730 \ - --hash=sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa \ - --hash=sha256:fee0c6bc7db1de362252affec009707a17478a00ec69f797d23ca256e36d5940 +aiohttp==3.13.5 \ + --hash=sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5 \ + --hash=sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b \ + --hash=sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9 \ + --hash=sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b \ + --hash=sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8 \ + --hash=sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a \ + --hash=sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2 \ + --hash=sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1 \ + --hash=sha256:147b4f501d0292077f29d5268c16bb7c864a1f054d7001c4c1812c0421ea1ed0 \ + --hash=sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037 \ + --hash=sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416 \ + --hash=sha256:178c7b5e62b454c2bc790786e6058c3cc968613b4419251b478c153a4aec32b1 \ + --hash=sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9 \ + --hash=sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a \ + --hash=sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36 \ + --hash=sha256:206b7b3ef96e4ce211754f0cd003feb28b7d81f0ad26b8d077a5d5161436067f \ + --hash=sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b \ + --hash=sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174 \ + --hash=sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b \ + --hash=sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8 \ + --hash=sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e \ + --hash=sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6 \ + --hash=sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c \ + --hash=sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe \ + --hash=sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9 \ + --hash=sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc \ + --hash=sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800 \ + --hash=sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286 \ + --hash=sha256:347542f0ea3f95b2a955ee6656461fa1c776e401ac50ebce055a6c38454a0adf \ + --hash=sha256:39380e12bd1f2fdab4285b6e055ad48efbaed5c836433b142ed4f5b9be71036a \ + --hash=sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc \ + --hash=sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9 \ + --hash=sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665 \ + --hash=sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832 \ + --hash=sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297 \ + --hash=sha256:4e704c52438f66fdd89588346183d898bb42167cf88f8b7ff1c0f9fc957c348f \ + --hash=sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73 \ + --hash=sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b \ + --hash=sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9 \ + --hash=sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090 \ + --hash=sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49 \ + --hash=sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d \ + --hash=sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46 \ + --hash=sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83 \ + --hash=sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796 \ + --hash=sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be \ + --hash=sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d \ + --hash=sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf \ + --hash=sha256:6f497a6876aa4b1a102b04996ce4c1170c7040d83faa9387dd921c16e30d5c83 \ + --hash=sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25 \ + --hash=sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06 \ + --hash=sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3 \ + --hash=sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6 \ + --hash=sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb \ + --hash=sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88 \ + --hash=sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9 \ + --hash=sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be \ + --hash=sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14 \ + --hash=sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a \ + --hash=sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c \ + --hash=sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3 \ + --hash=sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f \ + --hash=sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d \ + --hash=sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670 \ + --hash=sha256:912d4b6af530ddb1338a66229dac3a25ff11d4448be3ec3d6340583995f56031 \ + --hash=sha256:9277145d36a01653863899c665243871434694bcc3431922c3b35c978061bdb8 \ + --hash=sha256:95d14ca7abefde230f7639ec136ade282655431fd5db03c343b19dda72dd1643 \ + --hash=sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d \ + --hash=sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8 \ + --hash=sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8 \ + --hash=sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1 \ + --hash=sha256:9efcc0f11d850cefcafdd9275b9576ad3bfb539bed96807663b32ad99c4d4b88 \ + --hash=sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb \ + --hash=sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61 \ + --hash=sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4 \ + --hash=sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7 \ + --hash=sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9 \ + --hash=sha256:a8a4d3427e8de1312ddf309cc482186466c79895b3a139fed3259fc01dfa9a5b \ + --hash=sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500 \ + --hash=sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6 \ + --hash=sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2 \ + --hash=sha256:af545c2cffdb0967a96b6249e6f5f7b0d92cdfd267f9d5238d5b9ca63e8edb10 \ + --hash=sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1 \ + --hash=sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3 \ + --hash=sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e \ + --hash=sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a \ + --hash=sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5 \ + --hash=sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95 \ + --hash=sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074 \ + --hash=sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5 \ + --hash=sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b \ + --hash=sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772 \ + --hash=sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a \ + --hash=sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274 \ + --hash=sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94 \ + --hash=sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13 \ + --hash=sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac \ + --hash=sha256:cb979826071c0986a5f08333a36104153478ce6018c58cba7f9caddaf63d5d67 \ + --hash=sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76 \ + --hash=sha256:d147004fede1b12f6013a6dbb2a26a986a671a03c6ea740ddc76500e5f1c399f \ + --hash=sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8 \ + --hash=sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7 \ + --hash=sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8 \ + --hash=sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3 \ + --hash=sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be \ + --hash=sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b \ + --hash=sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c \ + --hash=sha256:e999f0c88a458c836d5fb521814e92ed2172c649200336a6df514987c1488258 \ + --hash=sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c \ + --hash=sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6 \ + --hash=sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56 \ + --hash=sha256:ee5e86776273de1795947d17bddd6bb19e0365fd2af4289c0d2c5454b6b1d36b \ + --hash=sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d \ + --hash=sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a \ + --hash=sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162 \ + --hash=sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1 \ + --hash=sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6 \ + --hash=sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5 \ + --hash=sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540 \ + --hash=sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254 # via # aiobotocore # fsspec @@ -160,9 +160,9 @@ annotated-types==0.7.0 \ --hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \ --hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89 # via pydantic -anyio==4.12.1 \ - --hash=sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703 \ - --hash=sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c +anyio==4.13.0 \ + --hash=sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708 \ + --hash=sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc # via # elasticsearch # httpx @@ -224,9 +224,9 @@ asttokens==3.0.1 \ --hash=sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a \ --hash=sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7 # via stack-data -async-lru==2.1.0 \ - --hash=sha256:9eeb2fecd3fe42cc8a787fc32ead53a3a7158cc43d039c3c55ab3e4e5b2a80ed \ - --hash=sha256:fa12dcf99a42ac1280bc16c634bbaf06883809790f6304d85cdab3f666f33a7e +async-lru==2.3.0 \ + --hash=sha256:89bdb258a0140d7313cf8f4031d816a042202faa61d0ab310a0a538baa1c24b6 \ + --hash=sha256:eea27b01841909316f2cc739807acea1c623df2be8c5cfad7583286397bb8315 # via jupyterlab async-property==0.2.2 \ --hash=sha256:17d9bd6ca67e27915a75d92549df64b5c7174e9dc806b30a3934dc4ff0506380 \ @@ -242,24 +242,24 @@ atpublic==7.0.0 \ --hash=sha256:466ef10d0c8bbd14fd02a5fbd5a8b6af6a846373d91106d3a07c16d72d96b63e \ --hash=sha256:6702bd9e7245eb4e8220a3e222afcef7f87412154732271ee7deee4433b72b4b # via ibis-framework -attrs==25.4.0 \ - --hash=sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11 \ - --hash=sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373 +attrs==26.1.0 \ + --hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \ + --hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32 # via # aiohttp # jsonlines # jsonschema # openlineage-python # referencing -azure-core==1.38.1 \ - --hash=sha256:69f08ee3d55136071b7100de5b198994fc1c5f89d2b91f2f43156d20fcf200a4 \ - --hash=sha256:9317db1d838e39877eb94a2240ce92fa607db68adf821817b723f0d679facbf6 +azure-core==1.39.0 \ + --hash=sha256:4ac7b70fab5438c3f68770649a78daf97833caa83827f91df9c14e0e0ea7d34f \ + --hash=sha256:8a90a562998dd44ce84597590fff6249701b98c0e8797c95fcdd695b54c35d74 # via # azure-identity # azure-storage-blob -azure-identity==1.25.2 \ - --hash=sha256:030dbaa720266c796221c6cdbd1999b408c079032c919fef725fcc348a540fe9 \ - --hash=sha256:1b40060553d01a72ba0d708b9a46d0f61f56312e215d8896d836653ffdc6753d +azure-identity==1.25.3 \ + --hash=sha256:ab23c0d63015f50b630ef6c6cf395e7262f439ce06e5d07a64e874c724f8d9e6 \ + --hash=sha256:f4d0b956a8146f30333e071374171f3cfa7bdb8073adb8c3814b65567aa7447c # via feast (pyproject.toml) azure-storage-blob==12.28.0 \ --hash=sha256:00fb1db28bf6a7b7ecaa48e3b1d5c83bfadacc5a678b77826081304bd87d6461 \ @@ -277,9 +277,9 @@ beautifulsoup4==4.14.3 \ # via # docling # nbconvert -bigtree==1.3.1 \ - --hash=sha256:a22a0ecd9b0abb283f4a1515370dbf1ec93adee70746767272e2c49d7af9f407 \ - --hash=sha256:c8b766b00188c532d3499bfd9e9666b357428db507fc701f088031a0d5c614d5 +bigtree==1.4.0 \ + --hash=sha256:d0d99550ae64ce4529f132602ab875c2ab472c96c942f5704f8c72a17450d3ea \ + --hash=sha256:e5ae2e948168da671d99601c9ed87ab3b48d9d4ea8a98f111e5748e98064c31c # via feast (pyproject.toml) bleach[css]==6.3.0 \ --hash=sha256:6f3b91b1c0a02bb9a78b5a454c92506aa0fdf197e1d5e114d2e00c6f64306d22 \ @@ -290,7 +290,6 @@ boto3==1.38.27 \ --hash=sha256:95f5fe688795303a8a15e8b7e7f255cadab35eae459d00cc281a4fd77252ea80 # via # feast (pyproject.toml) - # ikvpy # moto # snowflake-connector-python botocore==1.38.46 \ @@ -302,12 +301,11 @@ botocore==1.38.46 \ # moto # s3transfer # snowflake-connector-python -build==1.4.0 \ - --hash=sha256:6a07c1b8eb6f2b311b96fcbdbce5dab5fe637ffda0fd83c9cac622e927501596 \ - --hash=sha256:f1b91b925aa322be454f8330c6fb48b465da993d1e7e7e6fa35027ec49f3c936 +build==1.4.2 \ + --hash=sha256:35b14e1ee329c186d3f08466003521ed7685ec15ecffc07e68d706090bf161d1 \ + --hash=sha256:7a4d8651ea877cb2a89458b1b198f2e69f536c95e89129dbf5d448045d60db88 # via # feast (pyproject.toml) - # openlineage-python # pip-tools # singlestoredb cassandra-driver==3.29.3 \ @@ -343,9 +341,9 @@ cassandra-driver==3.29.3 \ --hash=sha256:fcf45725ae1751cb934b9b827a7d9cd899bbd09eb1ad28e2160b4584de35ba77 \ --hash=sha256:ff6b82ee4533f6fd4474d833e693b44b984f58337173ee98ed76bce08721a636 # via feast (pyproject.toml) -certifi==2026.1.4 \ - --hash=sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c \ - --hash=sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120 +certifi==2026.2.25 \ + --hash=sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa \ + --hash=sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7 # via # clickhouse-connect # docling @@ -445,125 +443,140 @@ cffi==2.0.0 \ # feast (pyproject.toml) # argon2-cffi-bindings # cryptography - # ikvpy cfgv==3.5.0 \ --hash=sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0 \ --hash=sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132 # via pre-commit -charset-normalizer==3.4.4 \ - --hash=sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad \ - --hash=sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93 \ - --hash=sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394 \ - --hash=sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89 \ - --hash=sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc \ - --hash=sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86 \ - --hash=sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63 \ - --hash=sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d \ - --hash=sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f \ - --hash=sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8 \ - --hash=sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0 \ - --hash=sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505 \ - --hash=sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161 \ - --hash=sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af \ - --hash=sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152 \ - --hash=sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318 \ - --hash=sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72 \ - --hash=sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4 \ - --hash=sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e \ - --hash=sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3 \ - --hash=sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576 \ - --hash=sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c \ - --hash=sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1 \ - --hash=sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8 \ - --hash=sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1 \ - --hash=sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2 \ - --hash=sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44 \ - --hash=sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26 \ - --hash=sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88 \ - --hash=sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016 \ - --hash=sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede \ - --hash=sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf \ - --hash=sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a \ - --hash=sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc \ - --hash=sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0 \ - --hash=sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84 \ - --hash=sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db \ - --hash=sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1 \ - --hash=sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7 \ - --hash=sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed \ - --hash=sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8 \ - --hash=sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133 \ - --hash=sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e \ - --hash=sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef \ - --hash=sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14 \ - --hash=sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2 \ - --hash=sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0 \ - --hash=sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d \ - --hash=sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828 \ - --hash=sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f \ - --hash=sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf \ - --hash=sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6 \ - --hash=sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328 \ - --hash=sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090 \ - --hash=sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa \ - --hash=sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381 \ - --hash=sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c \ - --hash=sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb \ - --hash=sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc \ - --hash=sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a \ - --hash=sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec \ - --hash=sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc \ - --hash=sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac \ - --hash=sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e \ - --hash=sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313 \ - --hash=sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569 \ - --hash=sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3 \ - --hash=sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d \ - --hash=sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525 \ - --hash=sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894 \ - --hash=sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3 \ - --hash=sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9 \ - --hash=sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a \ - --hash=sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9 \ - --hash=sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14 \ - --hash=sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25 \ - --hash=sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50 \ - --hash=sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf \ - --hash=sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1 \ - --hash=sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3 \ - --hash=sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac \ - --hash=sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e \ - --hash=sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815 \ - --hash=sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c \ - --hash=sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6 \ - --hash=sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6 \ - --hash=sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e \ - --hash=sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4 \ - --hash=sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84 \ - --hash=sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69 \ - --hash=sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15 \ - --hash=sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191 \ - --hash=sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0 \ - --hash=sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897 \ - --hash=sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd \ - --hash=sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2 \ - --hash=sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794 \ - --hash=sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d \ - --hash=sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074 \ - --hash=sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3 \ - --hash=sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224 \ - --hash=sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838 \ - --hash=sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a \ - --hash=sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d \ - --hash=sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d \ - --hash=sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f \ - --hash=sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8 \ - --hash=sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490 \ - --hash=sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966 \ - --hash=sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9 \ - --hash=sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3 \ - --hash=sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e \ - --hash=sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608 +charset-normalizer==3.4.7 \ + --hash=sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc \ + --hash=sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c \ + --hash=sha256:07d9e39b01743c3717745f4c530a6349eadbfa043c7577eef86c502c15df2c67 \ + --hash=sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4 \ + --hash=sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0 \ + --hash=sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c \ + --hash=sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5 \ + --hash=sha256:12a6fff75f6bc66711b73a2f0addfc4c8c15a20e805146a02d147a318962c444 \ + --hash=sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153 \ + --hash=sha256:14265bfe1f09498b9d8ec91e9ec9fa52775edf90fcbde092b25f4a33d444fea9 \ + --hash=sha256:16d971e29578a5e97d7117866d15889a4a07befe0e87e703ed63cd90cb348c01 \ + --hash=sha256:177a0ba5f0211d488e295aaf82707237e331c24788d8d76c96c5a41594723217 \ + --hash=sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b \ + --hash=sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c \ + --hash=sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a \ + --hash=sha256:1dc8b0ea451d6e69735094606991f32867807881400f808a106ee1d963c46a83 \ + --hash=sha256:1efde3cae86c8c273f1eb3b287be7d8499420cf2fe7585c41d370d3e790054a5 \ + --hash=sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7 \ + --hash=sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb \ + --hash=sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c \ + --hash=sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1 \ + --hash=sha256:2cd4a60d0e2fb04537162c62bbbb4182f53541fe0ede35cdf270a1c1e723cc42 \ + --hash=sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab \ + --hash=sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df \ + --hash=sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e \ + --hash=sha256:320ade88cfb846b8cd6b4ddf5ee9e80ee0c1f52401f2456b84ae1ae6a1a5f207 \ + --hash=sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18 \ + --hash=sha256:36836d6ff945a00b88ba1e4572d721e60b5b8c98c155d465f56ad19d68f23734 \ + --hash=sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38 \ + --hash=sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110 \ + --hash=sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18 \ + --hash=sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44 \ + --hash=sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d \ + --hash=sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48 \ + --hash=sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e \ + --hash=sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5 \ + --hash=sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d \ + --hash=sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53 \ + --hash=sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790 \ + --hash=sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c \ + --hash=sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b \ + --hash=sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116 \ + --hash=sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d \ + --hash=sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10 \ + --hash=sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6 \ + --hash=sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2 \ + --hash=sha256:6370e8686f662e6a3941ee48ed4742317cafbe5707e36406e9df792cdb535776 \ + --hash=sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a \ + --hash=sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265 \ + --hash=sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008 \ + --hash=sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943 \ + --hash=sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374 \ + --hash=sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246 \ + --hash=sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e \ + --hash=sha256:6e0d51f618228538a3e8f46bd246f87a6cd030565e015803691603f55e12afb5 \ + --hash=sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616 \ + --hash=sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15 \ + --hash=sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41 \ + --hash=sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960 \ + --hash=sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752 \ + --hash=sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e \ + --hash=sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72 \ + --hash=sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7 \ + --hash=sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8 \ + --hash=sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b \ + --hash=sha256:813c0e0132266c08eb87469a642cb30aaff57c5f426255419572aaeceeaa7bf4 \ + --hash=sha256:82b271f5137d07749f7bf32f70b17ab6eaabedd297e75dce75081a24f76eb545 \ + --hash=sha256:84c018e49c3bf790f9c2771c45e9313a08c2c2a6342b162cd650258b57817706 \ + --hash=sha256:8751d2787c9131302398b11e6c8068053dcb55d5a8964e114b6e196cf16cb366 \ + --hash=sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb \ + --hash=sha256:87fad7d9ba98c86bcb41b2dc8dbb326619be2562af1f8ff50776a39e55721c5a \ + --hash=sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e \ + --hash=sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00 \ + --hash=sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f \ + --hash=sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a \ + --hash=sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1 \ + --hash=sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66 \ + --hash=sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356 \ + --hash=sha256:a6c5863edfbe888d9eff9c8b8087354e27618d9da76425c119293f11712a6319 \ + --hash=sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4 \ + --hash=sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad \ + --hash=sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d \ + --hash=sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5 \ + --hash=sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7 \ + --hash=sha256:aef65cd602a6d0e0ff6f9930fcb1c8fec60dd2cfcb6facaf4bdb0e5873042db0 \ + --hash=sha256:af21eb4409a119e365397b2adbaca4c9ccab56543a65d5dbd9f920d6ac29f686 \ + --hash=sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34 \ + --hash=sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49 \ + --hash=sha256:bb8cc7534f51d9a017b93e3e85b260924f909601c3df002bcdb58ddb4dc41a5c \ + --hash=sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1 \ + --hash=sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e \ + --hash=sha256:bd9b23791fe793e4968dba0c447e12f78e425c59fc0e3b97f6450f4781f3ee60 \ + --hash=sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0 \ + --hash=sha256:c0f081d69a6e58272819b70288d3221a6ee64b98df852631c80f293514d3b274 \ + --hash=sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d \ + --hash=sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0 \ + --hash=sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae \ + --hash=sha256:c593052c465475e64bbfe5dbd81680f64a67fdc752c56d7a0ae205dc8aeefe0f \ + --hash=sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d \ + --hash=sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe \ + --hash=sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3 \ + --hash=sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393 \ + --hash=sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1 \ + --hash=sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af \ + --hash=sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44 \ + --hash=sha256:d61f00a0869d77422d9b2aba989e2d24afa6ffd552af442e0e58de4f35ea6d00 \ + --hash=sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c \ + --hash=sha256:dca4bbc466a95ba9c0234ef56d7dd9509f63da22274589ebd4ed7f1f4d4c54e3 \ + --hash=sha256:dd915403e231e6b1809fe9b6d9fc55cf8fb5e02765ac625d9cd623342a7905d7 \ + --hash=sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd \ + --hash=sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e \ + --hash=sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b \ + --hash=sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8 \ + --hash=sha256:e5f4d355f0a2b1a31bc3edec6795b46324349c9cb25eed068049e4f472fb4259 \ + --hash=sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859 \ + --hash=sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46 \ + --hash=sha256:e80c8378d8f3d83cd3164da1ad2df9e37a666cdde7b1cb2298ed0b558064be30 \ + --hash=sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b \ + --hash=sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46 \ + --hash=sha256:ed065083d0898c9d5b4bbec7b026fd755ff7454e6e8b73a67f8c744b13986e24 \ + --hash=sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a \ + --hash=sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24 \ + --hash=sha256:f22dec1690b584cea26fade98b2435c132c1b5f68e39f5a0b7627cd7ae31f1dc \ + --hash=sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215 \ + --hash=sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063 \ + --hash=sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832 \ + --hash=sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6 \ + --hash=sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79 \ + --hash=sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464 # via # requests # snowflake-connector-python @@ -579,66 +592,74 @@ click==8.3.1 \ # ray # typer # uvicorn -clickhouse-connect==0.11.0 \ - --hash=sha256:00c525036aeb968c578a7e32bf3d4acbac4f91a3748b39921a654dbbf8fae482 \ - --hash=sha256:035d66337654c7d7812e43910195d0c1ab2e64512a98407a51ee5860d7f32289 \ - --hash=sha256:0e1de4b74dbfd75b4990267a6168e1181130b2a255c1250e40f6aa922a147b4d \ - --hash=sha256:0e857234d6f91ce30dd4f3f6dfd0b84c83057cf45686a86eab1912c3991ce8b1 \ - --hash=sha256:0fdd59e35164472404ddddf4407903e516dd11c929f248846dd2993e2c005774 \ - --hash=sha256:121cb63648ee812582c8691bc1c4bd3f4c5ee1220278f32fb3d2bf581cb5fe2b \ - --hash=sha256:19b60f592b9de67c366d1459a2c73ded0955a9b0ccde265a1f9aa237c1e1c89f \ - --hash=sha256:242f891559a2b0c4b9eb37cad5181b6141c521763b10c8025a105826ae0c6957 \ - --hash=sha256:2853493849e59ccf60a095915f9a8d70f539853fc4536260f21720a6c495e339 \ - --hash=sha256:2dbc742bc0c7db72ca88bb5e67bf1959c60dfe1ed3376bf4c48e35b026374a97 \ - --hash=sha256:2dd49ac4d0d59a836ceda8b2c6b7f348accf2512f81d46543fc33f3b64c55152 \ - --hash=sha256:2e8f339f7fbd1880d67e5a8d07dfaecd4cd0f5bf6c77ae3e254030b2a7e71f53 \ - --hash=sha256:3b0196d4a7f6cd76dc57cf178f4dee2e92c08daa6e77def88d95604cf715b913 \ - --hash=sha256:3e5d64a10f2938ac3e84194c6dd312a42c62f875d6f0be00bc73d337d2115570 \ - --hash=sha256:40267a3b72c3d26b5e062d1858183d1b7c2ff8142457b6962a5826f726ba8ba8 \ - --hash=sha256:4196a2caad25ea83cfbc627306daa4345c9b44ce4dd247dc462842da5f10630f \ - --hash=sha256:470d5ab8f2cd9835feb4198c6fbd80730b52257fad23a20dbc7e4ab0c0ab1c2f \ - --hash=sha256:49898f30c94dfac1d655e32f3ca829f98344384b470f29dc46532ad2285b2fad \ - --hash=sha256:4b1ab7542701f8e76742da18eaac31a5c7b49ebab4020be90d1129a222de0dd5 \ - --hash=sha256:524afd5a64fd9fd53184ec14ad1a69ea89e1fa8373c89350b53c38982232aa45 \ - --hash=sha256:55d23aa3a68617323ea23440dcdcd6d85f47ac239076aa83c568ffdf28e41348 \ - --hash=sha256:55e08de1df514dc6b40fbf6264020750fea191343ad1c645ed5e7a1da5c9e78f \ - --hash=sha256:64662538e91077de6b73991e39ab0d90b0465cd510eb23ff4b2013c81a620063 \ - --hash=sha256:66bc5ed12b7a09e4ed68053eb3150c6243b6a1d82addb243bb3c6b75f48efefa \ - --hash=sha256:68cb75f902cf0bfa150ba4ebba01a831af62d54270e74ee7349c6dd62db40300 \ - --hash=sha256:69bf8935c8b4dd6455483ae4713ee21230bf6abe84a173e5587d8b9bb862bb7c \ - --hash=sha256:75924dcefba9727c39660ac0e94585fba44877839b026de7cdbf74e6c4e05b78 \ - --hash=sha256:76ad068e7b73c27eae7e620dd0bbbb95cf8089ecb661b50a02af771f845649a8 \ - --hash=sha256:7c24ae9f88caf9cb503c4641051cb89978cb677e0db0e1ef28eb3e3615e1473f \ - --hash=sha256:7c78caf3aeeed4243843be887a3056f0b0ef5d148f2035e2bd8decd3f8760399 \ - --hash=sha256:7e6b23587c7ef5c33c22b830e9ad93d0cc90d498526aec970467cac51065cfd7 \ - --hash=sha256:83478aa71633e1bc555c8607d6716c365d2e7bfdb1296588f386e29b464983cc \ - --hash=sha256:9159ac864c0fadd785de64aabf875e8bb1a97303871dff745a5ae647cc7d449f \ - --hash=sha256:9c16c54d3ae023a85ca278609c3a1fef9ccbfaa3d96c1a7d789b3c7faaf32262 \ - --hash=sha256:9d3174b1944391777d4549c29a88dbb5214e4ef7194d3cfcd3d338706f58d6bc \ - --hash=sha256:a27bf20184c491d42501989f04fa0228e4b062dd9b09b0ff9766a7968b92dcfb \ - --hash=sha256:acc1009501b651504aa7c6c0d1e21dd0974d1c36a77b10407c31c91fef359ffe \ - --hash=sha256:ad76bf2b433836d3730052113b357cfcb62accefd145b822bbf0fd0e537047c1 \ - --hash=sha256:b4730b1ac6f4d932628f44609ac4754b642d1138eb9f0c3934e7cfe344dfc590 \ - --hash=sha256:c00e38d3d621b3e14f2566257c4b95efc7769cb0673172ae0aeeb9114169dc62 \ - --hash=sha256:c109c35964bff0b0ed8adaa47d3a07d620188b451c4f7a1cbfda7e4d2db852d6 \ - --hash=sha256:c1f3daf18324c3ac4c56ddc594bc122dd9512c55df9410ae08a4df325e63df03 \ - --hash=sha256:c522fd0ee6adc0c9bac97cd4c079993301b79919dfdacfb6310eecfb62c050e7 \ - --hash=sha256:c6f19acaf8b2de034bae55ab82e154ed9194c5c5d454fde72012e9f44e9c52fa \ - --hash=sha256:cc0dfa69da660fa2847c79c0698e0ebfb5309afae14b53fb29121475860cfacb \ - --hash=sha256:d783d69eadc8d1b5f6581e3e1d82e8ea0af8f9a2386c795d35b4a2ac845f6f5a \ - --hash=sha256:d94a8e8e66e3a97ac4e7bbfce2a8a27f8b56d87bfa32739cac209159f5c186eb \ - --hash=sha256:dc91654e353b22980d4e34ca212e1eaa063b047110f8db7d1739a7ca8fbb44e6 \ - --hash=sha256:dceb4201905993dcf7efa56678d30c12f82c195c14249292b9f381bd91940f65 \ - --hash=sha256:dd1f9d8ac9b95027a36ba66e00bf82297e041e8682e68bc1dc5a4ab08d091e28 \ - --hash=sha256:de312c2a1be01c3015e8ac1ebd742f28843d12c1352359b4070c65fbbb6e1cb0 \ - --hash=sha256:dfd2b70a91debe45b9ad5470a87e7cf904e06981bc90c0380e5bd62da27c4393 \ - --hash=sha256:e3b31bb62f538ea70d0a285c8519c86707f7030ac505001f31596baca4cacd1e \ - --hash=sha256:e47d9270b2e6fcadd691f6958ae15a365e80edfb2ea002348ea0f045dc2485c3 \ - --hash=sha256:e4f2fd9df304ada18fbd4a8ef8008cbe77d64d163102ee173d4f05b86f00a7c5 \ - --hash=sha256:e70da2df99fff309285a4f25b774e05d82d01c60ff68dc414de9f292ad2508b4 \ - --hash=sha256:e9429c5241bf1fdeb92678705857aa06ef4bb2b923e382a7e76dc83b14eff615 \ - --hash=sha256:f5db1b8032d6a252040eb4fecb6a330de4712133d0d75b0fbf7cbee1ba7ade61 \ - --hash=sha256:ffde6e5bda89af1217bd888175e5854b5e7539b1e9efc715de48c908fe072561 +clickhouse-connect==0.15.1 \ + --hash=sha256:08df7857ecd2e345abbbdfc54d80fa060732cf75c953940355140af9a73b730a \ + --hash=sha256:0bef871fb9803ae82b4dc1f797b6e784de0a4dec351591191a0c1a6008548284 \ + --hash=sha256:158325a06978f91a182967341188502a0761447d1e13ffa775cf017def1a3d9e \ + --hash=sha256:167e674dff8ac12be7796d93190b6fe9097c042940b3c41d87fe4d85970be27d \ + --hash=sha256:1ef6922c8887a8b0db49a81823ef031807c971f628a363f6d53b030abaefd589 \ + --hash=sha256:1ff5d10c6e49d36ee6941f52c4233f2bfb4198e9c726fed224f725974a667e37 \ + --hash=sha256:24cdfe9b486c8f2e66f5f51b1f322d89d9eb4df29d9ebb2fa19b553065651e85 \ + --hash=sha256:265f1660e8db5006ca32e8894e6c6cc984b343d96171ab0580b2104084b0fc08 \ + --hash=sha256:2e19c9daabe4c24027006e903d0ba3f2a6b2e0703af37b2536335ac4558d541e \ + --hash=sha256:2e52e20190004ed4578b803b1d5f2097c336fafec41b2cc0d490b5a4964c1284 \ + --hash=sha256:371a201ee128ba2b47bd05e2f184b0d20fb78171d27441a6fb1183f4fcc9316e \ + --hash=sha256:3b456d469db994b188bb0b5afa373e8f2e5e2bf41a70a736b9ed2485a976e9ae \ + --hash=sha256:3cf1b78abf7e1b97ab279a2b244357c40657d2d8504ff3f713c6577cd0550b38 \ + --hash=sha256:46bcebd00aff52ea5f7433e9cee1157b411dba9187f6677a18378c799c27c8aa \ + --hash=sha256:4bf70933ab860bd2f0a872db624603706bed400c915c7aeef382956cf8ebbdf3 \ + --hash=sha256:4f87d283399cbda676c8765605bf60dc6559df6fd38cbb9ea07048a4b34dda26 \ + --hash=sha256:5046cb96d1c344c35198fe072a21ce3f273754df3e58fd0a6222c9a1aff72e75 \ + --hash=sha256:5462bad97d97919a4ed230e2ef28d0b76bec0354a343218647830aac7744a43b \ + --hash=sha256:57ad606e878fd284242713449217a0c475fde6b9b7ab59e7ba9e9c388431f004 \ + --hash=sha256:5ab0d019c18d9d63b228ce2e45768f6c65fd27067d1127ab3e558c35c90f52ef \ + --hash=sha256:5de299ada0f7eb9090bb5a6304d8d78163d4d9cc8eb04d8f552bfb82bafb61d5 \ + --hash=sha256:60aa8c9c775d22db324260265f4c656f803fbc71de9193ef83cf8d8d0ef6ab9a \ + --hash=sha256:691cbf6d3dd16988feb75d43942bb212f50f0cbec284eb249e0cd33ebf74ad09 \ + --hash=sha256:693a03e44256886ac5dd26dc708833913157ec72e3b3a44fb89fd5fc202f85dc \ + --hash=sha256:6f9619f9e8885886039e451c2e22d3fb9bd2e95bc64bbf4ebe6c0a50875785f4 \ + --hash=sha256:7586fae639db65d6ff9f7d539aaac04ebd8604657751d78f6b45e7f971be83f3 \ + --hash=sha256:76699fb79c0de182f915d96a08c15afc19755d9d0e9c93411abb0e4b539c7166 \ + --hash=sha256:7a590116037ae56fab339b625f317d7c0a15bbede5f2f206ce1e55b1a2385e90 \ + --hash=sha256:82e60e108d78e32d58a0f21570b02d3baad67ccbad6482eeb79d74a616d8a5ad \ + --hash=sha256:83d881bf786b05489ccf96f07972b9c28638b513f3e064d39987d837749b35e3 \ + --hash=sha256:859c718cb93780dd681f75d59ceaf4415915fa9617a5ba2de6105e291d6df3ad \ + --hash=sha256:873d8f74eaec141f40ae060318c32353da94fdd4601f925bfd52426f3ddcd689 \ + --hash=sha256:8bb70307589099c67dfe9a973998491bc82c1af9040560b5ebab799721bb197d \ + --hash=sha256:9610ef6ff653f8a030f50e39cdeb1a39bea925c48f9196d787ea4b9f5eb1c8f0 \ + --hash=sha256:99d55aab64fdeb53d74c16d2c46ae5491e90aa37ba55c24884a68a869418ee8e \ + --hash=sha256:a1266a52bf61f0420630f625c5ac87bc2d095f08321820546300a699d4300ba3 \ + --hash=sha256:a326e2f5518d6a9d71f0895d50a3ccd8c4d5e3abb625f39330512ff3c45c6731 \ + --hash=sha256:a9d1e12bf86cd96626f74d21e3ac237abcda105f55cd2e78d139197d35f86209 \ + --hash=sha256:aa9890507aac52a8a5363813bb315b6867e86a97ffa08576cb934603f5bc0216 \ + --hash=sha256:ae24e4e7b10ff140c9041d9bdb2c08781145d844c7486c2661d223ededce7634 \ + --hash=sha256:aeb09a6f8585f3bd4d8c5bead38f3821c076e0bca08c474a7b9039732a6e2e9a \ + --hash=sha256:aed10f7615d0c72457d21ace9b59bfcbea0293188af2ffa3f3c2942d36974e7c \ + --hash=sha256:b2f5174fc6001a1555fc3cb565f3b727e1b786d572df0b30d14929ae13bd3542 \ + --hash=sha256:b692998e6dea344a4a2d7c34c129379767a068f234e1cb721ba27f1f023c70ee \ + --hash=sha256:b6d107b5f964af97f25a0d1bfd59fe3510f2a646c87ad4f9ab9014bb0c66aa1c \ + --hash=sha256:b8236c7dd675ed13d5e96f1f9126eeb711e8c266e4a0476ebc32be8a17decb32 \ + --hash=sha256:c12d9f2b2fc57adaf5ea267804f00e520771794641227ed5285e38fdf36557a6 \ + --hash=sha256:cd41ebe8b7f1c2579b22bbc414a800f3f8f5c843928019aca27c81592f70c5a7 \ + --hash=sha256:cdeee50fb2822e4f886d9676c5979b9e6f93ee9159b1aa1b7d62e71bcf7ae551 \ + --hash=sha256:d0dad989ae193c7261b12c9829f219fc1cb1ae9cad380c35cfe489f139c03ee9 \ + --hash=sha256:d10e8f42bafa12d43dd280d157af1ca5a1743e0ca94e61de94c1d00cb1b2da2b \ + --hash=sha256:d3fca3e0781b664556690decc788e7d25691043bf67a0d241e9c29233a2990d5 \ + --hash=sha256:d6e98c0cf53db3b24dc0ff9f522fcf13205b1d191c632567d1744fbd4671741f \ + --hash=sha256:d75324bb3a611eeb8c22b7fdda7c2cbc6ddbcc3871c65624b97f219430ded282 \ + --hash=sha256:df93fa024d6ed46dbc3182b6202180be4cf2bbe9c331dcb21f85963b1b3fd1e5 \ + --hash=sha256:e1a157205efd47884c22bfe061fc6f8c9aea844929ee755c47b446093805d21a \ + --hash=sha256:e307ea69dc2a6e6d942d2799ee8bfe20c99019ddf95121cbeaf7efbb97f79f09 \ + --hash=sha256:e702b77720ae6fd501e5a52262518dddb6c705fbc122bca4567694fb0bab401f \ + --hash=sha256:e88a31bbd9da7f4b49de39d21e8c93c8fbb5cf487071e935af0eba884681df00 \ + --hash=sha256:e911cffe6a9d9d27ccf91b8060086254c152c48ade47c1de3fc8e91d22cdd143 \ + --hash=sha256:eb595e820e46ccdffd702d23e4d1d1efadaa60db81a3da53e693ab055d8a3b1a \ + --hash=sha256:ecf244f91fc72e5dfe83652baf69a7ced414e9147288138897bc4376ebd6f8ac \ + --hash=sha256:f03814b6e6a72892ce913eaef3931e6d011068480e9c19b80e5c640fdac55109 \ + --hash=sha256:f13c34ad1ddb0d1efc92bc4039b50b534da94c51bbce25e61484bfd28b231cb5 \ + --hash=sha256:f25df0298ecea9c29768ab1267ff1186aacfff0cbd75ff3b588644043f313cd6 \ + --hash=sha256:f2aaf5fc0bb3098c24f0d8ca7e4ecbe605a26957481dfca2c8cef9d1fad7b7ca \ + --hash=sha256:fa01fdb92db6bf72cb9509eecd0a0057a4558a4f40c02eebffbc2d61b644620e # via feast (pyproject.toml) cloudpickle==3.1.2 \ --hash=sha256:7fda9eb655c9c230dab534f1983763de5835249750e85fbcef43aaa30a9a2414 \ @@ -722,142 +743,164 @@ couchbase-columnar==1.0.0 \ --hash=sha256:fc0fad2d386c5b5df7aaaccd8751e01caa886cc640cc8c92523dd07c4e7be519 \ --hash=sha256:fc4efa3e15190c3731478006de494b046bc57785e9c8ae99ac8b375a91683e38 # via feast (pyproject.toml) -coverage[toml]==7.13.4 \ - --hash=sha256:01d4cbc3c283a17fc1e42d614a119f7f438eabb593391283adca8dc86eff1246 \ - --hash=sha256:02231499b08dabbe2b96612993e5fc34217cdae907a51b906ac7fca8027a4459 \ - --hash=sha256:0dd7ab8278f0d58a0128ba2fca25824321f05d059c1441800e934ff2efa52129 \ - --hash=sha256:0e086334e8537ddd17e5f16a344777c1ab8194986ec533711cbe6c41cde841b6 \ - --hash=sha256:0fc31c787a84f8cd6027eba44010517020e0d18487064cd3d8968941856d1415 \ - --hash=sha256:14375934243ee05f56c45393fe2ce81fe5cc503c07cee2bdf1725fb8bef3ffaf \ - --hash=sha256:1731dc33dc276dafc410a885cbf5992f1ff171393e48a21453b78727d090de80 \ - --hash=sha256:19bc3c88078789f8ef36acb014d7241961dbf883fd2533d18cb1e7a5b4e28b11 \ - --hash=sha256:1af1641e57cf7ba1bd67d677c9abdbcd6cc2ab7da3bca7fa1e2b7e50e65f2ad0 \ - --hash=sha256:1d4be36a5114c499f9f1f9195e95ebf979460dbe2d88e6816ea202010ba1c34b \ - --hash=sha256:200dea7d1e8095cc6e98cdabe3fd1d21ab17d3cee6dab00cadbb2fe35d9c15b9 \ - --hash=sha256:23e3f687cf945070d1c90f85db66d11e3025665d8dafa831301a0e0038f3db9b \ - --hash=sha256:2421d591f8ca05b308cf0092807308b2facbefe54af7c02ac22548b88b95c98f \ - --hash=sha256:245e37f664d89861cf2329c9afa2c1fe9e6d4e1a09d872c947e70718aeeac505 \ - --hash=sha256:25381386e80ae727608e662474db537d4df1ecd42379b5ba33c84633a2b36d47 \ - --hash=sha256:25a41c3104d08edb094d9db0d905ca54d0cd41c928bb6be3c4c799a54753af55 \ - --hash=sha256:296f8b0af861d3970c2a4d8c91d48eb4dd4771bcef9baedec6a9b515d7de3def \ - --hash=sha256:29e3220258d682b6226a9b0925bc563ed9a1ebcff3cad30f043eceea7eaf2689 \ - --hash=sha256:2a09cfa6a5862bc2fc6ca7c3def5b2926194a56b8ab78ffcf617d28911123012 \ - --hash=sha256:2b0f6ccf3dbe577170bebfce1318707d0e8c3650003cb4b3a9dd744575daa8b5 \ - --hash=sha256:2c048ea43875fbf8b45d476ad79f179809c590ec7b79e2035c662e7afa3192e3 \ - --hash=sha256:2cb0f1e000ebc419632bbe04366a8990b6e32c4e0b51543a6484ffe15eaeda95 \ - --hash=sha256:2fa8d5f8de70688a28240de9e139fa16b153cc3cbb01c5f16d88d6505ebdadf9 \ - --hash=sha256:300deaee342f90696ed186e3a00c71b5b3d27bffe9e827677954f4ee56969601 \ - --hash=sha256:30b8d0512f2dc8c8747557e8fb459d6176a2c9e5731e2b74d311c03b78451997 \ - --hash=sha256:33901f604424145c6e9c2398684b92e176c0b12df77d52db81c20abd48c3794c \ - --hash=sha256:3599eb3992d814d23b35c536c28df1a882caa950f8f507cef23d1cbf334995ac \ - --hash=sha256:391ee8f19bef69210978363ca930f7328081c6a0152f1166c91f0b5fdd2a773c \ - --hash=sha256:3998e5a32e62fdf410c0dbd3115df86297995d6e3429af80b8798aad894ca7aa \ - --hash=sha256:3c06f0f1337c667b971ca2f975523347e63ec5e500b9aa5882d91931cd3ef750 \ - --hash=sha256:40aa8808140e55dc022b15d8aa7f651b6b3d68b365ea0398f1441e0b04d859c3 \ - --hash=sha256:40d74da8e6c4b9ac18b15331c4b5ebc35a17069410cad462ad4f40dcd2d50c0d \ - --hash=sha256:4223b4230a376138939a9173f1bdd6521994f2aff8047fae100d6d94d50c5a12 \ - --hash=sha256:48685fee12c2eb3b27c62f2658e7ea21e9c3239cba5a8a242801a0a3f6a8c62a \ - --hash=sha256:4c7d3cc01e7350f2f0f6f7036caaf5673fb56b6998889ccfe9e1c1fe75a9c932 \ - --hash=sha256:4e83efc079eb39480e6346a15a1bcb3e9b04759c5202d157e1dd4303cd619356 \ - --hash=sha256:4fc7fa81bbaf5a02801b65346c8b3e657f1d93763e58c0abdf7c992addd81a92 \ - --hash=sha256:53d133df809c743eb8bce33b24bcababb371f4441340578cd406e084d94a6148 \ - --hash=sha256:590c0ed4bf8e85f745e6b805b2e1c457b2e33d5255dd9729743165253bc9ad39 \ - --hash=sha256:5b856a8ccf749480024ff3bd7310adaef57bf31fd17e1bfc404b7940b6986634 \ - --hash=sha256:65dfcbe305c3dfe658492df2d85259e0d79ead4177f9ae724b6fb245198f55d6 \ - --hash=sha256:6f01afcff62bf9a08fb32b2c1d6e924236c0383c02c790732b6537269e466a72 \ - --hash=sha256:6fdef321fdfbb30a197efa02d48fcd9981f0d8ad2ae8903ac318adc653f5df98 \ - --hash=sha256:71ca20079dd8f27fcf808817e281e90220475cd75115162218d0e27549f95fef \ - --hash=sha256:725d985c5ab621268b2edb8e50dfe57633dc69bda071abc470fed55a14935fd3 \ - --hash=sha256:75eab1ebe4f2f64d9509b984f9314d4aa788540368218b858dad56dc8f3e5eb9 \ - --hash=sha256:75fcd519f2a5765db3f0e391eb3b7d150cce1a771bf4c9f861aeab86c767a3c0 \ - --hash=sha256:76451d1978b95ba6507a039090ba076105c87cc76fc3efd5d35d72093964d49a \ - --hash=sha256:784fc3cf8be001197b652d51d3fd259b1e2262888693a4636e18879f613a62a9 \ - --hash=sha256:78cdf0d578b15148b009ccf18c686aa4f719d887e76e6b40c38ffb61d264a552 \ - --hash=sha256:79be69cf7f3bf9b0deeeb062eab7ac7f36cd4cc4c4dd694bd28921ba4d8596cc \ - --hash=sha256:79e73a76b854d9c6088fe5d8b2ebe745f8681c55f7397c3c0a016192d681045f \ - --hash=sha256:7b322db1284a2ed3aa28ffd8ebe3db91c929b7a333c0820abec3d838ef5b3525 \ - --hash=sha256:7d41eead3cc673cbd38a4417deb7fd0b4ca26954ff7dc6078e33f6ff97bed940 \ - --hash=sha256:7eda778067ad7ffccd23ecffce537dface96212576a07924cbf0d8799d2ded5a \ - --hash=sha256:7f57b33491e281e962021de110b451ab8a24182589be17e12a22c79047935e23 \ - --hash=sha256:8041b6c5bfdc03257666e9881d33b1abc88daccaf73f7b6340fb7946655cd10f \ - --hash=sha256:8248977c2e33aecb2ced42fef99f2d319e9904a36e55a8a68b69207fb7e43edc \ - --hash=sha256:845f352911777a8e722bfce168958214951e07e47e5d5d9744109fa5fe77f79b \ - --hash=sha256:85480adfb35ffc32d40918aad81b89c69c9cc5661a9b8a81476d3e645321a056 \ - --hash=sha256:8e264226ec98e01a8e1054314af91ee6cde0eacac4f465cc93b03dbe0bce2fd7 \ - --hash=sha256:8e798c266c378da2bd819b0677df41ab46d78065fb2a399558f3f6cae78b2fbb \ - --hash=sha256:9181a3ccead280b828fae232df12b16652702b49d41e99d657f46cc7b1f6ec7a \ - --hash=sha256:9351229c8c8407645840edcc277f4a2d44814d1bc34a2128c11c2a031d45a5dd \ - --hash=sha256:93550784d9281e374fb5a12bf1324cc8a963fd63b2d2f223503ef0fd4aa339ea \ - --hash=sha256:9401ebc7ef522f01d01d45532c68c5ac40fb27113019b6b7d8b208f6e9baa126 \ - --hash=sha256:94eb63f9b363180aff17de3e7c8760c3ba94664ea2695c52f10111244d16a299 \ - --hash=sha256:9d107aff57a83222ddbd8d9ee705ede2af2cc926608b57abed8ef96b50b7e8f9 \ - --hash=sha256:a32ebc02a1805adf637fc8dec324b5cdacd2e493515424f70ee33799573d661b \ - --hash=sha256:a3aa4e7b9e416774b21797365b358a6e827ffadaaca81b69ee02946852449f00 \ - --hash=sha256:a6f94a7d00eb18f1b6d403c91a88fd58cfc92d4b16080dfdb774afc8294469bf \ - --hash=sha256:aa3feb8db2e87ff5e6d00d7e1480ae241876286691265657b500886c98f38bda \ - --hash=sha256:ad27098a189e5838900ce4c2a99f2fe42a0bf0c2093c17c69b45a71579e8d4a2 \ - --hash=sha256:ae4578f8528569d3cf303fef2ea569c7f4c4059a38c8667ccef15c6e1f118aa5 \ - --hash=sha256:b1ec7b6b6e93255f952e27ab58fbc68dcc468844b16ecbee881aeb29b6ab4d8d \ - --hash=sha256:b507778ae8a4c915436ed5c2e05b4a6cecfa70f734e19c22a005152a11c7b6a9 \ - --hash=sha256:b66a2da594b6068b48b2692f043f35d4d3693fb639d5ea8b39533c2ad9ac3ab9 \ - --hash=sha256:b720ce6a88a2755f7c697c23268ddc47a571b88052e6b155224347389fdf6a3b \ - --hash=sha256:b7b38448866e83176e28086674fe7368ab8590e4610fb662b44e345b86d63ffa \ - --hash=sha256:b8eb931ee8e6d8243e253e5ed7336deea6904369d2fd8ae6e43f68abbf167092 \ - --hash=sha256:bb28c0f2cf2782508a40cec377935829d5fcc3ad9a3681375af4e84eb34b6b58 \ - --hash=sha256:bd60d4fe2f6fa7dff9223ca1bbc9f05d2b6697bc5961072e5d3b952d46e1b1ea \ - --hash=sha256:c35eb28c1d085eb7d8c9b3296567a1bebe03ce72962e932431b9a61f28facf26 \ - --hash=sha256:c4240e7eded42d131a2d2c4dec70374b781b043ddc79a9de4d55ca71f8e98aea \ - --hash=sha256:caa421e2684e382c5d8973ac55e4f36bed6821a9bad5c953494de960c74595c9 \ - --hash=sha256:d490ba50c3f35dd7c17953c68f3270e7ccd1c6642e2d2afe2d8e720b98f5a053 \ - --hash=sha256:d65b2d373032411e86960604dc4edac91fdfb5dca539461cf2cbe78327d1e64f \ - --hash=sha256:dae88bc0fc77edaa65c14be099bd57ee140cf507e6bfdeea7938457ab387efb0 \ - --hash=sha256:de6defc1c9badbf8b9e67ae90fd00519186d6ab64e5cc5f3d21359c2a9b2c1d3 \ - --hash=sha256:e101609bcbbfb04605ea1027b10dc3735c094d12d40826a60f897b98b1c30256 \ - --hash=sha256:e24f9156097ff9dc286f2f913df3a7f63c0e333dcafa3c196f2c18b4175ca09a \ - --hash=sha256:e2f25215f1a359ab17320b47bcdaca3e6e6356652e8256f2441e4ef972052903 \ - --hash=sha256:e5c8f6ed1e61a8b2dcdf31eb0b9bbf0130750ca79c1c49eb898e2ad86f5ccc91 \ - --hash=sha256:e6f70dec1cc557e52df5306d051ef56003f74d56e9c4dd7ddb07e07ef32a84dd \ - --hash=sha256:e856bf6616714c3a9fbc270ab54103f4e685ba236fa98c054e8f87f266c93505 \ - --hash=sha256:e87f6c587c3f34356c3759f0420693e35e7eb0e2e41e4c011cb6ec6ecbbf1db7 \ - --hash=sha256:eb30bf180de3f632cd043322dad5751390e5385108b2807368997d1a92a509d0 \ - --hash=sha256:eb88b316ec33760714a4720feb2816a3a59180fd58c1985012054fa7aebee4c2 \ - --hash=sha256:eb9078108fbf0bcdde37c3f4779303673c2fa1fe8f7956e68d447d0dd426d38a \ - --hash=sha256:ecae9737b72408d6a950f7e525f30aca12d4bd8dd95e37342e5beb3a2a8c4f71 \ - --hash=sha256:ee756f00726693e5ba94d6df2bdfd64d4852d23b09bb0bc700e3b30e6f333985 \ - --hash=sha256:f4594c67d8a7c89cf922d9df0438c7c7bb022ad506eddb0fdb2863359ff78242 \ - --hash=sha256:f53d492307962561ac7de4cd1de3e363589b000ab69617c6156a16ba7237998d \ - --hash=sha256:fb07dc5da7e849e2ad31a5d74e9bece81f30ecf5a42909d0a695f8bd1874d6af \ - --hash=sha256:fb26a934946a6afe0e326aebe0730cdff393a8bc0bbb65a2f41e30feddca399c \ - --hash=sha256:fdfc1e28e7c7cdce44985b3043bc13bbd9c747520f94a4d7164af8260b3d91f0 +coverage[toml]==7.13.5 \ + --hash=sha256:012d5319e66e9d5a218834642d6c35d265515a62f01157a45bcc036ecf947256 \ + --hash=sha256:02ca0eed225b2ff301c474aeeeae27d26e2537942aa0f87491d3e147e784a82b \ + --hash=sha256:03ccc709a17a1de074fb1d11f217342fb0d2b1582ed544f554fc9fc3f07e95f5 \ + --hash=sha256:0428cbef5783ad91fe240f673cc1f76b25e74bbfe1a13115e4aa30d3f538162d \ + --hash=sha256:04690832cbea4e4663d9149e05dba142546ca05cb1848816760e7f58285c970a \ + --hash=sha256:0590e44dd2745c696a778f7bab6aa95256de2cbc8b8cff4f7db8ff09813d6969 \ + --hash=sha256:0672854dc733c342fa3e957e0605256d2bf5934feeac328da9e0b5449634a642 \ + --hash=sha256:084b84a8c63e8d6fc7e3931b316a9bcafca1458d753c539db82d31ed20091a87 \ + --hash=sha256:0b67af5492adb31940ee418a5a655c28e48165da5afab8c7fa6fd72a142f8740 \ + --hash=sha256:0cd9ed7a8b181775459296e402ca4fb27db1279740a24e93b3b41942ebe4b215 \ + --hash=sha256:0cef0cdec915d11254a7f549c1170afecce708d30610c6abdded1f74e581666d \ + --hash=sha256:0e223ce4b4ed47f065bfb123687686512e37629be25cc63728557ae7db261422 \ + --hash=sha256:0e3c426ffc4cd952f54ee9ffbdd10345709ecc78a3ecfd796a57236bfad0b9b8 \ + --hash=sha256:0ecf12ecb326fe2c339d93fc131816f3a7367d223db37817208905c89bded911 \ + --hash=sha256:10a0c37f0b646eaff7cce1874c31d1f1ccb297688d4c747291f4f4c70741cc8b \ + --hash=sha256:145ede53ccbafb297c1c9287f788d1bc3efd6c900da23bf6931b09eafc931587 \ + --hash=sha256:1b11eef33edeae9d142f9b4358edb76273b3bfd30bc3df9a4f95d0e49caf94e8 \ + --hash=sha256:1b88c69c8ef5d4b6fe7dea66d6636056a0f6a7527c440e890cf9259011f5e606 \ + --hash=sha256:258354455f4e86e3e9d0d17571d522e13b4e1e19bf0f8596bcf9476d61e7d8a9 \ + --hash=sha256:259b69bb83ad9894c4b25be2528139eecba9a82646ebdda2d9db1ba28424a6bf \ + --hash=sha256:2aa055ae1857258f9e0045be26a6d62bdb47a72448b62d7b55f4820f361a2633 \ + --hash=sha256:2d3807015f138ffea1ed9afeeb8624fd781703f2858b62a8dd8da5a0994c57b6 \ + --hash=sha256:301e3b7dfefecaca37c9f1aa6f0049b7d4ab8dd933742b607765d757aca77d43 \ + --hash=sha256:32ca0c0114c9834a43f045a87dcebd69d108d8ffb666957ea65aa132f50332e2 \ + --hash=sha256:34b02417cf070e173989b3db962f7ed56d2f644307b2cf9d5a0f258e13084a61 \ + --hash=sha256:356e76b46783a98c2a2fe81ec79df4883a1e62895ea952968fb253c114e7f930 \ + --hash=sha256:35a31f2b1578185fbe6aa2e74cea1b1d0bbf4c552774247d9160d29b80ed56cc \ + --hash=sha256:380e8e9084d8eb38db3a9176a1a4f3c0082c3806fa0dc882d1d87abc3c789247 \ + --hash=sha256:3ad050321264c49c2fa67bb599100456fc51d004b82534f379d16445da40fb75 \ + --hash=sha256:3e1bb5f6c78feeb1be3475789b14a0f0a5b47d505bfc7267126ccbd50289999e \ + --hash=sha256:3f4818d065964db3c1c66dc0fbdac5ac692ecbc875555e13374fdbe7eedb4376 \ + --hash=sha256:460cf0114c5016fa841214ff5564aa4864f11948da9440bc97e21ad1f4ba1e01 \ + --hash=sha256:48c39bc4a04d983a54a705a6389512883d4a3b9862991b3617d547940e9f52b1 \ + --hash=sha256:4b59148601efcd2bac8c4dbf1f0ad6391693ccf7a74b8205781751637076aee3 \ + --hash=sha256:4d2afbc5cc54d286bfb54541aa50b64cdb07a718227168c87b9e2fb8f25e1743 \ + --hash=sha256:505d7083c8b0c87a8fa8c07370c285847c1f77739b22e299ad75a6af6c32c5c9 \ + --hash=sha256:52f444e86475992506b32d4e5ca55c24fc88d73bcbda0e9745095b28ef4dc0cf \ + --hash=sha256:5b13955d31d1633cf9376908089b7cebe7d15ddad7aeaabcbe969a595a97e95e \ + --hash=sha256:5ec4af212df513e399cf11610cc27063f1586419e814755ab362e50a85ea69c1 \ + --hash=sha256:60365289c3741e4db327e7baff2a4aaacf22f788e80fa4683393891b70a89fbd \ + --hash=sha256:631efb83f01569670a5e866ceb80fe483e7c159fac6f167e6571522636104a0b \ + --hash=sha256:6697e29b93707167687543480a40f0db8f356e86d9f67ddf2e37e2dfd91a9dab \ + --hash=sha256:66a80c616f80181f4d643b0f9e709d97bcea413ecd9631e1dedc7401c8e6695d \ + --hash=sha256:67e9bc5449801fad0e5dff329499fb090ba4c5800b86805c80617b4e29809b2a \ + --hash=sha256:68a4953be99b17ac3c23b6efbc8a38330d99680c9458927491d18700ef23ded0 \ + --hash=sha256:6c36ddb64ed9d7e496028d1d00dfec3e428e0aabf4006583bb1839958d280510 \ + --hash=sha256:6e3370441f4513c6252bf042b9c36d22491142385049243253c7e48398a15a9f \ + --hash=sha256:7034b5c56a58ae5e85f23949d52c14aca2cfc6848a31764995b7de88f13a1ea0 \ + --hash=sha256:704de6328e3d612a8f6c07000a878ff38181ec3263d5a11da1db294fa6a9bdf8 \ + --hash=sha256:7132bed4bd7b836200c591410ae7d97bf7ae8be6fc87d160b2bd881df929e7bf \ + --hash=sha256:7300c8a6d13335b29bb76d7651c66af6bd8658517c43499f110ddc6717bfc209 \ + --hash=sha256:750db93a81e3e5a9831b534be7b1229df848b2e125a604fe6651e48aa070e5f9 \ + --hash=sha256:777c4d1eff1b67876139d24288aaf1817f6c03d6bae9c5cc8d27b83bcfe38fe3 \ + --hash=sha256:78e696e1cc714e57e8b25760b33a8b1026b7048d270140d25dafe1b0a1ee05a3 \ + --hash=sha256:79060214983769c7ba3f0cee10b54c97609dca4d478fa1aa32b914480fd5738d \ + --hash=sha256:7c8d4bc913dd70b93488d6c496c77f3aff5ea99a07e36a18f865bca55adef8bd \ + --hash=sha256:7f2c47b36fe7709a6e83bfadf4eefb90bd25fbe4014d715224c4316f808e59a2 \ + --hash=sha256:800bc829053c80d240a687ceeb927a94fd108bbdc68dfbe505d0d75ab578a882 \ + --hash=sha256:843ea8643cf967d1ac7e8ecd4bb00c99135adf4816c0c0593fdcc47b597fcf09 \ + --hash=sha256:8769751c10f339021e2638cd354e13adeac54004d1941119b2c96fe5276d45ea \ + --hash=sha256:8dd02af98971bdb956363e4827d34425cb3df19ee550ef92855b0acb9c7ce51c \ + --hash=sha256:8fdf453a942c3e4d99bd80088141c4c6960bb232c409d9c3558e2dbaa3998562 \ + --hash=sha256:941617e518602e2d64942c88ec8499f7fbd49d3f6c4327d3a71d43a1973032f3 \ + --hash=sha256:972a9cd27894afe4bc2b1480107054e062df08e671df7c2f18c205e805ccd806 \ + --hash=sha256:9adb6688e3b53adffefd4a52d72cbd8b02602bfb8f74dcd862337182fd4d1a4e \ + --hash=sha256:9b74db26dfea4f4e50d48a4602207cd1e78be33182bc9cbf22da94f332f99878 \ + --hash=sha256:9bb2a28101a443669a423b665939381084412b81c3f8c0fcfbac57f4e30b5b8e \ + --hash=sha256:9d44d7aa963820b1b971dbecd90bfe5fe8f81cff79787eb6cca15750bd2f79b9 \ + --hash=sha256:9dacc2ad679b292709e0f5fc1ac74a6d4d5562e424058962c7bb0c658ad25e45 \ + --hash=sha256:9ddb4f4a5479f2539644be484da179b653273bca1a323947d48ab107b3ed1f29 \ + --hash=sha256:a1a6d79a14e1ec1832cabc833898636ad5f3754a678ef8bb4908515208bf84f4 \ + --hash=sha256:a698e363641b98843c517817db75373c83254781426e94ada3197cabbc2c919c \ + --hash=sha256:ad14385487393e386e2ea988b09d62dd42c397662ac2dabc3832d71253eee479 \ + --hash=sha256:ad146744ca4fd09b50c482650e3c1b1f4dfa1d4792e0a04a369c7f23336f0400 \ + --hash=sha256:b5db73ba3c41c7008037fa731ad5459fc3944cb7452fc0aa9f822ad3533c583c \ + --hash=sha256:bd3a2fbc1c6cccb3c5106140d87cc6a8715110373ef42b63cf5aea29df8c217a \ + --hash=sha256:bdba0a6b8812e8c7df002d908a9a2ea3c36e92611b5708633c50869e6d922fdf \ + --hash=sha256:be3d4bbad9d4b037791794ddeedd7d64a56f5933a2c1373e18e9e568b9141686 \ + --hash=sha256:bf69236a9a81bdca3bff53796237aab096cdbf8d78a66ad61e992d9dac7eb2de \ + --hash=sha256:bff95879c33ec8da99fc9b6fe345ddb5be6414b41d6d1ad1c8f188d26f36e028 \ + --hash=sha256:c555b48be1853fe3997c11c4bd521cdd9a9612352de01fa4508f16ec341e6fe0 \ + --hash=sha256:c81f6515c4c40141f83f502b07bbfa5c240ba25bbe73da7b33f1e5b6120ff179 \ + --hash=sha256:c9136ff29c3a91e25b1d1552b5308e53a1e0653a23e53b6366d7c2dcbbaf8a16 \ + --hash=sha256:ce1998c0483007608c8382f4ff50164bfc5bd07a2246dd272aa4043b75e61e85 \ + --hash=sha256:cec2d83125531bd153175354055cdb7a09987af08a9430bd173c937c6d0fba2a \ + --hash=sha256:cff784eef7f0b8f6cb28804fbddcfa99f89efe4cc35fb5627e3ac58f91ed3ac0 \ + --hash=sha256:d2c87e0c473a10bffe991502eac389220533024c8082ec1ce849f4218dded810 \ + --hash=sha256:d7cfad2d6d81dd298ab6b89fe72c3b7b05ec7544bdda3b707ddaecff8d25c161 \ + --hash=sha256:d8a7a2049c14f413163e2bdabd37e41179b1d1ccb10ffc6ccc4b7a718429c607 \ + --hash=sha256:da305e9937617ee95c2e39d8ff9f040e0487cbf1ac174f777ed5eddd7a7c1f26 \ + --hash=sha256:da86cdcf10d2519e10cabb8ac2de03da1bcb6e4853790b7fbd48523332e3a819 \ + --hash=sha256:dc022073d063b25a402454e5712ef9e007113e3a676b96c5f29b2bda29352f40 \ + --hash=sha256:e0723d2c96324561b9aa76fb982406e11d93cdb388a7a7da2b16e04719cf7ca5 \ + --hash=sha256:e092b9499de38ae0fbfbc603a74660eb6ff3e869e507b50d85a13b6db9863e15 \ + --hash=sha256:e0b216a19534b2427cc201a26c25da4a48633f29a487c61258643e89d28200c0 \ + --hash=sha256:e1c85e0b6c05c592ea6d8768a66a254bfb3874b53774b12d4c89c481eb78cb90 \ + --hash=sha256:e301d30dd7e95ae068671d746ba8c34e945a82682e62918e41b2679acd2051a0 \ + --hash=sha256:e808af52a0513762df4d945ea164a24b37f2f518cbe97e03deaa0ee66139b4d6 \ + --hash=sha256:eb07647a5738b89baab047f14edd18ded523de60f3b30e75c2acc826f79c839a \ + --hash=sha256:eb7fdf1ef130660e7415e0253a01a7d5a88c9c4d158bcf75cbbd922fd65a5b58 \ + --hash=sha256:ec10e2a42b41c923c2209b846126c6582db5e43a33157e9870ba9fb70dc7854b \ + --hash=sha256:ee2aa19e03161671ec964004fb74b2257805d9710bf14a5c704558b9d8dbaf17 \ + --hash=sha256:f08fd75c50a760c7eb068ae823777268daaf16a80b918fa58eea888f8e3919f5 \ + --hash=sha256:f4cd16206ad171cbc2470dbea9103cf9a7607d5fe8c242fdf1edf36174020664 \ + --hash=sha256:f70c9ab2595c56f81a89620e22899eea8b212a4041bd728ac6f4a28bf5d3ddd0 \ + --hash=sha256:fbabfaceaeb587e16f7008f7795cd80d20ec548dc7f94fbb0d4ec2e038ce563f # via pytest-cov -cryptography==43.0.3 \ - --hash=sha256:0c580952eef9bf68c4747774cde7ec1d85a6e61de97281f2dba83c7d2c806362 \ - --hash=sha256:0f996e7268af62598f2fc1204afa98a3b5712313a55c4c9d434aef49cadc91d4 \ - --hash=sha256:1ec0bcf7e17c0c5669d881b1cd38c4972fade441b27bda1051665faaa89bdcaa \ - --hash=sha256:281c945d0e28c92ca5e5930664c1cefd85efe80e5c0d2bc58dd63383fda29f83 \ - --hash=sha256:2ce6fae5bdad59577b44e4dfed356944fbf1d925269114c28be377692643b4ff \ - --hash=sha256:315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805 \ - --hash=sha256:443c4a81bb10daed9a8f334365fe52542771f25aedaf889fd323a853ce7377d6 \ - --hash=sha256:4a02ded6cd4f0a5562a8887df8b3bd14e822a90f97ac5e544c162899bc467664 \ - --hash=sha256:53a583b6637ab4c4e3591a15bc9db855b8d9dee9a669b550f311480acab6eb08 \ - --hash=sha256:63efa177ff54aec6e1c0aefaa1a241232dcd37413835a9b674b6e3f0ae2bfd3e \ - --hash=sha256:74f57f24754fe349223792466a709f8e0c093205ff0dca557af51072ff47ab18 \ - --hash=sha256:7e1ce50266f4f70bf41a2c6dc4358afadae90e2a1e5342d3c08883df1675374f \ - --hash=sha256:81ef806b1fef6b06dcebad789f988d3b37ccaee225695cf3e07648eee0fc6b73 \ - --hash=sha256:846da004a5804145a5f441b8530b4bf35afbf7da70f82409f151695b127213d5 \ - --hash=sha256:8ac43ae87929a5982f5948ceda07001ee5e83227fd69cf55b109144938d96984 \ - --hash=sha256:9762ea51a8fc2a88b70cf2995e5675b38d93bf36bd67d91721c309df184f49bd \ - --hash=sha256:a2a431ee15799d6db9fe80c82b055bae5a752bef645bba795e8e52687c69efe3 \ - --hash=sha256:bf7a1932ac4176486eab36a19ed4c0492da5d97123f1406cf15e41b05e787d2e \ - --hash=sha256:c2e6fc39c4ab499049df3bdf567f768a723a5e8464816e8f009f121a5a9f4405 \ - --hash=sha256:cbeb489927bd7af4aa98d4b261af9a5bc025bd87f0e3547e11584be9e9427be2 \ - --hash=sha256:d03b5621a135bffecad2c73e9f4deb1a0f977b9a8ffe6f8e002bf6c9d07b918c \ - --hash=sha256:d56e96520b1020449bbace2b78b603442e7e378a9b3bd68de65c782db1507995 \ - --hash=sha256:df6b6c6d742395dd77a23ea3728ab62f98379eff8fb61be2744d4679ab678f73 \ - --hash=sha256:e1be4655c7ef6e1bbe6b5d0403526601323420bcf414598955968c9ef3eb7d16 \ - --hash=sha256:f18c716be16bc1fea8e95def49edf46b82fccaa88587a45f8dc0ff6ab5d8e0a7 \ - --hash=sha256:f46304d6f0c6ab8e52770addfa2fc41e6629495548862279641972b6215451cd \ - --hash=sha256:f7b178f11ed3664fd0e995a47ed2b5ff0a12d893e41dd0494f406d1cf555cab7 +cryptography==46.0.6 \ + --hash=sha256:02fad249cb0e090b574e30b276a3da6a149e04ee2f049725b1f69e7b8351ec70 \ + --hash=sha256:063b67749f338ca9c5a0b7fe438a52c25f9526b851e24e6c9310e7195aad3b4d \ + --hash=sha256:12cae594e9473bca1a7aceb90536060643128bb274fcea0fc459ab90f7d1ae7a \ + --hash=sha256:12f0fa16cc247b13c43d56d7b35287ff1569b5b1f4c5e87e92cc4fcc00cd10c0 \ + --hash=sha256:22259338084d6ae497a19bae5d4c66b7ca1387d3264d1c2c0e72d9e9b6a77b97 \ + --hash=sha256:26031f1e5ca62fcb9d1fcb34b2b60b390d1aacaa15dc8b895a9ed00968b97b30 \ + --hash=sha256:27550628a518c5c6c903d84f637fbecf287f6cb9ced3804838a1295dc1fd0759 \ + --hash=sha256:2b417edbe8877cda9022dde3a008e2deb50be9c407eef034aeeb3a8b11d9db3c \ + --hash=sha256:2ea0f37e9a9cf0df2952893ad145fd9627d326a59daec9b0802480fa3bcd2ead \ + --hash=sha256:2ef9e69886cbb137c2aef9772c2e7138dc581fad4fcbcf13cc181eb5a3ab6275 \ + --hash=sha256:341359d6c9e68834e204ceaf25936dffeafea3829ab80e9503860dcc4f4dac58 \ + --hash=sha256:380343e0653b1c9d7e1f55b52aaa2dbb2fdf2730088d48c43ca1c7c0abb7cc2f \ + --hash=sha256:3c21d92ed15e9cfc6eb64c1f5a0326db22ca9c2566ca46d845119b45b4400361 \ + --hash=sha256:3dfa6567f2e9e4c5dceb8ccb5a708158a2a871052fa75c8b78cb0977063f1507 \ + --hash=sha256:456b3215172aeefb9284550b162801d62f5f264a081049a3e94307fe20792cfa \ + --hash=sha256:4668298aef7cddeaf5c6ecc244c2302a2b8e40f384255505c22875eebb47888b \ + --hash=sha256:50575a76e2951fe7dbd1f56d181f8c5ceeeb075e9ff88e7ad997d2f42af06e7b \ + --hash=sha256:639301950939d844a9e1c4464d7e07f902fe9a7f6b215bb0d4f28584729935d8 \ + --hash=sha256:64235194bad039a10bb6d2d930ab3323baaec67e2ce36215fd0952fad0930ca8 \ + --hash=sha256:6617f67b1606dfd9fe4dbfa354a9508d4a6d37afe30306fe6c101b7ce3274b72 \ + --hash=sha256:67177e8a9f421aa2d3a170c3e56eca4e0128883cf52a071a7cbf53297f18b175 \ + --hash=sha256:6728c49e3b2c180ef26f8e9f0a883a2c585638db64cf265b49c9ba10652d430e \ + --hash=sha256:6739d56300662c468fddb0e5e291f9b4d084bead381667b9e654c7dd81705124 \ + --hash=sha256:69cf0056d6947edc6e6760e5f17afe4bea06b56a9ac8a06de9d2bd6b532d4f3a \ + --hash=sha256:760997a4b950ff00d418398ad73fbc91aa2894b5c1db7ccb45b4f68b42a63b3c \ + --hash=sha256:79e865c642cfc5c0b3eb12af83c35c5aeff4fa5c672dc28c43721c2c9fdd2f0f \ + --hash=sha256:7e6142674f2a9291463e5e150090b95a8519b2fb6e6aaec8917dd8d094ce750d \ + --hash=sha256:7f417f034f91dcec1cb6c5c35b07cdbb2ef262557f701b4ecd803ee8cefed4f4 \ + --hash=sha256:7f6690b6c55e9c5332c0b59b9c8a3fb232ebf059094c17f9019a51e9827df91c \ + --hash=sha256:8927ccfbe967c7df312ade694f987e7e9e22b2425976ddbf28271d7e58845290 \ + --hash=sha256:8ce35b77aaf02f3b59c90b2c8a05c73bac12cea5b4e8f3fbece1f5fddea5f0ca \ + --hash=sha256:8e7304c4f4e9490e11efe56af6713983460ee0780f16c63f219984dab3af9d2d \ + --hash=sha256:90e5f0a7b3be5f40c3a0a0eafb32c681d8d2c181fc2a1bdabe9b3f611d9f6b1a \ + --hash=sha256:97c8115b27e19e592a05c45d0dd89c57f81f841cc9880e353e0d3bf25b2139ed \ + --hash=sha256:9a693028b9cbe51b5a1136232ee8f2bc242e4e19d456ded3fa7c86e43c713b4a \ + --hash=sha256:9a9c42a2723999a710445bc0d974e345c32adfd8d2fac6d8a251fa829ad31cfb \ + --hash=sha256:a3e84d5ec9ba01f8fd03802b2147ba77f0c8f2617b2aff254cedd551844209c8 \ + --hash=sha256:aad75154a7ac9039936d50cf431719a2f8d4ed3d3c277ac03f3339ded1a5e707 \ + --hash=sha256:b12c6b1e1651e42ab5de8b1e00dc3b6354fdfd778e7fa60541ddacc27cd21410 \ + --hash=sha256:b928a3ca837c77a10e81a814a693f2295200adb3352395fad024559b7be7a736 \ + --hash=sha256:bcb87663e1f7b075e48c3be3ecb5f0b46c8fc50b50a97cf264e7f60242dca3f2 \ + --hash=sha256:c797e2517cb7880f8297e2c0f43bb910e91381339336f75d2c1c2cbf811b70b4 \ + --hash=sha256:c89eb37fae9216985d8734c1afd172ba4927f5a05cfd9bf0e4863c6d5465b013 \ + --hash=sha256:cdcd3edcbc5d55757e5f5f3d330dd00007ae463a7e7aa5bf132d1f22a4b62b19 \ + --hash=sha256:d24c13369e856b94892a89ddf70b332e0b70ad4a5c43cf3e9cb71d6d7ffa1f7b \ + --hash=sha256:d4e4aadb7fc1f88687f47ca20bb7227981b03afaae69287029da08096853b738 \ + --hash=sha256:d9528b535a6c4f8ff37847144b8986a9a143585f0540fbcb1a98115b543aa463 \ + --hash=sha256:ed3775295fb91f70b4027aeba878d79b3e55c0b3e97eaa4de71f8f23a9f2eb77 \ + --hash=sha256:ed418c37d095aeddf5336898a132fba01091f0ac5844e3e8018506f014b6d2c4 # via # feast (pyproject.toml) # azure-identity @@ -867,28 +910,29 @@ cryptography==43.0.3 \ # jwcrypto # moto # msal + # oracledb # pyjwt # pyopenssl # snowflake-connector-python # types-pyopenssl # types-redis -dask[dataframe]==2026.1.2 \ - --hash=sha256:1136683de2750d98ea792670f7434e6c1cfce90cab2cc2f2495a9e60fd25a4fc \ - --hash=sha256:46a0cf3b8d87f78a3d2e6b145aea4418a6d6d606fe6a16c79bd8ca2bb862bc91 +dask[dataframe]==2026.3.0 \ + --hash=sha256:be614b9242b0b38288060fb2d7696125946469c98a1c30e174883fd199e0428d \ + --hash=sha256:f7d96c8274e8a900d217c1ff6ea8d1bbf0b4c2c21e74a409644498d925eb8f85 # via feast (pyproject.toml) -datasets==4.5.0 \ - --hash=sha256:00c698ce1c2452e646cc5fad47fef39d3fe78dd650a8a6eb205bb45eb63cd500 \ - --hash=sha256:b5d7e08096ffa407dd69e58b1c0271c9b2506140839b8d99af07375ad31b6726 +datasets==4.8.4 \ + --hash=sha256:a1429ed853275ce7943a01c6d2e25475b4501eb758934362106a280470df3a52 \ + --hash=sha256:cdc8bee4698e549d78bf1fed6aea2eebc760b22b084f07e6fc020c6577a6ce6d # via feast (pyproject.toml) -db-dtypes==1.5.0 \ - --hash=sha256:abdbb2e4eb965800ed6f98af0c5c1cafff9063ace09114be2d26a7f046be2c8a \ - --hash=sha256:ad9e94243f53e104bc77dbf9ae44b580d83a770d3694483aba59c9767966daa5 +db-dtypes==1.5.1 \ + --hash=sha256:901099b807c9312bc61a5bddbfb07512884e6c6d5a9edacf24d50bcf303aa5f7 \ + --hash=sha256:ad71a6645e3c1f06d4d32023940576648f43119822f825f0d22587c6ef8afe15 # via # google-cloud-bigquery # pandas-gbq -dbt-artifacts-parser==0.12.0 \ - --hash=sha256:3db93df7969c3f22c6fbf75a51b0af4c21b189d8db6f3c54e8471102c775bb0d \ - --hash=sha256:9d1c0ed41926102c1c39fdd780e1a332f58c9b794e94dba0dcf5dfefc847d6ea +dbt-artifacts-parser==0.13.0 \ + --hash=sha256:304f2b857650566fed4ed8b976ed3582332eda3cedfe7167158dbbcfced3fe47 \ + --hash=sha256:55498e8bd0d9064d56617f9c714ced8607d94ccb61e70d4b49dcfd8a28a030d8 # via feast (pyproject.toml) debugpy==1.8.20 \ --hash=sha256:077a7447589ee9bc1ff0cdf443566d0ecf540ac8aa7333b775ebcb8ce9f4ecad \ @@ -964,16 +1008,16 @@ docling==2.27.0 \ --hash=sha256:1288ed75b27e33bf94daff34faffc6d11b7d7ccc13e3df84fb24adad3991f72d \ --hash=sha256:faba35662612a2c687a3a463e501d95f645316436084af92a0442ce162429a3d # via feast (pyproject.toml) -docling-core[chunking]==2.65.1 \ - --hash=sha256:3a143adb9cc613c503380eff92f5895078fc5a00fc7264f327d0d85ff60176cd \ - --hash=sha256:fcdb30254bc5046b52b8bec5919de3b6cdbeed915399cede5351ff328cdd020d +docling-core[chunking]==2.71.0 \ + --hash=sha256:4761857816853b2b35263b5b4518e1ea6214e0565db0bbf1d929fb976665d1a0 \ + --hash=sha256:4caa9f50c68b9dd332584ae16170b36db05d773532b14d7078b580d89d8bd2a4 # via # docling # docling-ibm-models # docling-parse -docling-ibm-models==3.11.0 \ - --hash=sha256:454401563a8e79cb33b718bc559d9bacca8a0183583e48f8e616c9184c1f5eb1 \ - --hash=sha256:68f7961069d643bfdab21b1c9ef24a979db293496f4c2283d95b1025a9ac5347 +docling-ibm-models==3.13.0 \ + --hash=sha256:a11acc6034b06e0bed8dc0ca1fa700615b8246eacce411619168e1f6562b0d0d \ + --hash=sha256:f402effae8a63b0e5c3b5ce13120601baa2cd8098beef1d53ab5a056443758d3 # via docling docling-parse==4.7.3 \ --hash=sha256:1790e7e4ae202d67875c1c48fd6f8ef5c51d10b0c23157e4989b8673f2f31308 \ @@ -1008,48 +1052,42 @@ docutils==0.19 \ --hash=sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6 \ --hash=sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc # via sphinx -duckdb==1.4.4 \ - --hash=sha256:0509b39ea7af8cff0198a99d206dca753c62844adab54e545984c2e2c1381616 \ - --hash=sha256:0d636ceda422e7babd5e2f7275f6a0d1a3405e6a01873f00d38b72118d30c10b \ - --hash=sha256:1af6e76fe8bd24875dc56dd8e38300d64dc708cd2e772f67b9fbc635cc3066a3 \ - --hash=sha256:1f8d55843cc940e36261689054f7dfb6ce35b1f5b0953b0d355b6adb654b0d52 \ - --hash=sha256:25874f8b1355e96178079e37312c3ba6d61a2354f51319dae860cf21335c3a20 \ - --hash=sha256:337f8b24e89bc2e12dadcfe87b4eb1c00fd920f68ab07bc9b70960d6523b8bc3 \ - --hash=sha256:452c5b5d6c349dc5d1154eb2062ee547296fcbd0c20e9df1ed00b5e1809089da \ - --hash=sha256:453b115f4777467f35103d8081770ac2f223fb5799178db5b06186e3ab51d1f2 \ - --hash=sha256:47dd4162da6a2be59a0aef640eb08d6360df1cf83c317dcc127836daaf3b7f7c \ - --hash=sha256:49123b579e4a6323e65139210cd72dddc593a72d840211556b60f9703bda8526 \ - --hash=sha256:4c25d5b0febda02b7944e94fdae95aecf952797afc8cb920f677b46a7c251955 \ - --hash=sha256:50f2eb173c573811b44aba51176da7a4e5c487113982be6a6a1c37337ec5fa57 \ - --hash=sha256:53cd6423136ab44383ec9955aefe7599b3fb3dd1fe006161e6396d8167e0e0d4 \ - --hash=sha256:5536eb952a8aa6ae56469362e344d4e6403cc945a80bc8c5c2ebdd85d85eb64b \ - --hash=sha256:59c8d76016dde854beab844935b1ec31de358d4053e792988108e995b18c08e7 \ - --hash=sha256:5ba684f498d4e924c7e8f30dd157da8da34c8479746c5011b6c0e037e9c60ad2 \ - --hash=sha256:5cdc4126ec925edf3112bc656ac9ed23745294b854935fa7a643a216e4455af6 \ - --hash=sha256:5e1933fac5293fea5926b0ee75a55b8cfe7f516d867310a5b251831ab61fe62b \ - --hash=sha256:6703dd1bb650025b3771552333d305d62ddd7ff182de121483d4e042ea6e2e00 \ - --hash=sha256:6792ca647216bd5c4ff16396e4591cfa9b4a72e5ad7cdd312cec6d67e8431a7c \ - --hash=sha256:6cb357cfa3403910e79e2eb46c8e445bb1ee2fd62e9e9588c6b999df4256abc1 \ - --hash=sha256:6fb1225a9ea5877421481d59a6c556a9532c32c16c7ae6ca8d127e2b878c9389 \ - --hash=sha256:707530f6637e91dc4b8125260595299ec9dd157c09f5d16c4186c5988bfbd09a \ - --hash=sha256:7df7351328ffb812a4a289732f500d621e7de9942a3a2c9b6d4afcf4c0e72526 \ - --hash=sha256:7eec0bf271ac622e57b7f6554a27a6e7d1dd2f43d1871f7962c74bcbbede15ba \ - --hash=sha256:8097201bc5fd0779d7fcc2f3f4736c349197235f4cb7171622936343a1aa8dbf \ - --hash=sha256:8bba52fd2acb67668a4615ee17ee51814124223de836d9e2fdcbc4c9021b3d3c \ - --hash=sha256:8e5c2d8a0452df55e092959c0bfc8ab8897ac3ea0f754cb3b0ab3e165cd79aff \ - --hash=sha256:a3c8542db7ffb128aceb7f3b35502ebaddcd4f73f1227569306cc34bad06680c \ - --hash=sha256:b297eff642503fd435a9de5a9cb7db4eccb6f61d61a55b30d2636023f149855f \ - --hash=sha256:bf138201f56e5d6fc276a25138341b3523e2f84733613fc43f02c54465619a95 \ - --hash=sha256:c65d15c440c31e06baaebfd2c06d71ce877e132779d309f1edf0a85d23c07e92 \ - --hash=sha256:c9566a4ed834ec7999db5849f53da0a7ee83d86830c33f471bf0211a1148ca12 \ - --hash=sha256:cd1be3d48577f5b40eb9706c6b2ae10edfe18e78eb28e31a3b922dcff1183597 \ - --hash=sha256:d0440f59e0cd9936a9ebfcf7a13312eda480c79214ffed3878d75947fc3b7d6d \ - --hash=sha256:d525de5f282b03aa8be6db86b1abffdceae5f1055113a03d5b50cd2fb8cf2ef8 \ - --hash=sha256:ddcfd9c6ff234da603a1edd5fd8ae6107f4d042f74951b65f91bc5e2643856b3 \ - --hash=sha256:e041f2fbd6888da090eca96ac167a7eb62d02f778385dd9155ed859f1c6b6dc8 \ - --hash=sha256:e870a441cb1c41d556205deb665749f26347ed13b3a247b53714f5d589596977 \ - --hash=sha256:f28a18cc790217e5b347bb91b2cab27aafc557c58d3d8382e04b4fe55d0c3f66 \ - --hash=sha256:fb94de6d023de9d79b7edc1ae07ee1d0b4f5fa8a9dcec799650b5befdf7aafec +duckdb==1.5.1 \ + --hash=sha256:054ad424b051b334052afac58cb216f3b1ebb8579fc8c641e60f0182e8725ea9 \ + --hash=sha256:05fc91767d0cfc4cf2fa68966ab5b479ac07561752e42dd0ae30327bd160f64a \ + --hash=sha256:0a6acc2040bec1f05de62a2f3f68f4c12f3ec7d6012b4317d0ab1a195af26225 \ + --hash=sha256:26e56b5f0c96189e3288d83cf7b476e23615987902f801e5788dee15ee9f24a9 \ + --hash=sha256:36e8e32621a9e2a9abe75dc15a4b54a3997f2d8b1e53ad754bae48a083c91130 \ + --hash=sha256:40c5220ec93790b18ec6278da9c6ac2608d997ee6d6f7cd44c5c3992764e8e71 \ + --hash=sha256:446d500a2977c6ae2077f340c510a25956da5c77597175c316edfa87248ceda3 \ + --hash=sha256:46f92ada9023e59f27edc048167b31ac9a03911978b1296c845a34462a27f096 \ + --hash=sha256:482f8a13f2600f527e427f73c42b5aa75536f9892868068f0aaf573055a0135f \ + --hash=sha256:553c273a6a8f140adaa6da6a6135c7f95bdc8c2e5f95252fcdf9832d758e2141 \ + --hash=sha256:5ae7c0d744d64e2753149634787cc4ab60f05ef1e542b060eeab719f3cdb7723 \ + --hash=sha256:5d4147422d91ccdc2d2abf6ed24196025e020259d1d267970ae20c13c2ce84b1 \ + --hash=sha256:6af347debc8b721aa72e48671166282da979d5e5ae52dbc660ab417282b48e23 \ + --hash=sha256:6ba302115f63f6482c000ccfd62efdb6c41d9d182a5bcd4a90e7ab8cd13856eb \ + --hash=sha256:6f7361d66cc801d9eb4df734b139cd7b0e3c257a16f3573ebd550ddb255549e6 \ + --hash=sha256:715f05ea198d20d7f8b407b9b84e0023d17f2b9096c194cea702b7840e74f1f7 \ + --hash=sha256:71dddcebbc5a70e946a06c30b59b5dd7999c9833d307168f90fb4e4b672ab63e \ + --hash=sha256:8150c569b2aa4573b51ba8475e814aa41fd53a3d510c1ffb96f1139f46faf611 \ + --hash=sha256:8843bd9594e1387f1e601439e19ad73abdf57356104fd1e53a708255bb95a13d \ + --hash=sha256:8c0088765747ae5d6c9f89987bb36f9fb83564f07090d721344ce8e1abedffea \ + --hash=sha256:972d0dbf283508f9bc446ee09c3838cb7c7f114b5bdceee41753288c97fe2f7c \ + --hash=sha256:a28531cee2a5a42d89f9ba4da53bfeb15681f12acc0263476c8705380dadce07 \ + --hash=sha256:a3be2072315982e232bfe49c9d3db0a59ba67b2240a537ef42656cc772a887c7 \ + --hash=sha256:ac2804043bd1bc10b5da18f8f4c706877197263a510c41be9b4c0062f5783dcc \ + --hash=sha256:afab8b4b1f4469c3879bb049dd039f8fce402712050324e9524a43d7324c5e87 \ + --hash=sha256:b370d1620a34a4538ef66524fcee9de8171fa263c701036a92bc0b4c1f2f9c6d \ + --hash=sha256:b8b0808dba0c63b7633bdaefb34e08fe0612622224f9feb0e7518904b1615101 \ + --hash=sha256:bc7ca6a1a40e7e4c933017e6c09ef18032add793df4e42624c6c0c87e0bebdad \ + --hash=sha256:caa65e1f5bf007430bf657c37cab7ab81a4ddf8d337e3062bcc5085d17ef038b \ + --hash=sha256:d68c5a01a283cb13b79eafe016fe5869aa11bff8c46e7141c70aa0aac808010f \ + --hash=sha256:da137802688190835b4c863cafa77fd7e29dff662ee6d905a9ffc14f00299c91 \ + --hash=sha256:e56a20ab6cdb90a95b0c99652e28de3504ce77129087319c03c9098266183ae5 \ + --hash=sha256:e878ccb7d20872065e1597935fdb5e65efa43220c8edd0d9c4a1a7ff1f3eb277 \ + --hash=sha256:eba81e0b3011c1f23df7ea47ef4ffaa8239817959ae291515b6efd068bde2161 \ + --hash=sha256:ed6d23a3f806898e69c77430ebd8da0c79c219f97b9acbc9a29a653e09740c59 # via ibis-framework durationpy==0.10 \ --hash=sha256:1fa6893409a6e739c9c72334fc65cca1f355dbdd93405d30f726deb5bde42fba \ @@ -1116,9 +1154,9 @@ faiss-cpu==1.10.0 \ --hash=sha256:e71f7e24d5b02d3a51df47b77bd10f394a1b48a8331d5c817e71e9e27a8a75ac \ --hash=sha256:f71c5860c860df2320299f9e4f2ca1725beb559c04acb1cf961ed24e6218277a # via feast (pyproject.toml) -fastapi==0.129.0 \ - --hash=sha256:61315cebd2e65df5f97ec298c888f9de30430dd0612d59d6480beafbc10655af \ - --hash=sha256:b4946880e48f462692b31c083be0432275cbfb6e2274566b1be91479cc1a84ec +fastapi==0.135.3 \ + --hash=sha256:9b0f590c813acd13d0ab43dd8494138eb58e484bfac405db1f3187cfc5810d98 \ + --hash=sha256:bd6d7caf1a2bdd8d676843cdcd2287729572a1ef524fc4d65c17ae002a1be654 # via # feast (pyproject.toml) # fastapi-mcp @@ -1130,9 +1168,9 @@ fastjsonschema==2.21.2 \ --hash=sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463 \ --hash=sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de # via nbformat -filelock==3.24.2 \ - --hash=sha256:667d7dc0b7d1e1064dd5f8f8e80bdac157a6482e8d2e02cd16fd3b6b33bd6556 \ - --hash=sha256:c22803117490f156e59fafce621f0550a7a853e2bbf4f87f112b11d469b6c81b +filelock==3.25.2 \ + --hash=sha256:b64ece2b38f4ca29dd3e810287aa8c48182bbecd1ae6e9ae126c9b35f1382694 \ + --hash=sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70 # via # datasets # huggingface-hub @@ -1296,9 +1334,9 @@ geomet==1.1.0 \ --hash=sha256:4372fe4e286a34acc6f2e9308284850bd8c4aa5bc12065e2abbd4995900db12f \ --hash=sha256:51e92231a0ef6aaa63ac20c443377ba78a303fd2ecd179dc3567de79f3c11605 # via cassandra-driver -google-api-core[grpc]==2.29.0 \ - --hash=sha256:84181be0f8e6b04006df75ddfe728f24489f0af57c96a529ff7cf45bc28797f7 \ - --hash=sha256:d30bc60980daa36e314b5d5a3e5958b0200cb44ca8fa1be2b614e932b75a3ea9 +google-api-core[grpc]==2.30.2 \ + --hash=sha256:9a8113e1a88bdc09a7ff629707f2214d98d61c7f6ceb0ea38c42a095d02dc0f9 \ + --hash=sha256:a4c226766d6af2580577db1f1a51bf53cd262f722b49731ce7414c43068a9594 # via # feast (pyproject.toml) # google-cloud-bigquery @@ -1308,9 +1346,9 @@ google-api-core[grpc]==2.29.0 \ # google-cloud-datastore # google-cloud-storage # pandas-gbq -google-auth==2.48.0 \ - --hash=sha256:2e2a537873d449434252a9632c28bfc268b0adb1e53f9fb62afc5333a975903f \ - --hash=sha256:4f7e706b0cd3208a3d940a19a822c37a476ddba5450156c3e6624a71f7c841ce +google-auth==2.49.1 \ + --hash=sha256:16d40da1c3c5a0533f57d268fe72e0ebb0ae1cc3b567024122651c045d879b64 \ + --hash=sha256:195ebe3dca18eddd1b3db5edc5189b76c13e96f29e73043b923ebcf3f1a860f7 # via # google-api-core # google-auth-oauthlib @@ -1322,37 +1360,37 @@ google-auth==2.48.0 \ # google-cloud-storage # pandas-gbq # pydata-google-auth -google-auth-oauthlib==1.2.4 \ - --hash=sha256:0e922eea5f2baacaf8867febb782e46e7b153236c21592ed76ab3ddb77ffd772 \ - --hash=sha256:3ca93859c6cc9003c8e12b2a0868915209d7953f05a70f4880ab57d57e56ee3e +google-auth-oauthlib==1.3.1 \ + --hash=sha256:14c22c7b3dd3d06dbe44264144409039465effdd1eef94f7ce3710e486cc4bfa \ + --hash=sha256:1a139ef23f1318756805b0e95f655c238bffd29655329a2978218248da4ee7f8 # via # pandas-gbq # pydata-google-auth -google-cloud-bigquery[pandas]==3.40.1 \ - --hash=sha256:75afcfb6e007238fe1deefb2182105249321145ff921784fe7b1de2b4ba24506 \ - --hash=sha256:9082a6b8193aba87bed6a2c79cf1152b524c99bb7e7ac33a785e333c09eac868 +google-cloud-bigquery[pandas]==3.41.0 \ + --hash=sha256:2217e488b47ed576360c9b2cc07d59d883a54b83167c0ef37f915c26b01a06fe \ + --hash=sha256:2a5b5a737b401cbd824a6e5eac7554100b878668d908e6548836b5d8aaa4dcaa # via # feast (pyproject.toml) # pandas-gbq -google-cloud-bigquery-storage==2.36.1 \ - --hash=sha256:99ad6b8810d028f0cf368ea0cc54b3cda20e856f05eb4cda51f1db2a70692286 \ - --hash=sha256:fd3917584a41f7a9d9c633b31ff43103869b108224e8a4b765537eb1ea83148c +google-cloud-bigquery-storage==2.37.0 \ + --hash=sha256:1e319c27ef60fc31030f6e0b52e5e891e1cdd50551effe8c6f673a4c3c56fcb6 \ + --hash=sha256:f88ee7f1e49db1e639da3d9a8b79835ca4bc47afbb514fb2adfc0ccb41a7fd97 # via feast (pyproject.toml) -google-cloud-bigtable==2.35.0 \ - --hash=sha256:f355bfce1f239453ec2bb3839b0f4f9937cf34ef06ef29e1ca63d58fd38d0c50 \ - --hash=sha256:f5699012c5fea4bd4bdf7e80e5e3a812a847eb8f41bf8dc2f43095d6d876b83b +google-cloud-bigtable==2.36.0 \ + --hash=sha256:21b2f41231b7368a550b44d5b493b811b3507fcb23eb26d00005cd3f205f2207 \ + --hash=sha256:d5987733c2f60c739f93f259d2037858411cc994ac37cdfbccb6bb159f3ca43e # via feast (pyproject.toml) -google-cloud-core==2.5.0 \ - --hash=sha256:67d977b41ae6c7211ee830c7912e41003ea8194bff15ae7d72fd6f51e57acabc \ - --hash=sha256:7c1b7ef5c92311717bd05301aa1a91ffbc565673d3b0b4163a52d8413a186963 +google-cloud-core==2.5.1 \ + --hash=sha256:3dc94bdec9d05a31d9f355045ed0f369fbc0d8c665076c734f065d729800f811 \ + --hash=sha256:ea62cdf502c20e3e14be8a32c05ed02113d7bef454e40ff3fab6fe1ec9f1f4e7 # via # google-cloud-bigquery # google-cloud-bigtable # google-cloud-datastore # google-cloud-storage -google-cloud-datastore==2.23.0 \ - --hash=sha256:24a1b1d29b902148fe41b109699f76fd3aa60591e9d547c0f8b87d7bf9ff213f \ - --hash=sha256:80049883a4ae928fdcc661ba6803ec267665dc0e6f3ce2da91441079a6bb6387 +google-cloud-datastore==2.24.0 \ + --hash=sha256:81f1d1c12c2906f59507f72742545ab04c38f62ed70b0542057e3cf04a53aa65 \ + --hash=sha256:f087c02a6aa4ac68bbf17f0c048ae3ee355856bf09c51439bfba193741387792 # via feast (pyproject.toml) google-cloud-storage==2.19.0 \ --hash=sha256:aeb971b5c29cf8ab98445082cbfe7b161a1f48ed275822f59ed3f1524ea54fba \ @@ -1396,15 +1434,15 @@ google-crc32c==1.8.0 \ # google-cloud-bigtable # google-cloud-storage # google-resumable-media -google-resumable-media==2.8.0 \ - --hash=sha256:dd14a116af303845a8d932ddae161a26e86cc229645bc98b39f026f9b1717582 \ - --hash=sha256:f1157ed8b46994d60a1bc432544db62352043113684d4e030ee02e77ebe9a1ae +google-resumable-media==2.8.2 \ + --hash=sha256:82b6d8ccd11765268cdd2a2123f417ec806b8eef3000a9a38dfe3033da5fb220 \ + --hash=sha256:f3354a182ebd193ae3f42e3ef95e6c9b10f128320de23ac7637236713b1acd70 # via # google-cloud-bigquery # google-cloud-storage -googleapis-common-protos[grpc]==1.72.0 \ - --hash=sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038 \ - --hash=sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5 +googleapis-common-protos[grpc]==1.74.0 \ + --hash=sha256:57971e4eeeba6aad1163c1f0fc88543f965bb49129b8bb55b2b7b26ecab084f1 \ + --hash=sha256:702216f78610bb510e3f12ac3cafd281b7ac45cc5d86e90ad87e4d301a3426b5 # via # feast (pyproject.toml) # google-api-core @@ -1414,9 +1452,9 @@ great-expectations==0.18.8 \ --hash=sha256:ab41cfa3de829a4f77bdcd4a23244684cbb67fdacc734d38910164cd02ec95b6 \ --hash=sha256:c1205bede593f679e22e0b3826d6ae1623c439cafd553f9f0bc2b0fd441f6ed9 # via feast (pyproject.toml) -grpc-google-iam-v1==0.14.3 \ - --hash=sha256:7a7f697e017a067206a3dfef44e4c634a34d3dee135fe7d7a4613fe3e59217e6 \ - --hash=sha256:879ac4ef33136c5491a6300e27575a9ec760f6cdf9a2518798c1b8977a5dc389 +grpc-google-iam-v1==0.14.4 \ + --hash=sha256:392b3796947ed6334e61171d9ab06bf7eb357f554e5fc7556ad7aab6d0e17038 \ + --hash=sha256:412facc320fcbd94034b4df3d557662051d4d8adfa86e0ddb4dca70a3f739964 # via google-cloud-bigtable grpcio==1.62.3 \ --hash=sha256:059444f0ed5dba73ab7dd0ee7e8e6b606df4130d2b0a9f010f84da4ab9f6c2d8 \ @@ -1486,7 +1524,6 @@ grpcio==1.62.3 \ # grpcio-status # grpcio-testing # grpcio-tools - # ikvpy # pymilvus # qdrant-client grpcio-health-checking==1.62.3 \ @@ -1500,9 +1537,7 @@ grpcio-reflection==1.62.3 \ grpcio-status==1.62.3 \ --hash=sha256:289bdd7b2459794a12cf95dc0cb727bd4a1742c37bd823f760236c937e53a485 \ --hash=sha256:f9049b762ba8de6b1086789d8315846e094edac2c50beaf462338b301a8fd4b8 - # via - # google-api-core - # ikvpy + # via google-api-core grpcio-testing==1.62.3 \ --hash=sha256:06a4d7eb30d22f91368aa7f48bfc33563da13b9d951314455ca8c9c987fb75bb \ --hash=sha256:f63577f28aaa95ea525124a0fd63c3429d71f769f4179b13f5e6cbc54979bfab @@ -1557,9 +1592,9 @@ grpcio-tools==1.62.3 \ --hash=sha256:f4b1615adf67bd8bb71f3464146a6f9949972d06d21a4f5e87e73f6464d97f57 \ --hash=sha256:f6831fdec2b853c9daa3358535c55eed3694325889aa714070528cf8f92d7d6d # via feast (pyproject.toml) -gunicorn==25.1.0 \ - --hash=sha256:1426611d959fa77e7de89f8c0f32eed6aa03ee735f98c01efba3e281b1c47616 \ - --hash=sha256:d0b1236ccf27f72cfe14bce7caadf467186f19e865094ca84221424e839b8b8b +gunicorn==25.3.0 \ + --hash=sha256:cacea387dab08cd6776501621c295a904fe8e3b7aae9a1a3cbb26f4e7ed54660 \ + --hash=sha256:f74e1b2f9f76f6cd1ca01198968bd2dd65830edc24b6e8e4d78de8320e2fe889 # via # feast (pyproject.toml) # uvicorn-worker @@ -1581,29 +1616,32 @@ hazelcast-python-client==5.6.0 \ --hash=sha256:834b87076a47c781ef80bdcb522b86abc75ff28992dfe384e47f669f06cabb18 \ --hash=sha256:e2cec409068990ca9b4381fe97160cc2375412334782bef45ab4c8fe4d10536c # via feast (pyproject.toml) -hf-xet==1.2.0 \ - --hash=sha256:10bfab528b968c70e062607f663e21e34e2bba349e8038db546646875495179e \ - --hash=sha256:210d577732b519ac6ede149d2f2f34049d44e8622bf14eb3d63bbcd2d4b332dc \ - --hash=sha256:27df617a076420d8845bea087f59303da8be17ed7ec0cd7ee3b9b9f579dff0e4 \ - --hash=sha256:293a7a3787e5c95d7be1857358a9130694a9c6021de3f27fa233f37267174382 \ - --hash=sha256:29c8fc913a529ec0a91867ce3d119ac1aac966e098cf49501800c870328cc090 \ - --hash=sha256:2a212e842647b02eb6a911187dc878e79c4aa0aa397e88dd3b26761676e8c1f8 \ - --hash=sha256:30e06daccb3a7d4c065f34fc26c14c74f4653069bb2b194e7f18f17cbe9939c0 \ - --hash=sha256:3651fd5bfe0281951b988c0facbe726aa5e347b103a675f49a3fa8144c7968fd \ - --hash=sha256:46740d4ac024a7ca9b22bebf77460ff43332868b661186a8e46c227fdae01848 \ - --hash=sha256:4c1428c9ae73ec0939410ec73023c4f842927f39db09b063b9482dac5a3bb737 \ - --hash=sha256:66e159cbfcfbb29f920db2c09ed8b660eb894640d284f102ada929b6e3dc410a \ - --hash=sha256:6de1fc44f58f6dd937956c8d304d8c2dea264c80680bcfa61ca4a15e7b76780f \ - --hash=sha256:7d40b18769bb9a8bc82a9ede575ce1a44c75eb80e7375a01d76259089529b5dc \ - --hash=sha256:9c91d5ae931510107f148874e9e2de8a16052b6f1b3ca3c1b12f15ccb491390f \ - --hash=sha256:a55558084c16b09b5ed32ab9ed38421e2d87cf3f1f89815764d1177081b99865 \ - --hash=sha256:a8c27070ca547293b6890c4bf389f713f80e8c478631432962bb7f4bc0bd7d7f \ - --hash=sha256:b70218dd548e9840224df5638fdc94bd033552963cfa97f9170829381179c813 \ - --hash=sha256:cd3a6027d59cfb60177c12d6424e31f4b5ff13d8e3a1247b3a584bf8977e6df5 \ - --hash=sha256:ceeefcd1b7aed4956ae8499e2199607765fbd1c60510752003b6cc0b8413b649 \ - --hash=sha256:d06fa97c8562fb3ee7a378dd9b51e343bc5bc8190254202c9771029152f5e08c \ - --hash=sha256:e6584a52253f72c9f52f9e549d5895ca7a471608495c4ecaa6cc73dba2b24d69 \ - --hash=sha256:f182f264ed2acd566c514e45da9f2119110e48a87a327ca271027904c70c5832 +hf-xet==1.4.3 \ + --hash=sha256:0392c79b7cf48418cd61478c1a925246cf10639f4cd9d94368d8ca1e8df9ea07 \ + --hash=sha256:1feb0f3abeacee143367c326a128a2e2b60868ec12a36c225afb1d6c5a05e6d2 \ + --hash=sha256:21644b404bb0100fe3857892f752c4d09642586fd988e61501c95bbf44b393a3 \ + --hash=sha256:22bdc1f5fb8b15bf2831440b91d1c9bbceeb7e10c81a12e8d75889996a5c9da8 \ + --hash=sha256:27c976ba60079fb8217f485b9c5c7fcd21c90b0367753805f87cb9f3cdc4418a \ + --hash=sha256:2815a49a7a59f3e2edf0cf113ae88e8cb2ca2a221bf353fb60c609584f4884d4 \ + --hash=sha256:39f2d2e9654cd9b4319885733993807aab6de9dfbd34c42f0b78338d6617421f \ + --hash=sha256:42ee323265f1e6a81b0e11094564fb7f7e0ec75b5105ffd91ae63f403a11931b \ + --hash=sha256:49ad8a8cead2b56051aa84d7fce3e1335efe68df3cf6c058f22a65513885baac \ + --hash=sha256:5251d5ece3a81815bae9abab41cf7ddb7bcb8f56411bce0827f4a3071c92fdc6 \ + --hash=sha256:60cf7fc43a99da0a853345cf86d23738c03983ee5249613a6305d3e57a5dca74 \ + --hash=sha256:681c92a07796325778a79d76c67011764ecc9042a8c3579332b61b63ae512075 \ + --hash=sha256:6b591fcad34e272a5b02607485e4f2a1334aebf1bc6d16ce8eb1eb8978ac2021 \ + --hash=sha256:7551659ba4f1e1074e9623996f28c3873682530aee0a846b7f2f066239228144 \ + --hash=sha256:7716d62015477a70ea272d2d68cd7cad140f61c52ee452e133e139abfe2c17ba \ + --hash=sha256:7c2c7e20bcfcc946dc67187c203463f5e932e395845d098cc2a93f5b67ca0b47 \ + --hash=sha256:8b301fc150290ca90b4fccd079829b84bb4786747584ae08b94b4577d82fb791 \ + --hash=sha256:8ddedb73c8c08928c793df2f3401ec26f95be7f7e516a7bee2fbb546f6676113 \ + --hash=sha256:987f09cfe418237812896a6736b81b1af02a3a6dcb4b4944425c4c4fca7a7cf8 \ + --hash=sha256:bee693ada985e7045997f05f081d0e12c4c08bd7626dc397f8a7c487e6c04f7f \ + --hash=sha256:c5b48db1ee344a805a1b9bd2cda9b6b65fe77ed3787bd6e87ad5521141d317cd \ + --hash=sha256:d0da85329eaf196e03e90b84c2d0aca53bd4573d097a75f99609e80775f98025 \ + --hash=sha256:d972fbe95ddc0d3c0fc49b31a8a69f47db35c1e3699bf316421705741aab6653 \ + --hash=sha256:e23717ce4186b265f69afa66e6f0069fe7efbf331546f5c313d00e123dc84583 \ + --hash=sha256:fc360b70c815bf340ed56c7b8c63aacf11762a4b099b2fe2c9bd6d6068668c08 # via huggingface-hub hiredis==2.4.0 \ --hash=sha256:06815c3b9bf7225c4dcc9dd9dfb5a9fa91b4f680104443ef3fcd78410d7eb027 \ @@ -1778,6 +1816,7 @@ huggingface-hub==0.36.2 \ # datasets # docling # docling-ibm-models + # sentence-transformers # timm # tokenizers # transformers @@ -1785,13 +1824,13 @@ hyperframe==6.1.0 \ --hash=sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5 \ --hash=sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08 # via h2 -ibis-framework[duckdb, mssql]==12.0.0 \ +ibis-framework[duckdb, mssql, oracle]==12.0.0 \ --hash=sha256:0bbd790f268da9cb87926d5eaad2b827a573927113c4ed3be5095efa89b9e512 \ --hash=sha256:238624f2c14fdab8382ca2f4f667c3cdb81e29844cd5f8db8a325d0743767c61 # via feast (pyproject.toml) -identify==2.6.16 \ - --hash=sha256:391ee4d77741d994189522896270b787aed8670389bfd60f326d677d64a6dfb0 \ - --hash=sha256:846857203b5511bbe94d5a352a48ef2359532bc8f6727b5544077a0dcfb24980 +identify==2.6.18 \ + --hash=sha256:873ac56a5e3fd63e7438a7ecbc4d91aca692eb3fefa4534db2b7913f3fc352fd \ + --hash=sha256:8db9d3c8ea9079db92cafb0ebf97abdc09d52e97f4dcf773a2e694048b7cd737 # via pre-commit idna==3.11 \ --hash=sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea \ @@ -1803,21 +1842,17 @@ idna==3.11 \ # requests # snowflake-connector-python # yarl -ikvpy==0.0.36 \ - --hash=sha256:b0edf6fb6482877940f6c2b5d59a7fabe30cb554b13b88ca52805f043cfda5b3 \ - --hash=sha256:c0ce7dfb61456c283c9ba2cdeb68b3647f245c3905bca652ca2a1068804939d1 - # via feast (pyproject.toml) -imageio==2.37.2 \ - --hash=sha256:0212ef2727ac9caa5ca4b2c75ae89454312f440a756fcfc8ef1993e718f50f8a \ - --hash=sha256:ad9adfb20335d718c03de457358ed69f141021a333c40a53e57273d8a5bd0b9b +imageio==2.37.3 \ + --hash=sha256:46f5bb8522cd421c0f5ae104d8268f569d856b29eb1a13b92829d1970f32c9f0 \ + --hash=sha256:bbb37efbfc4c400fcd534b367b91fcd66d5da639aaa138034431a1c5e0a41451 # via scikit-image -imagesize==1.4.1 \ - --hash=sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b \ - --hash=sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a +imagesize==2.0.0 \ + --hash=sha256:5667c5bbb57ab3f1fa4bc366f4fbc971db3d5ed011fd2715fd8001f782718d96 \ + --hash=sha256:8e8358c4a05c304f1fccf7ff96f036e7243a189e9e42e90851993c558cfe9ee3 # via sphinx -importlib-metadata==8.7.1 \ - --hash=sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb \ - --hash=sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151 +importlib-metadata==9.0.0 \ + --hash=sha256:2d21d1cc5a017bd0559e36150c21c830ab1dc304dedd1b7ea85d20f45ef3edd7 \ + --hash=sha256:a4f57ab599e6a2e3016d7595cfd72eb4661a5106e787a95bcc90c7105b831efc # via # build # dask @@ -1833,9 +1868,9 @@ ipykernel==7.2.0 \ --hash=sha256:18ed160b6dee2cbb16e5f3575858bc19d8f1fe6046a9a680c708494ce31d909e \ --hash=sha256:3bbd4420d2b3cc105cbdf3756bfc04500b1e52f090a90716851f3916c62e1661 # via jupyterlab -ipython==8.38.0 \ - --hash=sha256:750162629d800ac65bb3b543a14e7a74b0e88063eac9b92124d4b2aa3f6d8e86 \ - --hash=sha256:9cfea8c903ce0867cc2f23199ed8545eb741f3a69420bfcf3743ad1cec856d39 +ipython==8.39.0 \ + --hash=sha256:4110ae96012c379b8b6db898a07e186c40a2a1ef5d57a7fa83166047d9da7624 \ + --hash=sha256:bb3c51c4fa8148ab1dea07a79584d1c854e234ea44aa1283bcb37bc75054651f # via # great-expectations # ipykernel @@ -1881,9 +1916,9 @@ joblib==1.5.3 \ --hash=sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713 \ --hash=sha256:8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3 # via scikit-learn -json5==0.13.0 \ - --hash=sha256:9a08e1dd65f6a4d4c6fa82d216cf2477349ec2346a38fd70cc11d2557499fbcc \ - --hash=sha256:b1edf8d487721c0bf64d83c28e91280781f6e21f4a797d3261c7c828d4c165bf +json5==0.14.0 \ + --hash=sha256:56cf861bab076b1178eb8c92e1311d273a9b9acea2ccc82c276abf839ebaef3a \ + --hash=sha256:b3f492fad9f6cdbced8b7d40b28b9b1c9701c5f561bef0d33b81c2ff433fefcb # via jupyterlab-server jsonlines==4.0.0 \ --hash=sha256:0c6d2c09117550c089995247f605ae4cf77dd1533041d366351f6f298822ea74 \ @@ -1893,9 +1928,9 @@ jsonpatch==1.33 \ --hash=sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade \ --hash=sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c # via great-expectations -jsonpointer==3.0.0 \ - --hash=sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942 \ - --hash=sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef +jsonpointer==3.1.1 \ + --hash=sha256:0b801c7db33a904024f6004d526dcc53bbb8a4a0f4e32bfd10beadf60adf1900 \ + --hash=sha256:8ff8b95779d071ba472cf5bc913028df06031797532f08a7d5b602d8b2a488ca # via # jsonpatch # jsonschema @@ -1942,9 +1977,9 @@ jupyter-events==0.12.0 \ --hash=sha256:6464b2fa5ad10451c3d35fabc75eab39556ae1e2853ad0c0cc31b656731a97fb \ --hash=sha256:fc3fce98865f6784c9cd0a56a20644fc6098f21c8c33834a8d9fe383c17e554b # via jupyter-server -jupyter-lsp==2.3.0 \ - --hash=sha256:458aa59339dc868fb784d73364f17dbce8836e906cd75fd471a325cba02e0245 \ - --hash=sha256:e914a3cb2addf48b1c7710914771aaf1819d46b2e5a79b0f917b5478ec93f34f +jupyter-lsp==2.3.1 \ + --hash=sha256:71b954d834e85ff3096400554f2eefaf7fe37053036f9a782b0f7c5e42dadb81 \ + --hash=sha256:fdf8a4aa7d85813976d6e29e95e6a2c8f752701f926f2715305249a3829805a6 # via jupyterlab jupyter-server==2.17.0 \ --hash=sha256:c38ea898566964c888b4772ae1ed58eca84592e88251d2cfc4d171f81f7e99d5 \ @@ -1959,9 +1994,9 @@ jupyter-server-terminals==0.5.4 \ --hash=sha256:55be353fc74a80bc7f3b20e6be50a55a61cd525626f578dcb66a5708e2007d14 \ --hash=sha256:bbda128ed41d0be9020349f9f1f2a4ab9952a73ed5f5ac9f1419794761fb87f5 # via jupyter-server -jupyterlab==4.5.4 \ - --hash=sha256:c215f48d8e4582bd2920ad61cc6a40d8ebfef7e5a517ae56b8a9413c9789fdfb \ - --hash=sha256:cc233f70539728534669fb0015331f2a3a87656207b3bb2d07916e9289192f12 +jupyterlab==4.5.6 \ + --hash=sha256:642fe2cfe7f0f5922a8a558ba7a0d246c7bc133b708dfe43f7b3a826d163cf42 \ + --hash=sha256:d6b3dac883aa4d9993348e0f8e95b24624f75099aed64eab6a4351a9cdd1e580 # via notebook jupyterlab-pygments==0.3.0 \ --hash=sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d \ @@ -1989,13 +2024,13 @@ lark==1.3.1 \ --hash=sha256:b426a7a6d6d53189d318f2b6236ab5d6429eaf09259f1ca33eb716eed10d2905 \ --hash=sha256:c629b661023a014c37da873b4ff58a817398d12635d3bbb2c5a03be7fe5d1e12 # via rfc3987-syntax -latex2mathml==3.78.1 \ - --hash=sha256:f089b6d75e85b937f99693c93e8c16c0804008672c3dd2a3d25affd36f238100 \ - --hash=sha256:f941db80bf41db33f31df87b304e8b588f8166b813b0257c11c98f7a9d0aac71 +latex2mathml==3.79.0 \ + --hash=sha256:11bde318c2d2d6fcdd105a07509d867cee2208f653278eb80243dec7ea77a0ce \ + --hash=sha256:9f10720d4fcf6b22d1b81f6628237832419a7a29783c13aa92fa8d680165e63d # via docling-core -lazy-loader==0.4 \ - --hash=sha256:342aa8e14d543a154047afb4ba8ef17f5563baad3fc610d7b15b213b0f119efc \ - --hash=sha256:47c75182589b91a4e1a85a136c074285a5ad4d9f39c63e0d7fb76391c4574cd1 +lazy-loader==0.5 \ + --hash=sha256:717f9179a0dbed357012ddad50a5ad3d5e4d9a0b8712680d4e687f5e6e6ed9b3 \ + --hash=sha256:ab0ea149e9c554d4ffeeb21105ac60bed7f3b4fd69b1d2360a4add51b170b005 # via scikit-image locket==1.0.0 \ --hash=sha256:5c0d4c052a8bbbf750e056a8e65ccd309086f4f0f18a2eac306a8dfa4112a632 \ @@ -2315,9 +2350,9 @@ matplotlib-inline==0.2.1 \ # via # ipykernel # ipython -mcp==1.26.0 \ - --hash=sha256:904a21c33c25aa98ddbeb47273033c435e595bbacfdb177f4bd87f6dceebe1ca \ - --hash=sha256:db6e2ef491eecc1a0d93711a76f28dec2e05999f93afd48795da1c1137142c66 +mcp==1.27.0 \ + --hash=sha256:5ce1fa81614958e267b21fb2aa34e0aea8e2c6ede60d52aba45fd47246b4d741 \ + --hash=sha256:d3dc35a7eec0d458c1da4976a48f982097ddaab87e278c5511d5a4a56e852b83 # via fastapi-mcp mdurl==0.1.2 \ --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ @@ -2341,128 +2376,114 @@ mistune==3.2.0 \ # via # great-expectations # nbconvert -mmh3==5.2.0 \ - --hash=sha256:03e08c6ebaf666ec1e3d6ea657a2d363bb01effd1a9acfe41f9197decaef0051 \ - --hash=sha256:097e13c8b8a66c5753c6968b7640faefe85d8e38992703c1f666eda6ef4c3762 \ - --hash=sha256:0b898cecff57442724a0f52bf42c2de42de63083a91008fb452887e372f9c328 \ - --hash=sha256:10983c10f5c77683bd845751905ba535ec47409874acc759d5ce3ff7ef34398a \ - --hash=sha256:11730eeb16dfcf9674fdea9bb6b8e6dd9b40813b7eb839bc35113649eef38aeb \ - --hash=sha256:127c95336f2a98c51e7682341ab7cb0be3adb9df0819ab8505a726ed1801876d \ - --hash=sha256:12da42c0a55c9d86ab566395324213c319c73ecb0c239fad4726324212b9441c \ - --hash=sha256:132dd943451a7c7546978863d2f5a64977928410782e1a87d583cb60eb89e667 \ - --hash=sha256:1556e31e4bd0ac0c17eaf220be17a09c171d7396919c3794274cb3415a9d3646 \ - --hash=sha256:1a5f4d2e59d6bba8ef01b013c472741835ad961e7c28f50c82b27c57748744a4 \ - --hash=sha256:1ba55d6ca32eeef8b2625e1e4bfc3b3db52bc63014bd7e5df8cc11bf2b036b12 \ - --hash=sha256:1efc8fec8478e9243a78bb993422cf79f8ff85cb4cf6b79647480a31e0d950a8 \ - --hash=sha256:1f8d8b627799f4e2fcc7c034fed8f5f24dc7724ff52f69838a3d6d15f1ad4765 \ - --hash=sha256:1fae471339ae1b9c641f19cf46dfe6ffd7f64b1fba7c4333b99fa3dd7f21ae0a \ - --hash=sha256:1fdb36b940e9261aff0b5177c5b74a36936b902f473180f6c15bde26143681a9 \ - --hash=sha256:2421b9d665a0b1ad724ec7332fb5a98d075f50bc51a6ff854f3a1882bd650d49 \ - --hash=sha256:29c2b9ce61886809d0492a274a5a53047742dea0f703f9c4d5d223c3ea6377d3 \ - --hash=sha256:2c9da0d568569cc87315cb063486d761e38458b8ad513fedd3dc9263e1b81bcd \ - --hash=sha256:2ebfc46b39168ab1cd44670a32ea5489bcbc74a25795c61b6d888c5c2cf654ed \ - --hash=sha256:3193752fc05ea72366c2b63ff24b9a190f422e32d75fdeae71087c08fff26115 \ - --hash=sha256:33576136c06b46a7046b6d83a3d75fbca7d25f84cec743f1ae156362608dc6d2 \ - --hash=sha256:37a358cc881fe796e099c1db6ce07ff757f088827b4e8467ac52b7a7ffdca647 \ - --hash=sha256:382a6bb3f8c6532ea084e7acc5be6ae0c6effa529240836d59352398f002e3fc \ - --hash=sha256:384eda9361a7bf83a85e09447e1feafe081034af9dd428893701b959230d84be \ - --hash=sha256:38d899a156549da8ef6a9f1d6f7ef231228d29f8f69bce2ee12f5fba6d6fd7c5 \ - --hash=sha256:3bc244802ccab5220008cb712ca1508cb6a12f0eb64ad62997156410579a1770 \ - --hash=sha256:3c6041fd9d5fb5fcac57d5c80f521a36b74aea06b8566431c63e4ffc49aced51 \ - --hash=sha256:3ca975c51c5028947bbcfc24966517aac06a01d6c921e30f7c5383c195f87991 \ - --hash=sha256:3d6bfd9662a20c054bc216f861fa330c2dac7c81e7fb8307b5e32ab5b9b4d2e0 \ - --hash=sha256:419005f84ba1cab47a77465a2a843562dadadd6671b8758bf179d82a15ca63eb \ - --hash=sha256:45b590e31bc552c6f8e2150ff1ad0c28dd151e9f87589e7eaf508fbdd8e8e908 \ - --hash=sha256:49037d417419863b222ae47ee562b2de9c3416add0a45c8d7f4e864be8dc4f89 \ - --hash=sha256:4a5f5536b1cbfa72318ab3bfc8a8188b949260baed186b75f0abc75b95d8c051 \ - --hash=sha256:582f9dbeefe15c32a5fa528b79b088b599a1dfe290a4436351c6090f90ddebb8 \ - --hash=sha256:58477cf9ef16664d1ce2b038f87d2dc96d70fe50733a34a7f07da6c9a5e3538c \ - --hash=sha256:58981d6ea9646dbbf9e59a30890cbf9f610df0e4a57dbfe09215116fd90b0093 \ - --hash=sha256:5a5dba98e514fb26241868f6eb90a7f7ca0e039aed779342965ce24ea32ba513 \ - --hash=sha256:5b0b58215befe0f0e120b828f7645e97719bbba9f23b69e268ed0ac7adde8645 \ - --hash=sha256:61ac226af521a572700f863d6ecddc6ece97220ce7174e311948ff8c8919a363 \ - --hash=sha256:63830f846797187c5d3e2dae50f0848fdc86032f5bfdc58ae352f02f857e9025 \ - --hash=sha256:69fc339d7202bea69ef9bd7c39bfdf9fdabc8e6822a01eba62fb43233c1b3932 \ - --hash=sha256:6d541038b3fc360ec538fc116de87462627944765a6750308118f8b509a8eec7 \ - --hash=sha256:6ecb4e750d712abde046858ee6992b65c93f1f71b397fce7975c3860c07365d2 \ - --hash=sha256:72d80005b7634a3a2220f81fbeb94775ebd12794623bb2e1451701ea732b4aa3 \ - --hash=sha256:7303aab41e97adcf010a09efd8f1403e719e59b7705d5e3cfed3dd7571589290 \ - --hash=sha256:7434a27754049144539d2099a6d2da5d88b8bdeedf935180bf42ad59b3607aa3 \ - --hash=sha256:746a5ee71c6d1103d9b560fa147881b5e68fd35da56e54e03d5acefad0e7c055 \ - --hash=sha256:7733ec52296fc1ba22e9b90a245c821adbb943e98c91d8a330a2254612726106 \ - --hash=sha256:7901c893e704ee3c65f92d39b951f8f34ccf8e8566768c58103fb10e55afb8c1 \ - --hash=sha256:7aa18cdb58983ee660c9c400b46272e14fa253c675ed963d3812487f8ca42037 \ - --hash=sha256:7b986d506a8e8ea345791897ba5d8ba0d9d8820cd4fc3e52dbe6de19388de2e7 \ - --hash=sha256:7bbb0df897944b5ec830f3ad883e32c5a7375370a521565f5fe24443bfb2c4f7 \ - --hash=sha256:7c7f0b342fd06044bedd0b6e72177ddc0076f54fd89ee239447f8b271d919d9b \ - --hash=sha256:7e5634565367b6d98dc4aa2983703526ef556b3688ba3065edb4b9b90ede1c54 \ - --hash=sha256:7fddccd4113e7b736706e17a239a696332360cbaddf25ae75b57ba1acce65081 \ - --hash=sha256:81c504ad11c588c8629536b032940f2a359dda3b6cbfd4ad8f74cb24dcd1b0bc \ - --hash=sha256:81df0dae22cd0da87f1c978602750f33d17fb3d21fb0f326c89dc89834fea79b \ - --hash=sha256:86d1be5d63232e6eb93c50881aea55ff06eb86d8e08f9b5417c8c9b10db9db96 \ - --hash=sha256:8b0c53fe0994beade1ad7c0f13bd6fec980a0664bfbe5a6a7d64500b9ab76772 \ - --hash=sha256:8ebf241072cf2777a492d0e09252f8cc2b3edd07dfdb9404b9757bffeb4f2cee \ - --hash=sha256:931d47e08c9c8a67bf75d82f0ada8399eac18b03388818b62bfa42882d571d72 \ - --hash=sha256:932a6eec1d2e2c3c9e630d10f7128d80e70e2d47fe6b8c7ea5e1afbd98733e65 \ - --hash=sha256:941603bfd75a46023807511c1ac2f1b0f39cccc393c15039969806063b27e6db \ - --hash=sha256:956127e663d05edbeec54df38885d943dfa27406594c411139690485128525de \ - --hash=sha256:96f1e1ac44cbb42bcc406e509f70c9af42c594e72ccc7b1257f97554204445f0 \ - --hash=sha256:99bb6a4d809aa4e528ddfe2c85dd5239b78b9dd14be62cca0329db78505e7b50 \ - --hash=sha256:9f64bf06f4bf623325fda3a6d02d36cd69199b9ace99b04bb2d7fd9f89688504 \ - --hash=sha256:a094319ec0db52a04af9fdc391b4d39a1bc72bc8424b47c4411afb05413a44b5 \ - --hash=sha256:a367d4741ac0103f8198c82f429bccb9359f543ca542b06a51f4f0332e8de279 \ - --hash=sha256:a7c0c7845566b9686480e6a7e9044db4afb60038d5fabd19227443f0104eeee4 \ - --hash=sha256:aa6e5d31fdc5ed9e3e95f9873508615a778fe9b523d52c17fc770a3eb39ab6e4 \ - --hash=sha256:ae9d032488fcec32d22be6542d1a836f00247f40f320844dbb361393b5b22773 \ - --hash=sha256:b0271ac12415afd3171ab9a3c7cbfc71dee2c68760a7dc9d05bf8ed6ddfa3a7a \ - --hash=sha256:b0d753ad566c721faa33db7e2e0eddd74b224cdd3eaf8481d76c926603c7a00e \ - --hash=sha256:b29044e1ffdb84fe164d0a7ea05c7316afea93c00f8ed9449cf357c36fc4f814 \ - --hash=sha256:b5995088dd7023d2d9f310a0c67de5a2b2e06a570ecfd00f9ff4ab94a67cde43 \ - --hash=sha256:b5f317a727bba0e633a12e71228bc6a4acb4f471a98b1c003163b917311ea9a9 \ - --hash=sha256:b9a87025121d1c448f24f27ff53a5fe7b6ef980574b4a4f11acaabe702420d63 \ - --hash=sha256:bb0fdc451fb6d86d81ab8f23d881b8d6e37fc373a2deae1c02d27002d2ad7a05 \ - --hash=sha256:bb4fe46bdc6104fbc28db7a6bacb115ee6368ff993366bbd8a2a7f0076e6f0c0 \ - --hash=sha256:bc44fc2b886243d7c0d8daeb37864e16f232e5b56aaec27cc781d848264cfd28 \ - --hash=sha256:bdde97310d59604f2a9119322f61b31546748499a21b44f6715e8ced9308a6c5 \ - --hash=sha256:be1374df449465c9f2500e62eee73a39db62152a8bdfbe12ec5b5c1cd451344d \ - --hash=sha256:be7d3dca9358e01dab1bad881fb2b4e8730cec58d36dd44482bc068bfcd3bc65 \ - --hash=sha256:bf7bee43e17e81671c447e9c83499f53d99bf440bc6d9dc26a841e21acfbe094 \ - --hash=sha256:c3dca4cb5b946ee91b3d6bb700d137b1cd85c20827f89fdf9c16258253489044 \ - --hash=sha256:c3f563e8901960e2eaa64c8e8821895818acabeb41c96f2efbb936f65dbe486c \ - --hash=sha256:c463d7c1c4cfc9d751efeaadd936bbba07b5b0ed81a012b3a9f5a12f0872bd6e \ - --hash=sha256:c4a2f3d83879e3de2eb8cbf562e71563a8ed15ee9b9c2e77ca5d9f73072ac15c \ - --hash=sha256:c5584061fd3da584659b13587f26c6cad25a096246a481636d64375d0c1f6c07 \ - --hash=sha256:c677d78887244bf3095020b73c42b505b700f801c690f8eaa90ad12d3179612f \ - --hash=sha256:c903e71fd8debb35ad2a4184c1316b3cb22f64ce517b4e6747f25b0a34e41266 \ - --hash=sha256:c9ff37ba9f15637e424c2ab57a1a590c52897c845b768e4e0a4958084ec87f22 \ - --hash=sha256:cadc16e8ea64b5d9a47363013e2bea469e121e6e7cb416a7593aeb24f2ad122e \ - --hash=sha256:cedac4f4054b8f7859e5aed41aaa31ad03fce6851901a7fdc2af0275ac533c10 \ - --hash=sha256:d22c9dcafed659fadc605538946c041722b6d1104fe619dbf5cc73b3c8a0ded8 \ - --hash=sha256:d765058da196f68dc721116cab335e696e87e76720e6ef8ee5a24801af65e63d \ - --hash=sha256:d86651fa45799530885ba4dab3d21144486ed15285e8784181a0ab37a4552384 \ - --hash=sha256:dd966df3489ec13848d6c6303429bbace94a153f43d1ae2a55115fd36fd5ca5d \ - --hash=sha256:ddc63328889bcaee77b743309e5c7d2d52cee0d7d577837c91b6e7cc9e755e0b \ - --hash=sha256:dfbead5575f6470c17e955b94f92d62a03dfc3d07f2e6f817d9b93dc211a1515 \ - --hash=sha256:e0f3ed828d709f5b82d8bfe14f8856120718ec4bd44a5b26102c3030a1e12501 \ - --hash=sha256:e1861fb6b1d0453ed7293200139c0a9011eeb1376632e048e3766945b13313c5 \ - --hash=sha256:e5015f0bb6eb50008bed2d4b1ce0f2a294698a926111e4bb202c0987b4f89078 \ - --hash=sha256:e651e17bfde5840e9e4174b01e9e080ce49277b70d424308b36a7969d0d1af73 \ - --hash=sha256:e7884931fe5e788163e7b3c511614130c2c59feffdc21112290a194487efb2e9 \ - --hash=sha256:e79c00eba78f7258e5b354eccd4d7907d60317ced924ea4a5f2e9d83f5453065 \ - --hash=sha256:e912b19cf2378f2967d0c08e86ff4c6c360129887f678e27e4dde970d21b3f4d \ - --hash=sha256:e9a011469b47b752e7d20de296bb34591cdfcbe76c99c2e863ceaa2aa61113d2 \ - --hash=sha256:eb756caf8975882630ce4e9fbbeb9d3401242a72528230422c9ab3a0d278e60c \ - --hash=sha256:eba01ec3bd4a49b9ac5ca2bc6a73ff5f3af53374b8556fcc2966dd2af9eb7779 \ - --hash=sha256:ecbfc0437ddfdced5e7822d1ce4855c9c64f46819d0fdc4482c53f56c707b935 \ - --hash=sha256:eed4bba7ff8a0d37106ba931ab03bdd3915fbb025bcf4e1f0aa02bc8114960c5 \ - --hash=sha256:f35727c5118aba95f0397e18a1a5b8405425581bfe53e821f0fb444cbdc2bc9b \ - --hash=sha256:f698733a8a494466432d611a8f0d1e026f5286dee051beea4b3c3146817e35d5 \ - --hash=sha256:f7f9034c7cf05ddfaac8d7a2e63a3c97a840d4615d0a0e65ba8bdf6f8576e3be \ - --hash=sha256:fa0c966ee727aad5406d516375593c5f058c766b21236ab8985693934bb5085b \ - --hash=sha256:fc9c5f280438cf1c1a8f9abb87dc8ce9630a964120cfb5dd50d1e7ce79690c7a \ - --hash=sha256:fd6e6c3d90660d085f7e73710eab6f5545d4854b81b0135a3526e797009dbda3 \ - --hash=sha256:fdfd3fb739f4e22746e13ad7ba0c6eedf5f454b18d11249724a388868e308ee4 \ - --hash=sha256:ff3d50dc3fe8a98059f99b445dfb62792b5d006c5e0b8f03c6de2813b8376110 +mmh3==5.2.1 \ + --hash=sha256:022aa1a528604e6c83d0a7705fdef0b5355d897a9e0fa3a8d26709ceaa06965d \ + --hash=sha256:0634581290e6714c068f4aa24020acf7880927d1f0084fa753d9799ae9610082 \ + --hash=sha256:08043f7cb1fb9467c3fbbbaea7896986e7fbc81f4d3fd9289a73d9110ab6207a \ + --hash=sha256:0a3984146e414684a6be2862d84fcb1035f4984851cb81b26d933bab6119bf00 \ + --hash=sha256:0bbc17250b10d3466875a40a52520a6bac3c02334ca709207648abd3c223ed5c \ + --hash=sha256:0cc21533878e5586b80d74c281d7f8da7932bc8ace50b8d5f6dbf7e3935f63f1 \ + --hash=sha256:0d0b7e803191db5f714d264044e06189c8ccd3219e936cc184f07106bd17fd7b \ + --hash=sha256:113f78e7463a36dbbcea05bfe688efd7fa759d0f0c56e73c974d60dcfec3dfcc \ + --hash=sha256:169e0d178cb59314456ab30772429a802b25d13227088085b0d49b9fe1533104 \ + --hash=sha256:17fbb47f0885ace8327ce1235d0416dc86a211dcd8cc1e703f41523be32cfec8 \ + --hash=sha256:19bbd3b841174ae6ed588536ab5e1b1fe83d046e668602c20266547298d939a9 \ + --hash=sha256:1d9f9a3ce559a5267014b04b82956993270f63ec91765e13e9fd73daf2d2738e \ + --hash=sha256:1e4ecee40ba19e6975e1120829796770325841c2f153c0e9aecca927194c6a2a \ + --hash=sha256:22b0f9971ec4e07e8223f2beebe96a6cfc779d940b6f27d26604040dd74d3a44 \ + --hash=sha256:26fb5b9c3946bf7f1daed7b37e0c03898a6f062149127570f8ede346390a0825 \ + --hash=sha256:2778fed822d7db23ac5008b181441af0c869455b2e7d001f4019636ac31b6fe4 \ + --hash=sha256:28cfab66577000b9505a0d068c731aee7ca85cd26d4d63881fab17857e0fe1fb \ + --hash=sha256:29bc3973676ae334412efdd367fcd11d036b7be3efc1ce2407ef8676dabfeb82 \ + --hash=sha256:2bd9f19f7f1fcebd74e830f4af0f28adad4975d40d80620be19ffb2b2af56c9f \ + --hash=sha256:2d5d542bf2abd0fd0361e8017d03f7cb5786214ceb4a40eef1539d6585d93386 \ + --hash=sha256:30e4d2084df019880d55f6f7bea35328d9b464ebee090baa372c096dc77556fb \ + --hash=sha256:3619473a0e0d329fd4aec8075628f8f616be2da41605300696206d6f36920c3d \ + --hash=sha256:368625fb01666655985391dbad3860dc0ba7c0d6b9125819f3121ee7292b4ac8 \ + --hash=sha256:3737303ca9ea0f7cb83028781148fcda4f1dac7821db0c47672971dabcf63593 \ + --hash=sha256:3a9fed49c6ce4ed7e73f13182760c65c816da006debe67f37635580dfb0fae00 \ + --hash=sha256:3c38d142c706201db5b2345166eeef1e7740e3e2422b470b8ba5c8727a9b4c7a \ + --hash=sha256:3cb61db880ec11e984348227b333259994c2c85caa775eb7875decb3768db890 \ + --hash=sha256:3d74a03fb57757ece25aa4b3c1c60157a1cece37a020542785f942e2f827eed5 \ + --hash=sha256:3f796b535008708846044c43302719c6956f39ca2d93f2edda5319e79a29efbb \ + --hash=sha256:41105377f6282e8297f182e393a79cfffd521dde37ace52b106373bdcd9ca5cb \ + --hash=sha256:41aac7002a749f08727cb91babff1daf8deac317c0b1f317adc69be0e6c375d1 \ + --hash=sha256:44983e45310ee5b9f73397350251cdf6e63a466406a105f1d16cb5baa659270b \ + --hash=sha256:4cbbde66f1183db040daede83dd86c06d663c5bb2af6de1142b7c8c37923dd74 \ + --hash=sha256:4eda76074cfca2787c8cf1bec603eaebdddd8b061ad5502f85cddae998d54f00 \ + --hash=sha256:4fc6cd65dc4d2fdb2625e288939a3566e36127a84811a4913f02f3d5931da52d \ + --hash=sha256:50885073e2909251d4718634a191c49ae5f527e5e1736d738e365c3e8be8f22b \ + --hash=sha256:5174a697ce042fa77c407e05efe41e03aa56dae9ec67388055820fb48cf4c3ba \ + --hash=sha256:54b64fb2433bc71488e7a449603bf8bd31fbcf9cb56fbe1eb6d459e90b86c37b \ + --hash=sha256:54fe8518abe06a4c3852754bfd498b30cc58e667f376c513eac89a244ce781a4 \ + --hash=sha256:55dbbd8ffbc40d1697d5e2d0375b08599dae8746b0b08dea05eee4ce81648fac \ + --hash=sha256:57b52603e89355ff318025dd55158f6e71396c0f1f609d548e9ea9c94cc6ce0a \ + --hash=sha256:58370d05d033ee97224c81263af123dea3d931025030fd34b61227a768a8858a \ + --hash=sha256:5d87a3584093e1a89987e3d36d82c98d9621b2cb944e22a420aa1401e096758f \ + --hash=sha256:623f938f6a039536cc02b7582a07a080f13fdfd48f87e63201d92d7e34d09a18 \ + --hash=sha256:62815d2c67f2dd1be76a253d88af4e1da19aeaa1820146dec52cf8bee2958b16 \ + --hash=sha256:6290289fa5fb4c70fd7f72016e03633d60388185483ff3b162912c81205ae2cf \ + --hash=sha256:67e41a497bac88cc1de96eeba56eeb933c39d54bc227352f8455aa87c4ca4000 \ + --hash=sha256:6c85c38a279ca9295a69b9b088a2e48aa49737bb1b34e6a9dc6297c110e8d912 \ + --hash=sha256:6f01f044112d43a20be2f13a11683666d87151542ad627fe41a18b9791d2802f \ + --hash=sha256:707151644085dd0f20fe4f4b573d28e5130c4aaa5f587e95b60989c5926653b5 \ + --hash=sha256:723b2681ed4cc07d3401bbea9c201ad4f2a4ca6ba8cddaff6789f715dd2b391e \ + --hash=sha256:72d1cc63bcc91e14933f77d51b3df899d6a07d184ec515ea7f56bff659e124d7 \ + --hash=sha256:7374d6e3ef72afe49697ecd683f3da12f4fc06af2d75433d0580c6746d2fa025 \ + --hash=sha256:7501e9be34cb21e72fcfe672aafd0eee65c16ba2afa9dcb5500a587d3a0580f0 \ + --hash=sha256:76219cd1eefb9bf4af7856e3ae563d15158efa145c0aab01e9933051a1954045 \ + --hash=sha256:7aec798c2b01aaa65a55f1124f3405804184373abb318a3091325aece235f67c \ + --hash=sha256:7be6dfb49e48fd0a7d91ff758a2b51336f1cd21f9d44b20f6801f072bd080cdd \ + --hash=sha256:7e4e1f580033335c6f76d1e0d6b56baf009d1a64d6a4816347e4271ba951f46d \ + --hash=sha256:7e8ec5f606e0809426d2440e0683509fb605a8820a21ebd120dcdba61b74ef7f \ + --hash=sha256:7f196cd7910d71e9d9860da0ff7a77f64d22c1ad931f1dd18559a06e03109fc0 \ + --hash=sha256:82f3802bfc4751f420d591c5c864de538b71cea117fce67e4595c2afede08a15 \ + --hash=sha256:85ffc9920ffc39c5eee1e3ac9100c913a0973996fbad5111f939bbda49204bb7 \ + --hash=sha256:8e6c219e375f6341d0959af814296372d265a8ca1af63825f65e2e87c618f006 \ + --hash=sha256:8f767ba0911602ddef289404e33835a61168314ebd3c729833db2ed685824211 \ + --hash=sha256:8ff038d52ef6aa0f309feeba00c5095c9118d0abf787e8e8454d6048db2037fc \ + --hash=sha256:915e7a2418f10bd1151b1953df06d896db9783c9cfdb9a8ee1f9b3a4331ab503 \ + --hash=sha256:92883836caf50d5255be03d988d75bc93e3f86ba247b7ca137347c323f731deb \ + --hash=sha256:960b1b3efa39872ac8b6cc3a556edd6fb90ed74f08c9c45e028f1005b26aa55d \ + --hash=sha256:9aeaf53eaa075dd63e81512522fd180097312fb2c9f476333309184285c49ce0 \ + --hash=sha256:9d8089d853c7963a8ce87fff93e2a67075c0bc08684a08ea6ad13577c38ffc38 \ + --hash=sha256:a4130d0b9ce5fad6af07421b1aecc7e079519f70d6c05729ab871794eded8617 \ + --hash=sha256:a482ac121de6973897c92c2f31defc6bafb11c83825109275cffce54bb64933f \ + --hash=sha256:add7ac388d1e0bf57259afbcf9ed05621a3bf11ce5ee337e7536f1e1aaf056b0 \ + --hash=sha256:b1f12bd684887a0a5d55e6363ca87056f361e45451105012d329b86ec19dbe0b \ + --hash=sha256:b3f99e1756fc48ad507b95e5d86f2fb21b3d495012ff13e6592ebac14033f166 \ + --hash=sha256:b4cce60d0223074803c9dbe0721ad3fa51dafe7d462fee4b656a1aa01ee07518 \ + --hash=sha256:baeb47635cb33375dee4924cd93d7f5dcaa786c740b08423b0209b824a1ee728 \ + --hash=sha256:bbea5b775f0ac84945191fb83f845a6fd9a21a03ea7f2e187defac7e401616ad \ + --hash=sha256:bbfcb95d9a744e6e2827dfc66ad10e1020e0cac255eb7f85652832d5a264c2fc \ + --hash=sha256:bd6e7d363aa93bd3421b30b6af97064daf47bc96005bddba67c5ffbc6df426b8 \ + --hash=sha256:be77c402d5e882b6fbacfd90823f13da8e0a69658405a39a569c6b58fdb17b03 \ + --hash=sha256:c302245fd6c33d96bd169c7ccf2513c20f4c1e417c07ce9dce107c8bc3f8411f \ + --hash=sha256:c88653877aeb514c089d1b3d473451677b8b9a6d1497dbddf1ae7934518b06d2 \ + --hash=sha256:cae6383181f1e345317742d2ddd88f9e7d2682fa4c9432e3a74e47d92dce0229 \ + --hash=sha256:cd471ede0d802dd936b6fab28188302b2d497f68436025857ca72cd3810423fe \ + --hash=sha256:d106493a60dcb4aef35a0fac85105e150a11cf8bc2b0d388f5a33272d756c966 \ + --hash=sha256:d30b650595fdbe32366b94cb14f30bb2b625e512bd4e1df00611f99dc5c27fd4 \ + --hash=sha256:d51fde50a77f81330523562e3c2734ffdca9c4c9e9d355478117905e1cfe16c6 \ + --hash=sha256:d57dea657357230cc780e13920d7fa7db059d58fe721c80020f94476da4ca0a1 \ + --hash=sha256:d771f085fcdf4035786adfb1d8db026df1eb4b41dac1c3d070d1e49512843227 \ + --hash=sha256:dae0f0bd7d30c0ad61b9a504e8e272cb8391eed3f1587edf933f4f6b33437450 \ + --hash=sha256:db0562c5f71d18596dcd45e854cf2eeba27d7543e1a3acdafb7eef728f7fe85d \ + --hash=sha256:dfd51b4c56b673dfbc43d7d27ef857dd91124801e2806c69bb45585ce0fa019b \ + --hash=sha256:e080c0637aea036f35507e803a4778f119a9b436617694ae1c5c366805f1e997 \ + --hash=sha256:e48d4dbe0f88e53081da605ae68644e5182752803bbc2beb228cca7f1c4454d6 \ + --hash=sha256:e8b4b5580280b9265af3e0409974fb79c64cf7523632d03fbf11df18f8b0181e \ + --hash=sha256:e8b5378de2b139c3a830f0209c1e91f7705919a4b3e563a10955104f5097a70a \ + --hash=sha256:e904f2417f0d6f6d514f3f8b836416c360f306ddaee1f84de8eef1e722d212e5 \ + --hash=sha256:eee884572b06bbe8a2b54f424dbd996139442cf83c76478e1ec162512e0dd2c7 \ + --hash=sha256:f1fbb0a99125b1287c6d9747f937dc66621426836d1a2d50d05aecfc81911b57 \ + --hash=sha256:f40a95186a72fa0b67d15fef0f157bfcda00b4f59c8a07cbe5530d41ac35d105 \ + --hash=sha256:f6e0bfe77d238308839699944164b96a2eeccaf55f2af400f54dc20669d8d5f2 \ + --hash=sha256:f963eafc0a77a6c0562397da004f5876a9bcf7265a7bcc3205e29636bc4a1312 \ + --hash=sha256:fb9d44c25244e11c8be3f12c938ca8ba8404620ef8092245d2093c6ab3df260f \ + --hash=sha256:fc78739b5ec6e4fb02301984a3d442a91406e7700efbe305071e7fd1c78278f2 \ + --hash=sha256:fceef7fe67c81e1585198215e42ad3fdba3a25644beda8fbdaf85f4d7b93175a \ + --hash=sha256:fd96476f04db5ceba1cfa0f21228f67c1f7402296f0e73fee3513aa680ad237b # via feast (pyproject.toml) mock==2.0.0 \ --hash=sha256:5ce3c71c5545b472da17b72268978914d0252980348636840bd34a00b5cc96c1 \ @@ -2480,9 +2501,9 @@ mpmath==1.3.0 \ --hash=sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f \ --hash=sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c # via sympy -msal==1.34.0 \ - --hash=sha256:76ba83b716ea5a6d75b0279c0ac353a0e05b820ca1f6682c0eb7f45190c43c2f \ - --hash=sha256:f669b1644e4950115da7a176441b0e13ec2975c29528d8b9e81316023676d6e1 +msal==1.35.1 \ + --hash=sha256:70cac18ab80a053bff86219ba64cfe3da1f307c74b009e2da57ef040eb1b5656 \ + --hash=sha256:8f4e82f34b10c19e326ec69f44dc6b30171f2f7098f3720ea8a9f0c11832caa3 # via # azure-identity # msal-extensions @@ -2815,9 +2836,9 @@ nodeenv==1.10.0 \ --hash=sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827 \ --hash=sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb # via pre-commit -notebook==7.5.3 \ - --hash=sha256:393ceb269cf9fdb02a3be607a57d7bd5c2c14604f1818a17dbeb38e04f98cbfa \ - --hash=sha256:c997bfa1a2a9eb58c9bbb7e77d50428befb1033dd6f02c482922e96851d67354 +notebook==7.5.5 \ + --hash=sha256:a7c14dbeefa6592e87f72290ca982e0c10f5bbf3786be2a600fda9da2764a2b8 \ + --hash=sha256:dc0bfab0f2372c8278c457423d3256c34154ac2cc76bf20e9925260c461013c3 # via great-expectations notebook-shim==0.2.4 \ --hash=sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef \ @@ -2902,6 +2923,7 @@ numpy==2.2.6 \ # scikit-image # scikit-learn # scipy + # sentence-transformers # shapely # tifffile # torchvision @@ -2920,88 +2942,121 @@ opencv-python-headless==4.13.0.92 \ --hash=sha256:a7cf08e5b191f4ebb530791acc0825a7986e0d0dee2a3c491184bd8599848a4b \ --hash=sha256:eb60e36b237b1ebd40a912da5384b348df8ed534f6f644d8e0b4f103e272ba7d # via easyocr -openlineage-python==1.43.0 \ - --hash=sha256:595dc641f696d0a1c021440a9ff8155f4e2776452cf118112a09b12cf4038827 +openlineage-python==1.45.0 \ + --hash=sha256:cf66e7d517d3c8b510b39ad646d8fd0ca2f0cc92d7d6d601d93b2a859783f380 # via feast (pyproject.toml) openpyxl==3.1.5 \ --hash=sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2 \ --hash=sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050 # via docling -orjson==3.11.7 \ - --hash=sha256:043d3006b7d32c7e233b8cfb1f01c651013ea079e08dcef7189a29abd8befe11 \ - --hash=sha256:0527a4510c300e3b406591b0ba69b5dc50031895b0a93743526a3fc45f59d26e \ - --hash=sha256:0724e265bc548af1dedebd9cb3d24b4e1c1e685a343be43e87ba922a5c5fff2f \ - --hash=sha256:136dcd6a2e796dfd9ffca9fc027d778567b0b7c9968d092842d3c323cef88aa8 \ - --hash=sha256:14f440c7268c8f8633d1b3d443a434bd70cb15686117ea6beff8fdc8f5917a1e \ - --hash=sha256:1d98b30cc1313d52d4af17d9c3d307b08389752ec5f2e5febdfada70b0f8c733 \ - --hash=sha256:1eb80451a9c351a71dfaf5b7ccc13ad065405217726b59fdbeadbcc544f9d223 \ - --hash=sha256:1ee5cc7160a821dfe14f130bc8e63e7611051f964b463d9e2a3a573204446a4d \ - --hash=sha256:23d6c20517a97a9daf1d48b580fcdc6f0516c6f4b5038823426033690b4d2650 \ - --hash=sha256:26c3b9132f783b7d7903bf1efb095fed8d4a3a85ec0d334ee8beff3d7a4749d5 \ - --hash=sha256:31c80ce534ac4ea3739c5ee751270646cbc46e45aea7576a38ffec040b4029a1 \ - --hash=sha256:3726be79e36e526e3d9c1aceaadbfb4a04ee80a72ab47b3f3c17fefb9812e7b8 \ - --hash=sha256:390a1dce0c055ddf8adb6aa94a73b45a4a7d7177b5c584b8d1c1947f2ba60fb3 \ - --hash=sha256:3a2479753bbb95b0ebcf7969f562cdb9668e6d12416a35b0dda79febf89cdea2 \ - --hash=sha256:3c4bc6c6ac52cdaa267552544c73e486fecbd710b7ac09bc024d5a78555a22f6 \ - --hash=sha256:411ebaf34d735e25e358a6d9e7978954a9c9d58cfb47bc6683cdc3964cd2f910 \ - --hash=sha256:4682d1db3bcebd2b64757e0ddf9e87ae5f00d29d16c5cdf3a62f561d08cc3dd2 \ - --hash=sha256:4a2e9c5be347b937a2e0203866f12bba36082e89b402ddb9e927d5822e43088d \ - --hash=sha256:57036b27ac8a25d81112eb0cc9835cd4833c5b16e1467816adc0015f59e870dc \ - --hash=sha256:5ede977b5fe5ac91b1dffc0a517ca4542d2ec8a6a4ff7b2652d94f640796342a \ - --hash=sha256:5fdfad2093bdd08245f2e204d977facd5f871c88c4a71230d5bcbd0e43bf6222 \ - --hash=sha256:623ad1b9548ef63886319c16fa317848e465a21513b31a6ad7b57443c3e0dcf5 \ - --hash=sha256:652c6c3af76716f4a9c290371ba2e390ede06f6603edb277b481daf37f6f464e \ - --hash=sha256:6543001328aa857187f905308a028935864aefe9968af3848401b6fe80dbb471 \ - --hash=sha256:6e776b998ac37c0396093d10290e60283f59cfe0fc3fccbd0ccc4bd04dd19892 \ - --hash=sha256:71924496986275a737f38e3f22b4e0878882b3f7a310d2ff4dc96e812789120c \ - --hash=sha256:733ae23ada68b804b222c44affed76b39e30806d38660bf1eb200520d259cc16 \ - --hash=sha256:7477aa6a6ec6139c5cb1cc7b214643592169a5494d200397c7fc95d740d5fcf3 \ - --hash=sha256:79cacb0b52f6004caf92405a7e1f11e6e2de8bdf9019e4f76b44ba045125cd6b \ - --hash=sha256:7ba61079379b0ae29e117db13bda5f28d939766e410d321ec1624afc6a0b0504 \ - --hash=sha256:800988273a014a0541483dc81021247d7eacb0c845a9d1a34a422bc718f41539 \ - --hash=sha256:814be4b49b228cfc0b3c565acf642dd7d13538f966e3ccde61f4f55be3e20785 \ - --hash=sha256:845c3e0d8ded9c9271cd79596b9b552448b885b97110f628fb687aee2eed11c1 \ - --hash=sha256:849e38203e5be40b776ed2718e587faf204d184fc9a008ae441f9442320c0cab \ - --hash=sha256:89e13dd3f89f1c38a9c9eba5fbf7cdc2d1feca82f5f290864b4b7a6aac704576 \ - --hash=sha256:89e440ebc74ce8ab5c7bc4ce6757b4a6b1041becb127df818f6997b5c71aa60b \ - --hash=sha256:8ff206156006da5b847c9304b6308a01e8cdbc8cce824e2779a5ba71c3def141 \ - --hash=sha256:91c81ef070c8f3220054115e1ef468b1c9ce8497b4e526cb9f68ab4dc0a7ac62 \ - --hash=sha256:9487abc2c2086e7c8eb9a211d2ce8855bae0e92586279d0d27b341d5ad76c85c \ - --hash=sha256:962d046ee1765f74a1da723f4b33e3b228fe3a48bd307acce5021dfefe0e29b2 \ - --hash=sha256:996b65230271f1a97026fd0e6a753f51fbc0c335d2ad0c6201f711b0da32693b \ - --hash=sha256:9b1a67243945819ce55d24a30b59d6a168e86220452d2c96f4d1f093e71c0c49 \ - --hash=sha256:9c0b51672e466fd7e56230ffbae7f1639e18d0ce023351fb75da21b71bc2c960 \ - --hash=sha256:9e54f3808e2b6b945078c41aa8d9b5834b28c50843846e97807e5adb75fa9705 \ - --hash=sha256:a02c833f38f36546ba65a452127633afce4cf0dd7296b753d3bb54e55e5c0174 \ - --hash=sha256:a12b80df61aab7b98b490fe9e4879925ba666fccdfcd175252ce4d9035865ace \ - --hash=sha256:a16bcd08ab0bcdfc7e8801d9c4a9cc17e58418e4d48ddc6ded4e9e4b1a94062b \ - --hash=sha256:a56df3239294ea5964adf074c54bcc4f0ccd21636049a2cf3ca9cf03b5d03cf1 \ - --hash=sha256:a709e881723c9b18acddcfb8ba357322491ad553e277cf467e1e7e20e2d90561 \ - --hash=sha256:ab49d4b2a6a1d415ddb9f37a21e02e0d5dbfe10b7870b21bf779fc21e9156157 \ - --hash=sha256:ae9e0b37a834cef7ce8f99de6498f8fad4a2c0bf6bfc3d02abd8ed56aa15b2de \ - --hash=sha256:b4a9eefdc70bf8bf9857f0290f973dec534ac84c35cd6a7f4083be43e7170a8f \ - --hash=sha256:b63c6e6738d7c3470ad01601e23376aa511e50e1f3931395b9f9c722406d1a67 \ - --hash=sha256:b7b1dae39230a393df353827c855a5f176271c23434cfd2db74e0e424e693e10 \ - --hash=sha256:b8d14b71c0b12963fe8a62aac87119f1afdf4cb88a400f61ca5ae581449efcb5 \ - --hash=sha256:b9f95dcdea9d4f805daa9ddf02617a89e484c6985fa03055459f90e87d7a0757 \ - --hash=sha256:b9fc4d0f81f394689e0814617aadc4f2ea0e8025f38c226cbf22d3b5ddbf025d \ - --hash=sha256:bd03ea7606833655048dab1a00734a2875e3e86c276e1d772b2a02556f0d895f \ - --hash=sha256:bd0d68edd7dfca1b2eca9361a44ac9f24b078de3481003159929a0573f21a6bf \ - --hash=sha256:bda117c4148e81f746655d5a3239ae9bd00cb7bc3ca178b5fc5a5997e9744183 \ - --hash=sha256:bf742e149121dc5648ba0a08ea0871e87b660467ef168a3a5e53bc1fbd64bb74 \ - --hash=sha256:c2428d358d85e8da9d37cba18b8c4047c55222007a84f97156a5b22028dfbfc0 \ - --hash=sha256:c2e85fe4698b6a56d5e2ebf7ae87544d668eb6bde1ad1226c13f44663f20ec9e \ - --hash=sha256:c43b8b5bab288b6b90dac410cca7e986a4fa747a2e8f94615aea407da706980d \ - --hash=sha256:cededd6738e1c153530793998e31c05086582b08315db48ab66649768f326baa \ - --hash=sha256:d06e5c5fed5caedd2e540d62e5b1c25e8c82431b9e577c33537e5fa4aa909539 \ - --hash=sha256:d772afdb22555f0c58cfc741bdae44180122b3616faa1ecadb595cd526e4c993 \ - --hash=sha256:d897e81f8d0cbd2abb82226d1860ad2e1ab3ff16d7b08c96ca00df9d45409ef4 \ - --hash=sha256:de0a37f21d0d364954ad5de1970491d7fbd0fb1ef7417d4d56a36dc01ba0c0a0 \ - --hash=sha256:e7745312efa9e11c17fbd3cb3097262d079da26930ae9ae7ba28fb738367cbad \ - --hash=sha256:ed46f17096e28fb28d2975834836a639af7278aa87c84f68ab08fbe5b8bd75fa \ - --hash=sha256:f4f7c956b5215d949a1f65334cf9d7612dde38f20a95f2315deef167def91a6f \ - --hash=sha256:f50979824bde13d32b4320eedd513431c921102796d86be3eee0b58e58a3ecd1 \ - --hash=sha256:f904c24bdeabd4298f7a977ef14ca2a022ca921ed670b92ecd16ab6f3d01f867 +oracledb==3.4.2 \ + --hash=sha256:00c79448017f367bb7ab6900efe0706658a53768abea2b4519a4c9b2d5743890 \ + --hash=sha256:0e16fe3d057e0c41a23ad2ae95bfa002401690773376d476be608f79ac74bf05 \ + --hash=sha256:0f04a2d62073407672f114d02529921de0677c6883ed7c64d8d1a3c04caa3238 \ + --hash=sha256:1617a1db020346883455af005efbefd51be2c4d797e43b1b38455a19f8526b48 \ + --hash=sha256:19fa80ef84f85ad74077aa626067bbe697e527bd39604b4209f9d86cb2876b89 \ + --hash=sha256:1e4930d7f6584832dcc15b8ca415a7957b0c45f5aa7c4f88702e070e5c53bf93 \ + --hash=sha256:23aa07c1eaca17ae74c6fdc86b218f58484d56452958aead1aa460c0596a76c1 \ + --hash=sha256:31b7ee83c23d0439778303de8a675717f805f7e8edb5556d48c4d8343bcf14f5 \ + --hash=sha256:3df8eee1410d25360599968b1625b000f10c5ae0e47274031a7842a9dc418890 \ + --hash=sha256:404ec1451d0448653ee074213b87d6c5bd65eaa74b50083ddf2c9c3e11c71c71 \ + --hash=sha256:46e0f2278ff1fe83fbc33a3b93c72d429323ec7eed47bc9484e217776cd437e5 \ + --hash=sha256:55397e7eb43bb7017c03a981c736c25724182f5210951181dfe3fab0e5d457fb \ + --hash=sha256:574c8280d49cbbe21dbe03fc28356d9b9a5b9e300ebcde6c6d106e51453a7e65 \ + --hash=sha256:59ad6438f56a25e8e1a4a3dd1b42235a5d09ab9ba417ff2ad14eae6596f3d06f \ + --hash=sha256:5d7befb014174c5ae11c3a08f5ed6668a25ab2335d8e7104dca70d54d54a5b3a \ + --hash=sha256:5ed78d7e7079a778062744ccf42141ce4806818c3f4dd6463e4a7edd561c9f86 \ + --hash=sha256:643c25d301a289a371e37fcedb59e5fa5e54fb321708e5c12821c4b55bdd8a4d \ + --hash=sha256:6d85622664cc88d5a82bbd7beccb62cd53bd272c550a5e15e7d5f8ae6b86f1f1 \ + --hash=sha256:9f434a739405557bd57cb39b62238142bb27855a524a70dc6d397a2a8c576c9d \ + --hash=sha256:a7396664e592881225ba66385ee83ce339d864f39003d6e4ca31a894a7e7c552 \ + --hash=sha256:ac25a0448fc830fb7029ad50cd136cdbfcd06975d53967e269772cc5cb8c203a \ + --hash=sha256:b1095d95d0c8b37e4d0e17cf1928919cb59222b6344362a1cf6a2f3ca205a28a \ + --hash=sha256:b26a10f9c790bd141ffc8af68520803ed4a44a9258bf7d1eea9bfdd36bd6df7f \ + --hash=sha256:b8e4b8a852251cef09038b75f30fce1227010835f4e19cfbd436027acba2697c \ + --hash=sha256:b974caec2c330c22bbe765705a5ac7d98ec3022811dec2042d561a3c65cb991b \ + --hash=sha256:d7ce75c498bff758548ec6e4424ab4271aa257e5887cc436a54bc947fd46199a \ + --hash=sha256:d8d75e4f879b908be66cce05ba6c05791a5dbb4a15e39abc01aa25c8a2492bd9 \ + --hash=sha256:e068ef844a327877bfefbef1bc6fb7284c727bb87af80095f08d95bcaf7b8bb2 \ + --hash=sha256:f8ea989965a4f636a309444bd696ab877bba373d5d67bf744785f9bd8c560865 \ + --hash=sha256:f93cae08e8ed20f2d5b777a8602a71f9418389c661d2c937e84d94863e7e7011 \ + --hash=sha256:ff3c89cecea62af8ca02aa33cab0f2edc0214c747eac7d3364ed6b2640cb55e4 + # via ibis-framework +orjson==3.11.8 \ + --hash=sha256:0022bb50f90da04b009ce32c512dc1885910daa7cb10b7b0cba4505b16db82a8 \ + --hash=sha256:003646067cc48b7fcab2ae0c562491c9b5d2cbd43f1e5f16d98fd118c5522d34 \ + --hash=sha256:01928d0476b216ad2201823b0a74000440360cef4fed1912d297b8d84718f277 \ + --hash=sha256:01c4e5a6695dc09098f2e6468a251bc4671c50922d4d745aff1a0a33a0cf5b8d \ + --hash=sha256:093d489fa039ddade2db541097dbb484999fcc65fc2b0ff9819141e2ab364f25 \ + --hash=sha256:0b57f67710a8cd459e4e54eb96d5f77f3624eba0c661ba19a525807e42eccade \ + --hash=sha256:0e32f7154299f42ae66f13488963269e5eccb8d588a65bc839ed986919fc9fac \ + --hash=sha256:14439063aebcb92401c11afc68ee4e407258d2752e62d748b6942dad20d2a70d \ + --hash=sha256:14778ffd0f6896aa613951a7fbf4690229aa7a543cb2bfbe9f358e08aafa9546 \ + --hash=sha256:14f7b8fcb35ef403b42fa5ecfa4ed032332a91f3dc7368fbce4184d59e1eae0d \ + --hash=sha256:1ab359aff0436d80bfe8a23b46b5fea69f1e18aaf1760a709b4787f1318b317f \ + --hash=sha256:1cd0b77e77c95758f8e1100139844e99f3ccc87e71e6fc8e1c027e55807c549f \ + --hash=sha256:25e0c672a2e32348d2eb33057b41e754091f2835f87222e4675b796b92264f06 \ + --hash=sha256:29c009e7a2ca9ad0ed1376ce20dd692146a5d9fe4310848904b6b4fee5c5c137 \ + --hash=sha256:3222adff1e1ff0dce93c16146b93063a7793de6c43d52309ae321234cdaf0f4d \ + --hash=sha256:3223665349bbfb68da234acd9846955b1a0808cbe5520ff634bf253a4407009b \ + --hash=sha256:3cf17c141617b88ced4536b2135c552490f07799f6ad565948ea07bef0dcb9a6 \ + --hash=sha256:3f23426851d98478c8970da5991f84784a76682213cd50eb73a1da56b95239dc \ + --hash=sha256:3f262401086a3960586af06c054609365e98407151f5ea24a62893a40d80dbbb \ + --hash=sha256:436c4922968a619fb7fef1ccd4b8b3a76c13b67d607073914d675026e911a65c \ + --hash=sha256:469ac2125611b7c5741a0b3798cd9e5786cbad6345f9f400c77212be89563bec \ + --hash=sha256:4861bde57f4d253ab041e374f44023460e60e71efaa121f3c5f0ed457c3a701e \ + --hash=sha256:48854463b0572cc87dac7d981aa72ed8bf6deedc0511853dc76b8bbd5482d36d \ + --hash=sha256:53a0f57e59a530d18a142f4d4ba6dfc708dc5fdedce45e98ff06b44930a2a48f \ + --hash=sha256:54153d21520a71a4c82a0dbb4523e468941d549d221dc173de0f019678cf3813 \ + --hash=sha256:55120759e61309af7fcf9e961c6f6af3dde5921cdb3ee863ef63fd9db126cae6 \ + --hash=sha256:5774c1fdcc98b2259800b683b19599c133baeb11d60033e2095fd9d4667b82db \ + --hash=sha256:58a4a208a6fbfdb7a7327b8f201c6014f189f721fd55d047cafc4157af1bc62a \ + --hash=sha256:58fb9b17b4472c7b1dcf1a54583629e62e23779b2331052f09a9249edf81675b \ + --hash=sha256:5d8b5231de76c528a46b57010bbd83fb51e056aa0220a372fd5065e978406f1c \ + --hash=sha256:5f8952d6d2505c003e8f0224ff7858d341fa4e33fef82b91c4ff0ef070f2393c \ + --hash=sha256:61c9d357a59465736022d5d9ba06687afb7611dfb581a9d2129b77a6fcf78e59 \ + --hash=sha256:6a3d159d5ffa0e3961f353c4b036540996bf8b9697ccc38261c0eac1fd3347a6 \ + --hash=sha256:6a4a639049c44d36a6d1ae0f4a94b271605c745aee5647fa8ffaabcdc01b69a6 \ + --hash=sha256:6ccdea2c213cf9f3d9490cbd5d427693c870753df41e6cb375bd79bcbafc8817 \ + --hash=sha256:6dbe9a97bdb4d8d9d5367b52a7c32549bba70b2739c58ef74a6964a6d05ae054 \ + --hash=sha256:6eda5b8b6be91d3f26efb7dc6e5e68ee805bc5617f65a328587b35255f138bf4 \ + --hash=sha256:705b895b781b3e395c067129d8551655642dfe9437273211d5404e87ac752b53 \ + --hash=sha256:708c95f925a43ab9f34625e45dcdadf09ec8a6e7b664a938f2f8d5650f6c090b \ + --hash=sha256:735e2262363dcbe05c35e3a8869898022af78f89dde9e256924dc02e99fe69ca \ + --hash=sha256:76070a76e9c5ae661e2d9848f216980d8d533e0f8143e6ed462807b242e3c5e8 \ + --hash=sha256:7679bc2f01bb0d219758f1a5f87bb7c8a81c0a186824a393b366876b4948e14f \ + --hash=sha256:88006eda83858a9fdf73985ce3804e885c2befb2f506c9a3723cdeb5a2880e3e \ + --hash=sha256:883206d55b1bd5f5679ad5e6ddd3d1a5e3cac5190482927fdb8c78fb699193b5 \ + --hash=sha256:8ac7381c83dd3d4a6347e6635950aa448f54e7b8406a27c7ecb4a37e9f1ae08b \ + --hash=sha256:8e8c6218b614badf8e229b697865df4301afa74b791b6c9ade01d19a9953a942 \ + --hash=sha256:9185589c1f2a944c17e26c9925dcdbc2df061cc4a145395c57f0c51f9b5dbfcd \ + --hash=sha256:93de06bc920854552493c81f1f729fab7213b7db4b8195355db5fda02c7d1363 \ + --hash=sha256:96163d9cdc5a202703e9ad1b9ae757d5f0ca62f4fa0cc93d1f27b0e180cc404e \ + --hash=sha256:97c8f5d3b62380b70c36ffacb2a356b7c6becec86099b177f73851ba095ef623 \ + --hash=sha256:97d823831105c01f6c8029faf297633dbeb30271892bd430e9c24ceae3734744 \ + --hash=sha256:98bdc6cb889d19bed01de46e67574a2eab61f5cc6b768ed50e8ac68e9d6ffab6 \ + --hash=sha256:9b48e274f8824567d74e2158199e269597edf00823a1b12b63d48462bbf5123e \ + --hash=sha256:a5c370674ebabe16c6ccac33ff80c62bf8a6e59439f5e9d40c1f5ab8fd2215b7 \ + --hash=sha256:b43dc2a391981d36c42fa57747a49dae793ef1d2e43898b197925b5534abd10a \ + --hash=sha256:c154a35dd1330707450bb4d4e7dd1f17fa6f42267a40c1e8a1daa5e13719b4b8 \ + --hash=sha256:c2bdf7b2facc80b5e34f48a2d557727d5c5c57a8a450de122ae81fa26a81c1bc \ + --hash=sha256:c492a0e011c0f9066e9ceaa896fbc5b068c54d365fea5f3444b697ee01bc8625 \ + --hash=sha256:c60c0423f15abb6cf78f56dff00168a1b582f7a1c23f114036e2bfc697814d5f \ + --hash=sha256:c98121237fea2f679480765abd566f7713185897f35c9e6c2add7e3a9900eb61 \ + --hash=sha256:ccd7ba1b0605813a0715171d39ec4c314cb97a9c85893c2c5c0c3a3729df38bf \ + --hash=sha256:cdbc8c9c02463fef4d3c53a9ba3336d05496ec8e1f1c53326a1e4acc11f5c600 \ + --hash=sha256:e0950ed1bcb9893f4293fd5c5a7ee10934fbf82c4101c70be360db23ce24b7d2 \ + --hash=sha256:e6693ff90018600c72fd18d3d22fa438be26076cd3c823da5f63f7bab28c11cb \ + --hash=sha256:ea56a955056a6d6c550cf18b3348656a9d9a4f02e2d0c02cabf3c73f1055d506 \ + --hash=sha256:ebaed4cef74a045b83e23537b52ef19a367c7e3f536751e355a2a394f8648559 \ + --hash=sha256:ec795530a73c269a55130498842aaa762e4a939f6ce481a7e986eeaa790e9da4 \ + --hash=sha256:ed193ce51d77a3830cad399a529cd4ef029968761f43ddc549e1bc62b40d88f8 \ + --hash=sha256:ee8db7bfb6fe03581bbab54d7c4124a6dd6a7f4273a38f7267197890f094675f \ + --hash=sha256:f30491bc4f862aa15744b9738517454f1e46e56c972a2be87d70d727d5b2a8f8 \ + --hash=sha256:f89b6d0b3a8d81e1929d3ab3d92bbc225688bd80a770c49432543928fe09ac55 \ + --hash=sha256:fa72e71977bff96567b0f500fc5bfd2fdf915f34052c782a4c6ebbdaa97aa858 \ + --hash=sha256:fe0b8c83e0f36247fc9431ce5425a5d95f9b3a689133d494831bdbd6f0bceb13 \ + --hash=sha256:ff51f9d657d1afb6f410cb435792ce4e1fe427aab23d2fcd727a2876e21d4cb6 # via trino overrides==7.7.0 \ --hash=sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a \ @@ -3431,26 +3486,26 @@ propcache==0.4.1 \ # via # aiohttp # yarl -proto-plus==1.27.1 \ - --hash=sha256:912a7460446625b792f6448bade9e55cd4e41e6ac10e27009ef71a7f317fa147 \ - --hash=sha256:e4643061f3a4d0de092d62aa4ad09fa4756b2cbb89d4627f3985018216f9fefc +proto-plus==1.27.2 \ + --hash=sha256:6432f75893d3b9e70b9c412f1d2f03f65b11fb164b793d14ae2ca01821d22718 \ + --hash=sha256:b2adde53adadf75737c44d3dcb0104fde65250dfc83ad59168b4aa3e574b6a24 # via # google-api-core # google-cloud-bigquery-storage # google-cloud-bigtable # google-cloud-datastore -protobuf==4.25.8 \ - --hash=sha256:077ff8badf2acf8bc474406706ad890466274191a48d0abd3bd6987107c9cde5 \ - --hash=sha256:15a0af558aa3b13efef102ae6e4f3efac06f1eea11afb3a57db2901447d9fb59 \ - --hash=sha256:27d498ffd1f21fb81d987a041c32d07857d1d107909f5134ba3350e1ce80a4af \ - --hash=sha256:504435d831565f7cfac9f0714440028907f1975e4bed228e58e72ecfff58a1e0 \ - --hash=sha256:6135cf8affe1fc6f76cced2641e4ea8d3e59518d1f24ae41ba97bcad82d397cd \ - --hash=sha256:83e6e54e93d2b696a92cad6e6efc924f3850f82b52e1563778dfab8b355101b0 \ - --hash=sha256:9ad7ef62d92baf5a8654fbb88dac7fa5594cfa70fd3440488a5ca3bfc6d795a7 \ - --hash=sha256:bd551eb1fe1d7e92c1af1d75bdfa572eff1ab0e5bf1736716814cdccdb2360f9 \ - --hash=sha256:ca809b42f4444f144f2115c4c1a747b9a404d590f18f37e9402422033e464e0f \ - --hash=sha256:d552c53d0415449c8d17ced5c341caba0d89dbf433698e1436c8fa0aae7808a3 \ - --hash=sha256:f4510b93a3bec6eba8fd8f1093e9d7fb0d4a24d1a81377c10c0e5bbfe9e4ed24 +protobuf==4.25.9 \ + --hash=sha256:3683c05154252206f7cb2d371626514b3708199d9bcf683b503dabf3a2e38e06 \ + --hash=sha256:438c636de8fb706a0de94a12a268ef1ae8f5ba5ae655a7671fcda5968ba3c9be \ + --hash=sha256:79faf4e5a80b231d94dcf3a0a2917ccbacf0f586f12c9b9c91794b41b913a853 \ + --hash=sha256:7f7c1abcea3fc215918fba67a2d2a80fbcccc0f84159610eb187e9bbe6f939ee \ + --hash=sha256:9481e80e8cffb1c492c68e7c4e6726f4ad02eebc4fa97ead7beebeaa3639511d \ + --hash=sha256:9560813560e6ee72c11ca8873878bdb7ee003c96a57ebb013245fe84e2540904 \ + --hash=sha256:999146ef02e7fa6a692477badd1528bcd7268df211852a3df2d834ba2b480791 \ + --hash=sha256:b0dc7e7c68de8b1ce831dacb12fb407e838edbb8b6cc0dc3a2a6b4cbf6de9cff \ + --hash=sha256:b1d467352de666dc1b6d5740b6319d9c08cab7b21b452501e4ee5b0ac5156780 \ + --hash=sha256:bde396f568b0b46fc8fbfe9f02facf25b6755b2578a3b8ac61e74b9d69499e03 \ + --hash=sha256:d49b615e7c935194ac161f0965699ac84df6112c378e05ec53da65d2e4cbb6d4 # via # feast (pyproject.toml) # google-api-core @@ -3464,7 +3519,6 @@ protobuf==4.25.8 \ # grpcio-status # grpcio-testing # grpcio-tools - # ikvpy # mypy-protobuf # proto-plus # pymilvus @@ -3669,12 +3723,10 @@ pyarrow-hotfix==0.7 \ --hash=sha256:3236f3b5f1260f0e2ac070a55c1a7b339c4bb7267839bd2015e283234e758100 \ --hash=sha256:59399cd58bdd978b2e42816a4183a55c6472d4e33d183351b6069f11ed42661d # via ibis-framework -pyasn1==0.6.2 \ - --hash=sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf \ - --hash=sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b - # via - # pyasn1-modules - # rsa +pyasn1==0.6.3 \ + --hash=sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf \ + --hash=sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde + # via pyasn1-modules pyasn1-modules==0.4.2 \ --hash=sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a \ --hash=sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6 @@ -3907,9 +3959,9 @@ pydantic-core==2.41.5 \ --hash=sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425 \ --hash=sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52 # via pydantic -pydantic-settings==2.13.0 \ - --hash=sha256:95d875514610e8595672800a5c40b073e99e4aae467fa7c8f9c263061ea2e1fe \ - --hash=sha256:d67b576fff39cd086b595441bf9c75d4193ca9c0ed643b90360694d0f1240246 +pydantic-settings==2.13.1 \ + --hash=sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025 \ + --hash=sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237 # via # docling # fastapi-mcp @@ -3918,9 +3970,9 @@ pydata-google-auth==1.9.1 \ --hash=sha256:0a51ce41c601ca0bc69b8795bf58bedff74b4a6a007c9106c7cbcdec00eaced2 \ --hash=sha256:75ffce5d106e34b717b31844c1639ea505b7d9550dc23b96fb6c20d086b53fa3 # via pandas-gbq -pygments==2.19.2 \ - --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \ - --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b +pygments==2.20.0 \ + --hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \ + --hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176 # via # feast (pyproject.toml) # ipython @@ -3928,9 +3980,9 @@ pygments==2.19.2 \ # nbconvert # rich # sphinx -pyjwt[crypto]==2.11.0 \ - --hash=sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623 \ - --hash=sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469 +pyjwt[crypto]==2.12.1 \ + --hash=sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c \ + --hash=sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b # via # feast (pyproject.toml) # mcp @@ -4076,9 +4128,9 @@ pyodbc==5.3.0 \ # via # feast (pyproject.toml) # ibis-framework -pyopenssl==25.1.0 \ - --hash=sha256:2b11f239acc47ac2e5aca04fd7fa829800aeee22a2eb30d744572a157bd8a1ab \ - --hash=sha256:8d031884482e0c67ee92bf9a4d8cceb08d92aba7136432ffb0703c5280fc205b +pyopenssl==26.0.0 \ + --hash=sha256:df94d28498848b98cc1c0ffb8ef1e71e40210d3b0a8064c9d29571ed2904bf81 \ + --hash=sha256:f293934e52936f2e3413b89c6ce36df66a0b34ae1ea3a053b8c5020ff2f513fc # via snowflake-connector-python pyparsing==3.3.2 \ --hash=sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d \ @@ -4130,9 +4182,9 @@ pytest-benchmark==3.4.1 \ --hash=sha256:36d2b08c4882f6f997fd3126a3d6dfd70f3249cde178ed8bbc0b73db7c20f809 \ --hash=sha256:40e263f912de5a81d891619032983557d62a3d85843f9a9f30b98baea0cd7b47 # via feast (pyproject.toml) -pytest-cov==7.0.0 \ - --hash=sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1 \ - --hash=sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861 +pytest-cov==7.1.0 \ + --hash=sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2 \ + --hash=sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678 # via feast (pyproject.toml) pytest-env==1.1.3 \ --hash=sha256:aada77e6d09fcfb04540a6e462c58533c37df35fa853da78707b17ec04d17dfc \ @@ -4288,17 +4340,17 @@ python-docx==1.2.0 \ --hash=sha256:3fd478f3250fbbbfd3b94fe1e985955737c145627498896a8a6bf81f4baf66c7 \ --hash=sha256:7bc9d7b7d8a69c9c02ca09216118c86552704edc23bac179283f2e38f86220ce # via docling -python-dotenv==1.2.1 \ - --hash=sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6 \ - --hash=sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61 +python-dotenv==1.2.2 \ + --hash=sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a \ + --hash=sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3 # via # pydantic-settings # pymilvus # testcontainers # uvicorn -python-json-logger==4.0.0 \ - --hash=sha256:af09c9daf6a813aa4cc7180395f50f2a9e5fa056034c9953aec92e381c5ba1e2 \ - --hash=sha256:f58e68eb46e1faed27e0f574a55a0455eecd7b8a5b88b85a784519ba3cff047f +python-json-logger==4.1.0 \ + --hash=sha256:132994765cf75bf44554be9aa49b06ef2345d23661a96720262716438141b6b2 \ + --hash=sha256:b396b9e3ed782b09ff9d6e4f1683d46c83ad0d35d2e407c09a9ebbf038f88195 # via jupyter-events python-keycloak==4.2.2 \ --hash=sha256:1d43a1accd4a038ed39317fcb3eb78211df6c75bbcbc4c482c99ee76327136f2 \ @@ -4312,9 +4364,9 @@ python-pptx==1.0.2 \ --hash=sha256:160838e0b8565a8b1f67947675886e9fea18aa5e795db7ae531606d68e785cba \ --hash=sha256:479a8af0eaf0f0d76b6f00b0887732874ad2e3188230315290cd1f9dd9cc7095 # via docling -pytz==2025.2 \ - --hash=sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3 \ - --hash=sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00 +pytz==2026.1.post1 \ + --hash=sha256:3378dde6a0c3d26719182142c56e60c7f9af7e968076f31aae569d72a0358ee1 \ + --hash=sha256:f2fd16142fda348286a75e1a524be810bb05d444e5a081f37f7affc635035f7a # via # clickhouse-connect # great-expectations @@ -4509,26 +4561,26 @@ pyzmq==27.1.0 \ # ipykernel # jupyter-client # jupyter-server -qdrant-client==1.16.2 \ - --hash=sha256:442c7ef32ae0f005e88b5d3c0783c63d4912b97ae756eb5e052523be682f17d3 \ - --hash=sha256:ca4ef5f9be7b5eadeec89a085d96d5c723585a391eb8b2be8192919ab63185f0 +qdrant-client==1.17.1 \ + --hash=sha256:22f990bbd63485ed97ba551a4c498181fcb723f71dcab5d6e4e43fe1050a2bc0 \ + --hash=sha256:6cda4064adfeaf211c751f3fbc00edbbdb499850918c7aff4855a9a759d56cbd # via feast (pyproject.toml) -ray==2.53.0 \ - --hash=sha256:14f46363e9b4cf0c1c8b4d8623ec337c5bd408377831b5e5b50067930137bbca \ - --hash=sha256:4108280d8a1cb90d7d68e5c954c35e63b8bb9a4ba15f88c5e7da0e2025647712 \ - --hash=sha256:4a1bb3fe09ab4cd0d16ddc96b9f60c9ed83b3f93b87aa8506e0d3b746fd4e825 \ - --hash=sha256:4db914a0a6dd608fa49c066929a1282745a2dbd73caee67d7b80fe684ca65bdd \ - --hash=sha256:4dbb5fce1364763f29741055f50abe33cf726397141f9cc0e845dd3cc963e455 \ - --hash=sha256:65e2ce58d3dc6baa3cf45824d889c1968ebde565ee54dfd80a98af8f31af8e4a \ - --hash=sha256:7196e5358dfcc8211be864f45e6dfe4827202df294af3c7a76ff8fbc080e0522 \ - --hash=sha256:73dbbaa7962a7f5e38aa8cf9483e0e9817205e989aa3dc859c738c2af1ae01df \ - --hash=sha256:85b472ab6fb8f1189f8cef81913fd91b24dd69b3fa7dcca7e144827bd924f6c0 \ - --hash=sha256:90faf630d20b6abf3135997fb3edb5842134aff92e04ee709865db04816d97ef \ - --hash=sha256:a0bbb98b0b0f25a3ee075ca10171e1260e70b6bc690cd509ecd7ce1228af854d \ - --hash=sha256:b828c147f9ff2f277b1d254e4fe9a746fdfaee7e313a93a97c7edf4dae9b81a4 \ - --hash=sha256:bd3ec4c342776ddac23ae2b108c64f5939f417ccc4875900d586c7c978463269 \ - --hash=sha256:d8b95d047d947493803fb8417aea31225dcacdab15afdc75b8a238901949d457 \ - --hash=sha256:eb000c17f7301071fdd15c44c4cd3ac0f7953bb4c7c227e61719fe7048195bcd +ray==2.54.1 \ + --hash=sha256:054985194bd32f4464c93f9318d247fac61e1f32ac221565ecfdc81ab8c75d0b \ + --hash=sha256:0c3ae2943176e7b239c78b825a5b2bf4135d90280083a0e19c0a75a5db4d836f \ + --hash=sha256:2766f0230806480c38a9a94502087f1d4aea919f38521a28781690613b0290a4 \ + --hash=sha256:2ea650e648acc6e76edd98c694657fd1fcb1cd97700d944a7d20da90269e9810 \ + --hash=sha256:4c6f7e23dda62a32f94083141c3f97e9c4246e3ae4ae2bc488bcd8fd0311f54a \ + --hash=sha256:512587412e2f5e1753adabfdfa4dd9cff1dc509601e36fd5fab671e448ae4dac \ + --hash=sha256:6425f15cfe6a298366b53c8658350f94ced2c548802ca3b69f94b87db16e97c5 \ + --hash=sha256:645ebfb73cfd32bd510a05ed9f2738a18d6db69929cae9701d749f2740dbfd9a \ + --hash=sha256:673a895c0c4a716ed772552baa3f5b8d7d1f7a4b34e04787fdfe6fe3049ed0d8 \ + --hash=sha256:86c51eafd3e84dad59c1ef4cf97b3ac8c088af0705782ee915e31bca5880597a \ + --hash=sha256:c0240496af274af7cd3b1b1d015f23b88e5fdafe59bfdc040e5f229e0aff5dff \ + --hash=sha256:cd452b61ae2e0daf9271f5a554614397429cc2731681bae10fe72316dadc2749 \ + --hash=sha256:d05f477d1518a00fd5880644e889a7a3eaf64ae5d1f8f239a682d052ad2a383d \ + --hash=sha256:e095dfe9c521a04e5930520b4a82ea82d61903d4cd2f3270fbc5dfbdb41b9c72 \ + --hash=sha256:ea90bed0110e0ce3ff6571e7a0c800920a3c6d299d29b8eac020dac362667169 # via feast (pyproject.toml) redis==4.6.0 \ --hash=sha256:585dc516b9eb042a619ef0a39c3d7d55fe81bdb4df09a52c9cdde0d07bf1aa7d \ @@ -4541,145 +4593,128 @@ referencing==0.37.0 \ # jsonschema # jsonschema-specifications # jupyter-events -regex==2026.1.15 \ - --hash=sha256:0057de9eaef45783ff69fa94ae9f0fd906d629d0bd4c3217048f46d1daa32e9b \ - --hash=sha256:008b185f235acd1e53787333e5690082e4f156c44c87d894f880056089e9bc7c \ - --hash=sha256:05d75a668e9ea16f832390d22131fe1e8acc8389a694c8febc3e340b0f810b93 \ - --hash=sha256:069f56a7bf71d286a6ff932a9e6fb878f151c998ebb2519a9f6d1cee4bffdba3 \ - --hash=sha256:0751a26ad39d4f2ade8fe16c59b2bf5cb19eb3d2cd543e709e583d559bd9efde \ - --hash=sha256:08df9722d9b87834a3d701f3fca570b2be115654dbfd30179f30ab2f39d606d3 \ - --hash=sha256:0bda75ebcac38d884240914c6c43d8ab5fb82e74cde6da94b43b17c411aa4c2b \ - --hash=sha256:0bf065240704cb8951cc04972cf107063917022511273e0969bdb34fc173456c \ - --hash=sha256:0bf650f26087363434c4e560011f8e4e738f6f3e029b85d4904c50135b86cfa5 \ - --hash=sha256:0dcd31594264029b57bf16f37fd7248a70b3b764ed9e0839a8f271b2d22c0785 \ - --hash=sha256:0f0c7684c7f9ca241344ff95a1de964f257a5251968484270e91c25a755532c5 \ - --hash=sha256:124dc36c85d34ef2d9164da41a53c1c8c122cfb1f6e1ec377a1f27ee81deb794 \ - --hash=sha256:164759aa25575cbc0651bef59a0b18353e54300d79ace8084c818ad8ac72b7d5 \ - --hash=sha256:166551807ec20d47ceaeec380081f843e88c8949780cd42c40f18d16168bed10 \ - --hash=sha256:1704d204bd42b6bb80167df0e4554f35c255b579ba99616def38f69e14a5ccb9 \ - --hash=sha256:18388a62989c72ac24de75f1449d0fb0b04dfccd0a1a7c1c43af5eb503d890f6 \ - --hash=sha256:194312a14819d3e44628a44ed6fea6898fdbecb0550089d84c403475138d0a09 \ - --hash=sha256:1ae6020fb311f68d753b7efa9d4b9a5d47a5d6466ea0d5e3b5a471a960ea6e4a \ - --hash=sha256:1cb740d044aff31898804e7bf1181cc72c03d11dfd19932b9911ffc19a79070a \ - --hash=sha256:1e1808471fbe44c1a63e5f577a1d5f02fe5d66031dcbdf12f093ffc1305a858e \ - --hash=sha256:1e8cd52557603f5c66a548f69421310886b28b7066853089e1a71ee710e1cdc1 \ - --hash=sha256:21ca32c28c30d5d65fc9886ff576fc9b59bbca08933e844fa2363e530f4c8218 \ - --hash=sha256:2748c1ec0663580b4510bd89941a31560b4b439a0b428b49472a3d9944d11cd8 \ - --hash=sha256:27618391db7bdaf87ac6c92b31e8f0dfb83a9de0075855152b720140bda177a2 \ - --hash=sha256:2a8d7b50c34578d0d3bf7ad58cde9652b7d683691876f83aedc002862a35dc5e \ - --hash=sha256:2b091aefc05c78d286657cd4db95f2e6313375ff65dcf085e42e4c04d9c8d410 \ - --hash=sha256:2c2b80399a422348ce5de4fe40c418d6299a0fa2803dd61dc0b1a2f28e280fcf \ - --hash=sha256:2f2775843ca49360508d080eaa87f94fa248e2c946bbcd963bb3aae14f333413 \ - --hash=sha256:3038a62fc7d6e5547b8915a3d927a0fbeef84cdbe0b1deb8c99bbd4a8961b52a \ - --hash=sha256:32655d17905e7ff8ba5c764c43cb124e34a9245e45b83c22e81041e1071aee10 \ - --hash=sha256:343db82cb3712c31ddf720f097ef17c11dab2f67f7a3e7be976c4f82eba4e6df \ - --hash=sha256:3601ffb5375de85a16f407854d11cca8fe3f5febbe3ac78fb2866bb220c74d10 \ - --hash=sha256:3d6ce5ae80066b319ae3bc62fd55a557c9491baa5efd0d355f0de08c4ba54e79 \ - --hash=sha256:3d7d92495f47567a9b1669c51fc8d6d809821849063d168121ef801bbc213846 \ - --hash=sha256:40c86d8046915bb9aeb15d3f3f15b6fd500b8ea4485b30e1bbc799dab3fe29f8 \ - --hash=sha256:4161d87f85fa831e31469bfd82c186923070fc970b9de75339b68f0c75b51903 \ - --hash=sha256:41aef6f953283291c4e4e6850607bd71502be67779586a61472beacb315c97ec \ - --hash=sha256:453078802f1b9e2b7303fb79222c054cb18e76f7bdc220f7530fdc85d319f99e \ - --hash=sha256:492534a0ab925d1db998defc3c302dae3616a2fc3fe2e08db1472348f096ddf2 \ - --hash=sha256:4c5ef43b5c2d4114eb8ea424bb8c9cec01d5d17f242af88b2448f5ee81caadbc \ - --hash=sha256:4c8fcc5793dde01641a35905d6731ee1548f02b956815f8f1cab89e515a5bdf1 \ - --hash=sha256:4def140aa6156bc64ee9912383d4038f3fdd18fee03a6f222abd4de6357ce42a \ - --hash=sha256:4e3dd93c8f9abe8aa4b6c652016da9a3afa190df5ad822907efe6b206c09896e \ - --hash=sha256:505831646c945e3e63552cc1b1b9b514f0e93232972a2d5bedbcc32f15bc82e3 \ - --hash=sha256:5170907244b14303edc5978f522f16c974f32d3aa92109fabc2af52411c9433b \ - --hash=sha256:55b4ea996a8e4458dd7b584a2f89863b1655dd3d17b88b46cbb9becc495a0ec5 \ - --hash=sha256:55e9d0118d97794367309635df398bdfd7c33b93e2fdfa0b239661cd74b4c14e \ - --hash=sha256:56a5595d0f892f214609c9f76b41b7428bed439d98dc961efafdd1354d42baae \ - --hash=sha256:57e7d17f59f9ebfa9667e6e5a1c0127b96b87cb9cede8335482451ed00788ba4 \ - --hash=sha256:5ef19071f4ac9f0834793af85bd04a920b4407715624e40cb7a0631a11137cdf \ - --hash=sha256:5ff818702440a5878a81886f127b80127f5d50563753a28211482867f8318106 \ - --hash=sha256:619843841e220adca114118533a574a9cd183ed8a28b85627d2844c500a2b0db \ - --hash=sha256:621f73a07595d83f28952d7bd1e91e9d1ed7625fb7af0064d3516674ec93a2a2 \ - --hash=sha256:693b465171707bbe882a7a05de5e866f33c76aa449750bee94a8d90463533cc9 \ - --hash=sha256:6bfc31a37fd1592f0c4fc4bfc674b5c42e52efe45b4b7a6a14f334cca4bcebe4 \ - --hash=sha256:6d220a2517f5893f55daac983bfa9fe998a7dbcaee4f5d27a88500f8b7873788 \ - --hash=sha256:6e42844ad64194fa08d5ccb75fe6a459b9b08e6d7296bd704460168d58a388f3 \ - --hash=sha256:726ea4e727aba21643205edad8f2187ec682d3305d790f73b7a51c7587b64bdd \ - --hash=sha256:74f45d170a21df41508cb67165456538425185baaf686281fa210d7e729abc34 \ - --hash=sha256:7dcc02368585334f5bc81fc73a2a6a0bbade60e7d83da21cead622faf408f32c \ - --hash=sha256:7e1e28be779884189cdd57735e997f282b64fd7ccf6e2eef3e16e57d7a34a815 \ - --hash=sha256:7ef7d5d4bd49ec7364315167a4134a015f61e8266c6d446fc116a9ac4456e10d \ - --hash=sha256:8050ba2e3ea1d8731a549e83c18d2f0999fbc99a5f6bd06b4c91449f55291804 \ - --hash=sha256:82345326b1d8d56afbe41d881fdf62f1926d7264b2fc1537f99ae5da9aad7913 \ - --hash=sha256:8355ad842a7c7e9e5e55653eade3b7d1885ba86f124dd8ab1f722f9be6627434 \ - --hash=sha256:86c1077a3cc60d453d4084d5b9649065f3bf1184e22992bd322e1f081d3117fb \ - --hash=sha256:87adf5bd6d72e3e17c9cb59ac4096b1faaf84b7eb3037a5ffa61c4b4370f0f13 \ - --hash=sha256:8db052bbd981e1666f09e957f3790ed74080c2229007c1dd67afdbf0b469c48b \ - --hash=sha256:8dd16fba2758db7a3780a051f245539c4451ca20910f5a5e6ea1c08d06d4a76b \ - --hash=sha256:8e32f7896f83774f91499d239e24cebfadbc07639c1494bb7213983842348337 \ - --hash=sha256:91c5036ebb62663a6b3999bdd2e559fd8456d17e2b485bf509784cd31a8b1705 \ - --hash=sha256:9250d087bc92b7d4899ccd5539a1b2334e44eee85d848c4c1aef8e221d3f8c8f \ - --hash=sha256:9479cae874c81bf610d72b85bb681a94c95722c127b55445285fb0e2c82db8e1 \ - --hash=sha256:968c14d4f03e10b2fd960f1d5168c1f0ac969381d3c1fcc973bc45fb06346599 \ - --hash=sha256:97499ff7862e868b1977107873dd1a06e151467129159a6ffd07b66706ba3a9f \ - --hash=sha256:99ad739c3686085e614bf77a508e26954ff1b8f14da0e3765ff7abbf7799f952 \ - --hash=sha256:9d787e3310c6a6425eb346be4ff2ccf6eece63017916fd77fe8328c57be83521 \ - --hash=sha256:a1774cd1981cd212506a23a14dba7fdeaee259f5deba2df6229966d9911e767a \ - --hash=sha256:a30a68e89e5a218b8b23a52292924c1f4b245cb0c68d1cce9aec9bbda6e2c160 \ - --hash=sha256:adc97a9077c2696501443d8ad3fa1b4fc6d131fc8fd7dfefd1a723f89071cf0a \ - --hash=sha256:b0d190e6f013ea938623a58706d1469a62103fb2a241ce2873a9906e0386582c \ - --hash=sha256:b10e42a6de0e32559a92f2f8dc908478cc0fa02838d7dbe764c44dca3fa13569 \ - --hash=sha256:b2a13dd6a95e95a489ca242319d18fc02e07ceb28fa9ad146385194d95b3c829 \ - --hash=sha256:b30bcbd1e1221783c721483953d9e4f3ab9c5d165aa709693d3f3946747b1aea \ - --hash=sha256:b325d4714c3c48277bfea1accd94e193ad6ed42b4bad79ad64f3b8f8a31260a5 \ - --hash=sha256:b5a28980a926fa810dbbed059547b02783952e2efd9c636412345232ddb87ff6 \ - --hash=sha256:b5f7d8d2867152cdb625e72a530d2ccb48a3d199159144cbdd63870882fb6f80 \ - --hash=sha256:bfb0d6be01fbae8d6655c8ca21b3b72458606c4aec9bbc932db758d47aba6db1 \ - --hash=sha256:bfd876041a956e6a90ad7cdb3f6a630c07d491280bfeed4544053cd434901681 \ - --hash=sha256:c08c1f3e34338256732bd6938747daa3c0d5b251e04b6e43b5813e94d503076e \ - --hash=sha256:c243da3436354f4af6c3058a3f81a97d47ea52c9bd874b52fd30274853a1d5df \ - --hash=sha256:c32bef3e7aeee75746748643667668ef941d28b003bfc89994ecf09a10f7a1b5 \ - --hash=sha256:c661fc820cfb33e166bf2450d3dadbda47c8d8981898adb9b6fe24e5e582ba60 \ - --hash=sha256:c6c4dcdfff2c08509faa15d36ba7e5ef5fcfab25f1e8f85a0c8f45bc3a30725d \ - --hash=sha256:c6c565d9a6e1a8d783c1948937ffc377dd5771e83bd56de8317c450a954d2056 \ - --hash=sha256:c8a154cf6537ebbc110e24dabe53095e714245c272da9c1be05734bdad4a61aa \ - --hash=sha256:c9c08c2fbc6120e70abff5d7f28ffb4d969e14294fb2143b4b5c7d20e46d1714 \ - --hash=sha256:ca89c5e596fc05b015f27561b3793dc2fa0917ea0d7507eebb448efd35274a70 \ - --hash=sha256:cc7cd0b2be0f0269283a45c0d8b2c35e149d1319dcb4a43c9c3689fa935c1ee6 \ - --hash=sha256:cda1ed70d2b264952e88adaa52eea653a33a1b98ac907ae2f86508eb44f65cdc \ - --hash=sha256:cf8ff04c642716a7f2048713ddc6278c5fd41faa3b9cab12607c7abecd012c22 \ - --hash=sha256:cfecdaa4b19f9ca534746eb3b55a5195d5c95b88cac32a205e981ec0a22b7d31 \ - --hash=sha256:d426616dae0967ca225ab12c22274eb816558f2f99ccb4a1d52ca92e8baf180f \ - --hash=sha256:d5eaa4a4c5b1906bd0d2508d68927f15b81821f85092e06f1a34a4254b0e1af3 \ - --hash=sha256:d639a750223132afbfb8f429c60d9d318aeba03281a5f1ab49f877456448dcf1 \ - --hash=sha256:d920392a6b1f353f4aa54328c867fec3320fa50657e25f64abf17af054fc97ac \ - --hash=sha256:d991483606f3dbec93287b9f35596f41aa2e92b7c2ebbb935b63f409e243c9af \ - --hash=sha256:d9ea2604370efc9a174c1b5dcc81784fb040044232150f7f33756049edfc9026 \ - --hash=sha256:dbaf3c3c37ef190439981648ccbf0c02ed99ae066087dd117fcb616d80b010a4 \ - --hash=sha256:dca3582bca82596609959ac39e12b7dad98385b4fefccb1151b937383cec547d \ - --hash=sha256:e3174a5ed4171570dc8318afada56373aa9289eb6dc0d96cceb48e7358b0e220 \ - --hash=sha256:e43a55f378df1e7a4fa3547c88d9a5a9b7113f653a66821bcea4718fe6c58763 \ - --hash=sha256:e69d0deeb977ffe7ed3d2e4439360089f9c3f217ada608f0f88ebd67afb6385e \ - --hash=sha256:e85dc94595f4d766bd7d872a9de5ede1ca8d3063f3bdf1e2c725f5eb411159e3 \ - --hash=sha256:e90b8db97f6f2c97eb045b51a6b2c5ed69cedd8392459e0642d4199b94fabd7e \ - --hash=sha256:e9bf3f0bbdb56633c07d7116ae60a576f846efdd86a8848f8d62b749e1209ca7 \ - --hash=sha256:ea4e6b3566127fda5e007e90a8fd5a4169f0cf0619506ed426db647f19c8454a \ - --hash=sha256:ec94c04149b6a7b8120f9f44565722c7ae31b7a6d2275569d2eefa76b83da3be \ - --hash=sha256:eddf73f41225942c1f994914742afa53dc0d01a6e20fe14b878a1b1edc74151f \ - --hash=sha256:ee6854c9000a10938c79238de2379bea30c82e4925a371711af45387df35cab8 \ - --hash=sha256:ef71d476caa6692eea743ae5ea23cde3260677f70122c4d258ca952e5c2d4e84 \ - --hash=sha256:f052d1be37ef35a54e394de66136e30fa1191fab64f71fc06ac7bc98c9a84618 \ - --hash=sha256:f1862739a1ffb50615c0fde6bae6569b5efbe08d98e59ce009f68a336f64da75 \ - --hash=sha256:f192a831d9575271a22d804ff1a5355355723f94f31d9eef25f0d45a152fdc1a \ - --hash=sha256:f42e68301ff4afee63e365a5fc302b81bb8ba31af625a671d7acb19d10168a8c \ - --hash=sha256:f7792f27d3ee6e0244ea4697d92b825f9a329ab5230a78c1a68bd274e64b5077 \ - --hash=sha256:f82110ab962a541737bd0ce87978d4c658f06e7591ba899192e2712a517badbb \ - --hash=sha256:f9ca1cbdc0fbfe5e6e6f8221ef2309988db5bcede52443aeaee9a4ad555e0dac \ - --hash=sha256:fd65af65e2aaf9474e468f9e571bd7b189e1df3a61caa59dcbabd0000e4ea839 \ - --hash=sha256:fe2fda4110a3d0bc163c2e0664be44657431440722c5c5315c65155cab92f9e5 \ - --hash=sha256:febd38857b09867d3ed3f4f1af7d241c5c50362e25ef43034995b77a50df494e +regex==2026.3.32 \ + --hash=sha256:03c2ebd15ff51e7b13bb3dc28dd5ac18cd39e59ebb40430b14ae1a19e833cff1 \ + --hash=sha256:09e26cad1544d856da85881ad292797289e4406338afe98163f3db9f7fac816c \ + --hash=sha256:0cec365d44835b043d7b3266487797639d07d621bec9dc0ea224b00775797cc1 \ + --hash=sha256:0d7855f5e59fcf91d0c9f4a51dc5d8847813832a2230c3e8e35912ccf20baaa2 \ + --hash=sha256:0f21ae18dfd15752cdd98d03cbd7a3640be826bfd58482a93f730dbd24d7b9fb \ + --hash=sha256:10fb2aaae1aaadf7d43c9f3c2450404253697bf8b9ce360bd5418d1d16292298 \ + --hash=sha256:110ba4920721374d16c4c8ea7ce27b09546d43e16aea1d7f43681b5b8f80ba61 \ + --hash=sha256:12917c6c6813ffcdfb11680a04e4d63c5532b88cf089f844721c5f41f41a63ad \ + --hash=sha256:18eb45f711e942c27dbed4109830bd070d8d618e008d0db39705f3f57070a4c6 \ + --hash=sha256:1a6ac1ed758902e664e0d95c1ee5991aa6fb355423f378ed184c6ec47a1ec0e9 \ + --hash=sha256:1ca02ff0ef33e9d8276a1fcd6d90ff6ea055a32c9149c0050b5b67e26c6d2c51 \ + --hash=sha256:1cb22fa9ee6a0acb22fc9aecce5f9995fe4d2426ed849357d499d62608fbd7f9 \ + --hash=sha256:1e0f6648fd48f4c73d801c55ab976cd602e2da87de99c07bff005b131f269c6a \ + --hash=sha256:245667ad430745bae6a1e41081872d25819d86fbd9e0eec485ba00d9f78ad43d \ + --hash=sha256:2820d2231885e97aff0fcf230a19ebd5d2b5b8a1ba338c20deb34f16db1c7897 \ + --hash=sha256:2c8d402ea3dfe674288fe3962016affd33b5b27213d2b5db1823ffa4de524c57 \ + --hash=sha256:2dcca2bceb823c9cc610e57b86a265d7ffc30e9fe98548c609eba8bd3c0c2488 \ + --hash=sha256:2ffbadc647325dd4e3118269bda93ded1eb5f5b0c3b7ba79a3da9fbd04f248e9 \ + --hash=sha256:34c905a721ddee0f84c99e3e3b59dd4a5564a6fe338222bc89dd4d4df166115c \ + --hash=sha256:3c054e39a9f85a3d76c62a1d50c626c5e9306964eaa675c53f61ff7ec1204bbb \ + --hash=sha256:3c0bbfbd38506e1ea96a85da6782577f06239cb9fcf9696f1ea537c980c0680b \ + --hash=sha256:3e221b615f83b15887636fcb90ed21f1a19541366f8b7ba14ba1ad8304f4ded4 \ + --hash=sha256:3ea568832eca219c2be1721afa073c1c9eb8f98a9733fdedd0a9747639fc22a5 \ + --hash=sha256:3f5747501b69299c6b0b047853771e4ed390510bada68cb16da9c9c2078343f7 \ + --hash=sha256:462a041d2160090553572f6bb0be417ab9bb912a08de54cb692829c871ee88c1 \ + --hash=sha256:4bc32b4dbdb4f9f300cf9f38f8ea2ce9511a068ffaa45ac1373ee7a943f1d810 \ + --hash=sha256:4d082be64e51671dd5ee1c208c92da2ddda0f2f20d8ef387e57634f7e97b6aae \ + --hash=sha256:4f9ae4755fa90f1dc2d0d393d572ebc134c0fe30fcfc0ab7e67c1db15f192041 \ + --hash=sha256:51a93452034d671b0e21b883d48ea66c5d6a05620ee16a9d3f229e828568f3f0 \ + --hash=sha256:51fb7e26f91f9091fd8ec6a946f99b15d3bc3667cb5ddc73dd6cb2222dd4a1cc \ + --hash=sha256:5336b1506142eb0f23c96fb4a34b37c4fefd4fed2a7042069f3c8058efe17855 \ + --hash=sha256:567b57eb987547a23306444e4f6f85d4314f83e65c71d320d898aa7550550443 \ + --hash=sha256:5aa78c857c1731bdd9863923ffadc816d823edf475c7db6d230c28b53b7bdb5e \ + --hash=sha256:5bf2f3c2c5bd8360d335c7dcd4a9006cf1dabae063ee2558ee1b07bbc8a20d88 \ + --hash=sha256:5c35d097f509cf7e40d20d5bee548d35d6049b36eb9965e8d43e4659923405b9 \ + --hash=sha256:5d86e3fb08c94f084a625c8dc2132a79a3a111c8bf6e2bc59351fa61753c2f6e \ + --hash=sha256:6062c4ef581a3e9e503dccf4e1b7f2d33fdc1c13ad510b287741ac73bc4c6b27 \ + --hash=sha256:6128dd0793a87287ea1d8bf16b4250dd96316c464ee15953d5b98875a284d41e \ + --hash=sha256:631f7d95c83f42bccfe18946a38ad27ff6b6717fb4807e60cf24860b5eb277fc \ + --hash=sha256:66a5083c3ffe5a5a95f8281ea47a88072d4f24001d562d1d9d28d4cdc005fec5 \ + --hash=sha256:66d3126afe7eac41759cd5f0b3b246598086e88e70527c0d68c9e615b81771c4 \ + --hash=sha256:67015a8162d413af9e3309d9a24e385816666fbf09e48e3ec43342c8536f7df6 \ + --hash=sha256:6980ceb5c1049d4878632f08ba0bf7234c30e741b0dc9081da0f86eca13189d3 \ + --hash=sha256:69a847a6ffaa86e8af7b9e7037606e05a6f663deec516ad851e8e05d9908d16a \ + --hash=sha256:6ada7bd5bb6511d12177a7b00416ce55caee49fbf8c268f26b909497b534cacb \ + --hash=sha256:70c634e39c5cda0da05c93d6747fdc957599f7743543662b6dbabdd8d3ba8a96 \ + --hash=sha256:7cdd508664430dd51b8888deb6c5b416d8de046b2e11837254378d31febe4a98 \ + --hash=sha256:844d88509c968dd44b30daeefac72b038b1bf31ac372d5106358ab01d393c48b \ + --hash=sha256:847087abe98b3c1ebf1eb49d6ef320dbba75a83ee4f83c94704580f1df007dd4 \ + --hash=sha256:85c9b0c131427470a6423baa0a9330be6fd8c3630cc3ee6fdee03360724cbec5 \ + --hash=sha256:879ae91f2928a13f01a55cfa168acedd2b02b11b4cd8b5bb9223e8cde777ca52 \ + --hash=sha256:887a9fa74418d74d645281ee0edcf60694053bd1bc2ebc49eb5e66bfffc6d107 \ + --hash=sha256:88ebc0783907468f17fca3d7821b30f9c21865a721144eb498cb0ff99a67bcac \ + --hash=sha256:89e50667e7e8c0e7903e4d644a2764fffe9a3a5d6578f72ab7a7b4205bf204b7 \ + --hash=sha256:8a4a3189a99ecdd1c13f42513ab3fc7fa8311b38ba7596dd98537acb8cd9acc3 \ + --hash=sha256:8aaf8ee8f34b677f90742ca089b9c83d64bdc410528767273c816a863ed57327 \ + --hash=sha256:8e4c8fa46aad1a11ae2f8fcd1c90b9d55e18925829ac0d98c5bb107f93351745 \ + --hash=sha256:8fc918cd003ba0d066bf0003deb05a259baaaab4dc9bd4f1207bbbe64224857a \ + --hash=sha256:8fe14e24124ef41220e5992a0f09432f890037df6f93fd3d6b7a0feff2db16b2 \ + --hash=sha256:918db4e34a7ef3d0beee913fa54b34231cc3424676f1c19bdb85f01828d3cd37 \ + --hash=sha256:987cdfcfb97a249abc3601ad53c7de5c370529f1981e4c8c46793e4a1e1bfe8e \ + --hash=sha256:9b9118a78e031a2e4709cd2fcc3028432e89b718db70073a8da574c249b5b249 \ + --hash=sha256:9cf7036dfa2370ccc8651521fcbb40391974841119e9982fa312b552929e6c85 \ + --hash=sha256:a094e9dcafedfb9d333db5cf880304946683f43a6582bb86688f123335122929 \ + --hash=sha256:a416ee898ecbc5d8b283223b4cf4d560f93244f6f7615c1bd67359744b00c166 \ + --hash=sha256:a5d88fa37ba5e8a80ca8d956b9ea03805cfa460223ac94b7d4854ee5e30f3173 \ + --hash=sha256:ace48c5e157c1e58b7de633c5e257285ce85e567ac500c833349c363b3df69d4 \ + --hash=sha256:ad5c53f2e8fcae9144009435ebe3d9832003508cf8935c04542a1b3b8deefa15 \ + --hash=sha256:ad8d372587e659940568afd009afeb72be939c769c552c9b28773d0337251391 \ + --hash=sha256:b193ed199848aa96618cd5959c1582a0bf23cd698b0b900cb0ffe81b02c8659c \ + --hash=sha256:b2e9c2ea2e93223579308263f359eab8837dc340530b860cb59b713651889f14 \ + --hash=sha256:b3aa21bad31db904e0b9055e12c8282df62d43169c4a9d2929407060066ebc74 \ + --hash=sha256:b565f25171e04d4fad950d1fa837133e3af6ea6f509d96166eed745eb0cf63bc \ + --hash=sha256:b56993a7aeb4140c4770f4f7965c9e5af4f024457d06e23c01b0d47501cb18ed \ + --hash=sha256:b6acb765e7c1f2fa08ac9057a33595e26104d7d67046becae184a8f100932dd9 \ + --hash=sha256:b6f366a5ef66a2df4d9e68035cfe9f0eb8473cdfb922c37fac1d169b468607b0 \ + --hash=sha256:b7836aa13721dbdef658aebd11f60d00de633a95726521860fe1f6be75fa225a \ + --hash=sha256:b8fca73e16c49dd972ce3a88278dfa5b93bf91ddef332a46e9443abe21ca2f7c \ + --hash=sha256:b953d9d496d19786f4d46e6ba4b386c6e493e81e40f9c5392332458183b0599d \ + --hash=sha256:bbc458a292aee57d572075f22c035fa32969cdb7987d454e3e34d45a40a0a8b4 \ + --hash=sha256:c1cecea3e477af105f32ef2119b8d895f297492e41d317e60d474bc4bffd62ff \ + --hash=sha256:c1d7fa44aece1fa02b8927441614c96520253a5cad6a96994e3a81e060feed55 \ + --hash=sha256:c1ed17104d1be7f807fdec35ec99777168dd793a09510d753f8710590ba54cdd \ + --hash=sha256:c3c6f6b027d10f84bfe65049028892b5740878edd9eae5fea0d1710b09b1d257 \ + --hash=sha256:c5e0fdb5744caf1036dec5510f543164f2144cb64932251f6dfd42fa872b7f9c \ + --hash=sha256:c60f1de066eb5a0fd8ee5974de4194bb1c2e7692941458807162ffbc39887303 \ + --hash=sha256:c6d9c6e783b348f719b6118bb3f187b2e138e3112576c9679eb458cc8b2e164b \ + --hash=sha256:c940e00e8d3d10932c929d4b8657c2ea47d2560f31874c3e174c0d3488e8b865 \ + --hash=sha256:c9f261ad3cd97257dc1d9355bfbaa7dd703e06574bffa0fa8fe1e31da915ee38 \ + --hash=sha256:d21a07edddb3e0ca12a8b8712abc8452481c3d3db19ae87fc94e9842d005964b \ + --hash=sha256:d363660f9ef8c734495598d2f3e527fb41f745c73159dc0d743402f049fb6836 \ + --hash=sha256:d478a2ca902b6ef28ffc9521e5f0f728d036abe35c0b250ee8ae78cfe7c5e44e \ + --hash=sha256:d571f0b2eec3513734ea31a16ce0f7840c0b85a98e7edfa0e328ed144f9ef78f \ + --hash=sha256:d6b39a2cc5625bbc4fda18919a891eab9aab934eecf83660a90ce20c53621a9a \ + --hash=sha256:d76d62909bfb14521c3f7cfd5b94c0c75ec94b0a11f647d2f604998962ec7b6c \ + --hash=sha256:dab4178a0bc1ef13178832b12db7bc7f562e8f028b2b5be186e370090dc50652 \ + --hash=sha256:db976be51375bca900e008941639448d148c655c9545071965d0571ecc04f5d0 \ + --hash=sha256:ded4fc0edf3de792850cb8b04bbf3c5bd725eeaf9df4c27aad510f6eed9c4e19 \ + --hash=sha256:e006ea703d5c0f3d112b51ba18af73b58209b954acfe3d8da42eacc9a00e4be6 \ + --hash=sha256:e3e5d1802cba785210a4a800e63fcee7a228649a880f3bf7f2aadccb151a834b \ + --hash=sha256:e480d3dac06c89bc2e0fd87524cc38c546ac8b4a38177650745e64acbbcfdeba \ + --hash=sha256:e50af656c15e2723eeb7279c0837e07accc594b95ec18b86821a4d44b51b24bf \ + --hash=sha256:e83ce8008b48762be296f1401f19afd9ea29f3d035d1974e0cecb74e9afbd1df \ + --hash=sha256:ed3b8281c5d0944d939c82db4ec2300409dd69ee087f7a75a94f2e301e855fb4 \ + --hash=sha256:ef250a3f5e93182193f5c927c5e9575b2cb14b80d03e258bc0b89cc5de076b60 \ + --hash=sha256:f1574566457161678297a116fa5d1556c5a4159d64c5ff7c760e7c564bf66f16 \ + --hash=sha256:f26262900edd16272b6360014495e8d68379c6c6e95983f9b7b322dc928a1194 \ + --hash=sha256:f28eac18a8733a124444643a66ac96fef2c0ad65f50034e0a043b90333dc677f \ + --hash=sha256:f54840bea73541652f1170dc63402a5b776fc851ad36a842da9e5163c1f504a0 \ + --hash=sha256:f785f44a44702dea89b28bce5bc82552490694ce4e144e21a4f0545e364d2150 \ + --hash=sha256:f7cc00089b4c21847852c0ad76fb3680f9833b855a0d30bcec94211c435bff6b \ + --hash=sha256:f95bd07f301135771559101c060f558e2cf896c7df00bec050ca7f93bf11585a \ + --hash=sha256:fc8ced733d6cd9af5e412f256a32f7c61cd2d7371280a65c689939ac4572499f \ + --hash=sha256:fd03e38068faeef937cc6761a250a4aaa015564bd0d61481fefcf15586d31825 # via # feast (pyproject.toml) # parsimonious # transformers -requests==2.32.5 \ - --hash=sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6 \ - --hash=sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf +requests==2.33.1 \ + --hash=sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517 \ + --hash=sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a # via # feast (pyproject.toml) # azure-core @@ -4717,9 +4752,9 @@ requests-toolbelt==1.0.0 \ --hash=sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6 \ --hash=sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06 # via python-keycloak -responses==0.25.8 \ - --hash=sha256:0c710af92def29c8352ceadff0c3fe340ace27cf5af1bbe46fb71275bcd2831c \ - --hash=sha256:9374d047a575c8f781b94454db5cab590b6029505f488d12899ddb10a4af1cf4 +responses==0.26.0 \ + --hash=sha256:03ec4409088cd5c66b71ecbbbd27fe2c58ddfad801c66203457b3e6a04868c37 \ + --hash=sha256:c7f6923e6343ef3682816ba421c006626777893cb0d5e1434f674b649bac9eb4 # via moto rfc3339-validator==0.1.4 \ --hash=sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b \ @@ -4737,9 +4772,9 @@ rfc3987-syntax==1.1.0 \ --hash=sha256:6c3d97604e4c5ce9f714898e05401a0445a641cfa276432b0a648c80856f6a3f \ --hash=sha256:717a62cbf33cffdd16dfa3a497d81ce48a660ea691b1ddd7be710c22f00b4a0d # via jsonschema -rich==14.3.2 \ - --hash=sha256:08e67c3e90884651da3239ea668222d19bea7b589149d8014a21c633420dbb69 \ - --hash=sha256:e712f11c1a562a11843306f5ed999475f09ac31ffb64281f73ab29ffdda8b3b8 +rich==14.3.3 \ + --hash=sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d \ + --hash=sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b # via # fastapi-mcp # ibis-framework @@ -4863,10 +4898,6 @@ rpds-py==0.30.0 \ # via # jsonschema # referencing -rsa==4.9.1 \ - --hash=sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762 \ - --hash=sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75 - # via google-auth rtree==1.4.1 \ --hash=sha256:12de4578f1b3381a93a655846900be4e3d5f4cd5e306b8b00aa77c1121dc7e8c \ --hash=sha256:3d46f55729b28138e897ffef32f7ce93ac335cb67f9120125ad3742a220800f0 \ @@ -4884,25 +4915,25 @@ ruamel-yaml==0.17.17 \ --hash=sha256:9751de4cbb57d4bfbf8fc394e125ed4a2f170fbff3dc3d78abf50be85924f8be \ --hash=sha256:9af3ec5d7f8065582f3aa841305465025d0afd26c5fb54e15b964e11838fc74f # via great-expectations -ruff==0.15.1 \ - --hash=sha256:1d83466455fdefe60b8d9c8df81d3c1bbb2115cede53549d3b522ce2bc703899 \ - --hash=sha256:1fe5c41ab43e3a06778844c586251eb5a510f67125427625f9eb2b9526535779 \ - --hash=sha256:3dd86dccb83cd7d4dcfac303ffc277e6048600dfc22e38158afa208e8bf94a1f \ - --hash=sha256:4ab064052c31dddada35079901592dfba2e05f5b1e43af3954aafcbc1096a5b2 \ - --hash=sha256:518f9af03bfc33c03bdb4cb63fabc935341bb7f54af500f92ac309ecfbba6330 \ - --hash=sha256:5631c940fe9fe91f817a4c2ea4e81f47bee3ca4aa646134a24374f3c19ad9454 \ - --hash=sha256:5ff7d5f0f88567850f45081fac8f4ec212be8d0b963e385c3f7d0d2eb4899416 \ - --hash=sha256:660975d9cb49b5d5278b12b03bb9951d554543a90b74ed5d366b20e2c57c2098 \ - --hash=sha256:66a6dd6df4d80dc382c6484f8ce1bcceb55c32e9f27a8b94c32f6c7331bf14fb \ - --hash=sha256:68138a4ba184b4691ccdc39f7795c66b3c68160c586519e7e8444cf5a53e1b4c \ - --hash=sha256:6a4a42cbb8af0bda9bcd7606b064d7c0bc311a88d141d02f78920be6acb5aa83 \ - --hash=sha256:92c92b003e9d4f7fbd33b1867bb15a1b785b1735069108dfc23821ba045b29bc \ - --hash=sha256:939c995e9277e63ea632cc8d3fae17aa758526f49a9a850d2e7e758bfef46602 \ - --hash=sha256:a9457e3c3291024866222b96108ab2d8265b477e5b1534c7ddb1810904858d16 \ - --hash=sha256:b101ed7cf4615bda6ffe65bdb59f964e9f4a0d3f85cbf0e54f0ab76d7b90228a \ - --hash=sha256:c590fe13fb57c97141ae975c03a1aedb3d3156030cabd740d6ff0b0d601e203f \ - --hash=sha256:c820fef9dd5d4172a6570e5721704a96c6679b80cf7be41659ed439653f62336 \ - --hash=sha256:da79f4d6a826caaea95de0237a67e33b81e6ec2e25fc7e1993a4015dffca7c61 +ruff==0.15.9 \ + --hash=sha256:058d8e99e1bfe79d8a0def0b481c56059ee6716214f7e425d8e737e412d69677 \ + --hash=sha256:0694e601c028fd97dc5c6ee244675bc241aeefced7ef80cd9c6935a871078f53 \ + --hash=sha256:29cbb1255a9797903f6dde5ba0188c707907ff44a9006eb273b5a17bfa0739a2 \ + --hash=sha256:2b0c7c341f68adb01c488c3b7d4b49aa8ea97409eae6462d860a79cf55f431b6 \ + --hash=sha256:45a70921b80e1c10cf0b734ef09421f71b5aa11d27404edc89d7e8a69505e43d \ + --hash=sha256:4965bac6ac9ea86772f4e23587746f0b7a395eccabb823eb8bfacc3fa06069f7 \ + --hash=sha256:55cc15eee27dc0eebdfcb0d185a6153420efbedc15eb1d38fe5e685657b0f840 \ + --hash=sha256:6d3fcbca7388b066139c523bda744c822258ebdcfbba7d24410c3f454cc9af71 \ + --hash=sha256:6efbe303983441c51975c243e26dff328aca11f94b70992f35b093c2e71801e1 \ + --hash=sha256:7b34a9766aeec27a222373d0b055722900fbc0582b24f39661aa96f3fe6ad901 \ + --hash=sha256:89dd695bc72ae76ff484ae54b7e8b0f6b50f49046e198355e44ea656e521fef9 \ + --hash=sha256:8e1ddb11dbd61d5983fa2d7d6370ef3eb210951e443cace19594c01c72abab4c \ + --hash=sha256:9439a342adb8725f32f92732e2bafb6d5246bd7a5021101166b223d312e8fc59 \ + --hash=sha256:9c5e6faf9d97c8edc43877c3f406f47446fc48c40e1442d58cfcdaba2acea745 \ + --hash=sha256:a6537f6eed5cda688c81073d46ffdfb962a5f29ecb6f7e770b2dc920598997ed \ + --hash=sha256:bde6ff36eaf72b700f32b7196088970bf8fdb2b917b7accd8c371bfc0fd573ec \ + --hash=sha256:ce187224ef1de1bd225bc9a152ac7102a6171107f026e81f317e4257052916d5 \ + --hash=sha256:eaf05aad70ca5b5a0a4b0e080df3a6b699803916d88f006efd1f5b46302daab8 # via feast (pyproject.toml) s3transfer==0.13.1 \ --hash=sha256:a981aa7429be23fe6dfc13e80e4020057cbab622b08c0315288758d67cabc724 \ @@ -4993,7 +5024,9 @@ scikit-learn==1.7.2 \ --hash=sha256:e5bf3d930aee75a65478df91ac1225ff89cd28e9ac7bd1196853a9229b6adb0b \ --hash=sha256:f95dc55b7902b91331fa4e5845dd5bde0580c9cd9612b1b2791b7e80c3d32615 \ --hash=sha256:fa8f63940e29c82d1e67a45d5297bdebbcb585f5a5a50c4914cc2e852ab77f33 - # via feast (pyproject.toml) + # via + # feast (pyproject.toml) + # sentence-transformers scipy==1.15.3 \ --hash=sha256:05dc6abcd105e1a29f95eada46d4a3f251743cfd7d3ae8ddb4088047f24ea477 \ --hash=sha256:06efcba926324df1696931a57a176c80848ccd67ce6ad020c810736bfd58eb1c \ @@ -5047,14 +5080,19 @@ scipy==1.15.3 \ # great-expectations # scikit-image # scikit-learn -semchunk==2.2.2 \ - --hash=sha256:940e89896e64eeb01de97ba60f51c8c7b96c6a3951dfcf574f25ce2146752f52 \ - --hash=sha256:94ca19020c013c073abdfd06d79a7c13637b91738335f3b8cdb5655ee7cc94d2 + # sentence-transformers +semchunk==3.2.5 \ + --hash=sha256:ee15e9a06a69a411937dd8fcf0a25d7ef389c5195863140436872a02c95b0218 \ + --hash=sha256:fd09cc5f380bd010b8ca773bd81893f7eaf11d37dd8362a83d46cedaf5dae076 # via docling-core send2trash==2.1.0 \ --hash=sha256:0da2f112e6d6bb22de6aa6daa7e144831a4febf2a87261451c4ad849fe9a873c \ --hash=sha256:1c72b39f09457db3c05ce1d19158c2cbef4c32b8bedd02c155e49282b7ea7459 # via jupyter-server +sentence-transformers==5.3.0 \ + --hash=sha256:414a0a881f53a4df0e6cbace75f823bfcb6b94d674c42a384b498959b7c065e2 \ + --hash=sha256:dca6b98db790274a68185d27a65801b58b4caf653a4e556b5f62827509347c7d + # via feast (pyproject.toml) setuptools==80.10.2 \ --hash=sha256:8b0e9d10c784bf7d262c4e5ec5d4ec94127ce206e8738f29a437945fbc219b70 \ --hash=sha256:95b30ddfb717250edb492926c92b5221f7ef3fbcc2b07579bcd4a27da21d0173 @@ -5068,6 +5106,7 @@ setuptools==80.10.2 \ # pydata-google-auth # pymilvus # singlestoredb + # torch shapely==2.1.2 \ --hash=sha256:0036ac886e0923417932c2e6369b6c52e38e0ff5d9120b90eef5cd9a5fc5cae9 \ --hash=sha256:01d0d304b25634d60bd7cf291828119ab55a3bab87dc4af1e44b07fb225f188b \ @@ -5161,33 +5200,32 @@ snowballstemmer==3.0.1 \ --hash=sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064 \ --hash=sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895 # via sphinx -snowflake-connector-python[pandas]==4.0.0 \ - --hash=sha256:0c0204f639fddc58452b0362ba8821cd5153bd7aaa89434d59104bc39f4fa176 \ - --hash=sha256:1ca2503f705627f7e045da6254d97c37210a3b0a18b43d0f1b29616d0c7aaa01 \ - --hash=sha256:1fea301e3d1e8022b9f2ff87dc3be139d5ed7be5e85fab8a6c59d400a02e6d58 \ - --hash=sha256:2c3e0f6d103fe67c975550ed424f579d3e7ae503d56467e5549f3a1a1e0e8f24 \ - --hash=sha256:4106a66e770e564b3037457b7b01b15ca28aee61afb88560b664aa8af439b533 \ - --hash=sha256:4b10a865c4a5e1fa60c365c7fe41e0433605e6e5edc824e8730a9038f330b3a6 \ - --hash=sha256:4e8c3d2ea4055dd4aecc93514030341e300f557f2e86ca21eb47568c461a6f56 \ - --hash=sha256:54e648bbd506a0f2f8076f9eafe231b2d4284b1a884528c3a0690391ab2bb54e \ - --hash=sha256:5ad5d0f1ebcb2c6b7a7859ee3d4e02203087e40faae539a336bbcb45a3660777 \ - --hash=sha256:65e4e36dd1b0c7235d84cddef8a3c97c5ea0dc8fea85e31e45fc485000b77a83 \ - --hash=sha256:7789df78f7c7abfb351f2709258d05a94652cfe3c2c617fb15f15a11fc1b7b25 \ - --hash=sha256:79b4e7a58e600419f083a63f99e5da89d438faddae1d344e9f9b003754fa231b \ - --hash=sha256:835161dd46ef8f5fc9d2f135ca654c2f3fbdf57b035d3e1980506aa8eac671dc \ - --hash=sha256:985cd2f8b6b2e663ef30dc59f1ba8c1becff7683ebc51bd7f14b962407a9fa88 \ - --hash=sha256:a790f06808e4481c23cfed1396d2c9a786060ddd62408b1fda1a63e1e6bc4b07 \ - --hash=sha256:af89a9e1355ea4dac7927d2f9bc15b2c81e381ad8bcdf8954ba3dd457a4d51d6 \ - --hash=sha256:b95b29589293ad14d0367428518141995524cfc7dc47d8f3d0c47010f5d974da \ - --hash=sha256:bfd3b8523d7adc830f99c5c4c635689ceca61700a05368d5bbb34c6811f2ec54 \ - --hash=sha256:cd23bff2abc74e34c6123a181c004ead9e6cc8ef2661250892afd64bad24533c \ - --hash=sha256:e376bad497c7932448cc29058e75737f02b3f0e25569de9e4ff0616944b4ceba \ - --hash=sha256:e6132986d6965e4005b0167270612fbc7fa4bc4ef42726a40b85a8f57475a78d \ - --hash=sha256:e8d5b66f283967c700fff2303ac5e52d1a3cf41990a634f121ac8b1f1cd9af10 \ - --hash=sha256:eb1bb9729fd3bfaae22364491cec4816dda380376ac3be4559a6f6949c6d2833 \ - --hash=sha256:ebbdeec0d65c2e3f648c8b05839001c062984959417902717f7fc6eed983211d \ - --hash=sha256:f67d844241a6fed764a8f04d32c0273aedf9159d5162b764748526277c7f8831 \ - --hash=sha256:fd0d2d2c5cfd15f041e8522f5f8bdad0be4de7d805dd1646377fccd6bd404fa8 +snowflake-connector-python[pandas]==4.4.0 \ + --hash=sha256:16fdca775f7ca5ce4a973c07c434f5ab72bef5284e81a5e4ae2fb4d54d28965c \ + --hash=sha256:19d0c1ed033abae715a71b74c53010b180a5247c6924f851e4f7d0b0d58066c4 \ + --hash=sha256:2a6f6a514a10c3bb2d4554132f0b639f43d7e9fbb73fa1fae1c8a75333102686 \ + --hash=sha256:307f41326c702f6976746d2001dacf35adaf567f3f12afb3a5778fbb063c7241 \ + --hash=sha256:43e1a2f3ac51d24406d4eb0c23a8ceb9d6f5cb4854c941e5e1375d8c481e2844 \ + --hash=sha256:52efe2d6543a09807283748dd50a36ec01d52b4f342868132f8f9856b9c95a42 \ + --hash=sha256:56ff04dd9e17edc82128f412aa3776687dc94088f3d6b9144971e169952623cb \ + --hash=sha256:648f49029d699591af0f253e81c5bf60efc4411c7b0149ef074a59a038210a3b \ + --hash=sha256:693a1bef97509f09b7e6f42ea6f743d27819413c04fb3dc543b060d029871c56 \ + --hash=sha256:70d4051e2d9c87258b02672e17e21f5873e0cb49ff9705f6194ccfa25ac0d5fd \ + --hash=sha256:7c2984663a733d06c979aa6c8c1d7691621ec0d3521ef345d57c869ff2f1c4b2 \ + --hash=sha256:8304b4818d3e9de552dcfbdd0bca61bae1583e1c9794e242e58fe44bce701604 \ + --hash=sha256:85a01338d282423611f357cd5392dca2219bbda9a66b44761b11d6ae8ebf1e50 \ + --hash=sha256:96fdca994c4d9f7780e82fc7b4bd3398d856b43de3bae57d44e242ff435a2431 \ + --hash=sha256:9b1a28f843c1c0b582db7854789525d0c8aac4ea5c56e31113684e38220d0af9 \ + --hash=sha256:9fa43d330389df27024757c4f97dabddafbedc74b8bcc189b6a86e8b4d036014 \ + --hash=sha256:a088f108da4653ad1396ddb63a1c757ad614d0862c38f6f69cc77344bdcfeccb \ + --hash=sha256:b9f0ac0c00075321e1720d3876e936ee0256f54832e7463c5193a8dfa54913d5 \ + --hash=sha256:c828248214a49f77b903e05acf887d3ccb9d958b5a979f2ed3663bba1bd0f2b3 \ + --hash=sha256:d6fd334e4d8df7fcb30e6746e5ade845e82de2942268862aa8bce974ae2b86a2 \ + --hash=sha256:d8ac1659c8e588b9502f8d3d03c1ded2f274de0da9c09e62fe007cba5b46d6a5 \ + --hash=sha256:e8e7ce0e8b33aec8b1fc6741eb51dbeb54e2c3a6d282a0d459c355a85f089b08 \ + --hash=sha256:ea6e4083ebea0a814b46f029d64a2fb0ba6e7732952cd8af4406041708ce0e21 \ + --hash=sha256:f5d0e90e68a899c13fda5ca842ff77b5759b1674adf2c72702d3c2b53ca9d27b \ + --hash=sha256:fb628d5ea1999e23bfbaabce4125eb44d56605ca5634b8b1d6092ab22d555598 # via feast (pyproject.toml) sortedcontainers==2.4.0 \ --hash=sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88 \ @@ -5225,135 +5263,107 @@ sphinxcontrib-serializinghtml==2.0.0 \ --hash=sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331 \ --hash=sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d # via sphinx -sqlalchemy[mypy]==2.0.46 \ - --hash=sha256:09168817d6c19954d3b7655da6ba87fcb3a62bb575fb396a81a8b6a9fadfe8b5 \ - --hash=sha256:0cc3117db526cad3e61074100bd2867b533e2c7dc1569e95c14089735d6fb4fe \ - --hash=sha256:181903fe8c1b9082995325f1b2e84ac078b1189e2819380c2303a5f90e114a62 \ - --hash=sha256:1bc3f601f0a818d27bfe139f6766487d9c88502062a2cd3a7ee6c342e81d5047 \ - --hash=sha256:1e6199143d51e3e1168bedd98cc698397404a8f7508831b81b6a29b18b051069 \ - --hash=sha256:2347c3f0efc4de367ba00218e0ae5c4ba2306e47216ef80d6e31761ac97cb0b9 \ - --hash=sha256:261c4b1f101b4a411154f1da2b76497d73abbfc42740029205d4d01fa1052684 \ - --hash=sha256:33e462154edb9493f6c3ad2125931e273bbd0be8ae53f3ecd1c161ea9a1dd366 \ - --hash=sha256:37fee2164cf21417478b6a906adc1a91d69ae9aba8f9533e67ce882f4bb1de53 \ - --hash=sha256:3a9a72b0da8387f15d5810f1facca8f879de9b85af8c645138cba61ea147968c \ - --hash=sha256:3aac08f7546179889c62b53b18ebf1148b10244b3405569c93984b0388d016a7 \ - --hash=sha256:3c32e993bc57be6d177f7d5d31edb93f30726d798ad86ff9066d75d9bf2e0b6b \ - --hash=sha256:412f26bb4ba942d52016edc8d12fb15d91d3cd46b0047ba46e424213ad407bcb \ - --hash=sha256:42a1643dc5427b69aca967dae540a90b0fbf57eaf248f13a90ea5930e0966863 \ - --hash=sha256:4396c948d8217e83e2c202fbdcc0389cf8c93d2c1c5e60fa5c5a955eae0e64be \ - --hash=sha256:4dafb537740eef640c4d6a7c254611dca2df87eaf6d14d6a5fca9d1f4c3fc0fa \ - --hash=sha256:4f52f7291a92381e9b4de9050b0a65ce5d6a763333406861e33906b8aa4906bf \ - --hash=sha256:52fe29b3817bd191cc20bad564237c808967972c97fa683c04b28ec8979ae36f \ - --hash=sha256:56bdd261bfd0895452006d5316cbf35739c53b9bb71a170a331fa0ea560b2ada \ - --hash=sha256:585af6afe518732d9ccd3aea33af2edaae4a7aa881af5d8f6f4fe3a368699597 \ - --hash=sha256:590be24e20e2424a4c3c1b0835e9405fa3d0af5823a1a9fc02e5dff56471515f \ - --hash=sha256:64901e08c33462acc9ec3bad27fc7a5c2b6491665f2aa57564e57a4f5d7c52ad \ - --hash=sha256:6ac245604295b521de49b465bab845e3afe6916bcb2147e5929c8041b4ec0545 \ - --hash=sha256:6f827fd687fa1ba7f51699e1132129eac8db8003695513fcf13fc587e1bd47a5 \ - --hash=sha256:70ed2830b169a9960193f4d4322d22be5c0925357d82cbf485b3369893350908 \ - --hash=sha256:716be5bcabf327b6d5d265dbdc6213a01199be587224eb991ad0d37e83d728fd \ - --hash=sha256:7568fe771f974abadce52669ef3a03150ff03186d8eb82613bc8adc435a03f01 \ - --hash=sha256:77f8071d8fbcbb2dd11b7fd40dedd04e8ebe2eb80497916efedba844298065ef \ - --hash=sha256:82ec52100ec1e6ec671563bbd02d7c7c8d0b9e71a0723c72f22ecf52d1755330 \ - --hash=sha256:895296687ad06dc9b11a024cf68e8d9d3943aa0b4964278d2553b86f1b267735 \ - --hash=sha256:8d3b44b3d0ab2f1319d71d9863d76eeb46766f8cf9e921ac293511804d39813f \ - --hash=sha256:8d679b5f318423eacb61f933a9a0f75535bfca7056daeadbf6bd5bcee6183aee \ - --hash=sha256:8e84b09a9b0f19accedcbeff5c2caf36e0dd537341a33aad8d680336152dc34e \ - --hash=sha256:9094c8b3197db12aa6f05c51c05daaad0a92b8c9af5388569847b03b1007fb1b \ - --hash=sha256:90bde6c6b1827565a95fde597da001212ab436f1b2e0c2dcc7246e14db26e2a3 \ - --hash=sha256:9397b381dcee8a2d6b99447ae85ea2530dcac82ca494d1db877087a13e38926d \ - --hash=sha256:93a12da97cca70cea10d4b4fc602589c4511f96c1f8f6c11817620c021d21d00 \ - --hash=sha256:93bb0aae40b52c57fd74ef9c6933c08c040ba98daf23ad33c3f9893494b8d3ce \ - --hash=sha256:94b1e5f3a5f1ff4f42d5daab047428cd45a3380e51e191360a35cef71c9a7a2a \ - --hash=sha256:965c62be8256d10c11f8907e7a8d3e18127a4c527a5919d85fa87fd9ecc2cfdc \ - --hash=sha256:96c7cca1a4babaaf3bfff3e4e606e38578856917e52f0384635a95b226c87764 \ - --hash=sha256:9bcdce05f056622a632f1d44bb47dbdb677f58cad393612280406ce37530eb6d \ - --hash=sha256:9d80ea2ac519c364a7286e8d765d6cd08648f5b21ca855a8017d9871f075542d \ - --hash=sha256:a1e8cc6cc01da346dc92d9509a63033b9b1bda4fed7a7a7807ed385c7dccdc10 \ - --hash=sha256:ab65cb2885a9f80f979b85aa4e9c9165a31381ca322cbde7c638fe6eefd1ec39 \ - --hash=sha256:af865c18752d416798dae13f83f38927c52f085c52e2f32b8ab0fef46fdd02c2 \ - --hash=sha256:b1e14b2f6965a685c7128bd315e27387205429c2e339eeec55cb75ca4ab0ea2e \ - --hash=sha256:b2a9f9aee38039cf4755891a1e50e1effcc42ea6ba053743f452c372c3152b1b \ - --hash=sha256:be6c0466b4c25b44c5d82b0426b5501de3c424d7a3220e86cd32f319ba56798e \ - --hash=sha256:c4e2cc868b7b5208aec6c960950b7bb821f82c2fe66446c92ee0a571765e91a5 \ - --hash=sha256:c805fa6e5d461329fa02f53f88c914d189ea771b6821083937e79550bf31fc19 \ - --hash=sha256:cf36851ee7219c170bb0793dbc3da3e80c582e04a5437bc601bfe8c85c9216d7 \ - --hash=sha256:db23b1bf8cfe1f7fda19018e7207b20cdb5168f83c437ff7e95d19e39289c447 \ - --hash=sha256:e0c05aff5c6b1bb5fb46a87e0f9d2f733f83ef6cbbbcd5c642b6c01678268061 \ - --hash=sha256:e8ac45e8f4eaac0f9f8043ea0e224158855c6a4329fd4ee37c45c61e3beb518e \ - --hash=sha256:ea3cd46b6713a10216323cda3333514944e510aa691c945334713fca6b5279ff \ - --hash=sha256:ebf7e1e78af38047e08836d33502c7a278915698b7c2145d045f780201679999 \ - --hash=sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e \ - --hash=sha256:ff33c6e6ad006bbc0f34f5faf941cfc62c45841c64c0a058ac38c799f15b5ede +sqlalchemy[mypy]==2.0.48 \ + --hash=sha256:01f6bbd4308b23240cf7d3ef117557c8fd097ec9549d5d8a52977544e35b40ad \ + --hash=sha256:07edba08061bc277bfdc772dd2a1a43978f5a45994dd3ede26391b405c15221e \ + --hash=sha256:10853a53a4a00417a00913d270dddda75815fcb80675874285f41051c094d7dd \ + --hash=sha256:1182437cb2d97988cfea04cf6cdc0b0bb9c74f4d56ec3d08b81e23d621a28cc6 \ + --hash=sha256:144921da96c08feb9e2b052c5c5c1d0d151a292c6135623c6b2c041f2a45f9e0 \ + --hash=sha256:1a89ce07ad2d4b8cfc30bd5889ec40613e028ed80ef47da7d9dd2ce969ad30e0 \ + --hash=sha256:1b4c575df7368b3b13e0cebf01d4679f9a28ed2ae6c1cd0b1d5beffb6b2007dc \ + --hash=sha256:1ccd42229aaac2df431562117ac7e667d702e8e44afdb6cf0e50fa3f18160f0b \ + --hash=sha256:2645b7d8a738763b664a12a1542c89c940daa55196e8d73e55b169cc5c99f65f \ + --hash=sha256:288937433bd44e3990e7da2402fabc44a3c6c25d3704da066b85b89a85474ae0 \ + --hash=sha256:34634e196f620c7a61d18d5cf7dc841ca6daa7961aed75d532b7e58b309ac894 \ + --hash=sha256:348174f228b99f33ca1f773e85510e08927620caa59ffe7803b37170df30332b \ + --hash=sha256:36ac4ddc3d33e852da9cb00ffb08cea62ca05c39711dc67062ca2bb1fae35fd8 \ + --hash=sha256:3713e21ea67bca727eecd4a24bf68bcd414c403faae4989442be60994301ded0 \ + --hash=sha256:389b984139278f97757ea9b08993e7b9d1142912e046ab7d82b3fbaeb0209131 \ + --hash=sha256:426c5ca86415d9b8945c7073597e10de9644802e2ff502b8e1f11a7a2642856b \ + --hash=sha256:4599a95f9430ae0de82b52ff0d27304fe898c17cb5f4099f7438a51b9998ac77 \ + --hash=sha256:49b7bddc1eebf011ea5ab722fdbe67a401caa34a350d278cc7733c0e88fecb1f \ + --hash=sha256:53667b5f668991e279d21f94ccfa6e45b4e3f4500e7591ae59a8012d0f010dcb \ + --hash=sha256:546572a1793cc35857a2ffa1fe0e58571af1779bcc1ffa7c9fb0839885ed69a9 \ + --hash=sha256:583849c743e0e3c9bb7446f5b5addeacedc168d657a69b418063dfdb2d90081c \ + --hash=sha256:5aee45fd2c6c0f2b9cdddf48c48535e7471e42d6fb81adfde801da0bd5b93241 \ + --hash=sha256:5b193a7e29fd9fa56e502920dca47dffe60f97c863494946bd698c6058a55658 \ + --hash=sha256:5ca74f37f3369b45e1f6b7b06afb182af1fd5dde009e4ffd831830d98cbe5fe7 \ + --hash=sha256:68549c403f79a8e25984376480959975212a670405e3913830614432b5daa07a \ + --hash=sha256:69f5bc24904d3bc3640961cddd2523e361257ef68585d6e364166dfbe8c78fae \ + --hash=sha256:6bb85c546591569558571aa1b06aba711b26ae62f111e15e56136d69920e1616 \ + --hash=sha256:6f7b7243850edd0b8b97043f04748f31de50cf426e939def5c16bedb540698f7 \ + --hash=sha256:7001dc9d5f6bb4deb756d5928eaefe1930f6f4179da3924cbd95ee0e9f4dce89 \ + --hash=sha256:7a936f1bb23d370b7c8cc079d5fce4c7d18da87a33c6744e51a93b0f9e97e9b3 \ + --hash=sha256:7c998f2ace8bf76b453b75dbcca500d4f4b9dd3908c13e89b86289b37784848b \ + --hash=sha256:7cddca31edf8b0653090cbb54562ca027c421c58ddde2c0685f49ff56a1690e0 \ + --hash=sha256:8183dc57ae7d9edc1346e007e840a9f3d6aa7b7f165203a99e16f447150140d2 \ + --hash=sha256:82745b03b4043e04600a6b665cb98697c4339b24e34d74b0a2ac0a2488b6f94d \ + --hash=sha256:841a94c66577661c1f088ac958cd767d7c9bf507698f45afffe7a4017049de76 \ + --hash=sha256:858e433f12b0e5b3ed2f8da917433b634f4937d0e8793e5cb33c54a1a01df565 \ + --hash=sha256:908a3fa6908716f803b86896a09a2c4dde5f5ce2bb07aacc71ffebb57986ce99 \ + --hash=sha256:9764014ef5e58aab76220c5664abb5d47d5bc858d9debf821e55cfdd0f128485 \ + --hash=sha256:9c7d0a77e36b5f4b01ca398482230ab792061d243d715299b44a0b55c89fe617 \ + --hash=sha256:a5b429eb84339f9f05e06083f119ad814e6d85e27ecbdf9c551dfdbb128eaf8a \ + --hash=sha256:a66fe406437dd65cacd96a72689a3aaaecaebbcd62d81c5ac1c0fdbeac835096 \ + --hash=sha256:a6b764fb312bd35e47797ad2e63f0d323792837a6ac785a4ca967019357d2bc7 \ + --hash=sha256:b19151e76620a412c2ac1c6f977ab1b9fa7ad43140178345136456d5265b32ed \ + --hash=sha256:b8438ec5594980d405251451c5b7ea9aa58dda38eb7ac35fb7e4c696712ee24f \ + --hash=sha256:b8fc3454b4f3bd0a368001d0e968852dad45a873f8b4babd41bc302ec851a099 \ + --hash=sha256:bcb8ebbf2e2c36cfe01a94f2438012c6a9d494cf80f129d9753bcdf33bfc35a6 \ + --hash=sha256:d404dc897ce10e565d647795861762aa2d06ca3f4a728c5e9a835096c7059018 \ + --hash=sha256:d612c976cbc2d17edfcc4c006874b764e85e990c29ce9bd411f926bbfb02b9a2 \ + --hash=sha256:d64177f443594c8697369c10e4bbcac70ef558e0f7921a1de7e4a3d1734bcf67 \ + --hash=sha256:d854b3970067297f3a7fbd7a4683587134aa9b3877ee15aa29eea478dc68f933 \ + --hash=sha256:d8fcccbbc0c13c13702c471da398b8cd72ba740dca5859f148ae8e0e8e0d3e7e \ + --hash=sha256:e004aa9248e8cb0a5f9b96d003ca7c1c0a5da8decd1066e7b53f59eb8ce7c62b \ + --hash=sha256:e214d546c8ecb5fc22d6e6011746082abf13a9cf46eefb45769c7b31407c97b5 \ + --hash=sha256:e2d0d88686e3d35a76f3e15a34e8c12d73fc94c1dea1cd55782e695cc14086dd \ + --hash=sha256:e2f35b4cccd9ed286ad62e0a3c3ac21e06c02abc60e20aa51a3e305a30f5fa79 \ + --hash=sha256:e3070c03701037aa418b55d36532ecb8f8446ed0135acb71c678dbdf12f5b6e4 \ + --hash=sha256:e5e088bf43f6ee6fec7dbf1ef7ff7774a616c236b5c0cb3e00662dd71a56b571 \ + --hash=sha256:e83e3f959aaa1c9df95c22c528096d94848a1bc819f5d0ebf7ee3df0ca63db6c \ + --hash=sha256:f0dcbc588cd5b725162c076eb9119342f6579c7f7f55057bb7e3c6ff27e13121 \ + --hash=sha256:f27f9da0a7d22b9f981108fd4b62f8b5743423388915a563e651c20d06c1f457 \ + --hash=sha256:f8649a14caa5f8a243628b1d61cf530ad9ae4578814ba726816adb1121fc493e \ + --hash=sha256:fac0fa4e4f55f118fd87177dacb1c6522fe39c28d498d259014020fec9164c29 \ + --hash=sha256:fd08b90d211c086181caed76931ecfa2bdfc83eea3cfccdb0f82abc6c4b876cb # via feast (pyproject.toml) -sqlglot[rs]==28.10.1 \ - --hash=sha256:214aef51fd4ce16407022f81cfc80c173409dab6d0f6ae18c52b43f43b31d4dd \ - --hash=sha256:66e0dae43b4bce23314b80e9aef41b8c88fea0e17ada62de095b45262084a8c5 +sqlglot[rs]==30.2.1 \ + --hash=sha256:ef4a67cc6f66a8043085eb8ea95fa9541c1625dffa9145ad4e9815a7ba60a199 \ + --hash=sha256:f23d9ee9427ef9d20df15f9b0ffa57d9eb45e52b012219a349d1e6b50ed926d1 # via # feast (pyproject.toml) # ibis-framework -sqlglotrs==0.12.0 \ - --hash=sha256:011e9c1c1465de06198cc6b3220e64c833a0ebe3565db8bea1ddda70a6515e8d \ - --hash=sha256:033160f03e6a6aa14e8a07a680eb0706e3ed1ad997ba9fb89c7fc8149e83899c \ - --hash=sha256:0c27d654a7dc0d0a06e3fb94798542e3e748a3f2fc41444565d18ba95021b806 \ - --hash=sha256:10a67825f654a599cbac58c8d129b0c7f49acf4e3ca05e471df301ca00b819e7 \ - --hash=sha256:16d581b25d0731aa25681640450f5d305a0aa04c3257a8e0d3a7ecd15e6e1c7f \ - --hash=sha256:1a5147585d909d5640aa2589a470986a7c9cfb3c90e92970942b9ccc512bacad \ - --hash=sha256:1ca61b15c2fd37d21770a02cf7b48e406e887ae597d158f67e8d868ddc79f4d6 \ - --hash=sha256:21d4c25cee14f758f8ca095fc9e61aa239cd93c438eaffc36462d85e94e7d395 \ - --hash=sha256:28d1ecc8afc6323a537d74df8c5f4545641742cf9b965813de1fb72ddc1bfe5c \ - --hash=sha256:2a097e56cbaed9b97901c2a149381e547627aaeb1dc388a0b691543558dad1ab \ - --hash=sha256:2a58221be2d771b6d65a7b3721a0c3020eeff17cd825905a35a47558acad8257 \ - --hash=sha256:2faa9dc5d11b19122189a8635a269efaee6f7bb609ae653d43f7b71be2ff54d0 \ - --hash=sha256:466451fed87ca90a4a2ec1b3e026ac9d4f8a57e4ed9c51583290ef11fc4c1631 \ - --hash=sha256:47b56e8bd5ed85055ae0409c53cdf4d8dbc5f7c3170f238b472173fcb16ddfe0 \ - --hash=sha256:4e5f477522a76fee1d1907b0196510f002f4c339a286de9cd63f8d51265b0f68 \ - --hash=sha256:4f0dac396c68ea9612cc89bb170c0366a7d686d012142a4365ed222401d6b645 \ - --hash=sha256:5312f17e3e2b5c18fac8269d8d5a2c26a0aed79a22854787153d7ff5bff7be66 \ - --hash=sha256:533cbefb35128de669efa7e1e86fec61383121ebd5514e0a1e70aa33bf875987 \ - --hash=sha256:5443e10a41894719778d40fb854192efd569eb99b26ef37e87a4730cc2ee899b \ - --hash=sha256:558720d901a0be3ee69660c0b72fe3dfdf23f557d7911d13f4d3555fdd44ae75 \ - --hash=sha256:6156f621c1c4ea4a46efbaf977f4df52a29f2f414bfb62de8ea878f50d4fd506 \ - --hash=sha256:61751c7f2ca0a1f83e2df041295fe71a88ce0b025bb4e578164657822bead0e1 \ - --hash=sha256:6364c8bfc8c5678e13562bf705a111124afbfaaa1762ce00384dc514e31c6a4a \ - --hash=sha256:656b03b7eae2fd03f0a89770e08a6b815f462d5eef8abf6942442c769bda8ca2 \ - --hash=sha256:672cdcbed0dfa45fa6f3922c8c9d893092dd47e0600f25b8076559e3aeeb1921 \ - --hash=sha256:69470afeaef3a48e1bb87f25c83d2061bc4bd870665e6a2c2e0c0c2b82ab0480 \ - --hash=sha256:6be5fac1f7a01c1b3e40c2478a3db5a125201d39e4601f6075660804a7b40e18 \ - --hash=sha256:6e0be4ceffe2aec98e308df9e872084c47c8f178fa0269d4bf1f1b99eb1c877b \ - --hash=sha256:72b9829ab9dfce9997740d6949a981f619f813d664524314386fa80b72ede7b1 \ - --hash=sha256:7a9f6ffb06b3d617556819f9e14703a0f5a65b8d87613969141be08cdd06b620 \ - --hash=sha256:7fcbc0004986510f4c5c625d053ee8febf836116db1dab3bd407292a69dee375 \ - --hash=sha256:850c408ae94f85f9d8c35a4511d1f67c560c077467c41a6ea66f5046b4b731f9 \ - --hash=sha256:8641bfbcc9b92167aff99d589e0fd2f4d902759e415b13e59352314bf5348770 \ - --hash=sha256:900f9023f8eca065e81665507722a4563e76bab19cc1322837d9248186e1ea90 \ - --hash=sha256:90bee58c15c9144f571e79e4e57b645452d0142cfee35cf2e11ec6124c4e5f07 \ - --hash=sha256:94b02d14c044d3eb22b4c494813f587f47e65d0343a4dc341c9b542a01cfca16 \ - --hash=sha256:a0b78f58b5ea14fef29d03636666e3a749b2aed88a3603df1dadc16215fb5b78 \ - --hash=sha256:a27d106b870d2a28f6caf100af8976054fdea649e6da733c31bcf7730ad928dd \ - --hash=sha256:a6c419d8ae6c234d151a71f1becabc13d0c44d67a76376d8d934aaf350f08858 \ - --hash=sha256:a880b4d4133591e90d40bdd802404e960e396dd24c2eda6a2a04cbba6effc4d5 \ - --hash=sha256:ae6d7e877bf6890fdb35ed00819783e1a1ddce8c8ed7009dc1604323bf24d0ed \ - --hash=sha256:b0e0193d3e13d37ede7969f3b52d3feaeb56d7e3ba78bafb1d75a2c789bf0373 \ - --hash=sha256:ba15622063c60b17bdce8575d53b1c81ad5d31fc77d00e20378c0051d6ffa4cf \ - --hash=sha256:bb7d8e05fe19b5bd157c20289a66a9b218c9eb3314ae78ec6bae2e9525900b30 \ - --hash=sha256:bd6c108d6b64950060570aba6181fa03366e2e458793706cef379d86ebde5670 \ - --hash=sha256:bdc5bb2c4ba35fa76baeb6eb31ee7c5bb349af1bc7c4b51ce5804e1370442e30 \ - --hash=sha256:c08e633850082cc1353fe2c24ec3c6bd229f8b5925662a8d5526cc94073349b4 \ - --hash=sha256:c26f1ff7eca636a55eb79bc2b622422561b9801201a4c2a62512902d818671e8 \ - --hash=sha256:c37796704edaa1ad73ba9e43f308f8e93d2392ade33fa8a51e1d55d8b6136b0f \ - --hash=sha256:c876cd551d3d724daac533b833e11d359f95037b5757487492caf8e600326848 \ - --hash=sha256:ce31216150be347a045ef35358c6c640a87c389482745cef5d481242cbac8f8e \ - --hash=sha256:d08c63e1bebe4963a5efe56e4ed278a441c2e552f9d1d6a768721b52b29cbb4a \ - --hash=sha256:d0bf559389c38aecdaefba14a7e4d59570ef491dbfaa41b8493614c97c1268c5 \ - --hash=sha256:e0f8c959e44f330e9b7000bc9a6926e18bf9d44b6cba2dd81807a6a2d552c597 \ - --hash=sha256:e55cb36ec074fd0abafd6698d2f7cd1d91e01c102384bdc945b977a86d2199a6 \ - --hash=sha256:f36716d090f373eda020b5e130a48da0139f3eede7f5e5b684c58263b83bd7d1 \ - --hash=sha256:f3c937c9ae8fb4ec3bc3bc0bea215dec290dfa0ce033048d25c87f7b632a3d3a \ - --hash=sha256:f4fc40bae51f36818acd8f98a4246eebd8c283081906dc22db353ab1e141f529 \ - --hash=sha256:f7426f61a2596a6f681dde5d8e4d0386aa2bdddee3af8902c6c3266d6249480e \ - --hash=sha256:fa2c04c40af5b209631feea812103a079f8a016e1ddb60eb74e9460d72050bfe \ - --hash=sha256:fb402884d234c0a500c42bb2a5f500604891ef83e58c984ec2b4af8fa76bd72d +sqlglotc==30.2.1 \ + --hash=sha256:052cd7bb41fc9b841eb268d4dd601eb6b5954b7c6d5656795d4350a0f8020d53 \ + --hash=sha256:058f0e9aed2b8dff87dc893b8793e514204c8dfef699b7d3d1704dfbdd949f2b \ + --hash=sha256:0e6be524252894c0fa98d25d4e60dfae6485ba66ca1abd40bf05f16a9cf26baf \ + --hash=sha256:13f8f68808777ba7d845bc908bf09f72a0c9899a19811483dc52f0fa48b38d5a \ + --hash=sha256:1a004086ab871be0cc97766f7b6fb8866729f09dd7272254fd31c05107f3fdc8 \ + --hash=sha256:25c6f62f31cd3a051285635c3f6a01d2f3c73ca2baaa26970815166928042ace \ + --hash=sha256:2b5fe8adc1a1e2fb819e014e94974a274f30dbf9684ceed9f171fb0889f80f0b \ + --hash=sha256:2ffe527bc8664b03cc936bae7ebf965f482beb4acee7a815c2ec2d9aea720b4e \ + --hash=sha256:4aa90e08f53409b1857572836e57a31835ed20e32521c6fafdc6af96199baff7 \ + --hash=sha256:507935a971e0a9e5d4ac7ca14df479f8e270502b44904f71d95c0aaed066006f \ + --hash=sha256:515e092ab8fb522b256fa8a34f471e9b187bb8a50a7c0226a65b036a07d6d188 \ + --hash=sha256:585bb610fde3e3dd1d7e5ff3cce14f70fbd53ced6769cd104679adf8b5c4ab5b \ + --hash=sha256:850e7517dd4739cad9af65bcb9699825f9202e5971407bf955e3248fe4814f96 \ + --hash=sha256:8f063af733cbcc51686380470e7f3f80b589b8c58084baa138efb3b8ca821597 \ + --hash=sha256:b17e3002ed10747388367621b2ecf39c06d5fdc6b3c31a8c32be2f5ef546fc0b \ + --hash=sha256:d577e1635e127febb7012bc42fa1c3b958076e59a1a116ade20048c572a1be42 \ + --hash=sha256:dc292cd73e0c447253877c27f00454a2d09b71324a130ad4c58c145ab753889e \ + --hash=sha256:de168df756a21a028cf1f917f92da2f77bb135f3b6cdd960914460942a5eca10 \ + --hash=sha256:de884dd224220002c3e940ca5bdceb27ef9638e5f02493db133ffb8ae88b5610 \ + --hash=sha256:f33c7d1646ff6531cb9b07f0740b2939f3ecaa31efebfbec8adb6b275f1a45f2 \ + --hash=sha256:f9a1fc7b1ff3b51d0d03a391768a79964f68541b4c2f294a25a6f14e6670ffab \ + --hash=sha256:fae4edad0b7c5f9f963bd63452f722f0d7f77a436c2d334b555b31722f9573ad \ + --hash=sha256:fdc19623a1c7659918c3cee18ea8849fc4af9eaeb87247acf37e0393295d32b7 \ + --hash=sha256:feefc0ab7606d1fe284d23bef09ea4829ce4fad679936959c29324310f23e081 \ + --hash=sha256:ff19b7ecb931aef6c7c6168af5530c07e67915102b701d45ae80446f0695ba54 + # via sqlglot +sqlglotrs==0.13.0 \ + --hash=sha256:6b934a244b16f26fca50974328a2ebc7689583c59f06203cebb46e2e6e8d93a7 \ + --hash=sha256:ad1ad158234af0f8ba5054ca51bd17a7c1e3f81b4798c7970ebf7953fe08ddcb # via sqlglot sqlite-vec==0.1.6 \ --hash=sha256:77491bcaa6d496f2acb5cc0d0ff0b8964434f141523c121e313f9a7d8088dee3 \ @@ -5366,17 +5376,17 @@ sqlparams==6.2.0 \ --hash=sha256:3744a2ad16f71293db6505b21fd5229b4757489a9b09f3553656a1ae97ba7ca5 \ --hash=sha256:63b32ed9051bdc52e7e8b38bc4f78aed51796cdd9135e730f4c6a7db1048dedf # via singlestoredb -sse-starlette==3.2.0 \ - --hash=sha256:5876954bd51920fc2cd51baee47a080eb88a37b5b784e615abb0b283f801cdbf \ - --hash=sha256:8127594edfb51abe44eac9c49e59b0b01f1039d0c7461c6fd91d4e03b70da422 +sse-starlette==3.3.4 \ + --hash=sha256:84bb06e58939a8b38d8341f1bc9792f06c2b53f48c608dd207582b664fc8f3c1 \ + --hash=sha256:aaf92fc067af8a5427192895ac028e947b484ac01edbc3caf00e7e7137c7bef1 # via mcp stack-data==0.6.3 \ --hash=sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9 \ --hash=sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695 # via ipython -starlette==0.52.1 \ - --hash=sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74 \ - --hash=sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933 +starlette==1.0.0 \ + --hash=sha256:6a4beaf1f81bb472fd19ea9b918b50dc3a77a6f2e190a12954b25e6ed5eea149 \ + --hash=sha256:d3ec55e0bb321692d275455ddfd3df75fff145d009685eb40dc91fc66b03d38b # via # fastapi # mcp @@ -5385,9 +5395,9 @@ sympy==1.14.0 \ --hash=sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517 \ --hash=sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5 # via torch -tabulate==0.9.0 \ - --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ - --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f +tabulate==0.10.0 \ + --hash=sha256:e2cfde8f79420f6deeffdeda9aaec3b6bc5abce947655d17ac662b126e48a60d \ + --hash=sha256:f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3 # via # feast (pyproject.toml) # docling-core @@ -5419,14 +5429,18 @@ thriftpy2==0.6.0 \ --hash=sha256:1245c36b82f34aa26f049e6529f40ad34d9be8d12bd0131559847c8476b98ce0 \ --hash=sha256:151d299e8e3694a6cc0f2f2cda01d5744080742649de958c5cdcbebb4306205f \ --hash=sha256:16eecfd34bd541b75172ba0d69ea90b874611a7361d18906fb6d95955089cc30 \ + --hash=sha256:182f54a7248c8ecf1320cf26d1fc9115765df6b1f2589c1d2d0df7049a5b27d4 \ --hash=sha256:210345281d41b3a76d263b555d3e3cc482103738441bdb92a73033a4e9a042e1 \ --hash=sha256:265588b8cdb3fe1097db43bf35fb208edc69d9350a2bec3a737d6357d0a5650d \ --hash=sha256:28fd55960a6d42207060536109928a4615fbbd6874c0ddd8a705b47075f1d2d0 \ --hash=sha256:29ff125e40c8016b4d3bf48e6d727bd93d2892451b47bfe57ba896944ecbdb0c \ --hash=sha256:2ae866adf9b112c7ab30c1a90d878a5d6f2d40244fbc46ec8477425d802f4ac5 \ --hash=sha256:2bf891c2d441b1edddfc62f16ab3031ac7506cba5b77680654179dbe93d8b7ec \ + --hash=sha256:2c88b0d356ea18ce026a52aa7c2110693db77fd52d5ac7553616635a7f165bbd \ --hash=sha256:3090d9cabc2c31c92ae943f36d539a20adfd82697f50e996ce94f0b279e9e1e4 \ + --hash=sha256:3359a7c4eb4c281bf54bd760dcc03c43299f0d529dd2a5018be2f1fbebf0cbbd \ --hash=sha256:375cca06f36f54339838c7f8251b64a777d5ff1277f8b91999487fad1a8e2d73 \ + --hash=sha256:386d8c4a5677fd94fd16c1af2adf39f59698af1e4ef0c3c026083f278540e352 \ --hash=sha256:44365bb5098d0a91c44382e7df0ad44d5b9a588d29d9071aca4a2867f704aaf1 \ --hash=sha256:443e502b428d325c57aec0947991857e8dc0589d0464181f35bd48f870cd5d18 \ --hash=sha256:4550cbb6629c9f6186ab22cb497f262408e1a90ae10b8653599f2717f518f0df \ @@ -5443,6 +5457,7 @@ thriftpy2==0.6.0 \ --hash=sha256:851981ded8bb42da66213cf95d1dd5eaf06c5d6b3a95725a18eddd58ec992b6b \ --hash=sha256:852e538b4866ed776126349161d9fdc37387b1e15ab46805f98dcdee25fee4b5 \ --hash=sha256:8b19d19661fc9a71f19b7c432c413ab65025e5dd11fbd192bd9169afb13b9ce0 \ + --hash=sha256:8e62d9c36bcfe6b85bec7b754accb97e2fa7b6a7c9a0c37f824d85eba699e7b8 \ --hash=sha256:8eb0566b4501c27ea51f2e593531122703946969564fe526a5ff1b18be0ad49a \ --hash=sha256:8f393607d54091e8976e297f8fd7399606d12cd8c2b8852353f07ad5ddac4224 \ --hash=sha256:91df1fa70a99ac08dc449d6fda24a14992a1836d571928f217c40c66fd63fcc8 \ @@ -5457,14 +5472,17 @@ thriftpy2==0.6.0 \ --hash=sha256:b361152c24fd5c791220de9966b00696578c9884a2bb67e4759d4dfe05fd7049 \ --hash=sha256:b51b5259dc344482ab21b768dfc7f54d51d9133665e72890831725068f69f24a \ --hash=sha256:b57f367d7b0e1bc9e5c9b0ff34febdb3fe440f1fe8d75903ae71301bc06072c0 \ + --hash=sha256:b8dc65d2e7951b7e81c17b92857db7c19d6b3dd442d2d8600b5bd5040aa43ce6 \ --hash=sha256:bc320e960347e5f9d27e8b4a9fc7044b2b26bfe4522bb4957e741fc1d1ebd2f0 \ --hash=sha256:bdf77ba7a8987a239eb57cf840d62669741f8b92b61a617e63898caed31da898 \ --hash=sha256:bf96b64400da2f411b43c4c81c2e20b09e3300d86766a52f42393696c8962f11 \ --hash=sha256:c37f5dbfe95579549485c33167854784358f559feda703ccc058719ca0efd8aa \ --hash=sha256:c41312c6edad5e875613719236f1ca6bba9310df40b1adc9308248e1bdb7a1ea \ + --hash=sha256:cafa1d43bcc69129a4855fd3973ab7983bb2274c407e5ff572af5dc196e00313 \ --hash=sha256:cb98556e919be3e6ba9bca629dbddccfaa33b95a0fe7503052849b124e4f88cd \ --hash=sha256:cd2e2c4dcc30c373e317d39b044afa6d9a090bec11d186f25841f70bc520bbb5 \ --hash=sha256:e6c4fb1e7f51f8858f348ed9c31bb408b61274942d18b549ec163bb480c987a0 \ + --hash=sha256:eccab0281667caab0c055882b3bbb8e346bb0181e55f37477e3e5e3f5b7a96dd \ --hash=sha256:f59f74c3779aa47223ba0a9e23ef10d2af5a873ed3624c78303f62a679d1b63e \ --hash=sha256:f6b86112cca7bd04151ce248d781763ea5f74cc18d148476c6d16cee32db81ac \ --hash=sha256:f837ab85ae93b118766b8b28a1cec47a1daddee303e1f986a595c56379062a5c @@ -5473,9 +5491,9 @@ tifffile==2025.5.10 \ --hash=sha256:018335d34283aa3fd8c263bae5c3c2b661ebc45548fde31504016fcae7bf1103 \ --hash=sha256:e37147123c0542d67bc37ba5cdd67e12ea6fbe6e86c52bee037a9eb6a064e5ad # via scikit-image -timm==1.0.24 \ - --hash=sha256:8301ac783410c6ad72c73c49326af6d71a9e4d1558238552796e825c2464913f \ - --hash=sha256:c7b909f43fe2ef8fe62c505e270cd4f1af230dfbc37f2ee93e3608492b9d9a40 +timm==1.0.26 \ + --hash=sha256:985c330de5ccc3a2aa0224eb7272e6a336084702390bb7e3801f3c91603d3683 \ + --hash=sha256:f66f082f2f381cf68431c22714c8b70f723837fa2a185b155961eab90f2d5b10 # via feast (pyproject.toml) tinycss2==1.4.0 \ --hash=sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7 \ @@ -5511,54 +5529,54 @@ toml==0.10.2 \ --hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \ --hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f # via feast (pyproject.toml) -tomli==2.4.0 \ - --hash=sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729 \ - --hash=sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b \ - --hash=sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d \ - --hash=sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df \ - --hash=sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576 \ - --hash=sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d \ - --hash=sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1 \ - --hash=sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a \ - --hash=sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e \ - --hash=sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc \ - --hash=sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702 \ - --hash=sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6 \ - --hash=sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd \ - --hash=sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4 \ - --hash=sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776 \ - --hash=sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a \ - --hash=sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66 \ - --hash=sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87 \ - --hash=sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2 \ - --hash=sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f \ - --hash=sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475 \ - --hash=sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f \ - --hash=sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95 \ - --hash=sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9 \ - --hash=sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3 \ - --hash=sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9 \ - --hash=sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76 \ - --hash=sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da \ - --hash=sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8 \ - --hash=sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51 \ - --hash=sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86 \ - --hash=sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8 \ - --hash=sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0 \ - --hash=sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b \ - --hash=sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1 \ - --hash=sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e \ - --hash=sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d \ - --hash=sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c \ - --hash=sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867 \ - --hash=sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a \ - --hash=sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c \ - --hash=sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0 \ - --hash=sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4 \ - --hash=sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614 \ - --hash=sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132 \ - --hash=sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa \ - --hash=sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087 +tomli==2.4.1 \ + --hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \ + --hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \ + --hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \ + --hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \ + --hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \ + --hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \ + --hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \ + --hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \ + --hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \ + --hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \ + --hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \ + --hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \ + --hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \ + --hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \ + --hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \ + --hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \ + --hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \ + --hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \ + --hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \ + --hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \ + --hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \ + --hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \ + --hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \ + --hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \ + --hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \ + --hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \ + --hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \ + --hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \ + --hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \ + --hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \ + --hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \ + --hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \ + --hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \ + --hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \ + --hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \ + --hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \ + --hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \ + --hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \ + --hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \ + --hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \ + --hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \ + --hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \ + --hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \ + --hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \ + --hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \ + --hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \ + --hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049 # via # build # coverage @@ -5581,94 +5599,89 @@ toolz==1.1.0 \ # dask # ibis-framework # partd -torch==2.10.0 \ - --hash=sha256:13ec4add8c3faaed8d13e0574f5cd4a323c11655546f91fbe6afa77b57423574 \ - --hash=sha256:233aed0659a2503b831d8a67e9da66a62c996204c0bba4f4c442ccc0c68a3f60 \ - --hash=sha256:29b7009dba4b7a1c960260fc8ac85022c784250af43af9fb0ebafc9883782ebd \ - --hash=sha256:2b980edd8d7c0a68c4e951ee1856334a43193f98730d97408fbd148c1a933313 \ - --hash=sha256:2c66c61f44c5f903046cc696d088e21062644cbe541c7f1c4eaae88b2ad23547 \ - --hash=sha256:3202429f58309b9fa96a614885eace4b7995729f44beb54d3e4a47773649d382 \ - --hash=sha256:3282d9febd1e4e476630a099692b44fdc214ee9bf8ee5377732d9d9dfe5712e4 \ - --hash=sha256:35e407430795c8d3edb07a1d711c41cc1f9eaddc8b2f1cc0a165a6767a8fb73d \ - --hash=sha256:418997cb02d0a0f1497cf6a09f63166f9f5df9f3e16c8a716ab76a72127c714f \ - --hash=sha256:5276fa790a666ee8becaffff8acb711922252521b28fbce5db7db5cf9cb2026d \ - --hash=sha256:5c4d217b14741e40776dd7074d9006fd28b8a97ef5654db959d8635b2fe5f29b \ - --hash=sha256:5fd4117d89ffd47e3dcc71e71a22efac24828ad781c7e46aaaf56bf7f2796acf \ - --hash=sha256:6021db85958db2f07ec94e1bc77212721ba4920c12a18dc552d2ae36a3eb163f \ - --hash=sha256:6528f13d2a8593a1a412ea07a99812495bec07e9224c28b2a25c0a30c7da025c \ - --hash=sha256:682497e16bdfa6efeec8cde66531bc8d1fbbbb4d8788ec6173c089ed3cc2bfe5 \ - --hash=sha256:6b71486353fce0f9714ca0c9ef1c850a2ae766b409808acd58e9678a3edb7738 \ - --hash=sha256:6d3707a61863d1c4d6ebba7be4ca320f42b869ee657e9b2c21c736bf17000294 \ - --hash=sha256:71283a373f0ee2c89e0f0d5f446039bdabe8dbc3c9ccf35f0f784908b0acd185 \ - --hash=sha256:716b01a176c2a5659c98f6b01bf868244abdd896526f1c692712ab36dbaf9b63 \ - --hash=sha256:787124e7db3b379d4f1ed54dd12ae7c741c16a4d29b49c0226a89bea50923ffb \ - --hash=sha256:a2f9edd8dbc99f62bc4dfb78af7bf89499bca3d753423ac1b4e06592e467b763 \ - --hash=sha256:a4be6a2a190b32ff5c8002a0977a25ea60e64f7ba46b1be37093c141d9c49aeb \ - --hash=sha256:aae1b29cd68e50a9397f5ee897b9c24742e9e306f88a807a27d617f07adb3bd8 \ - --hash=sha256:aaf663927bcd490ae971469a624c322202a2a1e68936eb952535ca4cd3b90444 \ - --hash=sha256:b7bd80f3477b830dd166c707c5b0b82a898e7b16f59a7d9d42778dd058272e8b \ - --hash=sha256:bf0d9ff448b0218e0433aeb198805192346c4fd659c852370d5cc245f602a06a \ - --hash=sha256:c2ee399c644dc92ef7bc0d4f7e74b5360c37cdbe7c5ba11318dda49ffac2bc57 \ - --hash=sha256:cdf2a523d699b70d613243211ecaac14fe9c5df8a0b0a9c02add60fb2a413e0f \ - --hash=sha256:d8f5912ba938233f86361e891789595ff35ca4b4e2ac8fe3670895e5976731d6 \ - --hash=sha256:e521c9f030a3774ed770a9c011751fb47c4d12029a3d6522116e48431f2ff89e \ - --hash=sha256:f5ab4ba32383061be0fb74bda772d470140a12c1c3b58a0cfbf3dae94d164c28 \ - --hash=sha256:ff43db38af76fda183156153983c9a096fc4c78d0cd1e07b14a2314c7f01c2c8 +torch==2.11.0 \ + --hash=sha256:01018087326984a33b64e04c8cb5c2795f9120e0d775ada1f6638840227b04d7 \ + --hash=sha256:0f68f4ac6d95d12e896c3b7a912b5871619542ec54d3649cf48cc1edd4dd2756 \ + --hash=sha256:1b32ceda909818a03b112006709b02be1877240c31750a8d9c6b7bf5f2d8a6e5 \ + --hash=sha256:1e6debd97ccd3205bbb37eb806a9d8219e1139d15419982c09e23ef7d4369d18 \ + --hash=sha256:2658f34ce7e2dabf4ec73b45e2ca68aedad7a5be87ea756ad656eaf32bf1e1ea \ + --hash=sha256:2b4e811728bd0cc58fb2b0948fe939a1ee2bf1422f6025be2fca4c7bd9d79718 \ + --hash=sha256:2bb3cc54bd0dea126b0060bb1ec9de0f9c7f7342d93d436646516b0330cd5be7 \ + --hash=sha256:2c0d7fcfbc0c4e8bb5ebc3907cbc0c6a0da1b8f82b1fc6e14e914fa0b9baf74e \ + --hash=sha256:4b5866312ee6e52ea625cd211dcb97d6a2cdc1131a5f15cc0d87eec948f6dd34 \ + --hash=sha256:4cf8687f4aec3900f748d553483ef40e0ac38411c3c48d0a86a438f6d7a99b18 \ + --hash=sha256:4dc8b3809469b6c30b411bb8c4cad3828efd26236153d9beb6a3ec500f211a60 \ + --hash=sha256:4dda3b3f52d121063a731ddb835f010dc137b920d7fec2778e52f60d8e4bf0cd \ + --hash=sha256:563ed3d25542d7e7bbc5b235ccfacfeb97fb470c7fee257eae599adb8005c8a2 \ + --hash=sha256:63a68fa59de8f87acc7e85a5478bb2dddbb3392b7593ec3e78827c793c4b73fd \ + --hash=sha256:73e24aaf8f36ab90d95cd1761208b2eb70841c2a9ca1a3f9061b39fc5331b708 \ + --hash=sha256:7aa2f9bbc6d4595ba72138026b2074be1233186150e9292865e04b7a63b8c67a \ + --hash=sha256:7b6a60d48062809f58595509c524b88e6ddec3ebe25833d6462eeab81e5f2ce4 \ + --hash=sha256:8245477871c3700d4370352ffec94b103cfcb737229445cf9946cddb7b2ca7cd \ + --hash=sha256:8b394322f49af4362d4f80e424bcaca7efcd049619af03a4cf4501520bdf0fb4 \ + --hash=sha256:98bb213c3084cfe176302949bdc360074b18a9da7ab59ef2edc9d9f742504778 \ + --hash=sha256:a97b94bbf62992949b4730c6cd2cc9aee7b335921ee8dc207d930f2ed09ae2db \ + --hash=sha256:ab9a8482f475f9ba20e12db84b0e55e2f58784bdca43a854a6ccd3fd4b9f75e6 \ + --hash=sha256:b2a43985ff5ef6ddd923bbcf99943e5f58059805787c5c9a2622bf05ca2965b0 \ + --hash=sha256:b3c712ae6fb8e7a949051a953fc412fe0a6940337336c3b6f905e905dac5157f \ + --hash=sha256:cc89b9b173d9adfab59fd227f0ab5e5516d9a52b658ae41d64e59d2e55a418db \ + --hash=sha256:d91aac77f24082809d2c5a93f52a5f085032740a1ebc9252a7b052ef5a4fddc6 \ + --hash=sha256:f99924682ef0aa6a4ab3b1b76f40dc6e273fca09f367d15a524266db100a723f \ + --hash=sha256:fbf39280699d1b869f55eac536deceaa1b60bd6788ba74f399cc67e60a5fab10 # via # feast (pyproject.toml) # accelerate # docling-ibm-models # easyocr # safetensors + # sentence-transformers # timm # torchvision -torchvision==0.25.0 \ - --hash=sha256:0b5e7f50002a8145a98c5694a018e738c50e2972608310c7e88e1bd4c058f6ce \ - --hash=sha256:0d9a3f925a081dd2ebb0b791249b687c2ef2c2717d027946654607494b9b64b6 \ - --hash=sha256:146d02c9876858420adf41f3189fe90e3d6a409cbfa65454c09f25fb33bf7266 \ - --hash=sha256:153c0d2cbc34b7cf2da19d73450f24ba36d2b75ec9211b9962b5022fb9e4ecee \ - --hash=sha256:24e11199e4d84ba9c5ee7825ebdf1cd37ce8deec225117f10243cae984ced3ec \ - --hash=sha256:40a122c3cf4d14b651f095e0f672b688dde78632783fc5cd3d4d5e4f6a828563 \ - --hash=sha256:5e6b449e9fa7d642142c0e27c41e5a43b508d57ed8e79b7c0a0c28652da8678c \ - --hash=sha256:5f271136d2d2c0b7a24c5671795c6e4fd8da4e0ea98aeb1041f62bc04c4370ef \ - --hash=sha256:620a236288d594dcec7634c754484542dc0a5c1b0e0b83a34bda5e91e9b7c3a1 \ - --hash=sha256:632db02300e83793812eee4f61ae6a2686dab10b4cfd628b620dc47747aa9d03 \ - --hash=sha256:846890161b825b38aa85fc37fb3ba5eea74e7091ff28bab378287111483b6443 \ - --hash=sha256:855c0dc6d37f462482da7531c6788518baedca1e0847f3df42a911713acdfe52 \ - --hash=sha256:a8f8061284395ce31bcd460f2169013382ccf411148ceb2ee38e718e9860f5a7 \ - --hash=sha256:a95c47abb817d4e90ea1a8e57bd0d728e3e6b533b3495ae77d84d883c4d11f56 \ - --hash=sha256:acc339aba4a858192998c2b91f635827e40d9c469d9cf1455bafdda6e4c28ea4 \ - --hash=sha256:ad9a8a5877782944d99186e4502a614770fe906626d76e9cd32446a0ac3075f2 \ - --hash=sha256:b57430fbe9e9b697418a395041bb615124d9c007710a2712fda6e35fb310f264 \ - --hash=sha256:b75deafa2dfea3e2c2a525559b04783515e3463f6e830cb71de0fb7ea36fe233 \ - --hash=sha256:c2abe430c90b1d5e552680037d68da4eb80a5852ebb1c811b2b89d299b10573b \ - --hash=sha256:c4d395cb2c4a2712f6eb93a34476cdf7aae74bb6ea2ea1917f858e96344b00aa \ - --hash=sha256:cef0196be31be421f6f462d1e9da1101be7332d91984caa6f8022e6c78a5877f \ - --hash=sha256:d1abd5ed030c708f5dbf4812ad5f6fbe9384b63c40d6bd79f8df41a4a759a917 \ - --hash=sha256:db74a551946b75d19f9996c419a799ffdf6a223ecf17c656f90da011f1d75b20 \ - --hash=sha256:ea580ffd6094cc01914ad32f8c8118174f18974629af905cea08cb6d5d48c7b7 \ - --hash=sha256:f07f01d27375ad89d72aa2b3f2180f07da95dd9d2e4c758e015c0acb2da72977 \ - --hash=sha256:f25aa9e380865b11ea6e9d99d84df86b9cc959f1a007cd966fc6f1ab2ed0e248 \ - --hash=sha256:f49964f96644dbac2506dffe1a0a7ec0f2bf8cf7a588c3319fed26e6329ffdf3 \ - --hash=sha256:f9c55ae8d673ab493325d1267cbd285bb94d56f99626c00ac4644de32a59ede3 +torchvision==0.26.0 \ + --hash=sha256:0f3e572efe62ad645017ea847e0b5e4f2f638d4e39f05bc011d1eb9ac68d4806 \ + --hash=sha256:114bec0c0e98aa4ba446f63e2fe7a2cbca37b39ac933987ee4804f65de121800 \ + --hash=sha256:1c55dc8affbcc0eb2060fbabbe996ae9e5839b24bb6419777f17848945a411b1 \ + --hash=sha256:2adfbe438473236191ff077a4a9a0c767436879c89628aa97137e959b0c11a94 \ + --hash=sha256:358fc4726d0c08615b6d83b3149854f11efb2a564ed1acb6fce882e151412d23 \ + --hash=sha256:3daf9cc149cf3cdcbd4df9c59dae69ffca86c6823250442c3bbfd63fc2e26c61 \ + --hash=sha256:406557718e62fdf10f5706e88d8a5ec000f872da913bf629aab9297622585547 \ + --hash=sha256:4280c35ec8cba1fcc8294fb87e136924708726864c379e4c54494797d86bc474 \ + --hash=sha256:55bd6ad4ae77be01ba67a410b05b51f53b0d0ee45f146eb6a0dfb9007e70ab3c \ + --hash=sha256:5d63dd43162691258b1b3529b9041bac7d54caa37eae0925f997108268cbf7c4 \ + --hash=sha256:7058c5878262937e876f20c25867b33724586aa4499e2853b2d52b99a5e51953 \ + --hash=sha256:7993c01648e7c61d191b018e84d38fe0825c8fcb2720cd0f37caf7ba14404aa1 \ + --hash=sha256:8008474855623c6ba52876589dc52df0aa66e518c25eca841445348e5f79844c \ + --hash=sha256:82c3965eca27e86a316e31e4c3e5a16d353e0bcbe0ef8efa2e66502c54493c4b \ + --hash=sha256:9a904f2131cbfadab4df828088a9f66291ad33f49ff853872aed1f86848ef776 \ + --hash=sha256:a06d4772a8e13e772906ed736cc53ec6639e5e60554f8e5fa6ca165aabebc464 \ + --hash=sha256:a39c7a26538c41fda453f9a9692b5ff9b35a5437db1d94f3027f6f509c160eac \ + --hash=sha256:b6f9ad1ecc0eab52647298b379ee9426845f8903703e6127973f8f3d049a798b \ + --hash=sha256:b7d3e295624a28b3b1769228ce1345d94cf4d390dd31136766f76f2d20f718da \ + --hash=sha256:b7e6213620bbf97742e5f79832f9e9d769e6cf0f744c5b53dad80b76db633691 \ + --hash=sha256:c409e1c3fdebec7a3834465086dbda8bf7680eff79abf7fd2f10c6b59520a7a4 \ + --hash=sha256:d61a5abb6b42a0c0c311996c2ac4b83a94418a97182c83b055a2a4ae985e05aa \ + --hash=sha256:de6424b12887ad884f39a0ee446994ae3cd3b6a00a9cafe1bead85a031132af0 \ + --hash=sha256:e9d0e022c19a78552fb055d0414d47fecb4a649309b9968573daea160ba6869c \ + --hash=sha256:eb61804eb9dbe88c5a2a6c4da8dec1d80d2d0a6f18c999c524e32266cb1ebcd3 \ + --hash=sha256:ebc043cc5a4f0bf22e7680806dbba37ffb19e70f6953bbb44ed1a90aeb5c9bea \ + --hash=sha256:f13f12b3791a266de2d599cb8162925261622a037d87fc03132848343cf68f75 \ + --hash=sha256:fd10b5f994c210f4f6d6761cf686f82d748554adf486cb0979770c3252868c8f # via # feast (pyproject.toml) # docling-ibm-models # easyocr # timm -tornado==6.5.4 \ - --hash=sha256:053e6e16701eb6cbe641f308f4c1a9541f91b6261991160391bfc342e8a551a1 \ - --hash=sha256:1768110f2411d5cd281bac0a090f707223ce77fd110424361092859e089b38d1 \ - --hash=sha256:2d50f63dda1d2cac3ae1fa23d254e16b5e38153758470e9956cbc3d813d40843 \ - --hash=sha256:50ff0a58b0dc97939d29da29cd624da010e7f804746621c78d14b80238669335 \ - --hash=sha256:6076d5dda368c9328ff41ab5d9dd3608e695e8225d1cd0fd1e006f05da3635a8 \ - --hash=sha256:6eb82872335a53dd063a4f10917b3efd28270b56a33db69009606a0312660a6f \ - --hash=sha256:9c86b1643b33a4cd415f8d0fe53045f913bf07b4a3ef646b735a6a86047dda84 \ - --hash=sha256:a22fa9047405d03260b483980635f0b041989d8bcc9a313f8fe18b411d84b1d7 \ - --hash=sha256:d1cf66105dc6acb5af613c054955b8137e34a03698aa53272dbda4afe252be17 \ - --hash=sha256:d6241c1a16b1c9e4cc28148b1cda97dd1c6cb4fb7068ac1bedc610768dff0ba9 \ - --hash=sha256:e5fb5e04efa54cf0baabdd10061eb4148e0be137166146fff835745f59ab9f7f \ - --hash=sha256:fa07d31e0cd85c60713f2b995da613588aa03e1303d75705dca6af8babc18ddc +tornado==6.5.5 \ + --hash=sha256:192b8f3ea91bd7f1f50c06955416ed76c6b72f96779b962f07f911b91e8d30e9 \ + --hash=sha256:2c9a876e094109333f888539ddb2de4361743e5d21eece20688e3e351e4990a6 \ + --hash=sha256:36abed1754faeb80fbd6e64db2758091e1320f6bba74a4cf8c09cd18ccce8aca \ + --hash=sha256:3f54aa540bdbfee7b9eb268ead60e7d199de5021facd276819c193c0fb28ea4e \ + --hash=sha256:435319e9e340276428bbdb4e7fa732c2d399386d1de5686cb331ec8eee754f07 \ + --hash=sha256:487dc9cc380e29f58c7ab88f9e27cdeef04b2140862e5076a66fb6bb68bb1bfa \ + --hash=sha256:6443a794ba961a9f619b1ae926a2e900ac20c34483eea67be4ed8f1e58d3ef7b \ + --hash=sha256:65a7f1d46d4bb41df1ac99f5fcb685fb25c7e61613742d5108b010975a9a6521 \ + --hash=sha256:dd3eafaaeec1c7f2f8fdcd5f964e8907ad788fe8a5a32c4426fbbdda621223b7 \ + --hash=sha256:e74c92e8e65086b338fd56333fb9a68b9f6f2fe7ad532645a290a464bcf46be5 # via # ipykernel # jupyter-client @@ -5689,6 +5702,7 @@ tqdm==4.67.3 \ # milvus-lite # mpire # semchunk + # sentence-transformers # transformers traitlets==5.14.3 \ --hash=sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7 \ @@ -5713,6 +5727,7 @@ transformers==4.57.6 \ # feast (pyproject.toml) # docling-core # docling-ibm-models + # sentence-transformers tree-sitter==0.25.2 \ --hash=sha256:0628671f0de69bb279558ef6b640bcfc97864fe0026d840f872728a86cd6b6cd \ --hash=sha256:0c8b6682cac77e37cfe5cf7ec388844957f48b7bd8d6321d0ca2d852994e10d5 \ @@ -5793,13 +5808,13 @@ tree-sitter-typescript==0.23.2 \ --hash=sha256:c7cc1b0ff5d91bac863b0e38b1578d5505e718156c9db577c8baea2557f66de8 \ --hash=sha256:e96d36b85bcacdeb8ff5c2618d75593ef12ebaf1b4eace3477e2bdb2abb1752c # via docling-core -trino==0.336.0 \ - --hash=sha256:389150841446949119c3c2c13c1a51bb4be1a27818e40ae40dd3701f36c02550 \ - --hash=sha256:e82339e9fffe5c6c51de3bfdf28f083e3ae5945a4502739ab2094a0d08d68070 +trino==0.337.0 \ + --hash=sha256:3a0bd03a09b7ea5dccd41ca6e58abfb127c6303f3a48a258ff794d411dd83a3c \ + --hash=sha256:868f2b8137d4d1baa84c9bc341f2cdf29039462aa69d7c089a0b821b5a91f29c # via feast (pyproject.toml) -typeguard==4.5.0 \ - --hash=sha256:749bea21cdb2553e12831bc29f1eae980b22c7de8331ab67ae7db9e85470b5a7 \ - --hash=sha256:cfda388fc88a9ce42a41890900d6f31ee124bea9b73bb84701a32438e92165c3 +typeguard==4.5.1 \ + --hash=sha256:44d2bf329d49a244110a090b55f5f91aa82d9a9834ebfd30bcc73651e4a8cc40 \ + --hash=sha256:f6f8ecbbc819c9bc749983cc67c02391e16a9b43b8b27f15dc70ed7c4a007274 # via feast (pyproject.toml) typer==0.12.5 \ --hash=sha256:62fe4e471711b147e3365034133904df3e235698399bc4de2b36c8579298d52b \ @@ -5808,9 +5823,9 @@ typer==0.12.5 \ # docling # docling-core # fastapi-mcp -types-cffi==1.17.0.20250915 \ - --hash=sha256:4362e20368f78dabd5c56bca8004752cc890e07a71605d9e0d9e069dbaac8c06 \ - --hash=sha256:cef4af1116c83359c11bb4269283c50f0688e9fc1d7f0eeb390f3661546da52c +types-cffi==2.0.0.20260402 \ + --hash=sha256:47e1320c009f630c59c55c8e3d2b8c501e280babf52e92f6109cbfb0864ba367 \ + --hash=sha256:f647a400fba0a31d603479169d82ee5359db79bd1136e41dc7e6489296e3a2b2 # via types-pyopenssl types-protobuf==3.19.22 \ --hash=sha256:d291388678af91bb045fafa864f142dc4ac22f5d4cdca097c7d8d8a32fa9b3ab \ @@ -5826,13 +5841,13 @@ types-pyopenssl==24.1.0.20240722 \ --hash=sha256:47913b4678a01d879f503a12044468221ed8576263c1540dcb0484ca21b08c39 \ --hash=sha256:6a7a5d2ec042537934cfb4c9d4deb0e16c4c6250b09358df1f083682fe6fda54 # via types-redis -types-python-dateutil==2.9.0.20260124 \ - --hash=sha256:7d2db9f860820c30e5b8152bfe78dbdf795f7d1c6176057424e8b3fdd1f581af \ - --hash=sha256:f802977ae08bf2260142e7ca1ab9d4403772a254409f7bbdf652229997124951 +types-python-dateutil==2.9.0.20260402 \ + --hash=sha256:7827e6a9c93587cc18e766944254d1351a2396262e4abe1510cbbd7601c5e01f \ + --hash=sha256:a980142b9966713acb382c467e35c5cc4208a2f91b10b8d785a0ae6765df6c0b # via feast (pyproject.toml) -types-pytz==2025.2.0.20251108 \ - --hash=sha256:0f1c9792cab4eb0e46c52f8845c8f77cf1e313cb3d68bf826aa867fe4717d91c \ - --hash=sha256:fca87917836ae843f07129567b74c1929f1870610681b4c92cb86a3df5817bdb +types-pytz==2026.1.1.20260402 \ + --hash=sha256:0d9a60ed1c6ad4fce7c6395b5bd2d9827db41d4b83de7c0322cf85869c2bfda3 \ + --hash=sha256:79209aa51dc003a4a6a764234d92b14e5c09a1b7f24e0f00c493929fd33618e8 # via feast (pyproject.toml) types-pyyaml==6.0.12.20250915 \ --hash=sha256:0f8b54a528c303f0e6f7165687dd33fafa81c807fcac23f632b63aa624ced1d3 \ @@ -5846,15 +5861,15 @@ types-requests==2.30.0.0 \ --hash=sha256:c6cf08e120ca9f0dc4fa4e32c3f953c3fba222bcc1db6b97695bce8da1ba9864 \ --hash=sha256:dec781054324a70ba64430ae9e62e7e9c8e4618c185a5cb3f87a6738251b5a31 # via feast (pyproject.toml) -types-setuptools==82.0.0.20260210 \ - --hash=sha256:5124a7daf67f195c6054e0f00f1d97c69caad12fdcf9113eba33eff0bce8cd2b \ - --hash=sha256:d9719fbbeb185254480ade1f25327c4654f8c00efda3fec36823379cebcdee58 +types-setuptools==82.0.0.20260402 \ + --hash=sha256:4b9a9f6c3c4c65107a3956ad6a6acbccec38e398ff6d5f78d5df7f103dadb8d6 \ + --hash=sha256:63d2b10ba7958396ad79bbc24d2f6311484e452daad4637ffd40407983a27069 # via # feast (pyproject.toml) # types-cffi -types-tabulate==0.9.0.20241207 \ - --hash=sha256:ac1ac174750c0a385dfd248edc6279fa328aaf4ea317915ab879a2ec47833230 \ - --hash=sha256:b8dad1343c2a8ba5861c5441370c3e35908edd234ff036d4298708a1d4cf8a85 +types-tabulate==0.10.0.20260308 \ + --hash=sha256:724dcb1330ffba5f46d3cf6e29f45089fccb8e85801e6e7ac9efb1195bf7bea1 \ + --hash=sha256:94a9795965bc6290f844d61e8680a1270040664b88fd12014624090fd847e13c # via feast (pyproject.toml) types-urllib3==1.26.25.14 \ --hash=sha256:229b7f577c951b8c1b92c1bc2b2fdb0b49847bd2af6d1cc2a2e3dd340f3bda8f \ @@ -5872,6 +5887,7 @@ typing-extensions==4.15.0 \ # azure-storage-blob # beautifulsoup4 # couchbase-columnar + # cryptography # docling-core # elasticsearch # exceptiongroup @@ -5886,14 +5902,17 @@ typing-extensions==4.15.0 \ # mistune # multidict # mypy + # oracledb # psycopg # psycopg-pool # pydantic # pydantic-core + # pyjwt # pyopenssl # python-docx # python-pptx # referencing + # sentence-transformers # snowflake-connector-python # sqlalchemy # starlette @@ -5924,91 +5943,85 @@ tzlocal==5.3.1 \ # via # great-expectations # trino -ujson==5.11.0 \ - --hash=sha256:0180a480a7d099082501cad1fe85252e4d4bf926b40960fb3d9e87a3a6fbbc80 \ - --hash=sha256:04c41afc195fd477a59db3a84d5b83a871bd648ef371cf8c6f43072d89144eef \ - --hash=sha256:0654a2691fc252c3c525e3d034bb27b8a7546c9d3eb33cd29ce6c9feda361a6a \ - --hash=sha256:090b4d11b380ae25453100b722d0609d5051ffe98f80ec52853ccf8249dfd840 \ - --hash=sha256:109f59885041b14ee9569bf0bb3f98579c3fa0652317b355669939e5fc5ede53 \ - --hash=sha256:10f29e71ecf4ecd93a6610bd8efa8e7b6467454a363c3d6416db65de883eb076 \ - --hash=sha256:1194b943e951092db611011cb8dbdb6cf94a3b816ed07906e14d3bc6ce0e90ab \ - --hash=sha256:12b5e7e22a1fe01058000d1b317d3b65cc3daf61bd2ea7a2b76721fe160fa74d \ - --hash=sha256:16ccb973b7ada0455201808ff11d48fe9c3f034a6ab5bd93b944443c88299f89 \ - --hash=sha256:181fb5b15703a8b9370b25345d2a1fd1359f0f18776b3643d24e13ed9c036d4c \ - --hash=sha256:185f93ebccffebc8baf8302c869fac70dd5dd78694f3b875d03a31b03b062cdb \ - --hash=sha256:1a0a9b76a89827a592656fe12e000cf4f12da9692f51a841a4a07aa4c7ecc41c \ - --hash=sha256:1a325fd2c3a056cf6c8e023f74a0c478dd282a93141356ae7f16d5309f5ff823 \ - --hash=sha256:1aa8a2ab482f09f6c10fba37112af5f957689a79ea598399c85009f2f29898b5 \ - --hash=sha256:1d663b96eb34c93392e9caae19c099ec4133ba21654b081956613327f0e973ac \ - --hash=sha256:29113c003ca33ab71b1b480bde952fbab2a0b6b03a4ee4c3d71687cdcbd1a29d \ - --hash=sha256:30f607c70091483550fbd669a0b37471e5165b317d6c16e75dba2aa967608723 \ - --hash=sha256:3134b783ab314d2298d58cda7e47e7a0f7f71fc6ade6ac86d5dbeaf4b9770fa6 \ - --hash=sha256:34032aeca4510a7c7102bd5933f59a37f63891f30a0706fb46487ab6f0edf8f0 \ - --hash=sha256:3772e4fe6b0c1e025ba3c50841a0ca4786825a4894c8411bf8d3afe3a8061328 \ - --hash=sha256:3d2720e9785f84312b8e2cb0c2b87f1a0b1c53aaab3b2af3ab817d54409012e0 \ - --hash=sha256:416389ec19ef5f2013592f791486bef712ebce0cd59299bf9df1ba40bb2f6e04 \ - --hash=sha256:446e8c11c06048611c9d29ef1237065de0af07cabdd97e6b5b527b957692ec25 \ - --hash=sha256:4598bf3965fc1a936bd84034312bcbe00ba87880ef1ee33e33c1e88f2c398b49 \ - --hash=sha256:48055e1061c1bb1f79e75b4ac39e821f3f35a9b82de17fce92c3140149009bec \ - --hash=sha256:4843f3ab4fe1cc596bb7e02228ef4c25d35b4bb0809d6a260852a4bfcab37ba3 \ - --hash=sha256:49e56ef8066f11b80d620985ae36869a3ff7e4b74c3b6129182ec5d1df0255f3 \ - --hash=sha256:4b42c115c7c6012506e8168315150d1e3f76e7ba0f4f95616f4ee599a1372bbc \ - --hash=sha256:4c9f5d6a27d035dd90a146f7761c2272cf7103de5127c9ab9c4cd39ea61e878a \ - --hash=sha256:5600202a731af24a25e2d7b6eb3f648e4ecd4bb67c4d5cf12f8fab31677469c9 \ - --hash=sha256:65724738c73645db88f70ba1f2e6fb678f913281804d5da2fd02c8c5839af302 \ - --hash=sha256:65f3c279f4ed4bf9131b11972040200c66ae040368abdbb21596bf1564899694 \ - --hash=sha256:674f306e3e6089f92b126eb2fe41bcb65e42a15432c143365c729fdb50518547 \ - --hash=sha256:683f57f0dd3acdd7d9aff1de0528d603aafcb0e6d126e3dc7ce8b020a28f5d01 \ - --hash=sha256:6b6ec7e7321d7fc19abdda3ad809baef935f49673951a8bab486aea975007e02 \ - --hash=sha256:6cd2df62f24c506a0ba322d5e4fe4466d47a9467b57e881ee15a31f7ecf68ff6 \ - --hash=sha256:6dd703c3e86dc6f7044c5ac0b3ae079ed96bf297974598116aa5fb7f655c3a60 \ - --hash=sha256:6eff24e1abd79e0ec6d7eae651dd675ddbc41f9e43e29ef81e16b421da896915 \ - --hash=sha256:7855ccea3f8dad5e66d8445d754fc1cf80265a4272b5f8059ebc7ec29b8d0835 \ - --hash=sha256:787aff4a84da301b7f3bac09bc696e2e5670df829c6f8ecf39916b4e7e24e701 \ - --hash=sha256:7895f0d2d53bd6aea11743bd56e3cb82d729980636cd0ed9b89418bf66591702 \ - --hash=sha256:78c684fb21255b9b90320ba7e199780f653e03f6c2528663768965f4126a5b50 \ - --hash=sha256:7e0ec1646db172beb8d3df4c32a9d78015e671d2000af548252769e33079d9a6 \ - --hash=sha256:7e3cff632c1d78023b15f7e3a81c3745cd3f94c044d1e8fa8efbd6b161997bbc \ - --hash=sha256:7f1a27ab91083b4770e160d17f61b407f587548f2c2b5fbf19f94794c495594a \ - --hash=sha256:80017e870d882d5517d28995b62e4e518a894f932f1e242cbc802a2fd64d365c \ - --hash=sha256:8254e858437c00f17cb72e7a644fc42dad0ebb21ea981b71df6e84b1072aaa7c \ - --hash=sha256:837da4d27fed5fdc1b630bd18f519744b23a0b5ada1bbde1a36ba463f2900c03 \ - --hash=sha256:849e65b696f0d242833f1df4182096cedc50d414215d1371fca85c541fbff629 \ - --hash=sha256:85e6796631165f719084a9af00c79195d3ebf108151452fefdcb1c8bb50f0105 \ - --hash=sha256:86baf341d90b566d61a394869ce77188cc8668f76d7bb2c311d77a00f4bdf844 \ - --hash=sha256:8fa2af7c1459204b7a42e98263b069bd535ea0cd978b4d6982f35af5a04a4241 \ - --hash=sha256:94fcae844f1e302f6f8095c5d1c45a2f0bfb928cccf9f1b99e3ace634b980a2a \ - --hash=sha256:952c0be400229940248c0f5356514123d428cba1946af6fa2bbd7503395fef26 \ - --hash=sha256:99c49400572cd77050894e16864a335225191fd72a818ea6423ae1a06467beac \ - --hash=sha256:9aacbeb23fdbc4b256a7d12e0beb9063a1ba5d9e0dbb2cfe16357c98b4334596 \ - --hash=sha256:a0af6574fc1d9d53f4ff371f58c96673e6d988ed2b5bf666a6143c782fa007e9 \ - --hash=sha256:a31c6b8004438e8c20fc55ac1c0e07dad42941db24176fe9acf2815971f8e752 \ - --hash=sha256:a4df61a6df0a4a8eb5b9b1ffd673429811f50b235539dac586bb7e9e91994138 \ - --hash=sha256:a638425d3c6eed0318df663df44480f4a40dc87cc7c6da44d221418312f6413b \ - --hash=sha256:aa6b3d4f1c0d3f82930f4cbd7fe46d905a4a9205a7c13279789c1263faf06dba \ - --hash=sha256:aa6d7a5e09217ff93234e050e3e380da62b084e26b9f2e277d2606406a2fc2e5 \ - --hash=sha256:ab2cb8351d976e788669c8281465d44d4e94413718af497b4e7342d7b2f78018 \ - --hash=sha256:abae0fb58cc820092a0e9e8ba0051ac4583958495bfa5262a12f628249e3b362 \ - --hash=sha256:b16930f6a0753cdc7d637b33b4e8f10d5e351e1fb83872ba6375f1e87be39746 \ - --hash=sha256:b7b136cc6abc7619124fd897ef75f8e63105298b5ca9bdf43ebd0e1fa0ee105f \ - --hash=sha256:be6b0eaf92cae8cdee4d4c9e074bde43ef1c590ed5ba037ea26c9632fb479c88 \ - --hash=sha256:c44c703842024d796b4c78542a6fcd5c3cb948b9fc2a73ee65b9c86a22ee3638 \ - --hash=sha256:c6618f480f7c9ded05e78a1938873fde68baf96cdd74e6d23c7e0a8441175c4b \ - --hash=sha256:ce076f2df2e1aa62b685086fbad67f2b1d3048369664b4cdccc50707325401f9 \ - --hash=sha256:d06e87eded62ff0e5f5178c916337d2262fdbc03b31688142a3433eabb6511db \ - --hash=sha256:d7c46cb0fe5e7056b9acb748a4c35aa1b428025853032540bb7e41f46767321f \ - --hash=sha256:d8951bb7a505ab2a700e26f691bdfacf395bc7e3111e3416d325b513eea03a58 \ - --hash=sha256:da473b23e3a54448b008d33f742bcd6d5fb2a897e42d1fc6e7bf306ea5d18b1b \ - --hash=sha256:de6e88f62796372fba1de973c11138f197d3e0e1d80bcb2b8aae1e826096d433 \ - --hash=sha256:e204ae6f909f099ba6b6b942131cee359ddda2b6e4ea39c12eb8b991fe2010e0 \ - --hash=sha256:e73df8648c9470af2b6a6bf5250d4744ad2cf3d774dcf8c6e31f018bdd04d764 \ - --hash=sha256:e750c436fb90edf85585f5c62a35b35082502383840962c6983403d1bd96a02c \ - --hash=sha256:e979fbc469a7f77f04ec2f4e853ba00c441bf2b06720aa259f0f720561335e34 \ - --hash=sha256:ecd6ff8a3b5a90c292c2396c2d63c687fd0ecdf17de390d852524393cd9ed052 \ - --hash=sha256:f278b31a7c52eb0947b2db55a5133fbc46b6f0ef49972cd1a80843b72e135aba \ - --hash=sha256:f62b9976fabbcde3ab6e413f4ec2ff017749819a0786d84d7510171109f2d53c \ - --hash=sha256:fa79fdb47701942c2132a9dd2297a1a85941d966d8c87bfd9e29b0cf423f26cc \ - --hash=sha256:fac6c0649d6b7c3682a0a6e18d3de6857977378dce8d419f57a0b20e3d775b39 +ujson==5.12.0 \ + --hash=sha256:006428d3813b87477d72d306c40c09f898a41b968e57b15a7d88454ecc42a3fb \ + --hash=sha256:02f93da7a4115e24f886b04fd56df1ee8741c2ce4ea491b7ab3152f744ad8f8e \ + --hash=sha256:0727363b05ab05ee737a28f6200dc4078bce6b0508e10bd8aab507995a15df61 \ + --hash=sha256:085b6ce182cdd6657481c7c4003a417e0655c4f6e58b76f26ee18f0ae21db827 \ + --hash=sha256:09b4beff9cc91d445d5818632907b85fb06943b61cb346919ce202668bf6794a \ + --hash=sha256:0a3ae28f0b209be5af50b54ca3e2123a3de3a57d87b75f1e5aa3d7961e041983 \ + --hash=sha256:0d2e8db5ade3736a163906154ca686203acc7d1d30736cbf577c730d13653d84 \ + --hash=sha256:0e00cec383eab2406c9e006bd4edb55d284e94bb943fda558326048178d26961 \ + --hash=sha256:0fe6b8b8968e11dd9b2348bd508f0f57cf49ab3512064b36bc4117328218718e \ + --hash=sha256:0fe9128e75c6aa6e9ae06c1408d6edd9179a2fef0fe6d9cda3166b887eba521d \ + --hash=sha256:14b2e1eb528d77bc0f4c5bd1a7ebc05e02b5b41beefb7e8567c9675b8b13bcf4 \ + --hash=sha256:15d416440148f3e56b9b244fdaf8a09fcf5a72e4944b8e119f5bf60417a2bfc8 \ + --hash=sha256:15e555c4caca42411270b2ed2b2ebc7b3a42bb04138cef6c956e1f1d49709fe2 \ + --hash=sha256:16b4fe9c97dc605f5e1887a9e1224287291e35c56cbc379f8aa44b6b7bcfe2bb \ + --hash=sha256:1b5c6ceb65fecd28a1d20d1eba9dbfa992612b86594e4b6d47bb580d2dd6bcb3 \ + --hash=sha256:1d072a403d82aef8090c6d4f728e3a727dfdba1ad3b7fa3a052c3ecbd37e73cb \ + --hash=sha256:2324d9a0502317ffc35d38e153c1b2fa9610ae03775c9d0f8d0cca7b8572b04e \ + --hash=sha256:2a248750abce1c76fbd11b2e1d88b95401e72819295c3b851ec73399d6849b3d \ + --hash=sha256:2ea6206043385343aff0b7da65cf73677f6f5e50de8f1c879e557f4298cac36a \ + --hash=sha256:31348a0ffbfc815ce78daac569d893349d85a0b57e1cd2cdbba50b7f333784da \ + --hash=sha256:38051f36423f084b909aaadb3b41c9c6a2958e86956ba21a8489636911e87504 \ + --hash=sha256:3c2f947e55d3c7cfe124dd4521ee481516f3007d13c6ad4bf6aeb722e190eb1b \ + --hash=sha256:3ed5cb149892141b1e77ef312924a327f2cc718b34247dae346ed66329e1b8be \ + --hash=sha256:3ff4ede90ed771140caa7e1890de17431763a483c54b3c1f88bd30f0cc1affc0 \ + --hash=sha256:40aa43a7a3a8d2f05e79900858053d697a88a605e3887be178b43acbcd781161 \ + --hash=sha256:42d875388fbd091c7ea01edfff260f839ba303038ffb23475ef392012e4d63dd \ + --hash=sha256:457fabc2700a8e6ddb85bc5a1d30d3345fe0d3ec3ee8161a4e032ec585801dfa \ + --hash=sha256:460e76a4daff214ae33ab959494962c93918cb44714ea3e3f748b14aa37f8a87 \ + --hash=sha256:50524f4f6a1c839714dbaff5386a1afb245d2d5ec8213a01fbc99cea7307811e \ + --hash=sha256:51acc750ec7a2df786cdc868fb16fa04abd6269a01d58cf59bafc57978773d8e \ + --hash=sha256:55ede2a7a051b3b7e71a394978a098d71b3783e6b904702ff45483fad434ae2d \ + --hash=sha256:561f89cc82deeae82e37d4a4764184926fb432f740a9691563a391b13f7339a4 \ + --hash=sha256:56ba3f7abbd6b0bb282a544dc38406d1a188d8bb9164f49fdb9c2fee62cb29da \ + --hash=sha256:57930ac9519099b852e190d2c04b1fb5d97ea128db33bce77ed874eccb4c7f09 \ + --hash=sha256:58a11cb49482f1a095a2bd9a1d81dd7c8fb5d2357f959ece85db4e46a825fd00 \ + --hash=sha256:64df53eef4ac857eb5816a56e2885ccf0d7dff6333c94065c93b39c51063e01d \ + --hash=sha256:6879aed770557f0961b252648d36f6fdaab41079d37a2296b5649fd1b35608e0 \ + --hash=sha256:6ad57654570464eb1b040b5c353dee442608e06cff9102b8fcb105565a44c9ed \ + --hash=sha256:6c0aed6a4439994c9666fb8a5b6c4eac94d4ef6ddc95f9b806a599ef83547e3b \ + --hash=sha256:76bf3e7406cf23a3e1ca6a23fb1fb9ea82f4f6bd226fe226e09146b0194f85dc \ + --hash=sha256:7bbf05c38debc90d1a195b11340cc85cb43ab3e753dc47558a3a84a38cbc72da \ + --hash=sha256:7ddb08b3c2f9213df1f2e3eb2fbea4963d80ec0f8de21f0b59898e34f3b3d96d \ + --hash=sha256:7e07f6f644d2c44d53b7a320a084eef98063651912c1b9449b5f45fcbdc6ccd2 \ + --hash=sha256:85833bca01aa5cae326ac759276dc175c5fa3f7b3733b7d543cf27f2df12d1ef \ + --hash=sha256:8712b61eb1b74a4478cfd1c54f576056199e9f093659334aeb5c4a6b385338e5 \ + --hash=sha256:871c0e5102e47995b0e37e8df7819a894a6c3da0d097545cd1f9f1f7d7079927 \ + --hash=sha256:89e302abd3749f6d6699691747969a5d85f7c73081d5ed7e2624c7bd9721a2ab \ + --hash=sha256:937794042342006f707837f38d721426b11b0774d327a2a45c0bd389eb750a87 \ + --hash=sha256:93bc91fdadcf046da37a214eaa714574e7e9b1913568e93bb09527b2ceb7f759 \ + --hash=sha256:94c5f1621cbcab83c03be46441f090b68b9f307b6c7ec44d4e3f6d5997383df4 \ + --hash=sha256:973b7d7145b1ac553a7466a64afa8b31ec2693d7c7fff6a755059e0a2885dfd2 \ + --hash=sha256:99cc80facad240b0c2fb5a633044420878aac87a8e7c348b9486450cba93f27c \ + --hash=sha256:9a5fcbe7b949f2e95c47ea8a80b410fcdf2da61c98553b45a4ee875580418b68 \ + --hash=sha256:9b3b86ec3e818f3dd3e13a9de628e88a9990f4af68ecb0b12dd3de81227f0a26 \ + --hash=sha256:9b3cf13facf6f77c283af0e1713e5e8c47a0fe295af81326cb3cb4380212e797 \ + --hash=sha256:9c5a52987a990eb1bae55f9000994f1afdb0326c154fb089992f839ab3c30688 \ + --hash=sha256:a2d79c6635ccffcbfc1d5c045874ba36b594589be81d50d43472570bb8de9c57 \ + --hash=sha256:a6ec5bf6bc361f2f0f9644907a36ce527715b488988a8df534120e5c34eeda94 \ + --hash=sha256:a7bf9cc97f05048ac8f3e02cd58f0fe62b901453c24345bfde287f4305dcc31c \ + --hash=sha256:ab9056d94e5db513d9313b34394f3a3b83e6301a581c28ad67773434f3faccab \ + --hash=sha256:adf28d13a33f9d750fe7a78fb481cac298fa257d8863d8727b2ea4455ea41235 \ + --hash=sha256:b62cb9a7501e1f5c9ffe190485501349c33e8862dde4377df774e40b8166871f \ + --hash=sha256:bacbd3c69862478cbe1c7ed4325caedec580d8acf31b8ee1b9a1e02a56295cad \ + --hash=sha256:bb349dbba57c76eec25e5917e07f35aabaf0a33b9e67fc13d188002500106487 \ + --hash=sha256:bd03472c36fa3a386a6deb887113b9e3fa40efba8203eb4fe786d3c0ccc724f6 \ + --hash=sha256:bf85a00ac3b56a1e7a19c5be7b02b5180a0895ac4d3c234d717a55e86960691c \ + --hash=sha256:ca0c7ce828bb76ab78b3991904b477c2fd0f711d7815c252d1ef28ff9450b052 \ + --hash=sha256:ccbfd94e59aad4a2566c71912b55f0547ac1680bfac25eb138e6703eb3dd434e \ + --hash=sha256:d1831c07bd4dce53c4b666fa846c7eba4b7c414f2e641a4585b7f50b72f502dc \ + --hash=sha256:d22cad98c2a10bbf6aa083a8980db6ed90d4285a841c4de892890c2b28286ef9 \ + --hash=sha256:d30ad4359413c8821cc7b3707f7ca38aa8bc852ba3b9c5a759ee2d7740157315 \ + --hash=sha256:e0dd3676ea0837cd70ea1879765e9e9f6be063be0436de9b3ea4b775caf83654 \ + --hash=sha256:e584d0cdd37cac355aca52ed788d1a2d939d6837e2870d3b70e585db24025a50 \ + --hash=sha256:e6369ac293d2cc40d52577e4fa3d75a70c1aae2d01fa3580a34a4e6eff9286b9 \ + --hash=sha256:efae5df7a8cc8bdb1037b0f786b044ce281081441df5418c3a0f0e1f86fe7bb3 \ + --hash=sha256:f19b3af31d02a2e79c5f9a6deaab0fb3c116456aeb9277d11720ad433de6dfc6 \ + --hash=sha256:f7a0430d765f9bda043e6aefaba5944d5f21ec43ff4774417d7e296f61917382 \ + --hash=sha256:fb94245a715b4d6e24689de12772b85329a1f9946cbf6187923a64ecdea39e65 # via pymilvus uri-template==1.3.0 \ --hash=sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7 \ @@ -6293,9 +6306,9 @@ websockets==16.0 \ --hash=sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da \ --hash=sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4 # via uvicorn -werkzeug==3.1.5 \ - --hash=sha256:5111e36e91086ece91f93268bb39b4a35c1e6f1feac762c9c822ded0a4e322dc \ - --hash=sha256:6a548b0e88955dd07ccb25539d7d0cc97417ee9e179677d22c7041c8f078ce67 +werkzeug==3.1.8 \ + --hash=sha256:63a77fb8892bf28ebc3178683445222aa500e48ebad5ec77b0ad80f8726b1f50 \ + --hash=sha256:9bad61a4268dac112f1c5cd4630a56ede601b6ed420300677a869083d70a4c44 # via moto wheel==0.46.3 \ --hash=sha256:4b399d56c9d9338230118d705d9737a2a468ccca63d5e813e2a4fc7815d8bc4d \ @@ -6396,9 +6409,9 @@ xlsxwriter==3.2.9 \ --hash=sha256:254b1c37a368c444eac6e2f867405cc9e461b0ed97a3233b2ac1e574efb4140c \ --hash=sha256:9a5db42bc5dff014806c58a20b9eae7322a134abb6fce3c92c181bfb275ec5b3 # via python-pptx -xmltodict==1.0.3 \ - --hash=sha256:35d65d5c08f2a1121df338a0c4e49ca638480fa7c1b899ded45e0759bf32e40e \ - --hash=sha256:3bf1f49c7836df34cf6d9cc7e690c4351f7dfff2ab0b8a1988bba4a9b9474909 +xmltodict==1.0.4 \ + --hash=sha256:6d94c9f834dd9e44514162799d344d815a3a4faec913717a9ecbfa5be1bb8e61 \ + --hash=sha256:a4a00d300b0e1c59fc2bfccb53d7b2e88c32f200df138a0dd2229f842497026a # via moto xxhash==3.6.0 \ --hash=sha256:01262da8798422d0685f7cef03b2bd3f4f46511b02830861df548d7def4402ad \ @@ -6542,137 +6555,135 @@ xxhash==3.6.0 \ --hash=sha256:fba27a198363a7ef87f8c0f6b171ec36b674fe9053742c58dd7e3201c1ab30ee \ --hash=sha256:ffc578717a347baf25be8397cb10d2528802d24f94cfc005c0e44fef44b5cdd6 # via datasets -yarl==1.22.0 \ - --hash=sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a \ - --hash=sha256:029866bde8d7b0878b9c160e72305bbf0a7342bcd20b9999381704ae03308dc8 \ - --hash=sha256:078278b9b0b11568937d9509b589ee83ef98ed6d561dfe2020e24a9fd08eaa2b \ - --hash=sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da \ - --hash=sha256:07a524d84df0c10f41e3ee918846e1974aba4ec017f990dc735aad487a0bdfdf \ - --hash=sha256:088e4e08f033db4be2ccd1f34cf29fe994772fb54cfe004bbf54db320af56890 \ - --hash=sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093 \ - --hash=sha256:0cf71bf877efeac18b38d3930594c0948c82b64547c1cf420ba48722fe5509f6 \ - --hash=sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79 \ - --hash=sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683 \ - --hash=sha256:10619d9fdee46d20edc49d3479e2f8269d0779f1b031e6f7c2aa1c76be04b7ed \ - --hash=sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2 \ - --hash=sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff \ - --hash=sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02 \ - --hash=sha256:14291620375b1060613f4aab9ebf21850058b6b1b438f386cc814813d901c60b \ - --hash=sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03 \ - --hash=sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511 \ - --hash=sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c \ - --hash=sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124 \ - --hash=sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c \ - --hash=sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da \ - --hash=sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2 \ - --hash=sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0 \ - --hash=sha256:2e4e1f6f0b4da23e61188676e3ed027ef0baa833a2e633c29ff8530800edccba \ - --hash=sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d \ - --hash=sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53 \ - --hash=sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138 \ - --hash=sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4 \ - --hash=sha256:3aa27acb6de7a23785d81557577491f6c38a5209a254d1191519d07d8fe51748 \ - --hash=sha256:3b06bcadaac49c70f4c88af4ffcfbe3dc155aab3163e75777818092478bcbbe7 \ - --hash=sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d \ - --hash=sha256:3e2daa88dc91870215961e96a039ec73e4937da13cf77ce17f9cad0c18df3503 \ - --hash=sha256:3ea66b1c11c9150f1372f69afb6b8116f2dd7286f38e14ea71a44eee9ec51b9d \ - --hash=sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2 \ - --hash=sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa \ - --hash=sha256:437840083abe022c978470b942ff832c3940b2ad3734d424b7eaffcd07f76737 \ - --hash=sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f \ - --hash=sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1 \ - --hash=sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d \ - --hash=sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694 \ - --hash=sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3 \ - --hash=sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a \ - --hash=sha256:4c52a6e78aef5cf47a98ef8e934755abf53953379b7d53e68b15ff4420e6683d \ - --hash=sha256:4dcc74149ccc8bba31ce1944acee24813e93cfdee2acda3c172df844948ddf7b \ - --hash=sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a \ - --hash=sha256:51af598701f5299012b8416486b40fceef8c26fc87dc6d7d1f6fc30609ea0aa6 \ - --hash=sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b \ - --hash=sha256:595697f68bd1f0c1c159fcb97b661fc9c3f5db46498043555d04805430e79bea \ - --hash=sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5 \ - --hash=sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f \ - --hash=sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df \ - --hash=sha256:5cdac20da754f3a723cceea5b3448e1a2074866406adeb4ef35b469d089adb8f \ - --hash=sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b \ - --hash=sha256:5dbeefd6ca588b33576a01b0ad58aa934bc1b41ef89dee505bf2932b22ddffba \ - --hash=sha256:62441e55958977b8167b2709c164c91a6363e25da322d87ae6dd9c6019ceecf9 \ - --hash=sha256:663e1cadaddae26be034a6ab6072449a8426ddb03d500f43daf952b74553bba0 \ - --hash=sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6 \ - --hash=sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b \ - --hash=sha256:6944b2dc72c4d7f7052683487e3677456050ff77fcf5e6204e98caf785ad1967 \ - --hash=sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2 \ - --hash=sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708 \ - --hash=sha256:6dcbb0829c671f305be48a7227918cfcd11276c2d637a8033a99a02b67bf9eda \ - --hash=sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8 \ - --hash=sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10 \ - --hash=sha256:75976c6945d85dbb9ee6308cd7ff7b1fb9409380c82d6119bd778d8fcfe2931c \ - --hash=sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b \ - --hash=sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028 \ - --hash=sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e \ - --hash=sha256:80ddf7a5f8c86cb3eb4bc9028b07bbbf1f08a96c5c0bc1244be5e8fefcb94147 \ - --hash=sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33 \ - --hash=sha256:84fc3ec96fce86ce5aa305eb4aa9358279d1aa644b71fab7b8ed33fe3ba1a7ca \ - --hash=sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590 \ - --hash=sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c \ - --hash=sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53 \ - --hash=sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74 \ - --hash=sha256:99b6fc1d55782461b78221e95fc357b47ad98b041e8e20f47c1411d0aacddc60 \ - --hash=sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f \ - --hash=sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1 \ - --hash=sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27 \ - --hash=sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520 \ - --hash=sha256:a4fcfc8eb2c34148c118dfa02e6427ca278bfd0f3df7c5f99e33d2c0e81eae3e \ - --hash=sha256:a899cbd98dce6f5d8de1aad31cb712ec0a530abc0a86bd6edaa47c1090138467 \ - --hash=sha256:a9b1ba5610a4e20f655258d5a1fdc7ebe3d837bb0e45b581398b99eb98b1f5ca \ - --hash=sha256:af74f05666a5e531289cb1cc9c883d1de2088b8e5b4de48004e5ca8a830ac859 \ - --hash=sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273 \ - --hash=sha256:b266bd01fedeffeeac01a79ae181719ff848a5a13ce10075adbefc8f1daee70e \ - --hash=sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601 \ - --hash=sha256:b580e71cac3f8113d3135888770903eaf2f507e9421e5697d6ee6d8cd1c7f054 \ - --hash=sha256:b6a6f620cfe13ccec221fa312139135166e47ae169f8253f72a0abc0dae94376 \ - --hash=sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7 \ - --hash=sha256:b85b982afde6df99ecc996990d4ad7ccbdbb70e2a4ba4de0aecde5922ba98a0b \ - --hash=sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb \ - --hash=sha256:ba440ae430c00eee41509353628600212112cd5018d5def7e9b05ea7ac34eb65 \ - --hash=sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784 \ - --hash=sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71 \ - --hash=sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b \ - --hash=sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a \ - --hash=sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c \ - --hash=sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face \ - --hash=sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d \ - --hash=sha256:c7bd6683587567e5a49ee6e336e0612bec8329be1b7d4c8af5687dcdeb67ee1e \ - --hash=sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e \ - --hash=sha256:cb95a9b1adaa48e41815a55ae740cfda005758104049a640a398120bf02515ca \ - --hash=sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9 \ - --hash=sha256:d332fc2e3c94dad927f2112395772a4e4fedbcf8f80efc21ed7cdfae4d574fdb \ - --hash=sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95 \ - --hash=sha256:d5372ca1df0f91a86b047d1277c2aaf1edb32d78bbcefffc81b40ffd18f027ed \ - --hash=sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf \ - --hash=sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca \ - --hash=sha256:dd7afd3f8b0bfb4e0d9fc3c31bfe8a4ec7debe124cfd90619305def3c8ca8cd2 \ - --hash=sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62 \ - --hash=sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df \ - --hash=sha256:e1b329cb8146d7b736677a2440e422eadd775d1806a81db2d4cded80a48efc1a \ - --hash=sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67 \ - --hash=sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f \ - --hash=sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529 \ - --hash=sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486 \ - --hash=sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a \ - --hash=sha256:e6438cc8f23a9c1478633d216b16104a586b9761db62bfacb6425bac0a36679e \ - --hash=sha256:e81fda2fb4a07eda1a2252b216aa0df23ebcd4d584894e9612e80999a78fd95b \ - --hash=sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74 \ - --hash=sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d \ - --hash=sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b \ - --hash=sha256:f0d97c18dfd9a9af4490631905a3f131a8e4c9e80a39353919e2cfed8f00aedc \ - --hash=sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2 \ - --hash=sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e \ - --hash=sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8 \ - --hash=sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82 \ - --hash=sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd \ - --hash=sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249 +yarl==1.23.0 \ + --hash=sha256:03214408cfa590df47728b84c679ae4ef00be2428e11630277be0727eba2d7cc \ + --hash=sha256:041b1a4cefacf65840b4e295c6985f334ba83c30607441ae3cf206a0eed1a2e4 \ + --hash=sha256:0793e2bd0cf14234983bbb371591e6bea9e876ddf6896cdcc93450996b0b5c85 \ + --hash=sha256:0e1fdaa14ef51366d7757b45bde294e95f6c8c049194e793eedb8387c86d5993 \ + --hash=sha256:0e40111274f340d32ebcc0a5668d54d2b552a6cca84c9475859d364b380e3222 \ + --hash=sha256:115136c4a426f9da976187d238e84139ff6b51a20839aa6e3720cd1026d768de \ + --hash=sha256:13a563739ae600a631c36ce096615fe307f131344588b0bc0daec108cdb47b25 \ + --hash=sha256:16c6994ac35c3e74fb0ae93323bf8b9c2a9088d55946109489667c510a7d010e \ + --hash=sha256:170e26584b060879e29fac213e4228ef063f39128723807a312e5c7fec28eff2 \ + --hash=sha256:17235362f580149742739cc3828b80e24029d08cbb9c4bda0242c7b5bc610a8e \ + --hash=sha256:1932b6b8bba8d0160a9d1078aae5838a66039e8832d41d2992daa9a3a08f7860 \ + --hash=sha256:1b6b572edd95b4fa8df75de10b04bc81acc87c1c7d16bcdd2035b09d30acc957 \ + --hash=sha256:1c3a3598a832590c5a3ce56ab5576361b5688c12cb1d39429cf5dba30b510760 \ + --hash=sha256:1c57676bdedc94cd3bc37724cf6f8cd2779f02f6aba48de45feca073e714fe52 \ + --hash=sha256:1dc702e42d0684f42d6519c8d581e49c96cefaaab16691f03566d30658ee8788 \ + --hash=sha256:21d1b7305a71a15b4794b5ff22e8eef96ff4a6d7f9657155e5aa419444b28912 \ + --hash=sha256:23f371bd662cf44a7630d4d113101eafc0cfa7518a2760d20760b26021454719 \ + --hash=sha256:2569b67d616eab450d262ca7cb9f9e19d2f718c70a8b88712859359d0ab17035 \ + --hash=sha256:263cd4f47159c09b8b685890af949195b51d1aa82ba451c5847ca9bc6413c220 \ + --hash=sha256:2803ed8b21ca47a43da80a6fd1ed3019d30061f7061daa35ac54f63933409412 \ + --hash=sha256:2a6940a074fb3c48356ed0158a3ca5699c955ee4185b4d7d619be3c327143e05 \ + --hash=sha256:2e27c8841126e017dd2a054a95771569e6070b9ee1b133366d8b31beb5018a41 \ + --hash=sha256:31c9921eb8bd12633b41ad27686bbb0b1a2a9b8452bfdf221e34f311e9942ed4 \ + --hash=sha256:34b6cf500e61c90f305094911f9acc9c86da1a05a7a3f5be9f68817043f486e4 \ + --hash=sha256:3650dc2480f94f7116c364096bc84b1d602f44224ef7d5c7208425915c0475dd \ + --hash=sha256:389871e65468400d6283c0308e791a640b5ab5c83bcee02a2f51295f95e09748 \ + --hash=sha256:39004f0ad156da43e86aa71f44e033de68a44e5a31fc53507b36dd253970054a \ + --hash=sha256:394906945aa8b19fc14a61cf69743a868bb8c465efe85eee687109cc540b98f4 \ + --hash=sha256:3ceb13c5c858d01321b5d9bb65e4cf37a92169ea470b70fec6f236b2c9dd7e34 \ + --hash=sha256:411225bae281f114067578891bc75534cfb3d92a3b4dfef7a6ca78ba354e6069 \ + --hash=sha256:44bb7bef4ea409384e3f8bc36c063d77ea1b8d4a5b2706956c0d6695f07dcc25 \ + --hash=sha256:4503053d296bc6e4cbd1fad61cf3b6e33b939886c4f249ba7c78b602214fabe2 \ + --hash=sha256:4764a6a7588561a9aef92f65bda2c4fb58fe7c675c0883862e6df97559de0bfb \ + --hash=sha256:4966242ec68afc74c122f8459abd597afd7d8a60dc93d695c1334c5fd25f762f \ + --hash=sha256:4a42e651629dafb64fd5b0286a3580613702b5809ad3f24934ea87595804f2c5 \ + --hash=sha256:4a59ba56f340334766f3a4442e0efd0af895fae9e2b204741ef885c446b3a1a8 \ + --hash=sha256:4c41e021bc6d7affb3364dc1e1e5fa9582b470f283748784bd6ea0558f87f42c \ + --hash=sha256:5023346c4ee7992febc0068e7593de5fa2bf611848c08404b35ebbb76b1b0512 \ + --hash=sha256:50f9d8d531dfb767c565f348f33dd5139a6c43f5cbdf3f67da40d54241df93f6 \ + --hash=sha256:51430653db848d258336cfa0244427b17d12db63d42603a55f0d4546f50f25b5 \ + --hash=sha256:531ef597132086b6cf96faa7c6c1dcd0361dd5f1694e5cc30375907b9b7d3ea9 \ + --hash=sha256:53ad387048f6f09a8969631e4de3f1bf70c50e93545d64af4f751b2498755072 \ + --hash=sha256:53b1ea6ca88ebd4420379c330aea57e258408dd0df9af0992e5de2078dc9f5d5 \ + --hash=sha256:575aa4405a656e61a540f4a80eaa5260f2a38fff7bfdc4b5f611840d76e9e277 \ + --hash=sha256:578110dd426f0d209d1509244e6d4a3f1a3e9077655d98c5f22583d63252a08a \ + --hash=sha256:5ec2f42d41ccbd5df0270d7df31618a8ee267bfa50997f5d720ddba86c4a83a6 \ + --hash=sha256:5ee586fb17ff8f90c91cf73c6108a434b02d69925f44f5f8e0d7f2f260607eae \ + --hash=sha256:5f10fd85e4b75967468af655228fbfd212bdf66db1c0d135065ce288982eda26 \ + --hash=sha256:609d3614d78d74ebe35f54953c5bbd2ac647a7ddb9c30a5d877580f5e86b22f2 \ + --hash=sha256:62694e275c93d54f7ccedcfef57d42761b2aad5234b6be1f3e3026cae4001cd4 \ + --hash=sha256:63e92247f383c85ab00dd0091e8c3fa331a96e865459f5ee80353c70a4a42d70 \ + --hash=sha256:682bae25f0a0dd23a056739f23a134db9f52a63e2afd6bfb37ddc76292bbd723 \ + --hash=sha256:6b41389c19b07c760c7e427a3462e8ab83c4bb087d127f0e854c706ce1b9215c \ + --hash=sha256:6e87a6e8735b44816e7db0b2fbc9686932df473c826b0d9743148432e10bb9b9 \ + --hash=sha256:6f0fd84de0c957b2d280143522c4f91a73aada1923caee763e24a2b3fda9f8a5 \ + --hash=sha256:70efd20be968c76ece7baa8dafe04c5be06abc57f754d6f36f3741f7aa7a208e \ + --hash=sha256:71d006bee8397a4a89f469b8deb22469fe7508132d3c17fa6ed871e79832691c \ + --hash=sha256:73309162a6a571d4cbd3b6a1dcc703c7311843ae0d1578df6f09be4e98df38d4 \ + --hash=sha256:75e3026ab649bf48f9a10c0134512638725b521340293f202a69b567518d94e0 \ + --hash=sha256:76855800ac56f878847a09ce6dba727c93ca2d89c9e9d63002d26b916810b0a2 \ + --hash=sha256:7c6b9461a2a8b47c65eef63bb1c76a4f1c119618ffa99ea79bc5bb1e46c5821b \ + --hash=sha256:803a3c3ce4acc62eaf01eaca1208dcf0783025ef27572c3336502b9c232005e7 \ + --hash=sha256:80e6d33a3d42a7549b409f199857b4fb54e2103fc44fb87605b6663b7a7ff750 \ + --hash=sha256:8419ebd326430d1cbb7efb5292330a2cf39114e82df5cc3d83c9a0d5ebeaf2f2 \ + --hash=sha256:85610b4f27f69984932a7abbe52703688de3724d9f72bceb1cca667deff27474 \ + --hash=sha256:85e9beda1f591bc73e77ea1c51965c68e98dafd0fec72cdd745f77d727466716 \ + --hash=sha256:877b0738624280e34c55680d6054a307aa94f7d52fa0e3034a9cc6e790871da7 \ + --hash=sha256:88f9fb0116fbfcefcab70f85cf4b74a2b6ce5d199c41345296f49d974ddb4123 \ + --hash=sha256:8c4fe09e0780c6c3bf2b7d4af02ee2394439d11a523bbcf095cf4747c2932007 \ + --hash=sha256:93a784271881035ab4406a172edb0faecb6e7d00f4b53dc2f55919d6c9688595 \ + --hash=sha256:94f8575fbdf81749008d980c17796097e645574a3b8c28ee313931068dad14fe \ + --hash=sha256:95451e6ce06c3e104556d73b559f5da6c34a069b6b62946d3ad66afcd51642ea \ + --hash=sha256:99c8a9ed30f4164bc4c14b37a90208836cbf50d4ce2a57c71d0f52c7fb4f7598 \ + --hash=sha256:9a18d6f9359e45722c064c97464ec883eb0e0366d33eda61cb19a244bf222679 \ + --hash=sha256:9cbf44c5cb4a7633d078788e1b56387e3d3cf2b8139a3be38040b22d6c3221c8 \ + --hash=sha256:9ee33b875f0b390564c1fb7bc528abf18c8ee6073b201c6ae8524aca778e2d83 \ + --hash=sha256:a0e317df055958a0c1e79e5d2aa5a5eaa4a6d05a20d4b0c9c3f48918139c9fc6 \ + --hash=sha256:a2df6afe50dea8ae15fa34c9f824a3ee958d785fd5d089063d960bae1daa0a3f \ + --hash=sha256:a31de1613658308efdb21ada98cbc86a97c181aa050ba22a808120bb5be3ab94 \ + --hash=sha256:a3d2bff8f37f8d0f96c7ec554d16945050d54462d6e95414babaa18bfafc7f51 \ + --hash=sha256:a41bcf68efd19073376eb8cf948b8d9be0af26256403e512bb18f3966f1f9120 \ + --hash=sha256:a82836cab5f197a0514235aaf7ffccdc886ccdaa2324bc0aafdd4ae898103039 \ + --hash=sha256:a8d00f29b42f534cc8aa3931cfe773b13b23e561e10d2b26f27a8d309b0e82a1 \ + --hash=sha256:aafe5dcfda86c8af00386d7781d4c2181b5011b7be3f2add5e99899ea925df05 \ + --hash=sha256:ab5f043cb8a2d71c981c09c510da013bc79fd661f5c60139f00dd3c3cc4f2ffb \ + --hash=sha256:ac09d42f48f80c9ee1635b2fcaa819496a44502737660d3c0f2ade7526d29144 \ + --hash=sha256:aecfed0b41aa72b7881712c65cf764e39ce2ec352324f5e0837c7048d9e6daaa \ + --hash=sha256:b2c6b50c7b0464165472b56b42d4c76a7b864597007d9c085e8b63e185cf4a7a \ + --hash=sha256:b35d13d549077713e4414f927cdc388d62e543987c572baee613bf82f11a4b99 \ + --hash=sha256:b39cb32a6582750b6cc77bfb3c49c0f8760dc18dc96ec9fb55fbb0f04e08b928 \ + --hash=sha256:b5405bb8f0e783a988172993cfc627e4d9d00432d6bbac65a923041edacf997d \ + --hash=sha256:baaf55442359053c7d62f6f8413a62adba3205119bcb6f49594894d8be47e5e3 \ + --hash=sha256:bd654fad46d8d9e823afbb4f87c79160b5a374ed1ff5bde24e542e6ba8f41434 \ + --hash=sha256:be61f6fff406ca40e3b1d84716fde398fc08bc63dd96d15f3a14230a0973ed86 \ + --hash=sha256:bf49a3ae946a87083ef3a34c8f677ae4243f5b824bfc4c69672e72b3d6719d46 \ + --hash=sha256:c4a80f77dc1acaaa61f0934176fccca7096d9b1ff08c8ba9cddf5ae034a24319 \ + --hash=sha256:c75eb09e8d55bceb4367e83496ff8ef2bc7ea6960efb38e978e8073ea59ecb67 \ + --hash=sha256:c7f8dc16c498ff06497c015642333219871effba93e4a2e8604a06264aca5c5c \ + --hash=sha256:c8aa34a5c864db1087d911a0b902d60d203ea3607d91f615acd3f3108ac32169 \ + --hash=sha256:cbb0fef01f0c6b38cb0f39b1f78fc90b807e0e3c86a7ff3ce74ad77ce5c7880c \ + --hash=sha256:cde9a2ecd91668bcb7f077c4966d8ceddb60af01b52e6e3e2680e4cf00ad1a59 \ + --hash=sha256:cff6d44cb13d39db2663a22b22305d10855efa0fa8015ddeacc40bc59b9d8107 \ + --hash=sha256:d1009abedb49ae95b136a8904a3f71b342f849ffeced2d3747bf29caeda218c4 \ + --hash=sha256:d38c1e8231722c4ce40d7593f28d92b5fc72f3e9774fe73d7e800ec32299f63a \ + --hash=sha256:d53834e23c015ee83a99377db6e5e37d8484f333edb03bd15b4bc312cc7254fb \ + --hash=sha256:d7504f2b476d21653e4d143f44a175f7f751cd41233525312696c76aa3dbb23f \ + --hash=sha256:dbf507e9ef5688bada447a24d68b4b58dd389ba93b7afc065a2ba892bea54769 \ + --hash=sha256:dc52310451fc7c629e13c4e061cbe2dd01684d91f2f8ee2821b083c58bd72432 \ + --hash=sha256:dd00607bffbf30250fe108065f07453ec124dbf223420f57f5e749b04295e090 \ + --hash=sha256:dda608c88cf709b1d406bdfcd84d8d63cff7c9e577a403c6108ce8ce9dcc8764 \ + --hash=sha256:debe9c4f41c32990771be5c22b56f810659f9ddf3d63f67abfdcaa2c6c9c5c1d \ + --hash=sha256:e09fd068c2e169a7070d83d3bde728a4d48de0549f975290be3c108c02e499b4 \ + --hash=sha256:e0fd068364a6759bc794459f0a735ab151d11304346332489c7972bacbe9e72b \ + --hash=sha256:e4c53f8347cd4200f0d70a48ad059cabaf24f5adc6ba08622a23423bc7efa10d \ + --hash=sha256:e5723c01a56c5028c807c701aa66722916d2747ad737a046853f6c46f4875543 \ + --hash=sha256:e7b0460976dc75cb87ad9cc1f9899a4b97751e7d4e77ab840fc9b6d377b8fd24 \ + --hash=sha256:e9d9a4d06d3481eab79803beb4d9bd6f6a8e781ec078ac70d7ef2dcc29d1bea5 \ + --hash=sha256:ead11956716a940c1abc816b7df3fa2b84d06eaed8832ca32f5c5e058c65506b \ + --hash=sha256:ed5f69ce7be7902e5c70ea19eb72d20abf7d725ab5d49777d696e32d4fc1811d \ + --hash=sha256:f2af5c81a1f124609d5f33507082fc3f739959d4719b56877ab1ee7e7b3d602b \ + --hash=sha256:f40e782d49630ad384db66d4d8b73ff4f1b8955dc12e26b09a3e3af064b3b9d6 \ + --hash=sha256:f514f6474e04179d3d33175ed3f3e31434d3130d42ec153540d5b157deefd735 \ + --hash=sha256:f69f57305656a4852f2a7203efc661d8c042e6cc67f7acd97d8667fb448a426e \ + --hash=sha256:fb1e8b8d66c278b21d13b0a7ca22c41dd757a7c209c6b12c313e445c31dd3b28 \ + --hash=sha256:fb4948814a2a98e3912505f09c9e7493b1506226afb1f881825368d6fb776ee3 \ + --hash=sha256:fda207c815b253e34f7e1909840fd14299567b1c0eb4908f8c2ce01a41265401 \ + --hash=sha256:fe8f8f5e70e6dbdfca9882cd9deaac058729bcf323cf7a58660901e55c9c94f6 \ + --hash=sha256:fffc45637bcd6538de8b85f51e3df3223e4ad89bccbfca0481c08c7fc8b7ed7d # via aiohttp zipp==3.23.0 \ --hash=sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e \ diff --git a/sdk/python/requirements/py3.10-minimal-requirements.txt b/sdk/python/requirements/py3.10-minimal-requirements.txt index 0a281d5e653..aafdc1baddc 100644 --- a/sdk/python/requirements/py3.10-minimal-requirements.txt +++ b/sdk/python/requirements/py3.10-minimal-requirements.txt @@ -8,127 +8,127 @@ aiohappyeyeballs==2.6.1 \ --hash=sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558 \ --hash=sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8 # via aiohttp -aiohttp==3.13.3 \ - --hash=sha256:01ad2529d4b5035578f5081606a465f3b814c542882804e2e8cda61adf5c71bf \ - --hash=sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c \ - --hash=sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c \ - --hash=sha256:084911a532763e9d3dd95adf78a78f4096cd5f58cdc18e6fdbc1b58417a45423 \ - --hash=sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f \ - --hash=sha256:0db318f7a6f065d84cb1e02662c526294450b314a02bd9e2a8e67f0d8564ce40 \ - --hash=sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2 \ - --hash=sha256:1449ceddcdbcf2e0446957863af03ebaaa03f94c090f945411b61269e2cb5daf \ - --hash=sha256:147e422fd1223005c22b4fe080f5d93ced44460f5f9c105406b753612b587821 \ - --hash=sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64 \ - --hash=sha256:215a685b6fbbfcf71dfe96e3eba7a6f58f10da1dfdf4889c7dd856abe430dca7 \ - --hash=sha256:2712039939ec963c237286113c68dbad80a82a4281543f3abf766d9d73228998 \ - --hash=sha256:27234ef6d85c914f9efeb77ff616dbf4ad2380be0cda40b4db086ffc7ddd1b7d \ - --hash=sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea \ - --hash=sha256:2b8d8ddba8f95ba17582226f80e2de99c7a7948e66490ef8d947e272a93e9463 \ - --hash=sha256:2ba0eea45eb5cc3172dbfc497c066f19c41bac70963ea1a67d51fc92e4cf9a80 \ - --hash=sha256:2be0e9ccf23e8a94f6f0650ce06042cefc6ac703d0d7ab6c7a917289f2539ad4 \ - --hash=sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767 \ - --hash=sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43 \ - --hash=sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592 \ - --hash=sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a \ - --hash=sha256:31a83ea4aead760dfcb6962efb1d861db48c34379f2ff72db9ddddd4cda9ea2e \ - --hash=sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687 \ - --hash=sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8 \ - --hash=sha256:37239e9f9a7ea9ac5bf6b92b0260b01f8a22281996da609206a84df860bc1261 \ - --hash=sha256:37da61e244d1749798c151421602884db5270faf479cf0ef03af0ff68954c9dd \ - --hash=sha256:3b61b7169ababd7802f9568ed96142616a9118dd2be0d1866e920e77ec8fa92a \ - --hash=sha256:3d9908a48eb7416dc1f4524e69f1d32e5d90e3981e4e37eb0aa1cd18f9cfa2a4 \ - --hash=sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587 \ - --hash=sha256:4021b51936308aeea0367b8f006dc999ca02bc118a0cc78c303f50a2ff6afb91 \ - --hash=sha256:40c5e40ecc29ba010656c18052b877a1c28f84344825efa106705e835c28530f \ - --hash=sha256:425c126c0dc43861e22cb1c14ba4c8e45d09516d0a3ae0a3f7494b79f5f233a3 \ - --hash=sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344 \ - --hash=sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6 \ - --hash=sha256:49a03727c1bba9a97d3e93c9f93ca03a57300f484b6e935463099841261195d3 \ - --hash=sha256:4ae5b5a0e1926e504c81c5b84353e7a5516d8778fbbff00429fe7b05bb25cbce \ - --hash=sha256:4e239d501f73d6db1522599e14b9b321a7e3b1de66ce33d53a765d975e9f4808 \ - --hash=sha256:56339a36b9f1fc708260c76c87e593e2afb30d26de9ae1eb445b5e051b98a7a1 \ - --hash=sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29 \ - --hash=sha256:5b179331a481cb5529fca8b432d8d3c7001cb217513c94cd72d668d1248688a3 \ - --hash=sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b \ - --hash=sha256:5d2d94f1f5fcbe40838ac51a6ab5704a6f9ea42e72ceda48de5e6b898521da51 \ - --hash=sha256:5dff64413671b0d3e7d5918ea490bdccb97a4ad29b3f311ed423200b2203e01c \ - --hash=sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926 \ - --hash=sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64 \ - --hash=sha256:642f752c3eb117b105acbd87e2c143de710987e09860d674e068c4c2c441034f \ - --hash=sha256:65d2ccb7eabee90ce0503c17716fc77226be026dcc3e65cce859a30db715025b \ - --hash=sha256:693781c45a4033d31d4187d2436f5ac701e7bbfe5df40d917736108c1cc7436e \ - --hash=sha256:694976222c711d1d00ba131904beb60534f93966562f64440d0c9d41b8cdb440 \ - --hash=sha256:697753042d57f4bf7122cab985bf15d0cef23c770864580f5af4f52023a56bd6 \ - --hash=sha256:69c56fbc1993fa17043e24a546959c0178fe2b5782405ad4559e6c13975c15e3 \ - --hash=sha256:6de499a1a44e7de70735d0b39f67c8f25eb3d91eb3103be99ca0fa882cdd987d \ - --hash=sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415 \ - --hash=sha256:75ca857eba4e20ce9f546cd59c7007b33906a4cd48f2ff6ccf1ccfc3b646f279 \ - --hash=sha256:7a4a94eb787e606d0a09404b9c38c113d3b099d508021faa615d70a0131907ce \ - --hash=sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603 \ - --hash=sha256:7bfdc049127717581866fa4708791220970ce291c23e28ccf3922c700740fdc0 \ - --hash=sha256:7e63f210bc1b57ef699035f2b4b6d9ce096b5914414a49b0997c839b2bd2223c \ - --hash=sha256:7f9120f7093c2a32d9647abcaf21e6ad275b4fbec5b55969f978b1a97c7c86bf \ - --hash=sha256:8057c98e0c8472d8846b9c79f56766bcc57e3e8ac7bfd510482332366c56c591 \ - --hash=sha256:80dd4c21b0f6237676449c6baaa1039abae86b91636b6c91a7f8e61c87f89540 \ - --hash=sha256:81e97251d9298386c2b7dbeb490d3d1badbdc69107fb8c9299dd04eb39bddc0e \ - --hash=sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26 \ - --hash=sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a \ - --hash=sha256:859bd3f2156e81dd01432f5849fc73e2243d4a487c4fd26609b1299534ee1845 \ - --hash=sha256:87797e645d9d8e222e04160ee32aa06bc5c163e8499f24db719e7852ec23093a \ - --hash=sha256:87b9aab6d6ed88235aa2970294f496ff1a1f9adcd724d800e9b952395a80ffd9 \ - --hash=sha256:8a60e60746623925eab7d25823329941aee7242d559baa119ca2b253c88a7bd6 \ - --hash=sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba \ - --hash=sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df \ - --hash=sha256:947c26539750deeaee933b000fb6517cc770bbd064bad6033f1cff4803881e43 \ - --hash=sha256:96d604498a7c782cb15a51c406acaea70d8c027ee6b90c569baa6e7b93073679 \ - --hash=sha256:988a8c5e317544fdf0d39871559e67b6341065b87fceac641108c2096d5506b7 \ - --hash=sha256:9a9dc347e5a3dc7dfdbc1f82da0ef29e388ddb2ed281bfce9dd8248a313e62b7 \ - --hash=sha256:9ae8dd55c8e6c4257eae3a20fd2c8f41edaea5992ed67156642493b8daf3cecc \ - --hash=sha256:9af5e68ee47d6534d36791bbe9b646d2a7c7deb6fc24d7943628edfbb3581f29 \ - --hash=sha256:9b174f267b5cfb9a7dba9ee6859cecd234e9a681841eb85068059bc867fb8f02 \ - --hash=sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984 \ - --hash=sha256:9d4c940f02f49483b18b079d1c27ab948721852b281f8b015c058100e9421dd1 \ - --hash=sha256:9ebf57d09e131f5323464bd347135a88622d1c0976e88ce15b670e7ad57e4bd6 \ - --hash=sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632 \ - --hash=sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56 \ - --hash=sha256:a2212ad43c0833a873d0fb3c63fa1bacedd4cf6af2fee62bf4b739ceec3ab239 \ - --hash=sha256:a45530014d7a1e09f4a55f4f43097ba0fd155089372e105e4bff4ca76cb1b168 \ - --hash=sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88 \ - --hash=sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc \ - --hash=sha256:af71fff7bac6bb7508956696dce8f6eec2bbb045eceb40343944b1ae62b5ef11 \ - --hash=sha256:b04be762396457bef43f3597c991e192ee7da460a4953d7e647ee4b1c28e7046 \ - --hash=sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0 \ - --hash=sha256:b1a6102b4d3ebc07dad44fbf07b45bb600300f15b552ddf1851b5390202ea2e3 \ - --hash=sha256:b46020d11d23fe16551466c77823df9cc2f2c1e63cc965daf67fa5eec6ca1877 \ - --hash=sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1 \ - --hash=sha256:b903a4dfee7d347e2d87697d0713be59e0b87925be030c9178c5faa58ea58d5c \ - --hash=sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25 \ - --hash=sha256:b99281b0704c103d4e11e72a76f1b543d4946fea7dd10767e7e1b5f00d4e5704 \ - --hash=sha256:bae5c2ed2eae26cc382020edad80d01f36cb8e746da40b292e68fec40421dc6a \ - --hash=sha256:bb4f7475e359992b580559e008c598091c45b5088f28614e855e42d39c2f1033 \ - --hash=sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1 \ - --hash=sha256:bfc1cc2fe31a6026a8a88e4ecfb98d7f6b1fec150cfd708adbfd1d2f42257c29 \ - --hash=sha256:c014c7ea7fb775dd015b2d3137378b7be0249a448a1612268b5a90c2d81de04d \ - --hash=sha256:c048058117fd649334d81b4b526e94bde3ccaddb20463a815ced6ecbb7d11160 \ - --hash=sha256:c0e2d366af265797506f0283487223146af57815b388623f0357ef7eac9b209d \ - --hash=sha256:c19b90316ad3b24c69cd78d5c9b4f3aa4497643685901185b65166293d36a00f \ - --hash=sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f \ - --hash=sha256:c6b8568a3bb5819a0ad087f16d40e5a3fb6099f39ea1d5625a3edc1e923fc538 \ - --hash=sha256:d32764c6c9aafb7fb55366a224756387cd50bfa720f32b88e0e6fa45b27dcf29 \ - --hash=sha256:d5a372fd5afd301b3a89582817fdcdb6c34124787c70dbcc616f259013e7eef7 \ - --hash=sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72 \ - --hash=sha256:dca68018bf48c251ba17c72ed479f4dafe9dbd5a73707ad8d28a38d11f3d42af \ - --hash=sha256:de2c184bb1fe2cbd2cefba613e9db29a5ab559323f994b6737e370d3da0ac455 \ - --hash=sha256:e3531d63d3bdfa7e3ac5e9b27b2dd7ec9df3206a98e0b3445fa906f233264c57 \ - --hash=sha256:e50a2e1404f063427c9d027378472316201a2290959a295169bcf25992d04558 \ - --hash=sha256:e636b3c5f61da31a92bf0d91da83e58fdfa96f178ba682f11d24f31944cdd28c \ - --hash=sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808 \ - --hash=sha256:f33ed1a2bf1997a36661874b017f5c4b760f41266341af36febaf271d179f6d7 \ - --hash=sha256:f76c1e3fe7d7c8afad7ed193f89a292e1999608170dcc9751a7462a87dfd5bc0 \ - --hash=sha256:f9444f105664c4ce47a2a7171a2418bce5b7bae45fb610f4e2c36045d85911d3 \ - --hash=sha256:fc290605db2a917f6e81b0e1e0796469871f5af381ce15c604a3c5c7e51cb730 \ - --hash=sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa \ - --hash=sha256:fee0c6bc7db1de362252affec009707a17478a00ec69f797d23ca256e36d5940 +aiohttp==3.13.5 \ + --hash=sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5 \ + --hash=sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b \ + --hash=sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9 \ + --hash=sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b \ + --hash=sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8 \ + --hash=sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a \ + --hash=sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2 \ + --hash=sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1 \ + --hash=sha256:147b4f501d0292077f29d5268c16bb7c864a1f054d7001c4c1812c0421ea1ed0 \ + --hash=sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037 \ + --hash=sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416 \ + --hash=sha256:178c7b5e62b454c2bc790786e6058c3cc968613b4419251b478c153a4aec32b1 \ + --hash=sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9 \ + --hash=sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a \ + --hash=sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36 \ + --hash=sha256:206b7b3ef96e4ce211754f0cd003feb28b7d81f0ad26b8d077a5d5161436067f \ + --hash=sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b \ + --hash=sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174 \ + --hash=sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b \ + --hash=sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8 \ + --hash=sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e \ + --hash=sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6 \ + --hash=sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c \ + --hash=sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe \ + --hash=sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9 \ + --hash=sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc \ + --hash=sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800 \ + --hash=sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286 \ + --hash=sha256:347542f0ea3f95b2a955ee6656461fa1c776e401ac50ebce055a6c38454a0adf \ + --hash=sha256:39380e12bd1f2fdab4285b6e055ad48efbaed5c836433b142ed4f5b9be71036a \ + --hash=sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc \ + --hash=sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9 \ + --hash=sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665 \ + --hash=sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832 \ + --hash=sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297 \ + --hash=sha256:4e704c52438f66fdd89588346183d898bb42167cf88f8b7ff1c0f9fc957c348f \ + --hash=sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73 \ + --hash=sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b \ + --hash=sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9 \ + --hash=sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090 \ + --hash=sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49 \ + --hash=sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d \ + --hash=sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46 \ + --hash=sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83 \ + --hash=sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796 \ + --hash=sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be \ + --hash=sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d \ + --hash=sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf \ + --hash=sha256:6f497a6876aa4b1a102b04996ce4c1170c7040d83faa9387dd921c16e30d5c83 \ + --hash=sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25 \ + --hash=sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06 \ + --hash=sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3 \ + --hash=sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6 \ + --hash=sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb \ + --hash=sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88 \ + --hash=sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9 \ + --hash=sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be \ + --hash=sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14 \ + --hash=sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a \ + --hash=sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c \ + --hash=sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3 \ + --hash=sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f \ + --hash=sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d \ + --hash=sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670 \ + --hash=sha256:912d4b6af530ddb1338a66229dac3a25ff11d4448be3ec3d6340583995f56031 \ + --hash=sha256:9277145d36a01653863899c665243871434694bcc3431922c3b35c978061bdb8 \ + --hash=sha256:95d14ca7abefde230f7639ec136ade282655431fd5db03c343b19dda72dd1643 \ + --hash=sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d \ + --hash=sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8 \ + --hash=sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8 \ + --hash=sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1 \ + --hash=sha256:9efcc0f11d850cefcafdd9275b9576ad3bfb539bed96807663b32ad99c4d4b88 \ + --hash=sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb \ + --hash=sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61 \ + --hash=sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4 \ + --hash=sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7 \ + --hash=sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9 \ + --hash=sha256:a8a4d3427e8de1312ddf309cc482186466c79895b3a139fed3259fc01dfa9a5b \ + --hash=sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500 \ + --hash=sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6 \ + --hash=sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2 \ + --hash=sha256:af545c2cffdb0967a96b6249e6f5f7b0d92cdfd267f9d5238d5b9ca63e8edb10 \ + --hash=sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1 \ + --hash=sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3 \ + --hash=sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e \ + --hash=sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a \ + --hash=sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5 \ + --hash=sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95 \ + --hash=sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074 \ + --hash=sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5 \ + --hash=sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b \ + --hash=sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772 \ + --hash=sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a \ + --hash=sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274 \ + --hash=sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94 \ + --hash=sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13 \ + --hash=sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac \ + --hash=sha256:cb979826071c0986a5f08333a36104153478ce6018c58cba7f9caddaf63d5d67 \ + --hash=sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76 \ + --hash=sha256:d147004fede1b12f6013a6dbb2a26a986a671a03c6ea740ddc76500e5f1c399f \ + --hash=sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8 \ + --hash=sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7 \ + --hash=sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8 \ + --hash=sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3 \ + --hash=sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be \ + --hash=sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b \ + --hash=sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c \ + --hash=sha256:e999f0c88a458c836d5fb521814e92ed2172c649200336a6df514987c1488258 \ + --hash=sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c \ + --hash=sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6 \ + --hash=sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56 \ + --hash=sha256:ee5e86776273de1795947d17bddd6bb19e0365fd2af4289c0d2c5454b6b1d36b \ + --hash=sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d \ + --hash=sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a \ + --hash=sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162 \ + --hash=sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1 \ + --hash=sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6 \ + --hash=sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5 \ + --hash=sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540 \ + --hash=sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254 # via aiobotocore aioitertools==0.13.0 \ --hash=sha256:0be0292b856f08dfac90e31f4739432f4cb6d7520ab9eb73e143f4f2fa5259be \ @@ -148,9 +148,9 @@ annotated-types==0.7.0 \ --hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \ --hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89 # via pydantic -anyio==4.12.1 \ - --hash=sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703 \ - --hash=sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c +anyio==4.13.0 \ + --hash=sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708 \ + --hash=sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc # via # httpx # mcp @@ -171,16 +171,16 @@ atpublic==7.0.0 \ --hash=sha256:466ef10d0c8bbd14fd02a5fbd5a8b6af6a846373d91106d3a07c16d72d96b63e \ --hash=sha256:6702bd9e7245eb4e8220a3e222afcef7f87412154732271ee7deee4433b72b4b # via ibis-framework -attrs==25.4.0 \ - --hash=sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11 \ - --hash=sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373 +attrs==26.1.0 \ + --hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \ + --hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32 # via # aiohttp # jsonschema # referencing -bigtree==1.3.1 \ - --hash=sha256:a22a0ecd9b0abb283f4a1515370dbf1ec93adee70746767272e2c49d7af9f407 \ - --hash=sha256:c8b766b00188c532d3499bfd9e9666b357428db507fc701f088031a0d5c614d5 +bigtree==1.4.0 \ + --hash=sha256:d0d99550ae64ce4529f132602ab875c2ab472c96c942f5704f8c72a17450d3ea \ + --hash=sha256:e5ae2e948168da671d99601c9ed87ab3b48d9d4ea8a98f111e5748e98064c31c # via feast (pyproject.toml) boto3==1.38.27 \ --hash=sha256:94bd7fdd92d5701b362d4df100d21e28f8307a67ff56b6a8b0398119cf22f859 \ @@ -196,9 +196,9 @@ botocore==1.38.46 \ # boto3 # s3transfer # snowflake-connector-python -certifi==2026.1.4 \ - --hash=sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c \ - --hash=sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120 +certifi==2026.2.25 \ + --hash=sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa \ + --hash=sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7 # via # httpcore # httpx @@ -293,120 +293,136 @@ cffi==2.0.0 \ # via # feast (pyproject.toml) # cryptography -charset-normalizer==3.4.4 \ - --hash=sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad \ - --hash=sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93 \ - --hash=sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394 \ - --hash=sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89 \ - --hash=sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc \ - --hash=sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86 \ - --hash=sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63 \ - --hash=sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d \ - --hash=sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f \ - --hash=sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8 \ - --hash=sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0 \ - --hash=sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505 \ - --hash=sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161 \ - --hash=sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af \ - --hash=sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152 \ - --hash=sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318 \ - --hash=sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72 \ - --hash=sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4 \ - --hash=sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e \ - --hash=sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3 \ - --hash=sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576 \ - --hash=sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c \ - --hash=sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1 \ - --hash=sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8 \ - --hash=sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1 \ - --hash=sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2 \ - --hash=sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44 \ - --hash=sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26 \ - --hash=sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88 \ - --hash=sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016 \ - --hash=sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede \ - --hash=sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf \ - --hash=sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a \ - --hash=sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc \ - --hash=sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0 \ - --hash=sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84 \ - --hash=sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db \ - --hash=sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1 \ - --hash=sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7 \ - --hash=sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed \ - --hash=sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8 \ - --hash=sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133 \ - --hash=sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e \ - --hash=sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef \ - --hash=sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14 \ - --hash=sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2 \ - --hash=sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0 \ - --hash=sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d \ - --hash=sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828 \ - --hash=sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f \ - --hash=sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf \ - --hash=sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6 \ - --hash=sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328 \ - --hash=sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090 \ - --hash=sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa \ - --hash=sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381 \ - --hash=sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c \ - --hash=sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb \ - --hash=sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc \ - --hash=sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a \ - --hash=sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec \ - --hash=sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc \ - --hash=sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac \ - --hash=sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e \ - --hash=sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313 \ - --hash=sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569 \ - --hash=sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3 \ - --hash=sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d \ - --hash=sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525 \ - --hash=sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894 \ - --hash=sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3 \ - --hash=sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9 \ - --hash=sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a \ - --hash=sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9 \ - --hash=sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14 \ - --hash=sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25 \ - --hash=sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50 \ - --hash=sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf \ - --hash=sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1 \ - --hash=sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3 \ - --hash=sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac \ - --hash=sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e \ - --hash=sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815 \ - --hash=sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c \ - --hash=sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6 \ - --hash=sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6 \ - --hash=sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e \ - --hash=sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4 \ - --hash=sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84 \ - --hash=sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69 \ - --hash=sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15 \ - --hash=sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191 \ - --hash=sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0 \ - --hash=sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897 \ - --hash=sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd \ - --hash=sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2 \ - --hash=sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794 \ - --hash=sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d \ - --hash=sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074 \ - --hash=sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3 \ - --hash=sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224 \ - --hash=sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838 \ - --hash=sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a \ - --hash=sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d \ - --hash=sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d \ - --hash=sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f \ - --hash=sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8 \ - --hash=sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490 \ - --hash=sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966 \ - --hash=sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9 \ - --hash=sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3 \ - --hash=sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e \ - --hash=sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608 +charset-normalizer==3.4.7 \ + --hash=sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc \ + --hash=sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c \ + --hash=sha256:07d9e39b01743c3717745f4c530a6349eadbfa043c7577eef86c502c15df2c67 \ + --hash=sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4 \ + --hash=sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0 \ + --hash=sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c \ + --hash=sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5 \ + --hash=sha256:12a6fff75f6bc66711b73a2f0addfc4c8c15a20e805146a02d147a318962c444 \ + --hash=sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153 \ + --hash=sha256:14265bfe1f09498b9d8ec91e9ec9fa52775edf90fcbde092b25f4a33d444fea9 \ + --hash=sha256:16d971e29578a5e97d7117866d15889a4a07befe0e87e703ed63cd90cb348c01 \ + --hash=sha256:177a0ba5f0211d488e295aaf82707237e331c24788d8d76c96c5a41594723217 \ + --hash=sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b \ + --hash=sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c \ + --hash=sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a \ + --hash=sha256:1dc8b0ea451d6e69735094606991f32867807881400f808a106ee1d963c46a83 \ + --hash=sha256:1efde3cae86c8c273f1eb3b287be7d8499420cf2fe7585c41d370d3e790054a5 \ + --hash=sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7 \ + --hash=sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb \ + --hash=sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c \ + --hash=sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1 \ + --hash=sha256:2cd4a60d0e2fb04537162c62bbbb4182f53541fe0ede35cdf270a1c1e723cc42 \ + --hash=sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab \ + --hash=sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df \ + --hash=sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e \ + --hash=sha256:320ade88cfb846b8cd6b4ddf5ee9e80ee0c1f52401f2456b84ae1ae6a1a5f207 \ + --hash=sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18 \ + --hash=sha256:36836d6ff945a00b88ba1e4572d721e60b5b8c98c155d465f56ad19d68f23734 \ + --hash=sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38 \ + --hash=sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110 \ + --hash=sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18 \ + --hash=sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44 \ + --hash=sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d \ + --hash=sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48 \ + --hash=sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e \ + --hash=sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5 \ + --hash=sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d \ + --hash=sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53 \ + --hash=sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790 \ + --hash=sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c \ + --hash=sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b \ + --hash=sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116 \ + --hash=sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d \ + --hash=sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10 \ + --hash=sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6 \ + --hash=sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2 \ + --hash=sha256:6370e8686f662e6a3941ee48ed4742317cafbe5707e36406e9df792cdb535776 \ + --hash=sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a \ + --hash=sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265 \ + --hash=sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008 \ + --hash=sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943 \ + --hash=sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374 \ + --hash=sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246 \ + --hash=sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e \ + --hash=sha256:6e0d51f618228538a3e8f46bd246f87a6cd030565e015803691603f55e12afb5 \ + --hash=sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616 \ + --hash=sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15 \ + --hash=sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41 \ + --hash=sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960 \ + --hash=sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752 \ + --hash=sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e \ + --hash=sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72 \ + --hash=sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7 \ + --hash=sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8 \ + --hash=sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b \ + --hash=sha256:813c0e0132266c08eb87469a642cb30aaff57c5f426255419572aaeceeaa7bf4 \ + --hash=sha256:82b271f5137d07749f7bf32f70b17ab6eaabedd297e75dce75081a24f76eb545 \ + --hash=sha256:84c018e49c3bf790f9c2771c45e9313a08c2c2a6342b162cd650258b57817706 \ + --hash=sha256:8751d2787c9131302398b11e6c8068053dcb55d5a8964e114b6e196cf16cb366 \ + --hash=sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb \ + --hash=sha256:87fad7d9ba98c86bcb41b2dc8dbb326619be2562af1f8ff50776a39e55721c5a \ + --hash=sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e \ + --hash=sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00 \ + --hash=sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f \ + --hash=sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a \ + --hash=sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1 \ + --hash=sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66 \ + --hash=sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356 \ + --hash=sha256:a6c5863edfbe888d9eff9c8b8087354e27618d9da76425c119293f11712a6319 \ + --hash=sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4 \ + --hash=sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad \ + --hash=sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d \ + --hash=sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5 \ + --hash=sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7 \ + --hash=sha256:aef65cd602a6d0e0ff6f9930fcb1c8fec60dd2cfcb6facaf4bdb0e5873042db0 \ + --hash=sha256:af21eb4409a119e365397b2adbaca4c9ccab56543a65d5dbd9f920d6ac29f686 \ + --hash=sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34 \ + --hash=sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49 \ + --hash=sha256:bb8cc7534f51d9a017b93e3e85b260924f909601c3df002bcdb58ddb4dc41a5c \ + --hash=sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1 \ + --hash=sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e \ + --hash=sha256:bd9b23791fe793e4968dba0c447e12f78e425c59fc0e3b97f6450f4781f3ee60 \ + --hash=sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0 \ + --hash=sha256:c0f081d69a6e58272819b70288d3221a6ee64b98df852631c80f293514d3b274 \ + --hash=sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d \ + --hash=sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0 \ + --hash=sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae \ + --hash=sha256:c593052c465475e64bbfe5dbd81680f64a67fdc752c56d7a0ae205dc8aeefe0f \ + --hash=sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d \ + --hash=sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe \ + --hash=sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3 \ + --hash=sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393 \ + --hash=sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1 \ + --hash=sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af \ + --hash=sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44 \ + --hash=sha256:d61f00a0869d77422d9b2aba989e2d24afa6ffd552af442e0e58de4f35ea6d00 \ + --hash=sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c \ + --hash=sha256:dca4bbc466a95ba9c0234ef56d7dd9509f63da22274589ebd4ed7f1f4d4c54e3 \ + --hash=sha256:dd915403e231e6b1809fe9b6d9fc55cf8fb5e02765ac625d9cd623342a7905d7 \ + --hash=sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd \ + --hash=sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e \ + --hash=sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b \ + --hash=sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8 \ + --hash=sha256:e5f4d355f0a2b1a31bc3edec6795b46324349c9cb25eed068049e4f472fb4259 \ + --hash=sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859 \ + --hash=sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46 \ + --hash=sha256:e80c8378d8f3d83cd3164da1ad2df9e37a666cdde7b1cb2298ed0b558064be30 \ + --hash=sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b \ + --hash=sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46 \ + --hash=sha256:ed065083d0898c9d5b4bbec7b026fd755ff7454e6e8b73a67f8c744b13986e24 \ + --hash=sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a \ + --hash=sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24 \ + --hash=sha256:f22dec1690b584cea26fade98b2435c132c1b5f68e39f5a0b7627cd7ae31f1dc \ + --hash=sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215 \ + --hash=sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063 \ + --hash=sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832 \ + --hash=sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6 \ + --hash=sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79 \ + --hash=sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464 # via # requests # snowflake-connector-python @@ -426,68 +442,68 @@ colorama==0.4.6 \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 # via feast (pyproject.toml) -cryptography==46.0.5 \ - --hash=sha256:02f547fce831f5096c9a567fd41bc12ca8f11df260959ecc7c3202555cc47a72 \ - --hash=sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235 \ - --hash=sha256:1abfdb89b41c3be0365328a410baa9df3ff8a9110fb75e7b52e66803ddabc9a9 \ - --hash=sha256:2ae6971afd6246710480e3f15824ed3029a60fc16991db250034efd0b9fb4356 \ - --hash=sha256:2b7a67c9cd56372f3249b39699f2ad479f6991e62ea15800973b956f4b73e257 \ - --hash=sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad \ - --hash=sha256:38946c54b16c885c72c4f59846be9743d699eee2b69b6988e0a00a01f46a61a4 \ - --hash=sha256:3b4995dc971c9fb83c25aa44cf45f02ba86f71ee600d81091c2f0cbae116b06c \ - --hash=sha256:3ce58ba46e1bc2aac4f7d9290223cead56743fa6ab94a5d53292ffaac6a91614 \ - --hash=sha256:3ee190460e2fbe447175cda91b88b84ae8322a104fc27766ad09428754a618ed \ - --hash=sha256:4108d4c09fbbf2789d0c926eb4152ae1760d5a2d97612b92d508d96c861e4d31 \ - --hash=sha256:420d0e909050490d04359e7fdb5ed7e667ca5c3c402b809ae2563d7e66a92229 \ - --hash=sha256:47fb8a66058b80e509c47118ef8a75d14c455e81ac369050f20ba0d23e77fee0 \ - --hash=sha256:4c3341037c136030cb46e4b1e17b7418ea4cbd9dd207e4a6f3b2b24e0d4ac731 \ - --hash=sha256:4d7e3d356b8cd4ea5aff04f129d5f66ebdc7b6f8eae802b93739ed520c47c79b \ - --hash=sha256:4d8ae8659ab18c65ced284993c2265910f6c9e650189d4e3f68445ef82a810e4 \ - --hash=sha256:4e817a8920bfbcff8940ecfd60f23d01836408242b30f1a708d93198393a80b4 \ - --hash=sha256:50bfb6925eff619c9c023b967d5b77a54e04256c4281b0e21336a130cd7fc263 \ - --hash=sha256:556e106ee01aa13484ce9b0239bca667be5004efb0aabbed28d353df86445595 \ - --hash=sha256:582f5fcd2afa31622f317f80426a027f30dc792e9c80ffee87b993200ea115f1 \ - --hash=sha256:5be7bf2fb40769e05739dd0046e7b26f9d4670badc7b032d6ce4db64dddc0678 \ - --hash=sha256:60ee7e19e95104d4c03871d7d7dfb3d22ef8a9b9c6778c94e1c8fcc8365afd48 \ - --hash=sha256:61aa400dce22cb001a98014f647dc21cda08f7915ceb95df0c9eaf84b4b6af76 \ - --hash=sha256:68f68d13f2e1cb95163fa3b4db4bf9a159a418f5f6e7242564fc75fcae667fd0 \ - --hash=sha256:7d1f30a86d2757199cb2d56e48cce14deddf1f9c95f1ef1b64ee91ea43fe2e18 \ - --hash=sha256:7d731d4b107030987fd61a7f8ab512b25b53cef8f233a97379ede116f30eb67d \ - --hash=sha256:803812e111e75d1aa73690d2facc295eaefd4439be1023fefc4995eaea2af90d \ - --hash=sha256:80a8d7bfdf38f87ca30a5391c0c9ce4ed2926918e017c29ddf643d0ed2778ea1 \ - --hash=sha256:8293f3dea7fc929ef7240796ba231413afa7b68ce38fd21da2995549f5961981 \ - --hash=sha256:8456928655f856c6e1533ff59d5be76578a7157224dbd9ce6872f25055ab9ab7 \ - --hash=sha256:890bcb4abd5a2d3f852196437129eb3667d62630333aacc13dfd470fad3aaa82 \ - --hash=sha256:94a76daa32eb78d61339aff7952ea819b1734b46f73646a07decb40e5b3448e2 \ - --hash=sha256:9f16fbdf4da055efb21c22d81b89f155f02ba420558db21288b3d0035bafd5f4 \ - --hash=sha256:a3d1fae9863299076f05cb8a778c467578262fae09f9dc0ee9b12eb4268ce663 \ - --hash=sha256:a3d507bb6a513ca96ba84443226af944b0f7f47dcc9a399d110cd6146481d24c \ - --hash=sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d \ - --hash=sha256:ba2a27ff02f48193fc4daeadf8ad2590516fa3d0adeeb34336b96f7fa64c1e3a \ - --hash=sha256:bc84e875994c3b445871ea7181d424588171efec3e185dced958dad9e001950a \ - --hash=sha256:bfd56bb4b37ed4f330b82402f6f435845a5f5648edf1ad497da51a8452d5d62d \ - --hash=sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b \ - --hash=sha256:c3bcce8521d785d510b2aad26ae2c966092b7daa8f45dd8f44734a104dc0bc1a \ - --hash=sha256:c4143987a42a2397f2fc3b4d7e3a7d313fbe684f67ff443999e803dd75a76826 \ - --hash=sha256:c69fd885df7d089548a42d5ec05be26050ebcd2283d89b3d30676eb32ff87dee \ - --hash=sha256:ced80795227d70549a411a4ab66e8ce307899fad2220ce5ab2f296e687eacde9 \ - --hash=sha256:d66e421495fdb797610a08f43b05269e0a5ea7f5e652a89bfd5a7d3c1dee3648 \ - --hash=sha256:d861ee9e76ace6cf36a6a89b959ec08e7bc2493ee39d07ffe5acb23ef46d27da \ - --hash=sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2 \ - --hash=sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2 \ - --hash=sha256:fe346b143ff9685e40192a4960938545c699054ba11d4f9029f94751e3f71d87 +cryptography==46.0.6 \ + --hash=sha256:02fad249cb0e090b574e30b276a3da6a149e04ee2f049725b1f69e7b8351ec70 \ + --hash=sha256:063b67749f338ca9c5a0b7fe438a52c25f9526b851e24e6c9310e7195aad3b4d \ + --hash=sha256:12cae594e9473bca1a7aceb90536060643128bb274fcea0fc459ab90f7d1ae7a \ + --hash=sha256:12f0fa16cc247b13c43d56d7b35287ff1569b5b1f4c5e87e92cc4fcc00cd10c0 \ + --hash=sha256:22259338084d6ae497a19bae5d4c66b7ca1387d3264d1c2c0e72d9e9b6a77b97 \ + --hash=sha256:26031f1e5ca62fcb9d1fcb34b2b60b390d1aacaa15dc8b895a9ed00968b97b30 \ + --hash=sha256:27550628a518c5c6c903d84f637fbecf287f6cb9ced3804838a1295dc1fd0759 \ + --hash=sha256:2b417edbe8877cda9022dde3a008e2deb50be9c407eef034aeeb3a8b11d9db3c \ + --hash=sha256:2ea0f37e9a9cf0df2952893ad145fd9627d326a59daec9b0802480fa3bcd2ead \ + --hash=sha256:2ef9e69886cbb137c2aef9772c2e7138dc581fad4fcbcf13cc181eb5a3ab6275 \ + --hash=sha256:341359d6c9e68834e204ceaf25936dffeafea3829ab80e9503860dcc4f4dac58 \ + --hash=sha256:380343e0653b1c9d7e1f55b52aaa2dbb2fdf2730088d48c43ca1c7c0abb7cc2f \ + --hash=sha256:3c21d92ed15e9cfc6eb64c1f5a0326db22ca9c2566ca46d845119b45b4400361 \ + --hash=sha256:3dfa6567f2e9e4c5dceb8ccb5a708158a2a871052fa75c8b78cb0977063f1507 \ + --hash=sha256:456b3215172aeefb9284550b162801d62f5f264a081049a3e94307fe20792cfa \ + --hash=sha256:4668298aef7cddeaf5c6ecc244c2302a2b8e40f384255505c22875eebb47888b \ + --hash=sha256:50575a76e2951fe7dbd1f56d181f8c5ceeeb075e9ff88e7ad997d2f42af06e7b \ + --hash=sha256:639301950939d844a9e1c4464d7e07f902fe9a7f6b215bb0d4f28584729935d8 \ + --hash=sha256:64235194bad039a10bb6d2d930ab3323baaec67e2ce36215fd0952fad0930ca8 \ + --hash=sha256:6617f67b1606dfd9fe4dbfa354a9508d4a6d37afe30306fe6c101b7ce3274b72 \ + --hash=sha256:67177e8a9f421aa2d3a170c3e56eca4e0128883cf52a071a7cbf53297f18b175 \ + --hash=sha256:6728c49e3b2c180ef26f8e9f0a883a2c585638db64cf265b49c9ba10652d430e \ + --hash=sha256:6739d56300662c468fddb0e5e291f9b4d084bead381667b9e654c7dd81705124 \ + --hash=sha256:69cf0056d6947edc6e6760e5f17afe4bea06b56a9ac8a06de9d2bd6b532d4f3a \ + --hash=sha256:760997a4b950ff00d418398ad73fbc91aa2894b5c1db7ccb45b4f68b42a63b3c \ + --hash=sha256:79e865c642cfc5c0b3eb12af83c35c5aeff4fa5c672dc28c43721c2c9fdd2f0f \ + --hash=sha256:7e6142674f2a9291463e5e150090b95a8519b2fb6e6aaec8917dd8d094ce750d \ + --hash=sha256:7f417f034f91dcec1cb6c5c35b07cdbb2ef262557f701b4ecd803ee8cefed4f4 \ + --hash=sha256:7f6690b6c55e9c5332c0b59b9c8a3fb232ebf059094c17f9019a51e9827df91c \ + --hash=sha256:8927ccfbe967c7df312ade694f987e7e9e22b2425976ddbf28271d7e58845290 \ + --hash=sha256:8ce35b77aaf02f3b59c90b2c8a05c73bac12cea5b4e8f3fbece1f5fddea5f0ca \ + --hash=sha256:8e7304c4f4e9490e11efe56af6713983460ee0780f16c63f219984dab3af9d2d \ + --hash=sha256:90e5f0a7b3be5f40c3a0a0eafb32c681d8d2c181fc2a1bdabe9b3f611d9f6b1a \ + --hash=sha256:97c8115b27e19e592a05c45d0dd89c57f81f841cc9880e353e0d3bf25b2139ed \ + --hash=sha256:9a693028b9cbe51b5a1136232ee8f2bc242e4e19d456ded3fa7c86e43c713b4a \ + --hash=sha256:9a9c42a2723999a710445bc0d974e345c32adfd8d2fac6d8a251fa829ad31cfb \ + --hash=sha256:a3e84d5ec9ba01f8fd03802b2147ba77f0c8f2617b2aff254cedd551844209c8 \ + --hash=sha256:aad75154a7ac9039936d50cf431719a2f8d4ed3d3c277ac03f3339ded1a5e707 \ + --hash=sha256:b12c6b1e1651e42ab5de8b1e00dc3b6354fdfd778e7fa60541ddacc27cd21410 \ + --hash=sha256:b928a3ca837c77a10e81a814a693f2295200adb3352395fad024559b7be7a736 \ + --hash=sha256:bcb87663e1f7b075e48c3be3ecb5f0b46c8fc50b50a97cf264e7f60242dca3f2 \ + --hash=sha256:c797e2517cb7880f8297e2c0f43bb910e91381339336f75d2c1c2cbf811b70b4 \ + --hash=sha256:c89eb37fae9216985d8734c1afd172ba4927f5a05cfd9bf0e4863c6d5465b013 \ + --hash=sha256:cdcd3edcbc5d55757e5f5f3d330dd00007ae463a7e7aa5bf132d1f22a4b62b19 \ + --hash=sha256:d24c13369e856b94892a89ddf70b332e0b70ad4a5c43cf3e9cb71d6d7ffa1f7b \ + --hash=sha256:d4e4aadb7fc1f88687f47ca20bb7227981b03afaae69287029da08096853b738 \ + --hash=sha256:d9528b535a6c4f8ff37847144b8986a9a143585f0540fbcb1a98115b543aa463 \ + --hash=sha256:ed3775295fb91f70b4027aeba878d79b3e55c0b3e97eaa4de71f8f23a9f2eb77 \ + --hash=sha256:ed418c37d095aeddf5336898a132fba01091f0ac5844e3e8018506f014b6d2c4 # via # google-auth # pyjwt # pyopenssl # snowflake-connector-python -dask[dataframe]==2026.1.2 \ - --hash=sha256:1136683de2750d98ea792670f7434e6c1cfce90cab2cc2f2495a9e60fd25a4fc \ - --hash=sha256:46a0cf3b8d87f78a3d2e6b145aea4418a6d6d606fe6a16c79bd8ca2bb862bc91 +dask[dataframe]==2026.3.0 \ + --hash=sha256:be614b9242b0b38288060fb2d7696125946469c98a1c30e174883fd199e0428d \ + --hash=sha256:f7d96c8274e8a900d217c1ff6ea8d1bbf0b4c2c21e74a409644498d925eb8f85 # via feast (pyproject.toml) -db-dtypes==1.5.0 \ - --hash=sha256:abdbb2e4eb965800ed6f98af0c5c1cafff9063ace09114be2d26a7f046be2c8a \ - --hash=sha256:ad9e94243f53e104bc77dbf9ae44b580d83a770d3694483aba59c9767966daa5 +db-dtypes==1.5.1 \ + --hash=sha256:901099b807c9312bc61a5bddbfb07512884e6c6d5a9edacf24d50bcf303aa5f7 \ + --hash=sha256:ad71a6645e3c1f06d4d32023940576648f43119822f825f0d22587c6ef8afe15 # via # google-cloud-bigquery # pandas-gbq @@ -495,48 +511,42 @@ dill==0.3.9 \ --hash=sha256:468dff3b89520b474c0397703366b7b95eebe6303f108adf9b19da1f702be87a \ --hash=sha256:81aa267dddf68cbfe8029c42ca9ec6a4ab3b22371d1c450abc54422577b4512c # via feast (pyproject.toml) -duckdb==1.4.4 \ - --hash=sha256:0509b39ea7af8cff0198a99d206dca753c62844adab54e545984c2e2c1381616 \ - --hash=sha256:0d636ceda422e7babd5e2f7275f6a0d1a3405e6a01873f00d38b72118d30c10b \ - --hash=sha256:1af6e76fe8bd24875dc56dd8e38300d64dc708cd2e772f67b9fbc635cc3066a3 \ - --hash=sha256:1f8d55843cc940e36261689054f7dfb6ce35b1f5b0953b0d355b6adb654b0d52 \ - --hash=sha256:25874f8b1355e96178079e37312c3ba6d61a2354f51319dae860cf21335c3a20 \ - --hash=sha256:337f8b24e89bc2e12dadcfe87b4eb1c00fd920f68ab07bc9b70960d6523b8bc3 \ - --hash=sha256:452c5b5d6c349dc5d1154eb2062ee547296fcbd0c20e9df1ed00b5e1809089da \ - --hash=sha256:453b115f4777467f35103d8081770ac2f223fb5799178db5b06186e3ab51d1f2 \ - --hash=sha256:47dd4162da6a2be59a0aef640eb08d6360df1cf83c317dcc127836daaf3b7f7c \ - --hash=sha256:49123b579e4a6323e65139210cd72dddc593a72d840211556b60f9703bda8526 \ - --hash=sha256:4c25d5b0febda02b7944e94fdae95aecf952797afc8cb920f677b46a7c251955 \ - --hash=sha256:50f2eb173c573811b44aba51176da7a4e5c487113982be6a6a1c37337ec5fa57 \ - --hash=sha256:53cd6423136ab44383ec9955aefe7599b3fb3dd1fe006161e6396d8167e0e0d4 \ - --hash=sha256:5536eb952a8aa6ae56469362e344d4e6403cc945a80bc8c5c2ebdd85d85eb64b \ - --hash=sha256:59c8d76016dde854beab844935b1ec31de358d4053e792988108e995b18c08e7 \ - --hash=sha256:5ba684f498d4e924c7e8f30dd157da8da34c8479746c5011b6c0e037e9c60ad2 \ - --hash=sha256:5cdc4126ec925edf3112bc656ac9ed23745294b854935fa7a643a216e4455af6 \ - --hash=sha256:5e1933fac5293fea5926b0ee75a55b8cfe7f516d867310a5b251831ab61fe62b \ - --hash=sha256:6703dd1bb650025b3771552333d305d62ddd7ff182de121483d4e042ea6e2e00 \ - --hash=sha256:6792ca647216bd5c4ff16396e4591cfa9b4a72e5ad7cdd312cec6d67e8431a7c \ - --hash=sha256:6cb357cfa3403910e79e2eb46c8e445bb1ee2fd62e9e9588c6b999df4256abc1 \ - --hash=sha256:6fb1225a9ea5877421481d59a6c556a9532c32c16c7ae6ca8d127e2b878c9389 \ - --hash=sha256:707530f6637e91dc4b8125260595299ec9dd157c09f5d16c4186c5988bfbd09a \ - --hash=sha256:7df7351328ffb812a4a289732f500d621e7de9942a3a2c9b6d4afcf4c0e72526 \ - --hash=sha256:7eec0bf271ac622e57b7f6554a27a6e7d1dd2f43d1871f7962c74bcbbede15ba \ - --hash=sha256:8097201bc5fd0779d7fcc2f3f4736c349197235f4cb7171622936343a1aa8dbf \ - --hash=sha256:8bba52fd2acb67668a4615ee17ee51814124223de836d9e2fdcbc4c9021b3d3c \ - --hash=sha256:8e5c2d8a0452df55e092959c0bfc8ab8897ac3ea0f754cb3b0ab3e165cd79aff \ - --hash=sha256:a3c8542db7ffb128aceb7f3b35502ebaddcd4f73f1227569306cc34bad06680c \ - --hash=sha256:b297eff642503fd435a9de5a9cb7db4eccb6f61d61a55b30d2636023f149855f \ - --hash=sha256:bf138201f56e5d6fc276a25138341b3523e2f84733613fc43f02c54465619a95 \ - --hash=sha256:c65d15c440c31e06baaebfd2c06d71ce877e132779d309f1edf0a85d23c07e92 \ - --hash=sha256:c9566a4ed834ec7999db5849f53da0a7ee83d86830c33f471bf0211a1148ca12 \ - --hash=sha256:cd1be3d48577f5b40eb9706c6b2ae10edfe18e78eb28e31a3b922dcff1183597 \ - --hash=sha256:d0440f59e0cd9936a9ebfcf7a13312eda480c79214ffed3878d75947fc3b7d6d \ - --hash=sha256:d525de5f282b03aa8be6db86b1abffdceae5f1055113a03d5b50cd2fb8cf2ef8 \ - --hash=sha256:ddcfd9c6ff234da603a1edd5fd8ae6107f4d042f74951b65f91bc5e2643856b3 \ - --hash=sha256:e041f2fbd6888da090eca96ac167a7eb62d02f778385dd9155ed859f1c6b6dc8 \ - --hash=sha256:e870a441cb1c41d556205deb665749f26347ed13b3a247b53714f5d589596977 \ - --hash=sha256:f28a18cc790217e5b347bb91b2cab27aafc557c58d3d8382e04b4fe55d0c3f66 \ - --hash=sha256:fb94de6d023de9d79b7edc1ae07ee1d0b4f5fa8a9dcec799650b5befdf7aafec +duckdb==1.5.1 \ + --hash=sha256:054ad424b051b334052afac58cb216f3b1ebb8579fc8c641e60f0182e8725ea9 \ + --hash=sha256:05fc91767d0cfc4cf2fa68966ab5b479ac07561752e42dd0ae30327bd160f64a \ + --hash=sha256:0a6acc2040bec1f05de62a2f3f68f4c12f3ec7d6012b4317d0ab1a195af26225 \ + --hash=sha256:26e56b5f0c96189e3288d83cf7b476e23615987902f801e5788dee15ee9f24a9 \ + --hash=sha256:36e8e32621a9e2a9abe75dc15a4b54a3997f2d8b1e53ad754bae48a083c91130 \ + --hash=sha256:40c5220ec93790b18ec6278da9c6ac2608d997ee6d6f7cd44c5c3992764e8e71 \ + --hash=sha256:446d500a2977c6ae2077f340c510a25956da5c77597175c316edfa87248ceda3 \ + --hash=sha256:46f92ada9023e59f27edc048167b31ac9a03911978b1296c845a34462a27f096 \ + --hash=sha256:482f8a13f2600f527e427f73c42b5aa75536f9892868068f0aaf573055a0135f \ + --hash=sha256:553c273a6a8f140adaa6da6a6135c7f95bdc8c2e5f95252fcdf9832d758e2141 \ + --hash=sha256:5ae7c0d744d64e2753149634787cc4ab60f05ef1e542b060eeab719f3cdb7723 \ + --hash=sha256:5d4147422d91ccdc2d2abf6ed24196025e020259d1d267970ae20c13c2ce84b1 \ + --hash=sha256:6af347debc8b721aa72e48671166282da979d5e5ae52dbc660ab417282b48e23 \ + --hash=sha256:6ba302115f63f6482c000ccfd62efdb6c41d9d182a5bcd4a90e7ab8cd13856eb \ + --hash=sha256:6f7361d66cc801d9eb4df734b139cd7b0e3c257a16f3573ebd550ddb255549e6 \ + --hash=sha256:715f05ea198d20d7f8b407b9b84e0023d17f2b9096c194cea702b7840e74f1f7 \ + --hash=sha256:71dddcebbc5a70e946a06c30b59b5dd7999c9833d307168f90fb4e4b672ab63e \ + --hash=sha256:8150c569b2aa4573b51ba8475e814aa41fd53a3d510c1ffb96f1139f46faf611 \ + --hash=sha256:8843bd9594e1387f1e601439e19ad73abdf57356104fd1e53a708255bb95a13d \ + --hash=sha256:8c0088765747ae5d6c9f89987bb36f9fb83564f07090d721344ce8e1abedffea \ + --hash=sha256:972d0dbf283508f9bc446ee09c3838cb7c7f114b5bdceee41753288c97fe2f7c \ + --hash=sha256:a28531cee2a5a42d89f9ba4da53bfeb15681f12acc0263476c8705380dadce07 \ + --hash=sha256:a3be2072315982e232bfe49c9d3db0a59ba67b2240a537ef42656cc772a887c7 \ + --hash=sha256:ac2804043bd1bc10b5da18f8f4c706877197263a510c41be9b4c0062f5783dcc \ + --hash=sha256:afab8b4b1f4469c3879bb049dd039f8fce402712050324e9524a43d7324c5e87 \ + --hash=sha256:b370d1620a34a4538ef66524fcee9de8171fa263c701036a92bc0b4c1f2f9c6d \ + --hash=sha256:b8b0808dba0c63b7633bdaefb34e08fe0612622224f9feb0e7518904b1615101 \ + --hash=sha256:bc7ca6a1a40e7e4c933017e6c09ef18032add793df4e42624c6c0c87e0bebdad \ + --hash=sha256:caa65e1f5bf007430bf657c37cab7ab81a4ddf8d337e3062bcc5085d17ef038b \ + --hash=sha256:d68c5a01a283cb13b79eafe016fe5869aa11bff8c46e7141c70aa0aac808010f \ + --hash=sha256:da137802688190835b4c863cafa77fd7e29dff662ee6d905a9ffc14f00299c91 \ + --hash=sha256:e56a20ab6cdb90a95b0c99652e28de3504ce77129087319c03c9098266183ae5 \ + --hash=sha256:e878ccb7d20872065e1597935fdb5e65efa43220c8edd0d9c4a1a7ff1f3eb277 \ + --hash=sha256:eba81e0b3011c1f23df7ea47ef4ffaa8239817959ae291515b6efd068bde2161 \ + --hash=sha256:ed6d23a3f806898e69c77430ebd8da0c79c219f97b9acbc9a29a653e09740c59 # via ibis-framework durationpy==0.10 \ --hash=sha256:1fa6893409a6e739c9c72334fc65cca1f355dbdd93405d30f726deb5bde42fba \ @@ -546,9 +556,9 @@ exceptiongroup==1.3.1 \ --hash=sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219 \ --hash=sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598 # via anyio -fastapi==0.129.0 \ - --hash=sha256:61315cebd2e65df5f97ec298c888f9de30430dd0612d59d6480beafbc10655af \ - --hash=sha256:b4946880e48f462692b31c083be0432275cbfb6e2274566b1be91479cc1a84ec +fastapi==0.135.3 \ + --hash=sha256:9b0f590c813acd13d0ab43dd8494138eb58e484bfac405db1f3187cfc5810d98 \ + --hash=sha256:bd6d7caf1a2bdd8d676843cdcd2287729572a1ef524fc4d65c17ae002a1be654 # via # feast (pyproject.toml) # fastapi-mcp @@ -556,9 +566,9 @@ fastapi-mcp==0.4.0 \ --hash=sha256:d4a3fe7966af24d44e4b412720561c95eb12bed999a4443a88221834b3b15aec \ --hash=sha256:d4ca9410996f4c7b8ea0d7b20fdf79878dc359ebf89cbf3b222e0b675a55097d # via feast (pyproject.toml) -filelock==3.24.2 \ - --hash=sha256:667d7dc0b7d1e1064dd5f8f8e80bdac157a6482e8d2e02cd16fd3b6b33bd6556 \ - --hash=sha256:c22803117490f156e59fafce621f0550a7a853e2bbf4f87f112b11d469b6c81b +filelock==3.25.2 \ + --hash=sha256:b64ece2b38f4ca29dd3e810287aa8c48182bbecd1ae6e9ae126c9b35f1382694 \ + --hash=sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70 # via snowflake-connector-python frozenlist==1.8.0 \ --hash=sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686 \ @@ -700,9 +710,9 @@ fsspec==2024.9.0 \ # via # feast (pyproject.toml) # dask -google-api-core[grpc]==2.29.0 \ - --hash=sha256:84181be0f8e6b04006df75ddfe728f24489f0af57c96a529ff7cf45bc28797f7 \ - --hash=sha256:d30bc60980daa36e314b5d5a3e5958b0200cb44ca8fa1be2b614e932b75a3ea9 +google-api-core[grpc]==2.30.2 \ + --hash=sha256:9a8113e1a88bdc09a7ff629707f2214d98d61c7f6ceb0ea38c42a095d02dc0f9 \ + --hash=sha256:a4c226766d6af2580577db1f1a51bf53cd262f722b49731ce7414c43068a9594 # via # feast (pyproject.toml) # google-cloud-bigquery @@ -712,9 +722,9 @@ google-api-core[grpc]==2.29.0 \ # google-cloud-datastore # google-cloud-storage # pandas-gbq -google-auth==2.48.0 \ - --hash=sha256:2e2a537873d449434252a9632c28bfc268b0adb1e53f9fb62afc5333a975903f \ - --hash=sha256:4f7e706b0cd3208a3d940a19a822c37a476ddba5450156c3e6624a71f7c841ce +google-auth==2.49.1 \ + --hash=sha256:16d40da1c3c5a0533f57d268fe72e0ebb0ae1cc3b567024122651c045d879b64 \ + --hash=sha256:195ebe3dca18eddd1b3db5edc5189b76c13e96f29e73043b923ebcf3f1a860f7 # via # google-api-core # google-auth-oauthlib @@ -726,37 +736,37 @@ google-auth==2.48.0 \ # google-cloud-storage # pandas-gbq # pydata-google-auth -google-auth-oauthlib==1.2.4 \ - --hash=sha256:0e922eea5f2baacaf8867febb782e46e7b153236c21592ed76ab3ddb77ffd772 \ - --hash=sha256:3ca93859c6cc9003c8e12b2a0868915209d7953f05a70f4880ab57d57e56ee3e +google-auth-oauthlib==1.3.1 \ + --hash=sha256:14c22c7b3dd3d06dbe44264144409039465effdd1eef94f7ce3710e486cc4bfa \ + --hash=sha256:1a139ef23f1318756805b0e95f655c238bffd29655329a2978218248da4ee7f8 # via # pandas-gbq # pydata-google-auth -google-cloud-bigquery[pandas]==3.40.1 \ - --hash=sha256:75afcfb6e007238fe1deefb2182105249321145ff921784fe7b1de2b4ba24506 \ - --hash=sha256:9082a6b8193aba87bed6a2c79cf1152b524c99bb7e7ac33a785e333c09eac868 +google-cloud-bigquery[pandas]==3.41.0 \ + --hash=sha256:2217e488b47ed576360c9b2cc07d59d883a54b83167c0ef37f915c26b01a06fe \ + --hash=sha256:2a5b5a737b401cbd824a6e5eac7554100b878668d908e6548836b5d8aaa4dcaa # via # feast (pyproject.toml) # pandas-gbq -google-cloud-bigquery-storage==2.36.1 \ - --hash=sha256:99ad6b8810d028f0cf368ea0cc54b3cda20e856f05eb4cda51f1db2a70692286 \ - --hash=sha256:fd3917584a41f7a9d9c633b31ff43103869b108224e8a4b765537eb1ea83148c +google-cloud-bigquery-storage==2.37.0 \ + --hash=sha256:1e319c27ef60fc31030f6e0b52e5e891e1cdd50551effe8c6f673a4c3c56fcb6 \ + --hash=sha256:f88ee7f1e49db1e639da3d9a8b79835ca4bc47afbb514fb2adfc0ccb41a7fd97 # via feast (pyproject.toml) -google-cloud-bigtable==2.35.0 \ - --hash=sha256:f355bfce1f239453ec2bb3839b0f4f9937cf34ef06ef29e1ca63d58fd38d0c50 \ - --hash=sha256:f5699012c5fea4bd4bdf7e80e5e3a812a847eb8f41bf8dc2f43095d6d876b83b +google-cloud-bigtable==2.36.0 \ + --hash=sha256:21b2f41231b7368a550b44d5b493b811b3507fcb23eb26d00005cd3f205f2207 \ + --hash=sha256:d5987733c2f60c739f93f259d2037858411cc994ac37cdfbccb6bb159f3ca43e # via feast (pyproject.toml) -google-cloud-core==2.5.0 \ - --hash=sha256:67d977b41ae6c7211ee830c7912e41003ea8194bff15ae7d72fd6f51e57acabc \ - --hash=sha256:7c1b7ef5c92311717bd05301aa1a91ffbc565673d3b0b4163a52d8413a186963 +google-cloud-core==2.5.1 \ + --hash=sha256:3dc94bdec9d05a31d9f355045ed0f369fbc0d8c665076c734f065d729800f811 \ + --hash=sha256:ea62cdf502c20e3e14be8a32c05ed02113d7bef454e40ff3fab6fe1ec9f1f4e7 # via # google-cloud-bigquery # google-cloud-bigtable # google-cloud-datastore # google-cloud-storage -google-cloud-datastore==2.23.0 \ - --hash=sha256:24a1b1d29b902148fe41b109699f76fd3aa60591e9d547c0f8b87d7bf9ff213f \ - --hash=sha256:80049883a4ae928fdcc661ba6803ec267665dc0e6f3ce2da91441079a6bb6387 +google-cloud-datastore==2.24.0 \ + --hash=sha256:81f1d1c12c2906f59507f72742545ab04c38f62ed70b0542057e3cf04a53aa65 \ + --hash=sha256:f087c02a6aa4ac68bbf17f0c048ae3ee355856bf09c51439bfba193741387792 # via feast (pyproject.toml) google-cloud-storage==2.19.0 \ --hash=sha256:aeb971b5c29cf8ab98445082cbfe7b161a1f48ed275822f59ed3f1524ea54fba \ @@ -800,23 +810,23 @@ google-crc32c==1.8.0 \ # google-cloud-bigtable # google-cloud-storage # google-resumable-media -google-resumable-media==2.8.0 \ - --hash=sha256:dd14a116af303845a8d932ddae161a26e86cc229645bc98b39f026f9b1717582 \ - --hash=sha256:f1157ed8b46994d60a1bc432544db62352043113684d4e030ee02e77ebe9a1ae +google-resumable-media==2.8.2 \ + --hash=sha256:82b6d8ccd11765268cdd2a2123f417ec806b8eef3000a9a38dfe3033da5fb220 \ + --hash=sha256:f3354a182ebd193ae3f42e3ef95e6c9b10f128320de23ac7637236713b1acd70 # via # google-cloud-bigquery # google-cloud-storage -googleapis-common-protos[grpc]==1.72.0 \ - --hash=sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038 \ - --hash=sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5 +googleapis-common-protos[grpc]==1.74.0 \ + --hash=sha256:57971e4eeeba6aad1163c1f0fc88543f965bb49129b8bb55b2b7b26ecab084f1 \ + --hash=sha256:702216f78610bb510e3f12ac3cafd281b7ac45cc5d86e90ad87e4d301a3426b5 # via # feast (pyproject.toml) # google-api-core # grpc-google-iam-v1 # grpcio-status -grpc-google-iam-v1==0.14.3 \ - --hash=sha256:7a7f697e017a067206a3dfef44e4c634a34d3dee135fe7d7a4613fe3e59217e6 \ - --hash=sha256:879ac4ef33136c5491a6300e27575a9ec760f6cdf9a2518798c1b8977a5dc389 +grpc-google-iam-v1==0.14.4 \ + --hash=sha256:392b3796947ed6334e61171d9ab06bf7eb357f554e5fc7556ad7aab6d0e17038 \ + --hash=sha256:412facc320fcbd94034b4df3d557662051d4d8adfa86e0ddb4dca70a3f739964 # via google-cloud-bigtable grpcio==1.62.3 \ --hash=sha256:059444f0ed5dba73ab7dd0ee7e8e6b606df4130d2b0a9f010f84da4ab9f6c2d8 \ @@ -897,9 +907,9 @@ grpcio-status==1.62.3 \ --hash=sha256:289bdd7b2459794a12cf95dc0cb727bd4a1742c37bd823f760236c937e53a485 \ --hash=sha256:f9049b762ba8de6b1086789d8315846e094edac2c50beaf462338b301a8fd4b8 # via google-api-core -gunicorn==25.1.0 \ - --hash=sha256:1426611d959fa77e7de89f8c0f32eed6aa03ee735f98c01efba3e281b1c47616 \ - --hash=sha256:d0b1236ccf27f72cfe14bce7caadf467186f19e865094ca84221424e839b8b8b +gunicorn==25.3.0 \ + --hash=sha256:cacea387dab08cd6776501621c295a904fe8e3b7aae9a1a3cbb26f4e7ed54660 \ + --hash=sha256:f74e1b2f9f76f6cd1ca01198968bd2dd65830edc24b6e8e4d78de8320e2fe889 # via # feast (pyproject.toml) # uvicorn-worker @@ -1077,9 +1087,9 @@ idna==3.11 \ # requests # snowflake-connector-python # yarl -importlib-metadata==8.7.1 \ - --hash=sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb \ - --hash=sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151 +importlib-metadata==9.0.0 \ + --hash=sha256:2d21d1cc5a017bd0559e36150c21c830ab1dc304dedd1b7ea85d20f45ef3edd7 \ + --hash=sha256:a4f57ab599e6a2e3016d7595cfd72eb4661a5106e787a95bcc90c7105b831efc # via dask jinja2==3.1.6 \ --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ @@ -1106,97 +1116,97 @@ kubernetes==35.0.0 \ --hash=sha256:39e2b33b46e5834ef6c3985ebfe2047ab39135d41de51ce7641a7ca5b372a13d \ --hash=sha256:3d00d344944239821458b9efd484d6df9f011da367ecb155dadf9513f05f09ee # via feast (pyproject.toml) -librt==0.8.0 \ - --hash=sha256:001e5330093d887b8b9165823eca6c5c4db183fe4edea4fdc0680bbac5f46944 \ - --hash=sha256:015e2dde6e096d27c10238bf9f6492ba6c65822dfb69d2bf74c41a8e88b7ddef \ - --hash=sha256:02a9fe85410cc9bef045e7cb7fd26fdde6669e6d173f99df659aa7f6335961e9 \ - --hash=sha256:0583aef7e9a720dd40f26a2ad5a1bf2ccbb90059dac2b32ac516df232c701db3 \ - --hash=sha256:05a3dd3f116747f7e1a2b475ccdc6fb637fd4987126d109e03013a79d40bf9e6 \ - --hash=sha256:0a33335eb59921e77c9acc05d0e654e4e32e45b014a4d61517897c11591094f8 \ - --hash=sha256:0ce33a9778e294507f3a0e3468eccb6a698b5166df7db85661543eca1cfc5369 \ - --hash=sha256:1566dbb9d1eb0987264c9b9460d212e809ba908d2f4a3999383a84d765f2f3f1 \ - --hash=sha256:17269dd2745dbe8e42475acb28e419ad92dfa38214224b1b01020b8cac70b645 \ - --hash=sha256:178707cda89d910c3b28bf5aa5f69d3d4734e0f6ae102f753ad79edef83a83c7 \ - --hash=sha256:1c25a131013eadd3c600686a0c0333eb2896483cbc7f65baa6a7ee761017aef9 \ - --hash=sha256:1e6811cac1dcb27ca4c74e0ca4a5917a8e06db0d8408d30daee3a41724bfde7a \ - --hash=sha256:1ef3bd856373cf8e7382402731f43bfe978a8613b4039e49e166e1e0dc590216 \ - --hash=sha256:20f73d4fecba969efc15cdefd030e382502d56bb6f1fc66b580cce582836c9fa \ - --hash=sha256:21b14464bee0b604d80a638cf1ee3148d84ca4cc163dcdcecb46060c1b3605e4 \ - --hash=sha256:24a01c13a2a9bdad20997a4443ebe6e329df063d1978bbe2ebbf637878a46d1e \ - --hash=sha256:25b3e667cbfc9000c4740b282df599ebd91dbdcc1aa6785050e4c1d6be5329ab \ - --hash=sha256:25e82d920d4d62ad741592fcf8d0f3bda0e3fc388a184cb7d2f566c681c5f7b9 \ - --hash=sha256:2b37437e7e4ef5e15a297b36ba9e577f73e29564131d86dd75875705e97402b5 \ - --hash=sha256:2ccdd20d9a72c562ffb73098ac411de351b53a6fbb3390903b2d33078ef90447 \ - --hash=sha256:2e0ffe88ebb5962f8fb0ddcbaaff30f1ea06a79501069310e1e030eafb1ad787 \ - --hash=sha256:375eda7acfce1f15f5ed56cfc960669eefa1ec8732e3e9087c3c4c3f2066759c \ - --hash=sha256:3d2720335020219197380ccfa5c895f079ac364b4c429e96952cd6509934d8eb \ - --hash=sha256:3e36a8da17134ffc29373775d88c04832f9ecfab1880470661813e6c7991ef79 \ - --hash=sha256:3e8b77b5f54d0937b26512774916041756c9eb3e66f1031971e626eea49d0bf4 \ - --hash=sha256:41064a0c07b4cc7a81355ccc305cb097d6027002209ffca51306e65ee8293630 \ - --hash=sha256:421765e8c6b18e64d21c8ead315708a56fc24f44075059702e421d164575fdda \ - --hash=sha256:4831c44b8919e75ca0dfb52052897c1ef59fdae19d3589893fbd068f1e41afbf \ - --hash=sha256:48f84830a8f8ad7918afd743fd7c4eb558728bceab7b0e38fd5a5cf78206a556 \ - --hash=sha256:4b705f85311ee76acec5ee70806990a51f0deb519ea0c29c1d1652d79127604d \ - --hash=sha256:4d3e38797eb482485b486898f89415a6ab163bc291476bd95712e42cf4383c05 \ - --hash=sha256:4eb5e06ebcc668677ed6389164f52f13f71737fc8be471101fa8b4ce77baeb0c \ - --hash=sha256:4f6e975377fbc4c9567cb33ea9ab826031b6c7ec0515bfae66a4fb110d40d6da \ - --hash=sha256:4f764b2424cb04524ff7a486b9c391e93f93dc1bd8305b2136d25e582e99aa2f \ - --hash=sha256:507e94f4bec00b2f590fbe55f48cd518a208e2474a3b90a60aa8f29136ddbada \ - --hash=sha256:56901f1eec031396f230db71c59a01d450715cbbef9856bf636726994331195d \ - --hash=sha256:5cb11061a736a9db45e3c1293cfcb1e3caf205912dfa085734ba750f2197ff9a \ - --hash=sha256:5d0f76fc73480d42285c609c0ea74d79856c160fa828ff9aceab574ea4ecfd7b \ - --hash=sha256:667e2513cf69bfd1e1ed9a00d6c736d5108714ec071192afb737987955888a25 \ - --hash=sha256:671a6152edf3b924d98a5ed5e6982ec9cb30894085482acadce0975f031d4c5c \ - --hash=sha256:693697133c3b32aa9b27f040e3691be210e9ac4d905061859a9ed519b1d5a376 \ - --hash=sha256:6a3146c63220d814c4a2c7d6a1eacc8d5c14aed0ff85115c1dfea868080cd18f \ - --hash=sha256:6b6caff69e25d80c269b1952be8493b4d94ef745f438fa619d7931066bdd26de \ - --hash=sha256:6e1af31a710e17891d9adf0dbd9a5fcd94901a3922a96499abdbf7ce658f4e01 \ - --hash=sha256:70defb797c4d5402166787a6b3c66dfb3fa7f93d118c0509ffafa35a392f4258 \ - --hash=sha256:71fc517efc14f75c2f74b1f0a5d5eb4a8e06aa135c34d18eaf3522f4a53cd62d \ - --hash=sha256:75d1a8cab20b2043f03f7aab730551e9e440adc034d776f15f6f8d582b0a5ad4 \ - --hash=sha256:789911e8fa40a2e82f41120c936b1965f3213c67f5a483fc5a41f5839a05dcbb \ - --hash=sha256:7bd68cebf3131bb920d5984f75fe302d758db33264e44b45ad139385662d7bc3 \ - --hash=sha256:7ce0a8cb67e702dcb06342b2aaaa3da9fb0ddc670417879adfa088b44cf7b3b6 \ - --hash=sha256:7f820210e21e3a8bf8fde2ae3c3d10106d4de9ead28cbfdf6d0f0f41f5b12fa1 \ - --hash=sha256:8070aa3368559de81061ef752770d03ca1f5fc9467d4d512d405bd0483bfffe6 \ - --hash=sha256:82e61cd1c563745ad495387c3b65806bfd453badb4adbc019df3389dddee1bf6 \ - --hash=sha256:82fb4602d1b3e303a58bfe6165992b5a78d823ec646445356c332cd5f5bbaa61 \ - --hash=sha256:88c6e75540f1f10f5e0fc5e87b4b6c290f0e90d1db8c6734f670840494764af8 \ - --hash=sha256:8992ca186a1678107b0af3d0c9303d8c7305981b9914989b9788319ed4d89546 \ - --hash=sha256:92249938ab744a5890580d3cb2b22042f0dce71cdaa7c1369823df62bedf7cbc \ - --hash=sha256:95a719a049f0eefaf1952673223cf00d442952273cbd20cf2ed7ec423a0ef58d \ - --hash=sha256:9646178cd794704d722306c2c920c221abbf080fede3ba539d5afdec16c46dad \ - --hash=sha256:9726305d3e53419d27fc8cdfcd3f9571f0ceae22fa6b5ea1b3662c2e538f833e \ - --hash=sha256:995d24caa6bbb34bcdd4a41df98ac6d1af637cfa8975cb0790e47d6623e70e3e \ - --hash=sha256:9ab3a3475a55b89b87ffd7e6665838e8458e0b596c22e0177e0f961434ec474a \ - --hash=sha256:9f09d4884f882baa39a7e36bbf3eae124c4ca2a223efb91e567381d1c55c6b06 \ - --hash=sha256:a512c88900bdb1d448882f5623a0b1ad27ba81a9bd75dacfe17080b72272ca1f \ - --hash=sha256:a905091a13e0884701226860836d0386b88c72ce5c2fdfba6618e14c72be9f25 \ - --hash=sha256:aaadec87f45a3612b6818d1db5fbfe93630669b7ee5d6bdb6427ae08a1aa2141 \ - --hash=sha256:b055bb3abaf69abed25743d8fc1ab691e4f51a912ee0a6f9a6c84f4bbddb283d \ - --hash=sha256:b4bb00bd71b448f16749909b08a0ff16f58b079e2261c2e1000f2bbb2a4f0a45 \ - --hash=sha256:b9aef96d7593584e31ef6ac1eb9775355b0099fee7651fae3a15bc8657b67b52 \ - --hash=sha256:ba581acad5ac8f33e2ff1746e8a57e001b47c6721873121bf8bbcf7ba8bd3aa4 \ - --hash=sha256:ba9d9e60651615bc614be5e21a82cdb7b1769a029369cf4b4d861e4f19686fb6 \ - --hash=sha256:bbebd2bba5c6ae02907df49150e55870fdd7440d727b6192c46b6f754723dde9 \ - --hash=sha256:bd32add59b58fba3439d48d6f36ac695830388e3da3e92e4fc26d2d02670d19c \ - --hash=sha256:bdab762e2c0b48bab76f1a08acb3f4c77afd2123bedac59446aeaaeed3d086cf \ - --hash=sha256:c5512aae4648152abaf4d48b59890503fcbe86e85abc12fb9b096fe948bdd816 \ - --hash=sha256:c6e4c10761ddbc0d67d2f6e2753daf99908db85d8b901729bf2bf5eaa60e0567 \ - --hash=sha256:cb4b3ad543084ed79f186741470b251b9d269cd8b03556f15a8d1a99a64b7de5 \ - --hash=sha256:cb74cdcbc0103fc988e04e5c58b0b31e8e5dd2babb9182b6f9490488eb36324b \ - --hash=sha256:cc3d107f603b5ee7a79b6aa6f166551b99b32fb4a5303c4dfcb4222fc6a0335e \ - --hash=sha256:d920789eca7ef71df7f31fd547ec0d3002e04d77f30ba6881e08a630e7b2c30e \ - --hash=sha256:daae5e955764be8fd70a93e9e5133c75297f8bce1e802e1d3683b98f77e1c5ab \ - --hash=sha256:db63cf3586a24241e89ca1ce0b56baaec9d371a328bd186c529b27c914c9a1ef \ - --hash=sha256:db953b675079884ffda33d1dca7189fb961b6d372153750beb81880384300817 \ - --hash=sha256:de076eaba208d16efb5962f99539867f8e2c73480988cb513fcf1b5dbb0c9dcf \ - --hash=sha256:e79dbc8f57de360f0ed987dc7de7be814b4803ef0e8fc6d3ff86e16798c99935 \ - --hash=sha256:e9a3a38eb4134ad33122a6d575e6324831f930a771d951a15ce232e0237412c2 \ - --hash=sha256:f04ca50e847abc486fa8f4107250566441e693779a5374ba211e96e238f298b9 \ - --hash=sha256:f1178e0de0c271231a660fbef9be6acdfa1d596803464706862bef6644cc1cae \ - --hash=sha256:f4617cef654fca552f00ce5ffdf4f4b68770f18950e4246ce94629b789b92467 \ - --hash=sha256:fa37f99bff354ff191c6bcdffbc9d7cdd4fc37faccfc9be0ef3a4fd5613977da +librt==0.8.1 \ + --hash=sha256:01170b6729a438f0dedc4a26ed342e3dc4f02d1000b4b19f980e1877f0c297e6 \ + --hash=sha256:039b9f2c506bd0ab0f8725aa5ba339c6f0cd19d3b514b50d134789809c24285d \ + --hash=sha256:05bd41cdee35b0c59c259f870f6da532a2c5ca57db95b5f23689fcb5c9e42440 \ + --hash=sha256:086a32dbb71336627e78cc1d6ee305a68d038ef7d4c39aaff41ae8c9aa46e91a \ + --hash=sha256:08eec3a1fc435f0d09c87b6bf1ec798986a3544f446b864e4099633a56fcd9ed \ + --hash=sha256:0bf69d79a23f4f40b8673a947a234baeeb133b5078b483b7297c5916539cf5d5 \ + --hash=sha256:0c3811485fccfda840861905b8c70bba5ec094e02825598bb9d4ca3936857a04 \ + --hash=sha256:0d2f82168e55ddefd27c01c654ce52379c0750ddc31ee86b4b266bcf4d65f2a3 \ + --hash=sha256:0f2ae3725904f7377e11cc37722d5d401e8b3d5851fb9273d7f4fe04f6b3d37d \ + --hash=sha256:10c42e1f6fd06733ef65ae7bebce2872bcafd8d6e6b0a08fe0a05a23b044fb14 \ + --hash=sha256:153188fe98a72f206042be10a2c6026139852805215ed9539186312d50a8e972 \ + --hash=sha256:172d57ec04346b047ca6af181e1ea4858086c80bdf455f61994c4aa6fc3f866c \ + --hash=sha256:190b109bb69592a3401fe1ffdea41a2e73370ace2ffdc4a0e8e2b39cdea81b78 \ + --hash=sha256:1d3a7da44baf692f0c6aeb5b2a09c5e6fc7a703bca9ffa337ddd2e2da53f7732 \ + --hash=sha256:228c2409c079f8c11fb2e5d7b277077f694cb93443eb760e00b3b83cb8b3176c \ + --hash=sha256:22b46eabd76c1986ee7d231b0765ad387d7673bbd996aa0d0d054b38ac65d8f6 \ + --hash=sha256:237796479f4d0637d6b9cbcb926ff424a97735e68ade6facf402df4ec93375ed \ + --hash=sha256:2c74a2da57a094bd48d03fa5d196da83d2815678385d2978657499063709abe1 \ + --hash=sha256:2cc68eeeef5e906839c7bb0815748b5b0a974ec27125beefc0f942715785b551 \ + --hash=sha256:2eb345e8b33fb748227409c9f1233d4df354d6e54091f0e8fc53acdb2ffedeb7 \ + --hash=sha256:31362dbfe297b23590530007062c32c6f6176f6099646bb2c95ab1b00a57c382 \ + --hash=sha256:3dff3d3ca8db20e783b1bc7de49c0a2ab0b8387f31236d6a026597d07fcd68ac \ + --hash=sha256:43353b943613c5d9c49a25aaffdba46f888ec354e71e3529a00cca3f04d66a7a \ + --hash=sha256:439352ba9373f11cb8e1933da194dcc6206daf779ff8df0ed69c5e39113e6a99 \ + --hash=sha256:4998009e7cb9e896569f4be7004f09d0ed70d386fa99d42b6d363f6d200501ac \ + --hash=sha256:4be2a5c926b9770c9e08e717f05737a269b9d0ebc5d2f0060f0fe3fe9ce47acb \ + --hash=sha256:4beb04b8c66c6ae62f8c1e0b2f097c1ebad9295c929a8d5286c05eae7c2fc7dc \ + --hash=sha256:4c8dfa264b9193c4ee19113c985c95f876fae5e51f731494fc4e0cf594990ba7 \ + --hash=sha256:5212a5bd7fae98dae95710032902edcd2ec4dc994e883294f75c857b83f9aba0 \ + --hash=sha256:52c224e14614b750c0a6d97368e16804a98c684657c7518752c356834fff83bb \ + --hash=sha256:56e04c14b696300d47b3bc5f1d10a00e86ae978886d0cee14e5714fafb5df5d2 \ + --hash=sha256:5bb54f1205a3a6ab41a6fd71dfcdcbd278670d3a90ca502a30d9da583105b6f7 \ + --hash=sha256:5cdc0f588ff4b663ea96c26d2a230c525c6fc62b28314edaaaca8ed5af931ad0 \ + --hash=sha256:5db05697c82b3a2ec53f6e72b2ed373132b0c2e05135f0696784e97d7f5d48e7 \ + --hash=sha256:5e4af413908f77294605e28cfd98063f54b2c790561383971d2f52d113d9c363 \ + --hash=sha256:5fc48998000cbc39ec0d5311312dda93ecf92b39aaf184c5e817d5d440b29624 \ + --hash=sha256:60a78b694c9aee2a0f1aaeaa7d101cf713e92e8423a941d2897f4fa37908dab9 \ + --hash=sha256:64548cde61b692dc0dc379f4b5f59a2f582c2ebe7890d09c1ae3b9e66fa015b7 \ + --hash=sha256:681dc2451d6d846794a828c16c22dc452d924e9f700a485b7ecb887a30aad1fd \ + --hash=sha256:6b1977c4ea97ce5eb7755a78fae68d87e4102e4aaf54985e8b56806849cc06a3 \ + --hash=sha256:6cfa7fe54fd4d1f47130017351a959fe5804bda7a0bc7e07a2cdbc3fdd28d34f \ + --hash=sha256:738f08021b3142c2918c03692608baed43bc51144c29e35807682f8070ee2a3a \ + --hash=sha256:747328be0c5b7075cde86a0e09d7a9196029800ba75a1689332348e998fb85c0 \ + --hash=sha256:758509ea3f1eba2a57558e7e98f4659d0ea7670bff49673b0dde18a3c7e6c0eb \ + --hash=sha256:785ae29c1f5c6e7c2cde2c7c0e148147f4503da3abc5d44d482068da5322fd9e \ + --hash=sha256:7aae78ab5e3206181780e56912d1b9bb9f90a7249ce12f0e8bf531d0462dd0fc \ + --hash=sha256:7b02679a0d783bdae30d443025b94465d8c3dc512f32f5b5031f93f57ac32071 \ + --hash=sha256:7e2f3edca35664499fbb36e4770650c4bd4a08abc1f4458eab9df4ec56389730 \ + --hash=sha256:7e6bad1cd94f6764e1e21950542f818a09316645337fd5ab9a7acc45d99a8f35 \ + --hash=sha256:81fd938344fecb9373ba1b155968c8a329491d2ce38e7ddb76f30ffb938f12dc \ + --hash=sha256:82210adabbc331dbb65d7868b105185464ef13f56f7f76688565ad79f648b0fe \ + --hash=sha256:89815a22daf9c51884fb5dbe4f1ef65ee6a146e0b6a8df05f753e2e4a9359bf4 \ + --hash=sha256:8f1125e6bbf2f1657d9a2f3ccc4a2c9b0c8b176965bb565dd4d86be67eddb4b6 \ + --hash=sha256:8f4bb453f408137d7581be309b2fbc6868a80e7ef60c88e689078ee3a296ae71 \ + --hash=sha256:924817ab3141aca17893386ee13261f1d100d1ef410d70afe4389f2359fea4f0 \ + --hash=sha256:93c2af9e01e0ef80d95ae3c720be101227edae5f2fe7e3dc63d8857fadfc5a1d \ + --hash=sha256:97c2b54ff6717a7a563b72627990bec60d8029df17df423f0ed37d56a17a176b \ + --hash=sha256:9be2f15e53ce4e83cc08adc29b26fb5978db62ef2a366fbdf716c8a6c8901040 \ + --hash=sha256:9e2c6f77b9ad48ce5603b83b7da9ee3e36b3ab425353f695cba13200c5d96596 \ + --hash=sha256:a28f2612ab566b17f3698b0da021ff9960610301607c9a5e8eaca62f5e1c350a \ + --hash=sha256:a355d99c4c0d8e5b770313b8b247411ed40949ca44e33e46a4789b9293a907ee \ + --hash=sha256:a3b4350b13cc0e6f5bec8fa7caf29a8fb8cdc051a3bae45cfbfd7ce64f009965 \ + --hash=sha256:aaab0e307e344cb28d800957ef3ec16605146ef0e59e059a60a176d19543d1b7 \ + --hash=sha256:ac1e7817fd0ed3d14fd7c5df91daed84c48e4c2a11ee99c0547f9f62fdae13da \ + --hash=sha256:adfab487facf03f0d0857b8710cf82d0704a309d8ffc33b03d9302b4c64e91a9 \ + --hash=sha256:b6d7ab1f01aa753188605b09a51faa44a3327400b00b8cce424c71910fc0a128 \ + --hash=sha256:bacdb58d9939d95cc557b4dbaa86527c9db2ac1ed76a18bc8d26f6dc8647d851 \ + --hash=sha256:be46a14693955b3bd96014ccbdb8339ee8c9346fbe11c1b78901b55125f14c73 \ + --hash=sha256:bf512a71a23504ed08103a13c941f763db13fb11177beb3d9244c98c29fb4a61 \ + --hash=sha256:c00e5c884f528c9932d278d5c9cbbea38a6b81eb62c02e06ae53751a83a4d52b \ + --hash=sha256:c25d9e338d5bed46c1632f851babf3d13c78f49a225462017cf5e11e845c5891 \ + --hash=sha256:c336d61d2fe74a3195edc1646d53ff1cddd3a9600b09fa6ab75e5514ba4862a7 \ + --hash=sha256:cc3656283d11540ab0ea01978378e73e10002145117055e03722417aeab30994 \ + --hash=sha256:cf450f498c30af55551ba4f66b9123b7185362ec8b625a773b3d39aa1a717583 \ + --hash=sha256:d0ee06b5b5291f609ddb37b9750985b27bc567791bc87c76a569b3feed8481ac \ + --hash=sha256:d480de377f5b687b6b1bc0c0407426da556e2a757633cc7e4d2e1a057aa688f3 \ + --hash=sha256:d56bc4011975f7460bea7b33e1ff425d2f1adf419935ff6707273c77f8a4ada6 \ + --hash=sha256:dd3c41254ee98604b08bd5b3af5bf0a89740d4ee0711de95b65166bf44091921 \ + --hash=sha256:e0d138c7ae532908cbb342162b2611dbd4d90c941cd25ab82084aaf71d2c0bd0 \ + --hash=sha256:e11769a1dbda4da7b00a76cfffa67aa47cfa66921d2724539eee4b9ede780b79 \ + --hash=sha256:e3f0a41487fd5fad7e760b9e8a90e251e27c2816fbc2cff36a22a0e6bcbbd9dd \ + --hash=sha256:e692aa2d1d604e6ca12d35e51fdc36f4cda6345e28e36374579f7ef3611b3012 \ + --hash=sha256:e70a57ecf89a0f64c24e37f38d3fe217a58169d2fe6ed6d70554964042474023 \ + --hash=sha256:e96baa6820280077a78244b2e06e416480ed859bbd8e5d641cf5742919d8beb4 \ + --hash=sha256:eb5656019db7c4deacf0c1a55a898c5bb8f989be904597fcb5232a2f4828fa05 \ + --hash=sha256:eca45e982fa074090057132e30585a7e8674e9e885d402eae85633e9f449ce6c \ + --hash=sha256:f0af2bd2bc204fa27f3d6711d0f360e6b8c684a035206257a81673ab924aa11e \ + --hash=sha256:f7cdf7f26c2286ffb02e46d7bac56c94655540b26347673bea15fa52a6af17e9 \ + --hash=sha256:fd1a720332ea335ceb544cf0a03f81df92abd4bb887679fd1e460976b0e6214b \ + --hash=sha256:ff8baf1f8d3f4b6b7257fcb75a501f2a5499d0dda57645baa09d4d0d34b19444 # via mypy locket==1.0.0 \ --hash=sha256:5c0d4c052a8bbbf750e056a8e65ccd309086f4f0f18a2eac306a8dfa4112a632 \ @@ -1297,9 +1307,9 @@ markupsafe==3.0.3 \ --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \ --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50 # via jinja2 -mcp==1.26.0 \ - --hash=sha256:904a21c33c25aa98ddbeb47273033c435e595bbacfdb177f4bd87f6dceebe1ca \ - --hash=sha256:db6e2ef491eecc1a0d93711a76f28dec2e05999f93afd48795da1c1137142c66 +mcp==1.27.0 \ + --hash=sha256:5ce1fa81614958e267b21fb2aa34e0aea8e2c6ede60d52aba45fd47246b4d741 \ + --hash=sha256:d3dc35a7eec0d458c1da4976a48f982097ddaab87e278c5511d5a4a56e852b83 # via fastapi-mcp mdurl==0.1.2 \ --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ @@ -1313,128 +1323,114 @@ milvus-lite==2.4.12 \ # via # feast (pyproject.toml) # pymilvus -mmh3==5.2.0 \ - --hash=sha256:03e08c6ebaf666ec1e3d6ea657a2d363bb01effd1a9acfe41f9197decaef0051 \ - --hash=sha256:097e13c8b8a66c5753c6968b7640faefe85d8e38992703c1f666eda6ef4c3762 \ - --hash=sha256:0b898cecff57442724a0f52bf42c2de42de63083a91008fb452887e372f9c328 \ - --hash=sha256:10983c10f5c77683bd845751905ba535ec47409874acc759d5ce3ff7ef34398a \ - --hash=sha256:11730eeb16dfcf9674fdea9bb6b8e6dd9b40813b7eb839bc35113649eef38aeb \ - --hash=sha256:127c95336f2a98c51e7682341ab7cb0be3adb9df0819ab8505a726ed1801876d \ - --hash=sha256:12da42c0a55c9d86ab566395324213c319c73ecb0c239fad4726324212b9441c \ - --hash=sha256:132dd943451a7c7546978863d2f5a64977928410782e1a87d583cb60eb89e667 \ - --hash=sha256:1556e31e4bd0ac0c17eaf220be17a09c171d7396919c3794274cb3415a9d3646 \ - --hash=sha256:1a5f4d2e59d6bba8ef01b013c472741835ad961e7c28f50c82b27c57748744a4 \ - --hash=sha256:1ba55d6ca32eeef8b2625e1e4bfc3b3db52bc63014bd7e5df8cc11bf2b036b12 \ - --hash=sha256:1efc8fec8478e9243a78bb993422cf79f8ff85cb4cf6b79647480a31e0d950a8 \ - --hash=sha256:1f8d8b627799f4e2fcc7c034fed8f5f24dc7724ff52f69838a3d6d15f1ad4765 \ - --hash=sha256:1fae471339ae1b9c641f19cf46dfe6ffd7f64b1fba7c4333b99fa3dd7f21ae0a \ - --hash=sha256:1fdb36b940e9261aff0b5177c5b74a36936b902f473180f6c15bde26143681a9 \ - --hash=sha256:2421b9d665a0b1ad724ec7332fb5a98d075f50bc51a6ff854f3a1882bd650d49 \ - --hash=sha256:29c2b9ce61886809d0492a274a5a53047742dea0f703f9c4d5d223c3ea6377d3 \ - --hash=sha256:2c9da0d568569cc87315cb063486d761e38458b8ad513fedd3dc9263e1b81bcd \ - --hash=sha256:2ebfc46b39168ab1cd44670a32ea5489bcbc74a25795c61b6d888c5c2cf654ed \ - --hash=sha256:3193752fc05ea72366c2b63ff24b9a190f422e32d75fdeae71087c08fff26115 \ - --hash=sha256:33576136c06b46a7046b6d83a3d75fbca7d25f84cec743f1ae156362608dc6d2 \ - --hash=sha256:37a358cc881fe796e099c1db6ce07ff757f088827b4e8467ac52b7a7ffdca647 \ - --hash=sha256:382a6bb3f8c6532ea084e7acc5be6ae0c6effa529240836d59352398f002e3fc \ - --hash=sha256:384eda9361a7bf83a85e09447e1feafe081034af9dd428893701b959230d84be \ - --hash=sha256:38d899a156549da8ef6a9f1d6f7ef231228d29f8f69bce2ee12f5fba6d6fd7c5 \ - --hash=sha256:3bc244802ccab5220008cb712ca1508cb6a12f0eb64ad62997156410579a1770 \ - --hash=sha256:3c6041fd9d5fb5fcac57d5c80f521a36b74aea06b8566431c63e4ffc49aced51 \ - --hash=sha256:3ca975c51c5028947bbcfc24966517aac06a01d6c921e30f7c5383c195f87991 \ - --hash=sha256:3d6bfd9662a20c054bc216f861fa330c2dac7c81e7fb8307b5e32ab5b9b4d2e0 \ - --hash=sha256:419005f84ba1cab47a77465a2a843562dadadd6671b8758bf179d82a15ca63eb \ - --hash=sha256:45b590e31bc552c6f8e2150ff1ad0c28dd151e9f87589e7eaf508fbdd8e8e908 \ - --hash=sha256:49037d417419863b222ae47ee562b2de9c3416add0a45c8d7f4e864be8dc4f89 \ - --hash=sha256:4a5f5536b1cbfa72318ab3bfc8a8188b949260baed186b75f0abc75b95d8c051 \ - --hash=sha256:582f9dbeefe15c32a5fa528b79b088b599a1dfe290a4436351c6090f90ddebb8 \ - --hash=sha256:58477cf9ef16664d1ce2b038f87d2dc96d70fe50733a34a7f07da6c9a5e3538c \ - --hash=sha256:58981d6ea9646dbbf9e59a30890cbf9f610df0e4a57dbfe09215116fd90b0093 \ - --hash=sha256:5a5dba98e514fb26241868f6eb90a7f7ca0e039aed779342965ce24ea32ba513 \ - --hash=sha256:5b0b58215befe0f0e120b828f7645e97719bbba9f23b69e268ed0ac7adde8645 \ - --hash=sha256:61ac226af521a572700f863d6ecddc6ece97220ce7174e311948ff8c8919a363 \ - --hash=sha256:63830f846797187c5d3e2dae50f0848fdc86032f5bfdc58ae352f02f857e9025 \ - --hash=sha256:69fc339d7202bea69ef9bd7c39bfdf9fdabc8e6822a01eba62fb43233c1b3932 \ - --hash=sha256:6d541038b3fc360ec538fc116de87462627944765a6750308118f8b509a8eec7 \ - --hash=sha256:6ecb4e750d712abde046858ee6992b65c93f1f71b397fce7975c3860c07365d2 \ - --hash=sha256:72d80005b7634a3a2220f81fbeb94775ebd12794623bb2e1451701ea732b4aa3 \ - --hash=sha256:7303aab41e97adcf010a09efd8f1403e719e59b7705d5e3cfed3dd7571589290 \ - --hash=sha256:7434a27754049144539d2099a6d2da5d88b8bdeedf935180bf42ad59b3607aa3 \ - --hash=sha256:746a5ee71c6d1103d9b560fa147881b5e68fd35da56e54e03d5acefad0e7c055 \ - --hash=sha256:7733ec52296fc1ba22e9b90a245c821adbb943e98c91d8a330a2254612726106 \ - --hash=sha256:7901c893e704ee3c65f92d39b951f8f34ccf8e8566768c58103fb10e55afb8c1 \ - --hash=sha256:7aa18cdb58983ee660c9c400b46272e14fa253c675ed963d3812487f8ca42037 \ - --hash=sha256:7b986d506a8e8ea345791897ba5d8ba0d9d8820cd4fc3e52dbe6de19388de2e7 \ - --hash=sha256:7bbb0df897944b5ec830f3ad883e32c5a7375370a521565f5fe24443bfb2c4f7 \ - --hash=sha256:7c7f0b342fd06044bedd0b6e72177ddc0076f54fd89ee239447f8b271d919d9b \ - --hash=sha256:7e5634565367b6d98dc4aa2983703526ef556b3688ba3065edb4b9b90ede1c54 \ - --hash=sha256:7fddccd4113e7b736706e17a239a696332360cbaddf25ae75b57ba1acce65081 \ - --hash=sha256:81c504ad11c588c8629536b032940f2a359dda3b6cbfd4ad8f74cb24dcd1b0bc \ - --hash=sha256:81df0dae22cd0da87f1c978602750f33d17fb3d21fb0f326c89dc89834fea79b \ - --hash=sha256:86d1be5d63232e6eb93c50881aea55ff06eb86d8e08f9b5417c8c9b10db9db96 \ - --hash=sha256:8b0c53fe0994beade1ad7c0f13bd6fec980a0664bfbe5a6a7d64500b9ab76772 \ - --hash=sha256:8ebf241072cf2777a492d0e09252f8cc2b3edd07dfdb9404b9757bffeb4f2cee \ - --hash=sha256:931d47e08c9c8a67bf75d82f0ada8399eac18b03388818b62bfa42882d571d72 \ - --hash=sha256:932a6eec1d2e2c3c9e630d10f7128d80e70e2d47fe6b8c7ea5e1afbd98733e65 \ - --hash=sha256:941603bfd75a46023807511c1ac2f1b0f39cccc393c15039969806063b27e6db \ - --hash=sha256:956127e663d05edbeec54df38885d943dfa27406594c411139690485128525de \ - --hash=sha256:96f1e1ac44cbb42bcc406e509f70c9af42c594e72ccc7b1257f97554204445f0 \ - --hash=sha256:99bb6a4d809aa4e528ddfe2c85dd5239b78b9dd14be62cca0329db78505e7b50 \ - --hash=sha256:9f64bf06f4bf623325fda3a6d02d36cd69199b9ace99b04bb2d7fd9f89688504 \ - --hash=sha256:a094319ec0db52a04af9fdc391b4d39a1bc72bc8424b47c4411afb05413a44b5 \ - --hash=sha256:a367d4741ac0103f8198c82f429bccb9359f543ca542b06a51f4f0332e8de279 \ - --hash=sha256:a7c0c7845566b9686480e6a7e9044db4afb60038d5fabd19227443f0104eeee4 \ - --hash=sha256:aa6e5d31fdc5ed9e3e95f9873508615a778fe9b523d52c17fc770a3eb39ab6e4 \ - --hash=sha256:ae9d032488fcec32d22be6542d1a836f00247f40f320844dbb361393b5b22773 \ - --hash=sha256:b0271ac12415afd3171ab9a3c7cbfc71dee2c68760a7dc9d05bf8ed6ddfa3a7a \ - --hash=sha256:b0d753ad566c721faa33db7e2e0eddd74b224cdd3eaf8481d76c926603c7a00e \ - --hash=sha256:b29044e1ffdb84fe164d0a7ea05c7316afea93c00f8ed9449cf357c36fc4f814 \ - --hash=sha256:b5995088dd7023d2d9f310a0c67de5a2b2e06a570ecfd00f9ff4ab94a67cde43 \ - --hash=sha256:b5f317a727bba0e633a12e71228bc6a4acb4f471a98b1c003163b917311ea9a9 \ - --hash=sha256:b9a87025121d1c448f24f27ff53a5fe7b6ef980574b4a4f11acaabe702420d63 \ - --hash=sha256:bb0fdc451fb6d86d81ab8f23d881b8d6e37fc373a2deae1c02d27002d2ad7a05 \ - --hash=sha256:bb4fe46bdc6104fbc28db7a6bacb115ee6368ff993366bbd8a2a7f0076e6f0c0 \ - --hash=sha256:bc44fc2b886243d7c0d8daeb37864e16f232e5b56aaec27cc781d848264cfd28 \ - --hash=sha256:bdde97310d59604f2a9119322f61b31546748499a21b44f6715e8ced9308a6c5 \ - --hash=sha256:be1374df449465c9f2500e62eee73a39db62152a8bdfbe12ec5b5c1cd451344d \ - --hash=sha256:be7d3dca9358e01dab1bad881fb2b4e8730cec58d36dd44482bc068bfcd3bc65 \ - --hash=sha256:bf7bee43e17e81671c447e9c83499f53d99bf440bc6d9dc26a841e21acfbe094 \ - --hash=sha256:c3dca4cb5b946ee91b3d6bb700d137b1cd85c20827f89fdf9c16258253489044 \ - --hash=sha256:c3f563e8901960e2eaa64c8e8821895818acabeb41c96f2efbb936f65dbe486c \ - --hash=sha256:c463d7c1c4cfc9d751efeaadd936bbba07b5b0ed81a012b3a9f5a12f0872bd6e \ - --hash=sha256:c4a2f3d83879e3de2eb8cbf562e71563a8ed15ee9b9c2e77ca5d9f73072ac15c \ - --hash=sha256:c5584061fd3da584659b13587f26c6cad25a096246a481636d64375d0c1f6c07 \ - --hash=sha256:c677d78887244bf3095020b73c42b505b700f801c690f8eaa90ad12d3179612f \ - --hash=sha256:c903e71fd8debb35ad2a4184c1316b3cb22f64ce517b4e6747f25b0a34e41266 \ - --hash=sha256:c9ff37ba9f15637e424c2ab57a1a590c52897c845b768e4e0a4958084ec87f22 \ - --hash=sha256:cadc16e8ea64b5d9a47363013e2bea469e121e6e7cb416a7593aeb24f2ad122e \ - --hash=sha256:cedac4f4054b8f7859e5aed41aaa31ad03fce6851901a7fdc2af0275ac533c10 \ - --hash=sha256:d22c9dcafed659fadc605538946c041722b6d1104fe619dbf5cc73b3c8a0ded8 \ - --hash=sha256:d765058da196f68dc721116cab335e696e87e76720e6ef8ee5a24801af65e63d \ - --hash=sha256:d86651fa45799530885ba4dab3d21144486ed15285e8784181a0ab37a4552384 \ - --hash=sha256:dd966df3489ec13848d6c6303429bbace94a153f43d1ae2a55115fd36fd5ca5d \ - --hash=sha256:ddc63328889bcaee77b743309e5c7d2d52cee0d7d577837c91b6e7cc9e755e0b \ - --hash=sha256:dfbead5575f6470c17e955b94f92d62a03dfc3d07f2e6f817d9b93dc211a1515 \ - --hash=sha256:e0f3ed828d709f5b82d8bfe14f8856120718ec4bd44a5b26102c3030a1e12501 \ - --hash=sha256:e1861fb6b1d0453ed7293200139c0a9011eeb1376632e048e3766945b13313c5 \ - --hash=sha256:e5015f0bb6eb50008bed2d4b1ce0f2a294698a926111e4bb202c0987b4f89078 \ - --hash=sha256:e651e17bfde5840e9e4174b01e9e080ce49277b70d424308b36a7969d0d1af73 \ - --hash=sha256:e7884931fe5e788163e7b3c511614130c2c59feffdc21112290a194487efb2e9 \ - --hash=sha256:e79c00eba78f7258e5b354eccd4d7907d60317ced924ea4a5f2e9d83f5453065 \ - --hash=sha256:e912b19cf2378f2967d0c08e86ff4c6c360129887f678e27e4dde970d21b3f4d \ - --hash=sha256:e9a011469b47b752e7d20de296bb34591cdfcbe76c99c2e863ceaa2aa61113d2 \ - --hash=sha256:eb756caf8975882630ce4e9fbbeb9d3401242a72528230422c9ab3a0d278e60c \ - --hash=sha256:eba01ec3bd4a49b9ac5ca2bc6a73ff5f3af53374b8556fcc2966dd2af9eb7779 \ - --hash=sha256:ecbfc0437ddfdced5e7822d1ce4855c9c64f46819d0fdc4482c53f56c707b935 \ - --hash=sha256:eed4bba7ff8a0d37106ba931ab03bdd3915fbb025bcf4e1f0aa02bc8114960c5 \ - --hash=sha256:f35727c5118aba95f0397e18a1a5b8405425581bfe53e821f0fb444cbdc2bc9b \ - --hash=sha256:f698733a8a494466432d611a8f0d1e026f5286dee051beea4b3c3146817e35d5 \ - --hash=sha256:f7f9034c7cf05ddfaac8d7a2e63a3c97a840d4615d0a0e65ba8bdf6f8576e3be \ - --hash=sha256:fa0c966ee727aad5406d516375593c5f058c766b21236ab8985693934bb5085b \ - --hash=sha256:fc9c5f280438cf1c1a8f9abb87dc8ce9630a964120cfb5dd50d1e7ce79690c7a \ - --hash=sha256:fd6e6c3d90660d085f7e73710eab6f5545d4854b81b0135a3526e797009dbda3 \ - --hash=sha256:fdfd3fb739f4e22746e13ad7ba0c6eedf5f454b18d11249724a388868e308ee4 \ - --hash=sha256:ff3d50dc3fe8a98059f99b445dfb62792b5d006c5e0b8f03c6de2813b8376110 +mmh3==5.2.1 \ + --hash=sha256:022aa1a528604e6c83d0a7705fdef0b5355d897a9e0fa3a8d26709ceaa06965d \ + --hash=sha256:0634581290e6714c068f4aa24020acf7880927d1f0084fa753d9799ae9610082 \ + --hash=sha256:08043f7cb1fb9467c3fbbbaea7896986e7fbc81f4d3fd9289a73d9110ab6207a \ + --hash=sha256:0a3984146e414684a6be2862d84fcb1035f4984851cb81b26d933bab6119bf00 \ + --hash=sha256:0bbc17250b10d3466875a40a52520a6bac3c02334ca709207648abd3c223ed5c \ + --hash=sha256:0cc21533878e5586b80d74c281d7f8da7932bc8ace50b8d5f6dbf7e3935f63f1 \ + --hash=sha256:0d0b7e803191db5f714d264044e06189c8ccd3219e936cc184f07106bd17fd7b \ + --hash=sha256:113f78e7463a36dbbcea05bfe688efd7fa759d0f0c56e73c974d60dcfec3dfcc \ + --hash=sha256:169e0d178cb59314456ab30772429a802b25d13227088085b0d49b9fe1533104 \ + --hash=sha256:17fbb47f0885ace8327ce1235d0416dc86a211dcd8cc1e703f41523be32cfec8 \ + --hash=sha256:19bbd3b841174ae6ed588536ab5e1b1fe83d046e668602c20266547298d939a9 \ + --hash=sha256:1d9f9a3ce559a5267014b04b82956993270f63ec91765e13e9fd73daf2d2738e \ + --hash=sha256:1e4ecee40ba19e6975e1120829796770325841c2f153c0e9aecca927194c6a2a \ + --hash=sha256:22b0f9971ec4e07e8223f2beebe96a6cfc779d940b6f27d26604040dd74d3a44 \ + --hash=sha256:26fb5b9c3946bf7f1daed7b37e0c03898a6f062149127570f8ede346390a0825 \ + --hash=sha256:2778fed822d7db23ac5008b181441af0c869455b2e7d001f4019636ac31b6fe4 \ + --hash=sha256:28cfab66577000b9505a0d068c731aee7ca85cd26d4d63881fab17857e0fe1fb \ + --hash=sha256:29bc3973676ae334412efdd367fcd11d036b7be3efc1ce2407ef8676dabfeb82 \ + --hash=sha256:2bd9f19f7f1fcebd74e830f4af0f28adad4975d40d80620be19ffb2b2af56c9f \ + --hash=sha256:2d5d542bf2abd0fd0361e8017d03f7cb5786214ceb4a40eef1539d6585d93386 \ + --hash=sha256:30e4d2084df019880d55f6f7bea35328d9b464ebee090baa372c096dc77556fb \ + --hash=sha256:3619473a0e0d329fd4aec8075628f8f616be2da41605300696206d6f36920c3d \ + --hash=sha256:368625fb01666655985391dbad3860dc0ba7c0d6b9125819f3121ee7292b4ac8 \ + --hash=sha256:3737303ca9ea0f7cb83028781148fcda4f1dac7821db0c47672971dabcf63593 \ + --hash=sha256:3a9fed49c6ce4ed7e73f13182760c65c816da006debe67f37635580dfb0fae00 \ + --hash=sha256:3c38d142c706201db5b2345166eeef1e7740e3e2422b470b8ba5c8727a9b4c7a \ + --hash=sha256:3cb61db880ec11e984348227b333259994c2c85caa775eb7875decb3768db890 \ + --hash=sha256:3d74a03fb57757ece25aa4b3c1c60157a1cece37a020542785f942e2f827eed5 \ + --hash=sha256:3f796b535008708846044c43302719c6956f39ca2d93f2edda5319e79a29efbb \ + --hash=sha256:41105377f6282e8297f182e393a79cfffd521dde37ace52b106373bdcd9ca5cb \ + --hash=sha256:41aac7002a749f08727cb91babff1daf8deac317c0b1f317adc69be0e6c375d1 \ + --hash=sha256:44983e45310ee5b9f73397350251cdf6e63a466406a105f1d16cb5baa659270b \ + --hash=sha256:4cbbde66f1183db040daede83dd86c06d663c5bb2af6de1142b7c8c37923dd74 \ + --hash=sha256:4eda76074cfca2787c8cf1bec603eaebdddd8b061ad5502f85cddae998d54f00 \ + --hash=sha256:4fc6cd65dc4d2fdb2625e288939a3566e36127a84811a4913f02f3d5931da52d \ + --hash=sha256:50885073e2909251d4718634a191c49ae5f527e5e1736d738e365c3e8be8f22b \ + --hash=sha256:5174a697ce042fa77c407e05efe41e03aa56dae9ec67388055820fb48cf4c3ba \ + --hash=sha256:54b64fb2433bc71488e7a449603bf8bd31fbcf9cb56fbe1eb6d459e90b86c37b \ + --hash=sha256:54fe8518abe06a4c3852754bfd498b30cc58e667f376c513eac89a244ce781a4 \ + --hash=sha256:55dbbd8ffbc40d1697d5e2d0375b08599dae8746b0b08dea05eee4ce81648fac \ + --hash=sha256:57b52603e89355ff318025dd55158f6e71396c0f1f609d548e9ea9c94cc6ce0a \ + --hash=sha256:58370d05d033ee97224c81263af123dea3d931025030fd34b61227a768a8858a \ + --hash=sha256:5d87a3584093e1a89987e3d36d82c98d9621b2cb944e22a420aa1401e096758f \ + --hash=sha256:623f938f6a039536cc02b7582a07a080f13fdfd48f87e63201d92d7e34d09a18 \ + --hash=sha256:62815d2c67f2dd1be76a253d88af4e1da19aeaa1820146dec52cf8bee2958b16 \ + --hash=sha256:6290289fa5fb4c70fd7f72016e03633d60388185483ff3b162912c81205ae2cf \ + --hash=sha256:67e41a497bac88cc1de96eeba56eeb933c39d54bc227352f8455aa87c4ca4000 \ + --hash=sha256:6c85c38a279ca9295a69b9b088a2e48aa49737bb1b34e6a9dc6297c110e8d912 \ + --hash=sha256:6f01f044112d43a20be2f13a11683666d87151542ad627fe41a18b9791d2802f \ + --hash=sha256:707151644085dd0f20fe4f4b573d28e5130c4aaa5f587e95b60989c5926653b5 \ + --hash=sha256:723b2681ed4cc07d3401bbea9c201ad4f2a4ca6ba8cddaff6789f715dd2b391e \ + --hash=sha256:72d1cc63bcc91e14933f77d51b3df899d6a07d184ec515ea7f56bff659e124d7 \ + --hash=sha256:7374d6e3ef72afe49697ecd683f3da12f4fc06af2d75433d0580c6746d2fa025 \ + --hash=sha256:7501e9be34cb21e72fcfe672aafd0eee65c16ba2afa9dcb5500a587d3a0580f0 \ + --hash=sha256:76219cd1eefb9bf4af7856e3ae563d15158efa145c0aab01e9933051a1954045 \ + --hash=sha256:7aec798c2b01aaa65a55f1124f3405804184373abb318a3091325aece235f67c \ + --hash=sha256:7be6dfb49e48fd0a7d91ff758a2b51336f1cd21f9d44b20f6801f072bd080cdd \ + --hash=sha256:7e4e1f580033335c6f76d1e0d6b56baf009d1a64d6a4816347e4271ba951f46d \ + --hash=sha256:7e8ec5f606e0809426d2440e0683509fb605a8820a21ebd120dcdba61b74ef7f \ + --hash=sha256:7f196cd7910d71e9d9860da0ff7a77f64d22c1ad931f1dd18559a06e03109fc0 \ + --hash=sha256:82f3802bfc4751f420d591c5c864de538b71cea117fce67e4595c2afede08a15 \ + --hash=sha256:85ffc9920ffc39c5eee1e3ac9100c913a0973996fbad5111f939bbda49204bb7 \ + --hash=sha256:8e6c219e375f6341d0959af814296372d265a8ca1af63825f65e2e87c618f006 \ + --hash=sha256:8f767ba0911602ddef289404e33835a61168314ebd3c729833db2ed685824211 \ + --hash=sha256:8ff038d52ef6aa0f309feeba00c5095c9118d0abf787e8e8454d6048db2037fc \ + --hash=sha256:915e7a2418f10bd1151b1953df06d896db9783c9cfdb9a8ee1f9b3a4331ab503 \ + --hash=sha256:92883836caf50d5255be03d988d75bc93e3f86ba247b7ca137347c323f731deb \ + --hash=sha256:960b1b3efa39872ac8b6cc3a556edd6fb90ed74f08c9c45e028f1005b26aa55d \ + --hash=sha256:9aeaf53eaa075dd63e81512522fd180097312fb2c9f476333309184285c49ce0 \ + --hash=sha256:9d8089d853c7963a8ce87fff93e2a67075c0bc08684a08ea6ad13577c38ffc38 \ + --hash=sha256:a4130d0b9ce5fad6af07421b1aecc7e079519f70d6c05729ab871794eded8617 \ + --hash=sha256:a482ac121de6973897c92c2f31defc6bafb11c83825109275cffce54bb64933f \ + --hash=sha256:add7ac388d1e0bf57259afbcf9ed05621a3bf11ce5ee337e7536f1e1aaf056b0 \ + --hash=sha256:b1f12bd684887a0a5d55e6363ca87056f361e45451105012d329b86ec19dbe0b \ + --hash=sha256:b3f99e1756fc48ad507b95e5d86f2fb21b3d495012ff13e6592ebac14033f166 \ + --hash=sha256:b4cce60d0223074803c9dbe0721ad3fa51dafe7d462fee4b656a1aa01ee07518 \ + --hash=sha256:baeb47635cb33375dee4924cd93d7f5dcaa786c740b08423b0209b824a1ee728 \ + --hash=sha256:bbea5b775f0ac84945191fb83f845a6fd9a21a03ea7f2e187defac7e401616ad \ + --hash=sha256:bbfcb95d9a744e6e2827dfc66ad10e1020e0cac255eb7f85652832d5a264c2fc \ + --hash=sha256:bd6e7d363aa93bd3421b30b6af97064daf47bc96005bddba67c5ffbc6df426b8 \ + --hash=sha256:be77c402d5e882b6fbacfd90823f13da8e0a69658405a39a569c6b58fdb17b03 \ + --hash=sha256:c302245fd6c33d96bd169c7ccf2513c20f4c1e417c07ce9dce107c8bc3f8411f \ + --hash=sha256:c88653877aeb514c089d1b3d473451677b8b9a6d1497dbddf1ae7934518b06d2 \ + --hash=sha256:cae6383181f1e345317742d2ddd88f9e7d2682fa4c9432e3a74e47d92dce0229 \ + --hash=sha256:cd471ede0d802dd936b6fab28188302b2d497f68436025857ca72cd3810423fe \ + --hash=sha256:d106493a60dcb4aef35a0fac85105e150a11cf8bc2b0d388f5a33272d756c966 \ + --hash=sha256:d30b650595fdbe32366b94cb14f30bb2b625e512bd4e1df00611f99dc5c27fd4 \ + --hash=sha256:d51fde50a77f81330523562e3c2734ffdca9c4c9e9d355478117905e1cfe16c6 \ + --hash=sha256:d57dea657357230cc780e13920d7fa7db059d58fe721c80020f94476da4ca0a1 \ + --hash=sha256:d771f085fcdf4035786adfb1d8db026df1eb4b41dac1c3d070d1e49512843227 \ + --hash=sha256:dae0f0bd7d30c0ad61b9a504e8e272cb8391eed3f1587edf933f4f6b33437450 \ + --hash=sha256:db0562c5f71d18596dcd45e854cf2eeba27d7543e1a3acdafb7eef728f7fe85d \ + --hash=sha256:dfd51b4c56b673dfbc43d7d27ef857dd91124801e2806c69bb45585ce0fa019b \ + --hash=sha256:e080c0637aea036f35507e803a4778f119a9b436617694ae1c5c366805f1e997 \ + --hash=sha256:e48d4dbe0f88e53081da605ae68644e5182752803bbc2beb228cca7f1c4454d6 \ + --hash=sha256:e8b4b5580280b9265af3e0409974fb79c64cf7523632d03fbf11df18f8b0181e \ + --hash=sha256:e8b5378de2b139c3a830f0209c1e91f7705919a4b3e563a10955104f5097a70a \ + --hash=sha256:e904f2417f0d6f6d514f3f8b836416c360f306ddaee1f84de8eef1e722d212e5 \ + --hash=sha256:eee884572b06bbe8a2b54f424dbd996139442cf83c76478e1ec162512e0dd2c7 \ + --hash=sha256:f1fbb0a99125b1287c6d9747f937dc66621426836d1a2d50d05aecfc81911b57 \ + --hash=sha256:f40a95186a72fa0b67d15fef0f157bfcda00b4f59c8a07cbe5530d41ac35d105 \ + --hash=sha256:f6e0bfe77d238308839699944164b96a2eeccaf55f2af400f54dc20669d8d5f2 \ + --hash=sha256:f963eafc0a77a6c0562397da004f5876a9bcf7265a7bcc3205e29636bc4a1312 \ + --hash=sha256:fb9d44c25244e11c8be3f12c938ca8ba8404620ef8092245d2093c6ab3df260f \ + --hash=sha256:fc78739b5ec6e4fb02301984a3d442a91406e7700efbe305071e7fd1c78278f2 \ + --hash=sha256:fceef7fe67c81e1585198215e42ad3fdba3a25644beda8fbdaf85f4d7b93175a \ + --hash=sha256:fd96476f04db5ceba1cfa0f21228f67c1f7402296f0e73fee3513aa680ad237b # via feast (pyproject.toml) multidict==6.7.1 \ --hash=sha256:026d264228bcd637d4e060844e39cdc60f86c479e463d49075dedc21b18fbbe0 \ @@ -1587,45 +1583,51 @@ multidict==6.7.1 \ # aiobotocore # aiohttp # yarl -mypy==1.19.1 \ - --hash=sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd \ - --hash=sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b \ - --hash=sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1 \ - --hash=sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba \ - --hash=sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b \ - --hash=sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045 \ - --hash=sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac \ - --hash=sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6 \ - --hash=sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a \ - --hash=sha256:409088884802d511ee52ca067707b90c883426bd95514e8cfda8281dc2effe24 \ - --hash=sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957 \ - --hash=sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042 \ - --hash=sha256:4f28f99c824ecebcdaa2e55d82953e38ff60ee5ec938476796636b86afa3956e \ - --hash=sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec \ - --hash=sha256:7bcfc336a03a1aaa26dfce9fff3e287a3ba99872a157561cbfcebe67c13308e3 \ - --hash=sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718 \ - --hash=sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f \ - --hash=sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331 \ - --hash=sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1 \ - --hash=sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1 \ - --hash=sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13 \ - --hash=sha256:b13cfdd6c87fc3efb69ea4ec18ef79c74c3f98b4e5498ca9b85ab3b2c2329a67 \ - --hash=sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2 \ - --hash=sha256:b7951a701c07ea584c4fe327834b92a30825514c868b1f69c30445093fdd9d5a \ - --hash=sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b \ - --hash=sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8 \ - --hash=sha256:c608937067d2fc5a4dd1a5ce92fd9e1398691b8c5d012d66e1ddd430e9244376 \ - --hash=sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef \ - --hash=sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288 \ - --hash=sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75 \ - --hash=sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74 \ - --hash=sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250 \ - --hash=sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab \ - --hash=sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6 \ - --hash=sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247 \ - --hash=sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925 \ - --hash=sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e \ - --hash=sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e +mypy==1.20.0 \ + --hash=sha256:002b613ae19f4ac7d18b7e168ffe1cb9013b37c57f7411984abbd3b817b0a214 \ + --hash=sha256:00e047c74d3ec6e71a2eb88e9ea551a2edb90c21f993aefa9e0d2a898e0bb732 \ + --hash=sha256:02cca0761c75b42a20a2757ae58713276605eb29a08dd8a6e092aa347c4115ca \ + --hash=sha256:0ecd63f75fdd30327e4ad8b5704bd6d91fc6c1b2e029f8ee14705e1207212489 \ + --hash=sha256:0f42dfaab7ec1baff3b383ad7af562ab0de573c5f6edb44b2dab016082b89948 \ + --hash=sha256:1973868d2adbb4584a3835780b27436f06d1dc606af5be09f187aaa25be1070f \ + --hash=sha256:26c8b52627b6552f47ff11adb4e1509605f094e29815323e487fc0053ebe93d1 \ + --hash=sha256:2721f0ce49cb74a38f00c50da67cb7d36317b5eda38877a49614dc018e91c787 \ + --hash=sha256:2fcedb16d456106e545b2bfd7ef9d24e70b38ec252d2a629823a4d07ebcdb69e \ + --hash=sha256:31b5dbb55293c1bd27c0fc813a0d2bb5ceef9d65ac5afa2e58f829dab7921fd5 \ + --hash=sha256:34506397dbf40c15dc567635d18a21d33827e9ab29014fb83d292a8f4f8953b6 \ + --hash=sha256:367e5c993ba34d5054d11937d0485ad6dfc60ba760fa326c01090fc256adf15c \ + --hash=sha256:379edf079ce44ac8d2805bcf9b3dd7340d4f97aad3a5e0ebabbf9d125b84b442 \ + --hash=sha256:39362cdb4ba5f916e7976fccecaab1ba3a83e35f60fa68b64e9a70e221bb2436 \ + --hash=sha256:4525e7010b1b38334516181c5b81e16180b8e149e6684cee5a727c78186b4e3b \ + --hash=sha256:47781555a7aa5fedcc2d16bcd72e0dc83eb272c10dd657f9fb3f9cc08e2e6abb \ + --hash=sha256:49d11c6f573a5a08f77fad13faff2139f6d0730ebed2cfa9b3d2702671dd7188 \ + --hash=sha256:555493c44a4f5a1b58d611a43333e71a9981c6dbe26270377b6f8174126a0526 \ + --hash=sha256:555658c611099455b2da507582ea20d2043dfdfe7f5ad0add472b1c6238b433f \ + --hash=sha256:697f102c5c1d526bdd761a69f17c6070f9892eebcb94b1a5963d679288c09e78 \ + --hash=sha256:76a70bf840495729be47510856b978f1b0ec7d08f257ca38c9d932720bf6b43e \ + --hash=sha256:7d3243c406773185144527f83be0e0aefc7bf4601b0b2b956665608bf7c98a83 \ + --hash=sha256:931a7630bba591593dcf6e97224a21ff80fb357e7982628d25e3c618e7f598ef \ + --hash=sha256:9804c3ad27f78e54e58b32e7cb532d128b43dbfb9f3f9f06262b821a0f6bd3f5 \ + --hash=sha256:a17c5d0bdcca61ce24a35beb828a2d0d323d3fcf387d7512206888c900193367 \ + --hash=sha256:a6e0641147cbfa7e4e94efdb95c2dab1aff8cfc159ded13e07f308ddccc8c48e \ + --hash=sha256:a79c1eba7ac4209f2d850f0edd0a2f8bba88cbfdfefe6fb76a19e9d4fe5e71a2 \ + --hash=sha256:a9336b5e6712f4adaf5afc3203a99a40b379049104349d747eb3e5a3aa23ac2e \ + --hash=sha256:b20c8b0fd5877abdf402e79a3af987053de07e6fb208c18df6659f708b535134 \ + --hash=sha256:b3a49064504be59e59da664c5e149edc1f26c67c4f8e8456f6ba6aba55033018 \ + --hash=sha256:b503ab55a836136b619b5fc21c8803d810c5b87551af8600b72eecafb0059cb0 \ + --hash=sha256:bd0212976dc57a5bfeede7c219e7cd66568a32c05c9129686dd487c059c1b88a \ + --hash=sha256:c70380fe5d64010f79fb863b9081c7004dd65225d2277333c219d93a10dad4dd \ + --hash=sha256:d99f515f95fd03a90875fdb2cca12ff074aa04490db4d190905851bdf8a549a8 \ + --hash=sha256:e80cf77847d0d3e6e3111b7b25db32a7f8762fd4b9a3a72ce53fe16a2863b281 \ + --hash=sha256:eb96c84efcc33f0b5e0e04beacf00129dd963b67226b01c00b9dfc8affb464c3 \ + --hash=sha256:ebea00201737ad4391142808ed16e875add5c17f676e0912b387739f84991e13 \ + --hash=sha256:efe8d70949c3023698c3fca1e94527e7e790a361ab8116f90d11221421cd8726 \ + --hash=sha256:f13b3e41bce9d257eded794c0f12878af3129d80aacd8a3ee0dee51f3a978651 \ + --hash=sha256:f194db59657c58593a3c47c6dfd7bad4ef4ac12dbc94d01b3a95521f78177e33 \ + --hash=sha256:f49590891d2c2f8a9de15614e32e459a794bcba84693c2394291a2038bbaaa69 \ + --hash=sha256:f75ff57defcd0f1d6e006d721ccdec6c88d4f6a7816eb92f1c4890d979d9ee62 \ + --hash=sha256:f799d9db89fc00446f03281f84a221e50018fc40113a3ba9864b132895619ebe \ + --hash=sha256:f8426d4d75d68714abc17a4292d922f6ba2cfb984b72c2278c437f6dae797865 # via sqlalchemy mypy-extensions==1.1.0 \ --hash=sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505 \ @@ -1774,9 +1776,9 @@ pandas==2.3.3 \ # pandas-gbq # pymilvus # snowflake-connector-python -pandas-gbq==0.33.0 \ - --hash=sha256:499ad18a7b1917e2cc04bbd763ec37c11ecc49030348c45cebb9cbbdb7f909af \ - --hash=sha256:61357e11d73e0ae57cbff31e71fc3ed83da3d16b58b653f715b32ad760527e34 +pandas-gbq==0.34.1 \ + --hash=sha256:6bea5b85937251b976cf9db38151ea59abbff98771179183488d4614694bff67 \ + --hash=sha256:b74932c6ee35dfc81582f39c792e3a68c9ef9bee8c85f25667d9d05dfadd0daf # via google-cloud-bigquery parsy==2.2 \ --hash=sha256:5e981613d9d2d8b68012d1dd0afe928967bea2e4eefdb76c2f545af0dd02a9e7 \ @@ -1790,9 +1792,9 @@ pathspec==1.0.4 \ --hash=sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645 \ --hash=sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723 # via mypy -platformdirs==4.9.2 \ - --hash=sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd \ - --hash=sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291 +platformdirs==4.9.4 \ + --hash=sha256:1ec356301b7dc906d83f371c8f487070e99d3ccf9e501686456394622a01a934 \ + --hash=sha256:68a9a4619a666ea6439f2ff250c12a853cd1cbd5158d258bd824a7df6be2f868 # via snowflake-connector-python prometheus-client==0.24.1 \ --hash=sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055 \ @@ -1924,25 +1926,25 @@ propcache==0.4.1 \ # via # aiohttp # yarl -proto-plus==1.27.1 \ - --hash=sha256:912a7460446625b792f6448bade9e55cd4e41e6ac10e27009ef71a7f317fa147 \ - --hash=sha256:e4643061f3a4d0de092d62aa4ad09fa4756b2cbb89d4627f3985018216f9fefc +proto-plus==1.27.2 \ + --hash=sha256:6432f75893d3b9e70b9c412f1d2f03f65b11fb164b793d14ae2ca01821d22718 \ + --hash=sha256:b2adde53adadf75737c44d3dcb0104fde65250dfc83ad59168b4aa3e574b6a24 # via # google-api-core # google-cloud-bigquery-storage # google-cloud-bigtable # google-cloud-datastore -protobuf==6.33.5 \ - --hash=sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c \ - --hash=sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02 \ - --hash=sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c \ - --hash=sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd \ - --hash=sha256:8f04fa32763dcdb4973d537d6b54e615cc61108c7cb38fe59310c3192d29510a \ - --hash=sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190 \ - --hash=sha256:a3157e62729aafb8df6da2c03aa5c0937c7266c626ce11a278b6eb7963c4e37c \ - --hash=sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5 \ - --hash=sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0 \ - --hash=sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b +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) # google-api-core @@ -2055,12 +2057,10 @@ pyarrow-hotfix==0.7 \ --hash=sha256:3236f3b5f1260f0e2ac070a55c1a7b339c4bb7267839bd2015e283234e758100 \ --hash=sha256:59399cd58bdd978b2e42816a4183a55c6472d4e33d183351b6069f11ed42661d # via ibis-framework -pyasn1==0.6.2 \ - --hash=sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf \ - --hash=sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b - # via - # pyasn1-modules - # rsa +pyasn1==0.6.3 \ + --hash=sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf \ + --hash=sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde + # via pyasn1-modules pyasn1-modules==0.4.2 \ --hash=sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a \ --hash=sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6 @@ -2201,9 +2201,9 @@ pydantic-core==2.41.5 \ --hash=sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425 \ --hash=sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52 # via pydantic -pydantic-settings==2.13.0 \ - --hash=sha256:95d875514610e8595672800a5c40b073e99e4aae467fa7c8f9c263061ea2e1fe \ - --hash=sha256:d67b576fff39cd086b595441bf9c75d4193ca9c0ed643b90360694d0f1240246 +pydantic-settings==2.13.1 \ + --hash=sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025 \ + --hash=sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237 # via # fastapi-mcp # mcp @@ -2211,15 +2211,15 @@ pydata-google-auth==1.9.1 \ --hash=sha256:0a51ce41c601ca0bc69b8795bf58bedff74b4a6a007c9106c7cbcdec00eaced2 \ --hash=sha256:75ffce5d106e34b717b31844c1639ea505b7d9550dc23b96fb6c20d086b53fa3 # via pandas-gbq -pygments==2.19.2 \ - --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \ - --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b +pygments==2.20.0 \ + --hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \ + --hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176 # via # feast (pyproject.toml) # rich -pyjwt[crypto]==2.11.0 \ - --hash=sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623 \ - --hash=sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469 +pyjwt[crypto]==2.12.1 \ + --hash=sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c \ + --hash=sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b # via # feast (pyproject.toml) # mcp @@ -2232,9 +2232,9 @@ pymysql==1.1.2 \ --hash=sha256:4961d3e165614ae65014e361811a724e2044ad3ea3739de9903ae7c21f539f03 \ --hash=sha256:e6b1d89711dd51f8f74b1631fe08f039e7d76cf67a42a323d3178f0f25762ed9 # via feast (pyproject.toml) -pyopenssl==25.3.0 \ - --hash=sha256:1fda6fc034d5e3d179d39e59c1895c9faeaf40a79de5fc4cbbfbe0d36f4a77b6 \ - --hash=sha256:c981cb0a3fd84e8602d7afc209522773b94c1c2446a3c710a75b06fe1beae329 +pyopenssl==26.0.0 \ + --hash=sha256:df94d28498848b98cc1c0ffb8ef1e71e40210d3b0a8064c9d29571ed2904bf81 \ + --hash=sha256:f293934e52936f2e3413b89c6ce36df66a0b34ae1ea3a053b8c5020ff2f513fc # via snowflake-connector-python python-dateutil==2.9.0.post0 \ --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ @@ -2246,9 +2246,9 @@ python-dateutil==2.9.0.post0 \ # ibis-framework # kubernetes # pandas -python-dotenv==1.2.1 \ - --hash=sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6 \ - --hash=sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61 +python-dotenv==1.2.2 \ + --hash=sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a \ + --hash=sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3 # via # pydantic-settings # pymilvus @@ -2257,9 +2257,9 @@ python-multipart==0.0.22 \ --hash=sha256:2b2cd894c83d21bf49d702499531c7bafd057d730c201782048f7945d82de155 \ --hash=sha256:7340bef99a7e0032613f56dc36027b959fd3b30a787ed62d310e951f7c3a3a58 # via mcp -pytz==2025.2 \ - --hash=sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3 \ - --hash=sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00 +pytz==2026.1.post1 \ + --hash=sha256:3378dde6a0c3d26719182142c56e60c7f9af7e968076f31aae569d72a0358ee1 \ + --hash=sha256:f2fd16142fda348286a75e1a524be810bb05d444e5a081f37f7affc635035f7a # via # pandas # snowflake-connector-python @@ -2352,9 +2352,9 @@ referencing==0.37.0 \ # via # jsonschema # jsonschema-specifications -requests==2.32.5 \ - --hash=sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6 \ - --hash=sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf +requests==2.33.1 \ + --hash=sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517 \ + --hash=sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a # via # feast (pyproject.toml) # fastapi-mcp @@ -2370,9 +2370,9 @@ requests-oauthlib==2.0.0 \ # via # google-auth-oauthlib # kubernetes -rich==14.3.2 \ - --hash=sha256:08e67c3e90884651da3239ea668222d19bea7b589149d8014a21c633420dbb69 \ - --hash=sha256:e712f11c1a562a11843306f5ed999475f09ac31ffb64281f73ab29ffdda8b3b8 +rich==14.3.3 \ + --hash=sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d \ + --hash=sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b # via # fastapi-mcp # ibis-framework @@ -2496,10 +2496,6 @@ rpds-py==0.30.0 \ # via # jsonschema # referencing -rsa==4.9.1 \ - --hash=sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762 \ - --hash=sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75 - # via google-auth s3transfer==0.13.1 \ --hash=sha256:a981aa7429be23fe6dfc13e80e4020057cbab622b08c0315288758d67cabc724 \ --hash=sha256:c3fdba22ba1bd367922f27ec8032d6a1cf5f10c934fb5d68cf60fd5a23d936cf @@ -2522,117 +2518,120 @@ six==1.17.0 \ # via # kubernetes # python-dateutil -snowflake-connector-python[pandas]==4.3.0 \ - --hash=sha256:08f5167a10d380fe66330d5b19d19bd8b4f4af27e9648e3b254e61da025646bf \ - --hash=sha256:120463ca391d9deda3bdb185104ba847e12f73c86ef411cfcf827ce49b64d1af \ - --hash=sha256:26a65c5c93d14c4d221b780fdb2f07b4dd83e848f39eabd4832778bf0e2694d4 \ - --hash=sha256:2e0f66acee330388815fb842f91a46c9cacdefdf02c816354e6adeca8c2c3f86 \ - --hash=sha256:3e2ce47485862fa14ffbf2732f0fd02aa69a7c68a50d5f6286f34ed17527cf87 \ - --hash=sha256:486d17332b9228d2e5975755b434e6a282756a447e0c6605d4e797944fa919da \ - --hash=sha256:55163c5d9b93e10d7217aabd56f776b16c0fe13774f8d5db9188824731da9586 \ - --hash=sha256:676b56eedcc268b7e25a447e736eb8bf8bcacfbc71196c94d6f45746672ee6d5 \ - --hash=sha256:726435b2769135b6282601efb2cd8fd53f7deb1ff2fb7da93d28141fa3c8b17e \ - --hash=sha256:762ffa9673465ccc630aba438d648e0b1a2452ba49669a54a60d1625f36898f3 \ - --hash=sha256:7763c0d5f8e6326ec31f8972cc806fb6d3e07b06ca59f67dfcdf02a34219bcbc \ - --hash=sha256:79cbf5e359cfc33b4c4307df1fe8f78cd5aee56f5c50b98a647fa0cd9ba82cfc \ - --hash=sha256:79f150297b39cfd2481b732554fc4d68b43c83c82eb01e670cc4051cffc089d6 \ - --hash=sha256:7c18b5021ffa6de8313f2c7f0ae6050c36bcee7cb33bb23d40a7fdf3e0a751f2 \ - --hash=sha256:9faa9280e41258fb479ec5395b6a17d3dbb316146832e436aed582b300de655e \ - --hash=sha256:ac18b37e03a29014a9c91aac10c7dbdfa11134c620c6f93dd16f4b99b6a38c2a \ - --hash=sha256:b5a8d91c3e0127360bc3de605df9d02ea4d87e4524a50bf2e7c5c4200f9abf78 \ - --hash=sha256:c1356a2c615e120f913e5235fe87ff8aadbb479ad5a5ac5c0a84881d5fbe981d \ - --hash=sha256:c6fa80373b82125552e691f47b603766ed783f3d90a5782564854aa224aee9d1 \ - --hash=sha256:ca9d22c61f4e3d171b0adad3e9211747917c3a978dfb99564307c1ceadb0f0cd \ - --hash=sha256:ce55b93120f8b429010bf39cc02e739610b6da2ccdd34fcfc0df04849d0fd9d4 \ - --hash=sha256:e3044e6a237b35f750394f199f5e3800dfeb3227c4c8562584877e814d2dc89a \ - --hash=sha256:e42dd9af46fa3ad0e61c1aa6a227357cace481916797ecb92dbb14adb61931e1 \ - --hash=sha256:e5d360d65d42dd97cf82e688a1a7f235b9bc048b4949c9c5c7052ff2783c444e \ - --hash=sha256:e96aaf23f2b021e0d2aac8ac1b541975cd1f6896d9115eefe0938114e694a562 \ - --hash=sha256:f5291c00f610b266ab8c79b1e008b3d0cb29bb5b86a0007529320921b4a3fc3c +snowflake-connector-python[pandas]==4.4.0 \ + --hash=sha256:16fdca775f7ca5ce4a973c07c434f5ab72bef5284e81a5e4ae2fb4d54d28965c \ + --hash=sha256:19d0c1ed033abae715a71b74c53010b180a5247c6924f851e4f7d0b0d58066c4 \ + --hash=sha256:2a6f6a514a10c3bb2d4554132f0b639f43d7e9fbb73fa1fae1c8a75333102686 \ + --hash=sha256:307f41326c702f6976746d2001dacf35adaf567f3f12afb3a5778fbb063c7241 \ + --hash=sha256:43e1a2f3ac51d24406d4eb0c23a8ceb9d6f5cb4854c941e5e1375d8c481e2844 \ + --hash=sha256:52efe2d6543a09807283748dd50a36ec01d52b4f342868132f8f9856b9c95a42 \ + --hash=sha256:56ff04dd9e17edc82128f412aa3776687dc94088f3d6b9144971e169952623cb \ + --hash=sha256:648f49029d699591af0f253e81c5bf60efc4411c7b0149ef074a59a038210a3b \ + --hash=sha256:693a1bef97509f09b7e6f42ea6f743d27819413c04fb3dc543b060d029871c56 \ + --hash=sha256:70d4051e2d9c87258b02672e17e21f5873e0cb49ff9705f6194ccfa25ac0d5fd \ + --hash=sha256:7c2984663a733d06c979aa6c8c1d7691621ec0d3521ef345d57c869ff2f1c4b2 \ + --hash=sha256:8304b4818d3e9de552dcfbdd0bca61bae1583e1c9794e242e58fe44bce701604 \ + --hash=sha256:85a01338d282423611f357cd5392dca2219bbda9a66b44761b11d6ae8ebf1e50 \ + --hash=sha256:96fdca994c4d9f7780e82fc7b4bd3398d856b43de3bae57d44e242ff435a2431 \ + --hash=sha256:9b1a28f843c1c0b582db7854789525d0c8aac4ea5c56e31113684e38220d0af9 \ + --hash=sha256:9fa43d330389df27024757c4f97dabddafbedc74b8bcc189b6a86e8b4d036014 \ + --hash=sha256:a088f108da4653ad1396ddb63a1c757ad614d0862c38f6f69cc77344bdcfeccb \ + --hash=sha256:b9f0ac0c00075321e1720d3876e936ee0256f54832e7463c5193a8dfa54913d5 \ + --hash=sha256:c828248214a49f77b903e05acf887d3ccb9d958b5a979f2ed3663bba1bd0f2b3 \ + --hash=sha256:d6fd334e4d8df7fcb30e6746e5ade845e82de2942268862aa8bce974ae2b86a2 \ + --hash=sha256:d8ac1659c8e588b9502f8d3d03c1ded2f274de0da9c09e62fe007cba5b46d6a5 \ + --hash=sha256:e8e7ce0e8b33aec8b1fc6741eb51dbeb54e2c3a6d282a0d459c355a85f089b08 \ + --hash=sha256:ea6e4083ebea0a814b46f029d64a2fb0ba6e7732952cd8af4406041708ce0e21 \ + --hash=sha256:f5d0e90e68a899c13fda5ca842ff77b5759b1674adf2c72702d3c2b53ca9d27b \ + --hash=sha256:fb628d5ea1999e23bfbaabce4125eb44d56605ca5634b8b1d6092ab22d555598 # via feast (pyproject.toml) sortedcontainers==2.4.0 \ --hash=sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88 \ --hash=sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0 # via snowflake-connector-python -sqlalchemy[mypy]==2.0.46 \ - --hash=sha256:09168817d6c19954d3b7655da6ba87fcb3a62bb575fb396a81a8b6a9fadfe8b5 \ - --hash=sha256:0cc3117db526cad3e61074100bd2867b533e2c7dc1569e95c14089735d6fb4fe \ - --hash=sha256:181903fe8c1b9082995325f1b2e84ac078b1189e2819380c2303a5f90e114a62 \ - --hash=sha256:1bc3f601f0a818d27bfe139f6766487d9c88502062a2cd3a7ee6c342e81d5047 \ - --hash=sha256:1e6199143d51e3e1168bedd98cc698397404a8f7508831b81b6a29b18b051069 \ - --hash=sha256:2347c3f0efc4de367ba00218e0ae5c4ba2306e47216ef80d6e31761ac97cb0b9 \ - --hash=sha256:261c4b1f101b4a411154f1da2b76497d73abbfc42740029205d4d01fa1052684 \ - --hash=sha256:33e462154edb9493f6c3ad2125931e273bbd0be8ae53f3ecd1c161ea9a1dd366 \ - --hash=sha256:37fee2164cf21417478b6a906adc1a91d69ae9aba8f9533e67ce882f4bb1de53 \ - --hash=sha256:3a9a72b0da8387f15d5810f1facca8f879de9b85af8c645138cba61ea147968c \ - --hash=sha256:3aac08f7546179889c62b53b18ebf1148b10244b3405569c93984b0388d016a7 \ - --hash=sha256:3c32e993bc57be6d177f7d5d31edb93f30726d798ad86ff9066d75d9bf2e0b6b \ - --hash=sha256:412f26bb4ba942d52016edc8d12fb15d91d3cd46b0047ba46e424213ad407bcb \ - --hash=sha256:42a1643dc5427b69aca967dae540a90b0fbf57eaf248f13a90ea5930e0966863 \ - --hash=sha256:4396c948d8217e83e2c202fbdcc0389cf8c93d2c1c5e60fa5c5a955eae0e64be \ - --hash=sha256:4dafb537740eef640c4d6a7c254611dca2df87eaf6d14d6a5fca9d1f4c3fc0fa \ - --hash=sha256:4f52f7291a92381e9b4de9050b0a65ce5d6a763333406861e33906b8aa4906bf \ - --hash=sha256:52fe29b3817bd191cc20bad564237c808967972c97fa683c04b28ec8979ae36f \ - --hash=sha256:56bdd261bfd0895452006d5316cbf35739c53b9bb71a170a331fa0ea560b2ada \ - --hash=sha256:585af6afe518732d9ccd3aea33af2edaae4a7aa881af5d8f6f4fe3a368699597 \ - --hash=sha256:590be24e20e2424a4c3c1b0835e9405fa3d0af5823a1a9fc02e5dff56471515f \ - --hash=sha256:64901e08c33462acc9ec3bad27fc7a5c2b6491665f2aa57564e57a4f5d7c52ad \ - --hash=sha256:6ac245604295b521de49b465bab845e3afe6916bcb2147e5929c8041b4ec0545 \ - --hash=sha256:6f827fd687fa1ba7f51699e1132129eac8db8003695513fcf13fc587e1bd47a5 \ - --hash=sha256:70ed2830b169a9960193f4d4322d22be5c0925357d82cbf485b3369893350908 \ - --hash=sha256:716be5bcabf327b6d5d265dbdc6213a01199be587224eb991ad0d37e83d728fd \ - --hash=sha256:7568fe771f974abadce52669ef3a03150ff03186d8eb82613bc8adc435a03f01 \ - --hash=sha256:77f8071d8fbcbb2dd11b7fd40dedd04e8ebe2eb80497916efedba844298065ef \ - --hash=sha256:82ec52100ec1e6ec671563bbd02d7c7c8d0b9e71a0723c72f22ecf52d1755330 \ - --hash=sha256:895296687ad06dc9b11a024cf68e8d9d3943aa0b4964278d2553b86f1b267735 \ - --hash=sha256:8d3b44b3d0ab2f1319d71d9863d76eeb46766f8cf9e921ac293511804d39813f \ - --hash=sha256:8d679b5f318423eacb61f933a9a0f75535bfca7056daeadbf6bd5bcee6183aee \ - --hash=sha256:8e84b09a9b0f19accedcbeff5c2caf36e0dd537341a33aad8d680336152dc34e \ - --hash=sha256:9094c8b3197db12aa6f05c51c05daaad0a92b8c9af5388569847b03b1007fb1b \ - --hash=sha256:90bde6c6b1827565a95fde597da001212ab436f1b2e0c2dcc7246e14db26e2a3 \ - --hash=sha256:9397b381dcee8a2d6b99447ae85ea2530dcac82ca494d1db877087a13e38926d \ - --hash=sha256:93a12da97cca70cea10d4b4fc602589c4511f96c1f8f6c11817620c021d21d00 \ - --hash=sha256:93bb0aae40b52c57fd74ef9c6933c08c040ba98daf23ad33c3f9893494b8d3ce \ - --hash=sha256:94b1e5f3a5f1ff4f42d5daab047428cd45a3380e51e191360a35cef71c9a7a2a \ - --hash=sha256:965c62be8256d10c11f8907e7a8d3e18127a4c527a5919d85fa87fd9ecc2cfdc \ - --hash=sha256:96c7cca1a4babaaf3bfff3e4e606e38578856917e52f0384635a95b226c87764 \ - --hash=sha256:9bcdce05f056622a632f1d44bb47dbdb677f58cad393612280406ce37530eb6d \ - --hash=sha256:9d80ea2ac519c364a7286e8d765d6cd08648f5b21ca855a8017d9871f075542d \ - --hash=sha256:a1e8cc6cc01da346dc92d9509a63033b9b1bda4fed7a7a7807ed385c7dccdc10 \ - --hash=sha256:ab65cb2885a9f80f979b85aa4e9c9165a31381ca322cbde7c638fe6eefd1ec39 \ - --hash=sha256:af865c18752d416798dae13f83f38927c52f085c52e2f32b8ab0fef46fdd02c2 \ - --hash=sha256:b1e14b2f6965a685c7128bd315e27387205429c2e339eeec55cb75ca4ab0ea2e \ - --hash=sha256:b2a9f9aee38039cf4755891a1e50e1effcc42ea6ba053743f452c372c3152b1b \ - --hash=sha256:be6c0466b4c25b44c5d82b0426b5501de3c424d7a3220e86cd32f319ba56798e \ - --hash=sha256:c4e2cc868b7b5208aec6c960950b7bb821f82c2fe66446c92ee0a571765e91a5 \ - --hash=sha256:c805fa6e5d461329fa02f53f88c914d189ea771b6821083937e79550bf31fc19 \ - --hash=sha256:cf36851ee7219c170bb0793dbc3da3e80c582e04a5437bc601bfe8c85c9216d7 \ - --hash=sha256:db23b1bf8cfe1f7fda19018e7207b20cdb5168f83c437ff7e95d19e39289c447 \ - --hash=sha256:e0c05aff5c6b1bb5fb46a87e0f9d2f733f83ef6cbbbcd5c642b6c01678268061 \ - --hash=sha256:e8ac45e8f4eaac0f9f8043ea0e224158855c6a4329fd4ee37c45c61e3beb518e \ - --hash=sha256:ea3cd46b6713a10216323cda3333514944e510aa691c945334713fca6b5279ff \ - --hash=sha256:ebf7e1e78af38047e08836d33502c7a278915698b7c2145d045f780201679999 \ - --hash=sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e \ - --hash=sha256:ff33c6e6ad006bbc0f34f5faf941cfc62c45841c64c0a058ac38c799f15b5ede +sqlalchemy[mypy]==2.0.48 \ + --hash=sha256:01f6bbd4308b23240cf7d3ef117557c8fd097ec9549d5d8a52977544e35b40ad \ + --hash=sha256:07edba08061bc277bfdc772dd2a1a43978f5a45994dd3ede26391b405c15221e \ + --hash=sha256:10853a53a4a00417a00913d270dddda75815fcb80675874285f41051c094d7dd \ + --hash=sha256:1182437cb2d97988cfea04cf6cdc0b0bb9c74f4d56ec3d08b81e23d621a28cc6 \ + --hash=sha256:144921da96c08feb9e2b052c5c5c1d0d151a292c6135623c6b2c041f2a45f9e0 \ + --hash=sha256:1a89ce07ad2d4b8cfc30bd5889ec40613e028ed80ef47da7d9dd2ce969ad30e0 \ + --hash=sha256:1b4c575df7368b3b13e0cebf01d4679f9a28ed2ae6c1cd0b1d5beffb6b2007dc \ + --hash=sha256:1ccd42229aaac2df431562117ac7e667d702e8e44afdb6cf0e50fa3f18160f0b \ + --hash=sha256:2645b7d8a738763b664a12a1542c89c940daa55196e8d73e55b169cc5c99f65f \ + --hash=sha256:288937433bd44e3990e7da2402fabc44a3c6c25d3704da066b85b89a85474ae0 \ + --hash=sha256:34634e196f620c7a61d18d5cf7dc841ca6daa7961aed75d532b7e58b309ac894 \ + --hash=sha256:348174f228b99f33ca1f773e85510e08927620caa59ffe7803b37170df30332b \ + --hash=sha256:36ac4ddc3d33e852da9cb00ffb08cea62ca05c39711dc67062ca2bb1fae35fd8 \ + --hash=sha256:3713e21ea67bca727eecd4a24bf68bcd414c403faae4989442be60994301ded0 \ + --hash=sha256:389b984139278f97757ea9b08993e7b9d1142912e046ab7d82b3fbaeb0209131 \ + --hash=sha256:426c5ca86415d9b8945c7073597e10de9644802e2ff502b8e1f11a7a2642856b \ + --hash=sha256:4599a95f9430ae0de82b52ff0d27304fe898c17cb5f4099f7438a51b9998ac77 \ + --hash=sha256:49b7bddc1eebf011ea5ab722fdbe67a401caa34a350d278cc7733c0e88fecb1f \ + --hash=sha256:53667b5f668991e279d21f94ccfa6e45b4e3f4500e7591ae59a8012d0f010dcb \ + --hash=sha256:546572a1793cc35857a2ffa1fe0e58571af1779bcc1ffa7c9fb0839885ed69a9 \ + --hash=sha256:583849c743e0e3c9bb7446f5b5addeacedc168d657a69b418063dfdb2d90081c \ + --hash=sha256:5aee45fd2c6c0f2b9cdddf48c48535e7471e42d6fb81adfde801da0bd5b93241 \ + --hash=sha256:5b193a7e29fd9fa56e502920dca47dffe60f97c863494946bd698c6058a55658 \ + --hash=sha256:5ca74f37f3369b45e1f6b7b06afb182af1fd5dde009e4ffd831830d98cbe5fe7 \ + --hash=sha256:68549c403f79a8e25984376480959975212a670405e3913830614432b5daa07a \ + --hash=sha256:69f5bc24904d3bc3640961cddd2523e361257ef68585d6e364166dfbe8c78fae \ + --hash=sha256:6bb85c546591569558571aa1b06aba711b26ae62f111e15e56136d69920e1616 \ + --hash=sha256:6f7b7243850edd0b8b97043f04748f31de50cf426e939def5c16bedb540698f7 \ + --hash=sha256:7001dc9d5f6bb4deb756d5928eaefe1930f6f4179da3924cbd95ee0e9f4dce89 \ + --hash=sha256:7a936f1bb23d370b7c8cc079d5fce4c7d18da87a33c6744e51a93b0f9e97e9b3 \ + --hash=sha256:7c998f2ace8bf76b453b75dbcca500d4f4b9dd3908c13e89b86289b37784848b \ + --hash=sha256:7cddca31edf8b0653090cbb54562ca027c421c58ddde2c0685f49ff56a1690e0 \ + --hash=sha256:8183dc57ae7d9edc1346e007e840a9f3d6aa7b7f165203a99e16f447150140d2 \ + --hash=sha256:82745b03b4043e04600a6b665cb98697c4339b24e34d74b0a2ac0a2488b6f94d \ + --hash=sha256:841a94c66577661c1f088ac958cd767d7c9bf507698f45afffe7a4017049de76 \ + --hash=sha256:858e433f12b0e5b3ed2f8da917433b634f4937d0e8793e5cb33c54a1a01df565 \ + --hash=sha256:908a3fa6908716f803b86896a09a2c4dde5f5ce2bb07aacc71ffebb57986ce99 \ + --hash=sha256:9764014ef5e58aab76220c5664abb5d47d5bc858d9debf821e55cfdd0f128485 \ + --hash=sha256:9c7d0a77e36b5f4b01ca398482230ab792061d243d715299b44a0b55c89fe617 \ + --hash=sha256:a5b429eb84339f9f05e06083f119ad814e6d85e27ecbdf9c551dfdbb128eaf8a \ + --hash=sha256:a66fe406437dd65cacd96a72689a3aaaecaebbcd62d81c5ac1c0fdbeac835096 \ + --hash=sha256:a6b764fb312bd35e47797ad2e63f0d323792837a6ac785a4ca967019357d2bc7 \ + --hash=sha256:b19151e76620a412c2ac1c6f977ab1b9fa7ad43140178345136456d5265b32ed \ + --hash=sha256:b8438ec5594980d405251451c5b7ea9aa58dda38eb7ac35fb7e4c696712ee24f \ + --hash=sha256:b8fc3454b4f3bd0a368001d0e968852dad45a873f8b4babd41bc302ec851a099 \ + --hash=sha256:bcb8ebbf2e2c36cfe01a94f2438012c6a9d494cf80f129d9753bcdf33bfc35a6 \ + --hash=sha256:d404dc897ce10e565d647795861762aa2d06ca3f4a728c5e9a835096c7059018 \ + --hash=sha256:d612c976cbc2d17edfcc4c006874b764e85e990c29ce9bd411f926bbfb02b9a2 \ + --hash=sha256:d64177f443594c8697369c10e4bbcac70ef558e0f7921a1de7e4a3d1734bcf67 \ + --hash=sha256:d854b3970067297f3a7fbd7a4683587134aa9b3877ee15aa29eea478dc68f933 \ + --hash=sha256:d8fcccbbc0c13c13702c471da398b8cd72ba740dca5859f148ae8e0e8e0d3e7e \ + --hash=sha256:e004aa9248e8cb0a5f9b96d003ca7c1c0a5da8decd1066e7b53f59eb8ce7c62b \ + --hash=sha256:e214d546c8ecb5fc22d6e6011746082abf13a9cf46eefb45769c7b31407c97b5 \ + --hash=sha256:e2d0d88686e3d35a76f3e15a34e8c12d73fc94c1dea1cd55782e695cc14086dd \ + --hash=sha256:e2f35b4cccd9ed286ad62e0a3c3ac21e06c02abc60e20aa51a3e305a30f5fa79 \ + --hash=sha256:e3070c03701037aa418b55d36532ecb8f8446ed0135acb71c678dbdf12f5b6e4 \ + --hash=sha256:e5e088bf43f6ee6fec7dbf1ef7ff7774a616c236b5c0cb3e00662dd71a56b571 \ + --hash=sha256:e83e3f959aaa1c9df95c22c528096d94848a1bc819f5d0ebf7ee3df0ca63db6c \ + --hash=sha256:f0dcbc588cd5b725162c076eb9119342f6579c7f7f55057bb7e3c6ff27e13121 \ + --hash=sha256:f27f9da0a7d22b9f981108fd4b62f8b5743423388915a563e651c20d06c1f457 \ + --hash=sha256:f8649a14caa5f8a243628b1d61cf530ad9ae4578814ba726816adb1121fc493e \ + --hash=sha256:fac0fa4e4f55f118fd87177dacb1c6522fe39c28d498d259014020fec9164c29 \ + --hash=sha256:fd08b90d211c086181caed76931ecfa2bdfc83eea3cfccdb0f82abc6c4b876cb # via feast (pyproject.toml) -sqlglot==28.10.1 \ - --hash=sha256:214aef51fd4ce16407022f81cfc80c173409dab6d0f6ae18c52b43f43b31d4dd \ - --hash=sha256:66e0dae43b4bce23314b80e9aef41b8c88fea0e17ada62de095b45262084a8c5 +sqlglot==30.2.1 \ + --hash=sha256:ef4a67cc6f66a8043085eb8ea95fa9541c1625dffa9145ad4e9815a7ba60a199 \ + --hash=sha256:f23d9ee9427ef9d20df15f9b0ffa57d9eb45e52b012219a349d1e6b50ed926d1 # via ibis-framework -sse-starlette==3.2.0 \ - --hash=sha256:5876954bd51920fc2cd51baee47a080eb88a37b5b784e615abb0b283f801cdbf \ - --hash=sha256:8127594edfb51abe44eac9c49e59b0b01f1039d0c7461c6fd91d4e03b70da422 +sse-starlette==3.3.4 \ + --hash=sha256:84bb06e58939a8b38d8341f1bc9792f06c2b53f48c608dd207582b664fc8f3c1 \ + --hash=sha256:aaf92fc067af8a5427192895ac028e947b484ac01edbc3caf00e7e7137c7bef1 # via mcp -starlette==0.52.1 \ - --hash=sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74 \ - --hash=sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933 +starlette==1.0.0 \ + --hash=sha256:6a4beaf1f81bb472fd19ea9b918b50dc3a77a6f2e190a12954b25e6ed5eea149 \ + --hash=sha256:d3ec55e0bb321692d275455ddfd3df75fff145d009685eb40dc91fc66b03d38b # via # fastapi # mcp # sse-starlette -tabulate==0.9.0 \ - --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ - --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f +tabulate==0.10.0 \ + --hash=sha256:e2cfde8f79420f6deeffdeda9aaec3b6bc5abce947655d17ac662b126e48a60d \ + --hash=sha256:f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3 # via feast (pyproject.toml) tenacity==8.5.0 \ --hash=sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78 \ @@ -2642,54 +2641,54 @@ toml==0.10.2 \ --hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \ --hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f # via feast (pyproject.toml) -tomli==2.4.0 \ - --hash=sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729 \ - --hash=sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b \ - --hash=sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d \ - --hash=sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df \ - --hash=sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576 \ - --hash=sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d \ - --hash=sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1 \ - --hash=sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a \ - --hash=sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e \ - --hash=sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc \ - --hash=sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702 \ - --hash=sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6 \ - --hash=sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd \ - --hash=sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4 \ - --hash=sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776 \ - --hash=sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a \ - --hash=sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66 \ - --hash=sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87 \ - --hash=sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2 \ - --hash=sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f \ - --hash=sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475 \ - --hash=sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f \ - --hash=sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95 \ - --hash=sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9 \ - --hash=sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3 \ - --hash=sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9 \ - --hash=sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76 \ - --hash=sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da \ - --hash=sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8 \ - --hash=sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51 \ - --hash=sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86 \ - --hash=sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8 \ - --hash=sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0 \ - --hash=sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b \ - --hash=sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1 \ - --hash=sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e \ - --hash=sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d \ - --hash=sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c \ - --hash=sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867 \ - --hash=sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a \ - --hash=sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c \ - --hash=sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0 \ - --hash=sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4 \ - --hash=sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614 \ - --hash=sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132 \ - --hash=sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa \ - --hash=sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087 +tomli==2.4.1 \ + --hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \ + --hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \ + --hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \ + --hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \ + --hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \ + --hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \ + --hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \ + --hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \ + --hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \ + --hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \ + --hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \ + --hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \ + --hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \ + --hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \ + --hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \ + --hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \ + --hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \ + --hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \ + --hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \ + --hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \ + --hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \ + --hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \ + --hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \ + --hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \ + --hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \ + --hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \ + --hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \ + --hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \ + --hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \ + --hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \ + --hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \ + --hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \ + --hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \ + --hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \ + --hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \ + --hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \ + --hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \ + --hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \ + --hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \ + --hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \ + --hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \ + --hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \ + --hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \ + --hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \ + --hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \ + --hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \ + --hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049 # via # fastapi-mcp # mypy @@ -2710,13 +2709,13 @@ tqdm==4.67.3 \ # via # feast (pyproject.toml) # milvus-lite -typeguard==4.5.0 \ - --hash=sha256:749bea21cdb2553e12831bc29f1eae980b22c7de8331ab67ae7db9e85470b5a7 \ - --hash=sha256:cfda388fc88a9ce42a41890900d6f31ee124bea9b73bb84701a32438e92165c3 +typeguard==4.5.1 \ + --hash=sha256:44d2bf329d49a244110a090b55f5f91aa82d9a9834ebfd30bcc73651e4a8cc40 \ + --hash=sha256:f6f8ecbbc819c9bc749983cc67c02391e16a9b43b8b27f15dc70ed7c4a007274 # via feast (pyproject.toml) -typer==0.23.1 \ - --hash=sha256:2070374e4d31c83e7b61362fd859aa683576432fd5b026b060ad6b4cd3b86134 \ - --hash=sha256:3291ad0d3c701cbf522012faccfbb29352ff16ad262db2139e6b01f15781f14e +typer==0.24.1 \ + --hash=sha256:112c1f0ce578bfb4cab9ffdabc68f031416ebcc216536611ba21f04e9aa84c9e \ + --hash=sha256:e39b4732d65fbdcde189ae76cf7cd48aeae72919dea1fdfc16593be016256b45 # via fastapi-mcp types-pymysql==1.1.0.20251220 \ --hash=sha256:ae1c3df32a777489431e2e9963880a0df48f6591e0aa2fd3a6fabd9dee6eca54 \ @@ -2739,6 +2738,7 @@ typing-extensions==4.15.0 \ # psycopg-pool # pydantic # pydantic-core + # pyjwt # pyopenssl # referencing # snowflake-connector-python @@ -2761,91 +2761,85 @@ tzdata==2025.3 \ # via # ibis-framework # pandas -ujson==5.11.0 \ - --hash=sha256:0180a480a7d099082501cad1fe85252e4d4bf926b40960fb3d9e87a3a6fbbc80 \ - --hash=sha256:04c41afc195fd477a59db3a84d5b83a871bd648ef371cf8c6f43072d89144eef \ - --hash=sha256:0654a2691fc252c3c525e3d034bb27b8a7546c9d3eb33cd29ce6c9feda361a6a \ - --hash=sha256:090b4d11b380ae25453100b722d0609d5051ffe98f80ec52853ccf8249dfd840 \ - --hash=sha256:109f59885041b14ee9569bf0bb3f98579c3fa0652317b355669939e5fc5ede53 \ - --hash=sha256:10f29e71ecf4ecd93a6610bd8efa8e7b6467454a363c3d6416db65de883eb076 \ - --hash=sha256:1194b943e951092db611011cb8dbdb6cf94a3b816ed07906e14d3bc6ce0e90ab \ - --hash=sha256:12b5e7e22a1fe01058000d1b317d3b65cc3daf61bd2ea7a2b76721fe160fa74d \ - --hash=sha256:16ccb973b7ada0455201808ff11d48fe9c3f034a6ab5bd93b944443c88299f89 \ - --hash=sha256:181fb5b15703a8b9370b25345d2a1fd1359f0f18776b3643d24e13ed9c036d4c \ - --hash=sha256:185f93ebccffebc8baf8302c869fac70dd5dd78694f3b875d03a31b03b062cdb \ - --hash=sha256:1a0a9b76a89827a592656fe12e000cf4f12da9692f51a841a4a07aa4c7ecc41c \ - --hash=sha256:1a325fd2c3a056cf6c8e023f74a0c478dd282a93141356ae7f16d5309f5ff823 \ - --hash=sha256:1aa8a2ab482f09f6c10fba37112af5f957689a79ea598399c85009f2f29898b5 \ - --hash=sha256:1d663b96eb34c93392e9caae19c099ec4133ba21654b081956613327f0e973ac \ - --hash=sha256:29113c003ca33ab71b1b480bde952fbab2a0b6b03a4ee4c3d71687cdcbd1a29d \ - --hash=sha256:30f607c70091483550fbd669a0b37471e5165b317d6c16e75dba2aa967608723 \ - --hash=sha256:3134b783ab314d2298d58cda7e47e7a0f7f71fc6ade6ac86d5dbeaf4b9770fa6 \ - --hash=sha256:34032aeca4510a7c7102bd5933f59a37f63891f30a0706fb46487ab6f0edf8f0 \ - --hash=sha256:3772e4fe6b0c1e025ba3c50841a0ca4786825a4894c8411bf8d3afe3a8061328 \ - --hash=sha256:3d2720e9785f84312b8e2cb0c2b87f1a0b1c53aaab3b2af3ab817d54409012e0 \ - --hash=sha256:416389ec19ef5f2013592f791486bef712ebce0cd59299bf9df1ba40bb2f6e04 \ - --hash=sha256:446e8c11c06048611c9d29ef1237065de0af07cabdd97e6b5b527b957692ec25 \ - --hash=sha256:4598bf3965fc1a936bd84034312bcbe00ba87880ef1ee33e33c1e88f2c398b49 \ - --hash=sha256:48055e1061c1bb1f79e75b4ac39e821f3f35a9b82de17fce92c3140149009bec \ - --hash=sha256:4843f3ab4fe1cc596bb7e02228ef4c25d35b4bb0809d6a260852a4bfcab37ba3 \ - --hash=sha256:49e56ef8066f11b80d620985ae36869a3ff7e4b74c3b6129182ec5d1df0255f3 \ - --hash=sha256:4b42c115c7c6012506e8168315150d1e3f76e7ba0f4f95616f4ee599a1372bbc \ - --hash=sha256:4c9f5d6a27d035dd90a146f7761c2272cf7103de5127c9ab9c4cd39ea61e878a \ - --hash=sha256:5600202a731af24a25e2d7b6eb3f648e4ecd4bb67c4d5cf12f8fab31677469c9 \ - --hash=sha256:65724738c73645db88f70ba1f2e6fb678f913281804d5da2fd02c8c5839af302 \ - --hash=sha256:65f3c279f4ed4bf9131b11972040200c66ae040368abdbb21596bf1564899694 \ - --hash=sha256:674f306e3e6089f92b126eb2fe41bcb65e42a15432c143365c729fdb50518547 \ - --hash=sha256:683f57f0dd3acdd7d9aff1de0528d603aafcb0e6d126e3dc7ce8b020a28f5d01 \ - --hash=sha256:6b6ec7e7321d7fc19abdda3ad809baef935f49673951a8bab486aea975007e02 \ - --hash=sha256:6cd2df62f24c506a0ba322d5e4fe4466d47a9467b57e881ee15a31f7ecf68ff6 \ - --hash=sha256:6dd703c3e86dc6f7044c5ac0b3ae079ed96bf297974598116aa5fb7f655c3a60 \ - --hash=sha256:6eff24e1abd79e0ec6d7eae651dd675ddbc41f9e43e29ef81e16b421da896915 \ - --hash=sha256:7855ccea3f8dad5e66d8445d754fc1cf80265a4272b5f8059ebc7ec29b8d0835 \ - --hash=sha256:787aff4a84da301b7f3bac09bc696e2e5670df829c6f8ecf39916b4e7e24e701 \ - --hash=sha256:7895f0d2d53bd6aea11743bd56e3cb82d729980636cd0ed9b89418bf66591702 \ - --hash=sha256:78c684fb21255b9b90320ba7e199780f653e03f6c2528663768965f4126a5b50 \ - --hash=sha256:7e0ec1646db172beb8d3df4c32a9d78015e671d2000af548252769e33079d9a6 \ - --hash=sha256:7e3cff632c1d78023b15f7e3a81c3745cd3f94c044d1e8fa8efbd6b161997bbc \ - --hash=sha256:7f1a27ab91083b4770e160d17f61b407f587548f2c2b5fbf19f94794c495594a \ - --hash=sha256:80017e870d882d5517d28995b62e4e518a894f932f1e242cbc802a2fd64d365c \ - --hash=sha256:8254e858437c00f17cb72e7a644fc42dad0ebb21ea981b71df6e84b1072aaa7c \ - --hash=sha256:837da4d27fed5fdc1b630bd18f519744b23a0b5ada1bbde1a36ba463f2900c03 \ - --hash=sha256:849e65b696f0d242833f1df4182096cedc50d414215d1371fca85c541fbff629 \ - --hash=sha256:85e6796631165f719084a9af00c79195d3ebf108151452fefdcb1c8bb50f0105 \ - --hash=sha256:86baf341d90b566d61a394869ce77188cc8668f76d7bb2c311d77a00f4bdf844 \ - --hash=sha256:8fa2af7c1459204b7a42e98263b069bd535ea0cd978b4d6982f35af5a04a4241 \ - --hash=sha256:94fcae844f1e302f6f8095c5d1c45a2f0bfb928cccf9f1b99e3ace634b980a2a \ - --hash=sha256:952c0be400229940248c0f5356514123d428cba1946af6fa2bbd7503395fef26 \ - --hash=sha256:99c49400572cd77050894e16864a335225191fd72a818ea6423ae1a06467beac \ - --hash=sha256:9aacbeb23fdbc4b256a7d12e0beb9063a1ba5d9e0dbb2cfe16357c98b4334596 \ - --hash=sha256:a0af6574fc1d9d53f4ff371f58c96673e6d988ed2b5bf666a6143c782fa007e9 \ - --hash=sha256:a31c6b8004438e8c20fc55ac1c0e07dad42941db24176fe9acf2815971f8e752 \ - --hash=sha256:a4df61a6df0a4a8eb5b9b1ffd673429811f50b235539dac586bb7e9e91994138 \ - --hash=sha256:a638425d3c6eed0318df663df44480f4a40dc87cc7c6da44d221418312f6413b \ - --hash=sha256:aa6b3d4f1c0d3f82930f4cbd7fe46d905a4a9205a7c13279789c1263faf06dba \ - --hash=sha256:aa6d7a5e09217ff93234e050e3e380da62b084e26b9f2e277d2606406a2fc2e5 \ - --hash=sha256:ab2cb8351d976e788669c8281465d44d4e94413718af497b4e7342d7b2f78018 \ - --hash=sha256:abae0fb58cc820092a0e9e8ba0051ac4583958495bfa5262a12f628249e3b362 \ - --hash=sha256:b16930f6a0753cdc7d637b33b4e8f10d5e351e1fb83872ba6375f1e87be39746 \ - --hash=sha256:b7b136cc6abc7619124fd897ef75f8e63105298b5ca9bdf43ebd0e1fa0ee105f \ - --hash=sha256:be6b0eaf92cae8cdee4d4c9e074bde43ef1c590ed5ba037ea26c9632fb479c88 \ - --hash=sha256:c44c703842024d796b4c78542a6fcd5c3cb948b9fc2a73ee65b9c86a22ee3638 \ - --hash=sha256:c6618f480f7c9ded05e78a1938873fde68baf96cdd74e6d23c7e0a8441175c4b \ - --hash=sha256:ce076f2df2e1aa62b685086fbad67f2b1d3048369664b4cdccc50707325401f9 \ - --hash=sha256:d06e87eded62ff0e5f5178c916337d2262fdbc03b31688142a3433eabb6511db \ - --hash=sha256:d7c46cb0fe5e7056b9acb748a4c35aa1b428025853032540bb7e41f46767321f \ - --hash=sha256:d8951bb7a505ab2a700e26f691bdfacf395bc7e3111e3416d325b513eea03a58 \ - --hash=sha256:da473b23e3a54448b008d33f742bcd6d5fb2a897e42d1fc6e7bf306ea5d18b1b \ - --hash=sha256:de6e88f62796372fba1de973c11138f197d3e0e1d80bcb2b8aae1e826096d433 \ - --hash=sha256:e204ae6f909f099ba6b6b942131cee359ddda2b6e4ea39c12eb8b991fe2010e0 \ - --hash=sha256:e73df8648c9470af2b6a6bf5250d4744ad2cf3d774dcf8c6e31f018bdd04d764 \ - --hash=sha256:e750c436fb90edf85585f5c62a35b35082502383840962c6983403d1bd96a02c \ - --hash=sha256:e979fbc469a7f77f04ec2f4e853ba00c441bf2b06720aa259f0f720561335e34 \ - --hash=sha256:ecd6ff8a3b5a90c292c2396c2d63c687fd0ecdf17de390d852524393cd9ed052 \ - --hash=sha256:f278b31a7c52eb0947b2db55a5133fbc46b6f0ef49972cd1a80843b72e135aba \ - --hash=sha256:f62b9976fabbcde3ab6e413f4ec2ff017749819a0786d84d7510171109f2d53c \ - --hash=sha256:fa79fdb47701942c2132a9dd2297a1a85941d966d8c87bfd9e29b0cf423f26cc \ - --hash=sha256:fac6c0649d6b7c3682a0a6e18d3de6857977378dce8d419f57a0b20e3d775b39 +ujson==5.12.0 \ + --hash=sha256:006428d3813b87477d72d306c40c09f898a41b968e57b15a7d88454ecc42a3fb \ + --hash=sha256:02f93da7a4115e24f886b04fd56df1ee8741c2ce4ea491b7ab3152f744ad8f8e \ + --hash=sha256:0727363b05ab05ee737a28f6200dc4078bce6b0508e10bd8aab507995a15df61 \ + --hash=sha256:085b6ce182cdd6657481c7c4003a417e0655c4f6e58b76f26ee18f0ae21db827 \ + --hash=sha256:09b4beff9cc91d445d5818632907b85fb06943b61cb346919ce202668bf6794a \ + --hash=sha256:0a3ae28f0b209be5af50b54ca3e2123a3de3a57d87b75f1e5aa3d7961e041983 \ + --hash=sha256:0d2e8db5ade3736a163906154ca686203acc7d1d30736cbf577c730d13653d84 \ + --hash=sha256:0e00cec383eab2406c9e006bd4edb55d284e94bb943fda558326048178d26961 \ + --hash=sha256:0fe6b8b8968e11dd9b2348bd508f0f57cf49ab3512064b36bc4117328218718e \ + --hash=sha256:0fe9128e75c6aa6e9ae06c1408d6edd9179a2fef0fe6d9cda3166b887eba521d \ + --hash=sha256:14b2e1eb528d77bc0f4c5bd1a7ebc05e02b5b41beefb7e8567c9675b8b13bcf4 \ + --hash=sha256:15d416440148f3e56b9b244fdaf8a09fcf5a72e4944b8e119f5bf60417a2bfc8 \ + --hash=sha256:15e555c4caca42411270b2ed2b2ebc7b3a42bb04138cef6c956e1f1d49709fe2 \ + --hash=sha256:16b4fe9c97dc605f5e1887a9e1224287291e35c56cbc379f8aa44b6b7bcfe2bb \ + --hash=sha256:1b5c6ceb65fecd28a1d20d1eba9dbfa992612b86594e4b6d47bb580d2dd6bcb3 \ + --hash=sha256:1d072a403d82aef8090c6d4f728e3a727dfdba1ad3b7fa3a052c3ecbd37e73cb \ + --hash=sha256:2324d9a0502317ffc35d38e153c1b2fa9610ae03775c9d0f8d0cca7b8572b04e \ + --hash=sha256:2a248750abce1c76fbd11b2e1d88b95401e72819295c3b851ec73399d6849b3d \ + --hash=sha256:2ea6206043385343aff0b7da65cf73677f6f5e50de8f1c879e557f4298cac36a \ + --hash=sha256:31348a0ffbfc815ce78daac569d893349d85a0b57e1cd2cdbba50b7f333784da \ + --hash=sha256:38051f36423f084b909aaadb3b41c9c6a2958e86956ba21a8489636911e87504 \ + --hash=sha256:3c2f947e55d3c7cfe124dd4521ee481516f3007d13c6ad4bf6aeb722e190eb1b \ + --hash=sha256:3ed5cb149892141b1e77ef312924a327f2cc718b34247dae346ed66329e1b8be \ + --hash=sha256:3ff4ede90ed771140caa7e1890de17431763a483c54b3c1f88bd30f0cc1affc0 \ + --hash=sha256:40aa43a7a3a8d2f05e79900858053d697a88a605e3887be178b43acbcd781161 \ + --hash=sha256:42d875388fbd091c7ea01edfff260f839ba303038ffb23475ef392012e4d63dd \ + --hash=sha256:457fabc2700a8e6ddb85bc5a1d30d3345fe0d3ec3ee8161a4e032ec585801dfa \ + --hash=sha256:460e76a4daff214ae33ab959494962c93918cb44714ea3e3f748b14aa37f8a87 \ + --hash=sha256:50524f4f6a1c839714dbaff5386a1afb245d2d5ec8213a01fbc99cea7307811e \ + --hash=sha256:51acc750ec7a2df786cdc868fb16fa04abd6269a01d58cf59bafc57978773d8e \ + --hash=sha256:55ede2a7a051b3b7e71a394978a098d71b3783e6b904702ff45483fad434ae2d \ + --hash=sha256:561f89cc82deeae82e37d4a4764184926fb432f740a9691563a391b13f7339a4 \ + --hash=sha256:56ba3f7abbd6b0bb282a544dc38406d1a188d8bb9164f49fdb9c2fee62cb29da \ + --hash=sha256:57930ac9519099b852e190d2c04b1fb5d97ea128db33bce77ed874eccb4c7f09 \ + --hash=sha256:58a11cb49482f1a095a2bd9a1d81dd7c8fb5d2357f959ece85db4e46a825fd00 \ + --hash=sha256:64df53eef4ac857eb5816a56e2885ccf0d7dff6333c94065c93b39c51063e01d \ + --hash=sha256:6879aed770557f0961b252648d36f6fdaab41079d37a2296b5649fd1b35608e0 \ + --hash=sha256:6ad57654570464eb1b040b5c353dee442608e06cff9102b8fcb105565a44c9ed \ + --hash=sha256:6c0aed6a4439994c9666fb8a5b6c4eac94d4ef6ddc95f9b806a599ef83547e3b \ + --hash=sha256:76bf3e7406cf23a3e1ca6a23fb1fb9ea82f4f6bd226fe226e09146b0194f85dc \ + --hash=sha256:7bbf05c38debc90d1a195b11340cc85cb43ab3e753dc47558a3a84a38cbc72da \ + --hash=sha256:7ddb08b3c2f9213df1f2e3eb2fbea4963d80ec0f8de21f0b59898e34f3b3d96d \ + --hash=sha256:7e07f6f644d2c44d53b7a320a084eef98063651912c1b9449b5f45fcbdc6ccd2 \ + --hash=sha256:85833bca01aa5cae326ac759276dc175c5fa3f7b3733b7d543cf27f2df12d1ef \ + --hash=sha256:8712b61eb1b74a4478cfd1c54f576056199e9f093659334aeb5c4a6b385338e5 \ + --hash=sha256:871c0e5102e47995b0e37e8df7819a894a6c3da0d097545cd1f9f1f7d7079927 \ + --hash=sha256:89e302abd3749f6d6699691747969a5d85f7c73081d5ed7e2624c7bd9721a2ab \ + --hash=sha256:937794042342006f707837f38d721426b11b0774d327a2a45c0bd389eb750a87 \ + --hash=sha256:93bc91fdadcf046da37a214eaa714574e7e9b1913568e93bb09527b2ceb7f759 \ + --hash=sha256:94c5f1621cbcab83c03be46441f090b68b9f307b6c7ec44d4e3f6d5997383df4 \ + --hash=sha256:973b7d7145b1ac553a7466a64afa8b31ec2693d7c7fff6a755059e0a2885dfd2 \ + --hash=sha256:99cc80facad240b0c2fb5a633044420878aac87a8e7c348b9486450cba93f27c \ + --hash=sha256:9a5fcbe7b949f2e95c47ea8a80b410fcdf2da61c98553b45a4ee875580418b68 \ + --hash=sha256:9b3b86ec3e818f3dd3e13a9de628e88a9990f4af68ecb0b12dd3de81227f0a26 \ + --hash=sha256:9b3cf13facf6f77c283af0e1713e5e8c47a0fe295af81326cb3cb4380212e797 \ + --hash=sha256:9c5a52987a990eb1bae55f9000994f1afdb0326c154fb089992f839ab3c30688 \ + --hash=sha256:a2d79c6635ccffcbfc1d5c045874ba36b594589be81d50d43472570bb8de9c57 \ + --hash=sha256:a6ec5bf6bc361f2f0f9644907a36ce527715b488988a8df534120e5c34eeda94 \ + --hash=sha256:a7bf9cc97f05048ac8f3e02cd58f0fe62b901453c24345bfde287f4305dcc31c \ + --hash=sha256:ab9056d94e5db513d9313b34394f3a3b83e6301a581c28ad67773434f3faccab \ + --hash=sha256:adf28d13a33f9d750fe7a78fb481cac298fa257d8863d8727b2ea4455ea41235 \ + --hash=sha256:b62cb9a7501e1f5c9ffe190485501349c33e8862dde4377df774e40b8166871f \ + --hash=sha256:bacbd3c69862478cbe1c7ed4325caedec580d8acf31b8ee1b9a1e02a56295cad \ + --hash=sha256:bb349dbba57c76eec25e5917e07f35aabaf0a33b9e67fc13d188002500106487 \ + --hash=sha256:bd03472c36fa3a386a6deb887113b9e3fa40efba8203eb4fe786d3c0ccc724f6 \ + --hash=sha256:bf85a00ac3b56a1e7a19c5be7b02b5180a0895ac4d3c234d717a55e86960691c \ + --hash=sha256:ca0c7ce828bb76ab78b3991904b477c2fd0f711d7815c252d1ef28ff9450b052 \ + --hash=sha256:ccbfd94e59aad4a2566c71912b55f0547ac1680bfac25eb138e6703eb3dd434e \ + --hash=sha256:d1831c07bd4dce53c4b666fa846c7eba4b7c414f2e641a4585b7f50b72f502dc \ + --hash=sha256:d22cad98c2a10bbf6aa083a8980db6ed90d4285a841c4de892890c2b28286ef9 \ + --hash=sha256:d30ad4359413c8821cc7b3707f7ca38aa8bc852ba3b9c5a759ee2d7740157315 \ + --hash=sha256:e0dd3676ea0837cd70ea1879765e9e9f6be063be0436de9b3ea4b775caf83654 \ + --hash=sha256:e584d0cdd37cac355aca52ed788d1a2d939d6837e2870d3b70e585db24025a50 \ + --hash=sha256:e6369ac293d2cc40d52577e4fa3d75a70c1aae2d01fa3580a34a4e6eff9286b9 \ + --hash=sha256:efae5df7a8cc8bdb1037b0f786b044ce281081441df5418c3a0f0e1f86fe7bb3 \ + --hash=sha256:f19b3af31d02a2e79c5f9a6deaab0fb3c116456aeb9277d11720ad433de6dfc6 \ + --hash=sha256:f7a0430d765f9bda043e6aefaba5944d5f21ec43ff4774417d7e296f61917382 \ + --hash=sha256:fb94245a715b4d6e24689de12772b85329a1f9946cbf6187923a64ecdea39e65 # via pymilvus urllib3==2.6.3 \ --hash=sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed \ @@ -3178,137 +3172,135 @@ wrapt==1.17.3 \ --hash=sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10 \ --hash=sha256:fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c # via aiobotocore -yarl==1.22.0 \ - --hash=sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a \ - --hash=sha256:029866bde8d7b0878b9c160e72305bbf0a7342bcd20b9999381704ae03308dc8 \ - --hash=sha256:078278b9b0b11568937d9509b589ee83ef98ed6d561dfe2020e24a9fd08eaa2b \ - --hash=sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da \ - --hash=sha256:07a524d84df0c10f41e3ee918846e1974aba4ec017f990dc735aad487a0bdfdf \ - --hash=sha256:088e4e08f033db4be2ccd1f34cf29fe994772fb54cfe004bbf54db320af56890 \ - --hash=sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093 \ - --hash=sha256:0cf71bf877efeac18b38d3930594c0948c82b64547c1cf420ba48722fe5509f6 \ - --hash=sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79 \ - --hash=sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683 \ - --hash=sha256:10619d9fdee46d20edc49d3479e2f8269d0779f1b031e6f7c2aa1c76be04b7ed \ - --hash=sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2 \ - --hash=sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff \ - --hash=sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02 \ - --hash=sha256:14291620375b1060613f4aab9ebf21850058b6b1b438f386cc814813d901c60b \ - --hash=sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03 \ - --hash=sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511 \ - --hash=sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c \ - --hash=sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124 \ - --hash=sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c \ - --hash=sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da \ - --hash=sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2 \ - --hash=sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0 \ - --hash=sha256:2e4e1f6f0b4da23e61188676e3ed027ef0baa833a2e633c29ff8530800edccba \ - --hash=sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d \ - --hash=sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53 \ - --hash=sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138 \ - --hash=sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4 \ - --hash=sha256:3aa27acb6de7a23785d81557577491f6c38a5209a254d1191519d07d8fe51748 \ - --hash=sha256:3b06bcadaac49c70f4c88af4ffcfbe3dc155aab3163e75777818092478bcbbe7 \ - --hash=sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d \ - --hash=sha256:3e2daa88dc91870215961e96a039ec73e4937da13cf77ce17f9cad0c18df3503 \ - --hash=sha256:3ea66b1c11c9150f1372f69afb6b8116f2dd7286f38e14ea71a44eee9ec51b9d \ - --hash=sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2 \ - --hash=sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa \ - --hash=sha256:437840083abe022c978470b942ff832c3940b2ad3734d424b7eaffcd07f76737 \ - --hash=sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f \ - --hash=sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1 \ - --hash=sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d \ - --hash=sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694 \ - --hash=sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3 \ - --hash=sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a \ - --hash=sha256:4c52a6e78aef5cf47a98ef8e934755abf53953379b7d53e68b15ff4420e6683d \ - --hash=sha256:4dcc74149ccc8bba31ce1944acee24813e93cfdee2acda3c172df844948ddf7b \ - --hash=sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a \ - --hash=sha256:51af598701f5299012b8416486b40fceef8c26fc87dc6d7d1f6fc30609ea0aa6 \ - --hash=sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b \ - --hash=sha256:595697f68bd1f0c1c159fcb97b661fc9c3f5db46498043555d04805430e79bea \ - --hash=sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5 \ - --hash=sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f \ - --hash=sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df \ - --hash=sha256:5cdac20da754f3a723cceea5b3448e1a2074866406adeb4ef35b469d089adb8f \ - --hash=sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b \ - --hash=sha256:5dbeefd6ca588b33576a01b0ad58aa934bc1b41ef89dee505bf2932b22ddffba \ - --hash=sha256:62441e55958977b8167b2709c164c91a6363e25da322d87ae6dd9c6019ceecf9 \ - --hash=sha256:663e1cadaddae26be034a6ab6072449a8426ddb03d500f43daf952b74553bba0 \ - --hash=sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6 \ - --hash=sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b \ - --hash=sha256:6944b2dc72c4d7f7052683487e3677456050ff77fcf5e6204e98caf785ad1967 \ - --hash=sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2 \ - --hash=sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708 \ - --hash=sha256:6dcbb0829c671f305be48a7227918cfcd11276c2d637a8033a99a02b67bf9eda \ - --hash=sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8 \ - --hash=sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10 \ - --hash=sha256:75976c6945d85dbb9ee6308cd7ff7b1fb9409380c82d6119bd778d8fcfe2931c \ - --hash=sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b \ - --hash=sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028 \ - --hash=sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e \ - --hash=sha256:80ddf7a5f8c86cb3eb4bc9028b07bbbf1f08a96c5c0bc1244be5e8fefcb94147 \ - --hash=sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33 \ - --hash=sha256:84fc3ec96fce86ce5aa305eb4aa9358279d1aa644b71fab7b8ed33fe3ba1a7ca \ - --hash=sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590 \ - --hash=sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c \ - --hash=sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53 \ - --hash=sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74 \ - --hash=sha256:99b6fc1d55782461b78221e95fc357b47ad98b041e8e20f47c1411d0aacddc60 \ - --hash=sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f \ - --hash=sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1 \ - --hash=sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27 \ - --hash=sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520 \ - --hash=sha256:a4fcfc8eb2c34148c118dfa02e6427ca278bfd0f3df7c5f99e33d2c0e81eae3e \ - --hash=sha256:a899cbd98dce6f5d8de1aad31cb712ec0a530abc0a86bd6edaa47c1090138467 \ - --hash=sha256:a9b1ba5610a4e20f655258d5a1fdc7ebe3d837bb0e45b581398b99eb98b1f5ca \ - --hash=sha256:af74f05666a5e531289cb1cc9c883d1de2088b8e5b4de48004e5ca8a830ac859 \ - --hash=sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273 \ - --hash=sha256:b266bd01fedeffeeac01a79ae181719ff848a5a13ce10075adbefc8f1daee70e \ - --hash=sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601 \ - --hash=sha256:b580e71cac3f8113d3135888770903eaf2f507e9421e5697d6ee6d8cd1c7f054 \ - --hash=sha256:b6a6f620cfe13ccec221fa312139135166e47ae169f8253f72a0abc0dae94376 \ - --hash=sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7 \ - --hash=sha256:b85b982afde6df99ecc996990d4ad7ccbdbb70e2a4ba4de0aecde5922ba98a0b \ - --hash=sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb \ - --hash=sha256:ba440ae430c00eee41509353628600212112cd5018d5def7e9b05ea7ac34eb65 \ - --hash=sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784 \ - --hash=sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71 \ - --hash=sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b \ - --hash=sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a \ - --hash=sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c \ - --hash=sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face \ - --hash=sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d \ - --hash=sha256:c7bd6683587567e5a49ee6e336e0612bec8329be1b7d4c8af5687dcdeb67ee1e \ - --hash=sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e \ - --hash=sha256:cb95a9b1adaa48e41815a55ae740cfda005758104049a640a398120bf02515ca \ - --hash=sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9 \ - --hash=sha256:d332fc2e3c94dad927f2112395772a4e4fedbcf8f80efc21ed7cdfae4d574fdb \ - --hash=sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95 \ - --hash=sha256:d5372ca1df0f91a86b047d1277c2aaf1edb32d78bbcefffc81b40ffd18f027ed \ - --hash=sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf \ - --hash=sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca \ - --hash=sha256:dd7afd3f8b0bfb4e0d9fc3c31bfe8a4ec7debe124cfd90619305def3c8ca8cd2 \ - --hash=sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62 \ - --hash=sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df \ - --hash=sha256:e1b329cb8146d7b736677a2440e422eadd775d1806a81db2d4cded80a48efc1a \ - --hash=sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67 \ - --hash=sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f \ - --hash=sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529 \ - --hash=sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486 \ - --hash=sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a \ - --hash=sha256:e6438cc8f23a9c1478633d216b16104a586b9761db62bfacb6425bac0a36679e \ - --hash=sha256:e81fda2fb4a07eda1a2252b216aa0df23ebcd4d584894e9612e80999a78fd95b \ - --hash=sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74 \ - --hash=sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d \ - --hash=sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b \ - --hash=sha256:f0d97c18dfd9a9af4490631905a3f131a8e4c9e80a39353919e2cfed8f00aedc \ - --hash=sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2 \ - --hash=sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e \ - --hash=sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8 \ - --hash=sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82 \ - --hash=sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd \ - --hash=sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249 +yarl==1.23.0 \ + --hash=sha256:03214408cfa590df47728b84c679ae4ef00be2428e11630277be0727eba2d7cc \ + --hash=sha256:041b1a4cefacf65840b4e295c6985f334ba83c30607441ae3cf206a0eed1a2e4 \ + --hash=sha256:0793e2bd0cf14234983bbb371591e6bea9e876ddf6896cdcc93450996b0b5c85 \ + --hash=sha256:0e1fdaa14ef51366d7757b45bde294e95f6c8c049194e793eedb8387c86d5993 \ + --hash=sha256:0e40111274f340d32ebcc0a5668d54d2b552a6cca84c9475859d364b380e3222 \ + --hash=sha256:115136c4a426f9da976187d238e84139ff6b51a20839aa6e3720cd1026d768de \ + --hash=sha256:13a563739ae600a631c36ce096615fe307f131344588b0bc0daec108cdb47b25 \ + --hash=sha256:16c6994ac35c3e74fb0ae93323bf8b9c2a9088d55946109489667c510a7d010e \ + --hash=sha256:170e26584b060879e29fac213e4228ef063f39128723807a312e5c7fec28eff2 \ + --hash=sha256:17235362f580149742739cc3828b80e24029d08cbb9c4bda0242c7b5bc610a8e \ + --hash=sha256:1932b6b8bba8d0160a9d1078aae5838a66039e8832d41d2992daa9a3a08f7860 \ + --hash=sha256:1b6b572edd95b4fa8df75de10b04bc81acc87c1c7d16bcdd2035b09d30acc957 \ + --hash=sha256:1c3a3598a832590c5a3ce56ab5576361b5688c12cb1d39429cf5dba30b510760 \ + --hash=sha256:1c57676bdedc94cd3bc37724cf6f8cd2779f02f6aba48de45feca073e714fe52 \ + --hash=sha256:1dc702e42d0684f42d6519c8d581e49c96cefaaab16691f03566d30658ee8788 \ + --hash=sha256:21d1b7305a71a15b4794b5ff22e8eef96ff4a6d7f9657155e5aa419444b28912 \ + --hash=sha256:23f371bd662cf44a7630d4d113101eafc0cfa7518a2760d20760b26021454719 \ + --hash=sha256:2569b67d616eab450d262ca7cb9f9e19d2f718c70a8b88712859359d0ab17035 \ + --hash=sha256:263cd4f47159c09b8b685890af949195b51d1aa82ba451c5847ca9bc6413c220 \ + --hash=sha256:2803ed8b21ca47a43da80a6fd1ed3019d30061f7061daa35ac54f63933409412 \ + --hash=sha256:2a6940a074fb3c48356ed0158a3ca5699c955ee4185b4d7d619be3c327143e05 \ + --hash=sha256:2e27c8841126e017dd2a054a95771569e6070b9ee1b133366d8b31beb5018a41 \ + --hash=sha256:31c9921eb8bd12633b41ad27686bbb0b1a2a9b8452bfdf221e34f311e9942ed4 \ + --hash=sha256:34b6cf500e61c90f305094911f9acc9c86da1a05a7a3f5be9f68817043f486e4 \ + --hash=sha256:3650dc2480f94f7116c364096bc84b1d602f44224ef7d5c7208425915c0475dd \ + --hash=sha256:389871e65468400d6283c0308e791a640b5ab5c83bcee02a2f51295f95e09748 \ + --hash=sha256:39004f0ad156da43e86aa71f44e033de68a44e5a31fc53507b36dd253970054a \ + --hash=sha256:394906945aa8b19fc14a61cf69743a868bb8c465efe85eee687109cc540b98f4 \ + --hash=sha256:3ceb13c5c858d01321b5d9bb65e4cf37a92169ea470b70fec6f236b2c9dd7e34 \ + --hash=sha256:411225bae281f114067578891bc75534cfb3d92a3b4dfef7a6ca78ba354e6069 \ + --hash=sha256:44bb7bef4ea409384e3f8bc36c063d77ea1b8d4a5b2706956c0d6695f07dcc25 \ + --hash=sha256:4503053d296bc6e4cbd1fad61cf3b6e33b939886c4f249ba7c78b602214fabe2 \ + --hash=sha256:4764a6a7588561a9aef92f65bda2c4fb58fe7c675c0883862e6df97559de0bfb \ + --hash=sha256:4966242ec68afc74c122f8459abd597afd7d8a60dc93d695c1334c5fd25f762f \ + --hash=sha256:4a42e651629dafb64fd5b0286a3580613702b5809ad3f24934ea87595804f2c5 \ + --hash=sha256:4a59ba56f340334766f3a4442e0efd0af895fae9e2b204741ef885c446b3a1a8 \ + --hash=sha256:4c41e021bc6d7affb3364dc1e1e5fa9582b470f283748784bd6ea0558f87f42c \ + --hash=sha256:5023346c4ee7992febc0068e7593de5fa2bf611848c08404b35ebbb76b1b0512 \ + --hash=sha256:50f9d8d531dfb767c565f348f33dd5139a6c43f5cbdf3f67da40d54241df93f6 \ + --hash=sha256:51430653db848d258336cfa0244427b17d12db63d42603a55f0d4546f50f25b5 \ + --hash=sha256:531ef597132086b6cf96faa7c6c1dcd0361dd5f1694e5cc30375907b9b7d3ea9 \ + --hash=sha256:53ad387048f6f09a8969631e4de3f1bf70c50e93545d64af4f751b2498755072 \ + --hash=sha256:53b1ea6ca88ebd4420379c330aea57e258408dd0df9af0992e5de2078dc9f5d5 \ + --hash=sha256:575aa4405a656e61a540f4a80eaa5260f2a38fff7bfdc4b5f611840d76e9e277 \ + --hash=sha256:578110dd426f0d209d1509244e6d4a3f1a3e9077655d98c5f22583d63252a08a \ + --hash=sha256:5ec2f42d41ccbd5df0270d7df31618a8ee267bfa50997f5d720ddba86c4a83a6 \ + --hash=sha256:5ee586fb17ff8f90c91cf73c6108a434b02d69925f44f5f8e0d7f2f260607eae \ + --hash=sha256:5f10fd85e4b75967468af655228fbfd212bdf66db1c0d135065ce288982eda26 \ + --hash=sha256:609d3614d78d74ebe35f54953c5bbd2ac647a7ddb9c30a5d877580f5e86b22f2 \ + --hash=sha256:62694e275c93d54f7ccedcfef57d42761b2aad5234b6be1f3e3026cae4001cd4 \ + --hash=sha256:63e92247f383c85ab00dd0091e8c3fa331a96e865459f5ee80353c70a4a42d70 \ + --hash=sha256:682bae25f0a0dd23a056739f23a134db9f52a63e2afd6bfb37ddc76292bbd723 \ + --hash=sha256:6b41389c19b07c760c7e427a3462e8ab83c4bb087d127f0e854c706ce1b9215c \ + --hash=sha256:6e87a6e8735b44816e7db0b2fbc9686932df473c826b0d9743148432e10bb9b9 \ + --hash=sha256:6f0fd84de0c957b2d280143522c4f91a73aada1923caee763e24a2b3fda9f8a5 \ + --hash=sha256:70efd20be968c76ece7baa8dafe04c5be06abc57f754d6f36f3741f7aa7a208e \ + --hash=sha256:71d006bee8397a4a89f469b8deb22469fe7508132d3c17fa6ed871e79832691c \ + --hash=sha256:73309162a6a571d4cbd3b6a1dcc703c7311843ae0d1578df6f09be4e98df38d4 \ + --hash=sha256:75e3026ab649bf48f9a10c0134512638725b521340293f202a69b567518d94e0 \ + --hash=sha256:76855800ac56f878847a09ce6dba727c93ca2d89c9e9d63002d26b916810b0a2 \ + --hash=sha256:7c6b9461a2a8b47c65eef63bb1c76a4f1c119618ffa99ea79bc5bb1e46c5821b \ + --hash=sha256:803a3c3ce4acc62eaf01eaca1208dcf0783025ef27572c3336502b9c232005e7 \ + --hash=sha256:80e6d33a3d42a7549b409f199857b4fb54e2103fc44fb87605b6663b7a7ff750 \ + --hash=sha256:8419ebd326430d1cbb7efb5292330a2cf39114e82df5cc3d83c9a0d5ebeaf2f2 \ + --hash=sha256:85610b4f27f69984932a7abbe52703688de3724d9f72bceb1cca667deff27474 \ + --hash=sha256:85e9beda1f591bc73e77ea1c51965c68e98dafd0fec72cdd745f77d727466716 \ + --hash=sha256:877b0738624280e34c55680d6054a307aa94f7d52fa0e3034a9cc6e790871da7 \ + --hash=sha256:88f9fb0116fbfcefcab70f85cf4b74a2b6ce5d199c41345296f49d974ddb4123 \ + --hash=sha256:8c4fe09e0780c6c3bf2b7d4af02ee2394439d11a523bbcf095cf4747c2932007 \ + --hash=sha256:93a784271881035ab4406a172edb0faecb6e7d00f4b53dc2f55919d6c9688595 \ + --hash=sha256:94f8575fbdf81749008d980c17796097e645574a3b8c28ee313931068dad14fe \ + --hash=sha256:95451e6ce06c3e104556d73b559f5da6c34a069b6b62946d3ad66afcd51642ea \ + --hash=sha256:99c8a9ed30f4164bc4c14b37a90208836cbf50d4ce2a57c71d0f52c7fb4f7598 \ + --hash=sha256:9a18d6f9359e45722c064c97464ec883eb0e0366d33eda61cb19a244bf222679 \ + --hash=sha256:9cbf44c5cb4a7633d078788e1b56387e3d3cf2b8139a3be38040b22d6c3221c8 \ + --hash=sha256:9ee33b875f0b390564c1fb7bc528abf18c8ee6073b201c6ae8524aca778e2d83 \ + --hash=sha256:a0e317df055958a0c1e79e5d2aa5a5eaa4a6d05a20d4b0c9c3f48918139c9fc6 \ + --hash=sha256:a2df6afe50dea8ae15fa34c9f824a3ee958d785fd5d089063d960bae1daa0a3f \ + --hash=sha256:a31de1613658308efdb21ada98cbc86a97c181aa050ba22a808120bb5be3ab94 \ + --hash=sha256:a3d2bff8f37f8d0f96c7ec554d16945050d54462d6e95414babaa18bfafc7f51 \ + --hash=sha256:a41bcf68efd19073376eb8cf948b8d9be0af26256403e512bb18f3966f1f9120 \ + --hash=sha256:a82836cab5f197a0514235aaf7ffccdc886ccdaa2324bc0aafdd4ae898103039 \ + --hash=sha256:a8d00f29b42f534cc8aa3931cfe773b13b23e561e10d2b26f27a8d309b0e82a1 \ + --hash=sha256:aafe5dcfda86c8af00386d7781d4c2181b5011b7be3f2add5e99899ea925df05 \ + --hash=sha256:ab5f043cb8a2d71c981c09c510da013bc79fd661f5c60139f00dd3c3cc4f2ffb \ + --hash=sha256:ac09d42f48f80c9ee1635b2fcaa819496a44502737660d3c0f2ade7526d29144 \ + --hash=sha256:aecfed0b41aa72b7881712c65cf764e39ce2ec352324f5e0837c7048d9e6daaa \ + --hash=sha256:b2c6b50c7b0464165472b56b42d4c76a7b864597007d9c085e8b63e185cf4a7a \ + --hash=sha256:b35d13d549077713e4414f927cdc388d62e543987c572baee613bf82f11a4b99 \ + --hash=sha256:b39cb32a6582750b6cc77bfb3c49c0f8760dc18dc96ec9fb55fbb0f04e08b928 \ + --hash=sha256:b5405bb8f0e783a988172993cfc627e4d9d00432d6bbac65a923041edacf997d \ + --hash=sha256:baaf55442359053c7d62f6f8413a62adba3205119bcb6f49594894d8be47e5e3 \ + --hash=sha256:bd654fad46d8d9e823afbb4f87c79160b5a374ed1ff5bde24e542e6ba8f41434 \ + --hash=sha256:be61f6fff406ca40e3b1d84716fde398fc08bc63dd96d15f3a14230a0973ed86 \ + --hash=sha256:bf49a3ae946a87083ef3a34c8f677ae4243f5b824bfc4c69672e72b3d6719d46 \ + --hash=sha256:c4a80f77dc1acaaa61f0934176fccca7096d9b1ff08c8ba9cddf5ae034a24319 \ + --hash=sha256:c75eb09e8d55bceb4367e83496ff8ef2bc7ea6960efb38e978e8073ea59ecb67 \ + --hash=sha256:c7f8dc16c498ff06497c015642333219871effba93e4a2e8604a06264aca5c5c \ + --hash=sha256:c8aa34a5c864db1087d911a0b902d60d203ea3607d91f615acd3f3108ac32169 \ + --hash=sha256:cbb0fef01f0c6b38cb0f39b1f78fc90b807e0e3c86a7ff3ce74ad77ce5c7880c \ + --hash=sha256:cde9a2ecd91668bcb7f077c4966d8ceddb60af01b52e6e3e2680e4cf00ad1a59 \ + --hash=sha256:cff6d44cb13d39db2663a22b22305d10855efa0fa8015ddeacc40bc59b9d8107 \ + --hash=sha256:d1009abedb49ae95b136a8904a3f71b342f849ffeced2d3747bf29caeda218c4 \ + --hash=sha256:d38c1e8231722c4ce40d7593f28d92b5fc72f3e9774fe73d7e800ec32299f63a \ + --hash=sha256:d53834e23c015ee83a99377db6e5e37d8484f333edb03bd15b4bc312cc7254fb \ + --hash=sha256:d7504f2b476d21653e4d143f44a175f7f751cd41233525312696c76aa3dbb23f \ + --hash=sha256:dbf507e9ef5688bada447a24d68b4b58dd389ba93b7afc065a2ba892bea54769 \ + --hash=sha256:dc52310451fc7c629e13c4e061cbe2dd01684d91f2f8ee2821b083c58bd72432 \ + --hash=sha256:dd00607bffbf30250fe108065f07453ec124dbf223420f57f5e749b04295e090 \ + --hash=sha256:dda608c88cf709b1d406bdfcd84d8d63cff7c9e577a403c6108ce8ce9dcc8764 \ + --hash=sha256:debe9c4f41c32990771be5c22b56f810659f9ddf3d63f67abfdcaa2c6c9c5c1d \ + --hash=sha256:e09fd068c2e169a7070d83d3bde728a4d48de0549f975290be3c108c02e499b4 \ + --hash=sha256:e0fd068364a6759bc794459f0a735ab151d11304346332489c7972bacbe9e72b \ + --hash=sha256:e4c53f8347cd4200f0d70a48ad059cabaf24f5adc6ba08622a23423bc7efa10d \ + --hash=sha256:e5723c01a56c5028c807c701aa66722916d2747ad737a046853f6c46f4875543 \ + --hash=sha256:e7b0460976dc75cb87ad9cc1f9899a4b97751e7d4e77ab840fc9b6d377b8fd24 \ + --hash=sha256:e9d9a4d06d3481eab79803beb4d9bd6f6a8e781ec078ac70d7ef2dcc29d1bea5 \ + --hash=sha256:ead11956716a940c1abc816b7df3fa2b84d06eaed8832ca32f5c5e058c65506b \ + --hash=sha256:ed5f69ce7be7902e5c70ea19eb72d20abf7d725ab5d49777d696e32d4fc1811d \ + --hash=sha256:f2af5c81a1f124609d5f33507082fc3f739959d4719b56877ab1ee7e7b3d602b \ + --hash=sha256:f40e782d49630ad384db66d4d8b73ff4f1b8955dc12e26b09a3e3af064b3b9d6 \ + --hash=sha256:f514f6474e04179d3d33175ed3f3e31434d3130d42ec153540d5b157deefd735 \ + --hash=sha256:f69f57305656a4852f2a7203efc661d8c042e6cc67f7acd97d8667fb448a426e \ + --hash=sha256:fb1e8b8d66c278b21d13b0a7ca22c41dd757a7c209c6b12c313e445c31dd3b28 \ + --hash=sha256:fb4948814a2a98e3912505f09c9e7493b1506226afb1f881825368d6fb776ee3 \ + --hash=sha256:fda207c815b253e34f7e1909840fd14299567b1c0eb4908f8c2ce01a41265401 \ + --hash=sha256:fe8f8f5e70e6dbdfca9882cd9deaac058729bcf323cf7a58660901e55c9c94f6 \ + --hash=sha256:fffc45637bcd6538de8b85f51e3df3223e4ad89bccbfca0481c08c7fc8b7ed7d # via aiohttp zipp==3.23.0 \ --hash=sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e \ diff --git a/sdk/python/requirements/py3.10-minimal-sdist-requirements-build.txt b/sdk/python/requirements/py3.10-minimal-sdist-requirements-build.txt index 70db9118276..3ecce8ab7be 100644 --- a/sdk/python/requirements/py3.10-minimal-sdist-requirements-build.txt +++ b/sdk/python/requirements/py3.10-minimal-sdist-requirements-build.txt @@ -295,9 +295,9 @@ hatch-vcs==0.5.0 \ # via # filelock # platformdirs -hatchling==1.28.0 \ - --hash=sha256:4d50b02aece6892b8cd0b3ce6c82cb218594d3ec5836dbde75bf41a21ab004c8 \ - --hash=sha256:dc48722b68b3f4bbfa3ff618ca07cdea6750e7d03481289ffa8be1521d18a961 +hatchling==1.29.0 \ + --hash=sha256:50af9343281f34785fab12da82e445ed987a6efb34fd8c2fc0f6e6630dbcc1b0 \ + --hash=sha256:793c31816d952cee405b83488ce001c719f325d9cda69f1fc4cd750527640ea6 # via # annotated-types # atpublic @@ -334,97 +334,97 @@ jinja2==3.1.6 \ --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 # via uv-dynamic-versioning -librt==0.8.0 \ - --hash=sha256:001e5330093d887b8b9165823eca6c5c4db183fe4edea4fdc0680bbac5f46944 \ - --hash=sha256:015e2dde6e096d27c10238bf9f6492ba6c65822dfb69d2bf74c41a8e88b7ddef \ - --hash=sha256:02a9fe85410cc9bef045e7cb7fd26fdde6669e6d173f99df659aa7f6335961e9 \ - --hash=sha256:0583aef7e9a720dd40f26a2ad5a1bf2ccbb90059dac2b32ac516df232c701db3 \ - --hash=sha256:05a3dd3f116747f7e1a2b475ccdc6fb637fd4987126d109e03013a79d40bf9e6 \ - --hash=sha256:0a33335eb59921e77c9acc05d0e654e4e32e45b014a4d61517897c11591094f8 \ - --hash=sha256:0ce33a9778e294507f3a0e3468eccb6a698b5166df7db85661543eca1cfc5369 \ - --hash=sha256:1566dbb9d1eb0987264c9b9460d212e809ba908d2f4a3999383a84d765f2f3f1 \ - --hash=sha256:17269dd2745dbe8e42475acb28e419ad92dfa38214224b1b01020b8cac70b645 \ - --hash=sha256:178707cda89d910c3b28bf5aa5f69d3d4734e0f6ae102f753ad79edef83a83c7 \ - --hash=sha256:1c25a131013eadd3c600686a0c0333eb2896483cbc7f65baa6a7ee761017aef9 \ - --hash=sha256:1e6811cac1dcb27ca4c74e0ca4a5917a8e06db0d8408d30daee3a41724bfde7a \ - --hash=sha256:1ef3bd856373cf8e7382402731f43bfe978a8613b4039e49e166e1e0dc590216 \ - --hash=sha256:20f73d4fecba969efc15cdefd030e382502d56bb6f1fc66b580cce582836c9fa \ - --hash=sha256:21b14464bee0b604d80a638cf1ee3148d84ca4cc163dcdcecb46060c1b3605e4 \ - --hash=sha256:24a01c13a2a9bdad20997a4443ebe6e329df063d1978bbe2ebbf637878a46d1e \ - --hash=sha256:25b3e667cbfc9000c4740b282df599ebd91dbdcc1aa6785050e4c1d6be5329ab \ - --hash=sha256:25e82d920d4d62ad741592fcf8d0f3bda0e3fc388a184cb7d2f566c681c5f7b9 \ - --hash=sha256:2b37437e7e4ef5e15a297b36ba9e577f73e29564131d86dd75875705e97402b5 \ - --hash=sha256:2ccdd20d9a72c562ffb73098ac411de351b53a6fbb3390903b2d33078ef90447 \ - --hash=sha256:2e0ffe88ebb5962f8fb0ddcbaaff30f1ea06a79501069310e1e030eafb1ad787 \ - --hash=sha256:375eda7acfce1f15f5ed56cfc960669eefa1ec8732e3e9087c3c4c3f2066759c \ - --hash=sha256:3d2720335020219197380ccfa5c895f079ac364b4c429e96952cd6509934d8eb \ - --hash=sha256:3e36a8da17134ffc29373775d88c04832f9ecfab1880470661813e6c7991ef79 \ - --hash=sha256:3e8b77b5f54d0937b26512774916041756c9eb3e66f1031971e626eea49d0bf4 \ - --hash=sha256:41064a0c07b4cc7a81355ccc305cb097d6027002209ffca51306e65ee8293630 \ - --hash=sha256:421765e8c6b18e64d21c8ead315708a56fc24f44075059702e421d164575fdda \ - --hash=sha256:4831c44b8919e75ca0dfb52052897c1ef59fdae19d3589893fbd068f1e41afbf \ - --hash=sha256:48f84830a8f8ad7918afd743fd7c4eb558728bceab7b0e38fd5a5cf78206a556 \ - --hash=sha256:4b705f85311ee76acec5ee70806990a51f0deb519ea0c29c1d1652d79127604d \ - --hash=sha256:4d3e38797eb482485b486898f89415a6ab163bc291476bd95712e42cf4383c05 \ - --hash=sha256:4eb5e06ebcc668677ed6389164f52f13f71737fc8be471101fa8b4ce77baeb0c \ - --hash=sha256:4f6e975377fbc4c9567cb33ea9ab826031b6c7ec0515bfae66a4fb110d40d6da \ - --hash=sha256:4f764b2424cb04524ff7a486b9c391e93f93dc1bd8305b2136d25e582e99aa2f \ - --hash=sha256:507e94f4bec00b2f590fbe55f48cd518a208e2474a3b90a60aa8f29136ddbada \ - --hash=sha256:56901f1eec031396f230db71c59a01d450715cbbef9856bf636726994331195d \ - --hash=sha256:5cb11061a736a9db45e3c1293cfcb1e3caf205912dfa085734ba750f2197ff9a \ - --hash=sha256:5d0f76fc73480d42285c609c0ea74d79856c160fa828ff9aceab574ea4ecfd7b \ - --hash=sha256:667e2513cf69bfd1e1ed9a00d6c736d5108714ec071192afb737987955888a25 \ - --hash=sha256:671a6152edf3b924d98a5ed5e6982ec9cb30894085482acadce0975f031d4c5c \ - --hash=sha256:693697133c3b32aa9b27f040e3691be210e9ac4d905061859a9ed519b1d5a376 \ - --hash=sha256:6a3146c63220d814c4a2c7d6a1eacc8d5c14aed0ff85115c1dfea868080cd18f \ - --hash=sha256:6b6caff69e25d80c269b1952be8493b4d94ef745f438fa619d7931066bdd26de \ - --hash=sha256:6e1af31a710e17891d9adf0dbd9a5fcd94901a3922a96499abdbf7ce658f4e01 \ - --hash=sha256:70defb797c4d5402166787a6b3c66dfb3fa7f93d118c0509ffafa35a392f4258 \ - --hash=sha256:71fc517efc14f75c2f74b1f0a5d5eb4a8e06aa135c34d18eaf3522f4a53cd62d \ - --hash=sha256:75d1a8cab20b2043f03f7aab730551e9e440adc034d776f15f6f8d582b0a5ad4 \ - --hash=sha256:789911e8fa40a2e82f41120c936b1965f3213c67f5a483fc5a41f5839a05dcbb \ - --hash=sha256:7bd68cebf3131bb920d5984f75fe302d758db33264e44b45ad139385662d7bc3 \ - --hash=sha256:7ce0a8cb67e702dcb06342b2aaaa3da9fb0ddc670417879adfa088b44cf7b3b6 \ - --hash=sha256:7f820210e21e3a8bf8fde2ae3c3d10106d4de9ead28cbfdf6d0f0f41f5b12fa1 \ - --hash=sha256:8070aa3368559de81061ef752770d03ca1f5fc9467d4d512d405bd0483bfffe6 \ - --hash=sha256:82e61cd1c563745ad495387c3b65806bfd453badb4adbc019df3389dddee1bf6 \ - --hash=sha256:82fb4602d1b3e303a58bfe6165992b5a78d823ec646445356c332cd5f5bbaa61 \ - --hash=sha256:88c6e75540f1f10f5e0fc5e87b4b6c290f0e90d1db8c6734f670840494764af8 \ - --hash=sha256:8992ca186a1678107b0af3d0c9303d8c7305981b9914989b9788319ed4d89546 \ - --hash=sha256:92249938ab744a5890580d3cb2b22042f0dce71cdaa7c1369823df62bedf7cbc \ - --hash=sha256:95a719a049f0eefaf1952673223cf00d442952273cbd20cf2ed7ec423a0ef58d \ - --hash=sha256:9646178cd794704d722306c2c920c221abbf080fede3ba539d5afdec16c46dad \ - --hash=sha256:9726305d3e53419d27fc8cdfcd3f9571f0ceae22fa6b5ea1b3662c2e538f833e \ - --hash=sha256:995d24caa6bbb34bcdd4a41df98ac6d1af637cfa8975cb0790e47d6623e70e3e \ - --hash=sha256:9ab3a3475a55b89b87ffd7e6665838e8458e0b596c22e0177e0f961434ec474a \ - --hash=sha256:9f09d4884f882baa39a7e36bbf3eae124c4ca2a223efb91e567381d1c55c6b06 \ - --hash=sha256:a512c88900bdb1d448882f5623a0b1ad27ba81a9bd75dacfe17080b72272ca1f \ - --hash=sha256:a905091a13e0884701226860836d0386b88c72ce5c2fdfba6618e14c72be9f25 \ - --hash=sha256:aaadec87f45a3612b6818d1db5fbfe93630669b7ee5d6bdb6427ae08a1aa2141 \ - --hash=sha256:b055bb3abaf69abed25743d8fc1ab691e4f51a912ee0a6f9a6c84f4bbddb283d \ - --hash=sha256:b4bb00bd71b448f16749909b08a0ff16f58b079e2261c2e1000f2bbb2a4f0a45 \ - --hash=sha256:b9aef96d7593584e31ef6ac1eb9775355b0099fee7651fae3a15bc8657b67b52 \ - --hash=sha256:ba581acad5ac8f33e2ff1746e8a57e001b47c6721873121bf8bbcf7ba8bd3aa4 \ - --hash=sha256:ba9d9e60651615bc614be5e21a82cdb7b1769a029369cf4b4d861e4f19686fb6 \ - --hash=sha256:bbebd2bba5c6ae02907df49150e55870fdd7440d727b6192c46b6f754723dde9 \ - --hash=sha256:bd32add59b58fba3439d48d6f36ac695830388e3da3e92e4fc26d2d02670d19c \ - --hash=sha256:bdab762e2c0b48bab76f1a08acb3f4c77afd2123bedac59446aeaaeed3d086cf \ - --hash=sha256:c5512aae4648152abaf4d48b59890503fcbe86e85abc12fb9b096fe948bdd816 \ - --hash=sha256:c6e4c10761ddbc0d67d2f6e2753daf99908db85d8b901729bf2bf5eaa60e0567 \ - --hash=sha256:cb4b3ad543084ed79f186741470b251b9d269cd8b03556f15a8d1a99a64b7de5 \ - --hash=sha256:cb74cdcbc0103fc988e04e5c58b0b31e8e5dd2babb9182b6f9490488eb36324b \ - --hash=sha256:cc3d107f603b5ee7a79b6aa6f166551b99b32fb4a5303c4dfcb4222fc6a0335e \ - --hash=sha256:d920789eca7ef71df7f31fd547ec0d3002e04d77f30ba6881e08a630e7b2c30e \ - --hash=sha256:daae5e955764be8fd70a93e9e5133c75297f8bce1e802e1d3683b98f77e1c5ab \ - --hash=sha256:db63cf3586a24241e89ca1ce0b56baaec9d371a328bd186c529b27c914c9a1ef \ - --hash=sha256:db953b675079884ffda33d1dca7189fb961b6d372153750beb81880384300817 \ - --hash=sha256:de076eaba208d16efb5962f99539867f8e2c73480988cb513fcf1b5dbb0c9dcf \ - --hash=sha256:e79dbc8f57de360f0ed987dc7de7be814b4803ef0e8fc6d3ff86e16798c99935 \ - --hash=sha256:e9a3a38eb4134ad33122a6d575e6324831f930a771d951a15ce232e0237412c2 \ - --hash=sha256:f04ca50e847abc486fa8f4107250566441e693779a5374ba211e96e238f298b9 \ - --hash=sha256:f1178e0de0c271231a660fbef9be6acdfa1d596803464706862bef6644cc1cae \ - --hash=sha256:f4617cef654fca552f00ce5ffdf4f4b68770f18950e4246ce94629b789b92467 \ - --hash=sha256:fa37f99bff354ff191c6bcdffbc9d7cdd4fc37faccfc9be0ef3a4fd5613977da +librt==0.8.1 \ + --hash=sha256:01170b6729a438f0dedc4a26ed342e3dc4f02d1000b4b19f980e1877f0c297e6 \ + --hash=sha256:039b9f2c506bd0ab0f8725aa5ba339c6f0cd19d3b514b50d134789809c24285d \ + --hash=sha256:05bd41cdee35b0c59c259f870f6da532a2c5ca57db95b5f23689fcb5c9e42440 \ + --hash=sha256:086a32dbb71336627e78cc1d6ee305a68d038ef7d4c39aaff41ae8c9aa46e91a \ + --hash=sha256:08eec3a1fc435f0d09c87b6bf1ec798986a3544f446b864e4099633a56fcd9ed \ + --hash=sha256:0bf69d79a23f4f40b8673a947a234baeeb133b5078b483b7297c5916539cf5d5 \ + --hash=sha256:0c3811485fccfda840861905b8c70bba5ec094e02825598bb9d4ca3936857a04 \ + --hash=sha256:0d2f82168e55ddefd27c01c654ce52379c0750ddc31ee86b4b266bcf4d65f2a3 \ + --hash=sha256:0f2ae3725904f7377e11cc37722d5d401e8b3d5851fb9273d7f4fe04f6b3d37d \ + --hash=sha256:10c42e1f6fd06733ef65ae7bebce2872bcafd8d6e6b0a08fe0a05a23b044fb14 \ + --hash=sha256:153188fe98a72f206042be10a2c6026139852805215ed9539186312d50a8e972 \ + --hash=sha256:172d57ec04346b047ca6af181e1ea4858086c80bdf455f61994c4aa6fc3f866c \ + --hash=sha256:190b109bb69592a3401fe1ffdea41a2e73370ace2ffdc4a0e8e2b39cdea81b78 \ + --hash=sha256:1d3a7da44baf692f0c6aeb5b2a09c5e6fc7a703bca9ffa337ddd2e2da53f7732 \ + --hash=sha256:228c2409c079f8c11fb2e5d7b277077f694cb93443eb760e00b3b83cb8b3176c \ + --hash=sha256:22b46eabd76c1986ee7d231b0765ad387d7673bbd996aa0d0d054b38ac65d8f6 \ + --hash=sha256:237796479f4d0637d6b9cbcb926ff424a97735e68ade6facf402df4ec93375ed \ + --hash=sha256:2c74a2da57a094bd48d03fa5d196da83d2815678385d2978657499063709abe1 \ + --hash=sha256:2cc68eeeef5e906839c7bb0815748b5b0a974ec27125beefc0f942715785b551 \ + --hash=sha256:2eb345e8b33fb748227409c9f1233d4df354d6e54091f0e8fc53acdb2ffedeb7 \ + --hash=sha256:31362dbfe297b23590530007062c32c6f6176f6099646bb2c95ab1b00a57c382 \ + --hash=sha256:3dff3d3ca8db20e783b1bc7de49c0a2ab0b8387f31236d6a026597d07fcd68ac \ + --hash=sha256:43353b943613c5d9c49a25aaffdba46f888ec354e71e3529a00cca3f04d66a7a \ + --hash=sha256:439352ba9373f11cb8e1933da194dcc6206daf779ff8df0ed69c5e39113e6a99 \ + --hash=sha256:4998009e7cb9e896569f4be7004f09d0ed70d386fa99d42b6d363f6d200501ac \ + --hash=sha256:4be2a5c926b9770c9e08e717f05737a269b9d0ebc5d2f0060f0fe3fe9ce47acb \ + --hash=sha256:4beb04b8c66c6ae62f8c1e0b2f097c1ebad9295c929a8d5286c05eae7c2fc7dc \ + --hash=sha256:4c8dfa264b9193c4ee19113c985c95f876fae5e51f731494fc4e0cf594990ba7 \ + --hash=sha256:5212a5bd7fae98dae95710032902edcd2ec4dc994e883294f75c857b83f9aba0 \ + --hash=sha256:52c224e14614b750c0a6d97368e16804a98c684657c7518752c356834fff83bb \ + --hash=sha256:56e04c14b696300d47b3bc5f1d10a00e86ae978886d0cee14e5714fafb5df5d2 \ + --hash=sha256:5bb54f1205a3a6ab41a6fd71dfcdcbd278670d3a90ca502a30d9da583105b6f7 \ + --hash=sha256:5cdc0f588ff4b663ea96c26d2a230c525c6fc62b28314edaaaca8ed5af931ad0 \ + --hash=sha256:5db05697c82b3a2ec53f6e72b2ed373132b0c2e05135f0696784e97d7f5d48e7 \ + --hash=sha256:5e4af413908f77294605e28cfd98063f54b2c790561383971d2f52d113d9c363 \ + --hash=sha256:5fc48998000cbc39ec0d5311312dda93ecf92b39aaf184c5e817d5d440b29624 \ + --hash=sha256:60a78b694c9aee2a0f1aaeaa7d101cf713e92e8423a941d2897f4fa37908dab9 \ + --hash=sha256:64548cde61b692dc0dc379f4b5f59a2f582c2ebe7890d09c1ae3b9e66fa015b7 \ + --hash=sha256:681dc2451d6d846794a828c16c22dc452d924e9f700a485b7ecb887a30aad1fd \ + --hash=sha256:6b1977c4ea97ce5eb7755a78fae68d87e4102e4aaf54985e8b56806849cc06a3 \ + --hash=sha256:6cfa7fe54fd4d1f47130017351a959fe5804bda7a0bc7e07a2cdbc3fdd28d34f \ + --hash=sha256:738f08021b3142c2918c03692608baed43bc51144c29e35807682f8070ee2a3a \ + --hash=sha256:747328be0c5b7075cde86a0e09d7a9196029800ba75a1689332348e998fb85c0 \ + --hash=sha256:758509ea3f1eba2a57558e7e98f4659d0ea7670bff49673b0dde18a3c7e6c0eb \ + --hash=sha256:785ae29c1f5c6e7c2cde2c7c0e148147f4503da3abc5d44d482068da5322fd9e \ + --hash=sha256:7aae78ab5e3206181780e56912d1b9bb9f90a7249ce12f0e8bf531d0462dd0fc \ + --hash=sha256:7b02679a0d783bdae30d443025b94465d8c3dc512f32f5b5031f93f57ac32071 \ + --hash=sha256:7e2f3edca35664499fbb36e4770650c4bd4a08abc1f4458eab9df4ec56389730 \ + --hash=sha256:7e6bad1cd94f6764e1e21950542f818a09316645337fd5ab9a7acc45d99a8f35 \ + --hash=sha256:81fd938344fecb9373ba1b155968c8a329491d2ce38e7ddb76f30ffb938f12dc \ + --hash=sha256:82210adabbc331dbb65d7868b105185464ef13f56f7f76688565ad79f648b0fe \ + --hash=sha256:89815a22daf9c51884fb5dbe4f1ef65ee6a146e0b6a8df05f753e2e4a9359bf4 \ + --hash=sha256:8f1125e6bbf2f1657d9a2f3ccc4a2c9b0c8b176965bb565dd4d86be67eddb4b6 \ + --hash=sha256:8f4bb453f408137d7581be309b2fbc6868a80e7ef60c88e689078ee3a296ae71 \ + --hash=sha256:924817ab3141aca17893386ee13261f1d100d1ef410d70afe4389f2359fea4f0 \ + --hash=sha256:93c2af9e01e0ef80d95ae3c720be101227edae5f2fe7e3dc63d8857fadfc5a1d \ + --hash=sha256:97c2b54ff6717a7a563b72627990bec60d8029df17df423f0ed37d56a17a176b \ + --hash=sha256:9be2f15e53ce4e83cc08adc29b26fb5978db62ef2a366fbdf716c8a6c8901040 \ + --hash=sha256:9e2c6f77b9ad48ce5603b83b7da9ee3e36b3ab425353f695cba13200c5d96596 \ + --hash=sha256:a28f2612ab566b17f3698b0da021ff9960610301607c9a5e8eaca62f5e1c350a \ + --hash=sha256:a355d99c4c0d8e5b770313b8b247411ed40949ca44e33e46a4789b9293a907ee \ + --hash=sha256:a3b4350b13cc0e6f5bec8fa7caf29a8fb8cdc051a3bae45cfbfd7ce64f009965 \ + --hash=sha256:aaab0e307e344cb28d800957ef3ec16605146ef0e59e059a60a176d19543d1b7 \ + --hash=sha256:ac1e7817fd0ed3d14fd7c5df91daed84c48e4c2a11ee99c0547f9f62fdae13da \ + --hash=sha256:adfab487facf03f0d0857b8710cf82d0704a309d8ffc33b03d9302b4c64e91a9 \ + --hash=sha256:b6d7ab1f01aa753188605b09a51faa44a3327400b00b8cce424c71910fc0a128 \ + --hash=sha256:bacdb58d9939d95cc557b4dbaa86527c9db2ac1ed76a18bc8d26f6dc8647d851 \ + --hash=sha256:be46a14693955b3bd96014ccbdb8339ee8c9346fbe11c1b78901b55125f14c73 \ + --hash=sha256:bf512a71a23504ed08103a13c941f763db13fb11177beb3d9244c98c29fb4a61 \ + --hash=sha256:c00e5c884f528c9932d278d5c9cbbea38a6b81eb62c02e06ae53751a83a4d52b \ + --hash=sha256:c25d9e338d5bed46c1632f851babf3d13c78f49a225462017cf5e11e845c5891 \ + --hash=sha256:c336d61d2fe74a3195edc1646d53ff1cddd3a9600b09fa6ab75e5514ba4862a7 \ + --hash=sha256:cc3656283d11540ab0ea01978378e73e10002145117055e03722417aeab30994 \ + --hash=sha256:cf450f498c30af55551ba4f66b9123b7185362ec8b625a773b3d39aa1a717583 \ + --hash=sha256:d0ee06b5b5291f609ddb37b9750985b27bc567791bc87c76a569b3feed8481ac \ + --hash=sha256:d480de377f5b687b6b1bc0c0407426da556e2a757633cc7e4d2e1a057aa688f3 \ + --hash=sha256:d56bc4011975f7460bea7b33e1ff425d2f1adf419935ff6707273c77f8a4ada6 \ + --hash=sha256:dd3c41254ee98604b08bd5b3af5bf0a89740d4ee0711de95b65166bf44091921 \ + --hash=sha256:e0d138c7ae532908cbb342162b2611dbd4d90c941cd25ab82084aaf71d2c0bd0 \ + --hash=sha256:e11769a1dbda4da7b00a76cfffa67aa47cfa66921d2724539eee4b9ede780b79 \ + --hash=sha256:e3f0a41487fd5fad7e760b9e8a90e251e27c2816fbc2cff36a22a0e6bcbbd9dd \ + --hash=sha256:e692aa2d1d604e6ca12d35e51fdc36f4cda6345e28e36374579f7ef3611b3012 \ + --hash=sha256:e70a57ecf89a0f64c24e37f38d3fe217a58169d2fe6ed6d70554964042474023 \ + --hash=sha256:e96baa6820280077a78244b2e06e416480ed859bbd8e5d641cf5742919d8beb4 \ + --hash=sha256:eb5656019db7c4deacf0c1a55a898c5bb8f989be904597fcb5232a2f4828fa05 \ + --hash=sha256:eca45e982fa074090057132e30585a7e8674e9e885d402eae85633e9f449ce6c \ + --hash=sha256:f0af2bd2bc204fa27f3d6711d0f360e6b8c684a035206257a81673ab924aa11e \ + --hash=sha256:f7cdf7f26c2286ffb02e46d7bac56c94655540b26347673bea15fa52a6af17e9 \ + --hash=sha256:fd1a720332ea335ceb544cf0a03f81df92abd4bb887679fd1e460976b0e6214b \ + --hash=sha256:ff8baf1f8d3f4b6b7257fcb75a501f2a5499d0dda57645baa09d4d0d34b19444 # via mypy markupsafe==3.0.3 \ --hash=sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f \ @@ -517,21 +517,21 @@ markupsafe==3.0.3 \ --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \ --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50 # via jinja2 -maturin==1.12.2 \ - --hash=sha256:04c9c4f9c9f904f007cbfcd4640c406e53f19d04c220f5940d1537edb914d325 \ - --hash=sha256:0ed31b6a392928ad23645a470edc4f3814b952a416e41f8e5daac42d7bfbabc6 \ - --hash=sha256:134e895578258a693ba1d55b166c2ba96e9f51067e106b8a74d422432653d45b \ - --hash=sha256:39665d622dcc950ab17b9569e8cab84a4d64eea6a18b540a8b49e00c0f7dda02 \ - --hash=sha256:4bdc486b9ab80d8b50143ecc9a1924b890866fe95be150dd9a59fa22a6b37238 \ - --hash=sha256:6af778e7ee048612e55a1255488db7678741bea2ba881e66a19712f59f2534cb \ - --hash=sha256:72aad9efe09a6392de9930f2bea80bfcc36fd98e18caa621f512571179c02d41 \ - --hash=sha256:9763d277e143409cf0ce309eb1a493fc4e1e75777364d67ccac39a161b51b5b0 \ - --hash=sha256:a882cc80c241b1e2c27bd1acd713b09e9ac9266a3159cc1e34e8c7b77f049bba \ - --hash=sha256:c06d218931985035d7ab4d0211ba96027e1bc7e4b01a87c8c4e30a57790403ec \ - --hash=sha256:ca3b20bcc3aff115c9eaf97340e78bff58829ea1efa16764940dd0d858dcf6af \ - --hash=sha256:d1617989b4a5dc543fea6d23c28b2f07fadb2c726ff00fe959538ee71a301384 \ - --hash=sha256:d6253079f53dbb692395a13abddc0f2d3d96af32f8c0b32e2912849713c55794 \ - --hash=sha256:f1c2e4ee43bf286b052091a3b2356a157978985837c7aed42354deb2947a4006 +maturin==1.12.6 \ + --hash=sha256:06fc8d089f98623ce924c669b70911dfed30f9a29956c362945f727f9abc546b \ + --hash=sha256:2cb41139295eed6411d3cdafc7430738094c2721f34b7eeb44f33cac516115dc \ + --hash=sha256:351f3af1488a7cbdcff3b6d8482c17164273ac981378a13a4a9937a49aec7d71 \ + --hash=sha256:3f32e0a3720b81423c9d35c14e728cb1f954678124749776dc72d533ea1115e8 \ + --hash=sha256:6892b4176992fcc143f9d1c1c874a816e9a041248eef46433db87b0f0aff4278 \ + --hash=sha256:6dbddfe4dc7ddee60bbac854870bd7cfec660acb54d015d24597d59a1c828f61 \ + --hash=sha256:75133e56274d43b9227fd49dca9a86e32f1fd56a7b55544910c4ce978c2bb5aa \ + --hash=sha256:8fdb0f63e77ee3df0f027a120e9af78dbc31edf0eb0f263d55783c250c33b728 \ + --hash=sha256:977290159d252db946054a0555263c59b3d0c7957135c69e690f4b1558ee9983 \ + --hash=sha256:bae91976cdc8148038e13c881e1e844e5c63e58e026e8b9945aa2d19b3b4ae89 \ + --hash=sha256:c0c742beeeef7fb93b6a81bd53e75507887e396fd1003c45117658d063812dad \ + --hash=sha256:d37be3a811a7f2ee28a0fa0964187efa50e90f21da0c6135c27787fa0b6a89db \ + --hash=sha256:e90dc12bc6a38e9495692a36c9e231c4d7e0c9bfde60719468ab7d8673db3c45 \ + --hash=sha256:fa84b7493a2e80759cacc2e668fa5b444d55b9994e90707c42904f55d6322c1e # via # cryptography # pydantic-core @@ -621,6 +621,7 @@ packaging==26.0 \ # scikit-build-core # setuptools-git-versioning # setuptools-scm + # vcs-versioning # wheel pathspec==1.0.4 \ --hash=sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645 \ @@ -629,38 +630,37 @@ pathspec==1.0.4 \ # hatchling # mypy # scikit-build-core -pdm-backend==2.4.7 \ - --hash=sha256:1599e3afa6f229b30cb4d3bd9caeca42229c42eb5730abd13e0b5256ec93c9f7 \ - --hash=sha256:a509d083850378ce919d41e7a2faddfc57a1764d376913c66731125d6b14110f +pdm-backend==2.4.8 \ + --hash=sha256:502a395859587b4f47ba36aded330aeda410da8d33751a56cb97c8c679276f8f \ + --hash=sha256:d8ef85d2c4306ee67195412d701fae9983e84ec6574598e26798ae26b7b3c7e0 # via # annotated-doc # fastapi # typer -pkgconfig==1.5.5 \ - --hash=sha256:d20023bbeb42ee6d428a0fac6e0904631f545985a10cdd71a20aa58bc47a4209 \ - --hash=sha256:deb4163ef11f75b520d822d9505c1f462761b4309b1bb713d08689759ea8b899 +pkgconfig==1.6.0 \ + --hash=sha256:4a5a6631ce937fafac457104a40d558785a658bbdca5c49b6295bc3fd651907f \ + --hash=sha256:98e71754855e9563838d952a160eb577edabb57782e49853edb5381927e6bea1 # via aiohttp pluggy==1.6.0 \ --hash=sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3 \ --hash=sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746 # via hatchling -poetry-core==2.3.1 \ - --hash=sha256:96f791d5d7d4e040f3983d76779425cf9532690e2756a24fd5ca0f86af19ef82 \ - --hash=sha256:db1cf63b782570deb38bfba61e2304a553eef0740dc17959a50cc0f5115ee634 +poetry-core==2.3.2 \ + --hash=sha256:20cb71be27b774628da9f384effd9183dfceb53bcef84063248a8672aa47031f \ + --hash=sha256:23df641b64f87fbb4ce1873c1915a4d4bb1b7d808c596e4307edc073e68d7234 # via # aiohappyeyeballs # dunamai # pkgconfig # rich - # rsa # tomlkit -pybind11-global==3.0.1 \ - --hash=sha256:0e8d5a68d084c50bf145ce5efdbdd00704dbe6315035d0b7a255708ddeb9faca \ - --hash=sha256:eb6ef4e8f5a60f4c0b6a9396cb7806f78d42f8d081e42a93c0bb62288f6cf403 +pybind11-global==3.0.3 \ + --hash=sha256:141adb150fdb84f6eba3e27241da886f4582574a3d1c30568bf33c1ed3ec8b82 \ + --hash=sha256:7a75ee81e903ea15bdf05db1342c37400751a72316b6620c800b66d70be45632 # via pybind11 -pybind11==3.0.1 \ - --hash=sha256:9c0f40056a016da59bab516efb523089139fcc6f2ba7e4930854c61efb932051 \ - --hash=sha256:aa8f0aa6e0a94d3b64adfc38f560f33f15e589be2175e103c0a33c6bce55ee89 +pybind11==3.0.3 \ + --hash=sha256:00471cdb816882c484708bc5dde80815c8c11cea540ab2cc6410f5ddea434755 \ + --hash=sha256:fb5f8e4a64946b4dcc0451c83a8c384f803bc0a62dd1ba02f199e97dbc9aad4c # via duckdb pycparser==3.0 \ --hash=sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29 \ @@ -670,9 +670,9 @@ pyproject-metadata==0.11.0 \ --hash=sha256:85bbecca8694e2c00f63b492c96921d6c228454057c88e7c352b2077fcaa4096 \ --hash=sha256:c72fa49418bb7c5a10f25e050c418009898d1c051721d19f98a6fb6da59a66cf # via meson-python -scikit-build-core==0.11.6 \ - --hash=sha256:5982ccd839735be99cfd3b92a8847c6c196692f476c215da84b79d2ad12f9f1b \ - --hash=sha256:ce6d8fe64e6b4c759ea0fb95d2f8a68f60d2df31c2989838633b8ec930736360 +scikit-build-core==0.12.2 \ + --hash=sha256:562e0bbc9de1a354c87825ccf732080268d6582a0200f648e8c4a2dcb1e3736d \ + --hash=sha256:6ea4730da400f9a998ec3287bd3ebc1d751fe45ad0a93451bead8618adbc02b1 # via # duckdb # patchelf @@ -686,17 +686,13 @@ setuptools-git-versioning==3.0.1 \ --hash=sha256:737c4d17e848edd46e28764a19dc424d8537fcb2257022e5f4f5c0c8e9b64c80 \ --hash=sha256:c8a599bacf163b5d215552b5701faf5480ffc4d65426a5711a010b802e1590eb # via toolz -setuptools-rust==1.12.0 \ - --hash=sha256:7e7db90547f224a835b45f5ad90c983340828a345554a9a660bdb2de8605dcdd \ - --hash=sha256:d94a93f0c97751c17014565f07bdc324bee45d396cd1bba83d8e7af92b945f0c +setuptools-rust==1.12.1 \ + --hash=sha256:85ae70989d96c9cfeb5ef79cf3bac2d5200bc5564f720a06edceedbdf6664640 \ + --hash=sha256:b7ebd6a182e7aefa97a072e880530c9b0ec8fcca8617e0bb8ff299c1a064f693 # via maturin -setuptools-scm==7.1.0 \ - --hash=sha256:6c508345a771aad7d56ebff0e70628bf2b0ec7573762be9960214730de278f27 \ - --hash=sha256:73988b6d848709e2af142aa48c986ea29592bbcfca5375678064708205253d8e - # via python-dateutil -setuptools-scm==9.2.2 \ - --hash=sha256:1c674ab4665686a0887d7e24c03ab25f24201c213e82ea689d2f3e169ef7ef57 \ - --hash=sha256:30e8f84d2ab1ba7cb0e653429b179395d0c33775d54807fc5f1dd6671801aef7 +setuptools-scm==10.0.5 \ + --hash=sha256:bbba8fe754516cdefd017f4456721775e6ef9662bd7887fb52ae26813d4838c3 \ + --hash=sha256:f611037d8aae618221503b8fa89319f073438252ae3420e01c9ceec249131a0a # via # anyio # dask @@ -716,69 +712,77 @@ setuptools-scm==9.2.2 \ # tqdm # typeguard # ujson - # urllib3 # zipp -smmap==5.0.2 \ - --hash=sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5 \ - --hash=sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e +setuptools-scm==7.1.0 \ + --hash=sha256:6c508345a771aad7d56ebff0e70628bf2b0ec7573762be9960214730de278f27 \ + --hash=sha256:73988b6d848709e2af142aa48c986ea29592bbcfca5375678064708205253d8e + # via python-dateutil +setuptools-scm==9.2.2 \ + --hash=sha256:1c674ab4665686a0887d7e24c03ab25f24201c213e82ea689d2f3e169ef7ef57 \ + --hash=sha256:30e8f84d2ab1ba7cb0e653429b179395d0c33775d54807fc5f1dd6671801aef7 + # via + # hatch-vcs + # urllib3 +smmap==5.0.3 \ + --hash=sha256:4d9debb8b99007ae47165abc08670bd74cb74b5227dda7f643eccc4e9eb5642c \ + --hash=sha256:c106e05d5a61449cf6ba9a1e650227ecfb141590d2a98412103ff35d89fc7b2f # via gitdb tomli==2.0.2 \ --hash=sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38 \ --hash=sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed # via setuptools-scm -tomli==2.4.0 \ - --hash=sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729 \ - --hash=sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b \ - --hash=sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d \ - --hash=sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df \ - --hash=sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576 \ - --hash=sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d \ - --hash=sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1 \ - --hash=sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a \ - --hash=sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e \ - --hash=sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc \ - --hash=sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702 \ - --hash=sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6 \ - --hash=sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd \ - --hash=sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4 \ - --hash=sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776 \ - --hash=sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a \ - --hash=sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66 \ - --hash=sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87 \ - --hash=sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2 \ - --hash=sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f \ - --hash=sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475 \ - --hash=sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f \ - --hash=sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95 \ - --hash=sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9 \ - --hash=sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3 \ - --hash=sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9 \ - --hash=sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76 \ - --hash=sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da \ - --hash=sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8 \ - --hash=sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51 \ - --hash=sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86 \ - --hash=sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8 \ - --hash=sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0 \ - --hash=sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b \ - --hash=sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1 \ - --hash=sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e \ - --hash=sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d \ - --hash=sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c \ - --hash=sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867 \ - --hash=sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a \ - --hash=sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c \ - --hash=sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0 \ - --hash=sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4 \ - --hash=sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614 \ - --hash=sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132 \ - --hash=sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa \ - --hash=sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087 +tomli==2.4.1 \ + --hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \ + --hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \ + --hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \ + --hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \ + --hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \ + --hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \ + --hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \ + --hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \ + --hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \ + --hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \ + --hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \ + --hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \ + --hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \ + --hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \ + --hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \ + --hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \ + --hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \ + --hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \ + --hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \ + --hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \ + --hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \ + --hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \ + --hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \ + --hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \ + --hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \ + --hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \ + --hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \ + --hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \ + --hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \ + --hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \ + --hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \ + --hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \ + --hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \ + --hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \ + --hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \ + --hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \ + --hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \ + --hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \ + --hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \ + --hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \ + --hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \ + --hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \ + --hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \ + --hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \ + --hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \ + --hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \ + --hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049 # via # fastapi-mcp # flit-scm # frozenlist - # hatch-fancy-pypi-readme # hatchling # maturin # meson-python @@ -788,6 +792,7 @@ tomli==2.4.0 \ # scikit-build-core # setuptools-git-versioning # setuptools-scm + # vcs-versioning # versioneer # yarl tomlkit==0.14.0 \ @@ -802,21 +807,26 @@ types-psutil==7.0.0.20250218 \ --hash=sha256:1447a30c282aafefcf8941ece854e1100eee7b0296a9d9be9977292f0269b121 \ --hash=sha256:1e642cdafe837b240295b23b1cbd4691d80b08a07d29932143cbbae30eb0db9c # via mypy -types-setuptools==82.0.0.20260210 \ - --hash=sha256:5124a7daf67f195c6054e0f00f1d97c69caad12fdcf9113eba33eff0bce8cd2b \ - --hash=sha256:d9719fbbeb185254480ade1f25327c4654f8c00efda3fec36823379cebcdee58 +types-setuptools==82.0.0.20260402 \ + --hash=sha256:4b9a9f6c3c4c65107a3956ad6a6acbccec38e398ff6d5f78d5df7f103dadb8d6 \ + --hash=sha256:63d2b10ba7958396ad79bbc24d2f6311484e452daad4637ffd40407983a27069 # via mypy typing-extensions==4.15.0 \ --hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \ --hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548 # via - # exceptiongroup # mypy + # scikit-build-core # setuptools-scm -uv-dynamic-versioning==0.13.0 \ - --hash=sha256:3220cbf10987d862d78e9931957782a274fa438d33efb1fa26b8155353749e06 \ - --hash=sha256:86d37b89fa2b6836a515301f74ea2d56a1bc59a46a74d66a24c869d1fc8f7585 + # vcs-versioning +uv-dynamic-versioning==0.14.0 \ + --hash=sha256:574fbc07e87ace45c01d55967ad3b864871257b98ff5b8ac87c261227ac8db5b \ + --hash=sha256:e087c346a786e98d41292ac2315180fb700cedfb30565fc973d64ce11a112387 # via mcp +vcs-versioning==1.1.1 \ + --hash=sha256:b541e2ba79fc6aaa3850f8a7f88af43d97c1c80649c01142ee4146eddbc599e4 \ + --hash=sha256:fabd75a3cab7dd8ac02fe24a3a9ba936bf258667b5a62ed468c9a1da0f5775bc + # via setuptools-scm versioneer==0.29 \ --hash=sha256:0f1a137bb5d6811e96a79bb0486798aeae9b9c6efc24b389659cebb0ee396cb9 \ --hash=sha256:5ab283b9857211d61b53318b7c792cf68e798e765ee17c27ade9f6c924235731 @@ -842,7 +852,6 @@ wheel==0.46.3 \ # setuptools-git-versioning # shellingham # snowflake-connector-python - # tabulate # tzdata # uvloop @@ -901,6 +910,7 @@ setuptools==80.10.2 \ # pymysql # python-dotenv # pyyaml + # requests # setuptools-git-versioning # setuptools-rust # setuptools-scm @@ -916,9 +926,10 @@ setuptools==80.10.2 \ # trove-classifiers # typeguard # types-pymysql - # types-setuptools # tzdata + # ujson # uvloop + # vcs-versioning # versioneer # websockets # wrapt @@ -928,10 +939,9 @@ setuptools==80.9.0 \ --hash=sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922 \ --hash=sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c # via httptools -setuptools==82.0.0 \ - --hash=sha256:22e0a2d69474c6ae4feb01951cb69d515ed23728cf96d05513d36e42b62b37cb \ - --hash=sha256:70b18734b607bd1da571d097d236cfcfacaf01de45717d59e6e04b96877532e0 +setuptools==82.0.1 \ + --hash=sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9 \ + --hash=sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb # via # python-dateutil - # setuptools-scm - # ujson + # types-setuptools diff --git a/sdk/python/requirements/py3.10-minimal-sdist-requirements.txt b/sdk/python/requirements/py3.10-minimal-sdist-requirements.txt index da8f2ae618e..8b25c5722d1 100644 --- a/sdk/python/requirements/py3.10-minimal-sdist-requirements.txt +++ b/sdk/python/requirements/py3.10-minimal-sdist-requirements.txt @@ -8,127 +8,127 @@ aiohappyeyeballs==2.6.1 \ --hash=sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558 \ --hash=sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8 # via aiohttp -aiohttp==3.13.3 \ - --hash=sha256:01ad2529d4b5035578f5081606a465f3b814c542882804e2e8cda61adf5c71bf \ - --hash=sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c \ - --hash=sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c \ - --hash=sha256:084911a532763e9d3dd95adf78a78f4096cd5f58cdc18e6fdbc1b58417a45423 \ - --hash=sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f \ - --hash=sha256:0db318f7a6f065d84cb1e02662c526294450b314a02bd9e2a8e67f0d8564ce40 \ - --hash=sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2 \ - --hash=sha256:1449ceddcdbcf2e0446957863af03ebaaa03f94c090f945411b61269e2cb5daf \ - --hash=sha256:147e422fd1223005c22b4fe080f5d93ced44460f5f9c105406b753612b587821 \ - --hash=sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64 \ - --hash=sha256:215a685b6fbbfcf71dfe96e3eba7a6f58f10da1dfdf4889c7dd856abe430dca7 \ - --hash=sha256:2712039939ec963c237286113c68dbad80a82a4281543f3abf766d9d73228998 \ - --hash=sha256:27234ef6d85c914f9efeb77ff616dbf4ad2380be0cda40b4db086ffc7ddd1b7d \ - --hash=sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea \ - --hash=sha256:2b8d8ddba8f95ba17582226f80e2de99c7a7948e66490ef8d947e272a93e9463 \ - --hash=sha256:2ba0eea45eb5cc3172dbfc497c066f19c41bac70963ea1a67d51fc92e4cf9a80 \ - --hash=sha256:2be0e9ccf23e8a94f6f0650ce06042cefc6ac703d0d7ab6c7a917289f2539ad4 \ - --hash=sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767 \ - --hash=sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43 \ - --hash=sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592 \ - --hash=sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a \ - --hash=sha256:31a83ea4aead760dfcb6962efb1d861db48c34379f2ff72db9ddddd4cda9ea2e \ - --hash=sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687 \ - --hash=sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8 \ - --hash=sha256:37239e9f9a7ea9ac5bf6b92b0260b01f8a22281996da609206a84df860bc1261 \ - --hash=sha256:37da61e244d1749798c151421602884db5270faf479cf0ef03af0ff68954c9dd \ - --hash=sha256:3b61b7169ababd7802f9568ed96142616a9118dd2be0d1866e920e77ec8fa92a \ - --hash=sha256:3d9908a48eb7416dc1f4524e69f1d32e5d90e3981e4e37eb0aa1cd18f9cfa2a4 \ - --hash=sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587 \ - --hash=sha256:4021b51936308aeea0367b8f006dc999ca02bc118a0cc78c303f50a2ff6afb91 \ - --hash=sha256:40c5e40ecc29ba010656c18052b877a1c28f84344825efa106705e835c28530f \ - --hash=sha256:425c126c0dc43861e22cb1c14ba4c8e45d09516d0a3ae0a3f7494b79f5f233a3 \ - --hash=sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344 \ - --hash=sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6 \ - --hash=sha256:49a03727c1bba9a97d3e93c9f93ca03a57300f484b6e935463099841261195d3 \ - --hash=sha256:4ae5b5a0e1926e504c81c5b84353e7a5516d8778fbbff00429fe7b05bb25cbce \ - --hash=sha256:4e239d501f73d6db1522599e14b9b321a7e3b1de66ce33d53a765d975e9f4808 \ - --hash=sha256:56339a36b9f1fc708260c76c87e593e2afb30d26de9ae1eb445b5e051b98a7a1 \ - --hash=sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29 \ - --hash=sha256:5b179331a481cb5529fca8b432d8d3c7001cb217513c94cd72d668d1248688a3 \ - --hash=sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b \ - --hash=sha256:5d2d94f1f5fcbe40838ac51a6ab5704a6f9ea42e72ceda48de5e6b898521da51 \ - --hash=sha256:5dff64413671b0d3e7d5918ea490bdccb97a4ad29b3f311ed423200b2203e01c \ - --hash=sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926 \ - --hash=sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64 \ - --hash=sha256:642f752c3eb117b105acbd87e2c143de710987e09860d674e068c4c2c441034f \ - --hash=sha256:65d2ccb7eabee90ce0503c17716fc77226be026dcc3e65cce859a30db715025b \ - --hash=sha256:693781c45a4033d31d4187d2436f5ac701e7bbfe5df40d917736108c1cc7436e \ - --hash=sha256:694976222c711d1d00ba131904beb60534f93966562f64440d0c9d41b8cdb440 \ - --hash=sha256:697753042d57f4bf7122cab985bf15d0cef23c770864580f5af4f52023a56bd6 \ - --hash=sha256:69c56fbc1993fa17043e24a546959c0178fe2b5782405ad4559e6c13975c15e3 \ - --hash=sha256:6de499a1a44e7de70735d0b39f67c8f25eb3d91eb3103be99ca0fa882cdd987d \ - --hash=sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415 \ - --hash=sha256:75ca857eba4e20ce9f546cd59c7007b33906a4cd48f2ff6ccf1ccfc3b646f279 \ - --hash=sha256:7a4a94eb787e606d0a09404b9c38c113d3b099d508021faa615d70a0131907ce \ - --hash=sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603 \ - --hash=sha256:7bfdc049127717581866fa4708791220970ce291c23e28ccf3922c700740fdc0 \ - --hash=sha256:7e63f210bc1b57ef699035f2b4b6d9ce096b5914414a49b0997c839b2bd2223c \ - --hash=sha256:7f9120f7093c2a32d9647abcaf21e6ad275b4fbec5b55969f978b1a97c7c86bf \ - --hash=sha256:8057c98e0c8472d8846b9c79f56766bcc57e3e8ac7bfd510482332366c56c591 \ - --hash=sha256:80dd4c21b0f6237676449c6baaa1039abae86b91636b6c91a7f8e61c87f89540 \ - --hash=sha256:81e97251d9298386c2b7dbeb490d3d1badbdc69107fb8c9299dd04eb39bddc0e \ - --hash=sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26 \ - --hash=sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a \ - --hash=sha256:859bd3f2156e81dd01432f5849fc73e2243d4a487c4fd26609b1299534ee1845 \ - --hash=sha256:87797e645d9d8e222e04160ee32aa06bc5c163e8499f24db719e7852ec23093a \ - --hash=sha256:87b9aab6d6ed88235aa2970294f496ff1a1f9adcd724d800e9b952395a80ffd9 \ - --hash=sha256:8a60e60746623925eab7d25823329941aee7242d559baa119ca2b253c88a7bd6 \ - --hash=sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba \ - --hash=sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df \ - --hash=sha256:947c26539750deeaee933b000fb6517cc770bbd064bad6033f1cff4803881e43 \ - --hash=sha256:96d604498a7c782cb15a51c406acaea70d8c027ee6b90c569baa6e7b93073679 \ - --hash=sha256:988a8c5e317544fdf0d39871559e67b6341065b87fceac641108c2096d5506b7 \ - --hash=sha256:9a9dc347e5a3dc7dfdbc1f82da0ef29e388ddb2ed281bfce9dd8248a313e62b7 \ - --hash=sha256:9ae8dd55c8e6c4257eae3a20fd2c8f41edaea5992ed67156642493b8daf3cecc \ - --hash=sha256:9af5e68ee47d6534d36791bbe9b646d2a7c7deb6fc24d7943628edfbb3581f29 \ - --hash=sha256:9b174f267b5cfb9a7dba9ee6859cecd234e9a681841eb85068059bc867fb8f02 \ - --hash=sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984 \ - --hash=sha256:9d4c940f02f49483b18b079d1c27ab948721852b281f8b015c058100e9421dd1 \ - --hash=sha256:9ebf57d09e131f5323464bd347135a88622d1c0976e88ce15b670e7ad57e4bd6 \ - --hash=sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632 \ - --hash=sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56 \ - --hash=sha256:a2212ad43c0833a873d0fb3c63fa1bacedd4cf6af2fee62bf4b739ceec3ab239 \ - --hash=sha256:a45530014d7a1e09f4a55f4f43097ba0fd155089372e105e4bff4ca76cb1b168 \ - --hash=sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88 \ - --hash=sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc \ - --hash=sha256:af71fff7bac6bb7508956696dce8f6eec2bbb045eceb40343944b1ae62b5ef11 \ - --hash=sha256:b04be762396457bef43f3597c991e192ee7da460a4953d7e647ee4b1c28e7046 \ - --hash=sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0 \ - --hash=sha256:b1a6102b4d3ebc07dad44fbf07b45bb600300f15b552ddf1851b5390202ea2e3 \ - --hash=sha256:b46020d11d23fe16551466c77823df9cc2f2c1e63cc965daf67fa5eec6ca1877 \ - --hash=sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1 \ - --hash=sha256:b903a4dfee7d347e2d87697d0713be59e0b87925be030c9178c5faa58ea58d5c \ - --hash=sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25 \ - --hash=sha256:b99281b0704c103d4e11e72a76f1b543d4946fea7dd10767e7e1b5f00d4e5704 \ - --hash=sha256:bae5c2ed2eae26cc382020edad80d01f36cb8e746da40b292e68fec40421dc6a \ - --hash=sha256:bb4f7475e359992b580559e008c598091c45b5088f28614e855e42d39c2f1033 \ - --hash=sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1 \ - --hash=sha256:bfc1cc2fe31a6026a8a88e4ecfb98d7f6b1fec150cfd708adbfd1d2f42257c29 \ - --hash=sha256:c014c7ea7fb775dd015b2d3137378b7be0249a448a1612268b5a90c2d81de04d \ - --hash=sha256:c048058117fd649334d81b4b526e94bde3ccaddb20463a815ced6ecbb7d11160 \ - --hash=sha256:c0e2d366af265797506f0283487223146af57815b388623f0357ef7eac9b209d \ - --hash=sha256:c19b90316ad3b24c69cd78d5c9b4f3aa4497643685901185b65166293d36a00f \ - --hash=sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f \ - --hash=sha256:c6b8568a3bb5819a0ad087f16d40e5a3fb6099f39ea1d5625a3edc1e923fc538 \ - --hash=sha256:d32764c6c9aafb7fb55366a224756387cd50bfa720f32b88e0e6fa45b27dcf29 \ - --hash=sha256:d5a372fd5afd301b3a89582817fdcdb6c34124787c70dbcc616f259013e7eef7 \ - --hash=sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72 \ - --hash=sha256:dca68018bf48c251ba17c72ed479f4dafe9dbd5a73707ad8d28a38d11f3d42af \ - --hash=sha256:de2c184bb1fe2cbd2cefba613e9db29a5ab559323f994b6737e370d3da0ac455 \ - --hash=sha256:e3531d63d3bdfa7e3ac5e9b27b2dd7ec9df3206a98e0b3445fa906f233264c57 \ - --hash=sha256:e50a2e1404f063427c9d027378472316201a2290959a295169bcf25992d04558 \ - --hash=sha256:e636b3c5f61da31a92bf0d91da83e58fdfa96f178ba682f11d24f31944cdd28c \ - --hash=sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808 \ - --hash=sha256:f33ed1a2bf1997a36661874b017f5c4b760f41266341af36febaf271d179f6d7 \ - --hash=sha256:f76c1e3fe7d7c8afad7ed193f89a292e1999608170dcc9751a7462a87dfd5bc0 \ - --hash=sha256:f9444f105664c4ce47a2a7171a2418bce5b7bae45fb610f4e2c36045d85911d3 \ - --hash=sha256:fc290605db2a917f6e81b0e1e0796469871f5af381ce15c604a3c5c7e51cb730 \ - --hash=sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa \ - --hash=sha256:fee0c6bc7db1de362252affec009707a17478a00ec69f797d23ca256e36d5940 +aiohttp==3.13.5 \ + --hash=sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5 \ + --hash=sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b \ + --hash=sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9 \ + --hash=sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b \ + --hash=sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8 \ + --hash=sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a \ + --hash=sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2 \ + --hash=sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1 \ + --hash=sha256:147b4f501d0292077f29d5268c16bb7c864a1f054d7001c4c1812c0421ea1ed0 \ + --hash=sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037 \ + --hash=sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416 \ + --hash=sha256:178c7b5e62b454c2bc790786e6058c3cc968613b4419251b478c153a4aec32b1 \ + --hash=sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9 \ + --hash=sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a \ + --hash=sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36 \ + --hash=sha256:206b7b3ef96e4ce211754f0cd003feb28b7d81f0ad26b8d077a5d5161436067f \ + --hash=sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b \ + --hash=sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174 \ + --hash=sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b \ + --hash=sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8 \ + --hash=sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e \ + --hash=sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6 \ + --hash=sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c \ + --hash=sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe \ + --hash=sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9 \ + --hash=sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc \ + --hash=sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800 \ + --hash=sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286 \ + --hash=sha256:347542f0ea3f95b2a955ee6656461fa1c776e401ac50ebce055a6c38454a0adf \ + --hash=sha256:39380e12bd1f2fdab4285b6e055ad48efbaed5c836433b142ed4f5b9be71036a \ + --hash=sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc \ + --hash=sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9 \ + --hash=sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665 \ + --hash=sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832 \ + --hash=sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297 \ + --hash=sha256:4e704c52438f66fdd89588346183d898bb42167cf88f8b7ff1c0f9fc957c348f \ + --hash=sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73 \ + --hash=sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b \ + --hash=sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9 \ + --hash=sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090 \ + --hash=sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49 \ + --hash=sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d \ + --hash=sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46 \ + --hash=sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83 \ + --hash=sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796 \ + --hash=sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be \ + --hash=sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d \ + --hash=sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf \ + --hash=sha256:6f497a6876aa4b1a102b04996ce4c1170c7040d83faa9387dd921c16e30d5c83 \ + --hash=sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25 \ + --hash=sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06 \ + --hash=sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3 \ + --hash=sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6 \ + --hash=sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb \ + --hash=sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88 \ + --hash=sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9 \ + --hash=sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be \ + --hash=sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14 \ + --hash=sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a \ + --hash=sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c \ + --hash=sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3 \ + --hash=sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f \ + --hash=sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d \ + --hash=sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670 \ + --hash=sha256:912d4b6af530ddb1338a66229dac3a25ff11d4448be3ec3d6340583995f56031 \ + --hash=sha256:9277145d36a01653863899c665243871434694bcc3431922c3b35c978061bdb8 \ + --hash=sha256:95d14ca7abefde230f7639ec136ade282655431fd5db03c343b19dda72dd1643 \ + --hash=sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d \ + --hash=sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8 \ + --hash=sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8 \ + --hash=sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1 \ + --hash=sha256:9efcc0f11d850cefcafdd9275b9576ad3bfb539bed96807663b32ad99c4d4b88 \ + --hash=sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb \ + --hash=sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61 \ + --hash=sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4 \ + --hash=sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7 \ + --hash=sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9 \ + --hash=sha256:a8a4d3427e8de1312ddf309cc482186466c79895b3a139fed3259fc01dfa9a5b \ + --hash=sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500 \ + --hash=sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6 \ + --hash=sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2 \ + --hash=sha256:af545c2cffdb0967a96b6249e6f5f7b0d92cdfd267f9d5238d5b9ca63e8edb10 \ + --hash=sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1 \ + --hash=sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3 \ + --hash=sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e \ + --hash=sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a \ + --hash=sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5 \ + --hash=sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95 \ + --hash=sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074 \ + --hash=sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5 \ + --hash=sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b \ + --hash=sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772 \ + --hash=sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a \ + --hash=sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274 \ + --hash=sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94 \ + --hash=sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13 \ + --hash=sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac \ + --hash=sha256:cb979826071c0986a5f08333a36104153478ce6018c58cba7f9caddaf63d5d67 \ + --hash=sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76 \ + --hash=sha256:d147004fede1b12f6013a6dbb2a26a986a671a03c6ea740ddc76500e5f1c399f \ + --hash=sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8 \ + --hash=sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7 \ + --hash=sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8 \ + --hash=sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3 \ + --hash=sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be \ + --hash=sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b \ + --hash=sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c \ + --hash=sha256:e999f0c88a458c836d5fb521814e92ed2172c649200336a6df514987c1488258 \ + --hash=sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c \ + --hash=sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6 \ + --hash=sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56 \ + --hash=sha256:ee5e86776273de1795947d17bddd6bb19e0365fd2af4289c0d2c5454b6b1d36b \ + --hash=sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d \ + --hash=sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a \ + --hash=sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162 \ + --hash=sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1 \ + --hash=sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6 \ + --hash=sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5 \ + --hash=sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540 \ + --hash=sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254 # via aiobotocore aioitertools==0.13.0 \ --hash=sha256:0be0292b856f08dfac90e31f4739432f4cb6d7520ab9eb73e143f4f2fa5259be \ @@ -152,9 +152,9 @@ annotated-types==0.7.0 \ --hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \ --hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89 # via pydantic -anyio==4.12.1 \ - --hash=sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703 \ - --hash=sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c +anyio==4.13.0 \ + --hash=sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708 \ + --hash=sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc # via # httpx # mcp @@ -175,9 +175,9 @@ atpublic==7.0.0 \ --hash=sha256:466ef10d0c8bbd14fd02a5fbd5a8b6af6a846373d91106d3a07c16d72d96b63e \ --hash=sha256:6702bd9e7245eb4e8220a3e222afcef7f87412154732271ee7deee4433b72b4b # via ibis-framework -attrs==25.4.0 \ - --hash=sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11 \ - --hash=sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373 +attrs==26.1.0 \ + --hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \ + --hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32 # via # aiohttp # jsonschema @@ -186,9 +186,9 @@ babel==2.18.0 \ --hash=sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d \ --hash=sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35 # via sphinx -bigtree==1.3.1 \ - --hash=sha256:a22a0ecd9b0abb283f4a1515370dbf1ec93adee70746767272e2c49d7af9f407 \ - --hash=sha256:c8b766b00188c532d3499bfd9e9666b357428db507fc701f088031a0d5c614d5 +bigtree==1.4.0 \ + --hash=sha256:d0d99550ae64ce4529f132602ab875c2ab472c96c942f5704f8c72a17450d3ea \ + --hash=sha256:e5ae2e948168da671d99601c9ed87ab3b48d9d4ea8a98f111e5748e98064c31c # via feast (pyproject.toml) boto3==1.38.27 \ --hash=sha256:94bd7fdd92d5701b362d4df100d21e28f8307a67ff56b6a8b0398119cf22f859 \ @@ -208,9 +208,9 @@ calver==2025.3.31 \ --hash=sha256:07511edf5e7fa75ae97445c8c5921240e0fe62937289a3ebe6963eddd3c691b6 \ --hash=sha256:255d1a70bba8f97dc1eee3af4240ed35980508da69257feef94c79e5c6545fc7 # via feast (pyproject.toml) -certifi==2026.1.4 \ - --hash=sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c \ - --hash=sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120 +certifi==2026.2.25 \ + --hash=sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa \ + --hash=sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7 # via # httpcore # httpx @@ -305,120 +305,136 @@ cffi==2.0.0 \ # via # feast (pyproject.toml) # cryptography -charset-normalizer==3.4.4 \ - --hash=sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad \ - --hash=sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93 \ - --hash=sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394 \ - --hash=sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89 \ - --hash=sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc \ - --hash=sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86 \ - --hash=sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63 \ - --hash=sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d \ - --hash=sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f \ - --hash=sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8 \ - --hash=sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0 \ - --hash=sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505 \ - --hash=sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161 \ - --hash=sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af \ - --hash=sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152 \ - --hash=sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318 \ - --hash=sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72 \ - --hash=sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4 \ - --hash=sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e \ - --hash=sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3 \ - --hash=sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576 \ - --hash=sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c \ - --hash=sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1 \ - --hash=sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8 \ - --hash=sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1 \ - --hash=sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2 \ - --hash=sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44 \ - --hash=sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26 \ - --hash=sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88 \ - --hash=sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016 \ - --hash=sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede \ - --hash=sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf \ - --hash=sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a \ - --hash=sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc \ - --hash=sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0 \ - --hash=sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84 \ - --hash=sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db \ - --hash=sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1 \ - --hash=sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7 \ - --hash=sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed \ - --hash=sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8 \ - --hash=sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133 \ - --hash=sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e \ - --hash=sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef \ - --hash=sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14 \ - --hash=sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2 \ - --hash=sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0 \ - --hash=sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d \ - --hash=sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828 \ - --hash=sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f \ - --hash=sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf \ - --hash=sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6 \ - --hash=sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328 \ - --hash=sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090 \ - --hash=sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa \ - --hash=sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381 \ - --hash=sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c \ - --hash=sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb \ - --hash=sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc \ - --hash=sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a \ - --hash=sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec \ - --hash=sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc \ - --hash=sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac \ - --hash=sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e \ - --hash=sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313 \ - --hash=sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569 \ - --hash=sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3 \ - --hash=sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d \ - --hash=sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525 \ - --hash=sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894 \ - --hash=sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3 \ - --hash=sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9 \ - --hash=sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a \ - --hash=sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9 \ - --hash=sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14 \ - --hash=sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25 \ - --hash=sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50 \ - --hash=sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf \ - --hash=sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1 \ - --hash=sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3 \ - --hash=sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac \ - --hash=sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e \ - --hash=sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815 \ - --hash=sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c \ - --hash=sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6 \ - --hash=sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6 \ - --hash=sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e \ - --hash=sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4 \ - --hash=sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84 \ - --hash=sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69 \ - --hash=sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15 \ - --hash=sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191 \ - --hash=sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0 \ - --hash=sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897 \ - --hash=sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd \ - --hash=sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2 \ - --hash=sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794 \ - --hash=sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d \ - --hash=sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074 \ - --hash=sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3 \ - --hash=sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224 \ - --hash=sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838 \ - --hash=sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a \ - --hash=sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d \ - --hash=sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d \ - --hash=sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f \ - --hash=sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8 \ - --hash=sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490 \ - --hash=sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966 \ - --hash=sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9 \ - --hash=sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3 \ - --hash=sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e \ - --hash=sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608 +charset-normalizer==3.4.7 \ + --hash=sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc \ + --hash=sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c \ + --hash=sha256:07d9e39b01743c3717745f4c530a6349eadbfa043c7577eef86c502c15df2c67 \ + --hash=sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4 \ + --hash=sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0 \ + --hash=sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c \ + --hash=sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5 \ + --hash=sha256:12a6fff75f6bc66711b73a2f0addfc4c8c15a20e805146a02d147a318962c444 \ + --hash=sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153 \ + --hash=sha256:14265bfe1f09498b9d8ec91e9ec9fa52775edf90fcbde092b25f4a33d444fea9 \ + --hash=sha256:16d971e29578a5e97d7117866d15889a4a07befe0e87e703ed63cd90cb348c01 \ + --hash=sha256:177a0ba5f0211d488e295aaf82707237e331c24788d8d76c96c5a41594723217 \ + --hash=sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b \ + --hash=sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c \ + --hash=sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a \ + --hash=sha256:1dc8b0ea451d6e69735094606991f32867807881400f808a106ee1d963c46a83 \ + --hash=sha256:1efde3cae86c8c273f1eb3b287be7d8499420cf2fe7585c41d370d3e790054a5 \ + --hash=sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7 \ + --hash=sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb \ + --hash=sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c \ + --hash=sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1 \ + --hash=sha256:2cd4a60d0e2fb04537162c62bbbb4182f53541fe0ede35cdf270a1c1e723cc42 \ + --hash=sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab \ + --hash=sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df \ + --hash=sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e \ + --hash=sha256:320ade88cfb846b8cd6b4ddf5ee9e80ee0c1f52401f2456b84ae1ae6a1a5f207 \ + --hash=sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18 \ + --hash=sha256:36836d6ff945a00b88ba1e4572d721e60b5b8c98c155d465f56ad19d68f23734 \ + --hash=sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38 \ + --hash=sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110 \ + --hash=sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18 \ + --hash=sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44 \ + --hash=sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d \ + --hash=sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48 \ + --hash=sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e \ + --hash=sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5 \ + --hash=sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d \ + --hash=sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53 \ + --hash=sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790 \ + --hash=sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c \ + --hash=sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b \ + --hash=sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116 \ + --hash=sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d \ + --hash=sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10 \ + --hash=sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6 \ + --hash=sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2 \ + --hash=sha256:6370e8686f662e6a3941ee48ed4742317cafbe5707e36406e9df792cdb535776 \ + --hash=sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a \ + --hash=sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265 \ + --hash=sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008 \ + --hash=sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943 \ + --hash=sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374 \ + --hash=sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246 \ + --hash=sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e \ + --hash=sha256:6e0d51f618228538a3e8f46bd246f87a6cd030565e015803691603f55e12afb5 \ + --hash=sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616 \ + --hash=sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15 \ + --hash=sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41 \ + --hash=sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960 \ + --hash=sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752 \ + --hash=sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e \ + --hash=sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72 \ + --hash=sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7 \ + --hash=sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8 \ + --hash=sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b \ + --hash=sha256:813c0e0132266c08eb87469a642cb30aaff57c5f426255419572aaeceeaa7bf4 \ + --hash=sha256:82b271f5137d07749f7bf32f70b17ab6eaabedd297e75dce75081a24f76eb545 \ + --hash=sha256:84c018e49c3bf790f9c2771c45e9313a08c2c2a6342b162cd650258b57817706 \ + --hash=sha256:8751d2787c9131302398b11e6c8068053dcb55d5a8964e114b6e196cf16cb366 \ + --hash=sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb \ + --hash=sha256:87fad7d9ba98c86bcb41b2dc8dbb326619be2562af1f8ff50776a39e55721c5a \ + --hash=sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e \ + --hash=sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00 \ + --hash=sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f \ + --hash=sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a \ + --hash=sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1 \ + --hash=sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66 \ + --hash=sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356 \ + --hash=sha256:a6c5863edfbe888d9eff9c8b8087354e27618d9da76425c119293f11712a6319 \ + --hash=sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4 \ + --hash=sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad \ + --hash=sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d \ + --hash=sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5 \ + --hash=sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7 \ + --hash=sha256:aef65cd602a6d0e0ff6f9930fcb1c8fec60dd2cfcb6facaf4bdb0e5873042db0 \ + --hash=sha256:af21eb4409a119e365397b2adbaca4c9ccab56543a65d5dbd9f920d6ac29f686 \ + --hash=sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34 \ + --hash=sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49 \ + --hash=sha256:bb8cc7534f51d9a017b93e3e85b260924f909601c3df002bcdb58ddb4dc41a5c \ + --hash=sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1 \ + --hash=sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e \ + --hash=sha256:bd9b23791fe793e4968dba0c447e12f78e425c59fc0e3b97f6450f4781f3ee60 \ + --hash=sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0 \ + --hash=sha256:c0f081d69a6e58272819b70288d3221a6ee64b98df852631c80f293514d3b274 \ + --hash=sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d \ + --hash=sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0 \ + --hash=sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae \ + --hash=sha256:c593052c465475e64bbfe5dbd81680f64a67fdc752c56d7a0ae205dc8aeefe0f \ + --hash=sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d \ + --hash=sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe \ + --hash=sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3 \ + --hash=sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393 \ + --hash=sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1 \ + --hash=sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af \ + --hash=sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44 \ + --hash=sha256:d61f00a0869d77422d9b2aba989e2d24afa6ffd552af442e0e58de4f35ea6d00 \ + --hash=sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c \ + --hash=sha256:dca4bbc466a95ba9c0234ef56d7dd9509f63da22274589ebd4ed7f1f4d4c54e3 \ + --hash=sha256:dd915403e231e6b1809fe9b6d9fc55cf8fb5e02765ac625d9cd623342a7905d7 \ + --hash=sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd \ + --hash=sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e \ + --hash=sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b \ + --hash=sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8 \ + --hash=sha256:e5f4d355f0a2b1a31bc3edec6795b46324349c9cb25eed068049e4f472fb4259 \ + --hash=sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859 \ + --hash=sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46 \ + --hash=sha256:e80c8378d8f3d83cd3164da1ad2df9e37a666cdde7b1cb2298ed0b558064be30 \ + --hash=sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b \ + --hash=sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46 \ + --hash=sha256:ed065083d0898c9d5b4bbec7b026fd755ff7454e6e8b73a67f8c744b13986e24 \ + --hash=sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a \ + --hash=sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24 \ + --hash=sha256:f22dec1690b584cea26fade98b2435c132c1b5f68e39f5a0b7627cd7ae31f1dc \ + --hash=sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215 \ + --hash=sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063 \ + --hash=sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832 \ + --hash=sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6 \ + --hash=sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79 \ + --hash=sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464 # via # requests # snowflake-connector-python @@ -438,56 +454,56 @@ colorama==0.4.6 \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 # via feast (pyproject.toml) -cryptography==46.0.5 \ - --hash=sha256:02f547fce831f5096c9a567fd41bc12ca8f11df260959ecc7c3202555cc47a72 \ - --hash=sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235 \ - --hash=sha256:1abfdb89b41c3be0365328a410baa9df3ff8a9110fb75e7b52e66803ddabc9a9 \ - --hash=sha256:2ae6971afd6246710480e3f15824ed3029a60fc16991db250034efd0b9fb4356 \ - --hash=sha256:2b7a67c9cd56372f3249b39699f2ad479f6991e62ea15800973b956f4b73e257 \ - --hash=sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad \ - --hash=sha256:38946c54b16c885c72c4f59846be9743d699eee2b69b6988e0a00a01f46a61a4 \ - --hash=sha256:3b4995dc971c9fb83c25aa44cf45f02ba86f71ee600d81091c2f0cbae116b06c \ - --hash=sha256:3ce58ba46e1bc2aac4f7d9290223cead56743fa6ab94a5d53292ffaac6a91614 \ - --hash=sha256:3ee190460e2fbe447175cda91b88b84ae8322a104fc27766ad09428754a618ed \ - --hash=sha256:4108d4c09fbbf2789d0c926eb4152ae1760d5a2d97612b92d508d96c861e4d31 \ - --hash=sha256:420d0e909050490d04359e7fdb5ed7e667ca5c3c402b809ae2563d7e66a92229 \ - --hash=sha256:47fb8a66058b80e509c47118ef8a75d14c455e81ac369050f20ba0d23e77fee0 \ - --hash=sha256:4c3341037c136030cb46e4b1e17b7418ea4cbd9dd207e4a6f3b2b24e0d4ac731 \ - --hash=sha256:4d7e3d356b8cd4ea5aff04f129d5f66ebdc7b6f8eae802b93739ed520c47c79b \ - --hash=sha256:4d8ae8659ab18c65ced284993c2265910f6c9e650189d4e3f68445ef82a810e4 \ - --hash=sha256:4e817a8920bfbcff8940ecfd60f23d01836408242b30f1a708d93198393a80b4 \ - --hash=sha256:50bfb6925eff619c9c023b967d5b77a54e04256c4281b0e21336a130cd7fc263 \ - --hash=sha256:556e106ee01aa13484ce9b0239bca667be5004efb0aabbed28d353df86445595 \ - --hash=sha256:582f5fcd2afa31622f317f80426a027f30dc792e9c80ffee87b993200ea115f1 \ - --hash=sha256:5be7bf2fb40769e05739dd0046e7b26f9d4670badc7b032d6ce4db64dddc0678 \ - --hash=sha256:60ee7e19e95104d4c03871d7d7dfb3d22ef8a9b9c6778c94e1c8fcc8365afd48 \ - --hash=sha256:61aa400dce22cb001a98014f647dc21cda08f7915ceb95df0c9eaf84b4b6af76 \ - --hash=sha256:68f68d13f2e1cb95163fa3b4db4bf9a159a418f5f6e7242564fc75fcae667fd0 \ - --hash=sha256:7d1f30a86d2757199cb2d56e48cce14deddf1f9c95f1ef1b64ee91ea43fe2e18 \ - --hash=sha256:7d731d4b107030987fd61a7f8ab512b25b53cef8f233a97379ede116f30eb67d \ - --hash=sha256:803812e111e75d1aa73690d2facc295eaefd4439be1023fefc4995eaea2af90d \ - --hash=sha256:80a8d7bfdf38f87ca30a5391c0c9ce4ed2926918e017c29ddf643d0ed2778ea1 \ - --hash=sha256:8293f3dea7fc929ef7240796ba231413afa7b68ce38fd21da2995549f5961981 \ - --hash=sha256:8456928655f856c6e1533ff59d5be76578a7157224dbd9ce6872f25055ab9ab7 \ - --hash=sha256:890bcb4abd5a2d3f852196437129eb3667d62630333aacc13dfd470fad3aaa82 \ - --hash=sha256:94a76daa32eb78d61339aff7952ea819b1734b46f73646a07decb40e5b3448e2 \ - --hash=sha256:9f16fbdf4da055efb21c22d81b89f155f02ba420558db21288b3d0035bafd5f4 \ - --hash=sha256:a3d1fae9863299076f05cb8a778c467578262fae09f9dc0ee9b12eb4268ce663 \ - --hash=sha256:a3d507bb6a513ca96ba84443226af944b0f7f47dcc9a399d110cd6146481d24c \ - --hash=sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d \ - --hash=sha256:ba2a27ff02f48193fc4daeadf8ad2590516fa3d0adeeb34336b96f7fa64c1e3a \ - --hash=sha256:bc84e875994c3b445871ea7181d424588171efec3e185dced958dad9e001950a \ - --hash=sha256:bfd56bb4b37ed4f330b82402f6f435845a5f5648edf1ad497da51a8452d5d62d \ - --hash=sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b \ - --hash=sha256:c3bcce8521d785d510b2aad26ae2c966092b7daa8f45dd8f44734a104dc0bc1a \ - --hash=sha256:c4143987a42a2397f2fc3b4d7e3a7d313fbe684f67ff443999e803dd75a76826 \ - --hash=sha256:c69fd885df7d089548a42d5ec05be26050ebcd2283d89b3d30676eb32ff87dee \ - --hash=sha256:ced80795227d70549a411a4ab66e8ce307899fad2220ce5ab2f296e687eacde9 \ - --hash=sha256:d66e421495fdb797610a08f43b05269e0a5ea7f5e652a89bfd5a7d3c1dee3648 \ - --hash=sha256:d861ee9e76ace6cf36a6a89b959ec08e7bc2493ee39d07ffe5acb23ef46d27da \ - --hash=sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2 \ - --hash=sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2 \ - --hash=sha256:fe346b143ff9685e40192a4960938545c699054ba11d4f9029f94751e3f71d87 +cryptography==46.0.6 \ + --hash=sha256:02fad249cb0e090b574e30b276a3da6a149e04ee2f049725b1f69e7b8351ec70 \ + --hash=sha256:063b67749f338ca9c5a0b7fe438a52c25f9526b851e24e6c9310e7195aad3b4d \ + --hash=sha256:12cae594e9473bca1a7aceb90536060643128bb274fcea0fc459ab90f7d1ae7a \ + --hash=sha256:12f0fa16cc247b13c43d56d7b35287ff1569b5b1f4c5e87e92cc4fcc00cd10c0 \ + --hash=sha256:22259338084d6ae497a19bae5d4c66b7ca1387d3264d1c2c0e72d9e9b6a77b97 \ + --hash=sha256:26031f1e5ca62fcb9d1fcb34b2b60b390d1aacaa15dc8b895a9ed00968b97b30 \ + --hash=sha256:27550628a518c5c6c903d84f637fbecf287f6cb9ced3804838a1295dc1fd0759 \ + --hash=sha256:2b417edbe8877cda9022dde3a008e2deb50be9c407eef034aeeb3a8b11d9db3c \ + --hash=sha256:2ea0f37e9a9cf0df2952893ad145fd9627d326a59daec9b0802480fa3bcd2ead \ + --hash=sha256:2ef9e69886cbb137c2aef9772c2e7138dc581fad4fcbcf13cc181eb5a3ab6275 \ + --hash=sha256:341359d6c9e68834e204ceaf25936dffeafea3829ab80e9503860dcc4f4dac58 \ + --hash=sha256:380343e0653b1c9d7e1f55b52aaa2dbb2fdf2730088d48c43ca1c7c0abb7cc2f \ + --hash=sha256:3c21d92ed15e9cfc6eb64c1f5a0326db22ca9c2566ca46d845119b45b4400361 \ + --hash=sha256:3dfa6567f2e9e4c5dceb8ccb5a708158a2a871052fa75c8b78cb0977063f1507 \ + --hash=sha256:456b3215172aeefb9284550b162801d62f5f264a081049a3e94307fe20792cfa \ + --hash=sha256:4668298aef7cddeaf5c6ecc244c2302a2b8e40f384255505c22875eebb47888b \ + --hash=sha256:50575a76e2951fe7dbd1f56d181f8c5ceeeb075e9ff88e7ad997d2f42af06e7b \ + --hash=sha256:639301950939d844a9e1c4464d7e07f902fe9a7f6b215bb0d4f28584729935d8 \ + --hash=sha256:64235194bad039a10bb6d2d930ab3323baaec67e2ce36215fd0952fad0930ca8 \ + --hash=sha256:6617f67b1606dfd9fe4dbfa354a9508d4a6d37afe30306fe6c101b7ce3274b72 \ + --hash=sha256:67177e8a9f421aa2d3a170c3e56eca4e0128883cf52a071a7cbf53297f18b175 \ + --hash=sha256:6728c49e3b2c180ef26f8e9f0a883a2c585638db64cf265b49c9ba10652d430e \ + --hash=sha256:6739d56300662c468fddb0e5e291f9b4d084bead381667b9e654c7dd81705124 \ + --hash=sha256:69cf0056d6947edc6e6760e5f17afe4bea06b56a9ac8a06de9d2bd6b532d4f3a \ + --hash=sha256:760997a4b950ff00d418398ad73fbc91aa2894b5c1db7ccb45b4f68b42a63b3c \ + --hash=sha256:79e865c642cfc5c0b3eb12af83c35c5aeff4fa5c672dc28c43721c2c9fdd2f0f \ + --hash=sha256:7e6142674f2a9291463e5e150090b95a8519b2fb6e6aaec8917dd8d094ce750d \ + --hash=sha256:7f417f034f91dcec1cb6c5c35b07cdbb2ef262557f701b4ecd803ee8cefed4f4 \ + --hash=sha256:7f6690b6c55e9c5332c0b59b9c8a3fb232ebf059094c17f9019a51e9827df91c \ + --hash=sha256:8927ccfbe967c7df312ade694f987e7e9e22b2425976ddbf28271d7e58845290 \ + --hash=sha256:8ce35b77aaf02f3b59c90b2c8a05c73bac12cea5b4e8f3fbece1f5fddea5f0ca \ + --hash=sha256:8e7304c4f4e9490e11efe56af6713983460ee0780f16c63f219984dab3af9d2d \ + --hash=sha256:90e5f0a7b3be5f40c3a0a0eafb32c681d8d2c181fc2a1bdabe9b3f611d9f6b1a \ + --hash=sha256:97c8115b27e19e592a05c45d0dd89c57f81f841cc9880e353e0d3bf25b2139ed \ + --hash=sha256:9a693028b9cbe51b5a1136232ee8f2bc242e4e19d456ded3fa7c86e43c713b4a \ + --hash=sha256:9a9c42a2723999a710445bc0d974e345c32adfd8d2fac6d8a251fa829ad31cfb \ + --hash=sha256:a3e84d5ec9ba01f8fd03802b2147ba77f0c8f2617b2aff254cedd551844209c8 \ + --hash=sha256:aad75154a7ac9039936d50cf431719a2f8d4ed3d3c277ac03f3339ded1a5e707 \ + --hash=sha256:b12c6b1e1651e42ab5de8b1e00dc3b6354fdfd778e7fa60541ddacc27cd21410 \ + --hash=sha256:b928a3ca837c77a10e81a814a693f2295200adb3352395fad024559b7be7a736 \ + --hash=sha256:bcb87663e1f7b075e48c3be3ecb5f0b46c8fc50b50a97cf264e7f60242dca3f2 \ + --hash=sha256:c797e2517cb7880f8297e2c0f43bb910e91381339336f75d2c1c2cbf811b70b4 \ + --hash=sha256:c89eb37fae9216985d8734c1afd172ba4927f5a05cfd9bf0e4863c6d5465b013 \ + --hash=sha256:cdcd3edcbc5d55757e5f5f3d330dd00007ae463a7e7aa5bf132d1f22a4b62b19 \ + --hash=sha256:d24c13369e856b94892a89ddf70b332e0b70ad4a5c43cf3e9cb71d6d7ffa1f7b \ + --hash=sha256:d4e4aadb7fc1f88687f47ca20bb7227981b03afaae69287029da08096853b738 \ + --hash=sha256:d9528b535a6c4f8ff37847144b8986a9a143585f0540fbcb1a98115b543aa463 \ + --hash=sha256:ed3775295fb91f70b4027aeba878d79b3e55c0b3e97eaa4de71f8f23a9f2eb77 \ + --hash=sha256:ed418c37d095aeddf5336898a132fba01091f0ac5844e3e8018506f014b6d2c4 # via # google-auth # pyjwt @@ -559,13 +575,13 @@ cython==3.0.12 \ --hash=sha256:feb86122a823937cc06e4c029d80ff69f082ebb0b959ab52a5af6cdd271c5dc3 \ --hash=sha256:ff5c0b6a65b08117d0534941d404833d516dac422eee88c6b4fd55feb409a5ed # via feast (pyproject.toml) -dask[dataframe]==2026.1.2 \ - --hash=sha256:1136683de2750d98ea792670f7434e6c1cfce90cab2cc2f2495a9e60fd25a4fc \ - --hash=sha256:46a0cf3b8d87f78a3d2e6b145aea4418a6d6d606fe6a16c79bd8ca2bb862bc91 +dask[dataframe]==2026.3.0 \ + --hash=sha256:be614b9242b0b38288060fb2d7696125946469c98a1c30e174883fd199e0428d \ + --hash=sha256:f7d96c8274e8a900d217c1ff6ea8d1bbf0b4c2c21e74a409644498d925eb8f85 # via feast (pyproject.toml) -db-dtypes==1.5.0 \ - --hash=sha256:abdbb2e4eb965800ed6f98af0c5c1cafff9063ace09114be2d26a7f046be2c8a \ - --hash=sha256:ad9e94243f53e104bc77dbf9ae44b580d83a770d3694483aba59c9767966daa5 +db-dtypes==1.5.1 \ + --hash=sha256:901099b807c9312bc61a5bddbfb07512884e6c6d5a9edacf24d50bcf303aa5f7 \ + --hash=sha256:ad71a6645e3c1f06d4d32023940576648f43119822f825f0d22587c6ef8afe15 # via # google-cloud-bigquery # pandas-gbq @@ -577,48 +593,42 @@ docutils==0.21.2 \ --hash=sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f \ --hash=sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2 # via sphinx -duckdb==1.4.4 \ - --hash=sha256:0509b39ea7af8cff0198a99d206dca753c62844adab54e545984c2e2c1381616 \ - --hash=sha256:0d636ceda422e7babd5e2f7275f6a0d1a3405e6a01873f00d38b72118d30c10b \ - --hash=sha256:1af6e76fe8bd24875dc56dd8e38300d64dc708cd2e772f67b9fbc635cc3066a3 \ - --hash=sha256:1f8d55843cc940e36261689054f7dfb6ce35b1f5b0953b0d355b6adb654b0d52 \ - --hash=sha256:25874f8b1355e96178079e37312c3ba6d61a2354f51319dae860cf21335c3a20 \ - --hash=sha256:337f8b24e89bc2e12dadcfe87b4eb1c00fd920f68ab07bc9b70960d6523b8bc3 \ - --hash=sha256:452c5b5d6c349dc5d1154eb2062ee547296fcbd0c20e9df1ed00b5e1809089da \ - --hash=sha256:453b115f4777467f35103d8081770ac2f223fb5799178db5b06186e3ab51d1f2 \ - --hash=sha256:47dd4162da6a2be59a0aef640eb08d6360df1cf83c317dcc127836daaf3b7f7c \ - --hash=sha256:49123b579e4a6323e65139210cd72dddc593a72d840211556b60f9703bda8526 \ - --hash=sha256:4c25d5b0febda02b7944e94fdae95aecf952797afc8cb920f677b46a7c251955 \ - --hash=sha256:50f2eb173c573811b44aba51176da7a4e5c487113982be6a6a1c37337ec5fa57 \ - --hash=sha256:53cd6423136ab44383ec9955aefe7599b3fb3dd1fe006161e6396d8167e0e0d4 \ - --hash=sha256:5536eb952a8aa6ae56469362e344d4e6403cc945a80bc8c5c2ebdd85d85eb64b \ - --hash=sha256:59c8d76016dde854beab844935b1ec31de358d4053e792988108e995b18c08e7 \ - --hash=sha256:5ba684f498d4e924c7e8f30dd157da8da34c8479746c5011b6c0e037e9c60ad2 \ - --hash=sha256:5cdc4126ec925edf3112bc656ac9ed23745294b854935fa7a643a216e4455af6 \ - --hash=sha256:5e1933fac5293fea5926b0ee75a55b8cfe7f516d867310a5b251831ab61fe62b \ - --hash=sha256:6703dd1bb650025b3771552333d305d62ddd7ff182de121483d4e042ea6e2e00 \ - --hash=sha256:6792ca647216bd5c4ff16396e4591cfa9b4a72e5ad7cdd312cec6d67e8431a7c \ - --hash=sha256:6cb357cfa3403910e79e2eb46c8e445bb1ee2fd62e9e9588c6b999df4256abc1 \ - --hash=sha256:6fb1225a9ea5877421481d59a6c556a9532c32c16c7ae6ca8d127e2b878c9389 \ - --hash=sha256:707530f6637e91dc4b8125260595299ec9dd157c09f5d16c4186c5988bfbd09a \ - --hash=sha256:7df7351328ffb812a4a289732f500d621e7de9942a3a2c9b6d4afcf4c0e72526 \ - --hash=sha256:7eec0bf271ac622e57b7f6554a27a6e7d1dd2f43d1871f7962c74bcbbede15ba \ - --hash=sha256:8097201bc5fd0779d7fcc2f3f4736c349197235f4cb7171622936343a1aa8dbf \ - --hash=sha256:8bba52fd2acb67668a4615ee17ee51814124223de836d9e2fdcbc4c9021b3d3c \ - --hash=sha256:8e5c2d8a0452df55e092959c0bfc8ab8897ac3ea0f754cb3b0ab3e165cd79aff \ - --hash=sha256:a3c8542db7ffb128aceb7f3b35502ebaddcd4f73f1227569306cc34bad06680c \ - --hash=sha256:b297eff642503fd435a9de5a9cb7db4eccb6f61d61a55b30d2636023f149855f \ - --hash=sha256:bf138201f56e5d6fc276a25138341b3523e2f84733613fc43f02c54465619a95 \ - --hash=sha256:c65d15c440c31e06baaebfd2c06d71ce877e132779d309f1edf0a85d23c07e92 \ - --hash=sha256:c9566a4ed834ec7999db5849f53da0a7ee83d86830c33f471bf0211a1148ca12 \ - --hash=sha256:cd1be3d48577f5b40eb9706c6b2ae10edfe18e78eb28e31a3b922dcff1183597 \ - --hash=sha256:d0440f59e0cd9936a9ebfcf7a13312eda480c79214ffed3878d75947fc3b7d6d \ - --hash=sha256:d525de5f282b03aa8be6db86b1abffdceae5f1055113a03d5b50cd2fb8cf2ef8 \ - --hash=sha256:ddcfd9c6ff234da603a1edd5fd8ae6107f4d042f74951b65f91bc5e2643856b3 \ - --hash=sha256:e041f2fbd6888da090eca96ac167a7eb62d02f778385dd9155ed859f1c6b6dc8 \ - --hash=sha256:e870a441cb1c41d556205deb665749f26347ed13b3a247b53714f5d589596977 \ - --hash=sha256:f28a18cc790217e5b347bb91b2cab27aafc557c58d3d8382e04b4fe55d0c3f66 \ - --hash=sha256:fb94de6d023de9d79b7edc1ae07ee1d0b4f5fa8a9dcec799650b5befdf7aafec +duckdb==1.5.1 \ + --hash=sha256:054ad424b051b334052afac58cb216f3b1ebb8579fc8c641e60f0182e8725ea9 \ + --hash=sha256:05fc91767d0cfc4cf2fa68966ab5b479ac07561752e42dd0ae30327bd160f64a \ + --hash=sha256:0a6acc2040bec1f05de62a2f3f68f4c12f3ec7d6012b4317d0ab1a195af26225 \ + --hash=sha256:26e56b5f0c96189e3288d83cf7b476e23615987902f801e5788dee15ee9f24a9 \ + --hash=sha256:36e8e32621a9e2a9abe75dc15a4b54a3997f2d8b1e53ad754bae48a083c91130 \ + --hash=sha256:40c5220ec93790b18ec6278da9c6ac2608d997ee6d6f7cd44c5c3992764e8e71 \ + --hash=sha256:446d500a2977c6ae2077f340c510a25956da5c77597175c316edfa87248ceda3 \ + --hash=sha256:46f92ada9023e59f27edc048167b31ac9a03911978b1296c845a34462a27f096 \ + --hash=sha256:482f8a13f2600f527e427f73c42b5aa75536f9892868068f0aaf573055a0135f \ + --hash=sha256:553c273a6a8f140adaa6da6a6135c7f95bdc8c2e5f95252fcdf9832d758e2141 \ + --hash=sha256:5ae7c0d744d64e2753149634787cc4ab60f05ef1e542b060eeab719f3cdb7723 \ + --hash=sha256:5d4147422d91ccdc2d2abf6ed24196025e020259d1d267970ae20c13c2ce84b1 \ + --hash=sha256:6af347debc8b721aa72e48671166282da979d5e5ae52dbc660ab417282b48e23 \ + --hash=sha256:6ba302115f63f6482c000ccfd62efdb6c41d9d182a5bcd4a90e7ab8cd13856eb \ + --hash=sha256:6f7361d66cc801d9eb4df734b139cd7b0e3c257a16f3573ebd550ddb255549e6 \ + --hash=sha256:715f05ea198d20d7f8b407b9b84e0023d17f2b9096c194cea702b7840e74f1f7 \ + --hash=sha256:71dddcebbc5a70e946a06c30b59b5dd7999c9833d307168f90fb4e4b672ab63e \ + --hash=sha256:8150c569b2aa4573b51ba8475e814aa41fd53a3d510c1ffb96f1139f46faf611 \ + --hash=sha256:8843bd9594e1387f1e601439e19ad73abdf57356104fd1e53a708255bb95a13d \ + --hash=sha256:8c0088765747ae5d6c9f89987bb36f9fb83564f07090d721344ce8e1abedffea \ + --hash=sha256:972d0dbf283508f9bc446ee09c3838cb7c7f114b5bdceee41753288c97fe2f7c \ + --hash=sha256:a28531cee2a5a42d89f9ba4da53bfeb15681f12acc0263476c8705380dadce07 \ + --hash=sha256:a3be2072315982e232bfe49c9d3db0a59ba67b2240a537ef42656cc772a887c7 \ + --hash=sha256:ac2804043bd1bc10b5da18f8f4c706877197263a510c41be9b4c0062f5783dcc \ + --hash=sha256:afab8b4b1f4469c3879bb049dd039f8fce402712050324e9524a43d7324c5e87 \ + --hash=sha256:b370d1620a34a4538ef66524fcee9de8171fa263c701036a92bc0b4c1f2f9c6d \ + --hash=sha256:b8b0808dba0c63b7633bdaefb34e08fe0612622224f9feb0e7518904b1615101 \ + --hash=sha256:bc7ca6a1a40e7e4c933017e6c09ef18032add793df4e42624c6c0c87e0bebdad \ + --hash=sha256:caa65e1f5bf007430bf657c37cab7ab81a4ddf8d337e3062bcc5085d17ef038b \ + --hash=sha256:d68c5a01a283cb13b79eafe016fe5869aa11bff8c46e7141c70aa0aac808010f \ + --hash=sha256:da137802688190835b4c863cafa77fd7e29dff662ee6d905a9ffc14f00299c91 \ + --hash=sha256:e56a20ab6cdb90a95b0c99652e28de3504ce77129087319c03c9098266183ae5 \ + --hash=sha256:e878ccb7d20872065e1597935fdb5e65efa43220c8edd0d9c4a1a7ff1f3eb277 \ + --hash=sha256:eba81e0b3011c1f23df7ea47ef4ffaa8239817959ae291515b6efd068bde2161 \ + --hash=sha256:ed6d23a3f806898e69c77430ebd8da0c79c219f97b9acbc9a29a653e09740c59 # via ibis-framework durationpy==0.10 \ --hash=sha256:1fa6893409a6e739c9c72334fc65cca1f355dbdd93405d30f726deb5bde42fba \ @@ -630,9 +640,9 @@ exceptiongroup==1.3.1 \ # via # anyio # scikit-build-core -fastapi==0.129.0 \ - --hash=sha256:61315cebd2e65df5f97ec298c888f9de30430dd0612d59d6480beafbc10655af \ - --hash=sha256:b4946880e48f462692b31c083be0432275cbfb6e2274566b1be91479cc1a84ec +fastapi==0.135.3 \ + --hash=sha256:9b0f590c813acd13d0ab43dd8494138eb58e484bfac405db1f3187cfc5810d98 \ + --hash=sha256:bd6d7caf1a2bdd8d676843cdcd2287729572a1ef524fc4d65c17ae002a1be654 # via # feast (pyproject.toml) # fastapi-mcp @@ -640,9 +650,9 @@ fastapi-mcp==0.4.0 \ --hash=sha256:d4a3fe7966af24d44e4b412720561c95eb12bed999a4443a88221834b3b15aec \ --hash=sha256:d4ca9410996f4c7b8ea0d7b20fdf79878dc359ebf89cbf3b222e0b675a55097d # via feast (pyproject.toml) -filelock==3.24.2 \ - --hash=sha256:667d7dc0b7d1e1064dd5f8f8e80bdac157a6482e8d2e02cd16fd3b6b33bd6556 \ - --hash=sha256:c22803117490f156e59fafce621f0550a7a853e2bbf4f87f112b11d469b6c81b +filelock==3.25.2 \ + --hash=sha256:b64ece2b38f4ca29dd3e810287aa8c48182bbecd1ae6e9ae126c9b35f1382694 \ + --hash=sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70 # via snowflake-connector-python flit-core==3.12.0 \ --hash=sha256:18f63100d6f94385c6ed57a72073443e1a71a4acb4339491615d0f16d6ff01b2 \ @@ -788,9 +798,9 @@ fsspec==2024.9.0 \ # via # feast (pyproject.toml) # dask -google-api-core[grpc]==2.29.0 \ - --hash=sha256:84181be0f8e6b04006df75ddfe728f24489f0af57c96a529ff7cf45bc28797f7 \ - --hash=sha256:d30bc60980daa36e314b5d5a3e5958b0200cb44ca8fa1be2b614e932b75a3ea9 +google-api-core[grpc]==2.30.2 \ + --hash=sha256:9a8113e1a88bdc09a7ff629707f2214d98d61c7f6ceb0ea38c42a095d02dc0f9 \ + --hash=sha256:a4c226766d6af2580577db1f1a51bf53cd262f722b49731ce7414c43068a9594 # via # feast (pyproject.toml) # google-cloud-bigquery @@ -800,9 +810,9 @@ google-api-core[grpc]==2.29.0 \ # google-cloud-datastore # google-cloud-storage # pandas-gbq -google-auth==2.48.0 \ - --hash=sha256:2e2a537873d449434252a9632c28bfc268b0adb1e53f9fb62afc5333a975903f \ - --hash=sha256:4f7e706b0cd3208a3d940a19a822c37a476ddba5450156c3e6624a71f7c841ce +google-auth==2.49.1 \ + --hash=sha256:16d40da1c3c5a0533f57d268fe72e0ebb0ae1cc3b567024122651c045d879b64 \ + --hash=sha256:195ebe3dca18eddd1b3db5edc5189b76c13e96f29e73043b923ebcf3f1a860f7 # via # google-api-core # google-auth-oauthlib @@ -814,37 +824,37 @@ google-auth==2.48.0 \ # google-cloud-storage # pandas-gbq # pydata-google-auth -google-auth-oauthlib==1.2.4 \ - --hash=sha256:0e922eea5f2baacaf8867febb782e46e7b153236c21592ed76ab3ddb77ffd772 \ - --hash=sha256:3ca93859c6cc9003c8e12b2a0868915209d7953f05a70f4880ab57d57e56ee3e +google-auth-oauthlib==1.3.1 \ + --hash=sha256:14c22c7b3dd3d06dbe44264144409039465effdd1eef94f7ce3710e486cc4bfa \ + --hash=sha256:1a139ef23f1318756805b0e95f655c238bffd29655329a2978218248da4ee7f8 # via # pandas-gbq # pydata-google-auth -google-cloud-bigquery[pandas]==3.40.1 \ - --hash=sha256:75afcfb6e007238fe1deefb2182105249321145ff921784fe7b1de2b4ba24506 \ - --hash=sha256:9082a6b8193aba87bed6a2c79cf1152b524c99bb7e7ac33a785e333c09eac868 +google-cloud-bigquery[pandas]==3.41.0 \ + --hash=sha256:2217e488b47ed576360c9b2cc07d59d883a54b83167c0ef37f915c26b01a06fe \ + --hash=sha256:2a5b5a737b401cbd824a6e5eac7554100b878668d908e6548836b5d8aaa4dcaa # via # feast (pyproject.toml) # pandas-gbq -google-cloud-bigquery-storage==2.36.1 \ - --hash=sha256:99ad6b8810d028f0cf368ea0cc54b3cda20e856f05eb4cda51f1db2a70692286 \ - --hash=sha256:fd3917584a41f7a9d9c633b31ff43103869b108224e8a4b765537eb1ea83148c +google-cloud-bigquery-storage==2.37.0 \ + --hash=sha256:1e319c27ef60fc31030f6e0b52e5e891e1cdd50551effe8c6f673a4c3c56fcb6 \ + --hash=sha256:f88ee7f1e49db1e639da3d9a8b79835ca4bc47afbb514fb2adfc0ccb41a7fd97 # via feast (pyproject.toml) -google-cloud-bigtable==2.35.0 \ - --hash=sha256:f355bfce1f239453ec2bb3839b0f4f9937cf34ef06ef29e1ca63d58fd38d0c50 \ - --hash=sha256:f5699012c5fea4bd4bdf7e80e5e3a812a847eb8f41bf8dc2f43095d6d876b83b +google-cloud-bigtable==2.36.0 \ + --hash=sha256:21b2f41231b7368a550b44d5b493b811b3507fcb23eb26d00005cd3f205f2207 \ + --hash=sha256:d5987733c2f60c739f93f259d2037858411cc994ac37cdfbccb6bb159f3ca43e # via feast (pyproject.toml) -google-cloud-core==2.5.0 \ - --hash=sha256:67d977b41ae6c7211ee830c7912e41003ea8194bff15ae7d72fd6f51e57acabc \ - --hash=sha256:7c1b7ef5c92311717bd05301aa1a91ffbc565673d3b0b4163a52d8413a186963 +google-cloud-core==2.5.1 \ + --hash=sha256:3dc94bdec9d05a31d9f355045ed0f369fbc0d8c665076c734f065d729800f811 \ + --hash=sha256:ea62cdf502c20e3e14be8a32c05ed02113d7bef454e40ff3fab6fe1ec9f1f4e7 # via # google-cloud-bigquery # google-cloud-bigtable # google-cloud-datastore # google-cloud-storage -google-cloud-datastore==2.23.0 \ - --hash=sha256:24a1b1d29b902148fe41b109699f76fd3aa60591e9d547c0f8b87d7bf9ff213f \ - --hash=sha256:80049883a4ae928fdcc661ba6803ec267665dc0e6f3ce2da91441079a6bb6387 +google-cloud-datastore==2.24.0 \ + --hash=sha256:81f1d1c12c2906f59507f72742545ab04c38f62ed70b0542057e3cf04a53aa65 \ + --hash=sha256:f087c02a6aa4ac68bbf17f0c048ae3ee355856bf09c51439bfba193741387792 # via feast (pyproject.toml) google-cloud-storage==2.19.0 \ --hash=sha256:aeb971b5c29cf8ab98445082cbfe7b161a1f48ed275822f59ed3f1524ea54fba \ @@ -888,78 +898,78 @@ google-crc32c==1.8.0 \ # google-cloud-bigtable # google-cloud-storage # google-resumable-media -google-resumable-media==2.8.0 \ - --hash=sha256:dd14a116af303845a8d932ddae161a26e86cc229645bc98b39f026f9b1717582 \ - --hash=sha256:f1157ed8b46994d60a1bc432544db62352043113684d4e030ee02e77ebe9a1ae +google-resumable-media==2.8.2 \ + --hash=sha256:82b6d8ccd11765268cdd2a2123f417ec806b8eef3000a9a38dfe3033da5fb220 \ + --hash=sha256:f3354a182ebd193ae3f42e3ef95e6c9b10f128320de23ac7637236713b1acd70 # via # google-cloud-bigquery # google-cloud-storage -googleapis-common-protos[grpc]==1.72.0 \ - --hash=sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038 \ - --hash=sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5 +googleapis-common-protos[grpc]==1.74.0 \ + --hash=sha256:57971e4eeeba6aad1163c1f0fc88543f965bb49129b8bb55b2b7b26ecab084f1 \ + --hash=sha256:702216f78610bb510e3f12ac3cafd281b7ac45cc5d86e90ad87e4d301a3426b5 # via # feast (pyproject.toml) # google-api-core # grpc-google-iam-v1 # grpcio-status -greenlet==3.3.1 \ - --hash=sha256:02925a0bfffc41e542c70aa14c7eda3593e4d7e274bfcccca1827e6c0875902e \ - --hash=sha256:04bee4775f40ecefcdaa9d115ab44736cd4b9c5fba733575bfe9379419582e13 \ - --hash=sha256:070472cd156f0656f86f92e954591644e158fd65aa415ffbe2d44ca77656a8f5 \ - --hash=sha256:09f51496a0bfbaa9d74d36a52d2580d1ef5ed4fdfcff0a73730abfbbbe1403dd \ - --hash=sha256:1108b61b06b5224656121c3c8ee8876161c491cbe74e5c519e0634c837cf93d5 \ - --hash=sha256:12184c61e5d64268a160226fb4818af4df02cfead8379d7f8b99a56c3a54ff3e \ - --hash=sha256:14194f5f4305800ff329cbf02c5fcc88f01886cadd29941b807668a45f0d2336 \ - --hash=sha256:20fedaadd422fa02695f82093f9a98bad3dab5fcda793c658b945fcde2ab27ba \ - --hash=sha256:27289986f4e5b0edec7b5a91063c109f0276abb09a7e9bdab08437525977c946 \ - --hash=sha256:2f080e028001c5273e0b42690eaf359aeef9cb1389da0f171ea51a5dc3c7608d \ - --hash=sha256:301860987846c24cb8964bdec0e31a96ad4a2a801b41b4ef40963c1b44f33451 \ - --hash=sha256:32e4ca9777c5addcbf42ff3915d99030d8e00173a56f80001fb3875998fe410b \ - --hash=sha256:33a956fe78bbbda82bfc95e128d61129b32d66bcf0a20a1f0c08aa4839ffa951 \ - --hash=sha256:34a729e2e4e4ffe9ae2408d5ecaf12f944853f40ad724929b7585bca808a9d6f \ - --hash=sha256:39eda9ba259cc9801da05351eaa8576e9aa83eb9411e8f0c299e05d712a210f2 \ - --hash=sha256:3a300354f27dd86bae5fbf7002e6dd2b3255cd372e9242c933faf5e859b703fe \ - --hash=sha256:3e0f3878ca3a3ff63ab4ea478585942b53df66ddde327b59ecb191b19dbbd62d \ - --hash=sha256:3e63252943c921b90abb035ebe9de832c436401d9c45f262d80e2d06cc659242 \ - --hash=sha256:41848f3230b58c08bb43dee542e74a2a2e34d3c59dc3076cec9151aeeedcae98 \ - --hash=sha256:49f4ad195d45f4a66a0eb9c1ba4832bb380570d361912fa3554746830d332149 \ - --hash=sha256:4b065d3284be43728dd280f6f9a13990b56470b81be20375a207cdc814a983f2 \ - --hash=sha256:4b9721549a95db96689458a1e0ae32412ca18776ed004463df3a9299c1b257ab \ - --hash=sha256:50e1457f4fed12a50e427988a07f0f9df53cf0ee8da23fab16e6732c2ec909d4 \ - --hash=sha256:59913f1e5ada20fde795ba906916aea25d442abcc0593fba7e26c92b7ad76249 \ - --hash=sha256:5fd23b9bc6d37b563211c6abbb1b3cab27db385a4449af5c32e932f93017080c \ - --hash=sha256:6423481193bbbe871313de5fd06a082f2649e7ce6e08015d2a76c1e9186ca5b3 \ - --hash=sha256:65be2f026ca6a176f88fb935ee23c18333ccea97048076aef4db1ef5bc0713ac \ - --hash=sha256:67ea3fc73c8cd92f42467a72b75e8f05ed51a0e9b1d15398c913416f2dafd49f \ - --hash=sha256:71c767cf281a80d02b6c1bdc41c9468e1f5a494fb11bc8688c360524e273d7b1 \ - --hash=sha256:76e39058e68eb125de10c92524573924e827927df5d3891fbc97bd55764a8774 \ - --hash=sha256:7932f5f57609b6a3b82cc11877709aa7a98e3308983ed93552a1c377069b20c8 \ - --hash=sha256:7a3ae05b3d225b4155bda56b072ceb09d05e974bc74be6c3fc15463cf69f33fd \ - --hash=sha256:7ab327905cabb0622adca5971e488064e35115430cec2c35a50fd36e72a315b3 \ - --hash=sha256:7b2fe4150a0cf59f847a67db8c155ac36aed89080a6a639e9f16df5d6c6096f1 \ - --hash=sha256:7e806ca53acf6d15a888405880766ec84721aa4181261cd11a457dfe9a7a4975 \ - --hash=sha256:80aa4d79eb5564f2e0a6144fcc744b5a37c56c4a92d60920720e99210d88db0f \ - --hash=sha256:92497c78adf3ac703b57f1e3813c2d874f27f71a178f9ea5887855da413cd6d2 \ - --hash=sha256:96aff77af063b607f2489473484e39a0bbae730f2ea90c9e5606c9b73c44174a \ - --hash=sha256:aec9ab04e82918e623415947921dea15851b152b822661cce3f8e4393c3df683 \ - --hash=sha256:b066e8b50e28b503f604fa538adc764a638b38cf8e81e025011d26e8a627fa79 \ - --hash=sha256:b31c05dd84ef6871dd47120386aed35323c944d86c3d91a17c4b8d23df62f15b \ - --hash=sha256:bd59acd8529b372775cd0fcbc5f420ae20681c5b045ce25bd453ed8455ab99b5 \ - --hash=sha256:bfb2d1763d777de5ee495c85309460f6fd8146e50ec9d0ae0183dbf6f0a829d1 \ - --hash=sha256:c620051669fd04ac6b60ebc70478210119c56e2d5d5df848baec4312e260e4ca \ - --hash=sha256:c9f9d5e7a9310b7a2f416dd13d2e3fd8b42d803968ea580b7c0f322ccb389b97 \ - --hash=sha256:cb0feb07fe6e6a74615ee62a880007d976cf739b6669cce95daa7373d4fc69c5 \ - --hash=sha256:cc98b9c4e4870fa983436afa999d4eb16b12872fab7071423d5262fa7120d57a \ - --hash=sha256:d842c94b9155f1c9b3058036c24ffb8ff78b428414a19792b2380be9cecf4f36 \ - --hash=sha256:da19609432f353fed186cc1b85e9440db93d489f198b4bdf42ae19cc9d9ac9b4 \ - --hash=sha256:e0093bd1a06d899892427217f0ff2a3c8f306182b8c754336d32e2d587c131b4 \ - --hash=sha256:e2e7e882f83149f0a71ac822ebf156d902e7a5d22c9045e3e0d1daf59cee2cc9 \ - --hash=sha256:e84b51cbebf9ae573b5fbd15df88887815e3253fc000a7d0ff95170e8f7e9729 \ - --hash=sha256:ed6b402bc74d6557a705e197d47f9063733091ed6357b3de33619d8a8d93ac53 +greenlet==3.3.2 \ + --hash=sha256:02b0a8682aecd4d3c6c18edf52bc8e51eacdd75c8eac52a790a210b06aa295fd \ + --hash=sha256:18cb1b7337bca281915b3c5d5ae19f4e76d35e1df80f4ad3c1a7be91fadf1082 \ + --hash=sha256:1a9172f5bf6bd88e6ba5a84e0a68afeac9dc7b6b412b245dd64f52d83c81e55b \ + --hash=sha256:1e692b2dae4cc7077cbb11b47d258533b48c8fde69a33d0d8a82e2fe8d8531d5 \ + --hash=sha256:1ebd458fa8285960f382841da585e02201b53a5ec2bac6b156fc623b5ce4499f \ + --hash=sha256:1fb39a11ee2e4d94be9a76671482be9398560955c9e568550de0224e41104727 \ + --hash=sha256:20154044d9085151bc309e7689d6f7ba10027f8f5a8c0676ad398b951913d89e \ + --hash=sha256:2eaf067fc6d886931c7962e8c6bede15d2f01965560f3359b27c80bde2d151f2 \ + --hash=sha256:34308836d8370bddadb41f5a7ce96879b72e2fdfb4e87729330c6ab52376409f \ + --hash=sha256:394ead29063ee3515b4e775216cb756b2e3b4a7e55ae8fd884f17fa579e6b327 \ + --hash=sha256:3ceec72030dae6ac0c8ed7591b96b70410a8be370b6a477b1dbc072856ad02bd \ + --hash=sha256:4375a58e49522698d3e70cc0b801c19433021b5c37686f7ce9c65b0d5c8677d2 \ + --hash=sha256:43e99d1749147ac21dde49b99c9abffcbc1e2d55c67501465ef0930d6e78e070 \ + --hash=sha256:442b6057453c8cb29b4fb36a2ac689382fc71112273726e2423f7f17dc73bf99 \ + --hash=sha256:45abe8eb6339518180d5a7fa47fa01945414d7cca5ecb745346fc6a87d2750be \ + --hash=sha256:4c956a19350e2c37f2c48b336a3afb4bff120b36076d9d7fb68cb44e05d95b79 \ + --hash=sha256:508c7f01f1791fbc8e011bd508f6794cb95397fdb198a46cb6635eb5b78d85a7 \ + --hash=sha256:527fec58dc9f90efd594b9b700662ed3fb2493c2122067ac9c740d98080a620e \ + --hash=sha256:59b3e2c40f6706b05a9cd299c836c6aa2378cabe25d021acd80f13abf81181cf \ + --hash=sha256:5d0e35379f93a6d0222de929a25ab47b5eb35b5ef4721c2b9cbcc4036129ff1f \ + --hash=sha256:63d10328839d1973e5ba35e98cccbca71b232b14051fd957b6f8b6e8e80d0506 \ + --hash=sha256:64970c33a50551c7c50491671265d8954046cb6e8e2999aacdd60e439b70418a \ + --hash=sha256:6c6f8ba97d17a1e7d664151284cb3315fc5f8353e75221ed4324f84eb162b395 \ + --hash=sha256:8b466dff7a4ffda6ca975979bab80bdadde979e29fc947ac3be4451428d8b0e4 \ + --hash=sha256:8c1fdd7d1b309ff0da81d60a9688a8bd044ac4e18b250320a96fc68d31c209ca \ + --hash=sha256:8c4dd0f3997cf2512f7601563cc90dfb8957c0cff1e3a1b23991d4ea1776c492 \ + --hash=sha256:8d1658d7291f9859beed69a776c10822a0a799bc4bfe1bd4272bb60e62507dab \ + --hash=sha256:8e2cd90d413acbf5e77ae41e5d3c9b3ac1d011a756d7284d7f3f2b806bbd6358 \ + --hash=sha256:8e4ab3cfb02993c8cc248ea73d7dae6cec0253e9afa311c9b37e603ca9fad2ce \ + --hash=sha256:94ad81f0fd3c0c0681a018a976e5c2bd2ca2d9d94895f23e7bb1af4e8af4e2d5 \ + --hash=sha256:97245cc10e5515dbc8c3104b2928f7f02b6813002770cfaffaf9a6e0fc2b94ef \ + --hash=sha256:9bc885b89709d901859cf95179ec9f6bb67a3d2bb1f0e88456461bd4b7f8fd0d \ + --hash=sha256:a2a5be83a45ce6188c045bcc44b0ee037d6a518978de9a5d97438548b953a1ac \ + --hash=sha256:a443358b33c4ec7b05b79a7c8b466f5d275025e750298be7340f8fc63dff2a55 \ + --hash=sha256:a7945dd0eab63ded0a48e4dcade82939783c172290a7903ebde9e184333ca124 \ + --hash=sha256:aa6ac98bdfd716a749b84d4034486863fd81c3abde9aa3cf8eff9127981a4ae4 \ + --hash=sha256:ab0c7e7901a00bc0a7284907273dc165b32e0d109a6713babd04471327ff7986 \ + --hash=sha256:ac8d61d4343b799d1e526db579833d72f23759c71e07181c2d2944e429eb09cd \ + --hash=sha256:ad0c8917dd42a819fe77e6bdfcb84e3379c0de956469301d9fd36427a1ca501f \ + --hash=sha256:ae9e21c84035c490506c17002f5c8ab25f980205c3e61ddb3a2a2a2e6c411fcb \ + --hash=sha256:b26b0f4428b871a751968285a1ac9648944cea09807177ac639b030bddebcea4 \ + --hash=sha256:b568183cf65b94919be4438dc28416b234b678c608cafac8874dfeeb2a9bbe13 \ + --hash=sha256:b6997d360a4e6a4e936c0f9625b1c20416b8a0ea18a8e19cabbefc712e7397ab \ + --hash=sha256:b8bddc5b73c9720bea487b3bffdb1840fe4e3656fba3bd40aa1489e9f37877ff \ + --hash=sha256:c04c5e06ec3e022cbfe2cd4a846e1d4e50087444f875ff6d2c2ad8445495cf1a \ + --hash=sha256:c2e47408e8ce1c6f1ceea0dffcdf6ebb85cc09e55c7af407c99f1112016e45e9 \ + --hash=sha256:c56692189a7d1c7606cb794be0a8381470d95c57ce5be03fb3d0ef57c7853b86 \ + --hash=sha256:ccd21bb86944ca9be6d967cf7691e658e43417782bce90b5d2faeda0ff78a7dd \ + --hash=sha256:cd6f9e2bbd46321ba3bbb4c8a15794d32960e3b0ae2cc4d49a1a53d314805d71 \ + --hash=sha256:d248d8c23c67d2291ffd47af766e2a3aa9fa1c6703155c099feb11f526c63a92 \ + --hash=sha256:d3a62fa76a32b462a97198e4c9e99afb9ab375115e74e9a83ce180e7a496f643 \ + --hash=sha256:e26e72bec7ab387ac80caa7496e0f908ff954f31065b0ffc1f8ecb1338b11b54 \ + --hash=sha256:e3cb43ce200f59483eb82949bf1835a99cf43d7571e900d7c8d5c62cdf25d2f9 # via feast (pyproject.toml) -grpc-google-iam-v1==0.14.3 \ - --hash=sha256:7a7f697e017a067206a3dfef44e4c634a34d3dee135fe7d7a4613fe3e59217e6 \ - --hash=sha256:879ac4ef33136c5491a6300e27575a9ec760f6cdf9a2518798c1b8977a5dc389 +grpc-google-iam-v1==0.14.4 \ + --hash=sha256:392b3796947ed6334e61171d9ab06bf7eb357f554e5fc7556ad7aab6d0e17038 \ + --hash=sha256:412facc320fcbd94034b4df3d557662051d4d8adfa86e0ddb4dca70a3f739964 # via google-cloud-bigtable grpcio==1.62.3 \ --hash=sha256:059444f0ed5dba73ab7dd0ee7e8e6b606df4130d2b0a9f010f84da4ab9f6c2d8 \ @@ -1040,9 +1050,9 @@ grpcio-status==1.62.3 \ --hash=sha256:289bdd7b2459794a12cf95dc0cb727bd4a1742c37bd823f760236c937e53a485 \ --hash=sha256:f9049b762ba8de6b1086789d8315846e094edac2c50beaf462338b301a8fd4b8 # via google-api-core -gunicorn==25.1.0 \ - --hash=sha256:1426611d959fa77e7de89f8c0f32eed6aa03ee735f98c01efba3e281b1c47616 \ - --hash=sha256:d0b1236ccf27f72cfe14bce7caadf467186f19e865094ca84221424e839b8b8b +gunicorn==25.3.0 \ + --hash=sha256:cacea387dab08cd6776501621c295a904fe8e3b7aae9a1a3cbb26f4e7ed54660 \ + --hash=sha256:f74e1b2f9f76f6cd1ca01198968bd2dd65830edc24b6e8e4d78de8320e2fe889 # via # feast (pyproject.toml) # uvicorn-worker @@ -1060,9 +1070,9 @@ hatch-vcs==0.4.0 \ --hash=sha256:093810748fe01db0d451fabcf2c1ac2688caefd232d4ede967090b1c1b07d9f7 \ --hash=sha256:b8a2b6bee54cf6f9fc93762db73890017ae59c9081d1038a41f16235ceaf8b2c # via feast (pyproject.toml) -hatchling==1.28.0 \ - --hash=sha256:4d50b02aece6892b8cd0b3ce6c82cb218594d3ec5836dbde75bf41a21ab004c8 \ - --hash=sha256:dc48722b68b3f4bbfa3ff618ca07cdea6750e7d03481289ffa8be1521d18a961 +hatchling==1.29.0 \ + --hash=sha256:50af9343281f34785fab12da82e445ed987a6efb34fd8c2fc0f6e6630dbcc1b0 \ + --hash=sha256:793c31816d952cee405b83488ce001c719f325d9cda69f1fc4cd750527640ea6 # via # feast (pyproject.toml) # hatch-fancy-pypi-readme @@ -1235,13 +1245,13 @@ idna==3.11 \ # requests # snowflake-connector-python # yarl -imagesize==1.4.1 \ - --hash=sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b \ - --hash=sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a +imagesize==2.0.0 \ + --hash=sha256:5667c5bbb57ab3f1fa4bc366f4fbc971db3d5ed011fd2715fd8001f782718d96 \ + --hash=sha256:8e8358c4a05c304f1fccf7ff96f036e7243a189e9e42e90851993c558cfe9ee3 # via sphinx -importlib-metadata==8.7.1 \ - --hash=sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb \ - --hash=sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151 +importlib-metadata==9.0.0 \ + --hash=sha256:2d21d1cc5a017bd0559e36150c21c830ab1dc304dedd1b7ea85d20f45ef3edd7 \ + --hash=sha256:a4f57ab599e6a2e3016d7595cfd72eb4661a5106e787a95bcc90c7105b831efc # via dask jinja2==3.1.6 \ --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ @@ -1270,97 +1280,97 @@ kubernetes==35.0.0 \ --hash=sha256:39e2b33b46e5834ef6c3985ebfe2047ab39135d41de51ce7641a7ca5b372a13d \ --hash=sha256:3d00d344944239821458b9efd484d6df9f011da367ecb155dadf9513f05f09ee # via feast (pyproject.toml) -librt==0.8.0 \ - --hash=sha256:001e5330093d887b8b9165823eca6c5c4db183fe4edea4fdc0680bbac5f46944 \ - --hash=sha256:015e2dde6e096d27c10238bf9f6492ba6c65822dfb69d2bf74c41a8e88b7ddef \ - --hash=sha256:02a9fe85410cc9bef045e7cb7fd26fdde6669e6d173f99df659aa7f6335961e9 \ - --hash=sha256:0583aef7e9a720dd40f26a2ad5a1bf2ccbb90059dac2b32ac516df232c701db3 \ - --hash=sha256:05a3dd3f116747f7e1a2b475ccdc6fb637fd4987126d109e03013a79d40bf9e6 \ - --hash=sha256:0a33335eb59921e77c9acc05d0e654e4e32e45b014a4d61517897c11591094f8 \ - --hash=sha256:0ce33a9778e294507f3a0e3468eccb6a698b5166df7db85661543eca1cfc5369 \ - --hash=sha256:1566dbb9d1eb0987264c9b9460d212e809ba908d2f4a3999383a84d765f2f3f1 \ - --hash=sha256:17269dd2745dbe8e42475acb28e419ad92dfa38214224b1b01020b8cac70b645 \ - --hash=sha256:178707cda89d910c3b28bf5aa5f69d3d4734e0f6ae102f753ad79edef83a83c7 \ - --hash=sha256:1c25a131013eadd3c600686a0c0333eb2896483cbc7f65baa6a7ee761017aef9 \ - --hash=sha256:1e6811cac1dcb27ca4c74e0ca4a5917a8e06db0d8408d30daee3a41724bfde7a \ - --hash=sha256:1ef3bd856373cf8e7382402731f43bfe978a8613b4039e49e166e1e0dc590216 \ - --hash=sha256:20f73d4fecba969efc15cdefd030e382502d56bb6f1fc66b580cce582836c9fa \ - --hash=sha256:21b14464bee0b604d80a638cf1ee3148d84ca4cc163dcdcecb46060c1b3605e4 \ - --hash=sha256:24a01c13a2a9bdad20997a4443ebe6e329df063d1978bbe2ebbf637878a46d1e \ - --hash=sha256:25b3e667cbfc9000c4740b282df599ebd91dbdcc1aa6785050e4c1d6be5329ab \ - --hash=sha256:25e82d920d4d62ad741592fcf8d0f3bda0e3fc388a184cb7d2f566c681c5f7b9 \ - --hash=sha256:2b37437e7e4ef5e15a297b36ba9e577f73e29564131d86dd75875705e97402b5 \ - --hash=sha256:2ccdd20d9a72c562ffb73098ac411de351b53a6fbb3390903b2d33078ef90447 \ - --hash=sha256:2e0ffe88ebb5962f8fb0ddcbaaff30f1ea06a79501069310e1e030eafb1ad787 \ - --hash=sha256:375eda7acfce1f15f5ed56cfc960669eefa1ec8732e3e9087c3c4c3f2066759c \ - --hash=sha256:3d2720335020219197380ccfa5c895f079ac364b4c429e96952cd6509934d8eb \ - --hash=sha256:3e36a8da17134ffc29373775d88c04832f9ecfab1880470661813e6c7991ef79 \ - --hash=sha256:3e8b77b5f54d0937b26512774916041756c9eb3e66f1031971e626eea49d0bf4 \ - --hash=sha256:41064a0c07b4cc7a81355ccc305cb097d6027002209ffca51306e65ee8293630 \ - --hash=sha256:421765e8c6b18e64d21c8ead315708a56fc24f44075059702e421d164575fdda \ - --hash=sha256:4831c44b8919e75ca0dfb52052897c1ef59fdae19d3589893fbd068f1e41afbf \ - --hash=sha256:48f84830a8f8ad7918afd743fd7c4eb558728bceab7b0e38fd5a5cf78206a556 \ - --hash=sha256:4b705f85311ee76acec5ee70806990a51f0deb519ea0c29c1d1652d79127604d \ - --hash=sha256:4d3e38797eb482485b486898f89415a6ab163bc291476bd95712e42cf4383c05 \ - --hash=sha256:4eb5e06ebcc668677ed6389164f52f13f71737fc8be471101fa8b4ce77baeb0c \ - --hash=sha256:4f6e975377fbc4c9567cb33ea9ab826031b6c7ec0515bfae66a4fb110d40d6da \ - --hash=sha256:4f764b2424cb04524ff7a486b9c391e93f93dc1bd8305b2136d25e582e99aa2f \ - --hash=sha256:507e94f4bec00b2f590fbe55f48cd518a208e2474a3b90a60aa8f29136ddbada \ - --hash=sha256:56901f1eec031396f230db71c59a01d450715cbbef9856bf636726994331195d \ - --hash=sha256:5cb11061a736a9db45e3c1293cfcb1e3caf205912dfa085734ba750f2197ff9a \ - --hash=sha256:5d0f76fc73480d42285c609c0ea74d79856c160fa828ff9aceab574ea4ecfd7b \ - --hash=sha256:667e2513cf69bfd1e1ed9a00d6c736d5108714ec071192afb737987955888a25 \ - --hash=sha256:671a6152edf3b924d98a5ed5e6982ec9cb30894085482acadce0975f031d4c5c \ - --hash=sha256:693697133c3b32aa9b27f040e3691be210e9ac4d905061859a9ed519b1d5a376 \ - --hash=sha256:6a3146c63220d814c4a2c7d6a1eacc8d5c14aed0ff85115c1dfea868080cd18f \ - --hash=sha256:6b6caff69e25d80c269b1952be8493b4d94ef745f438fa619d7931066bdd26de \ - --hash=sha256:6e1af31a710e17891d9adf0dbd9a5fcd94901a3922a96499abdbf7ce658f4e01 \ - --hash=sha256:70defb797c4d5402166787a6b3c66dfb3fa7f93d118c0509ffafa35a392f4258 \ - --hash=sha256:71fc517efc14f75c2f74b1f0a5d5eb4a8e06aa135c34d18eaf3522f4a53cd62d \ - --hash=sha256:75d1a8cab20b2043f03f7aab730551e9e440adc034d776f15f6f8d582b0a5ad4 \ - --hash=sha256:789911e8fa40a2e82f41120c936b1965f3213c67f5a483fc5a41f5839a05dcbb \ - --hash=sha256:7bd68cebf3131bb920d5984f75fe302d758db33264e44b45ad139385662d7bc3 \ - --hash=sha256:7ce0a8cb67e702dcb06342b2aaaa3da9fb0ddc670417879adfa088b44cf7b3b6 \ - --hash=sha256:7f820210e21e3a8bf8fde2ae3c3d10106d4de9ead28cbfdf6d0f0f41f5b12fa1 \ - --hash=sha256:8070aa3368559de81061ef752770d03ca1f5fc9467d4d512d405bd0483bfffe6 \ - --hash=sha256:82e61cd1c563745ad495387c3b65806bfd453badb4adbc019df3389dddee1bf6 \ - --hash=sha256:82fb4602d1b3e303a58bfe6165992b5a78d823ec646445356c332cd5f5bbaa61 \ - --hash=sha256:88c6e75540f1f10f5e0fc5e87b4b6c290f0e90d1db8c6734f670840494764af8 \ - --hash=sha256:8992ca186a1678107b0af3d0c9303d8c7305981b9914989b9788319ed4d89546 \ - --hash=sha256:92249938ab744a5890580d3cb2b22042f0dce71cdaa7c1369823df62bedf7cbc \ - --hash=sha256:95a719a049f0eefaf1952673223cf00d442952273cbd20cf2ed7ec423a0ef58d \ - --hash=sha256:9646178cd794704d722306c2c920c221abbf080fede3ba539d5afdec16c46dad \ - --hash=sha256:9726305d3e53419d27fc8cdfcd3f9571f0ceae22fa6b5ea1b3662c2e538f833e \ - --hash=sha256:995d24caa6bbb34bcdd4a41df98ac6d1af637cfa8975cb0790e47d6623e70e3e \ - --hash=sha256:9ab3a3475a55b89b87ffd7e6665838e8458e0b596c22e0177e0f961434ec474a \ - --hash=sha256:9f09d4884f882baa39a7e36bbf3eae124c4ca2a223efb91e567381d1c55c6b06 \ - --hash=sha256:a512c88900bdb1d448882f5623a0b1ad27ba81a9bd75dacfe17080b72272ca1f \ - --hash=sha256:a905091a13e0884701226860836d0386b88c72ce5c2fdfba6618e14c72be9f25 \ - --hash=sha256:aaadec87f45a3612b6818d1db5fbfe93630669b7ee5d6bdb6427ae08a1aa2141 \ - --hash=sha256:b055bb3abaf69abed25743d8fc1ab691e4f51a912ee0a6f9a6c84f4bbddb283d \ - --hash=sha256:b4bb00bd71b448f16749909b08a0ff16f58b079e2261c2e1000f2bbb2a4f0a45 \ - --hash=sha256:b9aef96d7593584e31ef6ac1eb9775355b0099fee7651fae3a15bc8657b67b52 \ - --hash=sha256:ba581acad5ac8f33e2ff1746e8a57e001b47c6721873121bf8bbcf7ba8bd3aa4 \ - --hash=sha256:ba9d9e60651615bc614be5e21a82cdb7b1769a029369cf4b4d861e4f19686fb6 \ - --hash=sha256:bbebd2bba5c6ae02907df49150e55870fdd7440d727b6192c46b6f754723dde9 \ - --hash=sha256:bd32add59b58fba3439d48d6f36ac695830388e3da3e92e4fc26d2d02670d19c \ - --hash=sha256:bdab762e2c0b48bab76f1a08acb3f4c77afd2123bedac59446aeaaeed3d086cf \ - --hash=sha256:c5512aae4648152abaf4d48b59890503fcbe86e85abc12fb9b096fe948bdd816 \ - --hash=sha256:c6e4c10761ddbc0d67d2f6e2753daf99908db85d8b901729bf2bf5eaa60e0567 \ - --hash=sha256:cb4b3ad543084ed79f186741470b251b9d269cd8b03556f15a8d1a99a64b7de5 \ - --hash=sha256:cb74cdcbc0103fc988e04e5c58b0b31e8e5dd2babb9182b6f9490488eb36324b \ - --hash=sha256:cc3d107f603b5ee7a79b6aa6f166551b99b32fb4a5303c4dfcb4222fc6a0335e \ - --hash=sha256:d920789eca7ef71df7f31fd547ec0d3002e04d77f30ba6881e08a630e7b2c30e \ - --hash=sha256:daae5e955764be8fd70a93e9e5133c75297f8bce1e802e1d3683b98f77e1c5ab \ - --hash=sha256:db63cf3586a24241e89ca1ce0b56baaec9d371a328bd186c529b27c914c9a1ef \ - --hash=sha256:db953b675079884ffda33d1dca7189fb961b6d372153750beb81880384300817 \ - --hash=sha256:de076eaba208d16efb5962f99539867f8e2c73480988cb513fcf1b5dbb0c9dcf \ - --hash=sha256:e79dbc8f57de360f0ed987dc7de7be814b4803ef0e8fc6d3ff86e16798c99935 \ - --hash=sha256:e9a3a38eb4134ad33122a6d575e6324831f930a771d951a15ce232e0237412c2 \ - --hash=sha256:f04ca50e847abc486fa8f4107250566441e693779a5374ba211e96e238f298b9 \ - --hash=sha256:f1178e0de0c271231a660fbef9be6acdfa1d596803464706862bef6644cc1cae \ - --hash=sha256:f4617cef654fca552f00ce5ffdf4f4b68770f18950e4246ce94629b789b92467 \ - --hash=sha256:fa37f99bff354ff191c6bcdffbc9d7cdd4fc37faccfc9be0ef3a4fd5613977da +librt==0.8.1 \ + --hash=sha256:01170b6729a438f0dedc4a26ed342e3dc4f02d1000b4b19f980e1877f0c297e6 \ + --hash=sha256:039b9f2c506bd0ab0f8725aa5ba339c6f0cd19d3b514b50d134789809c24285d \ + --hash=sha256:05bd41cdee35b0c59c259f870f6da532a2c5ca57db95b5f23689fcb5c9e42440 \ + --hash=sha256:086a32dbb71336627e78cc1d6ee305a68d038ef7d4c39aaff41ae8c9aa46e91a \ + --hash=sha256:08eec3a1fc435f0d09c87b6bf1ec798986a3544f446b864e4099633a56fcd9ed \ + --hash=sha256:0bf69d79a23f4f40b8673a947a234baeeb133b5078b483b7297c5916539cf5d5 \ + --hash=sha256:0c3811485fccfda840861905b8c70bba5ec094e02825598bb9d4ca3936857a04 \ + --hash=sha256:0d2f82168e55ddefd27c01c654ce52379c0750ddc31ee86b4b266bcf4d65f2a3 \ + --hash=sha256:0f2ae3725904f7377e11cc37722d5d401e8b3d5851fb9273d7f4fe04f6b3d37d \ + --hash=sha256:10c42e1f6fd06733ef65ae7bebce2872bcafd8d6e6b0a08fe0a05a23b044fb14 \ + --hash=sha256:153188fe98a72f206042be10a2c6026139852805215ed9539186312d50a8e972 \ + --hash=sha256:172d57ec04346b047ca6af181e1ea4858086c80bdf455f61994c4aa6fc3f866c \ + --hash=sha256:190b109bb69592a3401fe1ffdea41a2e73370ace2ffdc4a0e8e2b39cdea81b78 \ + --hash=sha256:1d3a7da44baf692f0c6aeb5b2a09c5e6fc7a703bca9ffa337ddd2e2da53f7732 \ + --hash=sha256:228c2409c079f8c11fb2e5d7b277077f694cb93443eb760e00b3b83cb8b3176c \ + --hash=sha256:22b46eabd76c1986ee7d231b0765ad387d7673bbd996aa0d0d054b38ac65d8f6 \ + --hash=sha256:237796479f4d0637d6b9cbcb926ff424a97735e68ade6facf402df4ec93375ed \ + --hash=sha256:2c74a2da57a094bd48d03fa5d196da83d2815678385d2978657499063709abe1 \ + --hash=sha256:2cc68eeeef5e906839c7bb0815748b5b0a974ec27125beefc0f942715785b551 \ + --hash=sha256:2eb345e8b33fb748227409c9f1233d4df354d6e54091f0e8fc53acdb2ffedeb7 \ + --hash=sha256:31362dbfe297b23590530007062c32c6f6176f6099646bb2c95ab1b00a57c382 \ + --hash=sha256:3dff3d3ca8db20e783b1bc7de49c0a2ab0b8387f31236d6a026597d07fcd68ac \ + --hash=sha256:43353b943613c5d9c49a25aaffdba46f888ec354e71e3529a00cca3f04d66a7a \ + --hash=sha256:439352ba9373f11cb8e1933da194dcc6206daf779ff8df0ed69c5e39113e6a99 \ + --hash=sha256:4998009e7cb9e896569f4be7004f09d0ed70d386fa99d42b6d363f6d200501ac \ + --hash=sha256:4be2a5c926b9770c9e08e717f05737a269b9d0ebc5d2f0060f0fe3fe9ce47acb \ + --hash=sha256:4beb04b8c66c6ae62f8c1e0b2f097c1ebad9295c929a8d5286c05eae7c2fc7dc \ + --hash=sha256:4c8dfa264b9193c4ee19113c985c95f876fae5e51f731494fc4e0cf594990ba7 \ + --hash=sha256:5212a5bd7fae98dae95710032902edcd2ec4dc994e883294f75c857b83f9aba0 \ + --hash=sha256:52c224e14614b750c0a6d97368e16804a98c684657c7518752c356834fff83bb \ + --hash=sha256:56e04c14b696300d47b3bc5f1d10a00e86ae978886d0cee14e5714fafb5df5d2 \ + --hash=sha256:5bb54f1205a3a6ab41a6fd71dfcdcbd278670d3a90ca502a30d9da583105b6f7 \ + --hash=sha256:5cdc0f588ff4b663ea96c26d2a230c525c6fc62b28314edaaaca8ed5af931ad0 \ + --hash=sha256:5db05697c82b3a2ec53f6e72b2ed373132b0c2e05135f0696784e97d7f5d48e7 \ + --hash=sha256:5e4af413908f77294605e28cfd98063f54b2c790561383971d2f52d113d9c363 \ + --hash=sha256:5fc48998000cbc39ec0d5311312dda93ecf92b39aaf184c5e817d5d440b29624 \ + --hash=sha256:60a78b694c9aee2a0f1aaeaa7d101cf713e92e8423a941d2897f4fa37908dab9 \ + --hash=sha256:64548cde61b692dc0dc379f4b5f59a2f582c2ebe7890d09c1ae3b9e66fa015b7 \ + --hash=sha256:681dc2451d6d846794a828c16c22dc452d924e9f700a485b7ecb887a30aad1fd \ + --hash=sha256:6b1977c4ea97ce5eb7755a78fae68d87e4102e4aaf54985e8b56806849cc06a3 \ + --hash=sha256:6cfa7fe54fd4d1f47130017351a959fe5804bda7a0bc7e07a2cdbc3fdd28d34f \ + --hash=sha256:738f08021b3142c2918c03692608baed43bc51144c29e35807682f8070ee2a3a \ + --hash=sha256:747328be0c5b7075cde86a0e09d7a9196029800ba75a1689332348e998fb85c0 \ + --hash=sha256:758509ea3f1eba2a57558e7e98f4659d0ea7670bff49673b0dde18a3c7e6c0eb \ + --hash=sha256:785ae29c1f5c6e7c2cde2c7c0e148147f4503da3abc5d44d482068da5322fd9e \ + --hash=sha256:7aae78ab5e3206181780e56912d1b9bb9f90a7249ce12f0e8bf531d0462dd0fc \ + --hash=sha256:7b02679a0d783bdae30d443025b94465d8c3dc512f32f5b5031f93f57ac32071 \ + --hash=sha256:7e2f3edca35664499fbb36e4770650c4bd4a08abc1f4458eab9df4ec56389730 \ + --hash=sha256:7e6bad1cd94f6764e1e21950542f818a09316645337fd5ab9a7acc45d99a8f35 \ + --hash=sha256:81fd938344fecb9373ba1b155968c8a329491d2ce38e7ddb76f30ffb938f12dc \ + --hash=sha256:82210adabbc331dbb65d7868b105185464ef13f56f7f76688565ad79f648b0fe \ + --hash=sha256:89815a22daf9c51884fb5dbe4f1ef65ee6a146e0b6a8df05f753e2e4a9359bf4 \ + --hash=sha256:8f1125e6bbf2f1657d9a2f3ccc4a2c9b0c8b176965bb565dd4d86be67eddb4b6 \ + --hash=sha256:8f4bb453f408137d7581be309b2fbc6868a80e7ef60c88e689078ee3a296ae71 \ + --hash=sha256:924817ab3141aca17893386ee13261f1d100d1ef410d70afe4389f2359fea4f0 \ + --hash=sha256:93c2af9e01e0ef80d95ae3c720be101227edae5f2fe7e3dc63d8857fadfc5a1d \ + --hash=sha256:97c2b54ff6717a7a563b72627990bec60d8029df17df423f0ed37d56a17a176b \ + --hash=sha256:9be2f15e53ce4e83cc08adc29b26fb5978db62ef2a366fbdf716c8a6c8901040 \ + --hash=sha256:9e2c6f77b9ad48ce5603b83b7da9ee3e36b3ab425353f695cba13200c5d96596 \ + --hash=sha256:a28f2612ab566b17f3698b0da021ff9960610301607c9a5e8eaca62f5e1c350a \ + --hash=sha256:a355d99c4c0d8e5b770313b8b247411ed40949ca44e33e46a4789b9293a907ee \ + --hash=sha256:a3b4350b13cc0e6f5bec8fa7caf29a8fb8cdc051a3bae45cfbfd7ce64f009965 \ + --hash=sha256:aaab0e307e344cb28d800957ef3ec16605146ef0e59e059a60a176d19543d1b7 \ + --hash=sha256:ac1e7817fd0ed3d14fd7c5df91daed84c48e4c2a11ee99c0547f9f62fdae13da \ + --hash=sha256:adfab487facf03f0d0857b8710cf82d0704a309d8ffc33b03d9302b4c64e91a9 \ + --hash=sha256:b6d7ab1f01aa753188605b09a51faa44a3327400b00b8cce424c71910fc0a128 \ + --hash=sha256:bacdb58d9939d95cc557b4dbaa86527c9db2ac1ed76a18bc8d26f6dc8647d851 \ + --hash=sha256:be46a14693955b3bd96014ccbdb8339ee8c9346fbe11c1b78901b55125f14c73 \ + --hash=sha256:bf512a71a23504ed08103a13c941f763db13fb11177beb3d9244c98c29fb4a61 \ + --hash=sha256:c00e5c884f528c9932d278d5c9cbbea38a6b81eb62c02e06ae53751a83a4d52b \ + --hash=sha256:c25d9e338d5bed46c1632f851babf3d13c78f49a225462017cf5e11e845c5891 \ + --hash=sha256:c336d61d2fe74a3195edc1646d53ff1cddd3a9600b09fa6ab75e5514ba4862a7 \ + --hash=sha256:cc3656283d11540ab0ea01978378e73e10002145117055e03722417aeab30994 \ + --hash=sha256:cf450f498c30af55551ba4f66b9123b7185362ec8b625a773b3d39aa1a717583 \ + --hash=sha256:d0ee06b5b5291f609ddb37b9750985b27bc567791bc87c76a569b3feed8481ac \ + --hash=sha256:d480de377f5b687b6b1bc0c0407426da556e2a757633cc7e4d2e1a057aa688f3 \ + --hash=sha256:d56bc4011975f7460bea7b33e1ff425d2f1adf419935ff6707273c77f8a4ada6 \ + --hash=sha256:dd3c41254ee98604b08bd5b3af5bf0a89740d4ee0711de95b65166bf44091921 \ + --hash=sha256:e0d138c7ae532908cbb342162b2611dbd4d90c941cd25ab82084aaf71d2c0bd0 \ + --hash=sha256:e11769a1dbda4da7b00a76cfffa67aa47cfa66921d2724539eee4b9ede780b79 \ + --hash=sha256:e3f0a41487fd5fad7e760b9e8a90e251e27c2816fbc2cff36a22a0e6bcbbd9dd \ + --hash=sha256:e692aa2d1d604e6ca12d35e51fdc36f4cda6345e28e36374579f7ef3611b3012 \ + --hash=sha256:e70a57ecf89a0f64c24e37f38d3fe217a58169d2fe6ed6d70554964042474023 \ + --hash=sha256:e96baa6820280077a78244b2e06e416480ed859bbd8e5d641cf5742919d8beb4 \ + --hash=sha256:eb5656019db7c4deacf0c1a55a898c5bb8f989be904597fcb5232a2f4828fa05 \ + --hash=sha256:eca45e982fa074090057132e30585a7e8674e9e885d402eae85633e9f449ce6c \ + --hash=sha256:f0af2bd2bc204fa27f3d6711d0f360e6b8c684a035206257a81673ab924aa11e \ + --hash=sha256:f7cdf7f26c2286ffb02e46d7bac56c94655540b26347673bea15fa52a6af17e9 \ + --hash=sha256:fd1a720332ea335ceb544cf0a03f81df92abd4bb887679fd1e460976b0e6214b \ + --hash=sha256:ff8baf1f8d3f4b6b7257fcb75a501f2a5499d0dda57645baa09d4d0d34b19444 # via mypy locket==1.0.0 \ --hash=sha256:5c0d4c052a8bbbf750e056a8e65ccd309086f4f0f18a2eac306a8dfa4112a632 \ @@ -1461,9 +1471,9 @@ markupsafe==3.0.3 \ --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \ --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50 # via jinja2 -mcp==1.26.0 \ - --hash=sha256:904a21c33c25aa98ddbeb47273033c435e595bbacfdb177f4bd87f6dceebe1ca \ - --hash=sha256:db6e2ef491eecc1a0d93711a76f28dec2e05999f93afd48795da1c1137142c66 +mcp==1.27.0 \ + --hash=sha256:5ce1fa81614958e267b21fb2aa34e0aea8e2c6ede60d52aba45fd47246b4d741 \ + --hash=sha256:d3dc35a7eec0d458c1da4976a48f982097ddaab87e278c5511d5a4a56e852b83 # via fastapi-mcp mdurl==0.1.2 \ --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ @@ -1479,128 +1489,114 @@ meson-python==0.15.0 \ --hash=sha256:3ae38253ff02b2e947a05e362a2eaf5a9a09d133c5666b4123399ee5fbf2e591 \ --hash=sha256:fddb73eecd49e89c1c41c87937cd89c2d0b65a1c63ba28238681d4bd9484d26f # via feast (pyproject.toml) -mmh3==5.2.0 \ - --hash=sha256:03e08c6ebaf666ec1e3d6ea657a2d363bb01effd1a9acfe41f9197decaef0051 \ - --hash=sha256:097e13c8b8a66c5753c6968b7640faefe85d8e38992703c1f666eda6ef4c3762 \ - --hash=sha256:0b898cecff57442724a0f52bf42c2de42de63083a91008fb452887e372f9c328 \ - --hash=sha256:10983c10f5c77683bd845751905ba535ec47409874acc759d5ce3ff7ef34398a \ - --hash=sha256:11730eeb16dfcf9674fdea9bb6b8e6dd9b40813b7eb839bc35113649eef38aeb \ - --hash=sha256:127c95336f2a98c51e7682341ab7cb0be3adb9df0819ab8505a726ed1801876d \ - --hash=sha256:12da42c0a55c9d86ab566395324213c319c73ecb0c239fad4726324212b9441c \ - --hash=sha256:132dd943451a7c7546978863d2f5a64977928410782e1a87d583cb60eb89e667 \ - --hash=sha256:1556e31e4bd0ac0c17eaf220be17a09c171d7396919c3794274cb3415a9d3646 \ - --hash=sha256:1a5f4d2e59d6bba8ef01b013c472741835ad961e7c28f50c82b27c57748744a4 \ - --hash=sha256:1ba55d6ca32eeef8b2625e1e4bfc3b3db52bc63014bd7e5df8cc11bf2b036b12 \ - --hash=sha256:1efc8fec8478e9243a78bb993422cf79f8ff85cb4cf6b79647480a31e0d950a8 \ - --hash=sha256:1f8d8b627799f4e2fcc7c034fed8f5f24dc7724ff52f69838a3d6d15f1ad4765 \ - --hash=sha256:1fae471339ae1b9c641f19cf46dfe6ffd7f64b1fba7c4333b99fa3dd7f21ae0a \ - --hash=sha256:1fdb36b940e9261aff0b5177c5b74a36936b902f473180f6c15bde26143681a9 \ - --hash=sha256:2421b9d665a0b1ad724ec7332fb5a98d075f50bc51a6ff854f3a1882bd650d49 \ - --hash=sha256:29c2b9ce61886809d0492a274a5a53047742dea0f703f9c4d5d223c3ea6377d3 \ - --hash=sha256:2c9da0d568569cc87315cb063486d761e38458b8ad513fedd3dc9263e1b81bcd \ - --hash=sha256:2ebfc46b39168ab1cd44670a32ea5489bcbc74a25795c61b6d888c5c2cf654ed \ - --hash=sha256:3193752fc05ea72366c2b63ff24b9a190f422e32d75fdeae71087c08fff26115 \ - --hash=sha256:33576136c06b46a7046b6d83a3d75fbca7d25f84cec743f1ae156362608dc6d2 \ - --hash=sha256:37a358cc881fe796e099c1db6ce07ff757f088827b4e8467ac52b7a7ffdca647 \ - --hash=sha256:382a6bb3f8c6532ea084e7acc5be6ae0c6effa529240836d59352398f002e3fc \ - --hash=sha256:384eda9361a7bf83a85e09447e1feafe081034af9dd428893701b959230d84be \ - --hash=sha256:38d899a156549da8ef6a9f1d6f7ef231228d29f8f69bce2ee12f5fba6d6fd7c5 \ - --hash=sha256:3bc244802ccab5220008cb712ca1508cb6a12f0eb64ad62997156410579a1770 \ - --hash=sha256:3c6041fd9d5fb5fcac57d5c80f521a36b74aea06b8566431c63e4ffc49aced51 \ - --hash=sha256:3ca975c51c5028947bbcfc24966517aac06a01d6c921e30f7c5383c195f87991 \ - --hash=sha256:3d6bfd9662a20c054bc216f861fa330c2dac7c81e7fb8307b5e32ab5b9b4d2e0 \ - --hash=sha256:419005f84ba1cab47a77465a2a843562dadadd6671b8758bf179d82a15ca63eb \ - --hash=sha256:45b590e31bc552c6f8e2150ff1ad0c28dd151e9f87589e7eaf508fbdd8e8e908 \ - --hash=sha256:49037d417419863b222ae47ee562b2de9c3416add0a45c8d7f4e864be8dc4f89 \ - --hash=sha256:4a5f5536b1cbfa72318ab3bfc8a8188b949260baed186b75f0abc75b95d8c051 \ - --hash=sha256:582f9dbeefe15c32a5fa528b79b088b599a1dfe290a4436351c6090f90ddebb8 \ - --hash=sha256:58477cf9ef16664d1ce2b038f87d2dc96d70fe50733a34a7f07da6c9a5e3538c \ - --hash=sha256:58981d6ea9646dbbf9e59a30890cbf9f610df0e4a57dbfe09215116fd90b0093 \ - --hash=sha256:5a5dba98e514fb26241868f6eb90a7f7ca0e039aed779342965ce24ea32ba513 \ - --hash=sha256:5b0b58215befe0f0e120b828f7645e97719bbba9f23b69e268ed0ac7adde8645 \ - --hash=sha256:61ac226af521a572700f863d6ecddc6ece97220ce7174e311948ff8c8919a363 \ - --hash=sha256:63830f846797187c5d3e2dae50f0848fdc86032f5bfdc58ae352f02f857e9025 \ - --hash=sha256:69fc339d7202bea69ef9bd7c39bfdf9fdabc8e6822a01eba62fb43233c1b3932 \ - --hash=sha256:6d541038b3fc360ec538fc116de87462627944765a6750308118f8b509a8eec7 \ - --hash=sha256:6ecb4e750d712abde046858ee6992b65c93f1f71b397fce7975c3860c07365d2 \ - --hash=sha256:72d80005b7634a3a2220f81fbeb94775ebd12794623bb2e1451701ea732b4aa3 \ - --hash=sha256:7303aab41e97adcf010a09efd8f1403e719e59b7705d5e3cfed3dd7571589290 \ - --hash=sha256:7434a27754049144539d2099a6d2da5d88b8bdeedf935180bf42ad59b3607aa3 \ - --hash=sha256:746a5ee71c6d1103d9b560fa147881b5e68fd35da56e54e03d5acefad0e7c055 \ - --hash=sha256:7733ec52296fc1ba22e9b90a245c821adbb943e98c91d8a330a2254612726106 \ - --hash=sha256:7901c893e704ee3c65f92d39b951f8f34ccf8e8566768c58103fb10e55afb8c1 \ - --hash=sha256:7aa18cdb58983ee660c9c400b46272e14fa253c675ed963d3812487f8ca42037 \ - --hash=sha256:7b986d506a8e8ea345791897ba5d8ba0d9d8820cd4fc3e52dbe6de19388de2e7 \ - --hash=sha256:7bbb0df897944b5ec830f3ad883e32c5a7375370a521565f5fe24443bfb2c4f7 \ - --hash=sha256:7c7f0b342fd06044bedd0b6e72177ddc0076f54fd89ee239447f8b271d919d9b \ - --hash=sha256:7e5634565367b6d98dc4aa2983703526ef556b3688ba3065edb4b9b90ede1c54 \ - --hash=sha256:7fddccd4113e7b736706e17a239a696332360cbaddf25ae75b57ba1acce65081 \ - --hash=sha256:81c504ad11c588c8629536b032940f2a359dda3b6cbfd4ad8f74cb24dcd1b0bc \ - --hash=sha256:81df0dae22cd0da87f1c978602750f33d17fb3d21fb0f326c89dc89834fea79b \ - --hash=sha256:86d1be5d63232e6eb93c50881aea55ff06eb86d8e08f9b5417c8c9b10db9db96 \ - --hash=sha256:8b0c53fe0994beade1ad7c0f13bd6fec980a0664bfbe5a6a7d64500b9ab76772 \ - --hash=sha256:8ebf241072cf2777a492d0e09252f8cc2b3edd07dfdb9404b9757bffeb4f2cee \ - --hash=sha256:931d47e08c9c8a67bf75d82f0ada8399eac18b03388818b62bfa42882d571d72 \ - --hash=sha256:932a6eec1d2e2c3c9e630d10f7128d80e70e2d47fe6b8c7ea5e1afbd98733e65 \ - --hash=sha256:941603bfd75a46023807511c1ac2f1b0f39cccc393c15039969806063b27e6db \ - --hash=sha256:956127e663d05edbeec54df38885d943dfa27406594c411139690485128525de \ - --hash=sha256:96f1e1ac44cbb42bcc406e509f70c9af42c594e72ccc7b1257f97554204445f0 \ - --hash=sha256:99bb6a4d809aa4e528ddfe2c85dd5239b78b9dd14be62cca0329db78505e7b50 \ - --hash=sha256:9f64bf06f4bf623325fda3a6d02d36cd69199b9ace99b04bb2d7fd9f89688504 \ - --hash=sha256:a094319ec0db52a04af9fdc391b4d39a1bc72bc8424b47c4411afb05413a44b5 \ - --hash=sha256:a367d4741ac0103f8198c82f429bccb9359f543ca542b06a51f4f0332e8de279 \ - --hash=sha256:a7c0c7845566b9686480e6a7e9044db4afb60038d5fabd19227443f0104eeee4 \ - --hash=sha256:aa6e5d31fdc5ed9e3e95f9873508615a778fe9b523d52c17fc770a3eb39ab6e4 \ - --hash=sha256:ae9d032488fcec32d22be6542d1a836f00247f40f320844dbb361393b5b22773 \ - --hash=sha256:b0271ac12415afd3171ab9a3c7cbfc71dee2c68760a7dc9d05bf8ed6ddfa3a7a \ - --hash=sha256:b0d753ad566c721faa33db7e2e0eddd74b224cdd3eaf8481d76c926603c7a00e \ - --hash=sha256:b29044e1ffdb84fe164d0a7ea05c7316afea93c00f8ed9449cf357c36fc4f814 \ - --hash=sha256:b5995088dd7023d2d9f310a0c67de5a2b2e06a570ecfd00f9ff4ab94a67cde43 \ - --hash=sha256:b5f317a727bba0e633a12e71228bc6a4acb4f471a98b1c003163b917311ea9a9 \ - --hash=sha256:b9a87025121d1c448f24f27ff53a5fe7b6ef980574b4a4f11acaabe702420d63 \ - --hash=sha256:bb0fdc451fb6d86d81ab8f23d881b8d6e37fc373a2deae1c02d27002d2ad7a05 \ - --hash=sha256:bb4fe46bdc6104fbc28db7a6bacb115ee6368ff993366bbd8a2a7f0076e6f0c0 \ - --hash=sha256:bc44fc2b886243d7c0d8daeb37864e16f232e5b56aaec27cc781d848264cfd28 \ - --hash=sha256:bdde97310d59604f2a9119322f61b31546748499a21b44f6715e8ced9308a6c5 \ - --hash=sha256:be1374df449465c9f2500e62eee73a39db62152a8bdfbe12ec5b5c1cd451344d \ - --hash=sha256:be7d3dca9358e01dab1bad881fb2b4e8730cec58d36dd44482bc068bfcd3bc65 \ - --hash=sha256:bf7bee43e17e81671c447e9c83499f53d99bf440bc6d9dc26a841e21acfbe094 \ - --hash=sha256:c3dca4cb5b946ee91b3d6bb700d137b1cd85c20827f89fdf9c16258253489044 \ - --hash=sha256:c3f563e8901960e2eaa64c8e8821895818acabeb41c96f2efbb936f65dbe486c \ - --hash=sha256:c463d7c1c4cfc9d751efeaadd936bbba07b5b0ed81a012b3a9f5a12f0872bd6e \ - --hash=sha256:c4a2f3d83879e3de2eb8cbf562e71563a8ed15ee9b9c2e77ca5d9f73072ac15c \ - --hash=sha256:c5584061fd3da584659b13587f26c6cad25a096246a481636d64375d0c1f6c07 \ - --hash=sha256:c677d78887244bf3095020b73c42b505b700f801c690f8eaa90ad12d3179612f \ - --hash=sha256:c903e71fd8debb35ad2a4184c1316b3cb22f64ce517b4e6747f25b0a34e41266 \ - --hash=sha256:c9ff37ba9f15637e424c2ab57a1a590c52897c845b768e4e0a4958084ec87f22 \ - --hash=sha256:cadc16e8ea64b5d9a47363013e2bea469e121e6e7cb416a7593aeb24f2ad122e \ - --hash=sha256:cedac4f4054b8f7859e5aed41aaa31ad03fce6851901a7fdc2af0275ac533c10 \ - --hash=sha256:d22c9dcafed659fadc605538946c041722b6d1104fe619dbf5cc73b3c8a0ded8 \ - --hash=sha256:d765058da196f68dc721116cab335e696e87e76720e6ef8ee5a24801af65e63d \ - --hash=sha256:d86651fa45799530885ba4dab3d21144486ed15285e8784181a0ab37a4552384 \ - --hash=sha256:dd966df3489ec13848d6c6303429bbace94a153f43d1ae2a55115fd36fd5ca5d \ - --hash=sha256:ddc63328889bcaee77b743309e5c7d2d52cee0d7d577837c91b6e7cc9e755e0b \ - --hash=sha256:dfbead5575f6470c17e955b94f92d62a03dfc3d07f2e6f817d9b93dc211a1515 \ - --hash=sha256:e0f3ed828d709f5b82d8bfe14f8856120718ec4bd44a5b26102c3030a1e12501 \ - --hash=sha256:e1861fb6b1d0453ed7293200139c0a9011eeb1376632e048e3766945b13313c5 \ - --hash=sha256:e5015f0bb6eb50008bed2d4b1ce0f2a294698a926111e4bb202c0987b4f89078 \ - --hash=sha256:e651e17bfde5840e9e4174b01e9e080ce49277b70d424308b36a7969d0d1af73 \ - --hash=sha256:e7884931fe5e788163e7b3c511614130c2c59feffdc21112290a194487efb2e9 \ - --hash=sha256:e79c00eba78f7258e5b354eccd4d7907d60317ced924ea4a5f2e9d83f5453065 \ - --hash=sha256:e912b19cf2378f2967d0c08e86ff4c6c360129887f678e27e4dde970d21b3f4d \ - --hash=sha256:e9a011469b47b752e7d20de296bb34591cdfcbe76c99c2e863ceaa2aa61113d2 \ - --hash=sha256:eb756caf8975882630ce4e9fbbeb9d3401242a72528230422c9ab3a0d278e60c \ - --hash=sha256:eba01ec3bd4a49b9ac5ca2bc6a73ff5f3af53374b8556fcc2966dd2af9eb7779 \ - --hash=sha256:ecbfc0437ddfdced5e7822d1ce4855c9c64f46819d0fdc4482c53f56c707b935 \ - --hash=sha256:eed4bba7ff8a0d37106ba931ab03bdd3915fbb025bcf4e1f0aa02bc8114960c5 \ - --hash=sha256:f35727c5118aba95f0397e18a1a5b8405425581bfe53e821f0fb444cbdc2bc9b \ - --hash=sha256:f698733a8a494466432d611a8f0d1e026f5286dee051beea4b3c3146817e35d5 \ - --hash=sha256:f7f9034c7cf05ddfaac8d7a2e63a3c97a840d4615d0a0e65ba8bdf6f8576e3be \ - --hash=sha256:fa0c966ee727aad5406d516375593c5f058c766b21236ab8985693934bb5085b \ - --hash=sha256:fc9c5f280438cf1c1a8f9abb87dc8ce9630a964120cfb5dd50d1e7ce79690c7a \ - --hash=sha256:fd6e6c3d90660d085f7e73710eab6f5545d4854b81b0135a3526e797009dbda3 \ - --hash=sha256:fdfd3fb739f4e22746e13ad7ba0c6eedf5f454b18d11249724a388868e308ee4 \ - --hash=sha256:ff3d50dc3fe8a98059f99b445dfb62792b5d006c5e0b8f03c6de2813b8376110 +mmh3==5.2.1 \ + --hash=sha256:022aa1a528604e6c83d0a7705fdef0b5355d897a9e0fa3a8d26709ceaa06965d \ + --hash=sha256:0634581290e6714c068f4aa24020acf7880927d1f0084fa753d9799ae9610082 \ + --hash=sha256:08043f7cb1fb9467c3fbbbaea7896986e7fbc81f4d3fd9289a73d9110ab6207a \ + --hash=sha256:0a3984146e414684a6be2862d84fcb1035f4984851cb81b26d933bab6119bf00 \ + --hash=sha256:0bbc17250b10d3466875a40a52520a6bac3c02334ca709207648abd3c223ed5c \ + --hash=sha256:0cc21533878e5586b80d74c281d7f8da7932bc8ace50b8d5f6dbf7e3935f63f1 \ + --hash=sha256:0d0b7e803191db5f714d264044e06189c8ccd3219e936cc184f07106bd17fd7b \ + --hash=sha256:113f78e7463a36dbbcea05bfe688efd7fa759d0f0c56e73c974d60dcfec3dfcc \ + --hash=sha256:169e0d178cb59314456ab30772429a802b25d13227088085b0d49b9fe1533104 \ + --hash=sha256:17fbb47f0885ace8327ce1235d0416dc86a211dcd8cc1e703f41523be32cfec8 \ + --hash=sha256:19bbd3b841174ae6ed588536ab5e1b1fe83d046e668602c20266547298d939a9 \ + --hash=sha256:1d9f9a3ce559a5267014b04b82956993270f63ec91765e13e9fd73daf2d2738e \ + --hash=sha256:1e4ecee40ba19e6975e1120829796770325841c2f153c0e9aecca927194c6a2a \ + --hash=sha256:22b0f9971ec4e07e8223f2beebe96a6cfc779d940b6f27d26604040dd74d3a44 \ + --hash=sha256:26fb5b9c3946bf7f1daed7b37e0c03898a6f062149127570f8ede346390a0825 \ + --hash=sha256:2778fed822d7db23ac5008b181441af0c869455b2e7d001f4019636ac31b6fe4 \ + --hash=sha256:28cfab66577000b9505a0d068c731aee7ca85cd26d4d63881fab17857e0fe1fb \ + --hash=sha256:29bc3973676ae334412efdd367fcd11d036b7be3efc1ce2407ef8676dabfeb82 \ + --hash=sha256:2bd9f19f7f1fcebd74e830f4af0f28adad4975d40d80620be19ffb2b2af56c9f \ + --hash=sha256:2d5d542bf2abd0fd0361e8017d03f7cb5786214ceb4a40eef1539d6585d93386 \ + --hash=sha256:30e4d2084df019880d55f6f7bea35328d9b464ebee090baa372c096dc77556fb \ + --hash=sha256:3619473a0e0d329fd4aec8075628f8f616be2da41605300696206d6f36920c3d \ + --hash=sha256:368625fb01666655985391dbad3860dc0ba7c0d6b9125819f3121ee7292b4ac8 \ + --hash=sha256:3737303ca9ea0f7cb83028781148fcda4f1dac7821db0c47672971dabcf63593 \ + --hash=sha256:3a9fed49c6ce4ed7e73f13182760c65c816da006debe67f37635580dfb0fae00 \ + --hash=sha256:3c38d142c706201db5b2345166eeef1e7740e3e2422b470b8ba5c8727a9b4c7a \ + --hash=sha256:3cb61db880ec11e984348227b333259994c2c85caa775eb7875decb3768db890 \ + --hash=sha256:3d74a03fb57757ece25aa4b3c1c60157a1cece37a020542785f942e2f827eed5 \ + --hash=sha256:3f796b535008708846044c43302719c6956f39ca2d93f2edda5319e79a29efbb \ + --hash=sha256:41105377f6282e8297f182e393a79cfffd521dde37ace52b106373bdcd9ca5cb \ + --hash=sha256:41aac7002a749f08727cb91babff1daf8deac317c0b1f317adc69be0e6c375d1 \ + --hash=sha256:44983e45310ee5b9f73397350251cdf6e63a466406a105f1d16cb5baa659270b \ + --hash=sha256:4cbbde66f1183db040daede83dd86c06d663c5bb2af6de1142b7c8c37923dd74 \ + --hash=sha256:4eda76074cfca2787c8cf1bec603eaebdddd8b061ad5502f85cddae998d54f00 \ + --hash=sha256:4fc6cd65dc4d2fdb2625e288939a3566e36127a84811a4913f02f3d5931da52d \ + --hash=sha256:50885073e2909251d4718634a191c49ae5f527e5e1736d738e365c3e8be8f22b \ + --hash=sha256:5174a697ce042fa77c407e05efe41e03aa56dae9ec67388055820fb48cf4c3ba \ + --hash=sha256:54b64fb2433bc71488e7a449603bf8bd31fbcf9cb56fbe1eb6d459e90b86c37b \ + --hash=sha256:54fe8518abe06a4c3852754bfd498b30cc58e667f376c513eac89a244ce781a4 \ + --hash=sha256:55dbbd8ffbc40d1697d5e2d0375b08599dae8746b0b08dea05eee4ce81648fac \ + --hash=sha256:57b52603e89355ff318025dd55158f6e71396c0f1f609d548e9ea9c94cc6ce0a \ + --hash=sha256:58370d05d033ee97224c81263af123dea3d931025030fd34b61227a768a8858a \ + --hash=sha256:5d87a3584093e1a89987e3d36d82c98d9621b2cb944e22a420aa1401e096758f \ + --hash=sha256:623f938f6a039536cc02b7582a07a080f13fdfd48f87e63201d92d7e34d09a18 \ + --hash=sha256:62815d2c67f2dd1be76a253d88af4e1da19aeaa1820146dec52cf8bee2958b16 \ + --hash=sha256:6290289fa5fb4c70fd7f72016e03633d60388185483ff3b162912c81205ae2cf \ + --hash=sha256:67e41a497bac88cc1de96eeba56eeb933c39d54bc227352f8455aa87c4ca4000 \ + --hash=sha256:6c85c38a279ca9295a69b9b088a2e48aa49737bb1b34e6a9dc6297c110e8d912 \ + --hash=sha256:6f01f044112d43a20be2f13a11683666d87151542ad627fe41a18b9791d2802f \ + --hash=sha256:707151644085dd0f20fe4f4b573d28e5130c4aaa5f587e95b60989c5926653b5 \ + --hash=sha256:723b2681ed4cc07d3401bbea9c201ad4f2a4ca6ba8cddaff6789f715dd2b391e \ + --hash=sha256:72d1cc63bcc91e14933f77d51b3df899d6a07d184ec515ea7f56bff659e124d7 \ + --hash=sha256:7374d6e3ef72afe49697ecd683f3da12f4fc06af2d75433d0580c6746d2fa025 \ + --hash=sha256:7501e9be34cb21e72fcfe672aafd0eee65c16ba2afa9dcb5500a587d3a0580f0 \ + --hash=sha256:76219cd1eefb9bf4af7856e3ae563d15158efa145c0aab01e9933051a1954045 \ + --hash=sha256:7aec798c2b01aaa65a55f1124f3405804184373abb318a3091325aece235f67c \ + --hash=sha256:7be6dfb49e48fd0a7d91ff758a2b51336f1cd21f9d44b20f6801f072bd080cdd \ + --hash=sha256:7e4e1f580033335c6f76d1e0d6b56baf009d1a64d6a4816347e4271ba951f46d \ + --hash=sha256:7e8ec5f606e0809426d2440e0683509fb605a8820a21ebd120dcdba61b74ef7f \ + --hash=sha256:7f196cd7910d71e9d9860da0ff7a77f64d22c1ad931f1dd18559a06e03109fc0 \ + --hash=sha256:82f3802bfc4751f420d591c5c864de538b71cea117fce67e4595c2afede08a15 \ + --hash=sha256:85ffc9920ffc39c5eee1e3ac9100c913a0973996fbad5111f939bbda49204bb7 \ + --hash=sha256:8e6c219e375f6341d0959af814296372d265a8ca1af63825f65e2e87c618f006 \ + --hash=sha256:8f767ba0911602ddef289404e33835a61168314ebd3c729833db2ed685824211 \ + --hash=sha256:8ff038d52ef6aa0f309feeba00c5095c9118d0abf787e8e8454d6048db2037fc \ + --hash=sha256:915e7a2418f10bd1151b1953df06d896db9783c9cfdb9a8ee1f9b3a4331ab503 \ + --hash=sha256:92883836caf50d5255be03d988d75bc93e3f86ba247b7ca137347c323f731deb \ + --hash=sha256:960b1b3efa39872ac8b6cc3a556edd6fb90ed74f08c9c45e028f1005b26aa55d \ + --hash=sha256:9aeaf53eaa075dd63e81512522fd180097312fb2c9f476333309184285c49ce0 \ + --hash=sha256:9d8089d853c7963a8ce87fff93e2a67075c0bc08684a08ea6ad13577c38ffc38 \ + --hash=sha256:a4130d0b9ce5fad6af07421b1aecc7e079519f70d6c05729ab871794eded8617 \ + --hash=sha256:a482ac121de6973897c92c2f31defc6bafb11c83825109275cffce54bb64933f \ + --hash=sha256:add7ac388d1e0bf57259afbcf9ed05621a3bf11ce5ee337e7536f1e1aaf056b0 \ + --hash=sha256:b1f12bd684887a0a5d55e6363ca87056f361e45451105012d329b86ec19dbe0b \ + --hash=sha256:b3f99e1756fc48ad507b95e5d86f2fb21b3d495012ff13e6592ebac14033f166 \ + --hash=sha256:b4cce60d0223074803c9dbe0721ad3fa51dafe7d462fee4b656a1aa01ee07518 \ + --hash=sha256:baeb47635cb33375dee4924cd93d7f5dcaa786c740b08423b0209b824a1ee728 \ + --hash=sha256:bbea5b775f0ac84945191fb83f845a6fd9a21a03ea7f2e187defac7e401616ad \ + --hash=sha256:bbfcb95d9a744e6e2827dfc66ad10e1020e0cac255eb7f85652832d5a264c2fc \ + --hash=sha256:bd6e7d363aa93bd3421b30b6af97064daf47bc96005bddba67c5ffbc6df426b8 \ + --hash=sha256:be77c402d5e882b6fbacfd90823f13da8e0a69658405a39a569c6b58fdb17b03 \ + --hash=sha256:c302245fd6c33d96bd169c7ccf2513c20f4c1e417c07ce9dce107c8bc3f8411f \ + --hash=sha256:c88653877aeb514c089d1b3d473451677b8b9a6d1497dbddf1ae7934518b06d2 \ + --hash=sha256:cae6383181f1e345317742d2ddd88f9e7d2682fa4c9432e3a74e47d92dce0229 \ + --hash=sha256:cd471ede0d802dd936b6fab28188302b2d497f68436025857ca72cd3810423fe \ + --hash=sha256:d106493a60dcb4aef35a0fac85105e150a11cf8bc2b0d388f5a33272d756c966 \ + --hash=sha256:d30b650595fdbe32366b94cb14f30bb2b625e512bd4e1df00611f99dc5c27fd4 \ + --hash=sha256:d51fde50a77f81330523562e3c2734ffdca9c4c9e9d355478117905e1cfe16c6 \ + --hash=sha256:d57dea657357230cc780e13920d7fa7db059d58fe721c80020f94476da4ca0a1 \ + --hash=sha256:d771f085fcdf4035786adfb1d8db026df1eb4b41dac1c3d070d1e49512843227 \ + --hash=sha256:dae0f0bd7d30c0ad61b9a504e8e272cb8391eed3f1587edf933f4f6b33437450 \ + --hash=sha256:db0562c5f71d18596dcd45e854cf2eeba27d7543e1a3acdafb7eef728f7fe85d \ + --hash=sha256:dfd51b4c56b673dfbc43d7d27ef857dd91124801e2806c69bb45585ce0fa019b \ + --hash=sha256:e080c0637aea036f35507e803a4778f119a9b436617694ae1c5c366805f1e997 \ + --hash=sha256:e48d4dbe0f88e53081da605ae68644e5182752803bbc2beb228cca7f1c4454d6 \ + --hash=sha256:e8b4b5580280b9265af3e0409974fb79c64cf7523632d03fbf11df18f8b0181e \ + --hash=sha256:e8b5378de2b139c3a830f0209c1e91f7705919a4b3e563a10955104f5097a70a \ + --hash=sha256:e904f2417f0d6f6d514f3f8b836416c360f306ddaee1f84de8eef1e722d212e5 \ + --hash=sha256:eee884572b06bbe8a2b54f424dbd996139442cf83c76478e1ec162512e0dd2c7 \ + --hash=sha256:f1fbb0a99125b1287c6d9747f937dc66621426836d1a2d50d05aecfc81911b57 \ + --hash=sha256:f40a95186a72fa0b67d15fef0f157bfcda00b4f59c8a07cbe5530d41ac35d105 \ + --hash=sha256:f6e0bfe77d238308839699944164b96a2eeccaf55f2af400f54dc20669d8d5f2 \ + --hash=sha256:f963eafc0a77a6c0562397da004f5876a9bcf7265a7bcc3205e29636bc4a1312 \ + --hash=sha256:fb9d44c25244e11c8be3f12c938ca8ba8404620ef8092245d2093c6ab3df260f \ + --hash=sha256:fc78739b5ec6e4fb02301984a3d442a91406e7700efbe305071e7fd1c78278f2 \ + --hash=sha256:fceef7fe67c81e1585198215e42ad3fdba3a25644beda8fbdaf85f4d7b93175a \ + --hash=sha256:fd96476f04db5ceba1cfa0f21228f67c1f7402296f0e73fee3513aa680ad237b # via feast (pyproject.toml) multidict==6.7.1 \ --hash=sha256:026d264228bcd637d4e060844e39cdc60f86c479e463d49075dedc21b18fbbe0 \ @@ -1753,45 +1749,51 @@ multidict==6.7.1 \ # aiobotocore # aiohttp # yarl -mypy==1.19.1 \ - --hash=sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd \ - --hash=sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b \ - --hash=sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1 \ - --hash=sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba \ - --hash=sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b \ - --hash=sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045 \ - --hash=sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac \ - --hash=sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6 \ - --hash=sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a \ - --hash=sha256:409088884802d511ee52ca067707b90c883426bd95514e8cfda8281dc2effe24 \ - --hash=sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957 \ - --hash=sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042 \ - --hash=sha256:4f28f99c824ecebcdaa2e55d82953e38ff60ee5ec938476796636b86afa3956e \ - --hash=sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec \ - --hash=sha256:7bcfc336a03a1aaa26dfce9fff3e287a3ba99872a157561cbfcebe67c13308e3 \ - --hash=sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718 \ - --hash=sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f \ - --hash=sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331 \ - --hash=sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1 \ - --hash=sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1 \ - --hash=sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13 \ - --hash=sha256:b13cfdd6c87fc3efb69ea4ec18ef79c74c3f98b4e5498ca9b85ab3b2c2329a67 \ - --hash=sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2 \ - --hash=sha256:b7951a701c07ea584c4fe327834b92a30825514c868b1f69c30445093fdd9d5a \ - --hash=sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b \ - --hash=sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8 \ - --hash=sha256:c608937067d2fc5a4dd1a5ce92fd9e1398691b8c5d012d66e1ddd430e9244376 \ - --hash=sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef \ - --hash=sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288 \ - --hash=sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75 \ - --hash=sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74 \ - --hash=sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250 \ - --hash=sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab \ - --hash=sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6 \ - --hash=sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247 \ - --hash=sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925 \ - --hash=sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e \ - --hash=sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e +mypy==1.20.0 \ + --hash=sha256:002b613ae19f4ac7d18b7e168ffe1cb9013b37c57f7411984abbd3b817b0a214 \ + --hash=sha256:00e047c74d3ec6e71a2eb88e9ea551a2edb90c21f993aefa9e0d2a898e0bb732 \ + --hash=sha256:02cca0761c75b42a20a2757ae58713276605eb29a08dd8a6e092aa347c4115ca \ + --hash=sha256:0ecd63f75fdd30327e4ad8b5704bd6d91fc6c1b2e029f8ee14705e1207212489 \ + --hash=sha256:0f42dfaab7ec1baff3b383ad7af562ab0de573c5f6edb44b2dab016082b89948 \ + --hash=sha256:1973868d2adbb4584a3835780b27436f06d1dc606af5be09f187aaa25be1070f \ + --hash=sha256:26c8b52627b6552f47ff11adb4e1509605f094e29815323e487fc0053ebe93d1 \ + --hash=sha256:2721f0ce49cb74a38f00c50da67cb7d36317b5eda38877a49614dc018e91c787 \ + --hash=sha256:2fcedb16d456106e545b2bfd7ef9d24e70b38ec252d2a629823a4d07ebcdb69e \ + --hash=sha256:31b5dbb55293c1bd27c0fc813a0d2bb5ceef9d65ac5afa2e58f829dab7921fd5 \ + --hash=sha256:34506397dbf40c15dc567635d18a21d33827e9ab29014fb83d292a8f4f8953b6 \ + --hash=sha256:367e5c993ba34d5054d11937d0485ad6dfc60ba760fa326c01090fc256adf15c \ + --hash=sha256:379edf079ce44ac8d2805bcf9b3dd7340d4f97aad3a5e0ebabbf9d125b84b442 \ + --hash=sha256:39362cdb4ba5f916e7976fccecaab1ba3a83e35f60fa68b64e9a70e221bb2436 \ + --hash=sha256:4525e7010b1b38334516181c5b81e16180b8e149e6684cee5a727c78186b4e3b \ + --hash=sha256:47781555a7aa5fedcc2d16bcd72e0dc83eb272c10dd657f9fb3f9cc08e2e6abb \ + --hash=sha256:49d11c6f573a5a08f77fad13faff2139f6d0730ebed2cfa9b3d2702671dd7188 \ + --hash=sha256:555493c44a4f5a1b58d611a43333e71a9981c6dbe26270377b6f8174126a0526 \ + --hash=sha256:555658c611099455b2da507582ea20d2043dfdfe7f5ad0add472b1c6238b433f \ + --hash=sha256:697f102c5c1d526bdd761a69f17c6070f9892eebcb94b1a5963d679288c09e78 \ + --hash=sha256:76a70bf840495729be47510856b978f1b0ec7d08f257ca38c9d932720bf6b43e \ + --hash=sha256:7d3243c406773185144527f83be0e0aefc7bf4601b0b2b956665608bf7c98a83 \ + --hash=sha256:931a7630bba591593dcf6e97224a21ff80fb357e7982628d25e3c618e7f598ef \ + --hash=sha256:9804c3ad27f78e54e58b32e7cb532d128b43dbfb9f3f9f06262b821a0f6bd3f5 \ + --hash=sha256:a17c5d0bdcca61ce24a35beb828a2d0d323d3fcf387d7512206888c900193367 \ + --hash=sha256:a6e0641147cbfa7e4e94efdb95c2dab1aff8cfc159ded13e07f308ddccc8c48e \ + --hash=sha256:a79c1eba7ac4209f2d850f0edd0a2f8bba88cbfdfefe6fb76a19e9d4fe5e71a2 \ + --hash=sha256:a9336b5e6712f4adaf5afc3203a99a40b379049104349d747eb3e5a3aa23ac2e \ + --hash=sha256:b20c8b0fd5877abdf402e79a3af987053de07e6fb208c18df6659f708b535134 \ + --hash=sha256:b3a49064504be59e59da664c5e149edc1f26c67c4f8e8456f6ba6aba55033018 \ + --hash=sha256:b503ab55a836136b619b5fc21c8803d810c5b87551af8600b72eecafb0059cb0 \ + --hash=sha256:bd0212976dc57a5bfeede7c219e7cd66568a32c05c9129686dd487c059c1b88a \ + --hash=sha256:c70380fe5d64010f79fb863b9081c7004dd65225d2277333c219d93a10dad4dd \ + --hash=sha256:d99f515f95fd03a90875fdb2cca12ff074aa04490db4d190905851bdf8a549a8 \ + --hash=sha256:e80cf77847d0d3e6e3111b7b25db32a7f8762fd4b9a3a72ce53fe16a2863b281 \ + --hash=sha256:eb96c84efcc33f0b5e0e04beacf00129dd963b67226b01c00b9dfc8affb464c3 \ + --hash=sha256:ebea00201737ad4391142808ed16e875add5c17f676e0912b387739f84991e13 \ + --hash=sha256:efe8d70949c3023698c3fca1e94527e7e790a361ab8116f90d11221421cd8726 \ + --hash=sha256:f13b3e41bce9d257eded794c0f12878af3129d80aacd8a3ee0dee51f3a978651 \ + --hash=sha256:f194db59657c58593a3c47c6dfd7bad4ef4ac12dbc94d01b3a95521f78177e33 \ + --hash=sha256:f49590891d2c2f8a9de15614e32e459a794bcba84693c2394291a2038bbaaa69 \ + --hash=sha256:f75ff57defcd0f1d6e006d721ccdec6c88d4f6a7816eb92f1c4890d979d9ee62 \ + --hash=sha256:f799d9db89fc00446f03281f84a221e50018fc40113a3ba9864b132895619ebe \ + --hash=sha256:f8426d4d75d68714abc17a4292d922f6ba2cfb984b72c2278c437f6dae797865 # via sqlalchemy mypy-extensions==1.1.0 \ --hash=sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505 \ @@ -1880,6 +1882,7 @@ packaging==26.0 \ # setuptools-scm # snowflake-connector-python # sphinx + # vcs-versioning pandas==2.3.3 \ --hash=sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7 \ --hash=sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593 \ @@ -1945,9 +1948,9 @@ pandas==2.3.3 \ # pandas-gbq # pymilvus # snowflake-connector-python -pandas-gbq==0.33.0 \ - --hash=sha256:499ad18a7b1917e2cc04bbd763ec37c11ecc49030348c45cebb9cbbdb7f909af \ - --hash=sha256:61357e11d73e0ae57cbff31e71fc3ed83da3d16b58b653f715b32ad760527e34 +pandas-gbq==0.34.1 \ + --hash=sha256:6bea5b85937251b976cf9db38151ea59abbff98771179183488d4614694bff67 \ + --hash=sha256:b74932c6ee35dfc81582f39c792e3a68c9ef9bee8c85f25667d9d05dfadd0daf # via google-cloud-bigquery parsy==2.2 \ --hash=sha256:5e981613d9d2d8b68012d1dd0afe928967bea2e4eefdb76c2f545af0dd02a9e7 \ @@ -1975,9 +1978,9 @@ pathspec==1.0.4 \ # hatchling # mypy # scikit-build-core -platformdirs==4.9.2 \ - --hash=sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd \ - --hash=sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291 +platformdirs==4.9.4 \ + --hash=sha256:1ec356301b7dc906d83f371c8f487070e99d3ccf9e501686456394622a01a934 \ + --hash=sha256:68a9a4619a666ea6439f2ff250c12a853cd1cbd5158d258bd824a7df6be2f868 # via snowflake-connector-python pluggy==1.6.0 \ --hash=sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3 \ @@ -2113,25 +2116,25 @@ propcache==0.4.1 \ # via # aiohttp # yarl -proto-plus==1.27.1 \ - --hash=sha256:912a7460446625b792f6448bade9e55cd4e41e6ac10e27009ef71a7f317fa147 \ - --hash=sha256:e4643061f3a4d0de092d62aa4ad09fa4756b2cbb89d4627f3985018216f9fefc +proto-plus==1.27.2 \ + --hash=sha256:6432f75893d3b9e70b9c412f1d2f03f65b11fb164b793d14ae2ca01821d22718 \ + --hash=sha256:b2adde53adadf75737c44d3dcb0104fde65250dfc83ad59168b4aa3e574b6a24 # via # google-api-core # google-cloud-bigquery-storage # google-cloud-bigtable # google-cloud-datastore -protobuf==6.33.5 \ - --hash=sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c \ - --hash=sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02 \ - --hash=sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c \ - --hash=sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd \ - --hash=sha256:8f04fa32763dcdb4973d537d6b54e615cc61108c7cb38fe59310c3192d29510a \ - --hash=sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190 \ - --hash=sha256:a3157e62729aafb8df6da2c03aa5c0937c7266c626ce11a278b6eb7963c4e37c \ - --hash=sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5 \ - --hash=sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0 \ - --hash=sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b +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) # google-api-core @@ -2244,12 +2247,10 @@ pyarrow-hotfix==0.7 \ --hash=sha256:3236f3b5f1260f0e2ac070a55c1a7b339c4bb7267839bd2015e283234e758100 \ --hash=sha256:59399cd58bdd978b2e42816a4183a55c6472d4e33d183351b6069f11ed42661d # via ibis-framework -pyasn1==0.6.2 \ - --hash=sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf \ - --hash=sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b - # via - # pyasn1-modules - # rsa +pyasn1==0.6.3 \ + --hash=sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf \ + --hash=sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde + # via pyasn1-modules pyasn1-modules==0.4.2 \ --hash=sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a \ --hash=sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6 @@ -2394,9 +2395,9 @@ pydantic-core==2.41.5 \ --hash=sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425 \ --hash=sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52 # via pydantic -pydantic-settings==2.13.0 \ - --hash=sha256:95d875514610e8595672800a5c40b073e99e4aae467fa7c8f9c263061ea2e1fe \ - --hash=sha256:d67b576fff39cd086b595441bf9c75d4193ca9c0ed643b90360694d0f1240246 +pydantic-settings==2.13.1 \ + --hash=sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025 \ + --hash=sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237 # via # fastapi-mcp # mcp @@ -2404,16 +2405,16 @@ pydata-google-auth==1.9.1 \ --hash=sha256:0a51ce41c601ca0bc69b8795bf58bedff74b4a6a007c9106c7cbcdec00eaced2 \ --hash=sha256:75ffce5d106e34b717b31844c1639ea505b7d9550dc23b96fb6c20d086b53fa3 # via pandas-gbq -pygments==2.19.2 \ - --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \ - --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b +pygments==2.20.0 \ + --hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \ + --hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176 # via # feast (pyproject.toml) # rich # sphinx -pyjwt[crypto]==2.11.0 \ - --hash=sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623 \ - --hash=sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469 +pyjwt[crypto]==2.12.1 \ + --hash=sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c \ + --hash=sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b # via # feast (pyproject.toml) # mcp @@ -2426,9 +2427,9 @@ pymysql==1.1.2 \ --hash=sha256:4961d3e165614ae65014e361811a724e2044ad3ea3739de9903ae7c21f539f03 \ --hash=sha256:e6b1d89711dd51f8f74b1631fe08f039e7d76cf67a42a323d3178f0f25762ed9 # via feast (pyproject.toml) -pyopenssl==25.3.0 \ - --hash=sha256:1fda6fc034d5e3d179d39e59c1895c9faeaf40a79de5fc4cbbfbe0d36f4a77b6 \ - --hash=sha256:c981cb0a3fd84e8602d7afc209522773b94c1c2446a3c710a75b06fe1beae329 +pyopenssl==26.0.0 \ + --hash=sha256:df94d28498848b98cc1c0ffb8ef1e71e40210d3b0a8064c9d29571ed2904bf81 \ + --hash=sha256:f293934e52936f2e3413b89c6ce36df66a0b34ae1ea3a053b8c5020ff2f513fc # via snowflake-connector-python pyproject-metadata==0.11.0 \ --hash=sha256:85bbecca8694e2c00f63b492c96921d6c228454057c88e7c352b2077fcaa4096 \ @@ -2444,9 +2445,9 @@ python-dateutil==2.9.0.post0 \ # ibis-framework # kubernetes # pandas -python-dotenv==1.2.1 \ - --hash=sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6 \ - --hash=sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61 +python-dotenv==1.2.2 \ + --hash=sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a \ + --hash=sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3 # via # pydantic-settings # pymilvus @@ -2455,9 +2456,9 @@ python-multipart==0.0.22 \ --hash=sha256:2b2cd894c83d21bf49d702499531c7bafd057d730c201782048f7945d82de155 \ --hash=sha256:7340bef99a7e0032613f56dc36027b959fd3b30a787ed62d310e951f7c3a3a58 # via mcp -pytz==2025.2 \ - --hash=sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3 \ - --hash=sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00 +pytz==2026.1.post1 \ + --hash=sha256:3378dde6a0c3d26719182142c56e60c7f9af7e968076f31aae569d72a0358ee1 \ + --hash=sha256:f2fd16142fda348286a75e1a524be810bb05d444e5a081f37f7affc635035f7a # via # pandas # snowflake-connector-python @@ -2550,9 +2551,9 @@ referencing==0.37.0 \ # via # jsonschema # jsonschema-specifications -requests==2.32.5 \ - --hash=sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6 \ - --hash=sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf +requests==2.33.1 \ + --hash=sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517 \ + --hash=sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a # via # feast (pyproject.toml) # fastapi-mcp @@ -2569,9 +2570,9 @@ requests-oauthlib==2.0.0 \ # via # google-auth-oauthlib # kubernetes -rich==14.3.2 \ - --hash=sha256:08e67c3e90884651da3239ea668222d19bea7b589149d8014a21c633420dbb69 \ - --hash=sha256:e712f11c1a562a11843306f5ed999475f09ac31ffb64281f73ab29ffdda8b3b8 +rich==14.3.3 \ + --hash=sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d \ + --hash=sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b # via # fastapi-mcp # ibis-framework @@ -2695,17 +2696,13 @@ rpds-py==0.30.0 \ # via # jsonschema # referencing -rsa==4.9.1 \ - --hash=sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762 \ - --hash=sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75 - # via google-auth s3transfer==0.13.1 \ --hash=sha256:a981aa7429be23fe6dfc13e80e4020057cbab622b08c0315288758d67cabc724 \ --hash=sha256:c3fdba22ba1bd367922f27ec8032d6a1cf5f10c934fb5d68cf60fd5a23d936cf # via boto3 -scikit-build-core==0.11.6 \ - --hash=sha256:5982ccd839735be99cfd3b92a8847c6c196692f476c215da84b79d2ad12f9f1b \ - --hash=sha256:ce6d8fe64e6b4c759ea0fb95d2f8a68f60d2df31c2989838633b8ec930736360 +scikit-build-core==0.12.2 \ + --hash=sha256:562e0bbc9de1a354c87825ccf732080268d6582a0200f648e8c4a2dcb1e3736d \ + --hash=sha256:6ea4730da400f9a998ec3287bd3ebc1d751fe45ad0a93451bead8618adbc02b1 # via feast (pyproject.toml) setuptools==80.10.2 \ --hash=sha256:8b0e9d10c784bf7d262c4e5ec5d4ec94127ce206e8738f29a437945fbc219b70 \ @@ -2716,9 +2713,9 @@ setuptools==80.10.2 \ # pydata-google-auth # pymilvus # setuptools-scm -setuptools-scm==9.2.2 \ - --hash=sha256:1c674ab4665686a0887d7e24c03ab25f24201c213e82ea689d2f3e169ef7ef57 \ - --hash=sha256:30e8f84d2ab1ba7cb0e653429b179395d0c33775d54807fc5f1dd6671801aef7 +setuptools-scm==10.0.5 \ + --hash=sha256:bbba8fe754516cdefd017f4456721775e6ef9662bd7887fb52ae26813d4838c3 \ + --hash=sha256:f611037d8aae618221503b8fa89319f073438252ae3420e01c9ceec249131a0a # via hatch-vcs shellingham==1.5.4 \ --hash=sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686 \ @@ -2734,33 +2731,32 @@ snowballstemmer==3.0.1 \ --hash=sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064 \ --hash=sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895 # via sphinx -snowflake-connector-python[pandas]==4.3.0 \ - --hash=sha256:08f5167a10d380fe66330d5b19d19bd8b4f4af27e9648e3b254e61da025646bf \ - --hash=sha256:120463ca391d9deda3bdb185104ba847e12f73c86ef411cfcf827ce49b64d1af \ - --hash=sha256:26a65c5c93d14c4d221b780fdb2f07b4dd83e848f39eabd4832778bf0e2694d4 \ - --hash=sha256:2e0f66acee330388815fb842f91a46c9cacdefdf02c816354e6adeca8c2c3f86 \ - --hash=sha256:3e2ce47485862fa14ffbf2732f0fd02aa69a7c68a50d5f6286f34ed17527cf87 \ - --hash=sha256:486d17332b9228d2e5975755b434e6a282756a447e0c6605d4e797944fa919da \ - --hash=sha256:55163c5d9b93e10d7217aabd56f776b16c0fe13774f8d5db9188824731da9586 \ - --hash=sha256:676b56eedcc268b7e25a447e736eb8bf8bcacfbc71196c94d6f45746672ee6d5 \ - --hash=sha256:726435b2769135b6282601efb2cd8fd53f7deb1ff2fb7da93d28141fa3c8b17e \ - --hash=sha256:762ffa9673465ccc630aba438d648e0b1a2452ba49669a54a60d1625f36898f3 \ - --hash=sha256:7763c0d5f8e6326ec31f8972cc806fb6d3e07b06ca59f67dfcdf02a34219bcbc \ - --hash=sha256:79cbf5e359cfc33b4c4307df1fe8f78cd5aee56f5c50b98a647fa0cd9ba82cfc \ - --hash=sha256:79f150297b39cfd2481b732554fc4d68b43c83c82eb01e670cc4051cffc089d6 \ - --hash=sha256:7c18b5021ffa6de8313f2c7f0ae6050c36bcee7cb33bb23d40a7fdf3e0a751f2 \ - --hash=sha256:9faa9280e41258fb479ec5395b6a17d3dbb316146832e436aed582b300de655e \ - --hash=sha256:ac18b37e03a29014a9c91aac10c7dbdfa11134c620c6f93dd16f4b99b6a38c2a \ - --hash=sha256:b5a8d91c3e0127360bc3de605df9d02ea4d87e4524a50bf2e7c5c4200f9abf78 \ - --hash=sha256:c1356a2c615e120f913e5235fe87ff8aadbb479ad5a5ac5c0a84881d5fbe981d \ - --hash=sha256:c6fa80373b82125552e691f47b603766ed783f3d90a5782564854aa224aee9d1 \ - --hash=sha256:ca9d22c61f4e3d171b0adad3e9211747917c3a978dfb99564307c1ceadb0f0cd \ - --hash=sha256:ce55b93120f8b429010bf39cc02e739610b6da2ccdd34fcfc0df04849d0fd9d4 \ - --hash=sha256:e3044e6a237b35f750394f199f5e3800dfeb3227c4c8562584877e814d2dc89a \ - --hash=sha256:e42dd9af46fa3ad0e61c1aa6a227357cace481916797ecb92dbb14adb61931e1 \ - --hash=sha256:e5d360d65d42dd97cf82e688a1a7f235b9bc048b4949c9c5c7052ff2783c444e \ - --hash=sha256:e96aaf23f2b021e0d2aac8ac1b541975cd1f6896d9115eefe0938114e694a562 \ - --hash=sha256:f5291c00f610b266ab8c79b1e008b3d0cb29bb5b86a0007529320921b4a3fc3c +snowflake-connector-python[pandas]==4.4.0 \ + --hash=sha256:16fdca775f7ca5ce4a973c07c434f5ab72bef5284e81a5e4ae2fb4d54d28965c \ + --hash=sha256:19d0c1ed033abae715a71b74c53010b180a5247c6924f851e4f7d0b0d58066c4 \ + --hash=sha256:2a6f6a514a10c3bb2d4554132f0b639f43d7e9fbb73fa1fae1c8a75333102686 \ + --hash=sha256:307f41326c702f6976746d2001dacf35adaf567f3f12afb3a5778fbb063c7241 \ + --hash=sha256:43e1a2f3ac51d24406d4eb0c23a8ceb9d6f5cb4854c941e5e1375d8c481e2844 \ + --hash=sha256:52efe2d6543a09807283748dd50a36ec01d52b4f342868132f8f9856b9c95a42 \ + --hash=sha256:56ff04dd9e17edc82128f412aa3776687dc94088f3d6b9144971e169952623cb \ + --hash=sha256:648f49029d699591af0f253e81c5bf60efc4411c7b0149ef074a59a038210a3b \ + --hash=sha256:693a1bef97509f09b7e6f42ea6f743d27819413c04fb3dc543b060d029871c56 \ + --hash=sha256:70d4051e2d9c87258b02672e17e21f5873e0cb49ff9705f6194ccfa25ac0d5fd \ + --hash=sha256:7c2984663a733d06c979aa6c8c1d7691621ec0d3521ef345d57c869ff2f1c4b2 \ + --hash=sha256:8304b4818d3e9de552dcfbdd0bca61bae1583e1c9794e242e58fe44bce701604 \ + --hash=sha256:85a01338d282423611f357cd5392dca2219bbda9a66b44761b11d6ae8ebf1e50 \ + --hash=sha256:96fdca994c4d9f7780e82fc7b4bd3398d856b43de3bae57d44e242ff435a2431 \ + --hash=sha256:9b1a28f843c1c0b582db7854789525d0c8aac4ea5c56e31113684e38220d0af9 \ + --hash=sha256:9fa43d330389df27024757c4f97dabddafbedc74b8bcc189b6a86e8b4d036014 \ + --hash=sha256:a088f108da4653ad1396ddb63a1c757ad614d0862c38f6f69cc77344bdcfeccb \ + --hash=sha256:b9f0ac0c00075321e1720d3876e936ee0256f54832e7463c5193a8dfa54913d5 \ + --hash=sha256:c828248214a49f77b903e05acf887d3ccb9d958b5a979f2ed3663bba1bd0f2b3 \ + --hash=sha256:d6fd334e4d8df7fcb30e6746e5ade845e82de2942268862aa8bce974ae2b86a2 \ + --hash=sha256:d8ac1659c8e588b9502f8d3d03c1ded2f274de0da9c09e62fe007cba5b46d6a5 \ + --hash=sha256:e8e7ce0e8b33aec8b1fc6741eb51dbeb54e2c3a6d282a0d459c355a85f089b08 \ + --hash=sha256:ea6e4083ebea0a814b46f029d64a2fb0ba6e7732952cd8af4406041708ce0e21 \ + --hash=sha256:f5d0e90e68a899c13fda5ca842ff77b5759b1674adf2c72702d3c2b53ca9d27b \ + --hash=sha256:fb628d5ea1999e23bfbaabce4125eb44d56605ca5634b8b1d6092ab22d555598 # via feast (pyproject.toml) sortedcontainers==2.4.0 \ --hash=sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88 \ @@ -2794,85 +2790,89 @@ sphinxcontrib-serializinghtml==2.0.0 \ --hash=sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331 \ --hash=sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d # via sphinx -sqlalchemy[mypy]==2.0.46 \ - --hash=sha256:09168817d6c19954d3b7655da6ba87fcb3a62bb575fb396a81a8b6a9fadfe8b5 \ - --hash=sha256:0cc3117db526cad3e61074100bd2867b533e2c7dc1569e95c14089735d6fb4fe \ - --hash=sha256:181903fe8c1b9082995325f1b2e84ac078b1189e2819380c2303a5f90e114a62 \ - --hash=sha256:1bc3f601f0a818d27bfe139f6766487d9c88502062a2cd3a7ee6c342e81d5047 \ - --hash=sha256:1e6199143d51e3e1168bedd98cc698397404a8f7508831b81b6a29b18b051069 \ - --hash=sha256:2347c3f0efc4de367ba00218e0ae5c4ba2306e47216ef80d6e31761ac97cb0b9 \ - --hash=sha256:261c4b1f101b4a411154f1da2b76497d73abbfc42740029205d4d01fa1052684 \ - --hash=sha256:33e462154edb9493f6c3ad2125931e273bbd0be8ae53f3ecd1c161ea9a1dd366 \ - --hash=sha256:37fee2164cf21417478b6a906adc1a91d69ae9aba8f9533e67ce882f4bb1de53 \ - --hash=sha256:3a9a72b0da8387f15d5810f1facca8f879de9b85af8c645138cba61ea147968c \ - --hash=sha256:3aac08f7546179889c62b53b18ebf1148b10244b3405569c93984b0388d016a7 \ - --hash=sha256:3c32e993bc57be6d177f7d5d31edb93f30726d798ad86ff9066d75d9bf2e0b6b \ - --hash=sha256:412f26bb4ba942d52016edc8d12fb15d91d3cd46b0047ba46e424213ad407bcb \ - --hash=sha256:42a1643dc5427b69aca967dae540a90b0fbf57eaf248f13a90ea5930e0966863 \ - --hash=sha256:4396c948d8217e83e2c202fbdcc0389cf8c93d2c1c5e60fa5c5a955eae0e64be \ - --hash=sha256:4dafb537740eef640c4d6a7c254611dca2df87eaf6d14d6a5fca9d1f4c3fc0fa \ - --hash=sha256:4f52f7291a92381e9b4de9050b0a65ce5d6a763333406861e33906b8aa4906bf \ - --hash=sha256:52fe29b3817bd191cc20bad564237c808967972c97fa683c04b28ec8979ae36f \ - --hash=sha256:56bdd261bfd0895452006d5316cbf35739c53b9bb71a170a331fa0ea560b2ada \ - --hash=sha256:585af6afe518732d9ccd3aea33af2edaae4a7aa881af5d8f6f4fe3a368699597 \ - --hash=sha256:590be24e20e2424a4c3c1b0835e9405fa3d0af5823a1a9fc02e5dff56471515f \ - --hash=sha256:64901e08c33462acc9ec3bad27fc7a5c2b6491665f2aa57564e57a4f5d7c52ad \ - --hash=sha256:6ac245604295b521de49b465bab845e3afe6916bcb2147e5929c8041b4ec0545 \ - --hash=sha256:6f827fd687fa1ba7f51699e1132129eac8db8003695513fcf13fc587e1bd47a5 \ - --hash=sha256:70ed2830b169a9960193f4d4322d22be5c0925357d82cbf485b3369893350908 \ - --hash=sha256:716be5bcabf327b6d5d265dbdc6213a01199be587224eb991ad0d37e83d728fd \ - --hash=sha256:7568fe771f974abadce52669ef3a03150ff03186d8eb82613bc8adc435a03f01 \ - --hash=sha256:77f8071d8fbcbb2dd11b7fd40dedd04e8ebe2eb80497916efedba844298065ef \ - --hash=sha256:82ec52100ec1e6ec671563bbd02d7c7c8d0b9e71a0723c72f22ecf52d1755330 \ - --hash=sha256:895296687ad06dc9b11a024cf68e8d9d3943aa0b4964278d2553b86f1b267735 \ - --hash=sha256:8d3b44b3d0ab2f1319d71d9863d76eeb46766f8cf9e921ac293511804d39813f \ - --hash=sha256:8d679b5f318423eacb61f933a9a0f75535bfca7056daeadbf6bd5bcee6183aee \ - --hash=sha256:8e84b09a9b0f19accedcbeff5c2caf36e0dd537341a33aad8d680336152dc34e \ - --hash=sha256:9094c8b3197db12aa6f05c51c05daaad0a92b8c9af5388569847b03b1007fb1b \ - --hash=sha256:90bde6c6b1827565a95fde597da001212ab436f1b2e0c2dcc7246e14db26e2a3 \ - --hash=sha256:9397b381dcee8a2d6b99447ae85ea2530dcac82ca494d1db877087a13e38926d \ - --hash=sha256:93a12da97cca70cea10d4b4fc602589c4511f96c1f8f6c11817620c021d21d00 \ - --hash=sha256:93bb0aae40b52c57fd74ef9c6933c08c040ba98daf23ad33c3f9893494b8d3ce \ - --hash=sha256:94b1e5f3a5f1ff4f42d5daab047428cd45a3380e51e191360a35cef71c9a7a2a \ - --hash=sha256:965c62be8256d10c11f8907e7a8d3e18127a4c527a5919d85fa87fd9ecc2cfdc \ - --hash=sha256:96c7cca1a4babaaf3bfff3e4e606e38578856917e52f0384635a95b226c87764 \ - --hash=sha256:9bcdce05f056622a632f1d44bb47dbdb677f58cad393612280406ce37530eb6d \ - --hash=sha256:9d80ea2ac519c364a7286e8d765d6cd08648f5b21ca855a8017d9871f075542d \ - --hash=sha256:a1e8cc6cc01da346dc92d9509a63033b9b1bda4fed7a7a7807ed385c7dccdc10 \ - --hash=sha256:ab65cb2885a9f80f979b85aa4e9c9165a31381ca322cbde7c638fe6eefd1ec39 \ - --hash=sha256:af865c18752d416798dae13f83f38927c52f085c52e2f32b8ab0fef46fdd02c2 \ - --hash=sha256:b1e14b2f6965a685c7128bd315e27387205429c2e339eeec55cb75ca4ab0ea2e \ - --hash=sha256:b2a9f9aee38039cf4755891a1e50e1effcc42ea6ba053743f452c372c3152b1b \ - --hash=sha256:be6c0466b4c25b44c5d82b0426b5501de3c424d7a3220e86cd32f319ba56798e \ - --hash=sha256:c4e2cc868b7b5208aec6c960950b7bb821f82c2fe66446c92ee0a571765e91a5 \ - --hash=sha256:c805fa6e5d461329fa02f53f88c914d189ea771b6821083937e79550bf31fc19 \ - --hash=sha256:cf36851ee7219c170bb0793dbc3da3e80c582e04a5437bc601bfe8c85c9216d7 \ - --hash=sha256:db23b1bf8cfe1f7fda19018e7207b20cdb5168f83c437ff7e95d19e39289c447 \ - --hash=sha256:e0c05aff5c6b1bb5fb46a87e0f9d2f733f83ef6cbbbcd5c642b6c01678268061 \ - --hash=sha256:e8ac45e8f4eaac0f9f8043ea0e224158855c6a4329fd4ee37c45c61e3beb518e \ - --hash=sha256:ea3cd46b6713a10216323cda3333514944e510aa691c945334713fca6b5279ff \ - --hash=sha256:ebf7e1e78af38047e08836d33502c7a278915698b7c2145d045f780201679999 \ - --hash=sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e \ - --hash=sha256:ff33c6e6ad006bbc0f34f5faf941cfc62c45841c64c0a058ac38c799f15b5ede +sqlalchemy[mypy]==2.0.48 \ + --hash=sha256:01f6bbd4308b23240cf7d3ef117557c8fd097ec9549d5d8a52977544e35b40ad \ + --hash=sha256:07edba08061bc277bfdc772dd2a1a43978f5a45994dd3ede26391b405c15221e \ + --hash=sha256:10853a53a4a00417a00913d270dddda75815fcb80675874285f41051c094d7dd \ + --hash=sha256:1182437cb2d97988cfea04cf6cdc0b0bb9c74f4d56ec3d08b81e23d621a28cc6 \ + --hash=sha256:144921da96c08feb9e2b052c5c5c1d0d151a292c6135623c6b2c041f2a45f9e0 \ + --hash=sha256:1a89ce07ad2d4b8cfc30bd5889ec40613e028ed80ef47da7d9dd2ce969ad30e0 \ + --hash=sha256:1b4c575df7368b3b13e0cebf01d4679f9a28ed2ae6c1cd0b1d5beffb6b2007dc \ + --hash=sha256:1ccd42229aaac2df431562117ac7e667d702e8e44afdb6cf0e50fa3f18160f0b \ + --hash=sha256:2645b7d8a738763b664a12a1542c89c940daa55196e8d73e55b169cc5c99f65f \ + --hash=sha256:288937433bd44e3990e7da2402fabc44a3c6c25d3704da066b85b89a85474ae0 \ + --hash=sha256:34634e196f620c7a61d18d5cf7dc841ca6daa7961aed75d532b7e58b309ac894 \ + --hash=sha256:348174f228b99f33ca1f773e85510e08927620caa59ffe7803b37170df30332b \ + --hash=sha256:36ac4ddc3d33e852da9cb00ffb08cea62ca05c39711dc67062ca2bb1fae35fd8 \ + --hash=sha256:3713e21ea67bca727eecd4a24bf68bcd414c403faae4989442be60994301ded0 \ + --hash=sha256:389b984139278f97757ea9b08993e7b9d1142912e046ab7d82b3fbaeb0209131 \ + --hash=sha256:426c5ca86415d9b8945c7073597e10de9644802e2ff502b8e1f11a7a2642856b \ + --hash=sha256:4599a95f9430ae0de82b52ff0d27304fe898c17cb5f4099f7438a51b9998ac77 \ + --hash=sha256:49b7bddc1eebf011ea5ab722fdbe67a401caa34a350d278cc7733c0e88fecb1f \ + --hash=sha256:53667b5f668991e279d21f94ccfa6e45b4e3f4500e7591ae59a8012d0f010dcb \ + --hash=sha256:546572a1793cc35857a2ffa1fe0e58571af1779bcc1ffa7c9fb0839885ed69a9 \ + --hash=sha256:583849c743e0e3c9bb7446f5b5addeacedc168d657a69b418063dfdb2d90081c \ + --hash=sha256:5aee45fd2c6c0f2b9cdddf48c48535e7471e42d6fb81adfde801da0bd5b93241 \ + --hash=sha256:5b193a7e29fd9fa56e502920dca47dffe60f97c863494946bd698c6058a55658 \ + --hash=sha256:5ca74f37f3369b45e1f6b7b06afb182af1fd5dde009e4ffd831830d98cbe5fe7 \ + --hash=sha256:68549c403f79a8e25984376480959975212a670405e3913830614432b5daa07a \ + --hash=sha256:69f5bc24904d3bc3640961cddd2523e361257ef68585d6e364166dfbe8c78fae \ + --hash=sha256:6bb85c546591569558571aa1b06aba711b26ae62f111e15e56136d69920e1616 \ + --hash=sha256:6f7b7243850edd0b8b97043f04748f31de50cf426e939def5c16bedb540698f7 \ + --hash=sha256:7001dc9d5f6bb4deb756d5928eaefe1930f6f4179da3924cbd95ee0e9f4dce89 \ + --hash=sha256:7a936f1bb23d370b7c8cc079d5fce4c7d18da87a33c6744e51a93b0f9e97e9b3 \ + --hash=sha256:7c998f2ace8bf76b453b75dbcca500d4f4b9dd3908c13e89b86289b37784848b \ + --hash=sha256:7cddca31edf8b0653090cbb54562ca027c421c58ddde2c0685f49ff56a1690e0 \ + --hash=sha256:8183dc57ae7d9edc1346e007e840a9f3d6aa7b7f165203a99e16f447150140d2 \ + --hash=sha256:82745b03b4043e04600a6b665cb98697c4339b24e34d74b0a2ac0a2488b6f94d \ + --hash=sha256:841a94c66577661c1f088ac958cd767d7c9bf507698f45afffe7a4017049de76 \ + --hash=sha256:858e433f12b0e5b3ed2f8da917433b634f4937d0e8793e5cb33c54a1a01df565 \ + --hash=sha256:908a3fa6908716f803b86896a09a2c4dde5f5ce2bb07aacc71ffebb57986ce99 \ + --hash=sha256:9764014ef5e58aab76220c5664abb5d47d5bc858d9debf821e55cfdd0f128485 \ + --hash=sha256:9c7d0a77e36b5f4b01ca398482230ab792061d243d715299b44a0b55c89fe617 \ + --hash=sha256:a5b429eb84339f9f05e06083f119ad814e6d85e27ecbdf9c551dfdbb128eaf8a \ + --hash=sha256:a66fe406437dd65cacd96a72689a3aaaecaebbcd62d81c5ac1c0fdbeac835096 \ + --hash=sha256:a6b764fb312bd35e47797ad2e63f0d323792837a6ac785a4ca967019357d2bc7 \ + --hash=sha256:b19151e76620a412c2ac1c6f977ab1b9fa7ad43140178345136456d5265b32ed \ + --hash=sha256:b8438ec5594980d405251451c5b7ea9aa58dda38eb7ac35fb7e4c696712ee24f \ + --hash=sha256:b8fc3454b4f3bd0a368001d0e968852dad45a873f8b4babd41bc302ec851a099 \ + --hash=sha256:bcb8ebbf2e2c36cfe01a94f2438012c6a9d494cf80f129d9753bcdf33bfc35a6 \ + --hash=sha256:d404dc897ce10e565d647795861762aa2d06ca3f4a728c5e9a835096c7059018 \ + --hash=sha256:d612c976cbc2d17edfcc4c006874b764e85e990c29ce9bd411f926bbfb02b9a2 \ + --hash=sha256:d64177f443594c8697369c10e4bbcac70ef558e0f7921a1de7e4a3d1734bcf67 \ + --hash=sha256:d854b3970067297f3a7fbd7a4683587134aa9b3877ee15aa29eea478dc68f933 \ + --hash=sha256:d8fcccbbc0c13c13702c471da398b8cd72ba740dca5859f148ae8e0e8e0d3e7e \ + --hash=sha256:e004aa9248e8cb0a5f9b96d003ca7c1c0a5da8decd1066e7b53f59eb8ce7c62b \ + --hash=sha256:e214d546c8ecb5fc22d6e6011746082abf13a9cf46eefb45769c7b31407c97b5 \ + --hash=sha256:e2d0d88686e3d35a76f3e15a34e8c12d73fc94c1dea1cd55782e695cc14086dd \ + --hash=sha256:e2f35b4cccd9ed286ad62e0a3c3ac21e06c02abc60e20aa51a3e305a30f5fa79 \ + --hash=sha256:e3070c03701037aa418b55d36532ecb8f8446ed0135acb71c678dbdf12f5b6e4 \ + --hash=sha256:e5e088bf43f6ee6fec7dbf1ef7ff7774a616c236b5c0cb3e00662dd71a56b571 \ + --hash=sha256:e83e3f959aaa1c9df95c22c528096d94848a1bc819f5d0ebf7ee3df0ca63db6c \ + --hash=sha256:f0dcbc588cd5b725162c076eb9119342f6579c7f7f55057bb7e3c6ff27e13121 \ + --hash=sha256:f27f9da0a7d22b9f981108fd4b62f8b5743423388915a563e651c20d06c1f457 \ + --hash=sha256:f8649a14caa5f8a243628b1d61cf530ad9ae4578814ba726816adb1121fc493e \ + --hash=sha256:fac0fa4e4f55f118fd87177dacb1c6522fe39c28d498d259014020fec9164c29 \ + --hash=sha256:fd08b90d211c086181caed76931ecfa2bdfc83eea3cfccdb0f82abc6c4b876cb # via feast (pyproject.toml) -sqlglot==28.10.1 \ - --hash=sha256:214aef51fd4ce16407022f81cfc80c173409dab6d0f6ae18c52b43f43b31d4dd \ - --hash=sha256:66e0dae43b4bce23314b80e9aef41b8c88fea0e17ada62de095b45262084a8c5 +sqlglot==30.2.1 \ + --hash=sha256:ef4a67cc6f66a8043085eb8ea95fa9541c1625dffa9145ad4e9815a7ba60a199 \ + --hash=sha256:f23d9ee9427ef9d20df15f9b0ffa57d9eb45e52b012219a349d1e6b50ed926d1 # via ibis-framework -sse-starlette==3.2.0 \ - --hash=sha256:5876954bd51920fc2cd51baee47a080eb88a37b5b784e615abb0b283f801cdbf \ - --hash=sha256:8127594edfb51abe44eac9c49e59b0b01f1039d0c7461c6fd91d4e03b70da422 +sse-starlette==3.3.4 \ + --hash=sha256:84bb06e58939a8b38d8341f1bc9792f06c2b53f48c608dd207582b664fc8f3c1 \ + --hash=sha256:aaf92fc067af8a5427192895ac028e947b484ac01edbc3caf00e7e7137c7bef1 # via mcp -starlette==0.52.1 \ - --hash=sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74 \ - --hash=sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933 +starlette==1.0.0 \ + --hash=sha256:6a4beaf1f81bb472fd19ea9b918b50dc3a77a6f2e190a12954b25e6ed5eea149 \ + --hash=sha256:d3ec55e0bb321692d275455ddfd3df75fff145d009685eb40dc91fc66b03d38b # via # fastapi # mcp # sse-starlette -tabulate==0.9.0 \ - --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ - --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f +tabulate==0.10.0 \ + --hash=sha256:e2cfde8f79420f6deeffdeda9aaec3b6bc5abce947655d17ac662b126e48a60d \ + --hash=sha256:f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3 # via feast (pyproject.toml) tenacity==8.5.0 \ --hash=sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78 \ @@ -2882,54 +2882,54 @@ toml==0.10.2 \ --hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \ --hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f # via feast (pyproject.toml) -tomli==2.4.0 \ - --hash=sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729 \ - --hash=sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b \ - --hash=sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d \ - --hash=sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df \ - --hash=sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576 \ - --hash=sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d \ - --hash=sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1 \ - --hash=sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a \ - --hash=sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e \ - --hash=sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc \ - --hash=sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702 \ - --hash=sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6 \ - --hash=sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd \ - --hash=sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4 \ - --hash=sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776 \ - --hash=sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a \ - --hash=sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66 \ - --hash=sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87 \ - --hash=sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2 \ - --hash=sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f \ - --hash=sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475 \ - --hash=sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f \ - --hash=sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95 \ - --hash=sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9 \ - --hash=sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3 \ - --hash=sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9 \ - --hash=sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76 \ - --hash=sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da \ - --hash=sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8 \ - --hash=sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51 \ - --hash=sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86 \ - --hash=sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8 \ - --hash=sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0 \ - --hash=sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b \ - --hash=sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1 \ - --hash=sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e \ - --hash=sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d \ - --hash=sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c \ - --hash=sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867 \ - --hash=sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a \ - --hash=sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c \ - --hash=sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0 \ - --hash=sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4 \ - --hash=sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614 \ - --hash=sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132 \ - --hash=sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa \ - --hash=sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087 +tomli==2.4.1 \ + --hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \ + --hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \ + --hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \ + --hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \ + --hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \ + --hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \ + --hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \ + --hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \ + --hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \ + --hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \ + --hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \ + --hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \ + --hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \ + --hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \ + --hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \ + --hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \ + --hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \ + --hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \ + --hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \ + --hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \ + --hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \ + --hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \ + --hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \ + --hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \ + --hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \ + --hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \ + --hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \ + --hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \ + --hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \ + --hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \ + --hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \ + --hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \ + --hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \ + --hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \ + --hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \ + --hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \ + --hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \ + --hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \ + --hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \ + --hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \ + --hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \ + --hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \ + --hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \ + --hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \ + --hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \ + --hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \ + --hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049 # via # fastapi-mcp # hatch-fancy-pypi-readme @@ -2939,6 +2939,7 @@ tomli==2.4.0 \ # scikit-build-core # setuptools-scm # sphinx + # vcs-versioning tomlkit==0.14.0 \ --hash=sha256:592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680 \ --hash=sha256:cf00efca415dbd57575befb1f6634c4f42d2d87dbba376128adb42c121b87064 @@ -2960,13 +2961,13 @@ trove-classifiers==2026.1.14.14 \ --hash=sha256:00492545a1402b09d4858605ba190ea33243d361e2b01c9c296ce06b5c3325f3 \ --hash=sha256:1f9553927f18d0513d8e5ff80ab8980b8202ce37ecae0e3274ed2ef11880e74d # via hatchling -typeguard==4.5.0 \ - --hash=sha256:749bea21cdb2553e12831bc29f1eae980b22c7de8331ab67ae7db9e85470b5a7 \ - --hash=sha256:cfda388fc88a9ce42a41890900d6f31ee124bea9b73bb84701a32438e92165c3 +typeguard==4.5.1 \ + --hash=sha256:44d2bf329d49a244110a090b55f5f91aa82d9a9834ebfd30bcc73651e4a8cc40 \ + --hash=sha256:f6f8ecbbc819c9bc749983cc67c02391e16a9b43b8b27f15dc70ed7c4a007274 # via feast (pyproject.toml) -typer==0.23.1 \ - --hash=sha256:2070374e4d31c83e7b61362fd859aa683576432fd5b026b060ad6b4cd3b86134 \ - --hash=sha256:3291ad0d3c701cbf522012faccfbb29352ff16ad262db2139e6b01f15781f14e +typer==0.24.1 \ + --hash=sha256:112c1f0ce578bfb4cab9ffdabc68f031416ebcc216536611ba21f04e9aa84c9e \ + --hash=sha256:e39b4732d65fbdcde189ae76cf7cd48aeae72919dea1fdfc16593be016256b45 # via fastapi-mcp types-psutil==7.0.0.20250218 \ --hash=sha256:1447a30c282aafefcf8941ece854e1100eee7b0296a9d9be9977292f0269b121 \ @@ -2993,14 +2994,18 @@ typing-extensions==4.15.0 \ # psycopg-pool # pydantic # pydantic-core + # pyjwt # pyopenssl # referencing + # scikit-build-core + # setuptools-scm # snowflake-connector-python # sqlalchemy # starlette # typeguard # typing-inspection # uvicorn + # vcs-versioning typing-inspection==0.4.2 \ --hash=sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7 \ --hash=sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464 @@ -3015,91 +3020,85 @@ tzdata==2025.3 \ # via # ibis-framework # pandas -ujson==5.11.0 \ - --hash=sha256:0180a480a7d099082501cad1fe85252e4d4bf926b40960fb3d9e87a3a6fbbc80 \ - --hash=sha256:04c41afc195fd477a59db3a84d5b83a871bd648ef371cf8c6f43072d89144eef \ - --hash=sha256:0654a2691fc252c3c525e3d034bb27b8a7546c9d3eb33cd29ce6c9feda361a6a \ - --hash=sha256:090b4d11b380ae25453100b722d0609d5051ffe98f80ec52853ccf8249dfd840 \ - --hash=sha256:109f59885041b14ee9569bf0bb3f98579c3fa0652317b355669939e5fc5ede53 \ - --hash=sha256:10f29e71ecf4ecd93a6610bd8efa8e7b6467454a363c3d6416db65de883eb076 \ - --hash=sha256:1194b943e951092db611011cb8dbdb6cf94a3b816ed07906e14d3bc6ce0e90ab \ - --hash=sha256:12b5e7e22a1fe01058000d1b317d3b65cc3daf61bd2ea7a2b76721fe160fa74d \ - --hash=sha256:16ccb973b7ada0455201808ff11d48fe9c3f034a6ab5bd93b944443c88299f89 \ - --hash=sha256:181fb5b15703a8b9370b25345d2a1fd1359f0f18776b3643d24e13ed9c036d4c \ - --hash=sha256:185f93ebccffebc8baf8302c869fac70dd5dd78694f3b875d03a31b03b062cdb \ - --hash=sha256:1a0a9b76a89827a592656fe12e000cf4f12da9692f51a841a4a07aa4c7ecc41c \ - --hash=sha256:1a325fd2c3a056cf6c8e023f74a0c478dd282a93141356ae7f16d5309f5ff823 \ - --hash=sha256:1aa8a2ab482f09f6c10fba37112af5f957689a79ea598399c85009f2f29898b5 \ - --hash=sha256:1d663b96eb34c93392e9caae19c099ec4133ba21654b081956613327f0e973ac \ - --hash=sha256:29113c003ca33ab71b1b480bde952fbab2a0b6b03a4ee4c3d71687cdcbd1a29d \ - --hash=sha256:30f607c70091483550fbd669a0b37471e5165b317d6c16e75dba2aa967608723 \ - --hash=sha256:3134b783ab314d2298d58cda7e47e7a0f7f71fc6ade6ac86d5dbeaf4b9770fa6 \ - --hash=sha256:34032aeca4510a7c7102bd5933f59a37f63891f30a0706fb46487ab6f0edf8f0 \ - --hash=sha256:3772e4fe6b0c1e025ba3c50841a0ca4786825a4894c8411bf8d3afe3a8061328 \ - --hash=sha256:3d2720e9785f84312b8e2cb0c2b87f1a0b1c53aaab3b2af3ab817d54409012e0 \ - --hash=sha256:416389ec19ef5f2013592f791486bef712ebce0cd59299bf9df1ba40bb2f6e04 \ - --hash=sha256:446e8c11c06048611c9d29ef1237065de0af07cabdd97e6b5b527b957692ec25 \ - --hash=sha256:4598bf3965fc1a936bd84034312bcbe00ba87880ef1ee33e33c1e88f2c398b49 \ - --hash=sha256:48055e1061c1bb1f79e75b4ac39e821f3f35a9b82de17fce92c3140149009bec \ - --hash=sha256:4843f3ab4fe1cc596bb7e02228ef4c25d35b4bb0809d6a260852a4bfcab37ba3 \ - --hash=sha256:49e56ef8066f11b80d620985ae36869a3ff7e4b74c3b6129182ec5d1df0255f3 \ - --hash=sha256:4b42c115c7c6012506e8168315150d1e3f76e7ba0f4f95616f4ee599a1372bbc \ - --hash=sha256:4c9f5d6a27d035dd90a146f7761c2272cf7103de5127c9ab9c4cd39ea61e878a \ - --hash=sha256:5600202a731af24a25e2d7b6eb3f648e4ecd4bb67c4d5cf12f8fab31677469c9 \ - --hash=sha256:65724738c73645db88f70ba1f2e6fb678f913281804d5da2fd02c8c5839af302 \ - --hash=sha256:65f3c279f4ed4bf9131b11972040200c66ae040368abdbb21596bf1564899694 \ - --hash=sha256:674f306e3e6089f92b126eb2fe41bcb65e42a15432c143365c729fdb50518547 \ - --hash=sha256:683f57f0dd3acdd7d9aff1de0528d603aafcb0e6d126e3dc7ce8b020a28f5d01 \ - --hash=sha256:6b6ec7e7321d7fc19abdda3ad809baef935f49673951a8bab486aea975007e02 \ - --hash=sha256:6cd2df62f24c506a0ba322d5e4fe4466d47a9467b57e881ee15a31f7ecf68ff6 \ - --hash=sha256:6dd703c3e86dc6f7044c5ac0b3ae079ed96bf297974598116aa5fb7f655c3a60 \ - --hash=sha256:6eff24e1abd79e0ec6d7eae651dd675ddbc41f9e43e29ef81e16b421da896915 \ - --hash=sha256:7855ccea3f8dad5e66d8445d754fc1cf80265a4272b5f8059ebc7ec29b8d0835 \ - --hash=sha256:787aff4a84da301b7f3bac09bc696e2e5670df829c6f8ecf39916b4e7e24e701 \ - --hash=sha256:7895f0d2d53bd6aea11743bd56e3cb82d729980636cd0ed9b89418bf66591702 \ - --hash=sha256:78c684fb21255b9b90320ba7e199780f653e03f6c2528663768965f4126a5b50 \ - --hash=sha256:7e0ec1646db172beb8d3df4c32a9d78015e671d2000af548252769e33079d9a6 \ - --hash=sha256:7e3cff632c1d78023b15f7e3a81c3745cd3f94c044d1e8fa8efbd6b161997bbc \ - --hash=sha256:7f1a27ab91083b4770e160d17f61b407f587548f2c2b5fbf19f94794c495594a \ - --hash=sha256:80017e870d882d5517d28995b62e4e518a894f932f1e242cbc802a2fd64d365c \ - --hash=sha256:8254e858437c00f17cb72e7a644fc42dad0ebb21ea981b71df6e84b1072aaa7c \ - --hash=sha256:837da4d27fed5fdc1b630bd18f519744b23a0b5ada1bbde1a36ba463f2900c03 \ - --hash=sha256:849e65b696f0d242833f1df4182096cedc50d414215d1371fca85c541fbff629 \ - --hash=sha256:85e6796631165f719084a9af00c79195d3ebf108151452fefdcb1c8bb50f0105 \ - --hash=sha256:86baf341d90b566d61a394869ce77188cc8668f76d7bb2c311d77a00f4bdf844 \ - --hash=sha256:8fa2af7c1459204b7a42e98263b069bd535ea0cd978b4d6982f35af5a04a4241 \ - --hash=sha256:94fcae844f1e302f6f8095c5d1c45a2f0bfb928cccf9f1b99e3ace634b980a2a \ - --hash=sha256:952c0be400229940248c0f5356514123d428cba1946af6fa2bbd7503395fef26 \ - --hash=sha256:99c49400572cd77050894e16864a335225191fd72a818ea6423ae1a06467beac \ - --hash=sha256:9aacbeb23fdbc4b256a7d12e0beb9063a1ba5d9e0dbb2cfe16357c98b4334596 \ - --hash=sha256:a0af6574fc1d9d53f4ff371f58c96673e6d988ed2b5bf666a6143c782fa007e9 \ - --hash=sha256:a31c6b8004438e8c20fc55ac1c0e07dad42941db24176fe9acf2815971f8e752 \ - --hash=sha256:a4df61a6df0a4a8eb5b9b1ffd673429811f50b235539dac586bb7e9e91994138 \ - --hash=sha256:a638425d3c6eed0318df663df44480f4a40dc87cc7c6da44d221418312f6413b \ - --hash=sha256:aa6b3d4f1c0d3f82930f4cbd7fe46d905a4a9205a7c13279789c1263faf06dba \ - --hash=sha256:aa6d7a5e09217ff93234e050e3e380da62b084e26b9f2e277d2606406a2fc2e5 \ - --hash=sha256:ab2cb8351d976e788669c8281465d44d4e94413718af497b4e7342d7b2f78018 \ - --hash=sha256:abae0fb58cc820092a0e9e8ba0051ac4583958495bfa5262a12f628249e3b362 \ - --hash=sha256:b16930f6a0753cdc7d637b33b4e8f10d5e351e1fb83872ba6375f1e87be39746 \ - --hash=sha256:b7b136cc6abc7619124fd897ef75f8e63105298b5ca9bdf43ebd0e1fa0ee105f \ - --hash=sha256:be6b0eaf92cae8cdee4d4c9e074bde43ef1c590ed5ba037ea26c9632fb479c88 \ - --hash=sha256:c44c703842024d796b4c78542a6fcd5c3cb948b9fc2a73ee65b9c86a22ee3638 \ - --hash=sha256:c6618f480f7c9ded05e78a1938873fde68baf96cdd74e6d23c7e0a8441175c4b \ - --hash=sha256:ce076f2df2e1aa62b685086fbad67f2b1d3048369664b4cdccc50707325401f9 \ - --hash=sha256:d06e87eded62ff0e5f5178c916337d2262fdbc03b31688142a3433eabb6511db \ - --hash=sha256:d7c46cb0fe5e7056b9acb748a4c35aa1b428025853032540bb7e41f46767321f \ - --hash=sha256:d8951bb7a505ab2a700e26f691bdfacf395bc7e3111e3416d325b513eea03a58 \ - --hash=sha256:da473b23e3a54448b008d33f742bcd6d5fb2a897e42d1fc6e7bf306ea5d18b1b \ - --hash=sha256:de6e88f62796372fba1de973c11138f197d3e0e1d80bcb2b8aae1e826096d433 \ - --hash=sha256:e204ae6f909f099ba6b6b942131cee359ddda2b6e4ea39c12eb8b991fe2010e0 \ - --hash=sha256:e73df8648c9470af2b6a6bf5250d4744ad2cf3d774dcf8c6e31f018bdd04d764 \ - --hash=sha256:e750c436fb90edf85585f5c62a35b35082502383840962c6983403d1bd96a02c \ - --hash=sha256:e979fbc469a7f77f04ec2f4e853ba00c441bf2b06720aa259f0f720561335e34 \ - --hash=sha256:ecd6ff8a3b5a90c292c2396c2d63c687fd0ecdf17de390d852524393cd9ed052 \ - --hash=sha256:f278b31a7c52eb0947b2db55a5133fbc46b6f0ef49972cd1a80843b72e135aba \ - --hash=sha256:f62b9976fabbcde3ab6e413f4ec2ff017749819a0786d84d7510171109f2d53c \ - --hash=sha256:fa79fdb47701942c2132a9dd2297a1a85941d966d8c87bfd9e29b0cf423f26cc \ - --hash=sha256:fac6c0649d6b7c3682a0a6e18d3de6857977378dce8d419f57a0b20e3d775b39 +ujson==5.12.0 \ + --hash=sha256:006428d3813b87477d72d306c40c09f898a41b968e57b15a7d88454ecc42a3fb \ + --hash=sha256:02f93da7a4115e24f886b04fd56df1ee8741c2ce4ea491b7ab3152f744ad8f8e \ + --hash=sha256:0727363b05ab05ee737a28f6200dc4078bce6b0508e10bd8aab507995a15df61 \ + --hash=sha256:085b6ce182cdd6657481c7c4003a417e0655c4f6e58b76f26ee18f0ae21db827 \ + --hash=sha256:09b4beff9cc91d445d5818632907b85fb06943b61cb346919ce202668bf6794a \ + --hash=sha256:0a3ae28f0b209be5af50b54ca3e2123a3de3a57d87b75f1e5aa3d7961e041983 \ + --hash=sha256:0d2e8db5ade3736a163906154ca686203acc7d1d30736cbf577c730d13653d84 \ + --hash=sha256:0e00cec383eab2406c9e006bd4edb55d284e94bb943fda558326048178d26961 \ + --hash=sha256:0fe6b8b8968e11dd9b2348bd508f0f57cf49ab3512064b36bc4117328218718e \ + --hash=sha256:0fe9128e75c6aa6e9ae06c1408d6edd9179a2fef0fe6d9cda3166b887eba521d \ + --hash=sha256:14b2e1eb528d77bc0f4c5bd1a7ebc05e02b5b41beefb7e8567c9675b8b13bcf4 \ + --hash=sha256:15d416440148f3e56b9b244fdaf8a09fcf5a72e4944b8e119f5bf60417a2bfc8 \ + --hash=sha256:15e555c4caca42411270b2ed2b2ebc7b3a42bb04138cef6c956e1f1d49709fe2 \ + --hash=sha256:16b4fe9c97dc605f5e1887a9e1224287291e35c56cbc379f8aa44b6b7bcfe2bb \ + --hash=sha256:1b5c6ceb65fecd28a1d20d1eba9dbfa992612b86594e4b6d47bb580d2dd6bcb3 \ + --hash=sha256:1d072a403d82aef8090c6d4f728e3a727dfdba1ad3b7fa3a052c3ecbd37e73cb \ + --hash=sha256:2324d9a0502317ffc35d38e153c1b2fa9610ae03775c9d0f8d0cca7b8572b04e \ + --hash=sha256:2a248750abce1c76fbd11b2e1d88b95401e72819295c3b851ec73399d6849b3d \ + --hash=sha256:2ea6206043385343aff0b7da65cf73677f6f5e50de8f1c879e557f4298cac36a \ + --hash=sha256:31348a0ffbfc815ce78daac569d893349d85a0b57e1cd2cdbba50b7f333784da \ + --hash=sha256:38051f36423f084b909aaadb3b41c9c6a2958e86956ba21a8489636911e87504 \ + --hash=sha256:3c2f947e55d3c7cfe124dd4521ee481516f3007d13c6ad4bf6aeb722e190eb1b \ + --hash=sha256:3ed5cb149892141b1e77ef312924a327f2cc718b34247dae346ed66329e1b8be \ + --hash=sha256:3ff4ede90ed771140caa7e1890de17431763a483c54b3c1f88bd30f0cc1affc0 \ + --hash=sha256:40aa43a7a3a8d2f05e79900858053d697a88a605e3887be178b43acbcd781161 \ + --hash=sha256:42d875388fbd091c7ea01edfff260f839ba303038ffb23475ef392012e4d63dd \ + --hash=sha256:457fabc2700a8e6ddb85bc5a1d30d3345fe0d3ec3ee8161a4e032ec585801dfa \ + --hash=sha256:460e76a4daff214ae33ab959494962c93918cb44714ea3e3f748b14aa37f8a87 \ + --hash=sha256:50524f4f6a1c839714dbaff5386a1afb245d2d5ec8213a01fbc99cea7307811e \ + --hash=sha256:51acc750ec7a2df786cdc868fb16fa04abd6269a01d58cf59bafc57978773d8e \ + --hash=sha256:55ede2a7a051b3b7e71a394978a098d71b3783e6b904702ff45483fad434ae2d \ + --hash=sha256:561f89cc82deeae82e37d4a4764184926fb432f740a9691563a391b13f7339a4 \ + --hash=sha256:56ba3f7abbd6b0bb282a544dc38406d1a188d8bb9164f49fdb9c2fee62cb29da \ + --hash=sha256:57930ac9519099b852e190d2c04b1fb5d97ea128db33bce77ed874eccb4c7f09 \ + --hash=sha256:58a11cb49482f1a095a2bd9a1d81dd7c8fb5d2357f959ece85db4e46a825fd00 \ + --hash=sha256:64df53eef4ac857eb5816a56e2885ccf0d7dff6333c94065c93b39c51063e01d \ + --hash=sha256:6879aed770557f0961b252648d36f6fdaab41079d37a2296b5649fd1b35608e0 \ + --hash=sha256:6ad57654570464eb1b040b5c353dee442608e06cff9102b8fcb105565a44c9ed \ + --hash=sha256:6c0aed6a4439994c9666fb8a5b6c4eac94d4ef6ddc95f9b806a599ef83547e3b \ + --hash=sha256:76bf3e7406cf23a3e1ca6a23fb1fb9ea82f4f6bd226fe226e09146b0194f85dc \ + --hash=sha256:7bbf05c38debc90d1a195b11340cc85cb43ab3e753dc47558a3a84a38cbc72da \ + --hash=sha256:7ddb08b3c2f9213df1f2e3eb2fbea4963d80ec0f8de21f0b59898e34f3b3d96d \ + --hash=sha256:7e07f6f644d2c44d53b7a320a084eef98063651912c1b9449b5f45fcbdc6ccd2 \ + --hash=sha256:85833bca01aa5cae326ac759276dc175c5fa3f7b3733b7d543cf27f2df12d1ef \ + --hash=sha256:8712b61eb1b74a4478cfd1c54f576056199e9f093659334aeb5c4a6b385338e5 \ + --hash=sha256:871c0e5102e47995b0e37e8df7819a894a6c3da0d097545cd1f9f1f7d7079927 \ + --hash=sha256:89e302abd3749f6d6699691747969a5d85f7c73081d5ed7e2624c7bd9721a2ab \ + --hash=sha256:937794042342006f707837f38d721426b11b0774d327a2a45c0bd389eb750a87 \ + --hash=sha256:93bc91fdadcf046da37a214eaa714574e7e9b1913568e93bb09527b2ceb7f759 \ + --hash=sha256:94c5f1621cbcab83c03be46441f090b68b9f307b6c7ec44d4e3f6d5997383df4 \ + --hash=sha256:973b7d7145b1ac553a7466a64afa8b31ec2693d7c7fff6a755059e0a2885dfd2 \ + --hash=sha256:99cc80facad240b0c2fb5a633044420878aac87a8e7c348b9486450cba93f27c \ + --hash=sha256:9a5fcbe7b949f2e95c47ea8a80b410fcdf2da61c98553b45a4ee875580418b68 \ + --hash=sha256:9b3b86ec3e818f3dd3e13a9de628e88a9990f4af68ecb0b12dd3de81227f0a26 \ + --hash=sha256:9b3cf13facf6f77c283af0e1713e5e8c47a0fe295af81326cb3cb4380212e797 \ + --hash=sha256:9c5a52987a990eb1bae55f9000994f1afdb0326c154fb089992f839ab3c30688 \ + --hash=sha256:a2d79c6635ccffcbfc1d5c045874ba36b594589be81d50d43472570bb8de9c57 \ + --hash=sha256:a6ec5bf6bc361f2f0f9644907a36ce527715b488988a8df534120e5c34eeda94 \ + --hash=sha256:a7bf9cc97f05048ac8f3e02cd58f0fe62b901453c24345bfde287f4305dcc31c \ + --hash=sha256:ab9056d94e5db513d9313b34394f3a3b83e6301a581c28ad67773434f3faccab \ + --hash=sha256:adf28d13a33f9d750fe7a78fb481cac298fa257d8863d8727b2ea4455ea41235 \ + --hash=sha256:b62cb9a7501e1f5c9ffe190485501349c33e8862dde4377df774e40b8166871f \ + --hash=sha256:bacbd3c69862478cbe1c7ed4325caedec580d8acf31b8ee1b9a1e02a56295cad \ + --hash=sha256:bb349dbba57c76eec25e5917e07f35aabaf0a33b9e67fc13d188002500106487 \ + --hash=sha256:bd03472c36fa3a386a6deb887113b9e3fa40efba8203eb4fe786d3c0ccc724f6 \ + --hash=sha256:bf85a00ac3b56a1e7a19c5be7b02b5180a0895ac4d3c234d717a55e86960691c \ + --hash=sha256:ca0c7ce828bb76ab78b3991904b477c2fd0f711d7815c252d1ef28ff9450b052 \ + --hash=sha256:ccbfd94e59aad4a2566c71912b55f0547ac1680bfac25eb138e6703eb3dd434e \ + --hash=sha256:d1831c07bd4dce53c4b666fa846c7eba4b7c414f2e641a4585b7f50b72f502dc \ + --hash=sha256:d22cad98c2a10bbf6aa083a8980db6ed90d4285a841c4de892890c2b28286ef9 \ + --hash=sha256:d30ad4359413c8821cc7b3707f7ca38aa8bc852ba3b9c5a759ee2d7740157315 \ + --hash=sha256:e0dd3676ea0837cd70ea1879765e9e9f6be063be0436de9b3ea4b775caf83654 \ + --hash=sha256:e584d0cdd37cac355aca52ed788d1a2d939d6837e2870d3b70e585db24025a50 \ + --hash=sha256:e6369ac293d2cc40d52577e4fa3d75a70c1aae2d01fa3580a34a4e6eff9286b9 \ + --hash=sha256:efae5df7a8cc8bdb1037b0f786b044ce281081441df5418c3a0f0e1f86fe7bb3 \ + --hash=sha256:f19b3af31d02a2e79c5f9a6deaab0fb3c116456aeb9277d11720ad433de6dfc6 \ + --hash=sha256:f7a0430d765f9bda043e6aefaba5944d5f21ec43ff4774417d7e296f61917382 \ + --hash=sha256:fb94245a715b4d6e24689de12772b85329a1f9946cbf6187923a64ecdea39e65 # via pymilvus urllib3==2.6.3 \ --hash=sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed \ @@ -3171,6 +3170,10 @@ uvloop==0.22.1 \ --hash=sha256:ef6f0d4cc8a9fa1f6a910230cd53545d9a14479311e87e3cb225495952eb672c \ --hash=sha256:fe94b4564e865d968414598eea1a6de60adba0c040ba4ed05ac1300de402cd42 # via uvicorn +vcs-versioning==1.1.1 \ + --hash=sha256:b541e2ba79fc6aaa3850f8a7f88af43d97c1c80649c01142ee4146eddbc599e4 \ + --hash=sha256:fabd75a3cab7dd8ac02fe24a3a9ba936bf258667b5a62ed468c9a1da0f5775bc + # via setuptools-scm watchfiles==1.1.1 \ --hash=sha256:00485f441d183717038ed2e887a7c868154f216877653121068107b227a2f64c \ --hash=sha256:03fa0f5237118a0c5e496185cafa92878568b652a2e9a9382a5151b1a0380a43 \ @@ -3432,137 +3435,135 @@ wrapt==1.17.3 \ --hash=sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10 \ --hash=sha256:fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c # via aiobotocore -yarl==1.22.0 \ - --hash=sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a \ - --hash=sha256:029866bde8d7b0878b9c160e72305bbf0a7342bcd20b9999381704ae03308dc8 \ - --hash=sha256:078278b9b0b11568937d9509b589ee83ef98ed6d561dfe2020e24a9fd08eaa2b \ - --hash=sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da \ - --hash=sha256:07a524d84df0c10f41e3ee918846e1974aba4ec017f990dc735aad487a0bdfdf \ - --hash=sha256:088e4e08f033db4be2ccd1f34cf29fe994772fb54cfe004bbf54db320af56890 \ - --hash=sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093 \ - --hash=sha256:0cf71bf877efeac18b38d3930594c0948c82b64547c1cf420ba48722fe5509f6 \ - --hash=sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79 \ - --hash=sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683 \ - --hash=sha256:10619d9fdee46d20edc49d3479e2f8269d0779f1b031e6f7c2aa1c76be04b7ed \ - --hash=sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2 \ - --hash=sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff \ - --hash=sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02 \ - --hash=sha256:14291620375b1060613f4aab9ebf21850058b6b1b438f386cc814813d901c60b \ - --hash=sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03 \ - --hash=sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511 \ - --hash=sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c \ - --hash=sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124 \ - --hash=sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c \ - --hash=sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da \ - --hash=sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2 \ - --hash=sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0 \ - --hash=sha256:2e4e1f6f0b4da23e61188676e3ed027ef0baa833a2e633c29ff8530800edccba \ - --hash=sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d \ - --hash=sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53 \ - --hash=sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138 \ - --hash=sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4 \ - --hash=sha256:3aa27acb6de7a23785d81557577491f6c38a5209a254d1191519d07d8fe51748 \ - --hash=sha256:3b06bcadaac49c70f4c88af4ffcfbe3dc155aab3163e75777818092478bcbbe7 \ - --hash=sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d \ - --hash=sha256:3e2daa88dc91870215961e96a039ec73e4937da13cf77ce17f9cad0c18df3503 \ - --hash=sha256:3ea66b1c11c9150f1372f69afb6b8116f2dd7286f38e14ea71a44eee9ec51b9d \ - --hash=sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2 \ - --hash=sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa \ - --hash=sha256:437840083abe022c978470b942ff832c3940b2ad3734d424b7eaffcd07f76737 \ - --hash=sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f \ - --hash=sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1 \ - --hash=sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d \ - --hash=sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694 \ - --hash=sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3 \ - --hash=sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a \ - --hash=sha256:4c52a6e78aef5cf47a98ef8e934755abf53953379b7d53e68b15ff4420e6683d \ - --hash=sha256:4dcc74149ccc8bba31ce1944acee24813e93cfdee2acda3c172df844948ddf7b \ - --hash=sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a \ - --hash=sha256:51af598701f5299012b8416486b40fceef8c26fc87dc6d7d1f6fc30609ea0aa6 \ - --hash=sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b \ - --hash=sha256:595697f68bd1f0c1c159fcb97b661fc9c3f5db46498043555d04805430e79bea \ - --hash=sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5 \ - --hash=sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f \ - --hash=sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df \ - --hash=sha256:5cdac20da754f3a723cceea5b3448e1a2074866406adeb4ef35b469d089adb8f \ - --hash=sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b \ - --hash=sha256:5dbeefd6ca588b33576a01b0ad58aa934bc1b41ef89dee505bf2932b22ddffba \ - --hash=sha256:62441e55958977b8167b2709c164c91a6363e25da322d87ae6dd9c6019ceecf9 \ - --hash=sha256:663e1cadaddae26be034a6ab6072449a8426ddb03d500f43daf952b74553bba0 \ - --hash=sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6 \ - --hash=sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b \ - --hash=sha256:6944b2dc72c4d7f7052683487e3677456050ff77fcf5e6204e98caf785ad1967 \ - --hash=sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2 \ - --hash=sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708 \ - --hash=sha256:6dcbb0829c671f305be48a7227918cfcd11276c2d637a8033a99a02b67bf9eda \ - --hash=sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8 \ - --hash=sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10 \ - --hash=sha256:75976c6945d85dbb9ee6308cd7ff7b1fb9409380c82d6119bd778d8fcfe2931c \ - --hash=sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b \ - --hash=sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028 \ - --hash=sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e \ - --hash=sha256:80ddf7a5f8c86cb3eb4bc9028b07bbbf1f08a96c5c0bc1244be5e8fefcb94147 \ - --hash=sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33 \ - --hash=sha256:84fc3ec96fce86ce5aa305eb4aa9358279d1aa644b71fab7b8ed33fe3ba1a7ca \ - --hash=sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590 \ - --hash=sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c \ - --hash=sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53 \ - --hash=sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74 \ - --hash=sha256:99b6fc1d55782461b78221e95fc357b47ad98b041e8e20f47c1411d0aacddc60 \ - --hash=sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f \ - --hash=sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1 \ - --hash=sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27 \ - --hash=sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520 \ - --hash=sha256:a4fcfc8eb2c34148c118dfa02e6427ca278bfd0f3df7c5f99e33d2c0e81eae3e \ - --hash=sha256:a899cbd98dce6f5d8de1aad31cb712ec0a530abc0a86bd6edaa47c1090138467 \ - --hash=sha256:a9b1ba5610a4e20f655258d5a1fdc7ebe3d837bb0e45b581398b99eb98b1f5ca \ - --hash=sha256:af74f05666a5e531289cb1cc9c883d1de2088b8e5b4de48004e5ca8a830ac859 \ - --hash=sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273 \ - --hash=sha256:b266bd01fedeffeeac01a79ae181719ff848a5a13ce10075adbefc8f1daee70e \ - --hash=sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601 \ - --hash=sha256:b580e71cac3f8113d3135888770903eaf2f507e9421e5697d6ee6d8cd1c7f054 \ - --hash=sha256:b6a6f620cfe13ccec221fa312139135166e47ae169f8253f72a0abc0dae94376 \ - --hash=sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7 \ - --hash=sha256:b85b982afde6df99ecc996990d4ad7ccbdbb70e2a4ba4de0aecde5922ba98a0b \ - --hash=sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb \ - --hash=sha256:ba440ae430c00eee41509353628600212112cd5018d5def7e9b05ea7ac34eb65 \ - --hash=sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784 \ - --hash=sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71 \ - --hash=sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b \ - --hash=sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a \ - --hash=sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c \ - --hash=sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face \ - --hash=sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d \ - --hash=sha256:c7bd6683587567e5a49ee6e336e0612bec8329be1b7d4c8af5687dcdeb67ee1e \ - --hash=sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e \ - --hash=sha256:cb95a9b1adaa48e41815a55ae740cfda005758104049a640a398120bf02515ca \ - --hash=sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9 \ - --hash=sha256:d332fc2e3c94dad927f2112395772a4e4fedbcf8f80efc21ed7cdfae4d574fdb \ - --hash=sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95 \ - --hash=sha256:d5372ca1df0f91a86b047d1277c2aaf1edb32d78bbcefffc81b40ffd18f027ed \ - --hash=sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf \ - --hash=sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca \ - --hash=sha256:dd7afd3f8b0bfb4e0d9fc3c31bfe8a4ec7debe124cfd90619305def3c8ca8cd2 \ - --hash=sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62 \ - --hash=sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df \ - --hash=sha256:e1b329cb8146d7b736677a2440e422eadd775d1806a81db2d4cded80a48efc1a \ - --hash=sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67 \ - --hash=sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f \ - --hash=sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529 \ - --hash=sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486 \ - --hash=sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a \ - --hash=sha256:e6438cc8f23a9c1478633d216b16104a586b9761db62bfacb6425bac0a36679e \ - --hash=sha256:e81fda2fb4a07eda1a2252b216aa0df23ebcd4d584894e9612e80999a78fd95b \ - --hash=sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74 \ - --hash=sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d \ - --hash=sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b \ - --hash=sha256:f0d97c18dfd9a9af4490631905a3f131a8e4c9e80a39353919e2cfed8f00aedc \ - --hash=sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2 \ - --hash=sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e \ - --hash=sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8 \ - --hash=sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82 \ - --hash=sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd \ - --hash=sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249 +yarl==1.23.0 \ + --hash=sha256:03214408cfa590df47728b84c679ae4ef00be2428e11630277be0727eba2d7cc \ + --hash=sha256:041b1a4cefacf65840b4e295c6985f334ba83c30607441ae3cf206a0eed1a2e4 \ + --hash=sha256:0793e2bd0cf14234983bbb371591e6bea9e876ddf6896cdcc93450996b0b5c85 \ + --hash=sha256:0e1fdaa14ef51366d7757b45bde294e95f6c8c049194e793eedb8387c86d5993 \ + --hash=sha256:0e40111274f340d32ebcc0a5668d54d2b552a6cca84c9475859d364b380e3222 \ + --hash=sha256:115136c4a426f9da976187d238e84139ff6b51a20839aa6e3720cd1026d768de \ + --hash=sha256:13a563739ae600a631c36ce096615fe307f131344588b0bc0daec108cdb47b25 \ + --hash=sha256:16c6994ac35c3e74fb0ae93323bf8b9c2a9088d55946109489667c510a7d010e \ + --hash=sha256:170e26584b060879e29fac213e4228ef063f39128723807a312e5c7fec28eff2 \ + --hash=sha256:17235362f580149742739cc3828b80e24029d08cbb9c4bda0242c7b5bc610a8e \ + --hash=sha256:1932b6b8bba8d0160a9d1078aae5838a66039e8832d41d2992daa9a3a08f7860 \ + --hash=sha256:1b6b572edd95b4fa8df75de10b04bc81acc87c1c7d16bcdd2035b09d30acc957 \ + --hash=sha256:1c3a3598a832590c5a3ce56ab5576361b5688c12cb1d39429cf5dba30b510760 \ + --hash=sha256:1c57676bdedc94cd3bc37724cf6f8cd2779f02f6aba48de45feca073e714fe52 \ + --hash=sha256:1dc702e42d0684f42d6519c8d581e49c96cefaaab16691f03566d30658ee8788 \ + --hash=sha256:21d1b7305a71a15b4794b5ff22e8eef96ff4a6d7f9657155e5aa419444b28912 \ + --hash=sha256:23f371bd662cf44a7630d4d113101eafc0cfa7518a2760d20760b26021454719 \ + --hash=sha256:2569b67d616eab450d262ca7cb9f9e19d2f718c70a8b88712859359d0ab17035 \ + --hash=sha256:263cd4f47159c09b8b685890af949195b51d1aa82ba451c5847ca9bc6413c220 \ + --hash=sha256:2803ed8b21ca47a43da80a6fd1ed3019d30061f7061daa35ac54f63933409412 \ + --hash=sha256:2a6940a074fb3c48356ed0158a3ca5699c955ee4185b4d7d619be3c327143e05 \ + --hash=sha256:2e27c8841126e017dd2a054a95771569e6070b9ee1b133366d8b31beb5018a41 \ + --hash=sha256:31c9921eb8bd12633b41ad27686bbb0b1a2a9b8452bfdf221e34f311e9942ed4 \ + --hash=sha256:34b6cf500e61c90f305094911f9acc9c86da1a05a7a3f5be9f68817043f486e4 \ + --hash=sha256:3650dc2480f94f7116c364096bc84b1d602f44224ef7d5c7208425915c0475dd \ + --hash=sha256:389871e65468400d6283c0308e791a640b5ab5c83bcee02a2f51295f95e09748 \ + --hash=sha256:39004f0ad156da43e86aa71f44e033de68a44e5a31fc53507b36dd253970054a \ + --hash=sha256:394906945aa8b19fc14a61cf69743a868bb8c465efe85eee687109cc540b98f4 \ + --hash=sha256:3ceb13c5c858d01321b5d9bb65e4cf37a92169ea470b70fec6f236b2c9dd7e34 \ + --hash=sha256:411225bae281f114067578891bc75534cfb3d92a3b4dfef7a6ca78ba354e6069 \ + --hash=sha256:44bb7bef4ea409384e3f8bc36c063d77ea1b8d4a5b2706956c0d6695f07dcc25 \ + --hash=sha256:4503053d296bc6e4cbd1fad61cf3b6e33b939886c4f249ba7c78b602214fabe2 \ + --hash=sha256:4764a6a7588561a9aef92f65bda2c4fb58fe7c675c0883862e6df97559de0bfb \ + --hash=sha256:4966242ec68afc74c122f8459abd597afd7d8a60dc93d695c1334c5fd25f762f \ + --hash=sha256:4a42e651629dafb64fd5b0286a3580613702b5809ad3f24934ea87595804f2c5 \ + --hash=sha256:4a59ba56f340334766f3a4442e0efd0af895fae9e2b204741ef885c446b3a1a8 \ + --hash=sha256:4c41e021bc6d7affb3364dc1e1e5fa9582b470f283748784bd6ea0558f87f42c \ + --hash=sha256:5023346c4ee7992febc0068e7593de5fa2bf611848c08404b35ebbb76b1b0512 \ + --hash=sha256:50f9d8d531dfb767c565f348f33dd5139a6c43f5cbdf3f67da40d54241df93f6 \ + --hash=sha256:51430653db848d258336cfa0244427b17d12db63d42603a55f0d4546f50f25b5 \ + --hash=sha256:531ef597132086b6cf96faa7c6c1dcd0361dd5f1694e5cc30375907b9b7d3ea9 \ + --hash=sha256:53ad387048f6f09a8969631e4de3f1bf70c50e93545d64af4f751b2498755072 \ + --hash=sha256:53b1ea6ca88ebd4420379c330aea57e258408dd0df9af0992e5de2078dc9f5d5 \ + --hash=sha256:575aa4405a656e61a540f4a80eaa5260f2a38fff7bfdc4b5f611840d76e9e277 \ + --hash=sha256:578110dd426f0d209d1509244e6d4a3f1a3e9077655d98c5f22583d63252a08a \ + --hash=sha256:5ec2f42d41ccbd5df0270d7df31618a8ee267bfa50997f5d720ddba86c4a83a6 \ + --hash=sha256:5ee586fb17ff8f90c91cf73c6108a434b02d69925f44f5f8e0d7f2f260607eae \ + --hash=sha256:5f10fd85e4b75967468af655228fbfd212bdf66db1c0d135065ce288982eda26 \ + --hash=sha256:609d3614d78d74ebe35f54953c5bbd2ac647a7ddb9c30a5d877580f5e86b22f2 \ + --hash=sha256:62694e275c93d54f7ccedcfef57d42761b2aad5234b6be1f3e3026cae4001cd4 \ + --hash=sha256:63e92247f383c85ab00dd0091e8c3fa331a96e865459f5ee80353c70a4a42d70 \ + --hash=sha256:682bae25f0a0dd23a056739f23a134db9f52a63e2afd6bfb37ddc76292bbd723 \ + --hash=sha256:6b41389c19b07c760c7e427a3462e8ab83c4bb087d127f0e854c706ce1b9215c \ + --hash=sha256:6e87a6e8735b44816e7db0b2fbc9686932df473c826b0d9743148432e10bb9b9 \ + --hash=sha256:6f0fd84de0c957b2d280143522c4f91a73aada1923caee763e24a2b3fda9f8a5 \ + --hash=sha256:70efd20be968c76ece7baa8dafe04c5be06abc57f754d6f36f3741f7aa7a208e \ + --hash=sha256:71d006bee8397a4a89f469b8deb22469fe7508132d3c17fa6ed871e79832691c \ + --hash=sha256:73309162a6a571d4cbd3b6a1dcc703c7311843ae0d1578df6f09be4e98df38d4 \ + --hash=sha256:75e3026ab649bf48f9a10c0134512638725b521340293f202a69b567518d94e0 \ + --hash=sha256:76855800ac56f878847a09ce6dba727c93ca2d89c9e9d63002d26b916810b0a2 \ + --hash=sha256:7c6b9461a2a8b47c65eef63bb1c76a4f1c119618ffa99ea79bc5bb1e46c5821b \ + --hash=sha256:803a3c3ce4acc62eaf01eaca1208dcf0783025ef27572c3336502b9c232005e7 \ + --hash=sha256:80e6d33a3d42a7549b409f199857b4fb54e2103fc44fb87605b6663b7a7ff750 \ + --hash=sha256:8419ebd326430d1cbb7efb5292330a2cf39114e82df5cc3d83c9a0d5ebeaf2f2 \ + --hash=sha256:85610b4f27f69984932a7abbe52703688de3724d9f72bceb1cca667deff27474 \ + --hash=sha256:85e9beda1f591bc73e77ea1c51965c68e98dafd0fec72cdd745f77d727466716 \ + --hash=sha256:877b0738624280e34c55680d6054a307aa94f7d52fa0e3034a9cc6e790871da7 \ + --hash=sha256:88f9fb0116fbfcefcab70f85cf4b74a2b6ce5d199c41345296f49d974ddb4123 \ + --hash=sha256:8c4fe09e0780c6c3bf2b7d4af02ee2394439d11a523bbcf095cf4747c2932007 \ + --hash=sha256:93a784271881035ab4406a172edb0faecb6e7d00f4b53dc2f55919d6c9688595 \ + --hash=sha256:94f8575fbdf81749008d980c17796097e645574a3b8c28ee313931068dad14fe \ + --hash=sha256:95451e6ce06c3e104556d73b559f5da6c34a069b6b62946d3ad66afcd51642ea \ + --hash=sha256:99c8a9ed30f4164bc4c14b37a90208836cbf50d4ce2a57c71d0f52c7fb4f7598 \ + --hash=sha256:9a18d6f9359e45722c064c97464ec883eb0e0366d33eda61cb19a244bf222679 \ + --hash=sha256:9cbf44c5cb4a7633d078788e1b56387e3d3cf2b8139a3be38040b22d6c3221c8 \ + --hash=sha256:9ee33b875f0b390564c1fb7bc528abf18c8ee6073b201c6ae8524aca778e2d83 \ + --hash=sha256:a0e317df055958a0c1e79e5d2aa5a5eaa4a6d05a20d4b0c9c3f48918139c9fc6 \ + --hash=sha256:a2df6afe50dea8ae15fa34c9f824a3ee958d785fd5d089063d960bae1daa0a3f \ + --hash=sha256:a31de1613658308efdb21ada98cbc86a97c181aa050ba22a808120bb5be3ab94 \ + --hash=sha256:a3d2bff8f37f8d0f96c7ec554d16945050d54462d6e95414babaa18bfafc7f51 \ + --hash=sha256:a41bcf68efd19073376eb8cf948b8d9be0af26256403e512bb18f3966f1f9120 \ + --hash=sha256:a82836cab5f197a0514235aaf7ffccdc886ccdaa2324bc0aafdd4ae898103039 \ + --hash=sha256:a8d00f29b42f534cc8aa3931cfe773b13b23e561e10d2b26f27a8d309b0e82a1 \ + --hash=sha256:aafe5dcfda86c8af00386d7781d4c2181b5011b7be3f2add5e99899ea925df05 \ + --hash=sha256:ab5f043cb8a2d71c981c09c510da013bc79fd661f5c60139f00dd3c3cc4f2ffb \ + --hash=sha256:ac09d42f48f80c9ee1635b2fcaa819496a44502737660d3c0f2ade7526d29144 \ + --hash=sha256:aecfed0b41aa72b7881712c65cf764e39ce2ec352324f5e0837c7048d9e6daaa \ + --hash=sha256:b2c6b50c7b0464165472b56b42d4c76a7b864597007d9c085e8b63e185cf4a7a \ + --hash=sha256:b35d13d549077713e4414f927cdc388d62e543987c572baee613bf82f11a4b99 \ + --hash=sha256:b39cb32a6582750b6cc77bfb3c49c0f8760dc18dc96ec9fb55fbb0f04e08b928 \ + --hash=sha256:b5405bb8f0e783a988172993cfc627e4d9d00432d6bbac65a923041edacf997d \ + --hash=sha256:baaf55442359053c7d62f6f8413a62adba3205119bcb6f49594894d8be47e5e3 \ + --hash=sha256:bd654fad46d8d9e823afbb4f87c79160b5a374ed1ff5bde24e542e6ba8f41434 \ + --hash=sha256:be61f6fff406ca40e3b1d84716fde398fc08bc63dd96d15f3a14230a0973ed86 \ + --hash=sha256:bf49a3ae946a87083ef3a34c8f677ae4243f5b824bfc4c69672e72b3d6719d46 \ + --hash=sha256:c4a80f77dc1acaaa61f0934176fccca7096d9b1ff08c8ba9cddf5ae034a24319 \ + --hash=sha256:c75eb09e8d55bceb4367e83496ff8ef2bc7ea6960efb38e978e8073ea59ecb67 \ + --hash=sha256:c7f8dc16c498ff06497c015642333219871effba93e4a2e8604a06264aca5c5c \ + --hash=sha256:c8aa34a5c864db1087d911a0b902d60d203ea3607d91f615acd3f3108ac32169 \ + --hash=sha256:cbb0fef01f0c6b38cb0f39b1f78fc90b807e0e3c86a7ff3ce74ad77ce5c7880c \ + --hash=sha256:cde9a2ecd91668bcb7f077c4966d8ceddb60af01b52e6e3e2680e4cf00ad1a59 \ + --hash=sha256:cff6d44cb13d39db2663a22b22305d10855efa0fa8015ddeacc40bc59b9d8107 \ + --hash=sha256:d1009abedb49ae95b136a8904a3f71b342f849ffeced2d3747bf29caeda218c4 \ + --hash=sha256:d38c1e8231722c4ce40d7593f28d92b5fc72f3e9774fe73d7e800ec32299f63a \ + --hash=sha256:d53834e23c015ee83a99377db6e5e37d8484f333edb03bd15b4bc312cc7254fb \ + --hash=sha256:d7504f2b476d21653e4d143f44a175f7f751cd41233525312696c76aa3dbb23f \ + --hash=sha256:dbf507e9ef5688bada447a24d68b4b58dd389ba93b7afc065a2ba892bea54769 \ + --hash=sha256:dc52310451fc7c629e13c4e061cbe2dd01684d91f2f8ee2821b083c58bd72432 \ + --hash=sha256:dd00607bffbf30250fe108065f07453ec124dbf223420f57f5e749b04295e090 \ + --hash=sha256:dda608c88cf709b1d406bdfcd84d8d63cff7c9e577a403c6108ce8ce9dcc8764 \ + --hash=sha256:debe9c4f41c32990771be5c22b56f810659f9ddf3d63f67abfdcaa2c6c9c5c1d \ + --hash=sha256:e09fd068c2e169a7070d83d3bde728a4d48de0549f975290be3c108c02e499b4 \ + --hash=sha256:e0fd068364a6759bc794459f0a735ab151d11304346332489c7972bacbe9e72b \ + --hash=sha256:e4c53f8347cd4200f0d70a48ad059cabaf24f5adc6ba08622a23423bc7efa10d \ + --hash=sha256:e5723c01a56c5028c807c701aa66722916d2747ad737a046853f6c46f4875543 \ + --hash=sha256:e7b0460976dc75cb87ad9cc1f9899a4b97751e7d4e77ab840fc9b6d377b8fd24 \ + --hash=sha256:e9d9a4d06d3481eab79803beb4d9bd6f6a8e781ec078ac70d7ef2dcc29d1bea5 \ + --hash=sha256:ead11956716a940c1abc816b7df3fa2b84d06eaed8832ca32f5c5e058c65506b \ + --hash=sha256:ed5f69ce7be7902e5c70ea19eb72d20abf7d725ab5d49777d696e32d4fc1811d \ + --hash=sha256:f2af5c81a1f124609d5f33507082fc3f739959d4719b56877ab1ee7e7b3d602b \ + --hash=sha256:f40e782d49630ad384db66d4d8b73ff4f1b8955dc12e26b09a3e3af064b3b9d6 \ + --hash=sha256:f514f6474e04179d3d33175ed3f3e31434d3130d42ec153540d5b157deefd735 \ + --hash=sha256:f69f57305656a4852f2a7203efc661d8c042e6cc67f7acd97d8667fb448a426e \ + --hash=sha256:fb1e8b8d66c278b21d13b0a7ca22c41dd757a7c209c6b12c313e445c31dd3b28 \ + --hash=sha256:fb4948814a2a98e3912505f09c9e7493b1506226afb1f881825368d6fb776ee3 \ + --hash=sha256:fda207c815b253e34f7e1909840fd14299567b1c0eb4908f8c2ce01a41265401 \ + --hash=sha256:fe8f8f5e70e6dbdfca9882cd9deaac058729bcf323cf7a58660901e55c9c94f6 \ + --hash=sha256:fffc45637bcd6538de8b85f51e3df3223e4ad89bccbfca0481c08c7fc8b7ed7d # via aiohttp zipp==3.23.0 \ --hash=sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e \ diff --git a/sdk/python/requirements/py3.10-requirements.txt b/sdk/python/requirements/py3.10-requirements.txt index 2eb2776034e..aaf668ef6ec 100644 --- a/sdk/python/requirements/py3.10-requirements.txt +++ b/sdk/python/requirements/py3.10-requirements.txt @@ -8,140 +8,156 @@ annotated-types==0.7.0 \ --hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \ --hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89 # via pydantic -anyio==4.12.1 \ - --hash=sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703 \ - --hash=sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c +anyio==4.13.0 \ + --hash=sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708 \ + --hash=sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc # via # starlette # watchfiles -attrs==25.4.0 \ - --hash=sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11 \ - --hash=sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373 +attrs==26.1.0 \ + --hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \ + --hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32 # via # jsonschema # referencing -bigtree==1.3.1 \ - --hash=sha256:a22a0ecd9b0abb283f4a1515370dbf1ec93adee70746767272e2c49d7af9f407 \ - --hash=sha256:c8b766b00188c532d3499bfd9e9666b357428db507fc701f088031a0d5c614d5 +bigtree==1.4.0 \ + --hash=sha256:d0d99550ae64ce4529f132602ab875c2ab472c96c942f5704f8c72a17450d3ea \ + --hash=sha256:e5ae2e948168da671d99601c9ed87ab3b48d9d4ea8a98f111e5748e98064c31c # via feast (pyproject.toml) -certifi==2026.1.4 \ - --hash=sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c \ - --hash=sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120 +certifi==2026.2.25 \ + --hash=sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa \ + --hash=sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7 # via requests -charset-normalizer==3.4.4 \ - --hash=sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad \ - --hash=sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93 \ - --hash=sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394 \ - --hash=sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89 \ - --hash=sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc \ - --hash=sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86 \ - --hash=sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63 \ - --hash=sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d \ - --hash=sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f \ - --hash=sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8 \ - --hash=sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0 \ - --hash=sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505 \ - --hash=sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161 \ - --hash=sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af \ - --hash=sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152 \ - --hash=sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318 \ - --hash=sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72 \ - --hash=sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4 \ - --hash=sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e \ - --hash=sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3 \ - --hash=sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576 \ - --hash=sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c \ - --hash=sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1 \ - --hash=sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8 \ - --hash=sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1 \ - --hash=sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2 \ - --hash=sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44 \ - --hash=sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26 \ - --hash=sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88 \ - --hash=sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016 \ - --hash=sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede \ - --hash=sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf \ - --hash=sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a \ - --hash=sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc \ - --hash=sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0 \ - --hash=sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84 \ - --hash=sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db \ - --hash=sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1 \ - --hash=sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7 \ - --hash=sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed \ - --hash=sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8 \ - --hash=sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133 \ - --hash=sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e \ - --hash=sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef \ - --hash=sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14 \ - --hash=sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2 \ - --hash=sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0 \ - --hash=sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d \ - --hash=sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828 \ - --hash=sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f \ - --hash=sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf \ - --hash=sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6 \ - --hash=sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328 \ - --hash=sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090 \ - --hash=sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa \ - --hash=sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381 \ - --hash=sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c \ - --hash=sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb \ - --hash=sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc \ - --hash=sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a \ - --hash=sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec \ - --hash=sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc \ - --hash=sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac \ - --hash=sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e \ - --hash=sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313 \ - --hash=sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569 \ - --hash=sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3 \ - --hash=sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d \ - --hash=sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525 \ - --hash=sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894 \ - --hash=sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3 \ - --hash=sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9 \ - --hash=sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a \ - --hash=sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9 \ - --hash=sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14 \ - --hash=sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25 \ - --hash=sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50 \ - --hash=sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf \ - --hash=sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1 \ - --hash=sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3 \ - --hash=sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac \ - --hash=sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e \ - --hash=sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815 \ - --hash=sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c \ - --hash=sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6 \ - --hash=sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6 \ - --hash=sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e \ - --hash=sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4 \ - --hash=sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84 \ - --hash=sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69 \ - --hash=sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15 \ - --hash=sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191 \ - --hash=sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0 \ - --hash=sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897 \ - --hash=sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd \ - --hash=sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2 \ - --hash=sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794 \ - --hash=sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d \ - --hash=sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074 \ - --hash=sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3 \ - --hash=sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224 \ - --hash=sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838 \ - --hash=sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a \ - --hash=sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d \ - --hash=sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d \ - --hash=sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f \ - --hash=sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8 \ - --hash=sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490 \ - --hash=sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966 \ - --hash=sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9 \ - --hash=sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3 \ - --hash=sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e \ - --hash=sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608 +charset-normalizer==3.4.7 \ + --hash=sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc \ + --hash=sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c \ + --hash=sha256:07d9e39b01743c3717745f4c530a6349eadbfa043c7577eef86c502c15df2c67 \ + --hash=sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4 \ + --hash=sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0 \ + --hash=sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c \ + --hash=sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5 \ + --hash=sha256:12a6fff75f6bc66711b73a2f0addfc4c8c15a20e805146a02d147a318962c444 \ + --hash=sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153 \ + --hash=sha256:14265bfe1f09498b9d8ec91e9ec9fa52775edf90fcbde092b25f4a33d444fea9 \ + --hash=sha256:16d971e29578a5e97d7117866d15889a4a07befe0e87e703ed63cd90cb348c01 \ + --hash=sha256:177a0ba5f0211d488e295aaf82707237e331c24788d8d76c96c5a41594723217 \ + --hash=sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b \ + --hash=sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c \ + --hash=sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a \ + --hash=sha256:1dc8b0ea451d6e69735094606991f32867807881400f808a106ee1d963c46a83 \ + --hash=sha256:1efde3cae86c8c273f1eb3b287be7d8499420cf2fe7585c41d370d3e790054a5 \ + --hash=sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7 \ + --hash=sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb \ + --hash=sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c \ + --hash=sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1 \ + --hash=sha256:2cd4a60d0e2fb04537162c62bbbb4182f53541fe0ede35cdf270a1c1e723cc42 \ + --hash=sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab \ + --hash=sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df \ + --hash=sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e \ + --hash=sha256:320ade88cfb846b8cd6b4ddf5ee9e80ee0c1f52401f2456b84ae1ae6a1a5f207 \ + --hash=sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18 \ + --hash=sha256:36836d6ff945a00b88ba1e4572d721e60b5b8c98c155d465f56ad19d68f23734 \ + --hash=sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38 \ + --hash=sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110 \ + --hash=sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18 \ + --hash=sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44 \ + --hash=sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d \ + --hash=sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48 \ + --hash=sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e \ + --hash=sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5 \ + --hash=sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d \ + --hash=sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53 \ + --hash=sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790 \ + --hash=sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c \ + --hash=sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b \ + --hash=sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116 \ + --hash=sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d \ + --hash=sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10 \ + --hash=sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6 \ + --hash=sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2 \ + --hash=sha256:6370e8686f662e6a3941ee48ed4742317cafbe5707e36406e9df792cdb535776 \ + --hash=sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a \ + --hash=sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265 \ + --hash=sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008 \ + --hash=sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943 \ + --hash=sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374 \ + --hash=sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246 \ + --hash=sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e \ + --hash=sha256:6e0d51f618228538a3e8f46bd246f87a6cd030565e015803691603f55e12afb5 \ + --hash=sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616 \ + --hash=sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15 \ + --hash=sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41 \ + --hash=sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960 \ + --hash=sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752 \ + --hash=sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e \ + --hash=sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72 \ + --hash=sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7 \ + --hash=sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8 \ + --hash=sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b \ + --hash=sha256:813c0e0132266c08eb87469a642cb30aaff57c5f426255419572aaeceeaa7bf4 \ + --hash=sha256:82b271f5137d07749f7bf32f70b17ab6eaabedd297e75dce75081a24f76eb545 \ + --hash=sha256:84c018e49c3bf790f9c2771c45e9313a08c2c2a6342b162cd650258b57817706 \ + --hash=sha256:8751d2787c9131302398b11e6c8068053dcb55d5a8964e114b6e196cf16cb366 \ + --hash=sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb \ + --hash=sha256:87fad7d9ba98c86bcb41b2dc8dbb326619be2562af1f8ff50776a39e55721c5a \ + --hash=sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e \ + --hash=sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00 \ + --hash=sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f \ + --hash=sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a \ + --hash=sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1 \ + --hash=sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66 \ + --hash=sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356 \ + --hash=sha256:a6c5863edfbe888d9eff9c8b8087354e27618d9da76425c119293f11712a6319 \ + --hash=sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4 \ + --hash=sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad \ + --hash=sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d \ + --hash=sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5 \ + --hash=sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7 \ + --hash=sha256:aef65cd602a6d0e0ff6f9930fcb1c8fec60dd2cfcb6facaf4bdb0e5873042db0 \ + --hash=sha256:af21eb4409a119e365397b2adbaca4c9ccab56543a65d5dbd9f920d6ac29f686 \ + --hash=sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34 \ + --hash=sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49 \ + --hash=sha256:bb8cc7534f51d9a017b93e3e85b260924f909601c3df002bcdb58ddb4dc41a5c \ + --hash=sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1 \ + --hash=sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e \ + --hash=sha256:bd9b23791fe793e4968dba0c447e12f78e425c59fc0e3b97f6450f4781f3ee60 \ + --hash=sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0 \ + --hash=sha256:c0f081d69a6e58272819b70288d3221a6ee64b98df852631c80f293514d3b274 \ + --hash=sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d \ + --hash=sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0 \ + --hash=sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae \ + --hash=sha256:c593052c465475e64bbfe5dbd81680f64a67fdc752c56d7a0ae205dc8aeefe0f \ + --hash=sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d \ + --hash=sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe \ + --hash=sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3 \ + --hash=sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393 \ + --hash=sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1 \ + --hash=sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af \ + --hash=sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44 \ + --hash=sha256:d61f00a0869d77422d9b2aba989e2d24afa6ffd552af442e0e58de4f35ea6d00 \ + --hash=sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c \ + --hash=sha256:dca4bbc466a95ba9c0234ef56d7dd9509f63da22274589ebd4ed7f1f4d4c54e3 \ + --hash=sha256:dd915403e231e6b1809fe9b6d9fc55cf8fb5e02765ac625d9cd623342a7905d7 \ + --hash=sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd \ + --hash=sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e \ + --hash=sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b \ + --hash=sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8 \ + --hash=sha256:e5f4d355f0a2b1a31bc3edec6795b46324349c9cb25eed068049e4f472fb4259 \ + --hash=sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859 \ + --hash=sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46 \ + --hash=sha256:e80c8378d8f3d83cd3164da1ad2df9e37a666cdde7b1cb2298ed0b558064be30 \ + --hash=sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b \ + --hash=sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46 \ + --hash=sha256:ed065083d0898c9d5b4bbec7b026fd755ff7454e6e8b73a67f8c744b13986e24 \ + --hash=sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a \ + --hash=sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24 \ + --hash=sha256:f22dec1690b584cea26fade98b2435c132c1b5f68e39f5a0b7627cd7ae31f1dc \ + --hash=sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215 \ + --hash=sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063 \ + --hash=sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832 \ + --hash=sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6 \ + --hash=sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79 \ + --hash=sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464 # via requests click==8.3.1 \ --hash=sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a \ @@ -158,9 +174,9 @@ colorama==0.4.6 \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 # via feast (pyproject.toml) -dask[dataframe]==2026.1.2 \ - --hash=sha256:1136683de2750d98ea792670f7434e6c1cfce90cab2cc2f2495a9e60fd25a4fc \ - --hash=sha256:46a0cf3b8d87f78a3d2e6b145aea4418a6d6d606fe6a16c79bd8ca2bb862bc91 +dask[dataframe]==2026.3.0 \ + --hash=sha256:be614b9242b0b38288060fb2d7696125946469c98a1c30e174883fd199e0428d \ + --hash=sha256:f7d96c8274e8a900d217c1ff6ea8d1bbf0b4c2c21e74a409644498d925eb8f85 # via feast (pyproject.toml) dill==0.3.9 \ --hash=sha256:468dff3b89520b474c0397703366b7b95eebe6303f108adf9b19da1f702be87a \ @@ -170,17 +186,17 @@ exceptiongroup==1.3.1 \ --hash=sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219 \ --hash=sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598 # via anyio -fastapi==0.129.0 \ - --hash=sha256:61315cebd2e65df5f97ec298c888f9de30430dd0612d59d6480beafbc10655af \ - --hash=sha256:b4946880e48f462692b31c083be0432275cbfb6e2274566b1be91479cc1a84ec +fastapi==0.135.3 \ + --hash=sha256:9b0f590c813acd13d0ab43dd8494138eb58e484bfac405db1f3187cfc5810d98 \ + --hash=sha256:bd6d7caf1a2bdd8d676843cdcd2287729572a1ef524fc4d65c17ae002a1be654 # via feast (pyproject.toml) -fsspec==2026.2.0 \ - --hash=sha256:6544e34b16869f5aacd5b90bdf1a71acb37792ea3ddf6125ee69a22a53fb8bff \ - --hash=sha256:98de475b5cb3bd66bedd5c4679e87b4fdfe1a3bf4d707b151b3c07e58c9a2437 +fsspec==2026.3.0 \ + --hash=sha256:1ee6a0e28677557f8c2f994e3eea77db6392b4de9cd1f5d7a9e87a0ae9d01b41 \ + --hash=sha256:d2ceafaad1b3457968ed14efa28798162f1638dbb5d2a6868a2db002a5ee39a4 # via dask -gunicorn==25.1.0 \ - --hash=sha256:1426611d959fa77e7de89f8c0f32eed6aa03ee735f98c01efba3e281b1c47616 \ - --hash=sha256:d0b1236ccf27f72cfe14bce7caadf467186f19e865094ca84221424e839b8b8b +gunicorn==25.3.0 \ + --hash=sha256:cacea387dab08cd6776501621c295a904fe8e3b7aae9a1a3cbb26f4e7ed54660 \ + --hash=sha256:f74e1b2f9f76f6cd1ca01198968bd2dd65830edc24b6e8e4d78de8320e2fe889 # via # feast (pyproject.toml) # uvicorn-worker @@ -239,9 +255,9 @@ idna==3.11 \ # via # anyio # requests -importlib-metadata==8.7.1 \ - --hash=sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb \ - --hash=sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151 +importlib-metadata==9.0.0 \ + --hash=sha256:2d21d1cc5a017bd0559e36150c21c830ab1dc304dedd1b7ea85d20f45ef3edd7 \ + --hash=sha256:a4f57ab599e6a2e3016d7595cfd72eb4661a5106e787a95bcc90c7105b831efc # via dask jinja2==3.1.6 \ --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ @@ -255,97 +271,97 @@ jsonschema-specifications==2025.9.1 \ --hash=sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe \ --hash=sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d # via jsonschema -librt==0.8.0 \ - --hash=sha256:001e5330093d887b8b9165823eca6c5c4db183fe4edea4fdc0680bbac5f46944 \ - --hash=sha256:015e2dde6e096d27c10238bf9f6492ba6c65822dfb69d2bf74c41a8e88b7ddef \ - --hash=sha256:02a9fe85410cc9bef045e7cb7fd26fdde6669e6d173f99df659aa7f6335961e9 \ - --hash=sha256:0583aef7e9a720dd40f26a2ad5a1bf2ccbb90059dac2b32ac516df232c701db3 \ - --hash=sha256:05a3dd3f116747f7e1a2b475ccdc6fb637fd4987126d109e03013a79d40bf9e6 \ - --hash=sha256:0a33335eb59921e77c9acc05d0e654e4e32e45b014a4d61517897c11591094f8 \ - --hash=sha256:0ce33a9778e294507f3a0e3468eccb6a698b5166df7db85661543eca1cfc5369 \ - --hash=sha256:1566dbb9d1eb0987264c9b9460d212e809ba908d2f4a3999383a84d765f2f3f1 \ - --hash=sha256:17269dd2745dbe8e42475acb28e419ad92dfa38214224b1b01020b8cac70b645 \ - --hash=sha256:178707cda89d910c3b28bf5aa5f69d3d4734e0f6ae102f753ad79edef83a83c7 \ - --hash=sha256:1c25a131013eadd3c600686a0c0333eb2896483cbc7f65baa6a7ee761017aef9 \ - --hash=sha256:1e6811cac1dcb27ca4c74e0ca4a5917a8e06db0d8408d30daee3a41724bfde7a \ - --hash=sha256:1ef3bd856373cf8e7382402731f43bfe978a8613b4039e49e166e1e0dc590216 \ - --hash=sha256:20f73d4fecba969efc15cdefd030e382502d56bb6f1fc66b580cce582836c9fa \ - --hash=sha256:21b14464bee0b604d80a638cf1ee3148d84ca4cc163dcdcecb46060c1b3605e4 \ - --hash=sha256:24a01c13a2a9bdad20997a4443ebe6e329df063d1978bbe2ebbf637878a46d1e \ - --hash=sha256:25b3e667cbfc9000c4740b282df599ebd91dbdcc1aa6785050e4c1d6be5329ab \ - --hash=sha256:25e82d920d4d62ad741592fcf8d0f3bda0e3fc388a184cb7d2f566c681c5f7b9 \ - --hash=sha256:2b37437e7e4ef5e15a297b36ba9e577f73e29564131d86dd75875705e97402b5 \ - --hash=sha256:2ccdd20d9a72c562ffb73098ac411de351b53a6fbb3390903b2d33078ef90447 \ - --hash=sha256:2e0ffe88ebb5962f8fb0ddcbaaff30f1ea06a79501069310e1e030eafb1ad787 \ - --hash=sha256:375eda7acfce1f15f5ed56cfc960669eefa1ec8732e3e9087c3c4c3f2066759c \ - --hash=sha256:3d2720335020219197380ccfa5c895f079ac364b4c429e96952cd6509934d8eb \ - --hash=sha256:3e36a8da17134ffc29373775d88c04832f9ecfab1880470661813e6c7991ef79 \ - --hash=sha256:3e8b77b5f54d0937b26512774916041756c9eb3e66f1031971e626eea49d0bf4 \ - --hash=sha256:41064a0c07b4cc7a81355ccc305cb097d6027002209ffca51306e65ee8293630 \ - --hash=sha256:421765e8c6b18e64d21c8ead315708a56fc24f44075059702e421d164575fdda \ - --hash=sha256:4831c44b8919e75ca0dfb52052897c1ef59fdae19d3589893fbd068f1e41afbf \ - --hash=sha256:48f84830a8f8ad7918afd743fd7c4eb558728bceab7b0e38fd5a5cf78206a556 \ - --hash=sha256:4b705f85311ee76acec5ee70806990a51f0deb519ea0c29c1d1652d79127604d \ - --hash=sha256:4d3e38797eb482485b486898f89415a6ab163bc291476bd95712e42cf4383c05 \ - --hash=sha256:4eb5e06ebcc668677ed6389164f52f13f71737fc8be471101fa8b4ce77baeb0c \ - --hash=sha256:4f6e975377fbc4c9567cb33ea9ab826031b6c7ec0515bfae66a4fb110d40d6da \ - --hash=sha256:4f764b2424cb04524ff7a486b9c391e93f93dc1bd8305b2136d25e582e99aa2f \ - --hash=sha256:507e94f4bec00b2f590fbe55f48cd518a208e2474a3b90a60aa8f29136ddbada \ - --hash=sha256:56901f1eec031396f230db71c59a01d450715cbbef9856bf636726994331195d \ - --hash=sha256:5cb11061a736a9db45e3c1293cfcb1e3caf205912dfa085734ba750f2197ff9a \ - --hash=sha256:5d0f76fc73480d42285c609c0ea74d79856c160fa828ff9aceab574ea4ecfd7b \ - --hash=sha256:667e2513cf69bfd1e1ed9a00d6c736d5108714ec071192afb737987955888a25 \ - --hash=sha256:671a6152edf3b924d98a5ed5e6982ec9cb30894085482acadce0975f031d4c5c \ - --hash=sha256:693697133c3b32aa9b27f040e3691be210e9ac4d905061859a9ed519b1d5a376 \ - --hash=sha256:6a3146c63220d814c4a2c7d6a1eacc8d5c14aed0ff85115c1dfea868080cd18f \ - --hash=sha256:6b6caff69e25d80c269b1952be8493b4d94ef745f438fa619d7931066bdd26de \ - --hash=sha256:6e1af31a710e17891d9adf0dbd9a5fcd94901a3922a96499abdbf7ce658f4e01 \ - --hash=sha256:70defb797c4d5402166787a6b3c66dfb3fa7f93d118c0509ffafa35a392f4258 \ - --hash=sha256:71fc517efc14f75c2f74b1f0a5d5eb4a8e06aa135c34d18eaf3522f4a53cd62d \ - --hash=sha256:75d1a8cab20b2043f03f7aab730551e9e440adc034d776f15f6f8d582b0a5ad4 \ - --hash=sha256:789911e8fa40a2e82f41120c936b1965f3213c67f5a483fc5a41f5839a05dcbb \ - --hash=sha256:7bd68cebf3131bb920d5984f75fe302d758db33264e44b45ad139385662d7bc3 \ - --hash=sha256:7ce0a8cb67e702dcb06342b2aaaa3da9fb0ddc670417879adfa088b44cf7b3b6 \ - --hash=sha256:7f820210e21e3a8bf8fde2ae3c3d10106d4de9ead28cbfdf6d0f0f41f5b12fa1 \ - --hash=sha256:8070aa3368559de81061ef752770d03ca1f5fc9467d4d512d405bd0483bfffe6 \ - --hash=sha256:82e61cd1c563745ad495387c3b65806bfd453badb4adbc019df3389dddee1bf6 \ - --hash=sha256:82fb4602d1b3e303a58bfe6165992b5a78d823ec646445356c332cd5f5bbaa61 \ - --hash=sha256:88c6e75540f1f10f5e0fc5e87b4b6c290f0e90d1db8c6734f670840494764af8 \ - --hash=sha256:8992ca186a1678107b0af3d0c9303d8c7305981b9914989b9788319ed4d89546 \ - --hash=sha256:92249938ab744a5890580d3cb2b22042f0dce71cdaa7c1369823df62bedf7cbc \ - --hash=sha256:95a719a049f0eefaf1952673223cf00d442952273cbd20cf2ed7ec423a0ef58d \ - --hash=sha256:9646178cd794704d722306c2c920c221abbf080fede3ba539d5afdec16c46dad \ - --hash=sha256:9726305d3e53419d27fc8cdfcd3f9571f0ceae22fa6b5ea1b3662c2e538f833e \ - --hash=sha256:995d24caa6bbb34bcdd4a41df98ac6d1af637cfa8975cb0790e47d6623e70e3e \ - --hash=sha256:9ab3a3475a55b89b87ffd7e6665838e8458e0b596c22e0177e0f961434ec474a \ - --hash=sha256:9f09d4884f882baa39a7e36bbf3eae124c4ca2a223efb91e567381d1c55c6b06 \ - --hash=sha256:a512c88900bdb1d448882f5623a0b1ad27ba81a9bd75dacfe17080b72272ca1f \ - --hash=sha256:a905091a13e0884701226860836d0386b88c72ce5c2fdfba6618e14c72be9f25 \ - --hash=sha256:aaadec87f45a3612b6818d1db5fbfe93630669b7ee5d6bdb6427ae08a1aa2141 \ - --hash=sha256:b055bb3abaf69abed25743d8fc1ab691e4f51a912ee0a6f9a6c84f4bbddb283d \ - --hash=sha256:b4bb00bd71b448f16749909b08a0ff16f58b079e2261c2e1000f2bbb2a4f0a45 \ - --hash=sha256:b9aef96d7593584e31ef6ac1eb9775355b0099fee7651fae3a15bc8657b67b52 \ - --hash=sha256:ba581acad5ac8f33e2ff1746e8a57e001b47c6721873121bf8bbcf7ba8bd3aa4 \ - --hash=sha256:ba9d9e60651615bc614be5e21a82cdb7b1769a029369cf4b4d861e4f19686fb6 \ - --hash=sha256:bbebd2bba5c6ae02907df49150e55870fdd7440d727b6192c46b6f754723dde9 \ - --hash=sha256:bd32add59b58fba3439d48d6f36ac695830388e3da3e92e4fc26d2d02670d19c \ - --hash=sha256:bdab762e2c0b48bab76f1a08acb3f4c77afd2123bedac59446aeaaeed3d086cf \ - --hash=sha256:c5512aae4648152abaf4d48b59890503fcbe86e85abc12fb9b096fe948bdd816 \ - --hash=sha256:c6e4c10761ddbc0d67d2f6e2753daf99908db85d8b901729bf2bf5eaa60e0567 \ - --hash=sha256:cb4b3ad543084ed79f186741470b251b9d269cd8b03556f15a8d1a99a64b7de5 \ - --hash=sha256:cb74cdcbc0103fc988e04e5c58b0b31e8e5dd2babb9182b6f9490488eb36324b \ - --hash=sha256:cc3d107f603b5ee7a79b6aa6f166551b99b32fb4a5303c4dfcb4222fc6a0335e \ - --hash=sha256:d920789eca7ef71df7f31fd547ec0d3002e04d77f30ba6881e08a630e7b2c30e \ - --hash=sha256:daae5e955764be8fd70a93e9e5133c75297f8bce1e802e1d3683b98f77e1c5ab \ - --hash=sha256:db63cf3586a24241e89ca1ce0b56baaec9d371a328bd186c529b27c914c9a1ef \ - --hash=sha256:db953b675079884ffda33d1dca7189fb961b6d372153750beb81880384300817 \ - --hash=sha256:de076eaba208d16efb5962f99539867f8e2c73480988cb513fcf1b5dbb0c9dcf \ - --hash=sha256:e79dbc8f57de360f0ed987dc7de7be814b4803ef0e8fc6d3ff86e16798c99935 \ - --hash=sha256:e9a3a38eb4134ad33122a6d575e6324831f930a771d951a15ce232e0237412c2 \ - --hash=sha256:f04ca50e847abc486fa8f4107250566441e693779a5374ba211e96e238f298b9 \ - --hash=sha256:f1178e0de0c271231a660fbef9be6acdfa1d596803464706862bef6644cc1cae \ - --hash=sha256:f4617cef654fca552f00ce5ffdf4f4b68770f18950e4246ce94629b789b92467 \ - --hash=sha256:fa37f99bff354ff191c6bcdffbc9d7cdd4fc37faccfc9be0ef3a4fd5613977da +librt==0.8.1 \ + --hash=sha256:01170b6729a438f0dedc4a26ed342e3dc4f02d1000b4b19f980e1877f0c297e6 \ + --hash=sha256:039b9f2c506bd0ab0f8725aa5ba339c6f0cd19d3b514b50d134789809c24285d \ + --hash=sha256:05bd41cdee35b0c59c259f870f6da532a2c5ca57db95b5f23689fcb5c9e42440 \ + --hash=sha256:086a32dbb71336627e78cc1d6ee305a68d038ef7d4c39aaff41ae8c9aa46e91a \ + --hash=sha256:08eec3a1fc435f0d09c87b6bf1ec798986a3544f446b864e4099633a56fcd9ed \ + --hash=sha256:0bf69d79a23f4f40b8673a947a234baeeb133b5078b483b7297c5916539cf5d5 \ + --hash=sha256:0c3811485fccfda840861905b8c70bba5ec094e02825598bb9d4ca3936857a04 \ + --hash=sha256:0d2f82168e55ddefd27c01c654ce52379c0750ddc31ee86b4b266bcf4d65f2a3 \ + --hash=sha256:0f2ae3725904f7377e11cc37722d5d401e8b3d5851fb9273d7f4fe04f6b3d37d \ + --hash=sha256:10c42e1f6fd06733ef65ae7bebce2872bcafd8d6e6b0a08fe0a05a23b044fb14 \ + --hash=sha256:153188fe98a72f206042be10a2c6026139852805215ed9539186312d50a8e972 \ + --hash=sha256:172d57ec04346b047ca6af181e1ea4858086c80bdf455f61994c4aa6fc3f866c \ + --hash=sha256:190b109bb69592a3401fe1ffdea41a2e73370ace2ffdc4a0e8e2b39cdea81b78 \ + --hash=sha256:1d3a7da44baf692f0c6aeb5b2a09c5e6fc7a703bca9ffa337ddd2e2da53f7732 \ + --hash=sha256:228c2409c079f8c11fb2e5d7b277077f694cb93443eb760e00b3b83cb8b3176c \ + --hash=sha256:22b46eabd76c1986ee7d231b0765ad387d7673bbd996aa0d0d054b38ac65d8f6 \ + --hash=sha256:237796479f4d0637d6b9cbcb926ff424a97735e68ade6facf402df4ec93375ed \ + --hash=sha256:2c74a2da57a094bd48d03fa5d196da83d2815678385d2978657499063709abe1 \ + --hash=sha256:2cc68eeeef5e906839c7bb0815748b5b0a974ec27125beefc0f942715785b551 \ + --hash=sha256:2eb345e8b33fb748227409c9f1233d4df354d6e54091f0e8fc53acdb2ffedeb7 \ + --hash=sha256:31362dbfe297b23590530007062c32c6f6176f6099646bb2c95ab1b00a57c382 \ + --hash=sha256:3dff3d3ca8db20e783b1bc7de49c0a2ab0b8387f31236d6a026597d07fcd68ac \ + --hash=sha256:43353b943613c5d9c49a25aaffdba46f888ec354e71e3529a00cca3f04d66a7a \ + --hash=sha256:439352ba9373f11cb8e1933da194dcc6206daf779ff8df0ed69c5e39113e6a99 \ + --hash=sha256:4998009e7cb9e896569f4be7004f09d0ed70d386fa99d42b6d363f6d200501ac \ + --hash=sha256:4be2a5c926b9770c9e08e717f05737a269b9d0ebc5d2f0060f0fe3fe9ce47acb \ + --hash=sha256:4beb04b8c66c6ae62f8c1e0b2f097c1ebad9295c929a8d5286c05eae7c2fc7dc \ + --hash=sha256:4c8dfa264b9193c4ee19113c985c95f876fae5e51f731494fc4e0cf594990ba7 \ + --hash=sha256:5212a5bd7fae98dae95710032902edcd2ec4dc994e883294f75c857b83f9aba0 \ + --hash=sha256:52c224e14614b750c0a6d97368e16804a98c684657c7518752c356834fff83bb \ + --hash=sha256:56e04c14b696300d47b3bc5f1d10a00e86ae978886d0cee14e5714fafb5df5d2 \ + --hash=sha256:5bb54f1205a3a6ab41a6fd71dfcdcbd278670d3a90ca502a30d9da583105b6f7 \ + --hash=sha256:5cdc0f588ff4b663ea96c26d2a230c525c6fc62b28314edaaaca8ed5af931ad0 \ + --hash=sha256:5db05697c82b3a2ec53f6e72b2ed373132b0c2e05135f0696784e97d7f5d48e7 \ + --hash=sha256:5e4af413908f77294605e28cfd98063f54b2c790561383971d2f52d113d9c363 \ + --hash=sha256:5fc48998000cbc39ec0d5311312dda93ecf92b39aaf184c5e817d5d440b29624 \ + --hash=sha256:60a78b694c9aee2a0f1aaeaa7d101cf713e92e8423a941d2897f4fa37908dab9 \ + --hash=sha256:64548cde61b692dc0dc379f4b5f59a2f582c2ebe7890d09c1ae3b9e66fa015b7 \ + --hash=sha256:681dc2451d6d846794a828c16c22dc452d924e9f700a485b7ecb887a30aad1fd \ + --hash=sha256:6b1977c4ea97ce5eb7755a78fae68d87e4102e4aaf54985e8b56806849cc06a3 \ + --hash=sha256:6cfa7fe54fd4d1f47130017351a959fe5804bda7a0bc7e07a2cdbc3fdd28d34f \ + --hash=sha256:738f08021b3142c2918c03692608baed43bc51144c29e35807682f8070ee2a3a \ + --hash=sha256:747328be0c5b7075cde86a0e09d7a9196029800ba75a1689332348e998fb85c0 \ + --hash=sha256:758509ea3f1eba2a57558e7e98f4659d0ea7670bff49673b0dde18a3c7e6c0eb \ + --hash=sha256:785ae29c1f5c6e7c2cde2c7c0e148147f4503da3abc5d44d482068da5322fd9e \ + --hash=sha256:7aae78ab5e3206181780e56912d1b9bb9f90a7249ce12f0e8bf531d0462dd0fc \ + --hash=sha256:7b02679a0d783bdae30d443025b94465d8c3dc512f32f5b5031f93f57ac32071 \ + --hash=sha256:7e2f3edca35664499fbb36e4770650c4bd4a08abc1f4458eab9df4ec56389730 \ + --hash=sha256:7e6bad1cd94f6764e1e21950542f818a09316645337fd5ab9a7acc45d99a8f35 \ + --hash=sha256:81fd938344fecb9373ba1b155968c8a329491d2ce38e7ddb76f30ffb938f12dc \ + --hash=sha256:82210adabbc331dbb65d7868b105185464ef13f56f7f76688565ad79f648b0fe \ + --hash=sha256:89815a22daf9c51884fb5dbe4f1ef65ee6a146e0b6a8df05f753e2e4a9359bf4 \ + --hash=sha256:8f1125e6bbf2f1657d9a2f3ccc4a2c9b0c8b176965bb565dd4d86be67eddb4b6 \ + --hash=sha256:8f4bb453f408137d7581be309b2fbc6868a80e7ef60c88e689078ee3a296ae71 \ + --hash=sha256:924817ab3141aca17893386ee13261f1d100d1ef410d70afe4389f2359fea4f0 \ + --hash=sha256:93c2af9e01e0ef80d95ae3c720be101227edae5f2fe7e3dc63d8857fadfc5a1d \ + --hash=sha256:97c2b54ff6717a7a563b72627990bec60d8029df17df423f0ed37d56a17a176b \ + --hash=sha256:9be2f15e53ce4e83cc08adc29b26fb5978db62ef2a366fbdf716c8a6c8901040 \ + --hash=sha256:9e2c6f77b9ad48ce5603b83b7da9ee3e36b3ab425353f695cba13200c5d96596 \ + --hash=sha256:a28f2612ab566b17f3698b0da021ff9960610301607c9a5e8eaca62f5e1c350a \ + --hash=sha256:a355d99c4c0d8e5b770313b8b247411ed40949ca44e33e46a4789b9293a907ee \ + --hash=sha256:a3b4350b13cc0e6f5bec8fa7caf29a8fb8cdc051a3bae45cfbfd7ce64f009965 \ + --hash=sha256:aaab0e307e344cb28d800957ef3ec16605146ef0e59e059a60a176d19543d1b7 \ + --hash=sha256:ac1e7817fd0ed3d14fd7c5df91daed84c48e4c2a11ee99c0547f9f62fdae13da \ + --hash=sha256:adfab487facf03f0d0857b8710cf82d0704a309d8ffc33b03d9302b4c64e91a9 \ + --hash=sha256:b6d7ab1f01aa753188605b09a51faa44a3327400b00b8cce424c71910fc0a128 \ + --hash=sha256:bacdb58d9939d95cc557b4dbaa86527c9db2ac1ed76a18bc8d26f6dc8647d851 \ + --hash=sha256:be46a14693955b3bd96014ccbdb8339ee8c9346fbe11c1b78901b55125f14c73 \ + --hash=sha256:bf512a71a23504ed08103a13c941f763db13fb11177beb3d9244c98c29fb4a61 \ + --hash=sha256:c00e5c884f528c9932d278d5c9cbbea38a6b81eb62c02e06ae53751a83a4d52b \ + --hash=sha256:c25d9e338d5bed46c1632f851babf3d13c78f49a225462017cf5e11e845c5891 \ + --hash=sha256:c336d61d2fe74a3195edc1646d53ff1cddd3a9600b09fa6ab75e5514ba4862a7 \ + --hash=sha256:cc3656283d11540ab0ea01978378e73e10002145117055e03722417aeab30994 \ + --hash=sha256:cf450f498c30af55551ba4f66b9123b7185362ec8b625a773b3d39aa1a717583 \ + --hash=sha256:d0ee06b5b5291f609ddb37b9750985b27bc567791bc87c76a569b3feed8481ac \ + --hash=sha256:d480de377f5b687b6b1bc0c0407426da556e2a757633cc7e4d2e1a057aa688f3 \ + --hash=sha256:d56bc4011975f7460bea7b33e1ff425d2f1adf419935ff6707273c77f8a4ada6 \ + --hash=sha256:dd3c41254ee98604b08bd5b3af5bf0a89740d4ee0711de95b65166bf44091921 \ + --hash=sha256:e0d138c7ae532908cbb342162b2611dbd4d90c941cd25ab82084aaf71d2c0bd0 \ + --hash=sha256:e11769a1dbda4da7b00a76cfffa67aa47cfa66921d2724539eee4b9ede780b79 \ + --hash=sha256:e3f0a41487fd5fad7e760b9e8a90e251e27c2816fbc2cff36a22a0e6bcbbd9dd \ + --hash=sha256:e692aa2d1d604e6ca12d35e51fdc36f4cda6345e28e36374579f7ef3611b3012 \ + --hash=sha256:e70a57ecf89a0f64c24e37f38d3fe217a58169d2fe6ed6d70554964042474023 \ + --hash=sha256:e96baa6820280077a78244b2e06e416480ed859bbd8e5d641cf5742919d8beb4 \ + --hash=sha256:eb5656019db7c4deacf0c1a55a898c5bb8f989be904597fcb5232a2f4828fa05 \ + --hash=sha256:eca45e982fa074090057132e30585a7e8674e9e885d402eae85633e9f449ce6c \ + --hash=sha256:f0af2bd2bc204fa27f3d6711d0f360e6b8c684a035206257a81673ab924aa11e \ + --hash=sha256:f7cdf7f26c2286ffb02e46d7bac56c94655540b26347673bea15fa52a6af17e9 \ + --hash=sha256:fd1a720332ea335ceb544cf0a03f81df92abd4bb887679fd1e460976b0e6214b \ + --hash=sha256:ff8baf1f8d3f4b6b7257fcb75a501f2a5499d0dda57645baa09d4d0d34b19444 # via mypy locket==1.0.0 \ --hash=sha256:5c0d4c052a8bbbf750e056a8e65ccd309086f4f0f18a2eac306a8dfa4112a632 \ @@ -442,168 +458,160 @@ markupsafe==3.0.3 \ --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \ --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50 # via jinja2 -mmh3==5.2.0 \ - --hash=sha256:03e08c6ebaf666ec1e3d6ea657a2d363bb01effd1a9acfe41f9197decaef0051 \ - --hash=sha256:097e13c8b8a66c5753c6968b7640faefe85d8e38992703c1f666eda6ef4c3762 \ - --hash=sha256:0b898cecff57442724a0f52bf42c2de42de63083a91008fb452887e372f9c328 \ - --hash=sha256:10983c10f5c77683bd845751905ba535ec47409874acc759d5ce3ff7ef34398a \ - --hash=sha256:11730eeb16dfcf9674fdea9bb6b8e6dd9b40813b7eb839bc35113649eef38aeb \ - --hash=sha256:127c95336f2a98c51e7682341ab7cb0be3adb9df0819ab8505a726ed1801876d \ - --hash=sha256:12da42c0a55c9d86ab566395324213c319c73ecb0c239fad4726324212b9441c \ - --hash=sha256:132dd943451a7c7546978863d2f5a64977928410782e1a87d583cb60eb89e667 \ - --hash=sha256:1556e31e4bd0ac0c17eaf220be17a09c171d7396919c3794274cb3415a9d3646 \ - --hash=sha256:1a5f4d2e59d6bba8ef01b013c472741835ad961e7c28f50c82b27c57748744a4 \ - --hash=sha256:1ba55d6ca32eeef8b2625e1e4bfc3b3db52bc63014bd7e5df8cc11bf2b036b12 \ - --hash=sha256:1efc8fec8478e9243a78bb993422cf79f8ff85cb4cf6b79647480a31e0d950a8 \ - --hash=sha256:1f8d8b627799f4e2fcc7c034fed8f5f24dc7724ff52f69838a3d6d15f1ad4765 \ - --hash=sha256:1fae471339ae1b9c641f19cf46dfe6ffd7f64b1fba7c4333b99fa3dd7f21ae0a \ - --hash=sha256:1fdb36b940e9261aff0b5177c5b74a36936b902f473180f6c15bde26143681a9 \ - --hash=sha256:2421b9d665a0b1ad724ec7332fb5a98d075f50bc51a6ff854f3a1882bd650d49 \ - --hash=sha256:29c2b9ce61886809d0492a274a5a53047742dea0f703f9c4d5d223c3ea6377d3 \ - --hash=sha256:2c9da0d568569cc87315cb063486d761e38458b8ad513fedd3dc9263e1b81bcd \ - --hash=sha256:2ebfc46b39168ab1cd44670a32ea5489bcbc74a25795c61b6d888c5c2cf654ed \ - --hash=sha256:3193752fc05ea72366c2b63ff24b9a190f422e32d75fdeae71087c08fff26115 \ - --hash=sha256:33576136c06b46a7046b6d83a3d75fbca7d25f84cec743f1ae156362608dc6d2 \ - --hash=sha256:37a358cc881fe796e099c1db6ce07ff757f088827b4e8467ac52b7a7ffdca647 \ - --hash=sha256:382a6bb3f8c6532ea084e7acc5be6ae0c6effa529240836d59352398f002e3fc \ - --hash=sha256:384eda9361a7bf83a85e09447e1feafe081034af9dd428893701b959230d84be \ - --hash=sha256:38d899a156549da8ef6a9f1d6f7ef231228d29f8f69bce2ee12f5fba6d6fd7c5 \ - --hash=sha256:3bc244802ccab5220008cb712ca1508cb6a12f0eb64ad62997156410579a1770 \ - --hash=sha256:3c6041fd9d5fb5fcac57d5c80f521a36b74aea06b8566431c63e4ffc49aced51 \ - --hash=sha256:3ca975c51c5028947bbcfc24966517aac06a01d6c921e30f7c5383c195f87991 \ - --hash=sha256:3d6bfd9662a20c054bc216f861fa330c2dac7c81e7fb8307b5e32ab5b9b4d2e0 \ - --hash=sha256:419005f84ba1cab47a77465a2a843562dadadd6671b8758bf179d82a15ca63eb \ - --hash=sha256:45b590e31bc552c6f8e2150ff1ad0c28dd151e9f87589e7eaf508fbdd8e8e908 \ - --hash=sha256:49037d417419863b222ae47ee562b2de9c3416add0a45c8d7f4e864be8dc4f89 \ - --hash=sha256:4a5f5536b1cbfa72318ab3bfc8a8188b949260baed186b75f0abc75b95d8c051 \ - --hash=sha256:582f9dbeefe15c32a5fa528b79b088b599a1dfe290a4436351c6090f90ddebb8 \ - --hash=sha256:58477cf9ef16664d1ce2b038f87d2dc96d70fe50733a34a7f07da6c9a5e3538c \ - --hash=sha256:58981d6ea9646dbbf9e59a30890cbf9f610df0e4a57dbfe09215116fd90b0093 \ - --hash=sha256:5a5dba98e514fb26241868f6eb90a7f7ca0e039aed779342965ce24ea32ba513 \ - --hash=sha256:5b0b58215befe0f0e120b828f7645e97719bbba9f23b69e268ed0ac7adde8645 \ - --hash=sha256:61ac226af521a572700f863d6ecddc6ece97220ce7174e311948ff8c8919a363 \ - --hash=sha256:63830f846797187c5d3e2dae50f0848fdc86032f5bfdc58ae352f02f857e9025 \ - --hash=sha256:69fc339d7202bea69ef9bd7c39bfdf9fdabc8e6822a01eba62fb43233c1b3932 \ - --hash=sha256:6d541038b3fc360ec538fc116de87462627944765a6750308118f8b509a8eec7 \ - --hash=sha256:6ecb4e750d712abde046858ee6992b65c93f1f71b397fce7975c3860c07365d2 \ - --hash=sha256:72d80005b7634a3a2220f81fbeb94775ebd12794623bb2e1451701ea732b4aa3 \ - --hash=sha256:7303aab41e97adcf010a09efd8f1403e719e59b7705d5e3cfed3dd7571589290 \ - --hash=sha256:7434a27754049144539d2099a6d2da5d88b8bdeedf935180bf42ad59b3607aa3 \ - --hash=sha256:746a5ee71c6d1103d9b560fa147881b5e68fd35da56e54e03d5acefad0e7c055 \ - --hash=sha256:7733ec52296fc1ba22e9b90a245c821adbb943e98c91d8a330a2254612726106 \ - --hash=sha256:7901c893e704ee3c65f92d39b951f8f34ccf8e8566768c58103fb10e55afb8c1 \ - --hash=sha256:7aa18cdb58983ee660c9c400b46272e14fa253c675ed963d3812487f8ca42037 \ - --hash=sha256:7b986d506a8e8ea345791897ba5d8ba0d9d8820cd4fc3e52dbe6de19388de2e7 \ - --hash=sha256:7bbb0df897944b5ec830f3ad883e32c5a7375370a521565f5fe24443bfb2c4f7 \ - --hash=sha256:7c7f0b342fd06044bedd0b6e72177ddc0076f54fd89ee239447f8b271d919d9b \ - --hash=sha256:7e5634565367b6d98dc4aa2983703526ef556b3688ba3065edb4b9b90ede1c54 \ - --hash=sha256:7fddccd4113e7b736706e17a239a696332360cbaddf25ae75b57ba1acce65081 \ - --hash=sha256:81c504ad11c588c8629536b032940f2a359dda3b6cbfd4ad8f74cb24dcd1b0bc \ - --hash=sha256:81df0dae22cd0da87f1c978602750f33d17fb3d21fb0f326c89dc89834fea79b \ - --hash=sha256:86d1be5d63232e6eb93c50881aea55ff06eb86d8e08f9b5417c8c9b10db9db96 \ - --hash=sha256:8b0c53fe0994beade1ad7c0f13bd6fec980a0664bfbe5a6a7d64500b9ab76772 \ - --hash=sha256:8ebf241072cf2777a492d0e09252f8cc2b3edd07dfdb9404b9757bffeb4f2cee \ - --hash=sha256:931d47e08c9c8a67bf75d82f0ada8399eac18b03388818b62bfa42882d571d72 \ - --hash=sha256:932a6eec1d2e2c3c9e630d10f7128d80e70e2d47fe6b8c7ea5e1afbd98733e65 \ - --hash=sha256:941603bfd75a46023807511c1ac2f1b0f39cccc393c15039969806063b27e6db \ - --hash=sha256:956127e663d05edbeec54df38885d943dfa27406594c411139690485128525de \ - --hash=sha256:96f1e1ac44cbb42bcc406e509f70c9af42c594e72ccc7b1257f97554204445f0 \ - --hash=sha256:99bb6a4d809aa4e528ddfe2c85dd5239b78b9dd14be62cca0329db78505e7b50 \ - --hash=sha256:9f64bf06f4bf623325fda3a6d02d36cd69199b9ace99b04bb2d7fd9f89688504 \ - --hash=sha256:a094319ec0db52a04af9fdc391b4d39a1bc72bc8424b47c4411afb05413a44b5 \ - --hash=sha256:a367d4741ac0103f8198c82f429bccb9359f543ca542b06a51f4f0332e8de279 \ - --hash=sha256:a7c0c7845566b9686480e6a7e9044db4afb60038d5fabd19227443f0104eeee4 \ - --hash=sha256:aa6e5d31fdc5ed9e3e95f9873508615a778fe9b523d52c17fc770a3eb39ab6e4 \ - --hash=sha256:ae9d032488fcec32d22be6542d1a836f00247f40f320844dbb361393b5b22773 \ - --hash=sha256:b0271ac12415afd3171ab9a3c7cbfc71dee2c68760a7dc9d05bf8ed6ddfa3a7a \ - --hash=sha256:b0d753ad566c721faa33db7e2e0eddd74b224cdd3eaf8481d76c926603c7a00e \ - --hash=sha256:b29044e1ffdb84fe164d0a7ea05c7316afea93c00f8ed9449cf357c36fc4f814 \ - --hash=sha256:b5995088dd7023d2d9f310a0c67de5a2b2e06a570ecfd00f9ff4ab94a67cde43 \ - --hash=sha256:b5f317a727bba0e633a12e71228bc6a4acb4f471a98b1c003163b917311ea9a9 \ - --hash=sha256:b9a87025121d1c448f24f27ff53a5fe7b6ef980574b4a4f11acaabe702420d63 \ - --hash=sha256:bb0fdc451fb6d86d81ab8f23d881b8d6e37fc373a2deae1c02d27002d2ad7a05 \ - --hash=sha256:bb4fe46bdc6104fbc28db7a6bacb115ee6368ff993366bbd8a2a7f0076e6f0c0 \ - --hash=sha256:bc44fc2b886243d7c0d8daeb37864e16f232e5b56aaec27cc781d848264cfd28 \ - --hash=sha256:bdde97310d59604f2a9119322f61b31546748499a21b44f6715e8ced9308a6c5 \ - --hash=sha256:be1374df449465c9f2500e62eee73a39db62152a8bdfbe12ec5b5c1cd451344d \ - --hash=sha256:be7d3dca9358e01dab1bad881fb2b4e8730cec58d36dd44482bc068bfcd3bc65 \ - --hash=sha256:bf7bee43e17e81671c447e9c83499f53d99bf440bc6d9dc26a841e21acfbe094 \ - --hash=sha256:c3dca4cb5b946ee91b3d6bb700d137b1cd85c20827f89fdf9c16258253489044 \ - --hash=sha256:c3f563e8901960e2eaa64c8e8821895818acabeb41c96f2efbb936f65dbe486c \ - --hash=sha256:c463d7c1c4cfc9d751efeaadd936bbba07b5b0ed81a012b3a9f5a12f0872bd6e \ - --hash=sha256:c4a2f3d83879e3de2eb8cbf562e71563a8ed15ee9b9c2e77ca5d9f73072ac15c \ - --hash=sha256:c5584061fd3da584659b13587f26c6cad25a096246a481636d64375d0c1f6c07 \ - --hash=sha256:c677d78887244bf3095020b73c42b505b700f801c690f8eaa90ad12d3179612f \ - --hash=sha256:c903e71fd8debb35ad2a4184c1316b3cb22f64ce517b4e6747f25b0a34e41266 \ - --hash=sha256:c9ff37ba9f15637e424c2ab57a1a590c52897c845b768e4e0a4958084ec87f22 \ - --hash=sha256:cadc16e8ea64b5d9a47363013e2bea469e121e6e7cb416a7593aeb24f2ad122e \ - --hash=sha256:cedac4f4054b8f7859e5aed41aaa31ad03fce6851901a7fdc2af0275ac533c10 \ - --hash=sha256:d22c9dcafed659fadc605538946c041722b6d1104fe619dbf5cc73b3c8a0ded8 \ - --hash=sha256:d765058da196f68dc721116cab335e696e87e76720e6ef8ee5a24801af65e63d \ - --hash=sha256:d86651fa45799530885ba4dab3d21144486ed15285e8784181a0ab37a4552384 \ - --hash=sha256:dd966df3489ec13848d6c6303429bbace94a153f43d1ae2a55115fd36fd5ca5d \ - --hash=sha256:ddc63328889bcaee77b743309e5c7d2d52cee0d7d577837c91b6e7cc9e755e0b \ - --hash=sha256:dfbead5575f6470c17e955b94f92d62a03dfc3d07f2e6f817d9b93dc211a1515 \ - --hash=sha256:e0f3ed828d709f5b82d8bfe14f8856120718ec4bd44a5b26102c3030a1e12501 \ - --hash=sha256:e1861fb6b1d0453ed7293200139c0a9011eeb1376632e048e3766945b13313c5 \ - --hash=sha256:e5015f0bb6eb50008bed2d4b1ce0f2a294698a926111e4bb202c0987b4f89078 \ - --hash=sha256:e651e17bfde5840e9e4174b01e9e080ce49277b70d424308b36a7969d0d1af73 \ - --hash=sha256:e7884931fe5e788163e7b3c511614130c2c59feffdc21112290a194487efb2e9 \ - --hash=sha256:e79c00eba78f7258e5b354eccd4d7907d60317ced924ea4a5f2e9d83f5453065 \ - --hash=sha256:e912b19cf2378f2967d0c08e86ff4c6c360129887f678e27e4dde970d21b3f4d \ - --hash=sha256:e9a011469b47b752e7d20de296bb34591cdfcbe76c99c2e863ceaa2aa61113d2 \ - --hash=sha256:eb756caf8975882630ce4e9fbbeb9d3401242a72528230422c9ab3a0d278e60c \ - --hash=sha256:eba01ec3bd4a49b9ac5ca2bc6a73ff5f3af53374b8556fcc2966dd2af9eb7779 \ - --hash=sha256:ecbfc0437ddfdced5e7822d1ce4855c9c64f46819d0fdc4482c53f56c707b935 \ - --hash=sha256:eed4bba7ff8a0d37106ba931ab03bdd3915fbb025bcf4e1f0aa02bc8114960c5 \ - --hash=sha256:f35727c5118aba95f0397e18a1a5b8405425581bfe53e821f0fb444cbdc2bc9b \ - --hash=sha256:f698733a8a494466432d611a8f0d1e026f5286dee051beea4b3c3146817e35d5 \ - --hash=sha256:f7f9034c7cf05ddfaac8d7a2e63a3c97a840d4615d0a0e65ba8bdf6f8576e3be \ - --hash=sha256:fa0c966ee727aad5406d516375593c5f058c766b21236ab8985693934bb5085b \ - --hash=sha256:fc9c5f280438cf1c1a8f9abb87dc8ce9630a964120cfb5dd50d1e7ce79690c7a \ - --hash=sha256:fd6e6c3d90660d085f7e73710eab6f5545d4854b81b0135a3526e797009dbda3 \ - --hash=sha256:fdfd3fb739f4e22746e13ad7ba0c6eedf5f454b18d11249724a388868e308ee4 \ - --hash=sha256:ff3d50dc3fe8a98059f99b445dfb62792b5d006c5e0b8f03c6de2813b8376110 +mmh3==5.2.1 \ + --hash=sha256:022aa1a528604e6c83d0a7705fdef0b5355d897a9e0fa3a8d26709ceaa06965d \ + --hash=sha256:0634581290e6714c068f4aa24020acf7880927d1f0084fa753d9799ae9610082 \ + --hash=sha256:08043f7cb1fb9467c3fbbbaea7896986e7fbc81f4d3fd9289a73d9110ab6207a \ + --hash=sha256:0a3984146e414684a6be2862d84fcb1035f4984851cb81b26d933bab6119bf00 \ + --hash=sha256:0bbc17250b10d3466875a40a52520a6bac3c02334ca709207648abd3c223ed5c \ + --hash=sha256:0cc21533878e5586b80d74c281d7f8da7932bc8ace50b8d5f6dbf7e3935f63f1 \ + --hash=sha256:0d0b7e803191db5f714d264044e06189c8ccd3219e936cc184f07106bd17fd7b \ + --hash=sha256:113f78e7463a36dbbcea05bfe688efd7fa759d0f0c56e73c974d60dcfec3dfcc \ + --hash=sha256:169e0d178cb59314456ab30772429a802b25d13227088085b0d49b9fe1533104 \ + --hash=sha256:17fbb47f0885ace8327ce1235d0416dc86a211dcd8cc1e703f41523be32cfec8 \ + --hash=sha256:19bbd3b841174ae6ed588536ab5e1b1fe83d046e668602c20266547298d939a9 \ + --hash=sha256:1d9f9a3ce559a5267014b04b82956993270f63ec91765e13e9fd73daf2d2738e \ + --hash=sha256:1e4ecee40ba19e6975e1120829796770325841c2f153c0e9aecca927194c6a2a \ + --hash=sha256:22b0f9971ec4e07e8223f2beebe96a6cfc779d940b6f27d26604040dd74d3a44 \ + --hash=sha256:26fb5b9c3946bf7f1daed7b37e0c03898a6f062149127570f8ede346390a0825 \ + --hash=sha256:2778fed822d7db23ac5008b181441af0c869455b2e7d001f4019636ac31b6fe4 \ + --hash=sha256:28cfab66577000b9505a0d068c731aee7ca85cd26d4d63881fab17857e0fe1fb \ + --hash=sha256:29bc3973676ae334412efdd367fcd11d036b7be3efc1ce2407ef8676dabfeb82 \ + --hash=sha256:2bd9f19f7f1fcebd74e830f4af0f28adad4975d40d80620be19ffb2b2af56c9f \ + --hash=sha256:2d5d542bf2abd0fd0361e8017d03f7cb5786214ceb4a40eef1539d6585d93386 \ + --hash=sha256:30e4d2084df019880d55f6f7bea35328d9b464ebee090baa372c096dc77556fb \ + --hash=sha256:3619473a0e0d329fd4aec8075628f8f616be2da41605300696206d6f36920c3d \ + --hash=sha256:368625fb01666655985391dbad3860dc0ba7c0d6b9125819f3121ee7292b4ac8 \ + --hash=sha256:3737303ca9ea0f7cb83028781148fcda4f1dac7821db0c47672971dabcf63593 \ + --hash=sha256:3a9fed49c6ce4ed7e73f13182760c65c816da006debe67f37635580dfb0fae00 \ + --hash=sha256:3c38d142c706201db5b2345166eeef1e7740e3e2422b470b8ba5c8727a9b4c7a \ + --hash=sha256:3cb61db880ec11e984348227b333259994c2c85caa775eb7875decb3768db890 \ + --hash=sha256:3d74a03fb57757ece25aa4b3c1c60157a1cece37a020542785f942e2f827eed5 \ + --hash=sha256:3f796b535008708846044c43302719c6956f39ca2d93f2edda5319e79a29efbb \ + --hash=sha256:41105377f6282e8297f182e393a79cfffd521dde37ace52b106373bdcd9ca5cb \ + --hash=sha256:41aac7002a749f08727cb91babff1daf8deac317c0b1f317adc69be0e6c375d1 \ + --hash=sha256:44983e45310ee5b9f73397350251cdf6e63a466406a105f1d16cb5baa659270b \ + --hash=sha256:4cbbde66f1183db040daede83dd86c06d663c5bb2af6de1142b7c8c37923dd74 \ + --hash=sha256:4eda76074cfca2787c8cf1bec603eaebdddd8b061ad5502f85cddae998d54f00 \ + --hash=sha256:4fc6cd65dc4d2fdb2625e288939a3566e36127a84811a4913f02f3d5931da52d \ + --hash=sha256:50885073e2909251d4718634a191c49ae5f527e5e1736d738e365c3e8be8f22b \ + --hash=sha256:5174a697ce042fa77c407e05efe41e03aa56dae9ec67388055820fb48cf4c3ba \ + --hash=sha256:54b64fb2433bc71488e7a449603bf8bd31fbcf9cb56fbe1eb6d459e90b86c37b \ + --hash=sha256:54fe8518abe06a4c3852754bfd498b30cc58e667f376c513eac89a244ce781a4 \ + --hash=sha256:55dbbd8ffbc40d1697d5e2d0375b08599dae8746b0b08dea05eee4ce81648fac \ + --hash=sha256:57b52603e89355ff318025dd55158f6e71396c0f1f609d548e9ea9c94cc6ce0a \ + --hash=sha256:58370d05d033ee97224c81263af123dea3d931025030fd34b61227a768a8858a \ + --hash=sha256:5d87a3584093e1a89987e3d36d82c98d9621b2cb944e22a420aa1401e096758f \ + --hash=sha256:623f938f6a039536cc02b7582a07a080f13fdfd48f87e63201d92d7e34d09a18 \ + --hash=sha256:62815d2c67f2dd1be76a253d88af4e1da19aeaa1820146dec52cf8bee2958b16 \ + --hash=sha256:6290289fa5fb4c70fd7f72016e03633d60388185483ff3b162912c81205ae2cf \ + --hash=sha256:67e41a497bac88cc1de96eeba56eeb933c39d54bc227352f8455aa87c4ca4000 \ + --hash=sha256:6c85c38a279ca9295a69b9b088a2e48aa49737bb1b34e6a9dc6297c110e8d912 \ + --hash=sha256:6f01f044112d43a20be2f13a11683666d87151542ad627fe41a18b9791d2802f \ + --hash=sha256:707151644085dd0f20fe4f4b573d28e5130c4aaa5f587e95b60989c5926653b5 \ + --hash=sha256:723b2681ed4cc07d3401bbea9c201ad4f2a4ca6ba8cddaff6789f715dd2b391e \ + --hash=sha256:72d1cc63bcc91e14933f77d51b3df899d6a07d184ec515ea7f56bff659e124d7 \ + --hash=sha256:7374d6e3ef72afe49697ecd683f3da12f4fc06af2d75433d0580c6746d2fa025 \ + --hash=sha256:7501e9be34cb21e72fcfe672aafd0eee65c16ba2afa9dcb5500a587d3a0580f0 \ + --hash=sha256:76219cd1eefb9bf4af7856e3ae563d15158efa145c0aab01e9933051a1954045 \ + --hash=sha256:7aec798c2b01aaa65a55f1124f3405804184373abb318a3091325aece235f67c \ + --hash=sha256:7be6dfb49e48fd0a7d91ff758a2b51336f1cd21f9d44b20f6801f072bd080cdd \ + --hash=sha256:7e4e1f580033335c6f76d1e0d6b56baf009d1a64d6a4816347e4271ba951f46d \ + --hash=sha256:7e8ec5f606e0809426d2440e0683509fb605a8820a21ebd120dcdba61b74ef7f \ + --hash=sha256:7f196cd7910d71e9d9860da0ff7a77f64d22c1ad931f1dd18559a06e03109fc0 \ + --hash=sha256:82f3802bfc4751f420d591c5c864de538b71cea117fce67e4595c2afede08a15 \ + --hash=sha256:85ffc9920ffc39c5eee1e3ac9100c913a0973996fbad5111f939bbda49204bb7 \ + --hash=sha256:8e6c219e375f6341d0959af814296372d265a8ca1af63825f65e2e87c618f006 \ + --hash=sha256:8f767ba0911602ddef289404e33835a61168314ebd3c729833db2ed685824211 \ + --hash=sha256:8ff038d52ef6aa0f309feeba00c5095c9118d0abf787e8e8454d6048db2037fc \ + --hash=sha256:915e7a2418f10bd1151b1953df06d896db9783c9cfdb9a8ee1f9b3a4331ab503 \ + --hash=sha256:92883836caf50d5255be03d988d75bc93e3f86ba247b7ca137347c323f731deb \ + --hash=sha256:960b1b3efa39872ac8b6cc3a556edd6fb90ed74f08c9c45e028f1005b26aa55d \ + --hash=sha256:9aeaf53eaa075dd63e81512522fd180097312fb2c9f476333309184285c49ce0 \ + --hash=sha256:9d8089d853c7963a8ce87fff93e2a67075c0bc08684a08ea6ad13577c38ffc38 \ + --hash=sha256:a4130d0b9ce5fad6af07421b1aecc7e079519f70d6c05729ab871794eded8617 \ + --hash=sha256:a482ac121de6973897c92c2f31defc6bafb11c83825109275cffce54bb64933f \ + --hash=sha256:add7ac388d1e0bf57259afbcf9ed05621a3bf11ce5ee337e7536f1e1aaf056b0 \ + --hash=sha256:b1f12bd684887a0a5d55e6363ca87056f361e45451105012d329b86ec19dbe0b \ + --hash=sha256:b3f99e1756fc48ad507b95e5d86f2fb21b3d495012ff13e6592ebac14033f166 \ + --hash=sha256:b4cce60d0223074803c9dbe0721ad3fa51dafe7d462fee4b656a1aa01ee07518 \ + --hash=sha256:baeb47635cb33375dee4924cd93d7f5dcaa786c740b08423b0209b824a1ee728 \ + --hash=sha256:bbea5b775f0ac84945191fb83f845a6fd9a21a03ea7f2e187defac7e401616ad \ + --hash=sha256:bbfcb95d9a744e6e2827dfc66ad10e1020e0cac255eb7f85652832d5a264c2fc \ + --hash=sha256:bd6e7d363aa93bd3421b30b6af97064daf47bc96005bddba67c5ffbc6df426b8 \ + --hash=sha256:be77c402d5e882b6fbacfd90823f13da8e0a69658405a39a569c6b58fdb17b03 \ + --hash=sha256:c302245fd6c33d96bd169c7ccf2513c20f4c1e417c07ce9dce107c8bc3f8411f \ + --hash=sha256:c88653877aeb514c089d1b3d473451677b8b9a6d1497dbddf1ae7934518b06d2 \ + --hash=sha256:cae6383181f1e345317742d2ddd88f9e7d2682fa4c9432e3a74e47d92dce0229 \ + --hash=sha256:cd471ede0d802dd936b6fab28188302b2d497f68436025857ca72cd3810423fe \ + --hash=sha256:d106493a60dcb4aef35a0fac85105e150a11cf8bc2b0d388f5a33272d756c966 \ + --hash=sha256:d30b650595fdbe32366b94cb14f30bb2b625e512bd4e1df00611f99dc5c27fd4 \ + --hash=sha256:d51fde50a77f81330523562e3c2734ffdca9c4c9e9d355478117905e1cfe16c6 \ + --hash=sha256:d57dea657357230cc780e13920d7fa7db059d58fe721c80020f94476da4ca0a1 \ + --hash=sha256:d771f085fcdf4035786adfb1d8db026df1eb4b41dac1c3d070d1e49512843227 \ + --hash=sha256:dae0f0bd7d30c0ad61b9a504e8e272cb8391eed3f1587edf933f4f6b33437450 \ + --hash=sha256:db0562c5f71d18596dcd45e854cf2eeba27d7543e1a3acdafb7eef728f7fe85d \ + --hash=sha256:dfd51b4c56b673dfbc43d7d27ef857dd91124801e2806c69bb45585ce0fa019b \ + --hash=sha256:e080c0637aea036f35507e803a4778f119a9b436617694ae1c5c366805f1e997 \ + --hash=sha256:e48d4dbe0f88e53081da605ae68644e5182752803bbc2beb228cca7f1c4454d6 \ + --hash=sha256:e8b4b5580280b9265af3e0409974fb79c64cf7523632d03fbf11df18f8b0181e \ + --hash=sha256:e8b5378de2b139c3a830f0209c1e91f7705919a4b3e563a10955104f5097a70a \ + --hash=sha256:e904f2417f0d6f6d514f3f8b836416c360f306ddaee1f84de8eef1e722d212e5 \ + --hash=sha256:eee884572b06bbe8a2b54f424dbd996139442cf83c76478e1ec162512e0dd2c7 \ + --hash=sha256:f1fbb0a99125b1287c6d9747f937dc66621426836d1a2d50d05aecfc81911b57 \ + --hash=sha256:f40a95186a72fa0b67d15fef0f157bfcda00b4f59c8a07cbe5530d41ac35d105 \ + --hash=sha256:f6e0bfe77d238308839699944164b96a2eeccaf55f2af400f54dc20669d8d5f2 \ + --hash=sha256:f963eafc0a77a6c0562397da004f5876a9bcf7265a7bcc3205e29636bc4a1312 \ + --hash=sha256:fb9d44c25244e11c8be3f12c938ca8ba8404620ef8092245d2093c6ab3df260f \ + --hash=sha256:fc78739b5ec6e4fb02301984a3d442a91406e7700efbe305071e7fd1c78278f2 \ + --hash=sha256:fceef7fe67c81e1585198215e42ad3fdba3a25644beda8fbdaf85f4d7b93175a \ + --hash=sha256:fd96476f04db5ceba1cfa0f21228f67c1f7402296f0e73fee3513aa680ad237b # via feast (pyproject.toml) -mypy==1.19.1 \ - --hash=sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd \ - --hash=sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b \ - --hash=sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1 \ - --hash=sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba \ - --hash=sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b \ - --hash=sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045 \ - --hash=sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac \ - --hash=sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6 \ - --hash=sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a \ - --hash=sha256:409088884802d511ee52ca067707b90c883426bd95514e8cfda8281dc2effe24 \ - --hash=sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957 \ - --hash=sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042 \ - --hash=sha256:4f28f99c824ecebcdaa2e55d82953e38ff60ee5ec938476796636b86afa3956e \ - --hash=sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec \ - --hash=sha256:7bcfc336a03a1aaa26dfce9fff3e287a3ba99872a157561cbfcebe67c13308e3 \ - --hash=sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718 \ - --hash=sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f \ - --hash=sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331 \ - --hash=sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1 \ - --hash=sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1 \ - --hash=sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13 \ - --hash=sha256:b13cfdd6c87fc3efb69ea4ec18ef79c74c3f98b4e5498ca9b85ab3b2c2329a67 \ - --hash=sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2 \ - --hash=sha256:b7951a701c07ea584c4fe327834b92a30825514c868b1f69c30445093fdd9d5a \ - --hash=sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b \ - --hash=sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8 \ - --hash=sha256:c608937067d2fc5a4dd1a5ce92fd9e1398691b8c5d012d66e1ddd430e9244376 \ - --hash=sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef \ - --hash=sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288 \ - --hash=sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75 \ - --hash=sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74 \ - --hash=sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250 \ - --hash=sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab \ - --hash=sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6 \ - --hash=sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247 \ - --hash=sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925 \ - --hash=sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e \ - --hash=sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e +mypy==1.20.0 \ + --hash=sha256:002b613ae19f4ac7d18b7e168ffe1cb9013b37c57f7411984abbd3b817b0a214 \ + --hash=sha256:00e047c74d3ec6e71a2eb88e9ea551a2edb90c21f993aefa9e0d2a898e0bb732 \ + --hash=sha256:02cca0761c75b42a20a2757ae58713276605eb29a08dd8a6e092aa347c4115ca \ + --hash=sha256:0ecd63f75fdd30327e4ad8b5704bd6d91fc6c1b2e029f8ee14705e1207212489 \ + --hash=sha256:0f42dfaab7ec1baff3b383ad7af562ab0de573c5f6edb44b2dab016082b89948 \ + --hash=sha256:1973868d2adbb4584a3835780b27436f06d1dc606af5be09f187aaa25be1070f \ + --hash=sha256:26c8b52627b6552f47ff11adb4e1509605f094e29815323e487fc0053ebe93d1 \ + --hash=sha256:2721f0ce49cb74a38f00c50da67cb7d36317b5eda38877a49614dc018e91c787 \ + --hash=sha256:2fcedb16d456106e545b2bfd7ef9d24e70b38ec252d2a629823a4d07ebcdb69e \ + --hash=sha256:31b5dbb55293c1bd27c0fc813a0d2bb5ceef9d65ac5afa2e58f829dab7921fd5 \ + --hash=sha256:34506397dbf40c15dc567635d18a21d33827e9ab29014fb83d292a8f4f8953b6 \ + --hash=sha256:367e5c993ba34d5054d11937d0485ad6dfc60ba760fa326c01090fc256adf15c \ + --hash=sha256:379edf079ce44ac8d2805bcf9b3dd7340d4f97aad3a5e0ebabbf9d125b84b442 \ + --hash=sha256:39362cdb4ba5f916e7976fccecaab1ba3a83e35f60fa68b64e9a70e221bb2436 \ + --hash=sha256:4525e7010b1b38334516181c5b81e16180b8e149e6684cee5a727c78186b4e3b \ + --hash=sha256:47781555a7aa5fedcc2d16bcd72e0dc83eb272c10dd657f9fb3f9cc08e2e6abb \ + --hash=sha256:49d11c6f573a5a08f77fad13faff2139f6d0730ebed2cfa9b3d2702671dd7188 \ + --hash=sha256:555493c44a4f5a1b58d611a43333e71a9981c6dbe26270377b6f8174126a0526 \ + --hash=sha256:555658c611099455b2da507582ea20d2043dfdfe7f5ad0add472b1c6238b433f \ + --hash=sha256:697f102c5c1d526bdd761a69f17c6070f9892eebcb94b1a5963d679288c09e78 \ + --hash=sha256:76a70bf840495729be47510856b978f1b0ec7d08f257ca38c9d932720bf6b43e \ + --hash=sha256:7d3243c406773185144527f83be0e0aefc7bf4601b0b2b956665608bf7c98a83 \ + --hash=sha256:931a7630bba591593dcf6e97224a21ff80fb357e7982628d25e3c618e7f598ef \ + --hash=sha256:9804c3ad27f78e54e58b32e7cb532d128b43dbfb9f3f9f06262b821a0f6bd3f5 \ + --hash=sha256:a17c5d0bdcca61ce24a35beb828a2d0d323d3fcf387d7512206888c900193367 \ + --hash=sha256:a6e0641147cbfa7e4e94efdb95c2dab1aff8cfc159ded13e07f308ddccc8c48e \ + --hash=sha256:a79c1eba7ac4209f2d850f0edd0a2f8bba88cbfdfefe6fb76a19e9d4fe5e71a2 \ + --hash=sha256:a9336b5e6712f4adaf5afc3203a99a40b379049104349d747eb3e5a3aa23ac2e \ + --hash=sha256:b20c8b0fd5877abdf402e79a3af987053de07e6fb208c18df6659f708b535134 \ + --hash=sha256:b3a49064504be59e59da664c5e149edc1f26c67c4f8e8456f6ba6aba55033018 \ + --hash=sha256:b503ab55a836136b619b5fc21c8803d810c5b87551af8600b72eecafb0059cb0 \ + --hash=sha256:bd0212976dc57a5bfeede7c219e7cd66568a32c05c9129686dd487c059c1b88a \ + --hash=sha256:c70380fe5d64010f79fb863b9081c7004dd65225d2277333c219d93a10dad4dd \ + --hash=sha256:d99f515f95fd03a90875fdb2cca12ff074aa04490db4d190905851bdf8a549a8 \ + --hash=sha256:e80cf77847d0d3e6e3111b7b25db32a7f8762fd4b9a3a72ce53fe16a2863b281 \ + --hash=sha256:eb96c84efcc33f0b5e0e04beacf00129dd963b67226b01c00b9dfc8affb464c3 \ + --hash=sha256:ebea00201737ad4391142808ed16e875add5c17f676e0912b387739f84991e13 \ + --hash=sha256:efe8d70949c3023698c3fca1e94527e7e790a361ab8116f90d11221421cd8726 \ + --hash=sha256:f13b3e41bce9d257eded794c0f12878af3129d80aacd8a3ee0dee51f3a978651 \ + --hash=sha256:f194db59657c58593a3c47c6dfd7bad4ef4ac12dbc94d01b3a95521f78177e33 \ + --hash=sha256:f49590891d2c2f8a9de15614e32e459a794bcba84693c2394291a2038bbaaa69 \ + --hash=sha256:f75ff57defcd0f1d6e006d721ccdec6c88d4f6a7816eb92f1c4890d979d9ee62 \ + --hash=sha256:f799d9db89fc00446f03281f84a221e50018fc40113a3ba9864b132895619ebe \ + --hash=sha256:f8426d4d75d68714abc17a4292d922f6ba2cfb984b72c2278c437f6dae797865 # via sqlalchemy mypy-extensions==1.1.0 \ --hash=sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505 \ @@ -746,17 +754,15 @@ prometheus-client==0.24.1 \ --hash=sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055 \ --hash=sha256:7e0ced7fbbd40f7b84962d5d2ab6f17ef88a72504dcf7c0b40737b43b2a461f9 # via feast (pyproject.toml) -protobuf==6.33.5 \ - --hash=sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c \ - --hash=sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02 \ - --hash=sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c \ - --hash=sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd \ - --hash=sha256:8f04fa32763dcdb4973d537d6b54e615cc61108c7cb38fe59310c3192d29510a \ - --hash=sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190 \ - --hash=sha256:a3157e62729aafb8df6da2c03aa5c0937c7266c626ce11a278b6eb7963c4e37c \ - --hash=sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5 \ - --hash=sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0 \ - --hash=sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b +protobuf==7.34.1 \ + --hash=sha256:34b84ce27680df7cca9f231043ada0daa55d0c44a2ddfaa58ec1d0d89d8bf60a \ + --hash=sha256:403b093a6e28a960372b44e5eb081775c9b056e816a8029c61231743d63f881a \ + --hash=sha256:5185e0e948d07abe94bb76ec9b8416b604cfe5da6f871d67aad30cbf24c3110b \ + --hash=sha256:8ff40ce8cd688f7265326b38d5a1bed9bfdf5e6723d49961432f83e21d5713e4 \ + --hash=sha256:9ce42245e704cc5027be797c1db1eb93184d44d1cdd71811fb2d9b25ad541280 \ + --hash=sha256:bb3812cd53aefea2b028ef42bd780f5b96407247f20c6ef7c679807e9d188f11 \ + --hash=sha256:d8b2cc79c4d8f62b293ad9b11ec3aebce9af481fa73e64556969f7345ebf9fc7 \ + --hash=sha256:e97b55646e6ce5cbb0954a8c28cd39a5869b59090dfaa7df4598a7fba869468c # via feast (pyproject.toml) psutil==7.2.2 \ --hash=sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372 \ @@ -964,25 +970,25 @@ pydantic-core==2.41.5 \ --hash=sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425 \ --hash=sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52 # via pydantic -pygments==2.19.2 \ - --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \ - --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b +pygments==2.20.0 \ + --hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \ + --hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176 # via feast (pyproject.toml) -pyjwt==2.11.0 \ - --hash=sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623 \ - --hash=sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469 +pyjwt==2.12.1 \ + --hash=sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c \ + --hash=sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b # via feast (pyproject.toml) python-dateutil==2.9.0.post0 \ --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 # via pandas -python-dotenv==1.2.1 \ - --hash=sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6 \ - --hash=sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61 +python-dotenv==1.2.2 \ + --hash=sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a \ + --hash=sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3 # via uvicorn -pytz==2025.2 \ - --hash=sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3 \ - --hash=sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00 +pytz==2026.1.post1 \ + --hash=sha256:3378dde6a0c3d26719182142c56e60c7f9af7e968076f31aae569d72a0358ee1 \ + --hash=sha256:f2fd16142fda348286a75e1a524be810bb05d444e5a081f37f7affc635035f7a # via pandas pyyaml==6.0.3 \ --hash=sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c \ @@ -1068,9 +1074,9 @@ referencing==0.37.0 \ # via # jsonschema # jsonschema-specifications -requests==2.32.5 \ - --hash=sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6 \ - --hash=sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf +requests==2.33.1 \ + --hash=sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517 \ + --hash=sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a # via feast (pyproject.toml) rpds-py==0.30.0 \ --hash=sha256:07ae8a593e1c3c6b82ca3292efbe73c30b61332fd612e05abee07c79359f292f \ @@ -1195,74 +1201,78 @@ six==1.17.0 \ --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \ --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81 # via python-dateutil -sqlalchemy[mypy]==2.0.46 \ - --hash=sha256:09168817d6c19954d3b7655da6ba87fcb3a62bb575fb396a81a8b6a9fadfe8b5 \ - --hash=sha256:0cc3117db526cad3e61074100bd2867b533e2c7dc1569e95c14089735d6fb4fe \ - --hash=sha256:181903fe8c1b9082995325f1b2e84ac078b1189e2819380c2303a5f90e114a62 \ - --hash=sha256:1bc3f601f0a818d27bfe139f6766487d9c88502062a2cd3a7ee6c342e81d5047 \ - --hash=sha256:1e6199143d51e3e1168bedd98cc698397404a8f7508831b81b6a29b18b051069 \ - --hash=sha256:2347c3f0efc4de367ba00218e0ae5c4ba2306e47216ef80d6e31761ac97cb0b9 \ - --hash=sha256:261c4b1f101b4a411154f1da2b76497d73abbfc42740029205d4d01fa1052684 \ - --hash=sha256:33e462154edb9493f6c3ad2125931e273bbd0be8ae53f3ecd1c161ea9a1dd366 \ - --hash=sha256:37fee2164cf21417478b6a906adc1a91d69ae9aba8f9533e67ce882f4bb1de53 \ - --hash=sha256:3a9a72b0da8387f15d5810f1facca8f879de9b85af8c645138cba61ea147968c \ - --hash=sha256:3aac08f7546179889c62b53b18ebf1148b10244b3405569c93984b0388d016a7 \ - --hash=sha256:3c32e993bc57be6d177f7d5d31edb93f30726d798ad86ff9066d75d9bf2e0b6b \ - --hash=sha256:412f26bb4ba942d52016edc8d12fb15d91d3cd46b0047ba46e424213ad407bcb \ - --hash=sha256:42a1643dc5427b69aca967dae540a90b0fbf57eaf248f13a90ea5930e0966863 \ - --hash=sha256:4396c948d8217e83e2c202fbdcc0389cf8c93d2c1c5e60fa5c5a955eae0e64be \ - --hash=sha256:4dafb537740eef640c4d6a7c254611dca2df87eaf6d14d6a5fca9d1f4c3fc0fa \ - --hash=sha256:4f52f7291a92381e9b4de9050b0a65ce5d6a763333406861e33906b8aa4906bf \ - --hash=sha256:52fe29b3817bd191cc20bad564237c808967972c97fa683c04b28ec8979ae36f \ - --hash=sha256:56bdd261bfd0895452006d5316cbf35739c53b9bb71a170a331fa0ea560b2ada \ - --hash=sha256:585af6afe518732d9ccd3aea33af2edaae4a7aa881af5d8f6f4fe3a368699597 \ - --hash=sha256:590be24e20e2424a4c3c1b0835e9405fa3d0af5823a1a9fc02e5dff56471515f \ - --hash=sha256:64901e08c33462acc9ec3bad27fc7a5c2b6491665f2aa57564e57a4f5d7c52ad \ - --hash=sha256:6ac245604295b521de49b465bab845e3afe6916bcb2147e5929c8041b4ec0545 \ - --hash=sha256:6f827fd687fa1ba7f51699e1132129eac8db8003695513fcf13fc587e1bd47a5 \ - --hash=sha256:70ed2830b169a9960193f4d4322d22be5c0925357d82cbf485b3369893350908 \ - --hash=sha256:716be5bcabf327b6d5d265dbdc6213a01199be587224eb991ad0d37e83d728fd \ - --hash=sha256:7568fe771f974abadce52669ef3a03150ff03186d8eb82613bc8adc435a03f01 \ - --hash=sha256:77f8071d8fbcbb2dd11b7fd40dedd04e8ebe2eb80497916efedba844298065ef \ - --hash=sha256:82ec52100ec1e6ec671563bbd02d7c7c8d0b9e71a0723c72f22ecf52d1755330 \ - --hash=sha256:895296687ad06dc9b11a024cf68e8d9d3943aa0b4964278d2553b86f1b267735 \ - --hash=sha256:8d3b44b3d0ab2f1319d71d9863d76eeb46766f8cf9e921ac293511804d39813f \ - --hash=sha256:8d679b5f318423eacb61f933a9a0f75535bfca7056daeadbf6bd5bcee6183aee \ - --hash=sha256:8e84b09a9b0f19accedcbeff5c2caf36e0dd537341a33aad8d680336152dc34e \ - --hash=sha256:9094c8b3197db12aa6f05c51c05daaad0a92b8c9af5388569847b03b1007fb1b \ - --hash=sha256:90bde6c6b1827565a95fde597da001212ab436f1b2e0c2dcc7246e14db26e2a3 \ - --hash=sha256:9397b381dcee8a2d6b99447ae85ea2530dcac82ca494d1db877087a13e38926d \ - --hash=sha256:93a12da97cca70cea10d4b4fc602589c4511f96c1f8f6c11817620c021d21d00 \ - --hash=sha256:93bb0aae40b52c57fd74ef9c6933c08c040ba98daf23ad33c3f9893494b8d3ce \ - --hash=sha256:94b1e5f3a5f1ff4f42d5daab047428cd45a3380e51e191360a35cef71c9a7a2a \ - --hash=sha256:965c62be8256d10c11f8907e7a8d3e18127a4c527a5919d85fa87fd9ecc2cfdc \ - --hash=sha256:96c7cca1a4babaaf3bfff3e4e606e38578856917e52f0384635a95b226c87764 \ - --hash=sha256:9bcdce05f056622a632f1d44bb47dbdb677f58cad393612280406ce37530eb6d \ - --hash=sha256:9d80ea2ac519c364a7286e8d765d6cd08648f5b21ca855a8017d9871f075542d \ - --hash=sha256:a1e8cc6cc01da346dc92d9509a63033b9b1bda4fed7a7a7807ed385c7dccdc10 \ - --hash=sha256:ab65cb2885a9f80f979b85aa4e9c9165a31381ca322cbde7c638fe6eefd1ec39 \ - --hash=sha256:af865c18752d416798dae13f83f38927c52f085c52e2f32b8ab0fef46fdd02c2 \ - --hash=sha256:b1e14b2f6965a685c7128bd315e27387205429c2e339eeec55cb75ca4ab0ea2e \ - --hash=sha256:b2a9f9aee38039cf4755891a1e50e1effcc42ea6ba053743f452c372c3152b1b \ - --hash=sha256:be6c0466b4c25b44c5d82b0426b5501de3c424d7a3220e86cd32f319ba56798e \ - --hash=sha256:c4e2cc868b7b5208aec6c960950b7bb821f82c2fe66446c92ee0a571765e91a5 \ - --hash=sha256:c805fa6e5d461329fa02f53f88c914d189ea771b6821083937e79550bf31fc19 \ - --hash=sha256:cf36851ee7219c170bb0793dbc3da3e80c582e04a5437bc601bfe8c85c9216d7 \ - --hash=sha256:db23b1bf8cfe1f7fda19018e7207b20cdb5168f83c437ff7e95d19e39289c447 \ - --hash=sha256:e0c05aff5c6b1bb5fb46a87e0f9d2f733f83ef6cbbbcd5c642b6c01678268061 \ - --hash=sha256:e8ac45e8f4eaac0f9f8043ea0e224158855c6a4329fd4ee37c45c61e3beb518e \ - --hash=sha256:ea3cd46b6713a10216323cda3333514944e510aa691c945334713fca6b5279ff \ - --hash=sha256:ebf7e1e78af38047e08836d33502c7a278915698b7c2145d045f780201679999 \ - --hash=sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e \ - --hash=sha256:ff33c6e6ad006bbc0f34f5faf941cfc62c45841c64c0a058ac38c799f15b5ede +sqlalchemy[mypy]==2.0.48 \ + --hash=sha256:01f6bbd4308b23240cf7d3ef117557c8fd097ec9549d5d8a52977544e35b40ad \ + --hash=sha256:07edba08061bc277bfdc772dd2a1a43978f5a45994dd3ede26391b405c15221e \ + --hash=sha256:10853a53a4a00417a00913d270dddda75815fcb80675874285f41051c094d7dd \ + --hash=sha256:1182437cb2d97988cfea04cf6cdc0b0bb9c74f4d56ec3d08b81e23d621a28cc6 \ + --hash=sha256:144921da96c08feb9e2b052c5c5c1d0d151a292c6135623c6b2c041f2a45f9e0 \ + --hash=sha256:1a89ce07ad2d4b8cfc30bd5889ec40613e028ed80ef47da7d9dd2ce969ad30e0 \ + --hash=sha256:1b4c575df7368b3b13e0cebf01d4679f9a28ed2ae6c1cd0b1d5beffb6b2007dc \ + --hash=sha256:1ccd42229aaac2df431562117ac7e667d702e8e44afdb6cf0e50fa3f18160f0b \ + --hash=sha256:2645b7d8a738763b664a12a1542c89c940daa55196e8d73e55b169cc5c99f65f \ + --hash=sha256:288937433bd44e3990e7da2402fabc44a3c6c25d3704da066b85b89a85474ae0 \ + --hash=sha256:34634e196f620c7a61d18d5cf7dc841ca6daa7961aed75d532b7e58b309ac894 \ + --hash=sha256:348174f228b99f33ca1f773e85510e08927620caa59ffe7803b37170df30332b \ + --hash=sha256:36ac4ddc3d33e852da9cb00ffb08cea62ca05c39711dc67062ca2bb1fae35fd8 \ + --hash=sha256:3713e21ea67bca727eecd4a24bf68bcd414c403faae4989442be60994301ded0 \ + --hash=sha256:389b984139278f97757ea9b08993e7b9d1142912e046ab7d82b3fbaeb0209131 \ + --hash=sha256:426c5ca86415d9b8945c7073597e10de9644802e2ff502b8e1f11a7a2642856b \ + --hash=sha256:4599a95f9430ae0de82b52ff0d27304fe898c17cb5f4099f7438a51b9998ac77 \ + --hash=sha256:49b7bddc1eebf011ea5ab722fdbe67a401caa34a350d278cc7733c0e88fecb1f \ + --hash=sha256:53667b5f668991e279d21f94ccfa6e45b4e3f4500e7591ae59a8012d0f010dcb \ + --hash=sha256:546572a1793cc35857a2ffa1fe0e58571af1779bcc1ffa7c9fb0839885ed69a9 \ + --hash=sha256:583849c743e0e3c9bb7446f5b5addeacedc168d657a69b418063dfdb2d90081c \ + --hash=sha256:5aee45fd2c6c0f2b9cdddf48c48535e7471e42d6fb81adfde801da0bd5b93241 \ + --hash=sha256:5b193a7e29fd9fa56e502920dca47dffe60f97c863494946bd698c6058a55658 \ + --hash=sha256:5ca74f37f3369b45e1f6b7b06afb182af1fd5dde009e4ffd831830d98cbe5fe7 \ + --hash=sha256:68549c403f79a8e25984376480959975212a670405e3913830614432b5daa07a \ + --hash=sha256:69f5bc24904d3bc3640961cddd2523e361257ef68585d6e364166dfbe8c78fae \ + --hash=sha256:6bb85c546591569558571aa1b06aba711b26ae62f111e15e56136d69920e1616 \ + --hash=sha256:6f7b7243850edd0b8b97043f04748f31de50cf426e939def5c16bedb540698f7 \ + --hash=sha256:7001dc9d5f6bb4deb756d5928eaefe1930f6f4179da3924cbd95ee0e9f4dce89 \ + --hash=sha256:7a936f1bb23d370b7c8cc079d5fce4c7d18da87a33c6744e51a93b0f9e97e9b3 \ + --hash=sha256:7c998f2ace8bf76b453b75dbcca500d4f4b9dd3908c13e89b86289b37784848b \ + --hash=sha256:7cddca31edf8b0653090cbb54562ca027c421c58ddde2c0685f49ff56a1690e0 \ + --hash=sha256:8183dc57ae7d9edc1346e007e840a9f3d6aa7b7f165203a99e16f447150140d2 \ + --hash=sha256:82745b03b4043e04600a6b665cb98697c4339b24e34d74b0a2ac0a2488b6f94d \ + --hash=sha256:841a94c66577661c1f088ac958cd767d7c9bf507698f45afffe7a4017049de76 \ + --hash=sha256:858e433f12b0e5b3ed2f8da917433b634f4937d0e8793e5cb33c54a1a01df565 \ + --hash=sha256:908a3fa6908716f803b86896a09a2c4dde5f5ce2bb07aacc71ffebb57986ce99 \ + --hash=sha256:9764014ef5e58aab76220c5664abb5d47d5bc858d9debf821e55cfdd0f128485 \ + --hash=sha256:9c7d0a77e36b5f4b01ca398482230ab792061d243d715299b44a0b55c89fe617 \ + --hash=sha256:a5b429eb84339f9f05e06083f119ad814e6d85e27ecbdf9c551dfdbb128eaf8a \ + --hash=sha256:a66fe406437dd65cacd96a72689a3aaaecaebbcd62d81c5ac1c0fdbeac835096 \ + --hash=sha256:a6b764fb312bd35e47797ad2e63f0d323792837a6ac785a4ca967019357d2bc7 \ + --hash=sha256:b19151e76620a412c2ac1c6f977ab1b9fa7ad43140178345136456d5265b32ed \ + --hash=sha256:b8438ec5594980d405251451c5b7ea9aa58dda38eb7ac35fb7e4c696712ee24f \ + --hash=sha256:b8fc3454b4f3bd0a368001d0e968852dad45a873f8b4babd41bc302ec851a099 \ + --hash=sha256:bcb8ebbf2e2c36cfe01a94f2438012c6a9d494cf80f129d9753bcdf33bfc35a6 \ + --hash=sha256:d404dc897ce10e565d647795861762aa2d06ca3f4a728c5e9a835096c7059018 \ + --hash=sha256:d612c976cbc2d17edfcc4c006874b764e85e990c29ce9bd411f926bbfb02b9a2 \ + --hash=sha256:d64177f443594c8697369c10e4bbcac70ef558e0f7921a1de7e4a3d1734bcf67 \ + --hash=sha256:d854b3970067297f3a7fbd7a4683587134aa9b3877ee15aa29eea478dc68f933 \ + --hash=sha256:d8fcccbbc0c13c13702c471da398b8cd72ba740dca5859f148ae8e0e8e0d3e7e \ + --hash=sha256:e004aa9248e8cb0a5f9b96d003ca7c1c0a5da8decd1066e7b53f59eb8ce7c62b \ + --hash=sha256:e214d546c8ecb5fc22d6e6011746082abf13a9cf46eefb45769c7b31407c97b5 \ + --hash=sha256:e2d0d88686e3d35a76f3e15a34e8c12d73fc94c1dea1cd55782e695cc14086dd \ + --hash=sha256:e2f35b4cccd9ed286ad62e0a3c3ac21e06c02abc60e20aa51a3e305a30f5fa79 \ + --hash=sha256:e3070c03701037aa418b55d36532ecb8f8446ed0135acb71c678dbdf12f5b6e4 \ + --hash=sha256:e5e088bf43f6ee6fec7dbf1ef7ff7774a616c236b5c0cb3e00662dd71a56b571 \ + --hash=sha256:e83e3f959aaa1c9df95c22c528096d94848a1bc819f5d0ebf7ee3df0ca63db6c \ + --hash=sha256:f0dcbc588cd5b725162c076eb9119342f6579c7f7f55057bb7e3c6ff27e13121 \ + --hash=sha256:f27f9da0a7d22b9f981108fd4b62f8b5743423388915a563e651c20d06c1f457 \ + --hash=sha256:f8649a14caa5f8a243628b1d61cf530ad9ae4578814ba726816adb1121fc493e \ + --hash=sha256:fac0fa4e4f55f118fd87177dacb1c6522fe39c28d498d259014020fec9164c29 \ + --hash=sha256:fd08b90d211c086181caed76931ecfa2bdfc83eea3cfccdb0f82abc6c4b876cb # via feast (pyproject.toml) -starlette==0.52.1 \ - --hash=sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74 \ - --hash=sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933 +starlette==1.0.0 \ + --hash=sha256:6a4beaf1f81bb472fd19ea9b918b50dc3a77a6f2e190a12954b25e6ed5eea149 \ + --hash=sha256:d3ec55e0bb321692d275455ddfd3df75fff145d009685eb40dc91fc66b03d38b # via fastapi -tabulate==0.9.0 \ - --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ - --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f +tabulate==0.10.0 \ + --hash=sha256:e2cfde8f79420f6deeffdeda9aaec3b6bc5abce947655d17ac662b126e48a60d \ + --hash=sha256:f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3 # via feast (pyproject.toml) tenacity==8.5.0 \ --hash=sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78 \ @@ -1272,54 +1282,54 @@ toml==0.10.2 \ --hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \ --hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f # via feast (pyproject.toml) -tomli==2.4.0 \ - --hash=sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729 \ - --hash=sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b \ - --hash=sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d \ - --hash=sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df \ - --hash=sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576 \ - --hash=sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d \ - --hash=sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1 \ - --hash=sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a \ - --hash=sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e \ - --hash=sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc \ - --hash=sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702 \ - --hash=sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6 \ - --hash=sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd \ - --hash=sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4 \ - --hash=sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776 \ - --hash=sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a \ - --hash=sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66 \ - --hash=sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87 \ - --hash=sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2 \ - --hash=sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f \ - --hash=sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475 \ - --hash=sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f \ - --hash=sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95 \ - --hash=sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9 \ - --hash=sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3 \ - --hash=sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9 \ - --hash=sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76 \ - --hash=sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da \ - --hash=sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8 \ - --hash=sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51 \ - --hash=sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86 \ - --hash=sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8 \ - --hash=sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0 \ - --hash=sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b \ - --hash=sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1 \ - --hash=sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e \ - --hash=sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d \ - --hash=sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c \ - --hash=sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867 \ - --hash=sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a \ - --hash=sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c \ - --hash=sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0 \ - --hash=sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4 \ - --hash=sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614 \ - --hash=sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132 \ - --hash=sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa \ - --hash=sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087 +tomli==2.4.1 \ + --hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \ + --hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \ + --hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \ + --hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \ + --hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \ + --hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \ + --hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \ + --hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \ + --hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \ + --hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \ + --hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \ + --hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \ + --hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \ + --hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \ + --hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \ + --hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \ + --hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \ + --hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \ + --hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \ + --hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \ + --hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \ + --hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \ + --hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \ + --hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \ + --hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \ + --hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \ + --hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \ + --hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \ + --hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \ + --hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \ + --hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \ + --hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \ + --hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \ + --hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \ + --hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \ + --hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \ + --hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \ + --hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \ + --hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \ + --hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \ + --hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \ + --hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \ + --hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \ + --hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \ + --hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \ + --hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \ + --hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049 # via mypy toolz==1.1.0 \ --hash=sha256:15ccc861ac51c53696de0a5d6d4607f99c210739caf987b5d2054f3efed429d8 \ @@ -1331,9 +1341,9 @@ tqdm==4.67.3 \ --hash=sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb \ --hash=sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf # via feast (pyproject.toml) -typeguard==4.5.0 \ - --hash=sha256:749bea21cdb2553e12831bc29f1eae980b22c7de8331ab67ae7db9e85470b5a7 \ - --hash=sha256:cfda388fc88a9ce42a41890900d6f31ee124bea9b73bb84701a32438e92165c3 +typeguard==4.5.1 \ + --hash=sha256:44d2bf329d49a244110a090b55f5f91aa82d9a9834ebfd30bcc73651e4a8cc40 \ + --hash=sha256:f6f8ecbbc819c9bc749983cc67c02391e16a9b43b8b27f15dc70ed7c4a007274 # via feast (pyproject.toml) typing-extensions==4.15.0 \ --hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \ @@ -1345,6 +1355,7 @@ typing-extensions==4.15.0 \ # mypy # pydantic # pydantic-core + # pyjwt # referencing # sqlalchemy # starlette diff --git a/sdk/python/requirements/py3.11-ci-requirements.txt b/sdk/python/requirements/py3.11-ci-requirements.txt index 0cb441f9906..2d496a89f36 100644 --- a/sdk/python/requirements/py3.11-ci-requirements.txt +++ b/sdk/python/requirements/py3.11-ci-requirements.txt @@ -1,8 +1,8 @@ # This file was autogenerated by uv via the following command: # uv pip compile -p 3.11 --no-strip-extras pyproject.toml --extra ci --generate-hashes --output-file sdk/python/requirements/py3.11-ci-requirements.txt -accelerate==1.12.0 \ - --hash=sha256:3e2091cd341423207e2f084a6654b1efcd250dc326f2a37d6dde446e07cabb11 \ - --hash=sha256:70988c352feb481887077d2ab845125024b2a137a5090d6d7a32b57d03a45df6 +accelerate==1.13.0 \ + --hash=sha256:cf1a3efb96c18f7b152eb0fa7490f3710b19c3f395699358f08decca2b8b62e0 \ + --hash=sha256:d631b4e0f5b3de4aff2d7e9e6857d164810dfc3237d54d017f075122d057b236 # via docling-ibm-models aiobotocore==2.23.1 \ --hash=sha256:a59f2a78629b97d52f10936b79c73de64e481a8c44a62c1871f088df6c1afc4f \ @@ -12,127 +12,127 @@ aiohappyeyeballs==2.6.1 \ --hash=sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558 \ --hash=sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8 # via aiohttp -aiohttp==3.13.3 \ - --hash=sha256:01ad2529d4b5035578f5081606a465f3b814c542882804e2e8cda61adf5c71bf \ - --hash=sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c \ - --hash=sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c \ - --hash=sha256:084911a532763e9d3dd95adf78a78f4096cd5f58cdc18e6fdbc1b58417a45423 \ - --hash=sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f \ - --hash=sha256:0db318f7a6f065d84cb1e02662c526294450b314a02bd9e2a8e67f0d8564ce40 \ - --hash=sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2 \ - --hash=sha256:1449ceddcdbcf2e0446957863af03ebaaa03f94c090f945411b61269e2cb5daf \ - --hash=sha256:147e422fd1223005c22b4fe080f5d93ced44460f5f9c105406b753612b587821 \ - --hash=sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64 \ - --hash=sha256:215a685b6fbbfcf71dfe96e3eba7a6f58f10da1dfdf4889c7dd856abe430dca7 \ - --hash=sha256:2712039939ec963c237286113c68dbad80a82a4281543f3abf766d9d73228998 \ - --hash=sha256:27234ef6d85c914f9efeb77ff616dbf4ad2380be0cda40b4db086ffc7ddd1b7d \ - --hash=sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea \ - --hash=sha256:2b8d8ddba8f95ba17582226f80e2de99c7a7948e66490ef8d947e272a93e9463 \ - --hash=sha256:2ba0eea45eb5cc3172dbfc497c066f19c41bac70963ea1a67d51fc92e4cf9a80 \ - --hash=sha256:2be0e9ccf23e8a94f6f0650ce06042cefc6ac703d0d7ab6c7a917289f2539ad4 \ - --hash=sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767 \ - --hash=sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43 \ - --hash=sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592 \ - --hash=sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a \ - --hash=sha256:31a83ea4aead760dfcb6962efb1d861db48c34379f2ff72db9ddddd4cda9ea2e \ - --hash=sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687 \ - --hash=sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8 \ - --hash=sha256:37239e9f9a7ea9ac5bf6b92b0260b01f8a22281996da609206a84df860bc1261 \ - --hash=sha256:37da61e244d1749798c151421602884db5270faf479cf0ef03af0ff68954c9dd \ - --hash=sha256:3b61b7169ababd7802f9568ed96142616a9118dd2be0d1866e920e77ec8fa92a \ - --hash=sha256:3d9908a48eb7416dc1f4524e69f1d32e5d90e3981e4e37eb0aa1cd18f9cfa2a4 \ - --hash=sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587 \ - --hash=sha256:4021b51936308aeea0367b8f006dc999ca02bc118a0cc78c303f50a2ff6afb91 \ - --hash=sha256:40c5e40ecc29ba010656c18052b877a1c28f84344825efa106705e835c28530f \ - --hash=sha256:425c126c0dc43861e22cb1c14ba4c8e45d09516d0a3ae0a3f7494b79f5f233a3 \ - --hash=sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344 \ - --hash=sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6 \ - --hash=sha256:49a03727c1bba9a97d3e93c9f93ca03a57300f484b6e935463099841261195d3 \ - --hash=sha256:4ae5b5a0e1926e504c81c5b84353e7a5516d8778fbbff00429fe7b05bb25cbce \ - --hash=sha256:4e239d501f73d6db1522599e14b9b321a7e3b1de66ce33d53a765d975e9f4808 \ - --hash=sha256:56339a36b9f1fc708260c76c87e593e2afb30d26de9ae1eb445b5e051b98a7a1 \ - --hash=sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29 \ - --hash=sha256:5b179331a481cb5529fca8b432d8d3c7001cb217513c94cd72d668d1248688a3 \ - --hash=sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b \ - --hash=sha256:5d2d94f1f5fcbe40838ac51a6ab5704a6f9ea42e72ceda48de5e6b898521da51 \ - --hash=sha256:5dff64413671b0d3e7d5918ea490bdccb97a4ad29b3f311ed423200b2203e01c \ - --hash=sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926 \ - --hash=sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64 \ - --hash=sha256:642f752c3eb117b105acbd87e2c143de710987e09860d674e068c4c2c441034f \ - --hash=sha256:65d2ccb7eabee90ce0503c17716fc77226be026dcc3e65cce859a30db715025b \ - --hash=sha256:693781c45a4033d31d4187d2436f5ac701e7bbfe5df40d917736108c1cc7436e \ - --hash=sha256:694976222c711d1d00ba131904beb60534f93966562f64440d0c9d41b8cdb440 \ - --hash=sha256:697753042d57f4bf7122cab985bf15d0cef23c770864580f5af4f52023a56bd6 \ - --hash=sha256:69c56fbc1993fa17043e24a546959c0178fe2b5782405ad4559e6c13975c15e3 \ - --hash=sha256:6de499a1a44e7de70735d0b39f67c8f25eb3d91eb3103be99ca0fa882cdd987d \ - --hash=sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415 \ - --hash=sha256:75ca857eba4e20ce9f546cd59c7007b33906a4cd48f2ff6ccf1ccfc3b646f279 \ - --hash=sha256:7a4a94eb787e606d0a09404b9c38c113d3b099d508021faa615d70a0131907ce \ - --hash=sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603 \ - --hash=sha256:7bfdc049127717581866fa4708791220970ce291c23e28ccf3922c700740fdc0 \ - --hash=sha256:7e63f210bc1b57ef699035f2b4b6d9ce096b5914414a49b0997c839b2bd2223c \ - --hash=sha256:7f9120f7093c2a32d9647abcaf21e6ad275b4fbec5b55969f978b1a97c7c86bf \ - --hash=sha256:8057c98e0c8472d8846b9c79f56766bcc57e3e8ac7bfd510482332366c56c591 \ - --hash=sha256:80dd4c21b0f6237676449c6baaa1039abae86b91636b6c91a7f8e61c87f89540 \ - --hash=sha256:81e97251d9298386c2b7dbeb490d3d1badbdc69107fb8c9299dd04eb39bddc0e \ - --hash=sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26 \ - --hash=sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a \ - --hash=sha256:859bd3f2156e81dd01432f5849fc73e2243d4a487c4fd26609b1299534ee1845 \ - --hash=sha256:87797e645d9d8e222e04160ee32aa06bc5c163e8499f24db719e7852ec23093a \ - --hash=sha256:87b9aab6d6ed88235aa2970294f496ff1a1f9adcd724d800e9b952395a80ffd9 \ - --hash=sha256:8a60e60746623925eab7d25823329941aee7242d559baa119ca2b253c88a7bd6 \ - --hash=sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba \ - --hash=sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df \ - --hash=sha256:947c26539750deeaee933b000fb6517cc770bbd064bad6033f1cff4803881e43 \ - --hash=sha256:96d604498a7c782cb15a51c406acaea70d8c027ee6b90c569baa6e7b93073679 \ - --hash=sha256:988a8c5e317544fdf0d39871559e67b6341065b87fceac641108c2096d5506b7 \ - --hash=sha256:9a9dc347e5a3dc7dfdbc1f82da0ef29e388ddb2ed281bfce9dd8248a313e62b7 \ - --hash=sha256:9ae8dd55c8e6c4257eae3a20fd2c8f41edaea5992ed67156642493b8daf3cecc \ - --hash=sha256:9af5e68ee47d6534d36791bbe9b646d2a7c7deb6fc24d7943628edfbb3581f29 \ - --hash=sha256:9b174f267b5cfb9a7dba9ee6859cecd234e9a681841eb85068059bc867fb8f02 \ - --hash=sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984 \ - --hash=sha256:9d4c940f02f49483b18b079d1c27ab948721852b281f8b015c058100e9421dd1 \ - --hash=sha256:9ebf57d09e131f5323464bd347135a88622d1c0976e88ce15b670e7ad57e4bd6 \ - --hash=sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632 \ - --hash=sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56 \ - --hash=sha256:a2212ad43c0833a873d0fb3c63fa1bacedd4cf6af2fee62bf4b739ceec3ab239 \ - --hash=sha256:a45530014d7a1e09f4a55f4f43097ba0fd155089372e105e4bff4ca76cb1b168 \ - --hash=sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88 \ - --hash=sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc \ - --hash=sha256:af71fff7bac6bb7508956696dce8f6eec2bbb045eceb40343944b1ae62b5ef11 \ - --hash=sha256:b04be762396457bef43f3597c991e192ee7da460a4953d7e647ee4b1c28e7046 \ - --hash=sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0 \ - --hash=sha256:b1a6102b4d3ebc07dad44fbf07b45bb600300f15b552ddf1851b5390202ea2e3 \ - --hash=sha256:b46020d11d23fe16551466c77823df9cc2f2c1e63cc965daf67fa5eec6ca1877 \ - --hash=sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1 \ - --hash=sha256:b903a4dfee7d347e2d87697d0713be59e0b87925be030c9178c5faa58ea58d5c \ - --hash=sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25 \ - --hash=sha256:b99281b0704c103d4e11e72a76f1b543d4946fea7dd10767e7e1b5f00d4e5704 \ - --hash=sha256:bae5c2ed2eae26cc382020edad80d01f36cb8e746da40b292e68fec40421dc6a \ - --hash=sha256:bb4f7475e359992b580559e008c598091c45b5088f28614e855e42d39c2f1033 \ - --hash=sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1 \ - --hash=sha256:bfc1cc2fe31a6026a8a88e4ecfb98d7f6b1fec150cfd708adbfd1d2f42257c29 \ - --hash=sha256:c014c7ea7fb775dd015b2d3137378b7be0249a448a1612268b5a90c2d81de04d \ - --hash=sha256:c048058117fd649334d81b4b526e94bde3ccaddb20463a815ced6ecbb7d11160 \ - --hash=sha256:c0e2d366af265797506f0283487223146af57815b388623f0357ef7eac9b209d \ - --hash=sha256:c19b90316ad3b24c69cd78d5c9b4f3aa4497643685901185b65166293d36a00f \ - --hash=sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f \ - --hash=sha256:c6b8568a3bb5819a0ad087f16d40e5a3fb6099f39ea1d5625a3edc1e923fc538 \ - --hash=sha256:d32764c6c9aafb7fb55366a224756387cd50bfa720f32b88e0e6fa45b27dcf29 \ - --hash=sha256:d5a372fd5afd301b3a89582817fdcdb6c34124787c70dbcc616f259013e7eef7 \ - --hash=sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72 \ - --hash=sha256:dca68018bf48c251ba17c72ed479f4dafe9dbd5a73707ad8d28a38d11f3d42af \ - --hash=sha256:de2c184bb1fe2cbd2cefba613e9db29a5ab559323f994b6737e370d3da0ac455 \ - --hash=sha256:e3531d63d3bdfa7e3ac5e9b27b2dd7ec9df3206a98e0b3445fa906f233264c57 \ - --hash=sha256:e50a2e1404f063427c9d027378472316201a2290959a295169bcf25992d04558 \ - --hash=sha256:e636b3c5f61da31a92bf0d91da83e58fdfa96f178ba682f11d24f31944cdd28c \ - --hash=sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808 \ - --hash=sha256:f33ed1a2bf1997a36661874b017f5c4b760f41266341af36febaf271d179f6d7 \ - --hash=sha256:f76c1e3fe7d7c8afad7ed193f89a292e1999608170dcc9751a7462a87dfd5bc0 \ - --hash=sha256:f9444f105664c4ce47a2a7171a2418bce5b7bae45fb610f4e2c36045d85911d3 \ - --hash=sha256:fc290605db2a917f6e81b0e1e0796469871f5af381ce15c604a3c5c7e51cb730 \ - --hash=sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa \ - --hash=sha256:fee0c6bc7db1de362252affec009707a17478a00ec69f797d23ca256e36d5940 +aiohttp==3.13.5 \ + --hash=sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5 \ + --hash=sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b \ + --hash=sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9 \ + --hash=sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b \ + --hash=sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8 \ + --hash=sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a \ + --hash=sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2 \ + --hash=sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1 \ + --hash=sha256:147b4f501d0292077f29d5268c16bb7c864a1f054d7001c4c1812c0421ea1ed0 \ + --hash=sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037 \ + --hash=sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416 \ + --hash=sha256:178c7b5e62b454c2bc790786e6058c3cc968613b4419251b478c153a4aec32b1 \ + --hash=sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9 \ + --hash=sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a \ + --hash=sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36 \ + --hash=sha256:206b7b3ef96e4ce211754f0cd003feb28b7d81f0ad26b8d077a5d5161436067f \ + --hash=sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b \ + --hash=sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174 \ + --hash=sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b \ + --hash=sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8 \ + --hash=sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e \ + --hash=sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6 \ + --hash=sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c \ + --hash=sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe \ + --hash=sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9 \ + --hash=sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc \ + --hash=sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800 \ + --hash=sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286 \ + --hash=sha256:347542f0ea3f95b2a955ee6656461fa1c776e401ac50ebce055a6c38454a0adf \ + --hash=sha256:39380e12bd1f2fdab4285b6e055ad48efbaed5c836433b142ed4f5b9be71036a \ + --hash=sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc \ + --hash=sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9 \ + --hash=sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665 \ + --hash=sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832 \ + --hash=sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297 \ + --hash=sha256:4e704c52438f66fdd89588346183d898bb42167cf88f8b7ff1c0f9fc957c348f \ + --hash=sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73 \ + --hash=sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b \ + --hash=sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9 \ + --hash=sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090 \ + --hash=sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49 \ + --hash=sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d \ + --hash=sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46 \ + --hash=sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83 \ + --hash=sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796 \ + --hash=sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be \ + --hash=sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d \ + --hash=sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf \ + --hash=sha256:6f497a6876aa4b1a102b04996ce4c1170c7040d83faa9387dd921c16e30d5c83 \ + --hash=sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25 \ + --hash=sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06 \ + --hash=sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3 \ + --hash=sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6 \ + --hash=sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb \ + --hash=sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88 \ + --hash=sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9 \ + --hash=sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be \ + --hash=sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14 \ + --hash=sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a \ + --hash=sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c \ + --hash=sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3 \ + --hash=sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f \ + --hash=sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d \ + --hash=sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670 \ + --hash=sha256:912d4b6af530ddb1338a66229dac3a25ff11d4448be3ec3d6340583995f56031 \ + --hash=sha256:9277145d36a01653863899c665243871434694bcc3431922c3b35c978061bdb8 \ + --hash=sha256:95d14ca7abefde230f7639ec136ade282655431fd5db03c343b19dda72dd1643 \ + --hash=sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d \ + --hash=sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8 \ + --hash=sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8 \ + --hash=sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1 \ + --hash=sha256:9efcc0f11d850cefcafdd9275b9576ad3bfb539bed96807663b32ad99c4d4b88 \ + --hash=sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb \ + --hash=sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61 \ + --hash=sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4 \ + --hash=sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7 \ + --hash=sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9 \ + --hash=sha256:a8a4d3427e8de1312ddf309cc482186466c79895b3a139fed3259fc01dfa9a5b \ + --hash=sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500 \ + --hash=sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6 \ + --hash=sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2 \ + --hash=sha256:af545c2cffdb0967a96b6249e6f5f7b0d92cdfd267f9d5238d5b9ca63e8edb10 \ + --hash=sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1 \ + --hash=sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3 \ + --hash=sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e \ + --hash=sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a \ + --hash=sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5 \ + --hash=sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95 \ + --hash=sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074 \ + --hash=sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5 \ + --hash=sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b \ + --hash=sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772 \ + --hash=sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a \ + --hash=sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274 \ + --hash=sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94 \ + --hash=sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13 \ + --hash=sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac \ + --hash=sha256:cb979826071c0986a5f08333a36104153478ce6018c58cba7f9caddaf63d5d67 \ + --hash=sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76 \ + --hash=sha256:d147004fede1b12f6013a6dbb2a26a986a671a03c6ea740ddc76500e5f1c399f \ + --hash=sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8 \ + --hash=sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7 \ + --hash=sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8 \ + --hash=sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3 \ + --hash=sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be \ + --hash=sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b \ + --hash=sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c \ + --hash=sha256:e999f0c88a458c836d5fb521814e92ed2172c649200336a6df514987c1488258 \ + --hash=sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c \ + --hash=sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6 \ + --hash=sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56 \ + --hash=sha256:ee5e86776273de1795947d17bddd6bb19e0365fd2af4289c0d2c5454b6b1d36b \ + --hash=sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d \ + --hash=sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a \ + --hash=sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162 \ + --hash=sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1 \ + --hash=sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6 \ + --hash=sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5 \ + --hash=sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540 \ + --hash=sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254 # via # aiobotocore # aiohttp-cors @@ -166,9 +166,9 @@ annotated-types==0.7.0 \ --hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \ --hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89 # via pydantic -anyio==4.12.1 \ - --hash=sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703 \ - --hash=sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c +anyio==4.13.0 \ + --hash=sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708 \ + --hash=sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc # via # elasticsearch # httpx @@ -230,9 +230,9 @@ asttokens==3.0.1 \ --hash=sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a \ --hash=sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7 # via stack-data -async-lru==2.1.0 \ - --hash=sha256:9eeb2fecd3fe42cc8a787fc32ead53a3a7158cc43d039c3c55ab3e4e5b2a80ed \ - --hash=sha256:fa12dcf99a42ac1280bc16c634bbaf06883809790f6304d85cdab3f666f33a7e +async-lru==2.3.0 \ + --hash=sha256:89bdb258a0140d7313cf8f4031d816a042202faa61d0ab310a0a538baa1c24b6 \ + --hash=sha256:eea27b01841909316f2cc739807acea1c623df2be8c5cfad7583286397bb8315 # via jupyterlab async-property==0.2.2 \ --hash=sha256:17d9bd6ca67e27915a75d92549df64b5c7174e9dc806b30a3934dc4ff0506380 \ @@ -246,24 +246,24 @@ atpublic==7.0.0 \ --hash=sha256:466ef10d0c8bbd14fd02a5fbd5a8b6af6a846373d91106d3a07c16d72d96b63e \ --hash=sha256:6702bd9e7245eb4e8220a3e222afcef7f87412154732271ee7deee4433b72b4b # via ibis-framework -attrs==25.4.0 \ - --hash=sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11 \ - --hash=sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373 +attrs==26.1.0 \ + --hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \ + --hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32 # via # aiohttp # jsonlines # jsonschema # openlineage-python # referencing -azure-core==1.38.1 \ - --hash=sha256:69f08ee3d55136071b7100de5b198994fc1c5f89d2b91f2f43156d20fcf200a4 \ - --hash=sha256:9317db1d838e39877eb94a2240ce92fa607db68adf821817b723f0d679facbf6 +azure-core==1.39.0 \ + --hash=sha256:4ac7b70fab5438c3f68770649a78daf97833caa83827f91df9c14e0e0ea7d34f \ + --hash=sha256:8a90a562998dd44ce84597590fff6249701b98c0e8797c95fcdd695b54c35d74 # via # azure-identity # azure-storage-blob -azure-identity==1.25.2 \ - --hash=sha256:030dbaa720266c796221c6cdbd1999b408c079032c919fef725fcc348a540fe9 \ - --hash=sha256:1b40060553d01a72ba0d708b9a46d0f61f56312e215d8896d836653ffdc6753d +azure-identity==1.25.3 \ + --hash=sha256:ab23c0d63015f50b630ef6c6cf395e7262f439ce06e5d07a64e874c724f8d9e6 \ + --hash=sha256:f4d0b956a8146f30333e071374171f3cfa7bdb8073adb8c3814b65567aa7447c # via feast (pyproject.toml) azure-storage-blob==12.28.0 \ --hash=sha256:00fb1db28bf6a7b7ecaa48e3b1d5c83bfadacc5a678b77826081304bd87d6461 \ @@ -346,9 +346,9 @@ beautifulsoup4==4.14.3 \ # via # docling # nbconvert -bigtree==1.3.1 \ - --hash=sha256:a22a0ecd9b0abb283f4a1515370dbf1ec93adee70746767272e2c49d7af9f407 \ - --hash=sha256:c8b766b00188c532d3499bfd9e9666b357428db507fc701f088031a0d5c614d5 +bigtree==1.4.0 \ + --hash=sha256:d0d99550ae64ce4529f132602ab875c2ab472c96c942f5704f8c72a17450d3ea \ + --hash=sha256:e5ae2e948168da671d99601c9ed87ab3b48d9d4ea8a98f111e5748e98064c31c # via feast (pyproject.toml) bleach[css]==6.3.0 \ --hash=sha256:6f3b91b1c0a02bb9a78b5a454c92506aa0fdf197e1d5e114d2e00c6f64306d22 \ @@ -359,7 +359,6 @@ boto3==1.38.27 \ --hash=sha256:95f5fe688795303a8a15e8b7e7f255cadab35eae459d00cc281a4fd77252ea80 # via # feast (pyproject.toml) - # ikvpy # moto # snowflake-connector-python botocore==1.38.46 \ @@ -371,12 +370,11 @@ botocore==1.38.46 \ # moto # s3transfer # snowflake-connector-python -build==1.4.0 \ - --hash=sha256:6a07c1b8eb6f2b311b96fcbdbce5dab5fe637ffda0fd83c9cac622e927501596 \ - --hash=sha256:f1b91b925aa322be454f8330c6fb48b465da993d1e7e7e6fa35027ec49f3c936 +build==1.4.2 \ + --hash=sha256:35b14e1ee329c186d3f08466003521ed7685ec15ecffc07e68d706090bf161d1 \ + --hash=sha256:7a4d8651ea877cb2a89458b1b198f2e69f536c95e89129dbf5d448045d60db88 # via # feast (pyproject.toml) - # openlineage-python # pip-tools # singlestoredb cassandra-driver==3.29.3 \ @@ -412,9 +410,9 @@ cassandra-driver==3.29.3 \ --hash=sha256:fcf45725ae1751cb934b9b827a7d9cd899bbd09eb1ad28e2160b4584de35ba77 \ --hash=sha256:ff6b82ee4533f6fd4474d833e693b44b984f58337173ee98ed76bce08721a636 # via feast (pyproject.toml) -certifi==2026.1.4 \ - --hash=sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c \ - --hash=sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120 +certifi==2026.2.25 \ + --hash=sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa \ + --hash=sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7 # via # clickhouse-connect # docling @@ -514,132 +512,147 @@ cffi==2.0.0 \ # feast (pyproject.toml) # argon2-cffi-bindings # cryptography - # ikvpy # pynacl cfgv==3.5.0 \ --hash=sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0 \ --hash=sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132 # via pre-commit -charset-normalizer==3.4.4 \ - --hash=sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad \ - --hash=sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93 \ - --hash=sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394 \ - --hash=sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89 \ - --hash=sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc \ - --hash=sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86 \ - --hash=sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63 \ - --hash=sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d \ - --hash=sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f \ - --hash=sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8 \ - --hash=sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0 \ - --hash=sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505 \ - --hash=sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161 \ - --hash=sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af \ - --hash=sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152 \ - --hash=sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318 \ - --hash=sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72 \ - --hash=sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4 \ - --hash=sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e \ - --hash=sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3 \ - --hash=sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576 \ - --hash=sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c \ - --hash=sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1 \ - --hash=sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8 \ - --hash=sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1 \ - --hash=sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2 \ - --hash=sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44 \ - --hash=sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26 \ - --hash=sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88 \ - --hash=sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016 \ - --hash=sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede \ - --hash=sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf \ - --hash=sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a \ - --hash=sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc \ - --hash=sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0 \ - --hash=sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84 \ - --hash=sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db \ - --hash=sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1 \ - --hash=sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7 \ - --hash=sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed \ - --hash=sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8 \ - --hash=sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133 \ - --hash=sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e \ - --hash=sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef \ - --hash=sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14 \ - --hash=sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2 \ - --hash=sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0 \ - --hash=sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d \ - --hash=sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828 \ - --hash=sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f \ - --hash=sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf \ - --hash=sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6 \ - --hash=sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328 \ - --hash=sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090 \ - --hash=sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa \ - --hash=sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381 \ - --hash=sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c \ - --hash=sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb \ - --hash=sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc \ - --hash=sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a \ - --hash=sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec \ - --hash=sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc \ - --hash=sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac \ - --hash=sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e \ - --hash=sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313 \ - --hash=sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569 \ - --hash=sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3 \ - --hash=sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d \ - --hash=sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525 \ - --hash=sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894 \ - --hash=sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3 \ - --hash=sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9 \ - --hash=sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a \ - --hash=sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9 \ - --hash=sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14 \ - --hash=sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25 \ - --hash=sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50 \ - --hash=sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf \ - --hash=sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1 \ - --hash=sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3 \ - --hash=sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac \ - --hash=sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e \ - --hash=sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815 \ - --hash=sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c \ - --hash=sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6 \ - --hash=sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6 \ - --hash=sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e \ - --hash=sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4 \ - --hash=sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84 \ - --hash=sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69 \ - --hash=sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15 \ - --hash=sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191 \ - --hash=sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0 \ - --hash=sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897 \ - --hash=sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd \ - --hash=sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2 \ - --hash=sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794 \ - --hash=sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d \ - --hash=sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074 \ - --hash=sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3 \ - --hash=sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224 \ - --hash=sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838 \ - --hash=sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a \ - --hash=sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d \ - --hash=sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d \ - --hash=sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f \ - --hash=sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8 \ - --hash=sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490 \ - --hash=sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966 \ - --hash=sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9 \ - --hash=sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3 \ - --hash=sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e \ - --hash=sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608 +charset-normalizer==3.4.7 \ + --hash=sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc \ + --hash=sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c \ + --hash=sha256:07d9e39b01743c3717745f4c530a6349eadbfa043c7577eef86c502c15df2c67 \ + --hash=sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4 \ + --hash=sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0 \ + --hash=sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c \ + --hash=sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5 \ + --hash=sha256:12a6fff75f6bc66711b73a2f0addfc4c8c15a20e805146a02d147a318962c444 \ + --hash=sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153 \ + --hash=sha256:14265bfe1f09498b9d8ec91e9ec9fa52775edf90fcbde092b25f4a33d444fea9 \ + --hash=sha256:16d971e29578a5e97d7117866d15889a4a07befe0e87e703ed63cd90cb348c01 \ + --hash=sha256:177a0ba5f0211d488e295aaf82707237e331c24788d8d76c96c5a41594723217 \ + --hash=sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b \ + --hash=sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c \ + --hash=sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a \ + --hash=sha256:1dc8b0ea451d6e69735094606991f32867807881400f808a106ee1d963c46a83 \ + --hash=sha256:1efde3cae86c8c273f1eb3b287be7d8499420cf2fe7585c41d370d3e790054a5 \ + --hash=sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7 \ + --hash=sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb \ + --hash=sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c \ + --hash=sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1 \ + --hash=sha256:2cd4a60d0e2fb04537162c62bbbb4182f53541fe0ede35cdf270a1c1e723cc42 \ + --hash=sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab \ + --hash=sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df \ + --hash=sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e \ + --hash=sha256:320ade88cfb846b8cd6b4ddf5ee9e80ee0c1f52401f2456b84ae1ae6a1a5f207 \ + --hash=sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18 \ + --hash=sha256:36836d6ff945a00b88ba1e4572d721e60b5b8c98c155d465f56ad19d68f23734 \ + --hash=sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38 \ + --hash=sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110 \ + --hash=sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18 \ + --hash=sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44 \ + --hash=sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d \ + --hash=sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48 \ + --hash=sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e \ + --hash=sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5 \ + --hash=sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d \ + --hash=sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53 \ + --hash=sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790 \ + --hash=sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c \ + --hash=sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b \ + --hash=sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116 \ + --hash=sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d \ + --hash=sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10 \ + --hash=sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6 \ + --hash=sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2 \ + --hash=sha256:6370e8686f662e6a3941ee48ed4742317cafbe5707e36406e9df792cdb535776 \ + --hash=sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a \ + --hash=sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265 \ + --hash=sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008 \ + --hash=sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943 \ + --hash=sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374 \ + --hash=sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246 \ + --hash=sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e \ + --hash=sha256:6e0d51f618228538a3e8f46bd246f87a6cd030565e015803691603f55e12afb5 \ + --hash=sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616 \ + --hash=sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15 \ + --hash=sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41 \ + --hash=sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960 \ + --hash=sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752 \ + --hash=sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e \ + --hash=sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72 \ + --hash=sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7 \ + --hash=sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8 \ + --hash=sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b \ + --hash=sha256:813c0e0132266c08eb87469a642cb30aaff57c5f426255419572aaeceeaa7bf4 \ + --hash=sha256:82b271f5137d07749f7bf32f70b17ab6eaabedd297e75dce75081a24f76eb545 \ + --hash=sha256:84c018e49c3bf790f9c2771c45e9313a08c2c2a6342b162cd650258b57817706 \ + --hash=sha256:8751d2787c9131302398b11e6c8068053dcb55d5a8964e114b6e196cf16cb366 \ + --hash=sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb \ + --hash=sha256:87fad7d9ba98c86bcb41b2dc8dbb326619be2562af1f8ff50776a39e55721c5a \ + --hash=sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e \ + --hash=sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00 \ + --hash=sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f \ + --hash=sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a \ + --hash=sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1 \ + --hash=sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66 \ + --hash=sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356 \ + --hash=sha256:a6c5863edfbe888d9eff9c8b8087354e27618d9da76425c119293f11712a6319 \ + --hash=sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4 \ + --hash=sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad \ + --hash=sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d \ + --hash=sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5 \ + --hash=sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7 \ + --hash=sha256:aef65cd602a6d0e0ff6f9930fcb1c8fec60dd2cfcb6facaf4bdb0e5873042db0 \ + --hash=sha256:af21eb4409a119e365397b2adbaca4c9ccab56543a65d5dbd9f920d6ac29f686 \ + --hash=sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34 \ + --hash=sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49 \ + --hash=sha256:bb8cc7534f51d9a017b93e3e85b260924f909601c3df002bcdb58ddb4dc41a5c \ + --hash=sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1 \ + --hash=sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e \ + --hash=sha256:bd9b23791fe793e4968dba0c447e12f78e425c59fc0e3b97f6450f4781f3ee60 \ + --hash=sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0 \ + --hash=sha256:c0f081d69a6e58272819b70288d3221a6ee64b98df852631c80f293514d3b274 \ + --hash=sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d \ + --hash=sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0 \ + --hash=sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae \ + --hash=sha256:c593052c465475e64bbfe5dbd81680f64a67fdc752c56d7a0ae205dc8aeefe0f \ + --hash=sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d \ + --hash=sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe \ + --hash=sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3 \ + --hash=sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393 \ + --hash=sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1 \ + --hash=sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af \ + --hash=sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44 \ + --hash=sha256:d61f00a0869d77422d9b2aba989e2d24afa6ffd552af442e0e58de4f35ea6d00 \ + --hash=sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c \ + --hash=sha256:dca4bbc466a95ba9c0234ef56d7dd9509f63da22274589ebd4ed7f1f4d4c54e3 \ + --hash=sha256:dd915403e231e6b1809fe9b6d9fc55cf8fb5e02765ac625d9cd623342a7905d7 \ + --hash=sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd \ + --hash=sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e \ + --hash=sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b \ + --hash=sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8 \ + --hash=sha256:e5f4d355f0a2b1a31bc3edec6795b46324349c9cb25eed068049e4f472fb4259 \ + --hash=sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859 \ + --hash=sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46 \ + --hash=sha256:e80c8378d8f3d83cd3164da1ad2df9e37a666cdde7b1cb2298ed0b558064be30 \ + --hash=sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b \ + --hash=sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46 \ + --hash=sha256:ed065083d0898c9d5b4bbec7b026fd755ff7454e6e8b73a67f8c744b13986e24 \ + --hash=sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a \ + --hash=sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24 \ + --hash=sha256:f22dec1690b584cea26fade98b2435c132c1b5f68e39f5a0b7627cd7ae31f1dc \ + --hash=sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215 \ + --hash=sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063 \ + --hash=sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832 \ + --hash=sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6 \ + --hash=sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79 \ + --hash=sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464 # via # requests # snowflake-connector-python -click==8.2.1 \ - --hash=sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202 \ - --hash=sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b +click==8.3.1 \ + --hash=sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a \ + --hash=sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6 # via # feast (pyproject.toml) # dask @@ -649,74 +662,82 @@ click==8.2.1 \ # ray # typer # uvicorn -clickhouse-connect==0.11.0 \ - --hash=sha256:00c525036aeb968c578a7e32bf3d4acbac4f91a3748b39921a654dbbf8fae482 \ - --hash=sha256:035d66337654c7d7812e43910195d0c1ab2e64512a98407a51ee5860d7f32289 \ - --hash=sha256:0e1de4b74dbfd75b4990267a6168e1181130b2a255c1250e40f6aa922a147b4d \ - --hash=sha256:0e857234d6f91ce30dd4f3f6dfd0b84c83057cf45686a86eab1912c3991ce8b1 \ - --hash=sha256:0fdd59e35164472404ddddf4407903e516dd11c929f248846dd2993e2c005774 \ - --hash=sha256:121cb63648ee812582c8691bc1c4bd3f4c5ee1220278f32fb3d2bf581cb5fe2b \ - --hash=sha256:19b60f592b9de67c366d1459a2c73ded0955a9b0ccde265a1f9aa237c1e1c89f \ - --hash=sha256:242f891559a2b0c4b9eb37cad5181b6141c521763b10c8025a105826ae0c6957 \ - --hash=sha256:2853493849e59ccf60a095915f9a8d70f539853fc4536260f21720a6c495e339 \ - --hash=sha256:2dbc742bc0c7db72ca88bb5e67bf1959c60dfe1ed3376bf4c48e35b026374a97 \ - --hash=sha256:2dd49ac4d0d59a836ceda8b2c6b7f348accf2512f81d46543fc33f3b64c55152 \ - --hash=sha256:2e8f339f7fbd1880d67e5a8d07dfaecd4cd0f5bf6c77ae3e254030b2a7e71f53 \ - --hash=sha256:3b0196d4a7f6cd76dc57cf178f4dee2e92c08daa6e77def88d95604cf715b913 \ - --hash=sha256:3e5d64a10f2938ac3e84194c6dd312a42c62f875d6f0be00bc73d337d2115570 \ - --hash=sha256:40267a3b72c3d26b5e062d1858183d1b7c2ff8142457b6962a5826f726ba8ba8 \ - --hash=sha256:4196a2caad25ea83cfbc627306daa4345c9b44ce4dd247dc462842da5f10630f \ - --hash=sha256:470d5ab8f2cd9835feb4198c6fbd80730b52257fad23a20dbc7e4ab0c0ab1c2f \ - --hash=sha256:49898f30c94dfac1d655e32f3ca829f98344384b470f29dc46532ad2285b2fad \ - --hash=sha256:4b1ab7542701f8e76742da18eaac31a5c7b49ebab4020be90d1129a222de0dd5 \ - --hash=sha256:524afd5a64fd9fd53184ec14ad1a69ea89e1fa8373c89350b53c38982232aa45 \ - --hash=sha256:55d23aa3a68617323ea23440dcdcd6d85f47ac239076aa83c568ffdf28e41348 \ - --hash=sha256:55e08de1df514dc6b40fbf6264020750fea191343ad1c645ed5e7a1da5c9e78f \ - --hash=sha256:64662538e91077de6b73991e39ab0d90b0465cd510eb23ff4b2013c81a620063 \ - --hash=sha256:66bc5ed12b7a09e4ed68053eb3150c6243b6a1d82addb243bb3c6b75f48efefa \ - --hash=sha256:68cb75f902cf0bfa150ba4ebba01a831af62d54270e74ee7349c6dd62db40300 \ - --hash=sha256:69bf8935c8b4dd6455483ae4713ee21230bf6abe84a173e5587d8b9bb862bb7c \ - --hash=sha256:75924dcefba9727c39660ac0e94585fba44877839b026de7cdbf74e6c4e05b78 \ - --hash=sha256:76ad068e7b73c27eae7e620dd0bbbb95cf8089ecb661b50a02af771f845649a8 \ - --hash=sha256:7c24ae9f88caf9cb503c4641051cb89978cb677e0db0e1ef28eb3e3615e1473f \ - --hash=sha256:7c78caf3aeeed4243843be887a3056f0b0ef5d148f2035e2bd8decd3f8760399 \ - --hash=sha256:7e6b23587c7ef5c33c22b830e9ad93d0cc90d498526aec970467cac51065cfd7 \ - --hash=sha256:83478aa71633e1bc555c8607d6716c365d2e7bfdb1296588f386e29b464983cc \ - --hash=sha256:9159ac864c0fadd785de64aabf875e8bb1a97303871dff745a5ae647cc7d449f \ - --hash=sha256:9c16c54d3ae023a85ca278609c3a1fef9ccbfaa3d96c1a7d789b3c7faaf32262 \ - --hash=sha256:9d3174b1944391777d4549c29a88dbb5214e4ef7194d3cfcd3d338706f58d6bc \ - --hash=sha256:a27bf20184c491d42501989f04fa0228e4b062dd9b09b0ff9766a7968b92dcfb \ - --hash=sha256:acc1009501b651504aa7c6c0d1e21dd0974d1c36a77b10407c31c91fef359ffe \ - --hash=sha256:ad76bf2b433836d3730052113b357cfcb62accefd145b822bbf0fd0e537047c1 \ - --hash=sha256:b4730b1ac6f4d932628f44609ac4754b642d1138eb9f0c3934e7cfe344dfc590 \ - --hash=sha256:c00e38d3d621b3e14f2566257c4b95efc7769cb0673172ae0aeeb9114169dc62 \ - --hash=sha256:c109c35964bff0b0ed8adaa47d3a07d620188b451c4f7a1cbfda7e4d2db852d6 \ - --hash=sha256:c1f3daf18324c3ac4c56ddc594bc122dd9512c55df9410ae08a4df325e63df03 \ - --hash=sha256:c522fd0ee6adc0c9bac97cd4c079993301b79919dfdacfb6310eecfb62c050e7 \ - --hash=sha256:c6f19acaf8b2de034bae55ab82e154ed9194c5c5d454fde72012e9f44e9c52fa \ - --hash=sha256:cc0dfa69da660fa2847c79c0698e0ebfb5309afae14b53fb29121475860cfacb \ - --hash=sha256:d783d69eadc8d1b5f6581e3e1d82e8ea0af8f9a2386c795d35b4a2ac845f6f5a \ - --hash=sha256:d94a8e8e66e3a97ac4e7bbfce2a8a27f8b56d87bfa32739cac209159f5c186eb \ - --hash=sha256:dc91654e353b22980d4e34ca212e1eaa063b047110f8db7d1739a7ca8fbb44e6 \ - --hash=sha256:dceb4201905993dcf7efa56678d30c12f82c195c14249292b9f381bd91940f65 \ - --hash=sha256:dd1f9d8ac9b95027a36ba66e00bf82297e041e8682e68bc1dc5a4ab08d091e28 \ - --hash=sha256:de312c2a1be01c3015e8ac1ebd742f28843d12c1352359b4070c65fbbb6e1cb0 \ - --hash=sha256:dfd2b70a91debe45b9ad5470a87e7cf904e06981bc90c0380e5bd62da27c4393 \ - --hash=sha256:e3b31bb62f538ea70d0a285c8519c86707f7030ac505001f31596baca4cacd1e \ - --hash=sha256:e47d9270b2e6fcadd691f6958ae15a365e80edfb2ea002348ea0f045dc2485c3 \ - --hash=sha256:e4f2fd9df304ada18fbd4a8ef8008cbe77d64d163102ee173d4f05b86f00a7c5 \ - --hash=sha256:e70da2df99fff309285a4f25b774e05d82d01c60ff68dc414de9f292ad2508b4 \ - --hash=sha256:e9429c5241bf1fdeb92678705857aa06ef4bb2b923e382a7e76dc83b14eff615 \ - --hash=sha256:f5db1b8032d6a252040eb4fecb6a330de4712133d0d75b0fbf7cbee1ba7ade61 \ - --hash=sha256:ffde6e5bda89af1217bd888175e5854b5e7539b1e9efc715de48c908fe072561 +clickhouse-connect==0.15.1 \ + --hash=sha256:08df7857ecd2e345abbbdfc54d80fa060732cf75c953940355140af9a73b730a \ + --hash=sha256:0bef871fb9803ae82b4dc1f797b6e784de0a4dec351591191a0c1a6008548284 \ + --hash=sha256:158325a06978f91a182967341188502a0761447d1e13ffa775cf017def1a3d9e \ + --hash=sha256:167e674dff8ac12be7796d93190b6fe9097c042940b3c41d87fe4d85970be27d \ + --hash=sha256:1ef6922c8887a8b0db49a81823ef031807c971f628a363f6d53b030abaefd589 \ + --hash=sha256:1ff5d10c6e49d36ee6941f52c4233f2bfb4198e9c726fed224f725974a667e37 \ + --hash=sha256:24cdfe9b486c8f2e66f5f51b1f322d89d9eb4df29d9ebb2fa19b553065651e85 \ + --hash=sha256:265f1660e8db5006ca32e8894e6c6cc984b343d96171ab0580b2104084b0fc08 \ + --hash=sha256:2e19c9daabe4c24027006e903d0ba3f2a6b2e0703af37b2536335ac4558d541e \ + --hash=sha256:2e52e20190004ed4578b803b1d5f2097c336fafec41b2cc0d490b5a4964c1284 \ + --hash=sha256:371a201ee128ba2b47bd05e2f184b0d20fb78171d27441a6fb1183f4fcc9316e \ + --hash=sha256:3b456d469db994b188bb0b5afa373e8f2e5e2bf41a70a736b9ed2485a976e9ae \ + --hash=sha256:3cf1b78abf7e1b97ab279a2b244357c40657d2d8504ff3f713c6577cd0550b38 \ + --hash=sha256:46bcebd00aff52ea5f7433e9cee1157b411dba9187f6677a18378c799c27c8aa \ + --hash=sha256:4bf70933ab860bd2f0a872db624603706bed400c915c7aeef382956cf8ebbdf3 \ + --hash=sha256:4f87d283399cbda676c8765605bf60dc6559df6fd38cbb9ea07048a4b34dda26 \ + --hash=sha256:5046cb96d1c344c35198fe072a21ce3f273754df3e58fd0a6222c9a1aff72e75 \ + --hash=sha256:5462bad97d97919a4ed230e2ef28d0b76bec0354a343218647830aac7744a43b \ + --hash=sha256:57ad606e878fd284242713449217a0c475fde6b9b7ab59e7ba9e9c388431f004 \ + --hash=sha256:5ab0d019c18d9d63b228ce2e45768f6c65fd27067d1127ab3e558c35c90f52ef \ + --hash=sha256:5de299ada0f7eb9090bb5a6304d8d78163d4d9cc8eb04d8f552bfb82bafb61d5 \ + --hash=sha256:60aa8c9c775d22db324260265f4c656f803fbc71de9193ef83cf8d8d0ef6ab9a \ + --hash=sha256:691cbf6d3dd16988feb75d43942bb212f50f0cbec284eb249e0cd33ebf74ad09 \ + --hash=sha256:693a03e44256886ac5dd26dc708833913157ec72e3b3a44fb89fd5fc202f85dc \ + --hash=sha256:6f9619f9e8885886039e451c2e22d3fb9bd2e95bc64bbf4ebe6c0a50875785f4 \ + --hash=sha256:7586fae639db65d6ff9f7d539aaac04ebd8604657751d78f6b45e7f971be83f3 \ + --hash=sha256:76699fb79c0de182f915d96a08c15afc19755d9d0e9c93411abb0e4b539c7166 \ + --hash=sha256:7a590116037ae56fab339b625f317d7c0a15bbede5f2f206ce1e55b1a2385e90 \ + --hash=sha256:82e60e108d78e32d58a0f21570b02d3baad67ccbad6482eeb79d74a616d8a5ad \ + --hash=sha256:83d881bf786b05489ccf96f07972b9c28638b513f3e064d39987d837749b35e3 \ + --hash=sha256:859c718cb93780dd681f75d59ceaf4415915fa9617a5ba2de6105e291d6df3ad \ + --hash=sha256:873d8f74eaec141f40ae060318c32353da94fdd4601f925bfd52426f3ddcd689 \ + --hash=sha256:8bb70307589099c67dfe9a973998491bc82c1af9040560b5ebab799721bb197d \ + --hash=sha256:9610ef6ff653f8a030f50e39cdeb1a39bea925c48f9196d787ea4b9f5eb1c8f0 \ + --hash=sha256:99d55aab64fdeb53d74c16d2c46ae5491e90aa37ba55c24884a68a869418ee8e \ + --hash=sha256:a1266a52bf61f0420630f625c5ac87bc2d095f08321820546300a699d4300ba3 \ + --hash=sha256:a326e2f5518d6a9d71f0895d50a3ccd8c4d5e3abb625f39330512ff3c45c6731 \ + --hash=sha256:a9d1e12bf86cd96626f74d21e3ac237abcda105f55cd2e78d139197d35f86209 \ + --hash=sha256:aa9890507aac52a8a5363813bb315b6867e86a97ffa08576cb934603f5bc0216 \ + --hash=sha256:ae24e4e7b10ff140c9041d9bdb2c08781145d844c7486c2661d223ededce7634 \ + --hash=sha256:aeb09a6f8585f3bd4d8c5bead38f3821c076e0bca08c474a7b9039732a6e2e9a \ + --hash=sha256:aed10f7615d0c72457d21ace9b59bfcbea0293188af2ffa3f3c2942d36974e7c \ + --hash=sha256:b2f5174fc6001a1555fc3cb565f3b727e1b786d572df0b30d14929ae13bd3542 \ + --hash=sha256:b692998e6dea344a4a2d7c34c129379767a068f234e1cb721ba27f1f023c70ee \ + --hash=sha256:b6d107b5f964af97f25a0d1bfd59fe3510f2a646c87ad4f9ab9014bb0c66aa1c \ + --hash=sha256:b8236c7dd675ed13d5e96f1f9126eeb711e8c266e4a0476ebc32be8a17decb32 \ + --hash=sha256:c12d9f2b2fc57adaf5ea267804f00e520771794641227ed5285e38fdf36557a6 \ + --hash=sha256:cd41ebe8b7f1c2579b22bbc414a800f3f8f5c843928019aca27c81592f70c5a7 \ + --hash=sha256:cdeee50fb2822e4f886d9676c5979b9e6f93ee9159b1aa1b7d62e71bcf7ae551 \ + --hash=sha256:d0dad989ae193c7261b12c9829f219fc1cb1ae9cad380c35cfe489f139c03ee9 \ + --hash=sha256:d10e8f42bafa12d43dd280d157af1ca5a1743e0ca94e61de94c1d00cb1b2da2b \ + --hash=sha256:d3fca3e0781b664556690decc788e7d25691043bf67a0d241e9c29233a2990d5 \ + --hash=sha256:d6e98c0cf53db3b24dc0ff9f522fcf13205b1d191c632567d1744fbd4671741f \ + --hash=sha256:d75324bb3a611eeb8c22b7fdda7c2cbc6ddbcc3871c65624b97f219430ded282 \ + --hash=sha256:df93fa024d6ed46dbc3182b6202180be4cf2bbe9c331dcb21f85963b1b3fd1e5 \ + --hash=sha256:e1a157205efd47884c22bfe061fc6f8c9aea844929ee755c47b446093805d21a \ + --hash=sha256:e307ea69dc2a6e6d942d2799ee8bfe20c99019ddf95121cbeaf7efbb97f79f09 \ + --hash=sha256:e702b77720ae6fd501e5a52262518dddb6c705fbc122bca4567694fb0bab401f \ + --hash=sha256:e88a31bbd9da7f4b49de39d21e8c93c8fbb5cf487071e935af0eba884681df00 \ + --hash=sha256:e911cffe6a9d9d27ccf91b8060086254c152c48ade47c1de3fc8e91d22cdd143 \ + --hash=sha256:eb595e820e46ccdffd702d23e4d1d1efadaa60db81a3da53e693ab055d8a3b1a \ + --hash=sha256:ecf244f91fc72e5dfe83652baf69a7ced414e9147288138897bc4376ebd6f8ac \ + --hash=sha256:f03814b6e6a72892ce913eaef3931e6d011068480e9c19b80e5c640fdac55109 \ + --hash=sha256:f13c34ad1ddb0d1efc92bc4039b50b534da94c51bbce25e61484bfd28b231cb5 \ + --hash=sha256:f25df0298ecea9c29768ab1267ff1186aacfff0cbd75ff3b588644043f313cd6 \ + --hash=sha256:f2aaf5fc0bb3098c24f0d8ca7e4ecbe605a26957481dfca2c8cef9d1fad7b7ca \ + --hash=sha256:fa01fdb92db6bf72cb9509eecd0a0057a4558a4f40c02eebffbc2d61b644620e # via feast (pyproject.toml) cloudpickle==3.1.2 \ --hash=sha256:7fda9eb655c9c230dab534f1983763de5835249750e85fbcef43aaa30a9a2414 \ --hash=sha256:9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a # via dask -codeflare-sdk==0.33.1 \ - --hash=sha256:6622a73edde5042455ae7d76279a5279c55db4950533ea7f12aac2fc51d49bb8 \ - --hash=sha256:ad41ec5260217fd030904fb4b9fe62e26c3f51ac7999a5d607eb4b1359edd5e5 +codeflare-sdk==0.36.0 \ + --hash=sha256:5dfba97aef0c2a83437682b960a9c323d54e459d949e24729d00d330b00b96a2 \ + --hash=sha256:cbac45169916e63198d214492ed1c17c49ee27d3e98303cff59e2170266a441d # via feast (pyproject.toml) colorama==0.4.6 \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ @@ -800,142 +821,164 @@ couchbase-columnar==1.0.0 \ --hash=sha256:fc0fad2d386c5b5df7aaaccd8751e01caa886cc640cc8c92523dd07c4e7be519 \ --hash=sha256:fc4efa3e15190c3731478006de494b046bc57785e9c8ae99ac8b375a91683e38 # via feast (pyproject.toml) -coverage[toml]==7.13.4 \ - --hash=sha256:01d4cbc3c283a17fc1e42d614a119f7f438eabb593391283adca8dc86eff1246 \ - --hash=sha256:02231499b08dabbe2b96612993e5fc34217cdae907a51b906ac7fca8027a4459 \ - --hash=sha256:0dd7ab8278f0d58a0128ba2fca25824321f05d059c1441800e934ff2efa52129 \ - --hash=sha256:0e086334e8537ddd17e5f16a344777c1ab8194986ec533711cbe6c41cde841b6 \ - --hash=sha256:0fc31c787a84f8cd6027eba44010517020e0d18487064cd3d8968941856d1415 \ - --hash=sha256:14375934243ee05f56c45393fe2ce81fe5cc503c07cee2bdf1725fb8bef3ffaf \ - --hash=sha256:1731dc33dc276dafc410a885cbf5992f1ff171393e48a21453b78727d090de80 \ - --hash=sha256:19bc3c88078789f8ef36acb014d7241961dbf883fd2533d18cb1e7a5b4e28b11 \ - --hash=sha256:1af1641e57cf7ba1bd67d677c9abdbcd6cc2ab7da3bca7fa1e2b7e50e65f2ad0 \ - --hash=sha256:1d4be36a5114c499f9f1f9195e95ebf979460dbe2d88e6816ea202010ba1c34b \ - --hash=sha256:200dea7d1e8095cc6e98cdabe3fd1d21ab17d3cee6dab00cadbb2fe35d9c15b9 \ - --hash=sha256:23e3f687cf945070d1c90f85db66d11e3025665d8dafa831301a0e0038f3db9b \ - --hash=sha256:2421d591f8ca05b308cf0092807308b2facbefe54af7c02ac22548b88b95c98f \ - --hash=sha256:245e37f664d89861cf2329c9afa2c1fe9e6d4e1a09d872c947e70718aeeac505 \ - --hash=sha256:25381386e80ae727608e662474db537d4df1ecd42379b5ba33c84633a2b36d47 \ - --hash=sha256:25a41c3104d08edb094d9db0d905ca54d0cd41c928bb6be3c4c799a54753af55 \ - --hash=sha256:296f8b0af861d3970c2a4d8c91d48eb4dd4771bcef9baedec6a9b515d7de3def \ - --hash=sha256:29e3220258d682b6226a9b0925bc563ed9a1ebcff3cad30f043eceea7eaf2689 \ - --hash=sha256:2a09cfa6a5862bc2fc6ca7c3def5b2926194a56b8ab78ffcf617d28911123012 \ - --hash=sha256:2b0f6ccf3dbe577170bebfce1318707d0e8c3650003cb4b3a9dd744575daa8b5 \ - --hash=sha256:2c048ea43875fbf8b45d476ad79f179809c590ec7b79e2035c662e7afa3192e3 \ - --hash=sha256:2cb0f1e000ebc419632bbe04366a8990b6e32c4e0b51543a6484ffe15eaeda95 \ - --hash=sha256:2fa8d5f8de70688a28240de9e139fa16b153cc3cbb01c5f16d88d6505ebdadf9 \ - --hash=sha256:300deaee342f90696ed186e3a00c71b5b3d27bffe9e827677954f4ee56969601 \ - --hash=sha256:30b8d0512f2dc8c8747557e8fb459d6176a2c9e5731e2b74d311c03b78451997 \ - --hash=sha256:33901f604424145c6e9c2398684b92e176c0b12df77d52db81c20abd48c3794c \ - --hash=sha256:3599eb3992d814d23b35c536c28df1a882caa950f8f507cef23d1cbf334995ac \ - --hash=sha256:391ee8f19bef69210978363ca930f7328081c6a0152f1166c91f0b5fdd2a773c \ - --hash=sha256:3998e5a32e62fdf410c0dbd3115df86297995d6e3429af80b8798aad894ca7aa \ - --hash=sha256:3c06f0f1337c667b971ca2f975523347e63ec5e500b9aa5882d91931cd3ef750 \ - --hash=sha256:40aa8808140e55dc022b15d8aa7f651b6b3d68b365ea0398f1441e0b04d859c3 \ - --hash=sha256:40d74da8e6c4b9ac18b15331c4b5ebc35a17069410cad462ad4f40dcd2d50c0d \ - --hash=sha256:4223b4230a376138939a9173f1bdd6521994f2aff8047fae100d6d94d50c5a12 \ - --hash=sha256:48685fee12c2eb3b27c62f2658e7ea21e9c3239cba5a8a242801a0a3f6a8c62a \ - --hash=sha256:4c7d3cc01e7350f2f0f6f7036caaf5673fb56b6998889ccfe9e1c1fe75a9c932 \ - --hash=sha256:4e83efc079eb39480e6346a15a1bcb3e9b04759c5202d157e1dd4303cd619356 \ - --hash=sha256:4fc7fa81bbaf5a02801b65346c8b3e657f1d93763e58c0abdf7c992addd81a92 \ - --hash=sha256:53d133df809c743eb8bce33b24bcababb371f4441340578cd406e084d94a6148 \ - --hash=sha256:590c0ed4bf8e85f745e6b805b2e1c457b2e33d5255dd9729743165253bc9ad39 \ - --hash=sha256:5b856a8ccf749480024ff3bd7310adaef57bf31fd17e1bfc404b7940b6986634 \ - --hash=sha256:65dfcbe305c3dfe658492df2d85259e0d79ead4177f9ae724b6fb245198f55d6 \ - --hash=sha256:6f01afcff62bf9a08fb32b2c1d6e924236c0383c02c790732b6537269e466a72 \ - --hash=sha256:6fdef321fdfbb30a197efa02d48fcd9981f0d8ad2ae8903ac318adc653f5df98 \ - --hash=sha256:71ca20079dd8f27fcf808817e281e90220475cd75115162218d0e27549f95fef \ - --hash=sha256:725d985c5ab621268b2edb8e50dfe57633dc69bda071abc470fed55a14935fd3 \ - --hash=sha256:75eab1ebe4f2f64d9509b984f9314d4aa788540368218b858dad56dc8f3e5eb9 \ - --hash=sha256:75fcd519f2a5765db3f0e391eb3b7d150cce1a771bf4c9f861aeab86c767a3c0 \ - --hash=sha256:76451d1978b95ba6507a039090ba076105c87cc76fc3efd5d35d72093964d49a \ - --hash=sha256:784fc3cf8be001197b652d51d3fd259b1e2262888693a4636e18879f613a62a9 \ - --hash=sha256:78cdf0d578b15148b009ccf18c686aa4f719d887e76e6b40c38ffb61d264a552 \ - --hash=sha256:79be69cf7f3bf9b0deeeb062eab7ac7f36cd4cc4c4dd694bd28921ba4d8596cc \ - --hash=sha256:79e73a76b854d9c6088fe5d8b2ebe745f8681c55f7397c3c0a016192d681045f \ - --hash=sha256:7b322db1284a2ed3aa28ffd8ebe3db91c929b7a333c0820abec3d838ef5b3525 \ - --hash=sha256:7d41eead3cc673cbd38a4417deb7fd0b4ca26954ff7dc6078e33f6ff97bed940 \ - --hash=sha256:7eda778067ad7ffccd23ecffce537dface96212576a07924cbf0d8799d2ded5a \ - --hash=sha256:7f57b33491e281e962021de110b451ab8a24182589be17e12a22c79047935e23 \ - --hash=sha256:8041b6c5bfdc03257666e9881d33b1abc88daccaf73f7b6340fb7946655cd10f \ - --hash=sha256:8248977c2e33aecb2ced42fef99f2d319e9904a36e55a8a68b69207fb7e43edc \ - --hash=sha256:845f352911777a8e722bfce168958214951e07e47e5d5d9744109fa5fe77f79b \ - --hash=sha256:85480adfb35ffc32d40918aad81b89c69c9cc5661a9b8a81476d3e645321a056 \ - --hash=sha256:8e264226ec98e01a8e1054314af91ee6cde0eacac4f465cc93b03dbe0bce2fd7 \ - --hash=sha256:8e798c266c378da2bd819b0677df41ab46d78065fb2a399558f3f6cae78b2fbb \ - --hash=sha256:9181a3ccead280b828fae232df12b16652702b49d41e99d657f46cc7b1f6ec7a \ - --hash=sha256:9351229c8c8407645840edcc277f4a2d44814d1bc34a2128c11c2a031d45a5dd \ - --hash=sha256:93550784d9281e374fb5a12bf1324cc8a963fd63b2d2f223503ef0fd4aa339ea \ - --hash=sha256:9401ebc7ef522f01d01d45532c68c5ac40fb27113019b6b7d8b208f6e9baa126 \ - --hash=sha256:94eb63f9b363180aff17de3e7c8760c3ba94664ea2695c52f10111244d16a299 \ - --hash=sha256:9d107aff57a83222ddbd8d9ee705ede2af2cc926608b57abed8ef96b50b7e8f9 \ - --hash=sha256:a32ebc02a1805adf637fc8dec324b5cdacd2e493515424f70ee33799573d661b \ - --hash=sha256:a3aa4e7b9e416774b21797365b358a6e827ffadaaca81b69ee02946852449f00 \ - --hash=sha256:a6f94a7d00eb18f1b6d403c91a88fd58cfc92d4b16080dfdb774afc8294469bf \ - --hash=sha256:aa3feb8db2e87ff5e6d00d7e1480ae241876286691265657b500886c98f38bda \ - --hash=sha256:ad27098a189e5838900ce4c2a99f2fe42a0bf0c2093c17c69b45a71579e8d4a2 \ - --hash=sha256:ae4578f8528569d3cf303fef2ea569c7f4c4059a38c8667ccef15c6e1f118aa5 \ - --hash=sha256:b1ec7b6b6e93255f952e27ab58fbc68dcc468844b16ecbee881aeb29b6ab4d8d \ - --hash=sha256:b507778ae8a4c915436ed5c2e05b4a6cecfa70f734e19c22a005152a11c7b6a9 \ - --hash=sha256:b66a2da594b6068b48b2692f043f35d4d3693fb639d5ea8b39533c2ad9ac3ab9 \ - --hash=sha256:b720ce6a88a2755f7c697c23268ddc47a571b88052e6b155224347389fdf6a3b \ - --hash=sha256:b7b38448866e83176e28086674fe7368ab8590e4610fb662b44e345b86d63ffa \ - --hash=sha256:b8eb931ee8e6d8243e253e5ed7336deea6904369d2fd8ae6e43f68abbf167092 \ - --hash=sha256:bb28c0f2cf2782508a40cec377935829d5fcc3ad9a3681375af4e84eb34b6b58 \ - --hash=sha256:bd60d4fe2f6fa7dff9223ca1bbc9f05d2b6697bc5961072e5d3b952d46e1b1ea \ - --hash=sha256:c35eb28c1d085eb7d8c9b3296567a1bebe03ce72962e932431b9a61f28facf26 \ - --hash=sha256:c4240e7eded42d131a2d2c4dec70374b781b043ddc79a9de4d55ca71f8e98aea \ - --hash=sha256:caa421e2684e382c5d8973ac55e4f36bed6821a9bad5c953494de960c74595c9 \ - --hash=sha256:d490ba50c3f35dd7c17953c68f3270e7ccd1c6642e2d2afe2d8e720b98f5a053 \ - --hash=sha256:d65b2d373032411e86960604dc4edac91fdfb5dca539461cf2cbe78327d1e64f \ - --hash=sha256:dae88bc0fc77edaa65c14be099bd57ee140cf507e6bfdeea7938457ab387efb0 \ - --hash=sha256:de6defc1c9badbf8b9e67ae90fd00519186d6ab64e5cc5f3d21359c2a9b2c1d3 \ - --hash=sha256:e101609bcbbfb04605ea1027b10dc3735c094d12d40826a60f897b98b1c30256 \ - --hash=sha256:e24f9156097ff9dc286f2f913df3a7f63c0e333dcafa3c196f2c18b4175ca09a \ - --hash=sha256:e2f25215f1a359ab17320b47bcdaca3e6e6356652e8256f2441e4ef972052903 \ - --hash=sha256:e5c8f6ed1e61a8b2dcdf31eb0b9bbf0130750ca79c1c49eb898e2ad86f5ccc91 \ - --hash=sha256:e6f70dec1cc557e52df5306d051ef56003f74d56e9c4dd7ddb07e07ef32a84dd \ - --hash=sha256:e856bf6616714c3a9fbc270ab54103f4e685ba236fa98c054e8f87f266c93505 \ - --hash=sha256:e87f6c587c3f34356c3759f0420693e35e7eb0e2e41e4c011cb6ec6ecbbf1db7 \ - --hash=sha256:eb30bf180de3f632cd043322dad5751390e5385108b2807368997d1a92a509d0 \ - --hash=sha256:eb88b316ec33760714a4720feb2816a3a59180fd58c1985012054fa7aebee4c2 \ - --hash=sha256:eb9078108fbf0bcdde37c3f4779303673c2fa1fe8f7956e68d447d0dd426d38a \ - --hash=sha256:ecae9737b72408d6a950f7e525f30aca12d4bd8dd95e37342e5beb3a2a8c4f71 \ - --hash=sha256:ee756f00726693e5ba94d6df2bdfd64d4852d23b09bb0bc700e3b30e6f333985 \ - --hash=sha256:f4594c67d8a7c89cf922d9df0438c7c7bb022ad506eddb0fdb2863359ff78242 \ - --hash=sha256:f53d492307962561ac7de4cd1de3e363589b000ab69617c6156a16ba7237998d \ - --hash=sha256:fb07dc5da7e849e2ad31a5d74e9bece81f30ecf5a42909d0a695f8bd1874d6af \ - --hash=sha256:fb26a934946a6afe0e326aebe0730cdff393a8bc0bbb65a2f41e30feddca399c \ - --hash=sha256:fdfc1e28e7c7cdce44985b3043bc13bbd9c747520f94a4d7164af8260b3d91f0 +coverage[toml]==7.13.5 \ + --hash=sha256:012d5319e66e9d5a218834642d6c35d265515a62f01157a45bcc036ecf947256 \ + --hash=sha256:02ca0eed225b2ff301c474aeeeae27d26e2537942aa0f87491d3e147e784a82b \ + --hash=sha256:03ccc709a17a1de074fb1d11f217342fb0d2b1582ed544f554fc9fc3f07e95f5 \ + --hash=sha256:0428cbef5783ad91fe240f673cc1f76b25e74bbfe1a13115e4aa30d3f538162d \ + --hash=sha256:04690832cbea4e4663d9149e05dba142546ca05cb1848816760e7f58285c970a \ + --hash=sha256:0590e44dd2745c696a778f7bab6aa95256de2cbc8b8cff4f7db8ff09813d6969 \ + --hash=sha256:0672854dc733c342fa3e957e0605256d2bf5934feeac328da9e0b5449634a642 \ + --hash=sha256:084b84a8c63e8d6fc7e3931b316a9bcafca1458d753c539db82d31ed20091a87 \ + --hash=sha256:0b67af5492adb31940ee418a5a655c28e48165da5afab8c7fa6fd72a142f8740 \ + --hash=sha256:0cd9ed7a8b181775459296e402ca4fb27db1279740a24e93b3b41942ebe4b215 \ + --hash=sha256:0cef0cdec915d11254a7f549c1170afecce708d30610c6abdded1f74e581666d \ + --hash=sha256:0e223ce4b4ed47f065bfb123687686512e37629be25cc63728557ae7db261422 \ + --hash=sha256:0e3c426ffc4cd952f54ee9ffbdd10345709ecc78a3ecfd796a57236bfad0b9b8 \ + --hash=sha256:0ecf12ecb326fe2c339d93fc131816f3a7367d223db37817208905c89bded911 \ + --hash=sha256:10a0c37f0b646eaff7cce1874c31d1f1ccb297688d4c747291f4f4c70741cc8b \ + --hash=sha256:145ede53ccbafb297c1c9287f788d1bc3efd6c900da23bf6931b09eafc931587 \ + --hash=sha256:1b11eef33edeae9d142f9b4358edb76273b3bfd30bc3df9a4f95d0e49caf94e8 \ + --hash=sha256:1b88c69c8ef5d4b6fe7dea66d6636056a0f6a7527c440e890cf9259011f5e606 \ + --hash=sha256:258354455f4e86e3e9d0d17571d522e13b4e1e19bf0f8596bcf9476d61e7d8a9 \ + --hash=sha256:259b69bb83ad9894c4b25be2528139eecba9a82646ebdda2d9db1ba28424a6bf \ + --hash=sha256:2aa055ae1857258f9e0045be26a6d62bdb47a72448b62d7b55f4820f361a2633 \ + --hash=sha256:2d3807015f138ffea1ed9afeeb8624fd781703f2858b62a8dd8da5a0994c57b6 \ + --hash=sha256:301e3b7dfefecaca37c9f1aa6f0049b7d4ab8dd933742b607765d757aca77d43 \ + --hash=sha256:32ca0c0114c9834a43f045a87dcebd69d108d8ffb666957ea65aa132f50332e2 \ + --hash=sha256:34b02417cf070e173989b3db962f7ed56d2f644307b2cf9d5a0f258e13084a61 \ + --hash=sha256:356e76b46783a98c2a2fe81ec79df4883a1e62895ea952968fb253c114e7f930 \ + --hash=sha256:35a31f2b1578185fbe6aa2e74cea1b1d0bbf4c552774247d9160d29b80ed56cc \ + --hash=sha256:380e8e9084d8eb38db3a9176a1a4f3c0082c3806fa0dc882d1d87abc3c789247 \ + --hash=sha256:3ad050321264c49c2fa67bb599100456fc51d004b82534f379d16445da40fb75 \ + --hash=sha256:3e1bb5f6c78feeb1be3475789b14a0f0a5b47d505bfc7267126ccbd50289999e \ + --hash=sha256:3f4818d065964db3c1c66dc0fbdac5ac692ecbc875555e13374fdbe7eedb4376 \ + --hash=sha256:460cf0114c5016fa841214ff5564aa4864f11948da9440bc97e21ad1f4ba1e01 \ + --hash=sha256:48c39bc4a04d983a54a705a6389512883d4a3b9862991b3617d547940e9f52b1 \ + --hash=sha256:4b59148601efcd2bac8c4dbf1f0ad6391693ccf7a74b8205781751637076aee3 \ + --hash=sha256:4d2afbc5cc54d286bfb54541aa50b64cdb07a718227168c87b9e2fb8f25e1743 \ + --hash=sha256:505d7083c8b0c87a8fa8c07370c285847c1f77739b22e299ad75a6af6c32c5c9 \ + --hash=sha256:52f444e86475992506b32d4e5ca55c24fc88d73bcbda0e9745095b28ef4dc0cf \ + --hash=sha256:5b13955d31d1633cf9376908089b7cebe7d15ddad7aeaabcbe969a595a97e95e \ + --hash=sha256:5ec4af212df513e399cf11610cc27063f1586419e814755ab362e50a85ea69c1 \ + --hash=sha256:60365289c3741e4db327e7baff2a4aaacf22f788e80fa4683393891b70a89fbd \ + --hash=sha256:631efb83f01569670a5e866ceb80fe483e7c159fac6f167e6571522636104a0b \ + --hash=sha256:6697e29b93707167687543480a40f0db8f356e86d9f67ddf2e37e2dfd91a9dab \ + --hash=sha256:66a80c616f80181f4d643b0f9e709d97bcea413ecd9631e1dedc7401c8e6695d \ + --hash=sha256:67e9bc5449801fad0e5dff329499fb090ba4c5800b86805c80617b4e29809b2a \ + --hash=sha256:68a4953be99b17ac3c23b6efbc8a38330d99680c9458927491d18700ef23ded0 \ + --hash=sha256:6c36ddb64ed9d7e496028d1d00dfec3e428e0aabf4006583bb1839958d280510 \ + --hash=sha256:6e3370441f4513c6252bf042b9c36d22491142385049243253c7e48398a15a9f \ + --hash=sha256:7034b5c56a58ae5e85f23949d52c14aca2cfc6848a31764995b7de88f13a1ea0 \ + --hash=sha256:704de6328e3d612a8f6c07000a878ff38181ec3263d5a11da1db294fa6a9bdf8 \ + --hash=sha256:7132bed4bd7b836200c591410ae7d97bf7ae8be6fc87d160b2bd881df929e7bf \ + --hash=sha256:7300c8a6d13335b29bb76d7651c66af6bd8658517c43499f110ddc6717bfc209 \ + --hash=sha256:750db93a81e3e5a9831b534be7b1229df848b2e125a604fe6651e48aa070e5f9 \ + --hash=sha256:777c4d1eff1b67876139d24288aaf1817f6c03d6bae9c5cc8d27b83bcfe38fe3 \ + --hash=sha256:78e696e1cc714e57e8b25760b33a8b1026b7048d270140d25dafe1b0a1ee05a3 \ + --hash=sha256:79060214983769c7ba3f0cee10b54c97609dca4d478fa1aa32b914480fd5738d \ + --hash=sha256:7c8d4bc913dd70b93488d6c496c77f3aff5ea99a07e36a18f865bca55adef8bd \ + --hash=sha256:7f2c47b36fe7709a6e83bfadf4eefb90bd25fbe4014d715224c4316f808e59a2 \ + --hash=sha256:800bc829053c80d240a687ceeb927a94fd108bbdc68dfbe505d0d75ab578a882 \ + --hash=sha256:843ea8643cf967d1ac7e8ecd4bb00c99135adf4816c0c0593fdcc47b597fcf09 \ + --hash=sha256:8769751c10f339021e2638cd354e13adeac54004d1941119b2c96fe5276d45ea \ + --hash=sha256:8dd02af98971bdb956363e4827d34425cb3df19ee550ef92855b0acb9c7ce51c \ + --hash=sha256:8fdf453a942c3e4d99bd80088141c4c6960bb232c409d9c3558e2dbaa3998562 \ + --hash=sha256:941617e518602e2d64942c88ec8499f7fbd49d3f6c4327d3a71d43a1973032f3 \ + --hash=sha256:972a9cd27894afe4bc2b1480107054e062df08e671df7c2f18c205e805ccd806 \ + --hash=sha256:9adb6688e3b53adffefd4a52d72cbd8b02602bfb8f74dcd862337182fd4d1a4e \ + --hash=sha256:9b74db26dfea4f4e50d48a4602207cd1e78be33182bc9cbf22da94f332f99878 \ + --hash=sha256:9bb2a28101a443669a423b665939381084412b81c3f8c0fcfbac57f4e30b5b8e \ + --hash=sha256:9d44d7aa963820b1b971dbecd90bfe5fe8f81cff79787eb6cca15750bd2f79b9 \ + --hash=sha256:9dacc2ad679b292709e0f5fc1ac74a6d4d5562e424058962c7bb0c658ad25e45 \ + --hash=sha256:9ddb4f4a5479f2539644be484da179b653273bca1a323947d48ab107b3ed1f29 \ + --hash=sha256:a1a6d79a14e1ec1832cabc833898636ad5f3754a678ef8bb4908515208bf84f4 \ + --hash=sha256:a698e363641b98843c517817db75373c83254781426e94ada3197cabbc2c919c \ + --hash=sha256:ad14385487393e386e2ea988b09d62dd42c397662ac2dabc3832d71253eee479 \ + --hash=sha256:ad146744ca4fd09b50c482650e3c1b1f4dfa1d4792e0a04a369c7f23336f0400 \ + --hash=sha256:b5db73ba3c41c7008037fa731ad5459fc3944cb7452fc0aa9f822ad3533c583c \ + --hash=sha256:bd3a2fbc1c6cccb3c5106140d87cc6a8715110373ef42b63cf5aea29df8c217a \ + --hash=sha256:bdba0a6b8812e8c7df002d908a9a2ea3c36e92611b5708633c50869e6d922fdf \ + --hash=sha256:be3d4bbad9d4b037791794ddeedd7d64a56f5933a2c1373e18e9e568b9141686 \ + --hash=sha256:bf69236a9a81bdca3bff53796237aab096cdbf8d78a66ad61e992d9dac7eb2de \ + --hash=sha256:bff95879c33ec8da99fc9b6fe345ddb5be6414b41d6d1ad1c8f188d26f36e028 \ + --hash=sha256:c555b48be1853fe3997c11c4bd521cdd9a9612352de01fa4508f16ec341e6fe0 \ + --hash=sha256:c81f6515c4c40141f83f502b07bbfa5c240ba25bbe73da7b33f1e5b6120ff179 \ + --hash=sha256:c9136ff29c3a91e25b1d1552b5308e53a1e0653a23e53b6366d7c2dcbbaf8a16 \ + --hash=sha256:ce1998c0483007608c8382f4ff50164bfc5bd07a2246dd272aa4043b75e61e85 \ + --hash=sha256:cec2d83125531bd153175354055cdb7a09987af08a9430bd173c937c6d0fba2a \ + --hash=sha256:cff784eef7f0b8f6cb28804fbddcfa99f89efe4cc35fb5627e3ac58f91ed3ac0 \ + --hash=sha256:d2c87e0c473a10bffe991502eac389220533024c8082ec1ce849f4218dded810 \ + --hash=sha256:d7cfad2d6d81dd298ab6b89fe72c3b7b05ec7544bdda3b707ddaecff8d25c161 \ + --hash=sha256:d8a7a2049c14f413163e2bdabd37e41179b1d1ccb10ffc6ccc4b7a718429c607 \ + --hash=sha256:da305e9937617ee95c2e39d8ff9f040e0487cbf1ac174f777ed5eddd7a7c1f26 \ + --hash=sha256:da86cdcf10d2519e10cabb8ac2de03da1bcb6e4853790b7fbd48523332e3a819 \ + --hash=sha256:dc022073d063b25a402454e5712ef9e007113e3a676b96c5f29b2bda29352f40 \ + --hash=sha256:e0723d2c96324561b9aa76fb982406e11d93cdb388a7a7da2b16e04719cf7ca5 \ + --hash=sha256:e092b9499de38ae0fbfbc603a74660eb6ff3e869e507b50d85a13b6db9863e15 \ + --hash=sha256:e0b216a19534b2427cc201a26c25da4a48633f29a487c61258643e89d28200c0 \ + --hash=sha256:e1c85e0b6c05c592ea6d8768a66a254bfb3874b53774b12d4c89c481eb78cb90 \ + --hash=sha256:e301d30dd7e95ae068671d746ba8c34e945a82682e62918e41b2679acd2051a0 \ + --hash=sha256:e808af52a0513762df4d945ea164a24b37f2f518cbe97e03deaa0ee66139b4d6 \ + --hash=sha256:eb07647a5738b89baab047f14edd18ded523de60f3b30e75c2acc826f79c839a \ + --hash=sha256:eb7fdf1ef130660e7415e0253a01a7d5a88c9c4d158bcf75cbbd922fd65a5b58 \ + --hash=sha256:ec10e2a42b41c923c2209b846126c6582db5e43a33157e9870ba9fb70dc7854b \ + --hash=sha256:ee2aa19e03161671ec964004fb74b2257805d9710bf14a5c704558b9d8dbaf17 \ + --hash=sha256:f08fd75c50a760c7eb068ae823777268daaf16a80b918fa58eea888f8e3919f5 \ + --hash=sha256:f4cd16206ad171cbc2470dbea9103cf9a7607d5fe8c242fdf1edf36174020664 \ + --hash=sha256:f70c9ab2595c56f81a89620e22899eea8b212a4041bd728ac6f4a28bf5d3ddd0 \ + --hash=sha256:fbabfaceaeb587e16f7008f7795cd80d20ec548dc7f94fbb0d4ec2e038ce563f # via pytest-cov -cryptography==43.0.3 \ - --hash=sha256:0c580952eef9bf68c4747774cde7ec1d85a6e61de97281f2dba83c7d2c806362 \ - --hash=sha256:0f996e7268af62598f2fc1204afa98a3b5712313a55c4c9d434aef49cadc91d4 \ - --hash=sha256:1ec0bcf7e17c0c5669d881b1cd38c4972fade441b27bda1051665faaa89bdcaa \ - --hash=sha256:281c945d0e28c92ca5e5930664c1cefd85efe80e5c0d2bc58dd63383fda29f83 \ - --hash=sha256:2ce6fae5bdad59577b44e4dfed356944fbf1d925269114c28be377692643b4ff \ - --hash=sha256:315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805 \ - --hash=sha256:443c4a81bb10daed9a8f334365fe52542771f25aedaf889fd323a853ce7377d6 \ - --hash=sha256:4a02ded6cd4f0a5562a8887df8b3bd14e822a90f97ac5e544c162899bc467664 \ - --hash=sha256:53a583b6637ab4c4e3591a15bc9db855b8d9dee9a669b550f311480acab6eb08 \ - --hash=sha256:63efa177ff54aec6e1c0aefaa1a241232dcd37413835a9b674b6e3f0ae2bfd3e \ - --hash=sha256:74f57f24754fe349223792466a709f8e0c093205ff0dca557af51072ff47ab18 \ - --hash=sha256:7e1ce50266f4f70bf41a2c6dc4358afadae90e2a1e5342d3c08883df1675374f \ - --hash=sha256:81ef806b1fef6b06dcebad789f988d3b37ccaee225695cf3e07648eee0fc6b73 \ - --hash=sha256:846da004a5804145a5f441b8530b4bf35afbf7da70f82409f151695b127213d5 \ - --hash=sha256:8ac43ae87929a5982f5948ceda07001ee5e83227fd69cf55b109144938d96984 \ - --hash=sha256:9762ea51a8fc2a88b70cf2995e5675b38d93bf36bd67d91721c309df184f49bd \ - --hash=sha256:a2a431ee15799d6db9fe80c82b055bae5a752bef645bba795e8e52687c69efe3 \ - --hash=sha256:bf7a1932ac4176486eab36a19ed4c0492da5d97123f1406cf15e41b05e787d2e \ - --hash=sha256:c2e6fc39c4ab499049df3bdf567f768a723a5e8464816e8f009f121a5a9f4405 \ - --hash=sha256:cbeb489927bd7af4aa98d4b261af9a5bc025bd87f0e3547e11584be9e9427be2 \ - --hash=sha256:d03b5621a135bffecad2c73e9f4deb1a0f977b9a8ffe6f8e002bf6c9d07b918c \ - --hash=sha256:d56e96520b1020449bbace2b78b603442e7e378a9b3bd68de65c782db1507995 \ - --hash=sha256:df6b6c6d742395dd77a23ea3728ab62f98379eff8fb61be2744d4679ab678f73 \ - --hash=sha256:e1be4655c7ef6e1bbe6b5d0403526601323420bcf414598955968c9ef3eb7d16 \ - --hash=sha256:f18c716be16bc1fea8e95def49edf46b82fccaa88587a45f8dc0ff6ab5d8e0a7 \ - --hash=sha256:f46304d6f0c6ab8e52770addfa2fc41e6629495548862279641972b6215451cd \ - --hash=sha256:f7b178f11ed3664fd0e995a47ed2b5ff0a12d893e41dd0494f406d1cf555cab7 +cryptography==46.0.6 \ + --hash=sha256:02fad249cb0e090b574e30b276a3da6a149e04ee2f049725b1f69e7b8351ec70 \ + --hash=sha256:063b67749f338ca9c5a0b7fe438a52c25f9526b851e24e6c9310e7195aad3b4d \ + --hash=sha256:12cae594e9473bca1a7aceb90536060643128bb274fcea0fc459ab90f7d1ae7a \ + --hash=sha256:12f0fa16cc247b13c43d56d7b35287ff1569b5b1f4c5e87e92cc4fcc00cd10c0 \ + --hash=sha256:22259338084d6ae497a19bae5d4c66b7ca1387d3264d1c2c0e72d9e9b6a77b97 \ + --hash=sha256:26031f1e5ca62fcb9d1fcb34b2b60b390d1aacaa15dc8b895a9ed00968b97b30 \ + --hash=sha256:27550628a518c5c6c903d84f637fbecf287f6cb9ced3804838a1295dc1fd0759 \ + --hash=sha256:2b417edbe8877cda9022dde3a008e2deb50be9c407eef034aeeb3a8b11d9db3c \ + --hash=sha256:2ea0f37e9a9cf0df2952893ad145fd9627d326a59daec9b0802480fa3bcd2ead \ + --hash=sha256:2ef9e69886cbb137c2aef9772c2e7138dc581fad4fcbcf13cc181eb5a3ab6275 \ + --hash=sha256:341359d6c9e68834e204ceaf25936dffeafea3829ab80e9503860dcc4f4dac58 \ + --hash=sha256:380343e0653b1c9d7e1f55b52aaa2dbb2fdf2730088d48c43ca1c7c0abb7cc2f \ + --hash=sha256:3c21d92ed15e9cfc6eb64c1f5a0326db22ca9c2566ca46d845119b45b4400361 \ + --hash=sha256:3dfa6567f2e9e4c5dceb8ccb5a708158a2a871052fa75c8b78cb0977063f1507 \ + --hash=sha256:456b3215172aeefb9284550b162801d62f5f264a081049a3e94307fe20792cfa \ + --hash=sha256:4668298aef7cddeaf5c6ecc244c2302a2b8e40f384255505c22875eebb47888b \ + --hash=sha256:50575a76e2951fe7dbd1f56d181f8c5ceeeb075e9ff88e7ad997d2f42af06e7b \ + --hash=sha256:639301950939d844a9e1c4464d7e07f902fe9a7f6b215bb0d4f28584729935d8 \ + --hash=sha256:64235194bad039a10bb6d2d930ab3323baaec67e2ce36215fd0952fad0930ca8 \ + --hash=sha256:6617f67b1606dfd9fe4dbfa354a9508d4a6d37afe30306fe6c101b7ce3274b72 \ + --hash=sha256:67177e8a9f421aa2d3a170c3e56eca4e0128883cf52a071a7cbf53297f18b175 \ + --hash=sha256:6728c49e3b2c180ef26f8e9f0a883a2c585638db64cf265b49c9ba10652d430e \ + --hash=sha256:6739d56300662c468fddb0e5e291f9b4d084bead381667b9e654c7dd81705124 \ + --hash=sha256:69cf0056d6947edc6e6760e5f17afe4bea06b56a9ac8a06de9d2bd6b532d4f3a \ + --hash=sha256:760997a4b950ff00d418398ad73fbc91aa2894b5c1db7ccb45b4f68b42a63b3c \ + --hash=sha256:79e865c642cfc5c0b3eb12af83c35c5aeff4fa5c672dc28c43721c2c9fdd2f0f \ + --hash=sha256:7e6142674f2a9291463e5e150090b95a8519b2fb6e6aaec8917dd8d094ce750d \ + --hash=sha256:7f417f034f91dcec1cb6c5c35b07cdbb2ef262557f701b4ecd803ee8cefed4f4 \ + --hash=sha256:7f6690b6c55e9c5332c0b59b9c8a3fb232ebf059094c17f9019a51e9827df91c \ + --hash=sha256:8927ccfbe967c7df312ade694f987e7e9e22b2425976ddbf28271d7e58845290 \ + --hash=sha256:8ce35b77aaf02f3b59c90b2c8a05c73bac12cea5b4e8f3fbece1f5fddea5f0ca \ + --hash=sha256:8e7304c4f4e9490e11efe56af6713983460ee0780f16c63f219984dab3af9d2d \ + --hash=sha256:90e5f0a7b3be5f40c3a0a0eafb32c681d8d2c181fc2a1bdabe9b3f611d9f6b1a \ + --hash=sha256:97c8115b27e19e592a05c45d0dd89c57f81f841cc9880e353e0d3bf25b2139ed \ + --hash=sha256:9a693028b9cbe51b5a1136232ee8f2bc242e4e19d456ded3fa7c86e43c713b4a \ + --hash=sha256:9a9c42a2723999a710445bc0d974e345c32adfd8d2fac6d8a251fa829ad31cfb \ + --hash=sha256:a3e84d5ec9ba01f8fd03802b2147ba77f0c8f2617b2aff254cedd551844209c8 \ + --hash=sha256:aad75154a7ac9039936d50cf431719a2f8d4ed3d3c277ac03f3339ded1a5e707 \ + --hash=sha256:b12c6b1e1651e42ab5de8b1e00dc3b6354fdfd778e7fa60541ddacc27cd21410 \ + --hash=sha256:b928a3ca837c77a10e81a814a693f2295200adb3352395fad024559b7be7a736 \ + --hash=sha256:bcb87663e1f7b075e48c3be3ecb5f0b46c8fc50b50a97cf264e7f60242dca3f2 \ + --hash=sha256:c797e2517cb7880f8297e2c0f43bb910e91381339336f75d2c1c2cbf811b70b4 \ + --hash=sha256:c89eb37fae9216985d8734c1afd172ba4927f5a05cfd9bf0e4863c6d5465b013 \ + --hash=sha256:cdcd3edcbc5d55757e5f5f3d330dd00007ae463a7e7aa5bf132d1f22a4b62b19 \ + --hash=sha256:d24c13369e856b94892a89ddf70b332e0b70ad4a5c43cf3e9cb71d6d7ffa1f7b \ + --hash=sha256:d4e4aadb7fc1f88687f47ca20bb7227981b03afaae69287029da08096853b738 \ + --hash=sha256:d9528b535a6c4f8ff37847144b8986a9a143585f0540fbcb1a98115b543aa463 \ + --hash=sha256:ed3775295fb91f70b4027aeba878d79b3e55c0b3e97eaa4de71f8f23a9f2eb77 \ + --hash=sha256:ed418c37d095aeddf5336898a132fba01091f0ac5844e3e8018506f014b6d2c4 # via # feast (pyproject.toml) # azure-identity @@ -946,29 +989,30 @@ cryptography==43.0.3 \ # jwcrypto # moto # msal + # oracledb # paramiko # pyjwt # pyopenssl # snowflake-connector-python # types-pyopenssl # types-redis -dask[dataframe]==2026.1.2 \ - --hash=sha256:1136683de2750d98ea792670f7434e6c1cfce90cab2cc2f2495a9e60fd25a4fc \ - --hash=sha256:46a0cf3b8d87f78a3d2e6b145aea4418a6d6d606fe6a16c79bd8ca2bb862bc91 +dask[dataframe]==2026.3.0 \ + --hash=sha256:be614b9242b0b38288060fb2d7696125946469c98a1c30e174883fd199e0428d \ + --hash=sha256:f7d96c8274e8a900d217c1ff6ea8d1bbf0b4c2c21e74a409644498d925eb8f85 # via feast (pyproject.toml) -datasets==4.5.0 \ - --hash=sha256:00c698ce1c2452e646cc5fad47fef39d3fe78dd650a8a6eb205bb45eb63cd500 \ - --hash=sha256:b5d7e08096ffa407dd69e58b1c0271c9b2506140839b8d99af07375ad31b6726 +datasets==4.8.4 \ + --hash=sha256:a1429ed853275ce7943a01c6d2e25475b4501eb758934362106a280470df3a52 \ + --hash=sha256:cdc8bee4698e549d78bf1fed6aea2eebc760b22b084f07e6fc020c6577a6ce6d # via feast (pyproject.toml) -db-dtypes==1.5.0 \ - --hash=sha256:abdbb2e4eb965800ed6f98af0c5c1cafff9063ace09114be2d26a7f046be2c8a \ - --hash=sha256:ad9e94243f53e104bc77dbf9ae44b580d83a770d3694483aba59c9767966daa5 +db-dtypes==1.5.1 \ + --hash=sha256:901099b807c9312bc61a5bddbfb07512884e6c6d5a9edacf24d50bcf303aa5f7 \ + --hash=sha256:ad71a6645e3c1f06d4d32023940576648f43119822f825f0d22587c6ef8afe15 # via # google-cloud-bigquery # pandas-gbq -dbt-artifacts-parser==0.12.0 \ - --hash=sha256:3db93df7969c3f22c6fbf75a51b0af4c21b189d8db6f3c54e8471102c775bb0d \ - --hash=sha256:9d1c0ed41926102c1c39fdd780e1a332f58c9b794e94dba0dcf5dfefc847d6ea +dbt-artifacts-parser==0.13.0 \ + --hash=sha256:304f2b857650566fed4ed8b976ed3582332eda3cedfe7167158dbbcfced3fe47 \ + --hash=sha256:55498e8bd0d9064d56617f9c714ced8607d94ccb61e70d4b49dcfd8a28a030d8 # via feast (pyproject.toml) debugpy==1.8.20 \ --hash=sha256:077a7447589ee9bc1ff0cdf443566d0ecf540ac8aa7333b775ebcb8ce9f4ecad \ @@ -1044,16 +1088,16 @@ docling==2.27.0 \ --hash=sha256:1288ed75b27e33bf94daff34faffc6d11b7d7ccc13e3df84fb24adad3991f72d \ --hash=sha256:faba35662612a2c687a3a463e501d95f645316436084af92a0442ce162429a3d # via feast (pyproject.toml) -docling-core[chunking]==2.65.1 \ - --hash=sha256:3a143adb9cc613c503380eff92f5895078fc5a00fc7264f327d0d85ff60176cd \ - --hash=sha256:fcdb30254bc5046b52b8bec5919de3b6cdbeed915399cede5351ff328cdd020d +docling-core[chunking]==2.71.0 \ + --hash=sha256:4761857816853b2b35263b5b4518e1ea6214e0565db0bbf1d929fb976665d1a0 \ + --hash=sha256:4caa9f50c68b9dd332584ae16170b36db05d773532b14d7078b580d89d8bd2a4 # via # docling # docling-ibm-models # docling-parse -docling-ibm-models==3.11.0 \ - --hash=sha256:454401563a8e79cb33b718bc559d9bacca8a0183583e48f8e616c9184c1f5eb1 \ - --hash=sha256:68f7961069d643bfdab21b1c9ef24a979db293496f4c2283d95b1025a9ac5347 +docling-ibm-models==3.13.0 \ + --hash=sha256:a11acc6034b06e0bed8dc0ca1fa700615b8246eacce411619168e1f6562b0d0d \ + --hash=sha256:f402effae8a63b0e5c3b5ce13120601baa2cd8098beef1d53ab5a056443758d3 # via docling docling-parse==4.7.3 \ --hash=sha256:1790e7e4ae202d67875c1c48fd6f8ef5c51d10b0c23157e4989b8673f2f31308 \ @@ -1088,48 +1132,42 @@ docutils==0.19 \ --hash=sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6 \ --hash=sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc # via sphinx -duckdb==1.4.4 \ - --hash=sha256:0509b39ea7af8cff0198a99d206dca753c62844adab54e545984c2e2c1381616 \ - --hash=sha256:0d636ceda422e7babd5e2f7275f6a0d1a3405e6a01873f00d38b72118d30c10b \ - --hash=sha256:1af6e76fe8bd24875dc56dd8e38300d64dc708cd2e772f67b9fbc635cc3066a3 \ - --hash=sha256:1f8d55843cc940e36261689054f7dfb6ce35b1f5b0953b0d355b6adb654b0d52 \ - --hash=sha256:25874f8b1355e96178079e37312c3ba6d61a2354f51319dae860cf21335c3a20 \ - --hash=sha256:337f8b24e89bc2e12dadcfe87b4eb1c00fd920f68ab07bc9b70960d6523b8bc3 \ - --hash=sha256:452c5b5d6c349dc5d1154eb2062ee547296fcbd0c20e9df1ed00b5e1809089da \ - --hash=sha256:453b115f4777467f35103d8081770ac2f223fb5799178db5b06186e3ab51d1f2 \ - --hash=sha256:47dd4162da6a2be59a0aef640eb08d6360df1cf83c317dcc127836daaf3b7f7c \ - --hash=sha256:49123b579e4a6323e65139210cd72dddc593a72d840211556b60f9703bda8526 \ - --hash=sha256:4c25d5b0febda02b7944e94fdae95aecf952797afc8cb920f677b46a7c251955 \ - --hash=sha256:50f2eb173c573811b44aba51176da7a4e5c487113982be6a6a1c37337ec5fa57 \ - --hash=sha256:53cd6423136ab44383ec9955aefe7599b3fb3dd1fe006161e6396d8167e0e0d4 \ - --hash=sha256:5536eb952a8aa6ae56469362e344d4e6403cc945a80bc8c5c2ebdd85d85eb64b \ - --hash=sha256:59c8d76016dde854beab844935b1ec31de358d4053e792988108e995b18c08e7 \ - --hash=sha256:5ba684f498d4e924c7e8f30dd157da8da34c8479746c5011b6c0e037e9c60ad2 \ - --hash=sha256:5cdc4126ec925edf3112bc656ac9ed23745294b854935fa7a643a216e4455af6 \ - --hash=sha256:5e1933fac5293fea5926b0ee75a55b8cfe7f516d867310a5b251831ab61fe62b \ - --hash=sha256:6703dd1bb650025b3771552333d305d62ddd7ff182de121483d4e042ea6e2e00 \ - --hash=sha256:6792ca647216bd5c4ff16396e4591cfa9b4a72e5ad7cdd312cec6d67e8431a7c \ - --hash=sha256:6cb357cfa3403910e79e2eb46c8e445bb1ee2fd62e9e9588c6b999df4256abc1 \ - --hash=sha256:6fb1225a9ea5877421481d59a6c556a9532c32c16c7ae6ca8d127e2b878c9389 \ - --hash=sha256:707530f6637e91dc4b8125260595299ec9dd157c09f5d16c4186c5988bfbd09a \ - --hash=sha256:7df7351328ffb812a4a289732f500d621e7de9942a3a2c9b6d4afcf4c0e72526 \ - --hash=sha256:7eec0bf271ac622e57b7f6554a27a6e7d1dd2f43d1871f7962c74bcbbede15ba \ - --hash=sha256:8097201bc5fd0779d7fcc2f3f4736c349197235f4cb7171622936343a1aa8dbf \ - --hash=sha256:8bba52fd2acb67668a4615ee17ee51814124223de836d9e2fdcbc4c9021b3d3c \ - --hash=sha256:8e5c2d8a0452df55e092959c0bfc8ab8897ac3ea0f754cb3b0ab3e165cd79aff \ - --hash=sha256:a3c8542db7ffb128aceb7f3b35502ebaddcd4f73f1227569306cc34bad06680c \ - --hash=sha256:b297eff642503fd435a9de5a9cb7db4eccb6f61d61a55b30d2636023f149855f \ - --hash=sha256:bf138201f56e5d6fc276a25138341b3523e2f84733613fc43f02c54465619a95 \ - --hash=sha256:c65d15c440c31e06baaebfd2c06d71ce877e132779d309f1edf0a85d23c07e92 \ - --hash=sha256:c9566a4ed834ec7999db5849f53da0a7ee83d86830c33f471bf0211a1148ca12 \ - --hash=sha256:cd1be3d48577f5b40eb9706c6b2ae10edfe18e78eb28e31a3b922dcff1183597 \ - --hash=sha256:d0440f59e0cd9936a9ebfcf7a13312eda480c79214ffed3878d75947fc3b7d6d \ - --hash=sha256:d525de5f282b03aa8be6db86b1abffdceae5f1055113a03d5b50cd2fb8cf2ef8 \ - --hash=sha256:ddcfd9c6ff234da603a1edd5fd8ae6107f4d042f74951b65f91bc5e2643856b3 \ - --hash=sha256:e041f2fbd6888da090eca96ac167a7eb62d02f778385dd9155ed859f1c6b6dc8 \ - --hash=sha256:e870a441cb1c41d556205deb665749f26347ed13b3a247b53714f5d589596977 \ - --hash=sha256:f28a18cc790217e5b347bb91b2cab27aafc557c58d3d8382e04b4fe55d0c3f66 \ - --hash=sha256:fb94de6d023de9d79b7edc1ae07ee1d0b4f5fa8a9dcec799650b5befdf7aafec +duckdb==1.5.1 \ + --hash=sha256:054ad424b051b334052afac58cb216f3b1ebb8579fc8c641e60f0182e8725ea9 \ + --hash=sha256:05fc91767d0cfc4cf2fa68966ab5b479ac07561752e42dd0ae30327bd160f64a \ + --hash=sha256:0a6acc2040bec1f05de62a2f3f68f4c12f3ec7d6012b4317d0ab1a195af26225 \ + --hash=sha256:26e56b5f0c96189e3288d83cf7b476e23615987902f801e5788dee15ee9f24a9 \ + --hash=sha256:36e8e32621a9e2a9abe75dc15a4b54a3997f2d8b1e53ad754bae48a083c91130 \ + --hash=sha256:40c5220ec93790b18ec6278da9c6ac2608d997ee6d6f7cd44c5c3992764e8e71 \ + --hash=sha256:446d500a2977c6ae2077f340c510a25956da5c77597175c316edfa87248ceda3 \ + --hash=sha256:46f92ada9023e59f27edc048167b31ac9a03911978b1296c845a34462a27f096 \ + --hash=sha256:482f8a13f2600f527e427f73c42b5aa75536f9892868068f0aaf573055a0135f \ + --hash=sha256:553c273a6a8f140adaa6da6a6135c7f95bdc8c2e5f95252fcdf9832d758e2141 \ + --hash=sha256:5ae7c0d744d64e2753149634787cc4ab60f05ef1e542b060eeab719f3cdb7723 \ + --hash=sha256:5d4147422d91ccdc2d2abf6ed24196025e020259d1d267970ae20c13c2ce84b1 \ + --hash=sha256:6af347debc8b721aa72e48671166282da979d5e5ae52dbc660ab417282b48e23 \ + --hash=sha256:6ba302115f63f6482c000ccfd62efdb6c41d9d182a5bcd4a90e7ab8cd13856eb \ + --hash=sha256:6f7361d66cc801d9eb4df734b139cd7b0e3c257a16f3573ebd550ddb255549e6 \ + --hash=sha256:715f05ea198d20d7f8b407b9b84e0023d17f2b9096c194cea702b7840e74f1f7 \ + --hash=sha256:71dddcebbc5a70e946a06c30b59b5dd7999c9833d307168f90fb4e4b672ab63e \ + --hash=sha256:8150c569b2aa4573b51ba8475e814aa41fd53a3d510c1ffb96f1139f46faf611 \ + --hash=sha256:8843bd9594e1387f1e601439e19ad73abdf57356104fd1e53a708255bb95a13d \ + --hash=sha256:8c0088765747ae5d6c9f89987bb36f9fb83564f07090d721344ce8e1abedffea \ + --hash=sha256:972d0dbf283508f9bc446ee09c3838cb7c7f114b5bdceee41753288c97fe2f7c \ + --hash=sha256:a28531cee2a5a42d89f9ba4da53bfeb15681f12acc0263476c8705380dadce07 \ + --hash=sha256:a3be2072315982e232bfe49c9d3db0a59ba67b2240a537ef42656cc772a887c7 \ + --hash=sha256:ac2804043bd1bc10b5da18f8f4c706877197263a510c41be9b4c0062f5783dcc \ + --hash=sha256:afab8b4b1f4469c3879bb049dd039f8fce402712050324e9524a43d7324c5e87 \ + --hash=sha256:b370d1620a34a4538ef66524fcee9de8171fa263c701036a92bc0b4c1f2f9c6d \ + --hash=sha256:b8b0808dba0c63b7633bdaefb34e08fe0612622224f9feb0e7518904b1615101 \ + --hash=sha256:bc7ca6a1a40e7e4c933017e6c09ef18032add793df4e42624c6c0c87e0bebdad \ + --hash=sha256:caa65e1f5bf007430bf657c37cab7ab81a4ddf8d337e3062bcc5085d17ef038b \ + --hash=sha256:d68c5a01a283cb13b79eafe016fe5869aa11bff8c46e7141c70aa0aac808010f \ + --hash=sha256:da137802688190835b4c863cafa77fd7e29dff662ee6d905a9ffc14f00299c91 \ + --hash=sha256:e56a20ab6cdb90a95b0c99652e28de3504ce77129087319c03c9098266183ae5 \ + --hash=sha256:e878ccb7d20872065e1597935fdb5e65efa43220c8edd0d9c4a1a7ff1f3eb277 \ + --hash=sha256:eba81e0b3011c1f23df7ea47ef4ffaa8239817959ae291515b6efd068bde2161 \ + --hash=sha256:ed6d23a3f806898e69c77430ebd8da0c79c219f97b9acbc9a29a653e09740c59 # via ibis-framework durationpy==0.10 \ --hash=sha256:1fa6893409a6e739c9c72334fc65cca1f355dbdd93405d30f726deb5bde42fba \ @@ -1158,9 +1196,9 @@ execnet==2.1.2 \ --hash=sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd \ --hash=sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec # via pytest-xdist -executing==1.2.0 \ - --hash=sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc \ - --hash=sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107 +executing==2.2.1 \ + --hash=sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4 \ + --hash=sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017 # via # codeflare-sdk # stack-data @@ -1191,9 +1229,9 @@ faiss-cpu==1.10.0 \ --hash=sha256:e71f7e24d5b02d3a51df47b77bd10f394a1b48a8331d5c817e71e9e27a8a75ac \ --hash=sha256:f71c5860c860df2320299f9e4f2ca1725beb559c04acb1cf961ed24e6218277a # via feast (pyproject.toml) -fastapi==0.129.0 \ - --hash=sha256:61315cebd2e65df5f97ec298c888f9de30430dd0612d59d6480beafbc10655af \ - --hash=sha256:b4946880e48f462692b31c083be0432275cbfb6e2274566b1be91479cc1a84ec +fastapi==0.135.3 \ + --hash=sha256:9b0f590c813acd13d0ab43dd8494138eb58e484bfac405db1f3187cfc5810d98 \ + --hash=sha256:bd6d7caf1a2bdd8d676843cdcd2287729572a1ef524fc4d65c17ae002a1be654 # via # feast (pyproject.toml) # fastapi-mcp @@ -1205,9 +1243,9 @@ fastjsonschema==2.21.2 \ --hash=sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463 \ --hash=sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de # via nbformat -filelock==3.24.2 \ - --hash=sha256:667d7dc0b7d1e1064dd5f8f8e80bdac157a6482e8d2e02cd16fd3b6b33bd6556 \ - --hash=sha256:c22803117490f156e59fafce621f0550a7a853e2bbf4f87f112b11d469b6c81b +filelock==3.25.2 \ + --hash=sha256:b64ece2b38f4ca29dd3e810287aa8c48182bbecd1ae6e9ae126c9b35f1382694 \ + --hash=sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70 # via # datasets # huggingface-hub @@ -1372,9 +1410,9 @@ geomet==1.1.0 \ --hash=sha256:4372fe4e286a34acc6f2e9308284850bd8c4aa5bc12065e2abbd4995900db12f \ --hash=sha256:51e92231a0ef6aaa63ac20c443377ba78a303fd2ecd179dc3567de79f3c11605 # via cassandra-driver -google-api-core[grpc]==2.29.0 \ - --hash=sha256:84181be0f8e6b04006df75ddfe728f24489f0af57c96a529ff7cf45bc28797f7 \ - --hash=sha256:d30bc60980daa36e314b5d5a3e5958b0200cb44ca8fa1be2b614e932b75a3ea9 +google-api-core[grpc]==2.30.2 \ + --hash=sha256:9a8113e1a88bdc09a7ff629707f2214d98d61c7f6ceb0ea38c42a095d02dc0f9 \ + --hash=sha256:a4c226766d6af2580577db1f1a51bf53cd262f722b49731ce7414c43068a9594 # via # feast (pyproject.toml) # google-cloud-bigquery @@ -1385,9 +1423,9 @@ google-api-core[grpc]==2.29.0 \ # google-cloud-storage # opencensus # pandas-gbq -google-auth==2.48.0 \ - --hash=sha256:2e2a537873d449434252a9632c28bfc268b0adb1e53f9fb62afc5333a975903f \ - --hash=sha256:4f7e706b0cd3208a3d940a19a822c37a476ddba5450156c3e6624a71f7c841ce +google-auth==2.49.1 \ + --hash=sha256:16d40da1c3c5a0533f57d268fe72e0ebb0ae1cc3b567024122651c045d879b64 \ + --hash=sha256:195ebe3dca18eddd1b3db5edc5189b76c13e96f29e73043b923ebcf3f1a860f7 # via # google-api-core # google-auth-oauthlib @@ -1399,37 +1437,37 @@ google-auth==2.48.0 \ # google-cloud-storage # pandas-gbq # pydata-google-auth -google-auth-oauthlib==1.2.4 \ - --hash=sha256:0e922eea5f2baacaf8867febb782e46e7b153236c21592ed76ab3ddb77ffd772 \ - --hash=sha256:3ca93859c6cc9003c8e12b2a0868915209d7953f05a70f4880ab57d57e56ee3e +google-auth-oauthlib==1.3.1 \ + --hash=sha256:14c22c7b3dd3d06dbe44264144409039465effdd1eef94f7ce3710e486cc4bfa \ + --hash=sha256:1a139ef23f1318756805b0e95f655c238bffd29655329a2978218248da4ee7f8 # via # pandas-gbq # pydata-google-auth -google-cloud-bigquery[pandas]==3.40.1 \ - --hash=sha256:75afcfb6e007238fe1deefb2182105249321145ff921784fe7b1de2b4ba24506 \ - --hash=sha256:9082a6b8193aba87bed6a2c79cf1152b524c99bb7e7ac33a785e333c09eac868 +google-cloud-bigquery[pandas]==3.41.0 \ + --hash=sha256:2217e488b47ed576360c9b2cc07d59d883a54b83167c0ef37f915c26b01a06fe \ + --hash=sha256:2a5b5a737b401cbd824a6e5eac7554100b878668d908e6548836b5d8aaa4dcaa # via # feast (pyproject.toml) # pandas-gbq -google-cloud-bigquery-storage==2.36.1 \ - --hash=sha256:99ad6b8810d028f0cf368ea0cc54b3cda20e856f05eb4cda51f1db2a70692286 \ - --hash=sha256:fd3917584a41f7a9d9c633b31ff43103869b108224e8a4b765537eb1ea83148c +google-cloud-bigquery-storage==2.37.0 \ + --hash=sha256:1e319c27ef60fc31030f6e0b52e5e891e1cdd50551effe8c6f673a4c3c56fcb6 \ + --hash=sha256:f88ee7f1e49db1e639da3d9a8b79835ca4bc47afbb514fb2adfc0ccb41a7fd97 # via feast (pyproject.toml) -google-cloud-bigtable==2.35.0 \ - --hash=sha256:f355bfce1f239453ec2bb3839b0f4f9937cf34ef06ef29e1ca63d58fd38d0c50 \ - --hash=sha256:f5699012c5fea4bd4bdf7e80e5e3a812a847eb8f41bf8dc2f43095d6d876b83b +google-cloud-bigtable==2.36.0 \ + --hash=sha256:21b2f41231b7368a550b44d5b493b811b3507fcb23eb26d00005cd3f205f2207 \ + --hash=sha256:d5987733c2f60c739f93f259d2037858411cc994ac37cdfbccb6bb159f3ca43e # via feast (pyproject.toml) -google-cloud-core==2.5.0 \ - --hash=sha256:67d977b41ae6c7211ee830c7912e41003ea8194bff15ae7d72fd6f51e57acabc \ - --hash=sha256:7c1b7ef5c92311717bd05301aa1a91ffbc565673d3b0b4163a52d8413a186963 +google-cloud-core==2.5.1 \ + --hash=sha256:3dc94bdec9d05a31d9f355045ed0f369fbc0d8c665076c734f065d729800f811 \ + --hash=sha256:ea62cdf502c20e3e14be8a32c05ed02113d7bef454e40ff3fab6fe1ec9f1f4e7 # via # google-cloud-bigquery # google-cloud-bigtable # google-cloud-datastore # google-cloud-storage -google-cloud-datastore==2.23.0 \ - --hash=sha256:24a1b1d29b902148fe41b109699f76fd3aa60591e9d547c0f8b87d7bf9ff213f \ - --hash=sha256:80049883a4ae928fdcc661ba6803ec267665dc0e6f3ce2da91441079a6bb6387 +google-cloud-datastore==2.24.0 \ + --hash=sha256:81f1d1c12c2906f59507f72742545ab04c38f62ed70b0542057e3cf04a53aa65 \ + --hash=sha256:f087c02a6aa4ac68bbf17f0c048ae3ee355856bf09c51439bfba193741387792 # via feast (pyproject.toml) google-cloud-storage==2.19.0 \ --hash=sha256:aeb971b5c29cf8ab98445082cbfe7b161a1f48ed275822f59ed3f1524ea54fba \ @@ -1473,15 +1511,15 @@ google-crc32c==1.8.0 \ # google-cloud-bigtable # google-cloud-storage # google-resumable-media -google-resumable-media==2.8.0 \ - --hash=sha256:dd14a116af303845a8d932ddae161a26e86cc229645bc98b39f026f9b1717582 \ - --hash=sha256:f1157ed8b46994d60a1bc432544db62352043113684d4e030ee02e77ebe9a1ae +google-resumable-media==2.8.2 \ + --hash=sha256:82b6d8ccd11765268cdd2a2123f417ec806b8eef3000a9a38dfe3033da5fb220 \ + --hash=sha256:f3354a182ebd193ae3f42e3ef95e6c9b10f128320de23ac7637236713b1acd70 # via # google-cloud-bigquery # google-cloud-storage -googleapis-common-protos[grpc]==1.72.0 \ - --hash=sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038 \ - --hash=sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5 +googleapis-common-protos[grpc]==1.74.0 \ + --hash=sha256:57971e4eeeba6aad1163c1f0fc88543f965bb49129b8bb55b2b7b26ecab084f1 \ + --hash=sha256:702216f78610bb510e3f12ac3cafd281b7ac45cc5d86e90ad87e4d301a3426b5 # via # feast (pyproject.toml) # google-api-core @@ -1491,9 +1529,9 @@ great-expectations==0.18.8 \ --hash=sha256:ab41cfa3de829a4f77bdcd4a23244684cbb67fdacc734d38910164cd02ec95b6 \ --hash=sha256:c1205bede593f679e22e0b3826d6ae1623c439cafd553f9f0bc2b0fd441f6ed9 # via feast (pyproject.toml) -grpc-google-iam-v1==0.14.3 \ - --hash=sha256:7a7f697e017a067206a3dfef44e4c634a34d3dee135fe7d7a4613fe3e59217e6 \ - --hash=sha256:879ac4ef33136c5491a6300e27575a9ec760f6cdf9a2518798c1b8977a5dc389 +grpc-google-iam-v1==0.14.4 \ + --hash=sha256:392b3796947ed6334e61171d9ab06bf7eb357f554e5fc7556ad7aab6d0e17038 \ + --hash=sha256:412facc320fcbd94034b4df3d557662051d4d8adfa86e0ddb4dca70a3f739964 # via google-cloud-bigtable grpcio==1.62.3 \ --hash=sha256:059444f0ed5dba73ab7dd0ee7e8e6b606df4130d2b0a9f010f84da4ab9f6c2d8 \ @@ -1563,7 +1601,6 @@ grpcio==1.62.3 \ # grpcio-status # grpcio-testing # grpcio-tools - # ikvpy # pymilvus # qdrant-client # ray @@ -1578,9 +1615,7 @@ grpcio-reflection==1.62.3 \ grpcio-status==1.62.3 \ --hash=sha256:289bdd7b2459794a12cf95dc0cb727bd4a1742c37bd823f760236c937e53a485 \ --hash=sha256:f9049b762ba8de6b1086789d8315846e094edac2c50beaf462338b301a8fd4b8 - # via - # google-api-core - # ikvpy + # via google-api-core grpcio-testing==1.62.3 \ --hash=sha256:06a4d7eb30d22f91368aa7f48bfc33563da13b9d951314455ca8c9c987fb75bb \ --hash=sha256:f63577f28aaa95ea525124a0fd63c3429d71f769f4179b13f5e6cbc54979bfab @@ -1635,9 +1670,9 @@ grpcio-tools==1.62.3 \ --hash=sha256:f4b1615adf67bd8bb71f3464146a6f9949972d06d21a4f5e87e73f6464d97f57 \ --hash=sha256:f6831fdec2b853c9daa3358535c55eed3694325889aa714070528cf8f92d7d6d # via feast (pyproject.toml) -gunicorn==25.1.0 \ - --hash=sha256:1426611d959fa77e7de89f8c0f32eed6aa03ee735f98c01efba3e281b1c47616 \ - --hash=sha256:d0b1236ccf27f72cfe14bce7caadf467186f19e865094ca84221424e839b8b8b +gunicorn==25.3.0 \ + --hash=sha256:cacea387dab08cd6776501621c295a904fe8e3b7aae9a1a3cbb26f4e7ed54660 \ + --hash=sha256:f74e1b2f9f76f6cd1ca01198968bd2dd65830edc24b6e8e4d78de8320e2fe889 # via # feast (pyproject.toml) # uvicorn-worker @@ -1659,29 +1694,32 @@ hazelcast-python-client==5.6.0 \ --hash=sha256:834b87076a47c781ef80bdcb522b86abc75ff28992dfe384e47f669f06cabb18 \ --hash=sha256:e2cec409068990ca9b4381fe97160cc2375412334782bef45ab4c8fe4d10536c # via feast (pyproject.toml) -hf-xet==1.2.0 \ - --hash=sha256:10bfab528b968c70e062607f663e21e34e2bba349e8038db546646875495179e \ - --hash=sha256:210d577732b519ac6ede149d2f2f34049d44e8622bf14eb3d63bbcd2d4b332dc \ - --hash=sha256:27df617a076420d8845bea087f59303da8be17ed7ec0cd7ee3b9b9f579dff0e4 \ - --hash=sha256:293a7a3787e5c95d7be1857358a9130694a9c6021de3f27fa233f37267174382 \ - --hash=sha256:29c8fc913a529ec0a91867ce3d119ac1aac966e098cf49501800c870328cc090 \ - --hash=sha256:2a212e842647b02eb6a911187dc878e79c4aa0aa397e88dd3b26761676e8c1f8 \ - --hash=sha256:30e06daccb3a7d4c065f34fc26c14c74f4653069bb2b194e7f18f17cbe9939c0 \ - --hash=sha256:3651fd5bfe0281951b988c0facbe726aa5e347b103a675f49a3fa8144c7968fd \ - --hash=sha256:46740d4ac024a7ca9b22bebf77460ff43332868b661186a8e46c227fdae01848 \ - --hash=sha256:4c1428c9ae73ec0939410ec73023c4f842927f39db09b063b9482dac5a3bb737 \ - --hash=sha256:66e159cbfcfbb29f920db2c09ed8b660eb894640d284f102ada929b6e3dc410a \ - --hash=sha256:6de1fc44f58f6dd937956c8d304d8c2dea264c80680bcfa61ca4a15e7b76780f \ - --hash=sha256:7d40b18769bb9a8bc82a9ede575ce1a44c75eb80e7375a01d76259089529b5dc \ - --hash=sha256:9c91d5ae931510107f148874e9e2de8a16052b6f1b3ca3c1b12f15ccb491390f \ - --hash=sha256:a55558084c16b09b5ed32ab9ed38421e2d87cf3f1f89815764d1177081b99865 \ - --hash=sha256:a8c27070ca547293b6890c4bf389f713f80e8c478631432962bb7f4bc0bd7d7f \ - --hash=sha256:b70218dd548e9840224df5638fdc94bd033552963cfa97f9170829381179c813 \ - --hash=sha256:cd3a6027d59cfb60177c12d6424e31f4b5ff13d8e3a1247b3a584bf8977e6df5 \ - --hash=sha256:ceeefcd1b7aed4956ae8499e2199607765fbd1c60510752003b6cc0b8413b649 \ - --hash=sha256:d06fa97c8562fb3ee7a378dd9b51e343bc5bc8190254202c9771029152f5e08c \ - --hash=sha256:e6584a52253f72c9f52f9e549d5895ca7a471608495c4ecaa6cc73dba2b24d69 \ - --hash=sha256:f182f264ed2acd566c514e45da9f2119110e48a87a327ca271027904c70c5832 +hf-xet==1.4.3 \ + --hash=sha256:0392c79b7cf48418cd61478c1a925246cf10639f4cd9d94368d8ca1e8df9ea07 \ + --hash=sha256:1feb0f3abeacee143367c326a128a2e2b60868ec12a36c225afb1d6c5a05e6d2 \ + --hash=sha256:21644b404bb0100fe3857892f752c4d09642586fd988e61501c95bbf44b393a3 \ + --hash=sha256:22bdc1f5fb8b15bf2831440b91d1c9bbceeb7e10c81a12e8d75889996a5c9da8 \ + --hash=sha256:27c976ba60079fb8217f485b9c5c7fcd21c90b0367753805f87cb9f3cdc4418a \ + --hash=sha256:2815a49a7a59f3e2edf0cf113ae88e8cb2ca2a221bf353fb60c609584f4884d4 \ + --hash=sha256:39f2d2e9654cd9b4319885733993807aab6de9dfbd34c42f0b78338d6617421f \ + --hash=sha256:42ee323265f1e6a81b0e11094564fb7f7e0ec75b5105ffd91ae63f403a11931b \ + --hash=sha256:49ad8a8cead2b56051aa84d7fce3e1335efe68df3cf6c058f22a65513885baac \ + --hash=sha256:5251d5ece3a81815bae9abab41cf7ddb7bcb8f56411bce0827f4a3071c92fdc6 \ + --hash=sha256:60cf7fc43a99da0a853345cf86d23738c03983ee5249613a6305d3e57a5dca74 \ + --hash=sha256:681c92a07796325778a79d76c67011764ecc9042a8c3579332b61b63ae512075 \ + --hash=sha256:6b591fcad34e272a5b02607485e4f2a1334aebf1bc6d16ce8eb1eb8978ac2021 \ + --hash=sha256:7551659ba4f1e1074e9623996f28c3873682530aee0a846b7f2f066239228144 \ + --hash=sha256:7716d62015477a70ea272d2d68cd7cad140f61c52ee452e133e139abfe2c17ba \ + --hash=sha256:7c2c7e20bcfcc946dc67187c203463f5e932e395845d098cc2a93f5b67ca0b47 \ + --hash=sha256:8b301fc150290ca90b4fccd079829b84bb4786747584ae08b94b4577d82fb791 \ + --hash=sha256:8ddedb73c8c08928c793df2f3401ec26f95be7f7e516a7bee2fbb546f6676113 \ + --hash=sha256:987f09cfe418237812896a6736b81b1af02a3a6dcb4b4944425c4c4fca7a7cf8 \ + --hash=sha256:bee693ada985e7045997f05f081d0e12c4c08bd7626dc397f8a7c487e6c04f7f \ + --hash=sha256:c5b48db1ee344a805a1b9bd2cda9b6b65fe77ed3787bd6e87ad5521141d317cd \ + --hash=sha256:d0da85329eaf196e03e90b84c2d0aca53bd4573d097a75f99609e80775f98025 \ + --hash=sha256:d972fbe95ddc0d3c0fc49b31a8a69f47db35c1e3699bf316421705741aab6653 \ + --hash=sha256:e23717ce4186b265f69afa66e6f0069fe7efbf331546f5c313d00e123dc84583 \ + --hash=sha256:fc360b70c815bf340ed56c7b8c63aacf11762a4b099b2fe2c9bd6d6068668c08 # via huggingface-hub hiredis==2.4.0 \ --hash=sha256:06815c3b9bf7225c4dcc9dd9dfb5a9fa91b4f680104443ef3fcd78410d7eb027 \ @@ -1856,6 +1894,7 @@ huggingface-hub==0.36.2 \ # datasets # docling # docling-ibm-models + # sentence-transformers # timm # tokenizers # transformers @@ -1863,13 +1902,13 @@ hyperframe==6.1.0 \ --hash=sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5 \ --hash=sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08 # via h2 -ibis-framework[duckdb, mssql]==12.0.0 \ +ibis-framework[duckdb, mssql, oracle]==12.0.0 \ --hash=sha256:0bbd790f268da9cb87926d5eaad2b827a573927113c4ed3be5095efa89b9e512 \ --hash=sha256:238624f2c14fdab8382ca2f4f667c3cdb81e29844cd5f8db8a325d0743767c61 # via feast (pyproject.toml) -identify==2.6.16 \ - --hash=sha256:391ee4d77741d994189522896270b787aed8670389bfd60f326d677d64a6dfb0 \ - --hash=sha256:846857203b5511bbe94d5a352a48ef2359532bc8f6727b5544077a0dcfb24980 +identify==2.6.18 \ + --hash=sha256:873ac56a5e3fd63e7438a7ecbc4d91aca692eb3fefa4534db2b7913f3fc352fd \ + --hash=sha256:8db9d3c8ea9079db92cafb0ebf97abdc09d52e97f4dcf773a2e694048b7cd737 # via pre-commit idna==3.11 \ --hash=sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea \ @@ -1881,17 +1920,13 @@ idna==3.11 \ # requests # snowflake-connector-python # yarl -ikvpy==0.0.36 \ - --hash=sha256:b0edf6fb6482877940f6c2b5d59a7fabe30cb554b13b88ca52805f043cfda5b3 \ - --hash=sha256:c0ce7dfb61456c283c9ba2cdeb68b3647f245c3905bca652ca2a1068804939d1 - # via feast (pyproject.toml) -imageio==2.37.2 \ - --hash=sha256:0212ef2727ac9caa5ca4b2c75ae89454312f440a756fcfc8ef1993e718f50f8a \ - --hash=sha256:ad9adfb20335d718c03de457358ed69f141021a333c40a53e57273d8a5bd0b9b +imageio==2.37.3 \ + --hash=sha256:46f5bb8522cd421c0f5ae104d8268f569d856b29eb1a13b92829d1970f32c9f0 \ + --hash=sha256:bbb37efbfc4c400fcd534b367b91fcd66d5da639aaa138034431a1c5e0a41451 # via scikit-image -imagesize==1.4.1 \ - --hash=sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b \ - --hash=sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a +imagesize==2.0.0 \ + --hash=sha256:5667c5bbb57ab3f1fa4bc366f4fbc971db3d5ed011fd2715fd8001f782718d96 \ + --hash=sha256:8e8358c4a05c304f1fccf7ff96f036e7243a189e9e42e90851993c558cfe9ee3 # via sphinx importlib-metadata==8.7.1 \ --hash=sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb \ @@ -1915,9 +1950,9 @@ ipykernel==7.2.0 \ --hash=sha256:18ed160b6dee2cbb16e5f3575858bc19d8f1fe6046a9a680c708494ce31d909e \ --hash=sha256:3bbd4420d2b3cc105cbdf3756bfc04500b1e52f090a90716851f3916c62e1661 # via jupyterlab -ipython==9.10.0 \ - --hash=sha256:c6ab68cc23bba8c7e18e9b932797014cc61ea7fd6f19de180ab9ba73e65ee58d \ - --hash=sha256:cd9e656be97618a0676d058134cd44e6dc7012c0e5cb36a9ce96a8c904adaf77 +ipython==9.10.1 \ + --hash=sha256:82d18ae9fb9164ded080c71ef92a182ee35ee7db2395f67616034bebb020a232 \ + --hash=sha256:e170e9b2a44312484415bdb750492699bf329233b03f2557a9692cce6466ada4 # via # great-expectations # ipykernel @@ -1969,9 +2004,9 @@ joblib==1.5.3 \ --hash=sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713 \ --hash=sha256:8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3 # via scikit-learn -json5==0.13.0 \ - --hash=sha256:9a08e1dd65f6a4d4c6fa82d216cf2477349ec2346a38fd70cc11d2557499fbcc \ - --hash=sha256:b1edf8d487721c0bf64d83c28e91280781f6e21f4a797d3261c7c828d4c165bf +json5==0.14.0 \ + --hash=sha256:56cf861bab076b1178eb8c92e1311d273a9b9acea2ccc82c276abf839ebaef3a \ + --hash=sha256:b3f492fad9f6cdbced8b7d40b28b9b1c9701c5f561bef0d33b81c2ff433fefcb # via jupyterlab-server jsonlines==4.0.0 \ --hash=sha256:0c6d2c09117550c089995247f605ae4cf77dd1533041d366351f6f298822ea74 \ @@ -1981,9 +2016,9 @@ jsonpatch==1.33 \ --hash=sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade \ --hash=sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c # via great-expectations -jsonpointer==3.0.0 \ - --hash=sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942 \ - --hash=sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef +jsonpointer==3.1.1 \ + --hash=sha256:0b801c7db33a904024f6004d526dcc53bbb8a4a0f4e32bfd10beadf60adf1900 \ + --hash=sha256:8ff8b95779d071ba472cf5bc913028df06031797532f08a7d5b602d8b2a488ca # via # jsonpatch # jsonschema @@ -2030,9 +2065,9 @@ jupyter-events==0.12.0 \ --hash=sha256:6464b2fa5ad10451c3d35fabc75eab39556ae1e2853ad0c0cc31b656731a97fb \ --hash=sha256:fc3fce98865f6784c9cd0a56a20644fc6098f21c8c33834a8d9fe383c17e554b # via jupyter-server -jupyter-lsp==2.3.0 \ - --hash=sha256:458aa59339dc868fb784d73364f17dbce8836e906cd75fd471a325cba02e0245 \ - --hash=sha256:e914a3cb2addf48b1c7710914771aaf1819d46b2e5a79b0f917b5478ec93f34f +jupyter-lsp==2.3.1 \ + --hash=sha256:71b954d834e85ff3096400554f2eefaf7fe37053036f9a782b0f7c5e42dadb81 \ + --hash=sha256:fdf8a4aa7d85813976d6e29e95e6a2c8f752701f926f2715305249a3829805a6 # via jupyterlab jupyter-server==2.17.0 \ --hash=sha256:c38ea898566964c888b4772ae1ed58eca84592e88251d2cfc4d171f81f7e99d5 \ @@ -2047,9 +2082,9 @@ jupyter-server-terminals==0.5.4 \ --hash=sha256:55be353fc74a80bc7f3b20e6be50a55a61cd525626f578dcb66a5708e2007d14 \ --hash=sha256:bbda128ed41d0be9020349f9f1f2a4ab9952a73ed5f5ac9f1419794761fb87f5 # via jupyter-server -jupyterlab==4.5.4 \ - --hash=sha256:c215f48d8e4582bd2920ad61cc6a40d8ebfef7e5a517ae56b8a9413c9789fdfb \ - --hash=sha256:cc233f70539728534669fb0015331f2a3a87656207b3bb2d07916e9289192f12 +jupyterlab==4.5.6 \ + --hash=sha256:642fe2cfe7f0f5922a8a558ba7a0d246c7bc133b708dfe43f7b3a826d163cf42 \ + --hash=sha256:d6b3dac883aa4d9993348e0f8e95b24624f75099aed64eab6a4351a9cdd1e580 # via notebook jupyterlab-pygments==0.3.0 \ --hash=sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d \ @@ -2069,23 +2104,28 @@ jwcrypto==1.5.6 \ --hash=sha256:150d2b0ebbdb8f40b77f543fb44ffd2baeff48788be71f67f03566692fd55789 \ --hash=sha256:771a87762a0c081ae6166958a954f80848820b2ab066937dc8b8379d65b1b039 # via python-keycloak +kube-authkit==0.4.0 \ + --hash=sha256:1df61ac392fca96c8f5ae8c3d6e9918f1e1655d212434b3c3da5f92cc23b660d \ + --hash=sha256:3bf5fc6ddc882498040118c907628ea68789f9a947454c241972008be59601a3 + # via codeflare-sdk kubernetes==35.0.0 \ --hash=sha256:39e2b33b46e5834ef6c3985ebfe2047ab39135d41de51ce7641a7ca5b372a13d \ --hash=sha256:3d00d344944239821458b9efd484d6df9f011da367ecb155dadf9513f05f09ee # via # feast (pyproject.toml) # codeflare-sdk + # kube-authkit lark==1.3.1 \ --hash=sha256:b426a7a6d6d53189d318f2b6236ab5d6429eaf09259f1ca33eb716eed10d2905 \ --hash=sha256:c629b661023a014c37da873b4ff58a817398d12635d3bbb2c5a03be7fe5d1e12 # via rfc3987-syntax -latex2mathml==3.78.1 \ - --hash=sha256:f089b6d75e85b937f99693c93e8c16c0804008672c3dd2a3d25affd36f238100 \ - --hash=sha256:f941db80bf41db33f31df87b304e8b588f8166b813b0257c11c98f7a9d0aac71 +latex2mathml==3.79.0 \ + --hash=sha256:11bde318c2d2d6fcdd105a07509d867cee2208f653278eb80243dec7ea77a0ce \ + --hash=sha256:9f10720d4fcf6b22d1b81f6628237832419a7a29783c13aa92fa8d680165e63d # via docling-core -lazy-loader==0.4 \ - --hash=sha256:342aa8e14d543a154047afb4ba8ef17f5563baad3fc610d7b15b213b0f119efc \ - --hash=sha256:47c75182589b91a4e1a85a136c074285a5ad4d9f39c63e0d7fb76391c4574cd1 +lazy-loader==0.5 \ + --hash=sha256:717f9179a0dbed357012ddad50a5ad3d5e4d9a0b8712680d4e687f5e6e6ed9b3 \ + --hash=sha256:ab0ea149e9c554d4ffeeb21105ac60bed7f3b4fd69b1d2360a4add51b170b005 # via scikit-image locket==1.0.0 \ --hash=sha256:5c0d4c052a8bbbf750e056a8e65ccd309086f4f0f18a2eac306a8dfa4112a632 \ @@ -2405,9 +2445,9 @@ matplotlib-inline==0.2.1 \ # via # ipykernel # ipython -mcp==1.26.0 \ - --hash=sha256:904a21c33c25aa98ddbeb47273033c435e595bbacfdb177f4bd87f6dceebe1ca \ - --hash=sha256:db6e2ef491eecc1a0d93711a76f28dec2e05999f93afd48795da1c1137142c66 +mcp==1.27.0 \ + --hash=sha256:5ce1fa81614958e267b21fb2aa34e0aea8e2c6ede60d52aba45fd47246b4d741 \ + --hash=sha256:d3dc35a7eec0d458c1da4976a48f982097ddaab87e278c5511d5a4a56e852b83 # via fastapi-mcp mdurl==0.1.2 \ --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ @@ -2431,128 +2471,114 @@ mistune==3.2.0 \ # via # great-expectations # nbconvert -mmh3==5.2.0 \ - --hash=sha256:03e08c6ebaf666ec1e3d6ea657a2d363bb01effd1a9acfe41f9197decaef0051 \ - --hash=sha256:097e13c8b8a66c5753c6968b7640faefe85d8e38992703c1f666eda6ef4c3762 \ - --hash=sha256:0b898cecff57442724a0f52bf42c2de42de63083a91008fb452887e372f9c328 \ - --hash=sha256:10983c10f5c77683bd845751905ba535ec47409874acc759d5ce3ff7ef34398a \ - --hash=sha256:11730eeb16dfcf9674fdea9bb6b8e6dd9b40813b7eb839bc35113649eef38aeb \ - --hash=sha256:127c95336f2a98c51e7682341ab7cb0be3adb9df0819ab8505a726ed1801876d \ - --hash=sha256:12da42c0a55c9d86ab566395324213c319c73ecb0c239fad4726324212b9441c \ - --hash=sha256:132dd943451a7c7546978863d2f5a64977928410782e1a87d583cb60eb89e667 \ - --hash=sha256:1556e31e4bd0ac0c17eaf220be17a09c171d7396919c3794274cb3415a9d3646 \ - --hash=sha256:1a5f4d2e59d6bba8ef01b013c472741835ad961e7c28f50c82b27c57748744a4 \ - --hash=sha256:1ba55d6ca32eeef8b2625e1e4bfc3b3db52bc63014bd7e5df8cc11bf2b036b12 \ - --hash=sha256:1efc8fec8478e9243a78bb993422cf79f8ff85cb4cf6b79647480a31e0d950a8 \ - --hash=sha256:1f8d8b627799f4e2fcc7c034fed8f5f24dc7724ff52f69838a3d6d15f1ad4765 \ - --hash=sha256:1fae471339ae1b9c641f19cf46dfe6ffd7f64b1fba7c4333b99fa3dd7f21ae0a \ - --hash=sha256:1fdb36b940e9261aff0b5177c5b74a36936b902f473180f6c15bde26143681a9 \ - --hash=sha256:2421b9d665a0b1ad724ec7332fb5a98d075f50bc51a6ff854f3a1882bd650d49 \ - --hash=sha256:29c2b9ce61886809d0492a274a5a53047742dea0f703f9c4d5d223c3ea6377d3 \ - --hash=sha256:2c9da0d568569cc87315cb063486d761e38458b8ad513fedd3dc9263e1b81bcd \ - --hash=sha256:2ebfc46b39168ab1cd44670a32ea5489bcbc74a25795c61b6d888c5c2cf654ed \ - --hash=sha256:3193752fc05ea72366c2b63ff24b9a190f422e32d75fdeae71087c08fff26115 \ - --hash=sha256:33576136c06b46a7046b6d83a3d75fbca7d25f84cec743f1ae156362608dc6d2 \ - --hash=sha256:37a358cc881fe796e099c1db6ce07ff757f088827b4e8467ac52b7a7ffdca647 \ - --hash=sha256:382a6bb3f8c6532ea084e7acc5be6ae0c6effa529240836d59352398f002e3fc \ - --hash=sha256:384eda9361a7bf83a85e09447e1feafe081034af9dd428893701b959230d84be \ - --hash=sha256:38d899a156549da8ef6a9f1d6f7ef231228d29f8f69bce2ee12f5fba6d6fd7c5 \ - --hash=sha256:3bc244802ccab5220008cb712ca1508cb6a12f0eb64ad62997156410579a1770 \ - --hash=sha256:3c6041fd9d5fb5fcac57d5c80f521a36b74aea06b8566431c63e4ffc49aced51 \ - --hash=sha256:3ca975c51c5028947bbcfc24966517aac06a01d6c921e30f7c5383c195f87991 \ - --hash=sha256:3d6bfd9662a20c054bc216f861fa330c2dac7c81e7fb8307b5e32ab5b9b4d2e0 \ - --hash=sha256:419005f84ba1cab47a77465a2a843562dadadd6671b8758bf179d82a15ca63eb \ - --hash=sha256:45b590e31bc552c6f8e2150ff1ad0c28dd151e9f87589e7eaf508fbdd8e8e908 \ - --hash=sha256:49037d417419863b222ae47ee562b2de9c3416add0a45c8d7f4e864be8dc4f89 \ - --hash=sha256:4a5f5536b1cbfa72318ab3bfc8a8188b949260baed186b75f0abc75b95d8c051 \ - --hash=sha256:582f9dbeefe15c32a5fa528b79b088b599a1dfe290a4436351c6090f90ddebb8 \ - --hash=sha256:58477cf9ef16664d1ce2b038f87d2dc96d70fe50733a34a7f07da6c9a5e3538c \ - --hash=sha256:58981d6ea9646dbbf9e59a30890cbf9f610df0e4a57dbfe09215116fd90b0093 \ - --hash=sha256:5a5dba98e514fb26241868f6eb90a7f7ca0e039aed779342965ce24ea32ba513 \ - --hash=sha256:5b0b58215befe0f0e120b828f7645e97719bbba9f23b69e268ed0ac7adde8645 \ - --hash=sha256:61ac226af521a572700f863d6ecddc6ece97220ce7174e311948ff8c8919a363 \ - --hash=sha256:63830f846797187c5d3e2dae50f0848fdc86032f5bfdc58ae352f02f857e9025 \ - --hash=sha256:69fc339d7202bea69ef9bd7c39bfdf9fdabc8e6822a01eba62fb43233c1b3932 \ - --hash=sha256:6d541038b3fc360ec538fc116de87462627944765a6750308118f8b509a8eec7 \ - --hash=sha256:6ecb4e750d712abde046858ee6992b65c93f1f71b397fce7975c3860c07365d2 \ - --hash=sha256:72d80005b7634a3a2220f81fbeb94775ebd12794623bb2e1451701ea732b4aa3 \ - --hash=sha256:7303aab41e97adcf010a09efd8f1403e719e59b7705d5e3cfed3dd7571589290 \ - --hash=sha256:7434a27754049144539d2099a6d2da5d88b8bdeedf935180bf42ad59b3607aa3 \ - --hash=sha256:746a5ee71c6d1103d9b560fa147881b5e68fd35da56e54e03d5acefad0e7c055 \ - --hash=sha256:7733ec52296fc1ba22e9b90a245c821adbb943e98c91d8a330a2254612726106 \ - --hash=sha256:7901c893e704ee3c65f92d39b951f8f34ccf8e8566768c58103fb10e55afb8c1 \ - --hash=sha256:7aa18cdb58983ee660c9c400b46272e14fa253c675ed963d3812487f8ca42037 \ - --hash=sha256:7b986d506a8e8ea345791897ba5d8ba0d9d8820cd4fc3e52dbe6de19388de2e7 \ - --hash=sha256:7bbb0df897944b5ec830f3ad883e32c5a7375370a521565f5fe24443bfb2c4f7 \ - --hash=sha256:7c7f0b342fd06044bedd0b6e72177ddc0076f54fd89ee239447f8b271d919d9b \ - --hash=sha256:7e5634565367b6d98dc4aa2983703526ef556b3688ba3065edb4b9b90ede1c54 \ - --hash=sha256:7fddccd4113e7b736706e17a239a696332360cbaddf25ae75b57ba1acce65081 \ - --hash=sha256:81c504ad11c588c8629536b032940f2a359dda3b6cbfd4ad8f74cb24dcd1b0bc \ - --hash=sha256:81df0dae22cd0da87f1c978602750f33d17fb3d21fb0f326c89dc89834fea79b \ - --hash=sha256:86d1be5d63232e6eb93c50881aea55ff06eb86d8e08f9b5417c8c9b10db9db96 \ - --hash=sha256:8b0c53fe0994beade1ad7c0f13bd6fec980a0664bfbe5a6a7d64500b9ab76772 \ - --hash=sha256:8ebf241072cf2777a492d0e09252f8cc2b3edd07dfdb9404b9757bffeb4f2cee \ - --hash=sha256:931d47e08c9c8a67bf75d82f0ada8399eac18b03388818b62bfa42882d571d72 \ - --hash=sha256:932a6eec1d2e2c3c9e630d10f7128d80e70e2d47fe6b8c7ea5e1afbd98733e65 \ - --hash=sha256:941603bfd75a46023807511c1ac2f1b0f39cccc393c15039969806063b27e6db \ - --hash=sha256:956127e663d05edbeec54df38885d943dfa27406594c411139690485128525de \ - --hash=sha256:96f1e1ac44cbb42bcc406e509f70c9af42c594e72ccc7b1257f97554204445f0 \ - --hash=sha256:99bb6a4d809aa4e528ddfe2c85dd5239b78b9dd14be62cca0329db78505e7b50 \ - --hash=sha256:9f64bf06f4bf623325fda3a6d02d36cd69199b9ace99b04bb2d7fd9f89688504 \ - --hash=sha256:a094319ec0db52a04af9fdc391b4d39a1bc72bc8424b47c4411afb05413a44b5 \ - --hash=sha256:a367d4741ac0103f8198c82f429bccb9359f543ca542b06a51f4f0332e8de279 \ - --hash=sha256:a7c0c7845566b9686480e6a7e9044db4afb60038d5fabd19227443f0104eeee4 \ - --hash=sha256:aa6e5d31fdc5ed9e3e95f9873508615a778fe9b523d52c17fc770a3eb39ab6e4 \ - --hash=sha256:ae9d032488fcec32d22be6542d1a836f00247f40f320844dbb361393b5b22773 \ - --hash=sha256:b0271ac12415afd3171ab9a3c7cbfc71dee2c68760a7dc9d05bf8ed6ddfa3a7a \ - --hash=sha256:b0d753ad566c721faa33db7e2e0eddd74b224cdd3eaf8481d76c926603c7a00e \ - --hash=sha256:b29044e1ffdb84fe164d0a7ea05c7316afea93c00f8ed9449cf357c36fc4f814 \ - --hash=sha256:b5995088dd7023d2d9f310a0c67de5a2b2e06a570ecfd00f9ff4ab94a67cde43 \ - --hash=sha256:b5f317a727bba0e633a12e71228bc6a4acb4f471a98b1c003163b917311ea9a9 \ - --hash=sha256:b9a87025121d1c448f24f27ff53a5fe7b6ef980574b4a4f11acaabe702420d63 \ - --hash=sha256:bb0fdc451fb6d86d81ab8f23d881b8d6e37fc373a2deae1c02d27002d2ad7a05 \ - --hash=sha256:bb4fe46bdc6104fbc28db7a6bacb115ee6368ff993366bbd8a2a7f0076e6f0c0 \ - --hash=sha256:bc44fc2b886243d7c0d8daeb37864e16f232e5b56aaec27cc781d848264cfd28 \ - --hash=sha256:bdde97310d59604f2a9119322f61b31546748499a21b44f6715e8ced9308a6c5 \ - --hash=sha256:be1374df449465c9f2500e62eee73a39db62152a8bdfbe12ec5b5c1cd451344d \ - --hash=sha256:be7d3dca9358e01dab1bad881fb2b4e8730cec58d36dd44482bc068bfcd3bc65 \ - --hash=sha256:bf7bee43e17e81671c447e9c83499f53d99bf440bc6d9dc26a841e21acfbe094 \ - --hash=sha256:c3dca4cb5b946ee91b3d6bb700d137b1cd85c20827f89fdf9c16258253489044 \ - --hash=sha256:c3f563e8901960e2eaa64c8e8821895818acabeb41c96f2efbb936f65dbe486c \ - --hash=sha256:c463d7c1c4cfc9d751efeaadd936bbba07b5b0ed81a012b3a9f5a12f0872bd6e \ - --hash=sha256:c4a2f3d83879e3de2eb8cbf562e71563a8ed15ee9b9c2e77ca5d9f73072ac15c \ - --hash=sha256:c5584061fd3da584659b13587f26c6cad25a096246a481636d64375d0c1f6c07 \ - --hash=sha256:c677d78887244bf3095020b73c42b505b700f801c690f8eaa90ad12d3179612f \ - --hash=sha256:c903e71fd8debb35ad2a4184c1316b3cb22f64ce517b4e6747f25b0a34e41266 \ - --hash=sha256:c9ff37ba9f15637e424c2ab57a1a590c52897c845b768e4e0a4958084ec87f22 \ - --hash=sha256:cadc16e8ea64b5d9a47363013e2bea469e121e6e7cb416a7593aeb24f2ad122e \ - --hash=sha256:cedac4f4054b8f7859e5aed41aaa31ad03fce6851901a7fdc2af0275ac533c10 \ - --hash=sha256:d22c9dcafed659fadc605538946c041722b6d1104fe619dbf5cc73b3c8a0ded8 \ - --hash=sha256:d765058da196f68dc721116cab335e696e87e76720e6ef8ee5a24801af65e63d \ - --hash=sha256:d86651fa45799530885ba4dab3d21144486ed15285e8784181a0ab37a4552384 \ - --hash=sha256:dd966df3489ec13848d6c6303429bbace94a153f43d1ae2a55115fd36fd5ca5d \ - --hash=sha256:ddc63328889bcaee77b743309e5c7d2d52cee0d7d577837c91b6e7cc9e755e0b \ - --hash=sha256:dfbead5575f6470c17e955b94f92d62a03dfc3d07f2e6f817d9b93dc211a1515 \ - --hash=sha256:e0f3ed828d709f5b82d8bfe14f8856120718ec4bd44a5b26102c3030a1e12501 \ - --hash=sha256:e1861fb6b1d0453ed7293200139c0a9011eeb1376632e048e3766945b13313c5 \ - --hash=sha256:e5015f0bb6eb50008bed2d4b1ce0f2a294698a926111e4bb202c0987b4f89078 \ - --hash=sha256:e651e17bfde5840e9e4174b01e9e080ce49277b70d424308b36a7969d0d1af73 \ - --hash=sha256:e7884931fe5e788163e7b3c511614130c2c59feffdc21112290a194487efb2e9 \ - --hash=sha256:e79c00eba78f7258e5b354eccd4d7907d60317ced924ea4a5f2e9d83f5453065 \ - --hash=sha256:e912b19cf2378f2967d0c08e86ff4c6c360129887f678e27e4dde970d21b3f4d \ - --hash=sha256:e9a011469b47b752e7d20de296bb34591cdfcbe76c99c2e863ceaa2aa61113d2 \ - --hash=sha256:eb756caf8975882630ce4e9fbbeb9d3401242a72528230422c9ab3a0d278e60c \ - --hash=sha256:eba01ec3bd4a49b9ac5ca2bc6a73ff5f3af53374b8556fcc2966dd2af9eb7779 \ - --hash=sha256:ecbfc0437ddfdced5e7822d1ce4855c9c64f46819d0fdc4482c53f56c707b935 \ - --hash=sha256:eed4bba7ff8a0d37106ba931ab03bdd3915fbb025bcf4e1f0aa02bc8114960c5 \ - --hash=sha256:f35727c5118aba95f0397e18a1a5b8405425581bfe53e821f0fb444cbdc2bc9b \ - --hash=sha256:f698733a8a494466432d611a8f0d1e026f5286dee051beea4b3c3146817e35d5 \ - --hash=sha256:f7f9034c7cf05ddfaac8d7a2e63a3c97a840d4615d0a0e65ba8bdf6f8576e3be \ - --hash=sha256:fa0c966ee727aad5406d516375593c5f058c766b21236ab8985693934bb5085b \ - --hash=sha256:fc9c5f280438cf1c1a8f9abb87dc8ce9630a964120cfb5dd50d1e7ce79690c7a \ - --hash=sha256:fd6e6c3d90660d085f7e73710eab6f5545d4854b81b0135a3526e797009dbda3 \ - --hash=sha256:fdfd3fb739f4e22746e13ad7ba0c6eedf5f454b18d11249724a388868e308ee4 \ - --hash=sha256:ff3d50dc3fe8a98059f99b445dfb62792b5d006c5e0b8f03c6de2813b8376110 +mmh3==5.2.1 \ + --hash=sha256:022aa1a528604e6c83d0a7705fdef0b5355d897a9e0fa3a8d26709ceaa06965d \ + --hash=sha256:0634581290e6714c068f4aa24020acf7880927d1f0084fa753d9799ae9610082 \ + --hash=sha256:08043f7cb1fb9467c3fbbbaea7896986e7fbc81f4d3fd9289a73d9110ab6207a \ + --hash=sha256:0a3984146e414684a6be2862d84fcb1035f4984851cb81b26d933bab6119bf00 \ + --hash=sha256:0bbc17250b10d3466875a40a52520a6bac3c02334ca709207648abd3c223ed5c \ + --hash=sha256:0cc21533878e5586b80d74c281d7f8da7932bc8ace50b8d5f6dbf7e3935f63f1 \ + --hash=sha256:0d0b7e803191db5f714d264044e06189c8ccd3219e936cc184f07106bd17fd7b \ + --hash=sha256:113f78e7463a36dbbcea05bfe688efd7fa759d0f0c56e73c974d60dcfec3dfcc \ + --hash=sha256:169e0d178cb59314456ab30772429a802b25d13227088085b0d49b9fe1533104 \ + --hash=sha256:17fbb47f0885ace8327ce1235d0416dc86a211dcd8cc1e703f41523be32cfec8 \ + --hash=sha256:19bbd3b841174ae6ed588536ab5e1b1fe83d046e668602c20266547298d939a9 \ + --hash=sha256:1d9f9a3ce559a5267014b04b82956993270f63ec91765e13e9fd73daf2d2738e \ + --hash=sha256:1e4ecee40ba19e6975e1120829796770325841c2f153c0e9aecca927194c6a2a \ + --hash=sha256:22b0f9971ec4e07e8223f2beebe96a6cfc779d940b6f27d26604040dd74d3a44 \ + --hash=sha256:26fb5b9c3946bf7f1daed7b37e0c03898a6f062149127570f8ede346390a0825 \ + --hash=sha256:2778fed822d7db23ac5008b181441af0c869455b2e7d001f4019636ac31b6fe4 \ + --hash=sha256:28cfab66577000b9505a0d068c731aee7ca85cd26d4d63881fab17857e0fe1fb \ + --hash=sha256:29bc3973676ae334412efdd367fcd11d036b7be3efc1ce2407ef8676dabfeb82 \ + --hash=sha256:2bd9f19f7f1fcebd74e830f4af0f28adad4975d40d80620be19ffb2b2af56c9f \ + --hash=sha256:2d5d542bf2abd0fd0361e8017d03f7cb5786214ceb4a40eef1539d6585d93386 \ + --hash=sha256:30e4d2084df019880d55f6f7bea35328d9b464ebee090baa372c096dc77556fb \ + --hash=sha256:3619473a0e0d329fd4aec8075628f8f616be2da41605300696206d6f36920c3d \ + --hash=sha256:368625fb01666655985391dbad3860dc0ba7c0d6b9125819f3121ee7292b4ac8 \ + --hash=sha256:3737303ca9ea0f7cb83028781148fcda4f1dac7821db0c47672971dabcf63593 \ + --hash=sha256:3a9fed49c6ce4ed7e73f13182760c65c816da006debe67f37635580dfb0fae00 \ + --hash=sha256:3c38d142c706201db5b2345166eeef1e7740e3e2422b470b8ba5c8727a9b4c7a \ + --hash=sha256:3cb61db880ec11e984348227b333259994c2c85caa775eb7875decb3768db890 \ + --hash=sha256:3d74a03fb57757ece25aa4b3c1c60157a1cece37a020542785f942e2f827eed5 \ + --hash=sha256:3f796b535008708846044c43302719c6956f39ca2d93f2edda5319e79a29efbb \ + --hash=sha256:41105377f6282e8297f182e393a79cfffd521dde37ace52b106373bdcd9ca5cb \ + --hash=sha256:41aac7002a749f08727cb91babff1daf8deac317c0b1f317adc69be0e6c375d1 \ + --hash=sha256:44983e45310ee5b9f73397350251cdf6e63a466406a105f1d16cb5baa659270b \ + --hash=sha256:4cbbde66f1183db040daede83dd86c06d663c5bb2af6de1142b7c8c37923dd74 \ + --hash=sha256:4eda76074cfca2787c8cf1bec603eaebdddd8b061ad5502f85cddae998d54f00 \ + --hash=sha256:4fc6cd65dc4d2fdb2625e288939a3566e36127a84811a4913f02f3d5931da52d \ + --hash=sha256:50885073e2909251d4718634a191c49ae5f527e5e1736d738e365c3e8be8f22b \ + --hash=sha256:5174a697ce042fa77c407e05efe41e03aa56dae9ec67388055820fb48cf4c3ba \ + --hash=sha256:54b64fb2433bc71488e7a449603bf8bd31fbcf9cb56fbe1eb6d459e90b86c37b \ + --hash=sha256:54fe8518abe06a4c3852754bfd498b30cc58e667f376c513eac89a244ce781a4 \ + --hash=sha256:55dbbd8ffbc40d1697d5e2d0375b08599dae8746b0b08dea05eee4ce81648fac \ + --hash=sha256:57b52603e89355ff318025dd55158f6e71396c0f1f609d548e9ea9c94cc6ce0a \ + --hash=sha256:58370d05d033ee97224c81263af123dea3d931025030fd34b61227a768a8858a \ + --hash=sha256:5d87a3584093e1a89987e3d36d82c98d9621b2cb944e22a420aa1401e096758f \ + --hash=sha256:623f938f6a039536cc02b7582a07a080f13fdfd48f87e63201d92d7e34d09a18 \ + --hash=sha256:62815d2c67f2dd1be76a253d88af4e1da19aeaa1820146dec52cf8bee2958b16 \ + --hash=sha256:6290289fa5fb4c70fd7f72016e03633d60388185483ff3b162912c81205ae2cf \ + --hash=sha256:67e41a497bac88cc1de96eeba56eeb933c39d54bc227352f8455aa87c4ca4000 \ + --hash=sha256:6c85c38a279ca9295a69b9b088a2e48aa49737bb1b34e6a9dc6297c110e8d912 \ + --hash=sha256:6f01f044112d43a20be2f13a11683666d87151542ad627fe41a18b9791d2802f \ + --hash=sha256:707151644085dd0f20fe4f4b573d28e5130c4aaa5f587e95b60989c5926653b5 \ + --hash=sha256:723b2681ed4cc07d3401bbea9c201ad4f2a4ca6ba8cddaff6789f715dd2b391e \ + --hash=sha256:72d1cc63bcc91e14933f77d51b3df899d6a07d184ec515ea7f56bff659e124d7 \ + --hash=sha256:7374d6e3ef72afe49697ecd683f3da12f4fc06af2d75433d0580c6746d2fa025 \ + --hash=sha256:7501e9be34cb21e72fcfe672aafd0eee65c16ba2afa9dcb5500a587d3a0580f0 \ + --hash=sha256:76219cd1eefb9bf4af7856e3ae563d15158efa145c0aab01e9933051a1954045 \ + --hash=sha256:7aec798c2b01aaa65a55f1124f3405804184373abb318a3091325aece235f67c \ + --hash=sha256:7be6dfb49e48fd0a7d91ff758a2b51336f1cd21f9d44b20f6801f072bd080cdd \ + --hash=sha256:7e4e1f580033335c6f76d1e0d6b56baf009d1a64d6a4816347e4271ba951f46d \ + --hash=sha256:7e8ec5f606e0809426d2440e0683509fb605a8820a21ebd120dcdba61b74ef7f \ + --hash=sha256:7f196cd7910d71e9d9860da0ff7a77f64d22c1ad931f1dd18559a06e03109fc0 \ + --hash=sha256:82f3802bfc4751f420d591c5c864de538b71cea117fce67e4595c2afede08a15 \ + --hash=sha256:85ffc9920ffc39c5eee1e3ac9100c913a0973996fbad5111f939bbda49204bb7 \ + --hash=sha256:8e6c219e375f6341d0959af814296372d265a8ca1af63825f65e2e87c618f006 \ + --hash=sha256:8f767ba0911602ddef289404e33835a61168314ebd3c729833db2ed685824211 \ + --hash=sha256:8ff038d52ef6aa0f309feeba00c5095c9118d0abf787e8e8454d6048db2037fc \ + --hash=sha256:915e7a2418f10bd1151b1953df06d896db9783c9cfdb9a8ee1f9b3a4331ab503 \ + --hash=sha256:92883836caf50d5255be03d988d75bc93e3f86ba247b7ca137347c323f731deb \ + --hash=sha256:960b1b3efa39872ac8b6cc3a556edd6fb90ed74f08c9c45e028f1005b26aa55d \ + --hash=sha256:9aeaf53eaa075dd63e81512522fd180097312fb2c9f476333309184285c49ce0 \ + --hash=sha256:9d8089d853c7963a8ce87fff93e2a67075c0bc08684a08ea6ad13577c38ffc38 \ + --hash=sha256:a4130d0b9ce5fad6af07421b1aecc7e079519f70d6c05729ab871794eded8617 \ + --hash=sha256:a482ac121de6973897c92c2f31defc6bafb11c83825109275cffce54bb64933f \ + --hash=sha256:add7ac388d1e0bf57259afbcf9ed05621a3bf11ce5ee337e7536f1e1aaf056b0 \ + --hash=sha256:b1f12bd684887a0a5d55e6363ca87056f361e45451105012d329b86ec19dbe0b \ + --hash=sha256:b3f99e1756fc48ad507b95e5d86f2fb21b3d495012ff13e6592ebac14033f166 \ + --hash=sha256:b4cce60d0223074803c9dbe0721ad3fa51dafe7d462fee4b656a1aa01ee07518 \ + --hash=sha256:baeb47635cb33375dee4924cd93d7f5dcaa786c740b08423b0209b824a1ee728 \ + --hash=sha256:bbea5b775f0ac84945191fb83f845a6fd9a21a03ea7f2e187defac7e401616ad \ + --hash=sha256:bbfcb95d9a744e6e2827dfc66ad10e1020e0cac255eb7f85652832d5a264c2fc \ + --hash=sha256:bd6e7d363aa93bd3421b30b6af97064daf47bc96005bddba67c5ffbc6df426b8 \ + --hash=sha256:be77c402d5e882b6fbacfd90823f13da8e0a69658405a39a569c6b58fdb17b03 \ + --hash=sha256:c302245fd6c33d96bd169c7ccf2513c20f4c1e417c07ce9dce107c8bc3f8411f \ + --hash=sha256:c88653877aeb514c089d1b3d473451677b8b9a6d1497dbddf1ae7934518b06d2 \ + --hash=sha256:cae6383181f1e345317742d2ddd88f9e7d2682fa4c9432e3a74e47d92dce0229 \ + --hash=sha256:cd471ede0d802dd936b6fab28188302b2d497f68436025857ca72cd3810423fe \ + --hash=sha256:d106493a60dcb4aef35a0fac85105e150a11cf8bc2b0d388f5a33272d756c966 \ + --hash=sha256:d30b650595fdbe32366b94cb14f30bb2b625e512bd4e1df00611f99dc5c27fd4 \ + --hash=sha256:d51fde50a77f81330523562e3c2734ffdca9c4c9e9d355478117905e1cfe16c6 \ + --hash=sha256:d57dea657357230cc780e13920d7fa7db059d58fe721c80020f94476da4ca0a1 \ + --hash=sha256:d771f085fcdf4035786adfb1d8db026df1eb4b41dac1c3d070d1e49512843227 \ + --hash=sha256:dae0f0bd7d30c0ad61b9a504e8e272cb8391eed3f1587edf933f4f6b33437450 \ + --hash=sha256:db0562c5f71d18596dcd45e854cf2eeba27d7543e1a3acdafb7eef728f7fe85d \ + --hash=sha256:dfd51b4c56b673dfbc43d7d27ef857dd91124801e2806c69bb45585ce0fa019b \ + --hash=sha256:e080c0637aea036f35507e803a4778f119a9b436617694ae1c5c366805f1e997 \ + --hash=sha256:e48d4dbe0f88e53081da605ae68644e5182752803bbc2beb228cca7f1c4454d6 \ + --hash=sha256:e8b4b5580280b9265af3e0409974fb79c64cf7523632d03fbf11df18f8b0181e \ + --hash=sha256:e8b5378de2b139c3a830f0209c1e91f7705919a4b3e563a10955104f5097a70a \ + --hash=sha256:e904f2417f0d6f6d514f3f8b836416c360f306ddaee1f84de8eef1e722d212e5 \ + --hash=sha256:eee884572b06bbe8a2b54f424dbd996139442cf83c76478e1ec162512e0dd2c7 \ + --hash=sha256:f1fbb0a99125b1287c6d9747f937dc66621426836d1a2d50d05aecfc81911b57 \ + --hash=sha256:f40a95186a72fa0b67d15fef0f157bfcda00b4f59c8a07cbe5530d41ac35d105 \ + --hash=sha256:f6e0bfe77d238308839699944164b96a2eeccaf55f2af400f54dc20669d8d5f2 \ + --hash=sha256:f963eafc0a77a6c0562397da004f5876a9bcf7265a7bcc3205e29636bc4a1312 \ + --hash=sha256:fb9d44c25244e11c8be3f12c938ca8ba8404620ef8092245d2093c6ab3df260f \ + --hash=sha256:fc78739b5ec6e4fb02301984a3d442a91406e7700efbe305071e7fd1c78278f2 \ + --hash=sha256:fceef7fe67c81e1585198215e42ad3fdba3a25644beda8fbdaf85f4d7b93175a \ + --hash=sha256:fd96476f04db5ceba1cfa0f21228f67c1f7402296f0e73fee3513aa680ad237b # via feast (pyproject.toml) mock==2.0.0 \ --hash=sha256:5ce3c71c5545b472da17b72268978914d0252980348636840bd34a00b5cc96c1 \ @@ -2570,9 +2596,9 @@ mpmath==1.3.0 \ --hash=sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f \ --hash=sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c # via sympy -msal==1.34.0 \ - --hash=sha256:76ba83b716ea5a6d75b0279c0ac353a0e05b820ca1f6682c0eb7f45190c43c2f \ - --hash=sha256:f669b1644e4950115da7a176441b0e13ec2975c29528d8b9e81316023676d6e1 +msal==1.35.1 \ + --hash=sha256:70cac18ab80a053bff86219ba64cfe3da1f307c74b009e2da57ef040eb1b5656 \ + --hash=sha256:8f4e82f34b10c19e326ec69f44dc6b30171f2f7098f3720ea8a9f0c11832caa3 # via # azure-identity # msal-extensions @@ -2905,9 +2931,9 @@ nodeenv==1.10.0 \ --hash=sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827 \ --hash=sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb # via pre-commit -notebook==7.5.3 \ - --hash=sha256:393ceb269cf9fdb02a3be607a57d7bd5c2c14604f1818a17dbeb38e04f98cbfa \ - --hash=sha256:c997bfa1a2a9eb58c9bbb7e77d50428befb1033dd6f02c482922e96851d67354 +notebook==7.5.5 \ + --hash=sha256:a7c14dbeefa6592e87f72290ca982e0c10f5bbf3786be2a600fda9da2764a2b8 \ + --hash=sha256:dc0bfab0f2372c8278c457423d3256c34154ac2cc76bf20e9925260c461013c3 # via great-expectations notebook-shim==0.2.4 \ --hash=sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef \ @@ -2915,79 +2941,79 @@ notebook-shim==0.2.4 \ # via # jupyterlab # notebook -numpy==2.4.2 \ - --hash=sha256:00ab83c56211a1d7c07c25e3217ea6695e50a3e2f255053686b081dc0b091a82 \ - --hash=sha256:068cdb2d0d644cdb45670810894f6a0600797a69c05f1ac478e8d31670b8ee75 \ - --hash=sha256:0f01dcf33e73d80bd8dc0f20a71303abbafa26a19e23f6b68d1aa9990af90257 \ - --hash=sha256:0fece1d1f0a89c16b03442eae5c56dc0be0c7883b5d388e0c03f53019a4bfd71 \ - --hash=sha256:12e26134a0331d8dbd9351620f037ec470b7c75929cb8a1537f6bfe411152a1a \ - --hash=sha256:1ae241bbfc6ae276f94a170b14785e561cb5e7f626b6688cf076af4110887413 \ - --hash=sha256:1f92f53998a17265194018d1cc321b2e96e900ca52d54c7c77837b71b9465181 \ - --hash=sha256:209fae046e62d0ce6435fcfe3b1a10537e858249b3d9b05829e2a05218296a85 \ - --hash=sha256:20abd069b9cda45874498b245c8015b18ace6de8546bf50dfa8cea1696ed06ef \ - --hash=sha256:21982668592194c609de53ba4933a7471880ccbaadcc52352694a59ecc860b3a \ - --hash=sha256:25f2059807faea4b077a2b6837391b5d830864b3543627f381821c646f31a63c \ - --hash=sha256:2653de5c24910e49c2b106499803124dde62a5a1fe0eedeaecf4309a5f639390 \ - --hash=sha256:2b8f157c8a6f20eb657e240f8985cc135598b2b46985c5bccbde7616dc9c6b1e \ - --hash=sha256:2fb882da679409066b4603579619341c6d6898fc83a8995199d5249f986e8e8f \ - --hash=sha256:40397bda92382fcec844066efb11f13e1c9a3e2a8e8f318fb72ed8b6db9f60f1 \ - --hash=sha256:444be170853f1f9d528428eceb55f12918e4fda5d8805480f36a002f1415e09b \ - --hash=sha256:47c5a6ed21d9452b10227e5e8a0e1c22979811cad7dcc19d8e3e2fb8fa03f1a3 \ - --hash=sha256:4f069069931240b3fc703f1e23df63443dbd6390614c8c44a87d96cd0ec81eb1 \ - --hash=sha256:52b913ec40ff7ae845687b0b34d8d93b60cb66dcee06996dd5c99f2fc9328657 \ - --hash=sha256:5633c0da313330fd20c484c78cdd3f9b175b55e1a766c4a174230c6b70ad8262 \ - --hash=sha256:5daf6f3914a733336dab21a05cdec343144600e964d2fcdabaac0c0269874b2a \ - --hash=sha256:5eea80d908b2c1f91486eb95b3fb6fab187e569ec9752ab7d9333d2e66bf2d6b \ - --hash=sha256:602f65afdef699cda27ec0b9224ae5dc43e328f4c24c689deaf77133dbee74d0 \ - --hash=sha256:659a6107e31a83c4e33f763942275fd278b21d095094044eb35569e86a21ddae \ - --hash=sha256:66cb9422236317f9d44b67b4d18f44efe6e9c7f8794ac0462978513359461554 \ - --hash=sha256:6d82351358ffbcdcd7b686b90742a9b86632d6c1c051016484fa0b326a0a1548 \ - --hash=sha256:6e9f61981ace1360e42737e2bae58b27bf28a1b27e781721047d84bd754d32e7 \ - --hash=sha256:6ed0be1ee58eef41231a5c943d7d1375f093142702d5723ca2eb07db9b934b05 \ - --hash=sha256:7cdde6de52fb6664b00b056341265441192d1291c130e99183ec0d4b110ff8b1 \ - --hash=sha256:7df2de1e4fba69a51c06c28f5a3de36731eb9639feb8e1cf7e4a7b0daf4cf622 \ - --hash=sha256:7edc794af8b36ca37ef5fcb5e0d128c7e0595c7b96a2318d1badb6fcd8ee86b1 \ - --hash=sha256:7f54844851cdb630ceb623dcec4db3240d1ac13d4990532446761baede94996a \ - --hash=sha256:805cc8de9fd6e7a22da5aed858e0ab16be5a4db6c873dde1d7451c541553aa27 \ - --hash=sha256:8906e71fd8afcb76580404e2a950caef2685df3d2a57fe82a86ac8d33cc007ba \ - --hash=sha256:89f7268c009bc492f506abd6f5265defa7cb3f7487dc21d357c3d290add45082 \ - --hash=sha256:8c50dd1fc8826f5b26a5ee4d77ca55d88a895f4e4819c7ecc2a9f5905047a443 \ - --hash=sha256:8e4549f8a3c6d13d55041925e912bfd834285ef1dd64d6bc7d542583355e2e98 \ - --hash=sha256:8e9afaeb0beff068b4d9cd20d322ba0ee1cecfb0b08db145e4ab4dd44a6b5110 \ - --hash=sha256:98f16a80e917003a12c0580f97b5f875853ebc33e2eaa4bccfc8201ac6869308 \ - --hash=sha256:9e35d3e0144137d9fdae62912e869136164534d64a169f86438bc9561b6ad49f \ - --hash=sha256:9e4424677ce4b47fe73c8b5556d876571f7c6945d264201180db2dc34f676ab5 \ - --hash=sha256:adb6ed2ad29b9e15321d167d152ee909ec73395901b70936f029c3bc6d7f4460 \ - --hash=sha256:aea4f66ff44dfddf8c2cffd66ba6538c5ec67d389285292fe428cb2c738c8aef \ - --hash=sha256:b21041e8cb6a1eb5312dd1d2f80a94d91efffb7a06b70597d44f1bd2dfc315ab \ - --hash=sha256:b2f0073ed0868db1dcd86e052d37279eef185b9c8db5bf61f30f46adac63c909 \ - --hash=sha256:b3a24467af63c67829bfaa61eecf18d5432d4f11992688537be59ecd6ad32f5e \ - --hash=sha256:b9c618d56a29c9cb1c4da979e9899be7578d2e0b3c24d52079c166324c9e8695 \ - --hash=sha256:bba37bc29d4d85761deed3954a1bc62be7cf462b9510b51d367b769a8c8df325 \ - --hash=sha256:bd3a7a9f5847d2fb8c2c6d1c862fa109c31a9abeca1a3c2bd5a64572955b2979 \ - --hash=sha256:be71bf1edb48ebbbf7f6337b5bfd2f895d1902f6335a5830b20141fc126ffba0 \ - --hash=sha256:c02ef4401a506fb60b411467ad501e1429a3487abca4664871d9ae0b46c8ba32 \ - --hash=sha256:c3cd545784805de05aafe1dde61752ea49a359ccba9760c1e5d1c88a93bbf2b7 \ - --hash=sha256:c7ac672d699bf36275c035e16b65539931347d68b70667d28984c9fb34e07fa7 \ - --hash=sha256:cb7bbb88aa74908950d979eeaa24dbdf1a865e3c7e45ff0121d8f70387b55f73 \ - --hash=sha256:cd2bd2bbed13e213d6b55dc1d035a4f91748a7d3edc9480c13898b0353708920 \ - --hash=sha256:cda077c2e5b780200b6b3e09d0b42205a3d1c68f30c6dceb90401c13bff8fe74 \ - --hash=sha256:cf28c0c1d4c4bf00f509fa7eb02c58d7caf221b50b467bcb0d9bbf1584d5c821 \ - --hash=sha256:d0d9b7c93578baafcbc5f0b83eaf17b79d345c6f36917ba0c67f45226911d499 \ - --hash=sha256:d1240d50adff70c2a88217698ca844723068533f3f5c5fa6ee2e3220e3bdb000 \ - --hash=sha256:d30291931c915b2ab5717c2974bb95ee891a1cf22ebc16a8006bd59cd210d40a \ - --hash=sha256:d9f64d786b3b1dd742c946c42d15b07497ed14af1a1f3ce840cce27daa0ce913 \ - --hash=sha256:da6cad4e82cb893db4b69105c604d805e0c3ce11501a55b5e9f9083b47d2ffe8 \ - --hash=sha256:df1b10187212b198dd45fa943d8985a3c8cf854aed4923796e0e019e113a1bda \ - --hash=sha256:e04ae107ac591763a47398bb45b568fc38f02dbc4aa44c063f67a131f99346cb \ - --hash=sha256:e6dee3bb76aa4009d5a912180bf5b2de012532998d094acee25d9cb8dee3e44a \ - --hash=sha256:e7e88598032542bd49af7c4747541422884219056c268823ef6e5e89851c8825 \ - --hash=sha256:e98c97502435b53741540a5717a6749ac2ada901056c7db951d33e11c885cc7d \ - --hash=sha256:ec055f6dae239a6299cace477b479cca2fc125c5675482daf1dd886933a1076f \ - --hash=sha256:f74f0f7779cc7ae07d1810aab8ac6b1464c3eafb9e283a40da7309d5e6e48fbb \ - --hash=sha256:fbde1b0c6e81d56f5dccd95dd4a711d9b95df1ae4009a60887e56b27e8d903fa \ - --hash=sha256:fcf92bee92742edd401ba41135185866f7026c502617f422eb432cfeca4fe236 \ - --hash=sha256:fd49860271d52127d61197bb50b64f58454e9f578cb4b2c001a6de8b1f50b0b1 +numpy==2.4.4 \ + --hash=sha256:07077278157d02f65c43b1b26a3886bce886f95d20aabd11f87932750dfb14ed \ + --hash=sha256:08f2e31ed5e6f04b118e49821397f12767934cfdd12a1ce86a058f91e004ee50 \ + --hash=sha256:0aec54fd785890ecca25a6003fd9a5aed47ad607bbac5cd64f836ad8666f4959 \ + --hash=sha256:0d35aea54ad1d420c812bfa0385c71cd7cc5bcf7c65fed95fc2cd02fe8c79827 \ + --hash=sha256:0d4e437e295f18ec29bc79daf55e8a47a9113df44d66f702f02a293d93a2d6dd \ + --hash=sha256:0dfd3f9d3adbe2920b68b5cd3d51444e13a10792ec7154cd0a2f6e74d4ab3233 \ + --hash=sha256:1378871da56ca8943c2ba674530924bb8ca40cd228358a3b5f302ad60cf875fc \ + --hash=sha256:15716cfef24d3a9762e3acdf87e27f58dc823d1348f765bbea6bef8c639bfa1b \ + --hash=sha256:19710a9ca9992d7174e9c52f643d4272dcd1558c5f7af7f6f8190f633bd651a7 \ + --hash=sha256:23cbfd4c17357c81021f21540da84ee282b9c8fba38a03b7b9d09ba6b951421e \ + --hash=sha256:2483e4584a1cb3092da4470b38866634bafb223cbcd551ee047633fd2584599a \ + --hash=sha256:27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d \ + --hash=sha256:28a650663f7314afc3e6ec620f44f333c386aad9f6fc472030865dc0ebb26ee3 \ + --hash=sha256:2aa0613a5177c264ff5921051a5719d20095ea586ca88cc802c5c218d1c67d3e \ + --hash=sha256:2c194dd721e54ecad9ad387c1d35e63dce5c4450c6dc7dd5611283dda239aabb \ + --hash=sha256:2d19e6e2095506d1736b7d80595e0f252d76b89f5e715c35e06e937679ea7d7a \ + --hash=sha256:2d390634c5182175533585cc89f3608a4682ccb173cc9bb940b2881c8d6f8fa0 \ + --hash=sha256:30caa73029a225b2d40d9fae193e008e24b2026b7ee1a867b7ee8d96ca1a448e \ + --hash=sha256:42c16925aa5a02362f986765f9ebabf20de75cdefdca827d14315c568dcab113 \ + --hash=sha256:45dbed2ab436a9e826e302fcdcbe9133f9b0006e5af7168afb8963a6520da103 \ + --hash=sha256:4636de7fd195197b7535f231b5de9e4b36d2c440b6e566d2e4e4746e6af0ca93 \ + --hash=sha256:4a19d9dba1a76618dd86b164d608566f393f8ec6ac7c44f0cc879011c45e65af \ + --hash=sha256:4bbc7f303d125971f60ec0aaad5e12c62d0d2c925f0ab1273debd0e4ba37aba5 \ + --hash=sha256:4d6d57903571f86180eb98f8f0c839fa9ebbfb031356d87f1361be91e433f5b7 \ + --hash=sha256:4e874c976154687c1f71715b034739b45c7711bec81db01914770373d125e392 \ + --hash=sha256:51fc224f7ca4d92656d5a5eb315f12eb5fe2c97a66249aa7b5f562528a3be38c \ + --hash=sha256:58c8b5929fcb8287cbd6f0a3fae19c6e03a5c48402ae792962ac465224a629a4 \ + --hash=sha256:5a285b3b96f951841799528cd1f4f01cd70e7e0204b4abebac9463eecfcf2a40 \ + --hash=sha256:5c70f1cc1c4efbe316a572e2d8b9b9cc44e89b95f79ca3331553fbb63716e2bf \ + --hash=sha256:62d6b0f03b694173f9fcb1fb317f7222fd0b0b103e784c6549f5e53a27718c44 \ + --hash=sha256:6a246d5914aa1c820c9443ddcee9c02bec3e203b0c080349533fae17727dfd1b \ + --hash=sha256:6aa3236c78803afbcb255045fbef97a9e25a1f6c9888357d205ddc42f4d6eba5 \ + --hash=sha256:6bbe4eb67390b0a0265a2c25458f6b90a409d5d069f1041e6aff1e27e3d9a79e \ + --hash=sha256:715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74 \ + --hash=sha256:72944b19f2324114e9dc86a159787333b77874143efcf89a5167ef83cfee8af0 \ + --hash=sha256:81f4a14bee47aec54f883e0cad2d73986640c1590eb9bfaaba7ad17394481e6e \ + --hash=sha256:846300f379b5b12cc769334464656bc882e0735d27d9726568bc932fdc49d5ec \ + --hash=sha256:86b6f55f5a352b48d7fbfd2dbc3d5b780b2d79f4d3c121f33eb6efb22e9a2015 \ + --hash=sha256:874f200b2a981c647340f841730fc3a2b54c9d940566a3c4149099591e2c4c3d \ + --hash=sha256:8a87ec22c87be071b6bdbd27920b129b94f2fc964358ce38f3822635a3e2e03d \ + --hash=sha256:8b3b60bb7cba2c8c81837661c488637eee696f59a877788a396d33150c35d842 \ + --hash=sha256:8e3ed142f2728df44263aaf5fb1f5b0b99f4070c553a0d7f033be65338329150 \ + --hash=sha256:93e15038125dc1e5345d9b5b68aa7f996ec33b98118d18c6ca0d0b7d6198b7e8 \ + --hash=sha256:989824e9faf85f96ec9c7761cd8d29c531ad857bfa1daa930cba85baaecf1a9a \ + --hash=sha256:99d838547ace2c4aace6c4f76e879ddfe02bb58a80c1549928477862b7a6d6ed \ + --hash=sha256:9b2aec6af35c113b05695ebb5749a787acd63cafc83086a05771d1e1cd1e555f \ + --hash=sha256:9c585a1790d5436a5374bac930dad6ed244c046ed91b2b2a3634eb2971d21008 \ + --hash=sha256:a7164afb23be6e37ad90b2f10426149fd75aee07ca55653d2aa41e66c4ef697e \ + --hash=sha256:ac6b31e35612a26483e20750126d30d0941f949426974cace8e6b5c58a3657b0 \ + --hash=sha256:ad2e2ef14e0b04e544ea2fa0a36463f847f113d314aa02e5b402fdf910ef309e \ + --hash=sha256:b268594bccac7d7cf5844c7732e3f20c50921d94e36d7ec9b79e9857694b1b2f \ + --hash=sha256:b5f0362dc928a6ecd9db58868fca5e48485205e3855957bdedea308f8672ea4a \ + --hash=sha256:ba1f4fc670ed79f876f70082eff4f9583c15fb9a4b89d6188412de4d18ae2f40 \ + --hash=sha256:ba203255017337d39f89bdd58417f03c4426f12beed0440cfd933cb15f8669c7 \ + --hash=sha256:c901b15172510173f5cb310eae652908340f8dede90fff9e3bf6c0d8dfd92f83 \ + --hash=sha256:c9b39d38a9bd2ae1becd7eac1303d031c5c110ad31f2b319c6e7d98b135c934d \ + --hash=sha256:d2a8490669bfe99a233298348acc2d824d496dee0e66e31b66a6022c2ad74a5c \ + --hash=sha256:dddbbd259598d7240b18c9d87c56a9d2fb3b02fe266f49a7c101532e78c1d871 \ + --hash=sha256:df3775294accfdd75f32c74ae39fcba920c9a378a2fc18a12b6820aa8c1fb502 \ + --hash=sha256:e44319a2953c738205bf3354537979eaa3998ed673395b964c1176083dd46252 \ + --hash=sha256:e4a010c27ff6f210ff4c6ef34394cd61470d01014439b192ec22552ee867f2a8 \ + --hash=sha256:e823b8b6edc81e747526f70f71a9c0a07ac4e7ad13020aa736bb7c9d67196115 \ + --hash=sha256:e892aff75639bbef0d2a2cfd55535510df26ff92f63c92cd84ef8d4ba5a5557f \ + --hash=sha256:eea7ac5d2dce4189771cedb559c738a71512768210dc4e4753b107a2048b3d0e \ + --hash=sha256:ef4059d6e5152fa1a39f888e344c73fdc926e1b2dd58c771d67b0acfbf2aa67d \ + --hash=sha256:f169b9a863d34f5d11b8698ead99febeaa17a13ca044961aa8e2662a6c7766a0 \ + --hash=sha256:f2cf083b324a467e1ab358c105f6cad5ea950f50524668a80c486ff1db24e119 \ + --hash=sha256:f8474c4241bc18b750be2abea9d7a9ec84f46ef861dbacf86a4f6e043401f79e \ + --hash=sha256:f983334aea213c99992053ede6168500e5f086ce74fbc4acc3f2b00f5762e9db \ + --hash=sha256:f9e75681b59ddaa5e659898085ae0eaea229d054f2ac0c7e563a62205a700121 \ + --hash=sha256:fbc356aae7adf9e6336d336b9c8111d390a05df88f1805573ebb0807bd06fd1d \ + --hash=sha256:fcfe2045fd2e8f3cb0ce9d4ba6dba6333b8fa05bb8a4939c908cd43322d14c7e # via # feast (pyproject.toml) # accelerate @@ -3010,6 +3036,7 @@ numpy==2.4.2 \ # scikit-image # scikit-learn # scipy + # sentence-transformers # shapely # tifffile # torchvision @@ -3036,8 +3063,8 @@ opencv-python-headless==4.13.0.92 \ --hash=sha256:a7cf08e5b191f4ebb530791acc0825a7986e0d0dee2a3c491184bd8599848a4b \ --hash=sha256:eb60e36b237b1ebd40a912da5384b348df8ed534f6f644d8e0b4f103e272ba7d # via easyocr -openlineage-python==1.43.0 \ - --hash=sha256:595dc641f696d0a1c021440a9ff8155f4e2776452cf118112a09b12cf4038827 +openlineage-python==1.45.0 \ + --hash=sha256:cf66e7d517d3c8b510b39ad646d8fd0ca2f0cc92d7d6d601d93b2a859783f380 # via feast (pyproject.toml) openpyxl==3.1.5 \ --hash=sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2 \ @@ -3047,106 +3074,139 @@ openshift-client==1.0.18 \ --hash=sha256:be3979440cfd96788146a3a1650dabe939d4d516eea0b39f87e66d2ab39495b1 \ --hash=sha256:d8a84080307ccd9556f6c62a3707a3e6507baedee36fa425754f67db9ded528b # via codeflare-sdk -opentelemetry-api==1.39.1 \ - --hash=sha256:2edd8463432a7f8443edce90972169b195e7d6a05500cd29e6d13898187c9950 \ - --hash=sha256:fbde8c80e1b937a2c61f20347e91c0c18a1940cecf012d62e65a7caf08967c9c +opentelemetry-api==1.40.0 \ + --hash=sha256:159be641c0b04d11e9ecd576906462773eb97ae1b657730f0ecf64d32071569f \ + --hash=sha256:82dd69331ae74b06f6a874704be0cfaa49a1650e1537d4a813b86ecef7d0ecf9 # via # opentelemetry-exporter-prometheus # opentelemetry-sdk # opentelemetry-semantic-conventions -opentelemetry-exporter-prometheus==0.60b1 \ - --hash=sha256:49f59178de4f4590e3cef0b8b95cf6e071aae70e1f060566df5546fad773b8fd \ - --hash=sha256:a4011b46906323f71724649d301b4dc188aaa068852e814f4df38cc76eac616b +opentelemetry-exporter-prometheus==0.61b0 \ + --hash=sha256:3013b41f4370143d48d219a2351473761423e5882fa4c213811eaefacba39cb7 \ + --hash=sha256:7c4919bd8e79abd62b610767e80f42c9c3a06c5183f4dd9141eedeb57aea284b # via ray opentelemetry-proto==1.27.0 \ --hash=sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6 \ --hash=sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace # via ray -opentelemetry-sdk==1.39.1 \ - --hash=sha256:4d5482c478513ecb0a5d938dcc61394e647066e0cc2676bee9f3af3f3f45f01c \ - --hash=sha256:cf4d4563caf7bff906c9f7967e2be22d0d6b349b908be0d90fb21c8e9c995cc6 +opentelemetry-sdk==1.40.0 \ + --hash=sha256:18e9f5ec20d859d268c7cb3c5198c8d105d073714db3de50b593b8c1345a48f2 \ + --hash=sha256:787d2154a71f4b3d81f20524a8ce061b7db667d24e46753f32a7bc48f1c1f3f1 # via # opentelemetry-exporter-prometheus # ray -opentelemetry-semantic-conventions==0.60b1 \ - --hash=sha256:87c228b5a0669b748c76d76df6c364c369c28f1c465e50f661e39737e84bc953 \ - --hash=sha256:9fa8c8b0c110da289809292b0591220d3a7b53c1526a23021e977d68597893fb +opentelemetry-semantic-conventions==0.61b0 \ + --hash=sha256:072f65473c5d7c6dc0355b27d6c9d1a679d63b6d4b4b16a9773062cb7e31192a \ + --hash=sha256:fa530a96be229795f8cef353739b618148b0fe2b4b3f005e60e262926c4d38e2 # via opentelemetry-sdk -orjson==3.11.7 \ - --hash=sha256:043d3006b7d32c7e233b8cfb1f01c651013ea079e08dcef7189a29abd8befe11 \ - --hash=sha256:0527a4510c300e3b406591b0ba69b5dc50031895b0a93743526a3fc45f59d26e \ - --hash=sha256:0724e265bc548af1dedebd9cb3d24b4e1c1e685a343be43e87ba922a5c5fff2f \ - --hash=sha256:136dcd6a2e796dfd9ffca9fc027d778567b0b7c9968d092842d3c323cef88aa8 \ - --hash=sha256:14f440c7268c8f8633d1b3d443a434bd70cb15686117ea6beff8fdc8f5917a1e \ - --hash=sha256:1d98b30cc1313d52d4af17d9c3d307b08389752ec5f2e5febdfada70b0f8c733 \ - --hash=sha256:1eb80451a9c351a71dfaf5b7ccc13ad065405217726b59fdbeadbcc544f9d223 \ - --hash=sha256:1ee5cc7160a821dfe14f130bc8e63e7611051f964b463d9e2a3a573204446a4d \ - --hash=sha256:23d6c20517a97a9daf1d48b580fcdc6f0516c6f4b5038823426033690b4d2650 \ - --hash=sha256:26c3b9132f783b7d7903bf1efb095fed8d4a3a85ec0d334ee8beff3d7a4749d5 \ - --hash=sha256:31c80ce534ac4ea3739c5ee751270646cbc46e45aea7576a38ffec040b4029a1 \ - --hash=sha256:3726be79e36e526e3d9c1aceaadbfb4a04ee80a72ab47b3f3c17fefb9812e7b8 \ - --hash=sha256:390a1dce0c055ddf8adb6aa94a73b45a4a7d7177b5c584b8d1c1947f2ba60fb3 \ - --hash=sha256:3a2479753bbb95b0ebcf7969f562cdb9668e6d12416a35b0dda79febf89cdea2 \ - --hash=sha256:3c4bc6c6ac52cdaa267552544c73e486fecbd710b7ac09bc024d5a78555a22f6 \ - --hash=sha256:411ebaf34d735e25e358a6d9e7978954a9c9d58cfb47bc6683cdc3964cd2f910 \ - --hash=sha256:4682d1db3bcebd2b64757e0ddf9e87ae5f00d29d16c5cdf3a62f561d08cc3dd2 \ - --hash=sha256:4a2e9c5be347b937a2e0203866f12bba36082e89b402ddb9e927d5822e43088d \ - --hash=sha256:57036b27ac8a25d81112eb0cc9835cd4833c5b16e1467816adc0015f59e870dc \ - --hash=sha256:5ede977b5fe5ac91b1dffc0a517ca4542d2ec8a6a4ff7b2652d94f640796342a \ - --hash=sha256:5fdfad2093bdd08245f2e204d977facd5f871c88c4a71230d5bcbd0e43bf6222 \ - --hash=sha256:623ad1b9548ef63886319c16fa317848e465a21513b31a6ad7b57443c3e0dcf5 \ - --hash=sha256:652c6c3af76716f4a9c290371ba2e390ede06f6603edb277b481daf37f6f464e \ - --hash=sha256:6543001328aa857187f905308a028935864aefe9968af3848401b6fe80dbb471 \ - --hash=sha256:6e776b998ac37c0396093d10290e60283f59cfe0fc3fccbd0ccc4bd04dd19892 \ - --hash=sha256:71924496986275a737f38e3f22b4e0878882b3f7a310d2ff4dc96e812789120c \ - --hash=sha256:733ae23ada68b804b222c44affed76b39e30806d38660bf1eb200520d259cc16 \ - --hash=sha256:7477aa6a6ec6139c5cb1cc7b214643592169a5494d200397c7fc95d740d5fcf3 \ - --hash=sha256:79cacb0b52f6004caf92405a7e1f11e6e2de8bdf9019e4f76b44ba045125cd6b \ - --hash=sha256:7ba61079379b0ae29e117db13bda5f28d939766e410d321ec1624afc6a0b0504 \ - --hash=sha256:800988273a014a0541483dc81021247d7eacb0c845a9d1a34a422bc718f41539 \ - --hash=sha256:814be4b49b228cfc0b3c565acf642dd7d13538f966e3ccde61f4f55be3e20785 \ - --hash=sha256:845c3e0d8ded9c9271cd79596b9b552448b885b97110f628fb687aee2eed11c1 \ - --hash=sha256:849e38203e5be40b776ed2718e587faf204d184fc9a008ae441f9442320c0cab \ - --hash=sha256:89e13dd3f89f1c38a9c9eba5fbf7cdc2d1feca82f5f290864b4b7a6aac704576 \ - --hash=sha256:89e440ebc74ce8ab5c7bc4ce6757b4a6b1041becb127df818f6997b5c71aa60b \ - --hash=sha256:8ff206156006da5b847c9304b6308a01e8cdbc8cce824e2779a5ba71c3def141 \ - --hash=sha256:91c81ef070c8f3220054115e1ef468b1c9ce8497b4e526cb9f68ab4dc0a7ac62 \ - --hash=sha256:9487abc2c2086e7c8eb9a211d2ce8855bae0e92586279d0d27b341d5ad76c85c \ - --hash=sha256:962d046ee1765f74a1da723f4b33e3b228fe3a48bd307acce5021dfefe0e29b2 \ - --hash=sha256:996b65230271f1a97026fd0e6a753f51fbc0c335d2ad0c6201f711b0da32693b \ - --hash=sha256:9b1a67243945819ce55d24a30b59d6a168e86220452d2c96f4d1f093e71c0c49 \ - --hash=sha256:9c0b51672e466fd7e56230ffbae7f1639e18d0ce023351fb75da21b71bc2c960 \ - --hash=sha256:9e54f3808e2b6b945078c41aa8d9b5834b28c50843846e97807e5adb75fa9705 \ - --hash=sha256:a02c833f38f36546ba65a452127633afce4cf0dd7296b753d3bb54e55e5c0174 \ - --hash=sha256:a12b80df61aab7b98b490fe9e4879925ba666fccdfcd175252ce4d9035865ace \ - --hash=sha256:a16bcd08ab0bcdfc7e8801d9c4a9cc17e58418e4d48ddc6ded4e9e4b1a94062b \ - --hash=sha256:a56df3239294ea5964adf074c54bcc4f0ccd21636049a2cf3ca9cf03b5d03cf1 \ - --hash=sha256:a709e881723c9b18acddcfb8ba357322491ad553e277cf467e1e7e20e2d90561 \ - --hash=sha256:ab49d4b2a6a1d415ddb9f37a21e02e0d5dbfe10b7870b21bf779fc21e9156157 \ - --hash=sha256:ae9e0b37a834cef7ce8f99de6498f8fad4a2c0bf6bfc3d02abd8ed56aa15b2de \ - --hash=sha256:b4a9eefdc70bf8bf9857f0290f973dec534ac84c35cd6a7f4083be43e7170a8f \ - --hash=sha256:b63c6e6738d7c3470ad01601e23376aa511e50e1f3931395b9f9c722406d1a67 \ - --hash=sha256:b7b1dae39230a393df353827c855a5f176271c23434cfd2db74e0e424e693e10 \ - --hash=sha256:b8d14b71c0b12963fe8a62aac87119f1afdf4cb88a400f61ca5ae581449efcb5 \ - --hash=sha256:b9f95dcdea9d4f805daa9ddf02617a89e484c6985fa03055459f90e87d7a0757 \ - --hash=sha256:b9fc4d0f81f394689e0814617aadc4f2ea0e8025f38c226cbf22d3b5ddbf025d \ - --hash=sha256:bd03ea7606833655048dab1a00734a2875e3e86c276e1d772b2a02556f0d895f \ - --hash=sha256:bd0d68edd7dfca1b2eca9361a44ac9f24b078de3481003159929a0573f21a6bf \ - --hash=sha256:bda117c4148e81f746655d5a3239ae9bd00cb7bc3ca178b5fc5a5997e9744183 \ - --hash=sha256:bf742e149121dc5648ba0a08ea0871e87b660467ef168a3a5e53bc1fbd64bb74 \ - --hash=sha256:c2428d358d85e8da9d37cba18b8c4047c55222007a84f97156a5b22028dfbfc0 \ - --hash=sha256:c2e85fe4698b6a56d5e2ebf7ae87544d668eb6bde1ad1226c13f44663f20ec9e \ - --hash=sha256:c43b8b5bab288b6b90dac410cca7e986a4fa747a2e8f94615aea407da706980d \ - --hash=sha256:cededd6738e1c153530793998e31c05086582b08315db48ab66649768f326baa \ - --hash=sha256:d06e5c5fed5caedd2e540d62e5b1c25e8c82431b9e577c33537e5fa4aa909539 \ - --hash=sha256:d772afdb22555f0c58cfc741bdae44180122b3616faa1ecadb595cd526e4c993 \ - --hash=sha256:d897e81f8d0cbd2abb82226d1860ad2e1ab3ff16d7b08c96ca00df9d45409ef4 \ - --hash=sha256:de0a37f21d0d364954ad5de1970491d7fbd0fb1ef7417d4d56a36dc01ba0c0a0 \ - --hash=sha256:e7745312efa9e11c17fbd3cb3097262d079da26930ae9ae7ba28fb738367cbad \ - --hash=sha256:ed46f17096e28fb28d2975834836a639af7278aa87c84f68ab08fbe5b8bd75fa \ - --hash=sha256:f4f7c956b5215d949a1f65334cf9d7612dde38f20a95f2315deef167def91a6f \ - --hash=sha256:f50979824bde13d32b4320eedd513431c921102796d86be3eee0b58e58a3ecd1 \ - --hash=sha256:f904c24bdeabd4298f7a977ef14ca2a022ca921ed670b92ecd16ab6f3d01f867 +oracledb==3.4.2 \ + --hash=sha256:00c79448017f367bb7ab6900efe0706658a53768abea2b4519a4c9b2d5743890 \ + --hash=sha256:0e16fe3d057e0c41a23ad2ae95bfa002401690773376d476be608f79ac74bf05 \ + --hash=sha256:0f04a2d62073407672f114d02529921de0677c6883ed7c64d8d1a3c04caa3238 \ + --hash=sha256:1617a1db020346883455af005efbefd51be2c4d797e43b1b38455a19f8526b48 \ + --hash=sha256:19fa80ef84f85ad74077aa626067bbe697e527bd39604b4209f9d86cb2876b89 \ + --hash=sha256:1e4930d7f6584832dcc15b8ca415a7957b0c45f5aa7c4f88702e070e5c53bf93 \ + --hash=sha256:23aa07c1eaca17ae74c6fdc86b218f58484d56452958aead1aa460c0596a76c1 \ + --hash=sha256:31b7ee83c23d0439778303de8a675717f805f7e8edb5556d48c4d8343bcf14f5 \ + --hash=sha256:3df8eee1410d25360599968b1625b000f10c5ae0e47274031a7842a9dc418890 \ + --hash=sha256:404ec1451d0448653ee074213b87d6c5bd65eaa74b50083ddf2c9c3e11c71c71 \ + --hash=sha256:46e0f2278ff1fe83fbc33a3b93c72d429323ec7eed47bc9484e217776cd437e5 \ + --hash=sha256:55397e7eb43bb7017c03a981c736c25724182f5210951181dfe3fab0e5d457fb \ + --hash=sha256:574c8280d49cbbe21dbe03fc28356d9b9a5b9e300ebcde6c6d106e51453a7e65 \ + --hash=sha256:59ad6438f56a25e8e1a4a3dd1b42235a5d09ab9ba417ff2ad14eae6596f3d06f \ + --hash=sha256:5d7befb014174c5ae11c3a08f5ed6668a25ab2335d8e7104dca70d54d54a5b3a \ + --hash=sha256:5ed78d7e7079a778062744ccf42141ce4806818c3f4dd6463e4a7edd561c9f86 \ + --hash=sha256:643c25d301a289a371e37fcedb59e5fa5e54fb321708e5c12821c4b55bdd8a4d \ + --hash=sha256:6d85622664cc88d5a82bbd7beccb62cd53bd272c550a5e15e7d5f8ae6b86f1f1 \ + --hash=sha256:9f434a739405557bd57cb39b62238142bb27855a524a70dc6d397a2a8c576c9d \ + --hash=sha256:a7396664e592881225ba66385ee83ce339d864f39003d6e4ca31a894a7e7c552 \ + --hash=sha256:ac25a0448fc830fb7029ad50cd136cdbfcd06975d53967e269772cc5cb8c203a \ + --hash=sha256:b1095d95d0c8b37e4d0e17cf1928919cb59222b6344362a1cf6a2f3ca205a28a \ + --hash=sha256:b26a10f9c790bd141ffc8af68520803ed4a44a9258bf7d1eea9bfdd36bd6df7f \ + --hash=sha256:b8e4b8a852251cef09038b75f30fce1227010835f4e19cfbd436027acba2697c \ + --hash=sha256:b974caec2c330c22bbe765705a5ac7d98ec3022811dec2042d561a3c65cb991b \ + --hash=sha256:d7ce75c498bff758548ec6e4424ab4271aa257e5887cc436a54bc947fd46199a \ + --hash=sha256:d8d75e4f879b908be66cce05ba6c05791a5dbb4a15e39abc01aa25c8a2492bd9 \ + --hash=sha256:e068ef844a327877bfefbef1bc6fb7284c727bb87af80095f08d95bcaf7b8bb2 \ + --hash=sha256:f8ea989965a4f636a309444bd696ab877bba373d5d67bf744785f9bd8c560865 \ + --hash=sha256:f93cae08e8ed20f2d5b777a8602a71f9418389c661d2c937e84d94863e7e7011 \ + --hash=sha256:ff3c89cecea62af8ca02aa33cab0f2edc0214c747eac7d3364ed6b2640cb55e4 + # via ibis-framework +orjson==3.11.8 \ + --hash=sha256:0022bb50f90da04b009ce32c512dc1885910daa7cb10b7b0cba4505b16db82a8 \ + --hash=sha256:003646067cc48b7fcab2ae0c562491c9b5d2cbd43f1e5f16d98fd118c5522d34 \ + --hash=sha256:01928d0476b216ad2201823b0a74000440360cef4fed1912d297b8d84718f277 \ + --hash=sha256:01c4e5a6695dc09098f2e6468a251bc4671c50922d4d745aff1a0a33a0cf5b8d \ + --hash=sha256:093d489fa039ddade2db541097dbb484999fcc65fc2b0ff9819141e2ab364f25 \ + --hash=sha256:0b57f67710a8cd459e4e54eb96d5f77f3624eba0c661ba19a525807e42eccade \ + --hash=sha256:0e32f7154299f42ae66f13488963269e5eccb8d588a65bc839ed986919fc9fac \ + --hash=sha256:14439063aebcb92401c11afc68ee4e407258d2752e62d748b6942dad20d2a70d \ + --hash=sha256:14778ffd0f6896aa613951a7fbf4690229aa7a543cb2bfbe9f358e08aafa9546 \ + --hash=sha256:14f7b8fcb35ef403b42fa5ecfa4ed032332a91f3dc7368fbce4184d59e1eae0d \ + --hash=sha256:1ab359aff0436d80bfe8a23b46b5fea69f1e18aaf1760a709b4787f1318b317f \ + --hash=sha256:1cd0b77e77c95758f8e1100139844e99f3ccc87e71e6fc8e1c027e55807c549f \ + --hash=sha256:25e0c672a2e32348d2eb33057b41e754091f2835f87222e4675b796b92264f06 \ + --hash=sha256:29c009e7a2ca9ad0ed1376ce20dd692146a5d9fe4310848904b6b4fee5c5c137 \ + --hash=sha256:3222adff1e1ff0dce93c16146b93063a7793de6c43d52309ae321234cdaf0f4d \ + --hash=sha256:3223665349bbfb68da234acd9846955b1a0808cbe5520ff634bf253a4407009b \ + --hash=sha256:3cf17c141617b88ced4536b2135c552490f07799f6ad565948ea07bef0dcb9a6 \ + --hash=sha256:3f23426851d98478c8970da5991f84784a76682213cd50eb73a1da56b95239dc \ + --hash=sha256:3f262401086a3960586af06c054609365e98407151f5ea24a62893a40d80dbbb \ + --hash=sha256:436c4922968a619fb7fef1ccd4b8b3a76c13b67d607073914d675026e911a65c \ + --hash=sha256:469ac2125611b7c5741a0b3798cd9e5786cbad6345f9f400c77212be89563bec \ + --hash=sha256:4861bde57f4d253ab041e374f44023460e60e71efaa121f3c5f0ed457c3a701e \ + --hash=sha256:48854463b0572cc87dac7d981aa72ed8bf6deedc0511853dc76b8bbd5482d36d \ + --hash=sha256:53a0f57e59a530d18a142f4d4ba6dfc708dc5fdedce45e98ff06b44930a2a48f \ + --hash=sha256:54153d21520a71a4c82a0dbb4523e468941d549d221dc173de0f019678cf3813 \ + --hash=sha256:55120759e61309af7fcf9e961c6f6af3dde5921cdb3ee863ef63fd9db126cae6 \ + --hash=sha256:5774c1fdcc98b2259800b683b19599c133baeb11d60033e2095fd9d4667b82db \ + --hash=sha256:58a4a208a6fbfdb7a7327b8f201c6014f189f721fd55d047cafc4157af1bc62a \ + --hash=sha256:58fb9b17b4472c7b1dcf1a54583629e62e23779b2331052f09a9249edf81675b \ + --hash=sha256:5d8b5231de76c528a46b57010bbd83fb51e056aa0220a372fd5065e978406f1c \ + --hash=sha256:5f8952d6d2505c003e8f0224ff7858d341fa4e33fef82b91c4ff0ef070f2393c \ + --hash=sha256:61c9d357a59465736022d5d9ba06687afb7611dfb581a9d2129b77a6fcf78e59 \ + --hash=sha256:6a3d159d5ffa0e3961f353c4b036540996bf8b9697ccc38261c0eac1fd3347a6 \ + --hash=sha256:6a4a639049c44d36a6d1ae0f4a94b271605c745aee5647fa8ffaabcdc01b69a6 \ + --hash=sha256:6ccdea2c213cf9f3d9490cbd5d427693c870753df41e6cb375bd79bcbafc8817 \ + --hash=sha256:6dbe9a97bdb4d8d9d5367b52a7c32549bba70b2739c58ef74a6964a6d05ae054 \ + --hash=sha256:6eda5b8b6be91d3f26efb7dc6e5e68ee805bc5617f65a328587b35255f138bf4 \ + --hash=sha256:705b895b781b3e395c067129d8551655642dfe9437273211d5404e87ac752b53 \ + --hash=sha256:708c95f925a43ab9f34625e45dcdadf09ec8a6e7b664a938f2f8d5650f6c090b \ + --hash=sha256:735e2262363dcbe05c35e3a8869898022af78f89dde9e256924dc02e99fe69ca \ + --hash=sha256:76070a76e9c5ae661e2d9848f216980d8d533e0f8143e6ed462807b242e3c5e8 \ + --hash=sha256:7679bc2f01bb0d219758f1a5f87bb7c8a81c0a186824a393b366876b4948e14f \ + --hash=sha256:88006eda83858a9fdf73985ce3804e885c2befb2f506c9a3723cdeb5a2880e3e \ + --hash=sha256:883206d55b1bd5f5679ad5e6ddd3d1a5e3cac5190482927fdb8c78fb699193b5 \ + --hash=sha256:8ac7381c83dd3d4a6347e6635950aa448f54e7b8406a27c7ecb4a37e9f1ae08b \ + --hash=sha256:8e8c6218b614badf8e229b697865df4301afa74b791b6c9ade01d19a9953a942 \ + --hash=sha256:9185589c1f2a944c17e26c9925dcdbc2df061cc4a145395c57f0c51f9b5dbfcd \ + --hash=sha256:93de06bc920854552493c81f1f729fab7213b7db4b8195355db5fda02c7d1363 \ + --hash=sha256:96163d9cdc5a202703e9ad1b9ae757d5f0ca62f4fa0cc93d1f27b0e180cc404e \ + --hash=sha256:97c8f5d3b62380b70c36ffacb2a356b7c6becec86099b177f73851ba095ef623 \ + --hash=sha256:97d823831105c01f6c8029faf297633dbeb30271892bd430e9c24ceae3734744 \ + --hash=sha256:98bdc6cb889d19bed01de46e67574a2eab61f5cc6b768ed50e8ac68e9d6ffab6 \ + --hash=sha256:9b48e274f8824567d74e2158199e269597edf00823a1b12b63d48462bbf5123e \ + --hash=sha256:a5c370674ebabe16c6ccac33ff80c62bf8a6e59439f5e9d40c1f5ab8fd2215b7 \ + --hash=sha256:b43dc2a391981d36c42fa57747a49dae793ef1d2e43898b197925b5534abd10a \ + --hash=sha256:c154a35dd1330707450bb4d4e7dd1f17fa6f42267a40c1e8a1daa5e13719b4b8 \ + --hash=sha256:c2bdf7b2facc80b5e34f48a2d557727d5c5c57a8a450de122ae81fa26a81c1bc \ + --hash=sha256:c492a0e011c0f9066e9ceaa896fbc5b068c54d365fea5f3444b697ee01bc8625 \ + --hash=sha256:c60c0423f15abb6cf78f56dff00168a1b582f7a1c23f114036e2bfc697814d5f \ + --hash=sha256:c98121237fea2f679480765abd566f7713185897f35c9e6c2add7e3a9900eb61 \ + --hash=sha256:ccd7ba1b0605813a0715171d39ec4c314cb97a9c85893c2c5c0c3a3729df38bf \ + --hash=sha256:cdbc8c9c02463fef4d3c53a9ba3336d05496ec8e1f1c53326a1e4acc11f5c600 \ + --hash=sha256:e0950ed1bcb9893f4293fd5c5a7ee10934fbf82c4101c70be360db23ce24b7d2 \ + --hash=sha256:e6693ff90018600c72fd18d3d22fa438be26076cd3c823da5f63f7bab28c11cb \ + --hash=sha256:ea56a955056a6d6c550cf18b3348656a9d9a4f02e2d0c02cabf3c73f1055d506 \ + --hash=sha256:ebaed4cef74a045b83e23537b52ef19a367c7e3f536751e355a2a394f8648559 \ + --hash=sha256:ec795530a73c269a55130498842aaa762e4a939f6ce481a7e986eeaa790e9da4 \ + --hash=sha256:ed193ce51d77a3830cad399a529cd4ef029968761f43ddc549e1bc62b40d88f8 \ + --hash=sha256:ee8db7bfb6fe03581bbab54d7c4124a6dd6a7f4273a38f7267197890f094675f \ + --hash=sha256:f30491bc4f862aa15744b9738517454f1e46e56c972a2be87d70d727d5b2a8f8 \ + --hash=sha256:f89b6d0b3a8d81e1929d3ab3d92bbc225688bd80a770c49432543928fe09ac55 \ + --hash=sha256:fa72e71977bff96567b0f500fc5bfd2fdf915f34052c782a4c6ebbdaa97aa858 \ + --hash=sha256:fe0b8c83e0f36247fc9431ce5425a5d95f9b3a689133d494831bdbd6f0bceb13 \ + --hash=sha256:ff51f9d657d1afb6f410cb435792ce4e1fe427aab23d2fcd727a2876e21d4cb6 # via trino overrides==7.7.0 \ --hash=sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a \ @@ -3583,26 +3643,26 @@ propcache==0.4.1 \ # via # aiohttp # yarl -proto-plus==1.27.1 \ - --hash=sha256:912a7460446625b792f6448bade9e55cd4e41e6ac10e27009ef71a7f317fa147 \ - --hash=sha256:e4643061f3a4d0de092d62aa4ad09fa4756b2cbb89d4627f3985018216f9fefc +proto-plus==1.27.2 \ + --hash=sha256:6432f75893d3b9e70b9c412f1d2f03f65b11fb164b793d14ae2ca01821d22718 \ + --hash=sha256:b2adde53adadf75737c44d3dcb0104fde65250dfc83ad59168b4aa3e574b6a24 # via # google-api-core # google-cloud-bigquery-storage # google-cloud-bigtable # google-cloud-datastore -protobuf==4.25.8 \ - --hash=sha256:077ff8badf2acf8bc474406706ad890466274191a48d0abd3bd6987107c9cde5 \ - --hash=sha256:15a0af558aa3b13efef102ae6e4f3efac06f1eea11afb3a57db2901447d9fb59 \ - --hash=sha256:27d498ffd1f21fb81d987a041c32d07857d1d107909f5134ba3350e1ce80a4af \ - --hash=sha256:504435d831565f7cfac9f0714440028907f1975e4bed228e58e72ecfff58a1e0 \ - --hash=sha256:6135cf8affe1fc6f76cced2641e4ea8d3e59518d1f24ae41ba97bcad82d397cd \ - --hash=sha256:83e6e54e93d2b696a92cad6e6efc924f3850f82b52e1563778dfab8b355101b0 \ - --hash=sha256:9ad7ef62d92baf5a8654fbb88dac7fa5594cfa70fd3440488a5ca3bfc6d795a7 \ - --hash=sha256:bd551eb1fe1d7e92c1af1d75bdfa572eff1ab0e5bf1736716814cdccdb2360f9 \ - --hash=sha256:ca809b42f4444f144f2115c4c1a747b9a404d590f18f37e9402422033e464e0f \ - --hash=sha256:d552c53d0415449c8d17ced5c341caba0d89dbf433698e1436c8fa0aae7808a3 \ - --hash=sha256:f4510b93a3bec6eba8fd8f1093e9d7fb0d4a24d1a81377c10c0e5bbfe9e4ed24 +protobuf==4.25.9 \ + --hash=sha256:3683c05154252206f7cb2d371626514b3708199d9bcf683b503dabf3a2e38e06 \ + --hash=sha256:438c636de8fb706a0de94a12a268ef1ae8f5ba5ae655a7671fcda5968ba3c9be \ + --hash=sha256:79faf4e5a80b231d94dcf3a0a2917ccbacf0f586f12c9b9c91794b41b913a853 \ + --hash=sha256:7f7c1abcea3fc215918fba67a2d2a80fbcccc0f84159610eb187e9bbe6f939ee \ + --hash=sha256:9481e80e8cffb1c492c68e7c4e6726f4ad02eebc4fa97ead7beebeaa3639511d \ + --hash=sha256:9560813560e6ee72c11ca8873878bdb7ee003c96a57ebb013245fe84e2540904 \ + --hash=sha256:999146ef02e7fa6a692477badd1528bcd7268df211852a3df2d834ba2b480791 \ + --hash=sha256:b0dc7e7c68de8b1ce831dacb12fb407e838edbb8b6cc0dc3a2a6b4cbf6de9cff \ + --hash=sha256:b1d467352de666dc1b6d5740b6319d9c08cab7b21b452501e4ee5b0ac5156780 \ + --hash=sha256:bde396f568b0b46fc8fbfe9f02facf25b6755b2578a3b8ac61e74b9d69499e03 \ + --hash=sha256:d49b615e7c935194ac161f0965699ac84df6112c378e05ec53da65d2e4cbb6d4 # via # feast (pyproject.toml) # google-api-core @@ -3616,7 +3676,6 @@ protobuf==4.25.8 \ # grpcio-status # grpcio-testing # grpcio-tools - # ikvpy # mypy-protobuf # opentelemetry-proto # proto-plus @@ -3833,12 +3892,10 @@ pyarrow-hotfix==0.7 \ --hash=sha256:3236f3b5f1260f0e2ac070a55c1a7b339c4bb7267839bd2015e283234e758100 \ --hash=sha256:59399cd58bdd978b2e42816a4183a55c6472d4e33d183351b6069f11ed42661d # via ibis-framework -pyasn1==0.6.2 \ - --hash=sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf \ - --hash=sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b - # via - # pyasn1-modules - # rsa +pyasn1==0.6.3 \ + --hash=sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf \ + --hash=sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde + # via pyasn1-modules pyasn1-modules==0.4.2 \ --hash=sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a \ --hash=sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6 @@ -4073,9 +4130,9 @@ pydantic-core==2.41.5 \ --hash=sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425 \ --hash=sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52 # via pydantic -pydantic-settings==2.13.0 \ - --hash=sha256:95d875514610e8595672800a5c40b073e99e4aae467fa7c8f9c263061ea2e1fe \ - --hash=sha256:d67b576fff39cd086b595441bf9c75d4193ca9c0ed643b90360694d0f1240246 +pydantic-settings==2.13.1 \ + --hash=sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025 \ + --hash=sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237 # via # docling # fastapi-mcp @@ -4084,9 +4141,9 @@ pydata-google-auth==1.9.1 \ --hash=sha256:0a51ce41c601ca0bc69b8795bf58bedff74b4a6a007c9106c7cbcdec00eaced2 \ --hash=sha256:75ffce5d106e34b717b31844c1639ea505b7d9550dc23b96fb6c20d086b53fa3 # via pandas-gbq -pygments==2.19.2 \ - --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \ - --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b +pygments==2.20.0 \ + --hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \ + --hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176 # via # feast (pyproject.toml) # ipython @@ -4095,11 +4152,12 @@ pygments==2.19.2 \ # nbconvert # rich # sphinx -pyjwt[crypto]==2.11.0 \ - --hash=sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623 \ - --hash=sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469 +pyjwt[crypto]==2.12.1 \ + --hash=sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c \ + --hash=sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b # via # feast (pyproject.toml) + # kube-authkit # mcp # msal # singlestoredb @@ -4270,9 +4328,9 @@ pyodbc==5.3.0 \ # via # feast (pyproject.toml) # ibis-framework -pyopenssl==25.1.0 \ - --hash=sha256:2b11f239acc47ac2e5aca04fd7fa829800aeee22a2eb30d744572a157bd8a1ab \ - --hash=sha256:8d031884482e0c67ee92bf9a4d8cceb08d92aba7136432ffb0703c5280fc205b +pyopenssl==26.0.0 \ + --hash=sha256:df94d28498848b98cc1c0ffb8ef1e71e40210d3b0a8064c9d29571ed2904bf81 \ + --hash=sha256:f293934e52936f2e3413b89c6ce36df66a0b34ae1ea3a053b8c5020ff2f513fc # via snowflake-connector-python pyparsing==3.3.2 \ --hash=sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d \ @@ -4324,9 +4382,9 @@ pytest-benchmark==3.4.1 \ --hash=sha256:36d2b08c4882f6f997fd3126a3d6dfd70f3249cde178ed8bbc0b73db7c20f809 \ --hash=sha256:40e263f912de5a81d891619032983557d62a3d85843f9a9f30b98baea0cd7b47 # via feast (pyproject.toml) -pytest-cov==7.0.0 \ - --hash=sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1 \ - --hash=sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861 +pytest-cov==7.1.0 \ + --hash=sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2 \ + --hash=sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678 # via feast (pyproject.toml) pytest-env==1.1.3 \ --hash=sha256:aada77e6d09fcfb04540a6e462c58533c37df35fa853da78707b17ec04d17dfc \ @@ -4482,17 +4540,17 @@ python-docx==1.2.0 \ --hash=sha256:3fd478f3250fbbbfd3b94fe1e985955737c145627498896a8a6bf81f4baf66c7 \ --hash=sha256:7bc9d7b7d8a69c9c02ca09216118c86552704edc23bac179283f2e38f86220ce # via docling -python-dotenv==1.2.1 \ - --hash=sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6 \ - --hash=sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61 +python-dotenv==1.2.2 \ + --hash=sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a \ + --hash=sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3 # via # pydantic-settings # pymilvus # testcontainers # uvicorn -python-json-logger==4.0.0 \ - --hash=sha256:af09c9daf6a813aa4cc7180395f50f2a9e5fa056034c9953aec92e381c5ba1e2 \ - --hash=sha256:f58e68eb46e1faed27e0f574a55a0455eecd7b8a5b88b85a784519ba3cff047f +python-json-logger==4.1.0 \ + --hash=sha256:132994765cf75bf44554be9aa49b06ef2345d23661a96720262716438141b6b2 \ + --hash=sha256:b396b9e3ed782b09ff9d6e4f1683d46c83ad0d35d2e407c09a9ebbf038f88195 # via jupyter-events python-keycloak==4.2.2 \ --hash=sha256:1d43a1accd4a038ed39317fcb3eb78211df6c75bbcbc4c482c99ee76327136f2 \ @@ -4506,9 +4564,9 @@ python-pptx==1.0.2 \ --hash=sha256:160838e0b8565a8b1f67947675886e9fea18aa5e795db7ae531606d68e785cba \ --hash=sha256:479a8af0eaf0f0d76b6f00b0887732874ad2e3188230315290cd1f9dd9cc7095 # via docling -pytz==2025.2 \ - --hash=sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3 \ - --hash=sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00 +pytz==2026.1.post1 \ + --hash=sha256:3378dde6a0c3d26719182142c56e60c7f9af7e968076f31aae569d72a0358ee1 \ + --hash=sha256:f2fd16142fda348286a75e1a524be810bb05d444e5a081f37f7affc635035f7a # via # clickhouse-connect # great-expectations @@ -4704,26 +4762,26 @@ pyzmq==27.1.0 \ # ipykernel # jupyter-client # jupyter-server -qdrant-client==1.16.2 \ - --hash=sha256:442c7ef32ae0f005e88b5d3c0783c63d4912b97ae756eb5e052523be682f17d3 \ - --hash=sha256:ca4ef5f9be7b5eadeec89a085d96d5c723585a391eb8b2be8192919ab63185f0 +qdrant-client==1.17.1 \ + --hash=sha256:22f990bbd63485ed97ba551a4c498181fcb723f71dcab5d6e4e43fe1050a2bc0 \ + --hash=sha256:6cda4064adfeaf211c751f3fbc00edbbdb499850918c7aff4855a9a759d56cbd # via feast (pyproject.toml) -ray[data, default]==2.52.1 \ - --hash=sha256:08eb8f5fd55292ba6bee363a32491136a5e54af54e007f81e0603986fbea41a4 \ - --hash=sha256:24694e60cdc7770b90f123cc578cabb9d1a231c1fe673b5da0027b118de45846 \ - --hash=sha256:2b57ef272a2a0a0dbae6d18d70aa541eab620b4fe3b44d50466d3a533c16f9d9 \ - --hash=sha256:4e8478544fef69a17d865431c0bebdcfeff7c0f76a306f29b73c3bc3cbb0bdb9 \ - --hash=sha256:65bf461fdfe4ffa667c46f9455f8740b2ad6c1fa471b461d5f5cf6b7baf177b5 \ - --hash=sha256:6831592fedf0a122016f5dab4b67d85fa3d4db3b21f588d18834b5c031396d1c \ - --hash=sha256:8045172ad3fcff62b9dab9a4cd2e0991ad0e27fc814fe625a8d3a120306651d6 \ - --hash=sha256:843c0108ad72bb7fc6c23a22e29e6099546a5eaad3ad675c78a146d9080f6ec6 \ - --hash=sha256:993194a8be70540e0f819862031bbf19a64401fbe6c31b42065fd313ba466d34 \ - --hash=sha256:a5a3c268d45060c50cd029979ecc5f1eaaec040b19fa88dd4fe9e927d19ff13e \ - --hash=sha256:b3f9e61b799fb3cc8fd7077a3d2eb676ddfef7db644f6b6a2b657c5c3214cf19 \ - --hash=sha256:b5bc29548abb0a0a7ae9e6ff3b0ccca2824edaf011a4336e15a32793d574fbfd \ - --hash=sha256:bbe492c780a39a64bd3d0766cad10d54cf12222df88d287ec2d8f2d52de37c79 \ - --hash=sha256:e3826aeb4e4399de0c6885bd8be7ce2f629fa0010f0013f1183e0726b3d25e40 \ - --hash=sha256:f59e3b2d1a1466ac0778f2c6fac9ccb5f30107d77e3dddd1d60167248d268474 +ray[data, default]==2.53.0 \ + --hash=sha256:14f46363e9b4cf0c1c8b4d8623ec337c5bd408377831b5e5b50067930137bbca \ + --hash=sha256:4108280d8a1cb90d7d68e5c954c35e63b8bb9a4ba15f88c5e7da0e2025647712 \ + --hash=sha256:4a1bb3fe09ab4cd0d16ddc96b9f60c9ed83b3f93b87aa8506e0d3b746fd4e825 \ + --hash=sha256:4db914a0a6dd608fa49c066929a1282745a2dbd73caee67d7b80fe684ca65bdd \ + --hash=sha256:4dbb5fce1364763f29741055f50abe33cf726397141f9cc0e845dd3cc963e455 \ + --hash=sha256:65e2ce58d3dc6baa3cf45824d889c1968ebde565ee54dfd80a98af8f31af8e4a \ + --hash=sha256:7196e5358dfcc8211be864f45e6dfe4827202df294af3c7a76ff8fbc080e0522 \ + --hash=sha256:73dbbaa7962a7f5e38aa8cf9483e0e9817205e989aa3dc859c738c2af1ae01df \ + --hash=sha256:85b472ab6fb8f1189f8cef81913fd91b24dd69b3fa7dcca7e144827bd924f6c0 \ + --hash=sha256:90faf630d20b6abf3135997fb3edb5842134aff92e04ee709865db04816d97ef \ + --hash=sha256:a0bbb98b0b0f25a3ee075ca10171e1260e70b6bc690cd509ecd7ce1228af854d \ + --hash=sha256:b828c147f9ff2f277b1d254e4fe9a746fdfaee7e313a93a97c7edf4dae9b81a4 \ + --hash=sha256:bd3ec4c342776ddac23ae2b108c64f5939f417ccc4875900d586c7c978463269 \ + --hash=sha256:d8b95d047d947493803fb8417aea31225dcacdab15afdc75b8a238901949d457 \ + --hash=sha256:eb000c17f7301071fdd15c44c4cd3ac0f7953bb4c7c227e61719fe7048195bcd # via codeflare-sdk redis==4.6.0 \ --hash=sha256:585dc516b9eb042a619ef0a39c3d7d55fe81bdb4df09a52c9cdde0d07bf1aa7d \ @@ -4736,145 +4794,128 @@ referencing==0.37.0 \ # jsonschema # jsonschema-specifications # jupyter-events -regex==2026.1.15 \ - --hash=sha256:0057de9eaef45783ff69fa94ae9f0fd906d629d0bd4c3217048f46d1daa32e9b \ - --hash=sha256:008b185f235acd1e53787333e5690082e4f156c44c87d894f880056089e9bc7c \ - --hash=sha256:05d75a668e9ea16f832390d22131fe1e8acc8389a694c8febc3e340b0f810b93 \ - --hash=sha256:069f56a7bf71d286a6ff932a9e6fb878f151c998ebb2519a9f6d1cee4bffdba3 \ - --hash=sha256:0751a26ad39d4f2ade8fe16c59b2bf5cb19eb3d2cd543e709e583d559bd9efde \ - --hash=sha256:08df9722d9b87834a3d701f3fca570b2be115654dbfd30179f30ab2f39d606d3 \ - --hash=sha256:0bda75ebcac38d884240914c6c43d8ab5fb82e74cde6da94b43b17c411aa4c2b \ - --hash=sha256:0bf065240704cb8951cc04972cf107063917022511273e0969bdb34fc173456c \ - --hash=sha256:0bf650f26087363434c4e560011f8e4e738f6f3e029b85d4904c50135b86cfa5 \ - --hash=sha256:0dcd31594264029b57bf16f37fd7248a70b3b764ed9e0839a8f271b2d22c0785 \ - --hash=sha256:0f0c7684c7f9ca241344ff95a1de964f257a5251968484270e91c25a755532c5 \ - --hash=sha256:124dc36c85d34ef2d9164da41a53c1c8c122cfb1f6e1ec377a1f27ee81deb794 \ - --hash=sha256:164759aa25575cbc0651bef59a0b18353e54300d79ace8084c818ad8ac72b7d5 \ - --hash=sha256:166551807ec20d47ceaeec380081f843e88c8949780cd42c40f18d16168bed10 \ - --hash=sha256:1704d204bd42b6bb80167df0e4554f35c255b579ba99616def38f69e14a5ccb9 \ - --hash=sha256:18388a62989c72ac24de75f1449d0fb0b04dfccd0a1a7c1c43af5eb503d890f6 \ - --hash=sha256:194312a14819d3e44628a44ed6fea6898fdbecb0550089d84c403475138d0a09 \ - --hash=sha256:1ae6020fb311f68d753b7efa9d4b9a5d47a5d6466ea0d5e3b5a471a960ea6e4a \ - --hash=sha256:1cb740d044aff31898804e7bf1181cc72c03d11dfd19932b9911ffc19a79070a \ - --hash=sha256:1e1808471fbe44c1a63e5f577a1d5f02fe5d66031dcbdf12f093ffc1305a858e \ - --hash=sha256:1e8cd52557603f5c66a548f69421310886b28b7066853089e1a71ee710e1cdc1 \ - --hash=sha256:21ca32c28c30d5d65fc9886ff576fc9b59bbca08933e844fa2363e530f4c8218 \ - --hash=sha256:2748c1ec0663580b4510bd89941a31560b4b439a0b428b49472a3d9944d11cd8 \ - --hash=sha256:27618391db7bdaf87ac6c92b31e8f0dfb83a9de0075855152b720140bda177a2 \ - --hash=sha256:2a8d7b50c34578d0d3bf7ad58cde9652b7d683691876f83aedc002862a35dc5e \ - --hash=sha256:2b091aefc05c78d286657cd4db95f2e6313375ff65dcf085e42e4c04d9c8d410 \ - --hash=sha256:2c2b80399a422348ce5de4fe40c418d6299a0fa2803dd61dc0b1a2f28e280fcf \ - --hash=sha256:2f2775843ca49360508d080eaa87f94fa248e2c946bbcd963bb3aae14f333413 \ - --hash=sha256:3038a62fc7d6e5547b8915a3d927a0fbeef84cdbe0b1deb8c99bbd4a8961b52a \ - --hash=sha256:32655d17905e7ff8ba5c764c43cb124e34a9245e45b83c22e81041e1071aee10 \ - --hash=sha256:343db82cb3712c31ddf720f097ef17c11dab2f67f7a3e7be976c4f82eba4e6df \ - --hash=sha256:3601ffb5375de85a16f407854d11cca8fe3f5febbe3ac78fb2866bb220c74d10 \ - --hash=sha256:3d6ce5ae80066b319ae3bc62fd55a557c9491baa5efd0d355f0de08c4ba54e79 \ - --hash=sha256:3d7d92495f47567a9b1669c51fc8d6d809821849063d168121ef801bbc213846 \ - --hash=sha256:40c86d8046915bb9aeb15d3f3f15b6fd500b8ea4485b30e1bbc799dab3fe29f8 \ - --hash=sha256:4161d87f85fa831e31469bfd82c186923070fc970b9de75339b68f0c75b51903 \ - --hash=sha256:41aef6f953283291c4e4e6850607bd71502be67779586a61472beacb315c97ec \ - --hash=sha256:453078802f1b9e2b7303fb79222c054cb18e76f7bdc220f7530fdc85d319f99e \ - --hash=sha256:492534a0ab925d1db998defc3c302dae3616a2fc3fe2e08db1472348f096ddf2 \ - --hash=sha256:4c5ef43b5c2d4114eb8ea424bb8c9cec01d5d17f242af88b2448f5ee81caadbc \ - --hash=sha256:4c8fcc5793dde01641a35905d6731ee1548f02b956815f8f1cab89e515a5bdf1 \ - --hash=sha256:4def140aa6156bc64ee9912383d4038f3fdd18fee03a6f222abd4de6357ce42a \ - --hash=sha256:4e3dd93c8f9abe8aa4b6c652016da9a3afa190df5ad822907efe6b206c09896e \ - --hash=sha256:505831646c945e3e63552cc1b1b9b514f0e93232972a2d5bedbcc32f15bc82e3 \ - --hash=sha256:5170907244b14303edc5978f522f16c974f32d3aa92109fabc2af52411c9433b \ - --hash=sha256:55b4ea996a8e4458dd7b584a2f89863b1655dd3d17b88b46cbb9becc495a0ec5 \ - --hash=sha256:55e9d0118d97794367309635df398bdfd7c33b93e2fdfa0b239661cd74b4c14e \ - --hash=sha256:56a5595d0f892f214609c9f76b41b7428bed439d98dc961efafdd1354d42baae \ - --hash=sha256:57e7d17f59f9ebfa9667e6e5a1c0127b96b87cb9cede8335482451ed00788ba4 \ - --hash=sha256:5ef19071f4ac9f0834793af85bd04a920b4407715624e40cb7a0631a11137cdf \ - --hash=sha256:5ff818702440a5878a81886f127b80127f5d50563753a28211482867f8318106 \ - --hash=sha256:619843841e220adca114118533a574a9cd183ed8a28b85627d2844c500a2b0db \ - --hash=sha256:621f73a07595d83f28952d7bd1e91e9d1ed7625fb7af0064d3516674ec93a2a2 \ - --hash=sha256:693b465171707bbe882a7a05de5e866f33c76aa449750bee94a8d90463533cc9 \ - --hash=sha256:6bfc31a37fd1592f0c4fc4bfc674b5c42e52efe45b4b7a6a14f334cca4bcebe4 \ - --hash=sha256:6d220a2517f5893f55daac983bfa9fe998a7dbcaee4f5d27a88500f8b7873788 \ - --hash=sha256:6e42844ad64194fa08d5ccb75fe6a459b9b08e6d7296bd704460168d58a388f3 \ - --hash=sha256:726ea4e727aba21643205edad8f2187ec682d3305d790f73b7a51c7587b64bdd \ - --hash=sha256:74f45d170a21df41508cb67165456538425185baaf686281fa210d7e729abc34 \ - --hash=sha256:7dcc02368585334f5bc81fc73a2a6a0bbade60e7d83da21cead622faf408f32c \ - --hash=sha256:7e1e28be779884189cdd57735e997f282b64fd7ccf6e2eef3e16e57d7a34a815 \ - --hash=sha256:7ef7d5d4bd49ec7364315167a4134a015f61e8266c6d446fc116a9ac4456e10d \ - --hash=sha256:8050ba2e3ea1d8731a549e83c18d2f0999fbc99a5f6bd06b4c91449f55291804 \ - --hash=sha256:82345326b1d8d56afbe41d881fdf62f1926d7264b2fc1537f99ae5da9aad7913 \ - --hash=sha256:8355ad842a7c7e9e5e55653eade3b7d1885ba86f124dd8ab1f722f9be6627434 \ - --hash=sha256:86c1077a3cc60d453d4084d5b9649065f3bf1184e22992bd322e1f081d3117fb \ - --hash=sha256:87adf5bd6d72e3e17c9cb59ac4096b1faaf84b7eb3037a5ffa61c4b4370f0f13 \ - --hash=sha256:8db052bbd981e1666f09e957f3790ed74080c2229007c1dd67afdbf0b469c48b \ - --hash=sha256:8dd16fba2758db7a3780a051f245539c4451ca20910f5a5e6ea1c08d06d4a76b \ - --hash=sha256:8e32f7896f83774f91499d239e24cebfadbc07639c1494bb7213983842348337 \ - --hash=sha256:91c5036ebb62663a6b3999bdd2e559fd8456d17e2b485bf509784cd31a8b1705 \ - --hash=sha256:9250d087bc92b7d4899ccd5539a1b2334e44eee85d848c4c1aef8e221d3f8c8f \ - --hash=sha256:9479cae874c81bf610d72b85bb681a94c95722c127b55445285fb0e2c82db8e1 \ - --hash=sha256:968c14d4f03e10b2fd960f1d5168c1f0ac969381d3c1fcc973bc45fb06346599 \ - --hash=sha256:97499ff7862e868b1977107873dd1a06e151467129159a6ffd07b66706ba3a9f \ - --hash=sha256:99ad739c3686085e614bf77a508e26954ff1b8f14da0e3765ff7abbf7799f952 \ - --hash=sha256:9d787e3310c6a6425eb346be4ff2ccf6eece63017916fd77fe8328c57be83521 \ - --hash=sha256:a1774cd1981cd212506a23a14dba7fdeaee259f5deba2df6229966d9911e767a \ - --hash=sha256:a30a68e89e5a218b8b23a52292924c1f4b245cb0c68d1cce9aec9bbda6e2c160 \ - --hash=sha256:adc97a9077c2696501443d8ad3fa1b4fc6d131fc8fd7dfefd1a723f89071cf0a \ - --hash=sha256:b0d190e6f013ea938623a58706d1469a62103fb2a241ce2873a9906e0386582c \ - --hash=sha256:b10e42a6de0e32559a92f2f8dc908478cc0fa02838d7dbe764c44dca3fa13569 \ - --hash=sha256:b2a13dd6a95e95a489ca242319d18fc02e07ceb28fa9ad146385194d95b3c829 \ - --hash=sha256:b30bcbd1e1221783c721483953d9e4f3ab9c5d165aa709693d3f3946747b1aea \ - --hash=sha256:b325d4714c3c48277bfea1accd94e193ad6ed42b4bad79ad64f3b8f8a31260a5 \ - --hash=sha256:b5a28980a926fa810dbbed059547b02783952e2efd9c636412345232ddb87ff6 \ - --hash=sha256:b5f7d8d2867152cdb625e72a530d2ccb48a3d199159144cbdd63870882fb6f80 \ - --hash=sha256:bfb0d6be01fbae8d6655c8ca21b3b72458606c4aec9bbc932db758d47aba6db1 \ - --hash=sha256:bfd876041a956e6a90ad7cdb3f6a630c07d491280bfeed4544053cd434901681 \ - --hash=sha256:c08c1f3e34338256732bd6938747daa3c0d5b251e04b6e43b5813e94d503076e \ - --hash=sha256:c243da3436354f4af6c3058a3f81a97d47ea52c9bd874b52fd30274853a1d5df \ - --hash=sha256:c32bef3e7aeee75746748643667668ef941d28b003bfc89994ecf09a10f7a1b5 \ - --hash=sha256:c661fc820cfb33e166bf2450d3dadbda47c8d8981898adb9b6fe24e5e582ba60 \ - --hash=sha256:c6c4dcdfff2c08509faa15d36ba7e5ef5fcfab25f1e8f85a0c8f45bc3a30725d \ - --hash=sha256:c6c565d9a6e1a8d783c1948937ffc377dd5771e83bd56de8317c450a954d2056 \ - --hash=sha256:c8a154cf6537ebbc110e24dabe53095e714245c272da9c1be05734bdad4a61aa \ - --hash=sha256:c9c08c2fbc6120e70abff5d7f28ffb4d969e14294fb2143b4b5c7d20e46d1714 \ - --hash=sha256:ca89c5e596fc05b015f27561b3793dc2fa0917ea0d7507eebb448efd35274a70 \ - --hash=sha256:cc7cd0b2be0f0269283a45c0d8b2c35e149d1319dcb4a43c9c3689fa935c1ee6 \ - --hash=sha256:cda1ed70d2b264952e88adaa52eea653a33a1b98ac907ae2f86508eb44f65cdc \ - --hash=sha256:cf8ff04c642716a7f2048713ddc6278c5fd41faa3b9cab12607c7abecd012c22 \ - --hash=sha256:cfecdaa4b19f9ca534746eb3b55a5195d5c95b88cac32a205e981ec0a22b7d31 \ - --hash=sha256:d426616dae0967ca225ab12c22274eb816558f2f99ccb4a1d52ca92e8baf180f \ - --hash=sha256:d5eaa4a4c5b1906bd0d2508d68927f15b81821f85092e06f1a34a4254b0e1af3 \ - --hash=sha256:d639a750223132afbfb8f429c60d9d318aeba03281a5f1ab49f877456448dcf1 \ - --hash=sha256:d920392a6b1f353f4aa54328c867fec3320fa50657e25f64abf17af054fc97ac \ - --hash=sha256:d991483606f3dbec93287b9f35596f41aa2e92b7c2ebbb935b63f409e243c9af \ - --hash=sha256:d9ea2604370efc9a174c1b5dcc81784fb040044232150f7f33756049edfc9026 \ - --hash=sha256:dbaf3c3c37ef190439981648ccbf0c02ed99ae066087dd117fcb616d80b010a4 \ - --hash=sha256:dca3582bca82596609959ac39e12b7dad98385b4fefccb1151b937383cec547d \ - --hash=sha256:e3174a5ed4171570dc8318afada56373aa9289eb6dc0d96cceb48e7358b0e220 \ - --hash=sha256:e43a55f378df1e7a4fa3547c88d9a5a9b7113f653a66821bcea4718fe6c58763 \ - --hash=sha256:e69d0deeb977ffe7ed3d2e4439360089f9c3f217ada608f0f88ebd67afb6385e \ - --hash=sha256:e85dc94595f4d766bd7d872a9de5ede1ca8d3063f3bdf1e2c725f5eb411159e3 \ - --hash=sha256:e90b8db97f6f2c97eb045b51a6b2c5ed69cedd8392459e0642d4199b94fabd7e \ - --hash=sha256:e9bf3f0bbdb56633c07d7116ae60a576f846efdd86a8848f8d62b749e1209ca7 \ - --hash=sha256:ea4e6b3566127fda5e007e90a8fd5a4169f0cf0619506ed426db647f19c8454a \ - --hash=sha256:ec94c04149b6a7b8120f9f44565722c7ae31b7a6d2275569d2eefa76b83da3be \ - --hash=sha256:eddf73f41225942c1f994914742afa53dc0d01a6e20fe14b878a1b1edc74151f \ - --hash=sha256:ee6854c9000a10938c79238de2379bea30c82e4925a371711af45387df35cab8 \ - --hash=sha256:ef71d476caa6692eea743ae5ea23cde3260677f70122c4d258ca952e5c2d4e84 \ - --hash=sha256:f052d1be37ef35a54e394de66136e30fa1191fab64f71fc06ac7bc98c9a84618 \ - --hash=sha256:f1862739a1ffb50615c0fde6bae6569b5efbe08d98e59ce009f68a336f64da75 \ - --hash=sha256:f192a831d9575271a22d804ff1a5355355723f94f31d9eef25f0d45a152fdc1a \ - --hash=sha256:f42e68301ff4afee63e365a5fc302b81bb8ba31af625a671d7acb19d10168a8c \ - --hash=sha256:f7792f27d3ee6e0244ea4697d92b825f9a329ab5230a78c1a68bd274e64b5077 \ - --hash=sha256:f82110ab962a541737bd0ce87978d4c658f06e7591ba899192e2712a517badbb \ - --hash=sha256:f9ca1cbdc0fbfe5e6e6f8221ef2309988db5bcede52443aeaee9a4ad555e0dac \ - --hash=sha256:fd65af65e2aaf9474e468f9e571bd7b189e1df3a61caa59dcbabd0000e4ea839 \ - --hash=sha256:fe2fda4110a3d0bc163c2e0664be44657431440722c5c5315c65155cab92f9e5 \ - --hash=sha256:febd38857b09867d3ed3f4f1af7d241c5c50362e25ef43034995b77a50df494e +regex==2026.3.32 \ + --hash=sha256:03c2ebd15ff51e7b13bb3dc28dd5ac18cd39e59ebb40430b14ae1a19e833cff1 \ + --hash=sha256:09e26cad1544d856da85881ad292797289e4406338afe98163f3db9f7fac816c \ + --hash=sha256:0cec365d44835b043d7b3266487797639d07d621bec9dc0ea224b00775797cc1 \ + --hash=sha256:0d7855f5e59fcf91d0c9f4a51dc5d8847813832a2230c3e8e35912ccf20baaa2 \ + --hash=sha256:0f21ae18dfd15752cdd98d03cbd7a3640be826bfd58482a93f730dbd24d7b9fb \ + --hash=sha256:10fb2aaae1aaadf7d43c9f3c2450404253697bf8b9ce360bd5418d1d16292298 \ + --hash=sha256:110ba4920721374d16c4c8ea7ce27b09546d43e16aea1d7f43681b5b8f80ba61 \ + --hash=sha256:12917c6c6813ffcdfb11680a04e4d63c5532b88cf089f844721c5f41f41a63ad \ + --hash=sha256:18eb45f711e942c27dbed4109830bd070d8d618e008d0db39705f3f57070a4c6 \ + --hash=sha256:1a6ac1ed758902e664e0d95c1ee5991aa6fb355423f378ed184c6ec47a1ec0e9 \ + --hash=sha256:1ca02ff0ef33e9d8276a1fcd6d90ff6ea055a32c9149c0050b5b67e26c6d2c51 \ + --hash=sha256:1cb22fa9ee6a0acb22fc9aecce5f9995fe4d2426ed849357d499d62608fbd7f9 \ + --hash=sha256:1e0f6648fd48f4c73d801c55ab976cd602e2da87de99c07bff005b131f269c6a \ + --hash=sha256:245667ad430745bae6a1e41081872d25819d86fbd9e0eec485ba00d9f78ad43d \ + --hash=sha256:2820d2231885e97aff0fcf230a19ebd5d2b5b8a1ba338c20deb34f16db1c7897 \ + --hash=sha256:2c8d402ea3dfe674288fe3962016affd33b5b27213d2b5db1823ffa4de524c57 \ + --hash=sha256:2dcca2bceb823c9cc610e57b86a265d7ffc30e9fe98548c609eba8bd3c0c2488 \ + --hash=sha256:2ffbadc647325dd4e3118269bda93ded1eb5f5b0c3b7ba79a3da9fbd04f248e9 \ + --hash=sha256:34c905a721ddee0f84c99e3e3b59dd4a5564a6fe338222bc89dd4d4df166115c \ + --hash=sha256:3c054e39a9f85a3d76c62a1d50c626c5e9306964eaa675c53f61ff7ec1204bbb \ + --hash=sha256:3c0bbfbd38506e1ea96a85da6782577f06239cb9fcf9696f1ea537c980c0680b \ + --hash=sha256:3e221b615f83b15887636fcb90ed21f1a19541366f8b7ba14ba1ad8304f4ded4 \ + --hash=sha256:3ea568832eca219c2be1721afa073c1c9eb8f98a9733fdedd0a9747639fc22a5 \ + --hash=sha256:3f5747501b69299c6b0b047853771e4ed390510bada68cb16da9c9c2078343f7 \ + --hash=sha256:462a041d2160090553572f6bb0be417ab9bb912a08de54cb692829c871ee88c1 \ + --hash=sha256:4bc32b4dbdb4f9f300cf9f38f8ea2ce9511a068ffaa45ac1373ee7a943f1d810 \ + --hash=sha256:4d082be64e51671dd5ee1c208c92da2ddda0f2f20d8ef387e57634f7e97b6aae \ + --hash=sha256:4f9ae4755fa90f1dc2d0d393d572ebc134c0fe30fcfc0ab7e67c1db15f192041 \ + --hash=sha256:51a93452034d671b0e21b883d48ea66c5d6a05620ee16a9d3f229e828568f3f0 \ + --hash=sha256:51fb7e26f91f9091fd8ec6a946f99b15d3bc3667cb5ddc73dd6cb2222dd4a1cc \ + --hash=sha256:5336b1506142eb0f23c96fb4a34b37c4fefd4fed2a7042069f3c8058efe17855 \ + --hash=sha256:567b57eb987547a23306444e4f6f85d4314f83e65c71d320d898aa7550550443 \ + --hash=sha256:5aa78c857c1731bdd9863923ffadc816d823edf475c7db6d230c28b53b7bdb5e \ + --hash=sha256:5bf2f3c2c5bd8360d335c7dcd4a9006cf1dabae063ee2558ee1b07bbc8a20d88 \ + --hash=sha256:5c35d097f509cf7e40d20d5bee548d35d6049b36eb9965e8d43e4659923405b9 \ + --hash=sha256:5d86e3fb08c94f084a625c8dc2132a79a3a111c8bf6e2bc59351fa61753c2f6e \ + --hash=sha256:6062c4ef581a3e9e503dccf4e1b7f2d33fdc1c13ad510b287741ac73bc4c6b27 \ + --hash=sha256:6128dd0793a87287ea1d8bf16b4250dd96316c464ee15953d5b98875a284d41e \ + --hash=sha256:631f7d95c83f42bccfe18946a38ad27ff6b6717fb4807e60cf24860b5eb277fc \ + --hash=sha256:66a5083c3ffe5a5a95f8281ea47a88072d4f24001d562d1d9d28d4cdc005fec5 \ + --hash=sha256:66d3126afe7eac41759cd5f0b3b246598086e88e70527c0d68c9e615b81771c4 \ + --hash=sha256:67015a8162d413af9e3309d9a24e385816666fbf09e48e3ec43342c8536f7df6 \ + --hash=sha256:6980ceb5c1049d4878632f08ba0bf7234c30e741b0dc9081da0f86eca13189d3 \ + --hash=sha256:69a847a6ffaa86e8af7b9e7037606e05a6f663deec516ad851e8e05d9908d16a \ + --hash=sha256:6ada7bd5bb6511d12177a7b00416ce55caee49fbf8c268f26b909497b534cacb \ + --hash=sha256:70c634e39c5cda0da05c93d6747fdc957599f7743543662b6dbabdd8d3ba8a96 \ + --hash=sha256:7cdd508664430dd51b8888deb6c5b416d8de046b2e11837254378d31febe4a98 \ + --hash=sha256:844d88509c968dd44b30daeefac72b038b1bf31ac372d5106358ab01d393c48b \ + --hash=sha256:847087abe98b3c1ebf1eb49d6ef320dbba75a83ee4f83c94704580f1df007dd4 \ + --hash=sha256:85c9b0c131427470a6423baa0a9330be6fd8c3630cc3ee6fdee03360724cbec5 \ + --hash=sha256:879ae91f2928a13f01a55cfa168acedd2b02b11b4cd8b5bb9223e8cde777ca52 \ + --hash=sha256:887a9fa74418d74d645281ee0edcf60694053bd1bc2ebc49eb5e66bfffc6d107 \ + --hash=sha256:88ebc0783907468f17fca3d7821b30f9c21865a721144eb498cb0ff99a67bcac \ + --hash=sha256:89e50667e7e8c0e7903e4d644a2764fffe9a3a5d6578f72ab7a7b4205bf204b7 \ + --hash=sha256:8a4a3189a99ecdd1c13f42513ab3fc7fa8311b38ba7596dd98537acb8cd9acc3 \ + --hash=sha256:8aaf8ee8f34b677f90742ca089b9c83d64bdc410528767273c816a863ed57327 \ + --hash=sha256:8e4c8fa46aad1a11ae2f8fcd1c90b9d55e18925829ac0d98c5bb107f93351745 \ + --hash=sha256:8fc918cd003ba0d066bf0003deb05a259baaaab4dc9bd4f1207bbbe64224857a \ + --hash=sha256:8fe14e24124ef41220e5992a0f09432f890037df6f93fd3d6b7a0feff2db16b2 \ + --hash=sha256:918db4e34a7ef3d0beee913fa54b34231cc3424676f1c19bdb85f01828d3cd37 \ + --hash=sha256:987cdfcfb97a249abc3601ad53c7de5c370529f1981e4c8c46793e4a1e1bfe8e \ + --hash=sha256:9b9118a78e031a2e4709cd2fcc3028432e89b718db70073a8da574c249b5b249 \ + --hash=sha256:9cf7036dfa2370ccc8651521fcbb40391974841119e9982fa312b552929e6c85 \ + --hash=sha256:a094e9dcafedfb9d333db5cf880304946683f43a6582bb86688f123335122929 \ + --hash=sha256:a416ee898ecbc5d8b283223b4cf4d560f93244f6f7615c1bd67359744b00c166 \ + --hash=sha256:a5d88fa37ba5e8a80ca8d956b9ea03805cfa460223ac94b7d4854ee5e30f3173 \ + --hash=sha256:ace48c5e157c1e58b7de633c5e257285ce85e567ac500c833349c363b3df69d4 \ + --hash=sha256:ad5c53f2e8fcae9144009435ebe3d9832003508cf8935c04542a1b3b8deefa15 \ + --hash=sha256:ad8d372587e659940568afd009afeb72be939c769c552c9b28773d0337251391 \ + --hash=sha256:b193ed199848aa96618cd5959c1582a0bf23cd698b0b900cb0ffe81b02c8659c \ + --hash=sha256:b2e9c2ea2e93223579308263f359eab8837dc340530b860cb59b713651889f14 \ + --hash=sha256:b3aa21bad31db904e0b9055e12c8282df62d43169c4a9d2929407060066ebc74 \ + --hash=sha256:b565f25171e04d4fad950d1fa837133e3af6ea6f509d96166eed745eb0cf63bc \ + --hash=sha256:b56993a7aeb4140c4770f4f7965c9e5af4f024457d06e23c01b0d47501cb18ed \ + --hash=sha256:b6acb765e7c1f2fa08ac9057a33595e26104d7d67046becae184a8f100932dd9 \ + --hash=sha256:b6f366a5ef66a2df4d9e68035cfe9f0eb8473cdfb922c37fac1d169b468607b0 \ + --hash=sha256:b7836aa13721dbdef658aebd11f60d00de633a95726521860fe1f6be75fa225a \ + --hash=sha256:b8fca73e16c49dd972ce3a88278dfa5b93bf91ddef332a46e9443abe21ca2f7c \ + --hash=sha256:b953d9d496d19786f4d46e6ba4b386c6e493e81e40f9c5392332458183b0599d \ + --hash=sha256:bbc458a292aee57d572075f22c035fa32969cdb7987d454e3e34d45a40a0a8b4 \ + --hash=sha256:c1cecea3e477af105f32ef2119b8d895f297492e41d317e60d474bc4bffd62ff \ + --hash=sha256:c1d7fa44aece1fa02b8927441614c96520253a5cad6a96994e3a81e060feed55 \ + --hash=sha256:c1ed17104d1be7f807fdec35ec99777168dd793a09510d753f8710590ba54cdd \ + --hash=sha256:c3c6f6b027d10f84bfe65049028892b5740878edd9eae5fea0d1710b09b1d257 \ + --hash=sha256:c5e0fdb5744caf1036dec5510f543164f2144cb64932251f6dfd42fa872b7f9c \ + --hash=sha256:c60f1de066eb5a0fd8ee5974de4194bb1c2e7692941458807162ffbc39887303 \ + --hash=sha256:c6d9c6e783b348f719b6118bb3f187b2e138e3112576c9679eb458cc8b2e164b \ + --hash=sha256:c940e00e8d3d10932c929d4b8657c2ea47d2560f31874c3e174c0d3488e8b865 \ + --hash=sha256:c9f261ad3cd97257dc1d9355bfbaa7dd703e06574bffa0fa8fe1e31da915ee38 \ + --hash=sha256:d21a07edddb3e0ca12a8b8712abc8452481c3d3db19ae87fc94e9842d005964b \ + --hash=sha256:d363660f9ef8c734495598d2f3e527fb41f745c73159dc0d743402f049fb6836 \ + --hash=sha256:d478a2ca902b6ef28ffc9521e5f0f728d036abe35c0b250ee8ae78cfe7c5e44e \ + --hash=sha256:d571f0b2eec3513734ea31a16ce0f7840c0b85a98e7edfa0e328ed144f9ef78f \ + --hash=sha256:d6b39a2cc5625bbc4fda18919a891eab9aab934eecf83660a90ce20c53621a9a \ + --hash=sha256:d76d62909bfb14521c3f7cfd5b94c0c75ec94b0a11f647d2f604998962ec7b6c \ + --hash=sha256:dab4178a0bc1ef13178832b12db7bc7f562e8f028b2b5be186e370090dc50652 \ + --hash=sha256:db976be51375bca900e008941639448d148c655c9545071965d0571ecc04f5d0 \ + --hash=sha256:ded4fc0edf3de792850cb8b04bbf3c5bd725eeaf9df4c27aad510f6eed9c4e19 \ + --hash=sha256:e006ea703d5c0f3d112b51ba18af73b58209b954acfe3d8da42eacc9a00e4be6 \ + --hash=sha256:e3e5d1802cba785210a4a800e63fcee7a228649a880f3bf7f2aadccb151a834b \ + --hash=sha256:e480d3dac06c89bc2e0fd87524cc38c546ac8b4a38177650745e64acbbcfdeba \ + --hash=sha256:e50af656c15e2723eeb7279c0837e07accc594b95ec18b86821a4d44b51b24bf \ + --hash=sha256:e83ce8008b48762be296f1401f19afd9ea29f3d035d1974e0cecb74e9afbd1df \ + --hash=sha256:ed3b8281c5d0944d939c82db4ec2300409dd69ee087f7a75a94f2e301e855fb4 \ + --hash=sha256:ef250a3f5e93182193f5c927c5e9575b2cb14b80d03e258bc0b89cc5de076b60 \ + --hash=sha256:f1574566457161678297a116fa5d1556c5a4159d64c5ff7c760e7c564bf66f16 \ + --hash=sha256:f26262900edd16272b6360014495e8d68379c6c6e95983f9b7b322dc928a1194 \ + --hash=sha256:f28eac18a8733a124444643a66ac96fef2c0ad65f50034e0a043b90333dc677f \ + --hash=sha256:f54840bea73541652f1170dc63402a5b776fc851ad36a842da9e5163c1f504a0 \ + --hash=sha256:f785f44a44702dea89b28bce5bc82552490694ce4e144e21a4f0545e364d2150 \ + --hash=sha256:f7cc00089b4c21847852c0ad76fb3680f9833b855a0d30bcec94211c435bff6b \ + --hash=sha256:f95bd07f301135771559101c060f558e2cf896c7df00bec050ca7f93bf11585a \ + --hash=sha256:fc8ced733d6cd9af5e412f256a32f7c61cd2d7371280a65c689939ac4572499f \ + --hash=sha256:fd03e38068faeef937cc6761a250a4aaa015564bd0d61481fefcf15586d31825 # via # feast (pyproject.toml) # parsimonious # transformers -requests==2.32.5 \ - --hash=sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6 \ - --hash=sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf +requests==2.33.1 \ + --hash=sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517 \ + --hash=sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a # via # feast (pyproject.toml) # azure-core @@ -4888,6 +4929,7 @@ requests==2.32.5 \ # great-expectations # huggingface-hub # jupyterlab-server + # kube-authkit # kubernetes # moto # msal @@ -4912,9 +4954,9 @@ requests-toolbelt==1.0.0 \ --hash=sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6 \ --hash=sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06 # via python-keycloak -responses==0.25.8 \ - --hash=sha256:0c710af92def29c8352ceadff0c3fe340ace27cf5af1bbe46fb71275bcd2831c \ - --hash=sha256:9374d047a575c8f781b94454db5cab590b6029505f488d12899ddb10a4af1cf4 +responses==0.26.0 \ + --hash=sha256:03ec4409088cd5c66b71ecbbbd27fe2c58ddfad801c66203457b3e6a04868c37 \ + --hash=sha256:c7f6923e6343ef3682816ba421c006626777893cb0d5e1434f674b649bac9eb4 # via moto rfc3339-validator==0.1.4 \ --hash=sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b \ @@ -4932,9 +4974,9 @@ rfc3987-syntax==1.1.0 \ --hash=sha256:6c3d97604e4c5ce9f714898e05401a0445a641cfa276432b0a648c80856f6a3f \ --hash=sha256:717a62cbf33cffdd16dfa3a497d81ce48a660ea691b1ddd7be710c22f00b4a0d # via jsonschema -rich==13.9.4 \ - --hash=sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098 \ - --hash=sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90 +rich==14.3.3 \ + --hash=sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d \ + --hash=sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b # via # codeflare-sdk # fastapi-mcp @@ -5059,10 +5101,6 @@ rpds-py==0.30.0 \ # via # jsonschema # referencing -rsa==4.9.1 \ - --hash=sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762 \ - --hash=sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75 - # via google-auth rtree==1.4.1 \ --hash=sha256:12de4578f1b3381a93a655846900be4e3d5f4cd5e306b8b00aa77c1121dc7e8c \ --hash=sha256:3d46f55729b28138e897ffef32f7ce93ac335cb67f9120125ad3742a220800f0 \ @@ -5080,25 +5118,25 @@ ruamel-yaml==0.17.17 \ --hash=sha256:9751de4cbb57d4bfbf8fc394e125ed4a2f170fbff3dc3d78abf50be85924f8be \ --hash=sha256:9af3ec5d7f8065582f3aa841305465025d0afd26c5fb54e15b964e11838fc74f # via great-expectations -ruff==0.15.1 \ - --hash=sha256:1d83466455fdefe60b8d9c8df81d3c1bbb2115cede53549d3b522ce2bc703899 \ - --hash=sha256:1fe5c41ab43e3a06778844c586251eb5a510f67125427625f9eb2b9526535779 \ - --hash=sha256:3dd86dccb83cd7d4dcfac303ffc277e6048600dfc22e38158afa208e8bf94a1f \ - --hash=sha256:4ab064052c31dddada35079901592dfba2e05f5b1e43af3954aafcbc1096a5b2 \ - --hash=sha256:518f9af03bfc33c03bdb4cb63fabc935341bb7f54af500f92ac309ecfbba6330 \ - --hash=sha256:5631c940fe9fe91f817a4c2ea4e81f47bee3ca4aa646134a24374f3c19ad9454 \ - --hash=sha256:5ff7d5f0f88567850f45081fac8f4ec212be8d0b963e385c3f7d0d2eb4899416 \ - --hash=sha256:660975d9cb49b5d5278b12b03bb9951d554543a90b74ed5d366b20e2c57c2098 \ - --hash=sha256:66a6dd6df4d80dc382c6484f8ce1bcceb55c32e9f27a8b94c32f6c7331bf14fb \ - --hash=sha256:68138a4ba184b4691ccdc39f7795c66b3c68160c586519e7e8444cf5a53e1b4c \ - --hash=sha256:6a4a42cbb8af0bda9bcd7606b064d7c0bc311a88d141d02f78920be6acb5aa83 \ - --hash=sha256:92c92b003e9d4f7fbd33b1867bb15a1b785b1735069108dfc23821ba045b29bc \ - --hash=sha256:939c995e9277e63ea632cc8d3fae17aa758526f49a9a850d2e7e758bfef46602 \ - --hash=sha256:a9457e3c3291024866222b96108ab2d8265b477e5b1534c7ddb1810904858d16 \ - --hash=sha256:b101ed7cf4615bda6ffe65bdb59f964e9f4a0d3f85cbf0e54f0ab76d7b90228a \ - --hash=sha256:c590fe13fb57c97141ae975c03a1aedb3d3156030cabd740d6ff0b0d601e203f \ - --hash=sha256:c820fef9dd5d4172a6570e5721704a96c6679b80cf7be41659ed439653f62336 \ - --hash=sha256:da79f4d6a826caaea95de0237a67e33b81e6ec2e25fc7e1993a4015dffca7c61 +ruff==0.15.9 \ + --hash=sha256:058d8e99e1bfe79d8a0def0b481c56059ee6716214f7e425d8e737e412d69677 \ + --hash=sha256:0694e601c028fd97dc5c6ee244675bc241aeefced7ef80cd9c6935a871078f53 \ + --hash=sha256:29cbb1255a9797903f6dde5ba0188c707907ff44a9006eb273b5a17bfa0739a2 \ + --hash=sha256:2b0c7c341f68adb01c488c3b7d4b49aa8ea97409eae6462d860a79cf55f431b6 \ + --hash=sha256:45a70921b80e1c10cf0b734ef09421f71b5aa11d27404edc89d7e8a69505e43d \ + --hash=sha256:4965bac6ac9ea86772f4e23587746f0b7a395eccabb823eb8bfacc3fa06069f7 \ + --hash=sha256:55cc15eee27dc0eebdfcb0d185a6153420efbedc15eb1d38fe5e685657b0f840 \ + --hash=sha256:6d3fcbca7388b066139c523bda744c822258ebdcfbba7d24410c3f454cc9af71 \ + --hash=sha256:6efbe303983441c51975c243e26dff328aca11f94b70992f35b093c2e71801e1 \ + --hash=sha256:7b34a9766aeec27a222373d0b055722900fbc0582b24f39661aa96f3fe6ad901 \ + --hash=sha256:89dd695bc72ae76ff484ae54b7e8b0f6b50f49046e198355e44ea656e521fef9 \ + --hash=sha256:8e1ddb11dbd61d5983fa2d7d6370ef3eb210951e443cace19594c01c72abab4c \ + --hash=sha256:9439a342adb8725f32f92732e2bafb6d5246bd7a5021101166b223d312e8fc59 \ + --hash=sha256:9c5e6faf9d97c8edc43877c3f406f47446fc48c40e1442d58cfcdaba2acea745 \ + --hash=sha256:a6537f6eed5cda688c81073d46ffdfb962a5f29ecb6f7e770b2dc920598997ed \ + --hash=sha256:bde6ff36eaf72b700f32b7196088970bf8fdb2b917b7accd8c371bfc0fd573ec \ + --hash=sha256:ce187224ef1de1bd225bc9a152ac7102a6171107f026e81f317e4257052916d5 \ + --hash=sha256:eaf05aad70ca5b5a0a4b0e080df3a6b699803916d88f006efd1f5b46302daab8 # via feast (pyproject.toml) s3transfer==0.13.1 \ --hash=sha256:a981aa7429be23fe6dfc13e80e4020057cbab622b08c0315288758d67cabc724 \ @@ -5222,83 +5260,90 @@ scikit-learn==1.8.0 \ --hash=sha256:f984ca4b14914e6b4094c5d52a32ea16b49832c03bd17a110f004db3c223e8e1 \ --hash=sha256:fb65db5d7531bccf3a4f6bec3462223bea71384e2cda41da0f10b7c292b9e7c4 \ --hash=sha256:fe1c011a640a9f0791146011dfd3c7d9669785f9fed2b2a5f9e207536cf5c2fd - # via feast (pyproject.toml) -scipy==1.17.0 \ - --hash=sha256:00fb5f8ec8398ad90215008d8b6009c9db9fa924fd4c7d6be307c6f945f9cd73 \ - --hash=sha256:031121914e295d9791319a1875444d55079885bbae5bdc9c5e0f2ee5f09d34ff \ - --hash=sha256:0937a0b0d8d593a198cededd4c439a0ea216a3f36653901ea1f3e4be949056f8 \ - --hash=sha256:0cf46c8013fec9d3694dc572f0b54100c28405d55d3e2cb15e2895b25057996e \ - --hash=sha256:0d5018a57c24cb1dd828bcf51d7b10e65986d549f52ef5adb6b4d1ded3e32a57 \ - --hash=sha256:130d12926ae34399d157de777472bf82e9061c60cc081372b3118edacafe1d00 \ - --hash=sha256:13c4096ac6bc31d706018f06a49abe0485f96499deb82066b94d19b02f664209 \ - --hash=sha256:13e861634a2c480bd237deb69333ac79ea1941b94568d4b0efa5db5e263d4fd1 \ - --hash=sha256:1f9586a58039d7229ce77b52f8472c972448cded5736eaf102d5658bbac4c269 \ - --hash=sha256:1ff269abf702f6c7e67a4b7aad981d42871a11b9dd83c58d2d2ea624efbd1088 \ - --hash=sha256:255c0da161bd7b32a6c898e7891509e8a9289f0b1c6c7d96142ee0d2b114c2ea \ - --hash=sha256:2591060c8e648d8b96439e111ac41fd8342fdeff1876be2e19dea3fe8930454e \ - --hash=sha256:272a9f16d6bb4667e8b50d25d71eddcc2158a214df1b566319298de0939d2ab7 \ - --hash=sha256:2abd71643797bd8a106dff97894ff7869eeeb0af0f7a5ce02e4227c6a2e9d6fd \ - --hash=sha256:2b531f57e09c946f56ad0b4a3b2abee778789097871fc541e267d2eca081cff1 \ - --hash=sha256:30509da9dbec1c2ed8f168b8d8aa853bc6723fede1dbc23c7d43a56f5ab72a67 \ - --hash=sha256:33af70d040e8af9d5e7a38b5ed3b772adddd281e3062ff23fec49e49681c38cf \ - --hash=sha256:357ca001c6e37601066092e7c89cca2f1ce74e2a520ca78d063a6d2201101df2 \ - --hash=sha256:3625c631a7acd7cfd929e4e31d2582cf00f42fcf06011f59281271746d77e061 \ - --hash=sha256:363ad4ae2853d88ebcde3ae6ec46ccca903ea9835ee8ba543f12f575e7b07e4e \ - --hash=sha256:40052543f7bbe921df4408f46003d6f01c6af109b9e2c8a66dd1cf6cf57f7d5d \ - --hash=sha256:423ca1f6584fc03936972b5f7c06961670dbba9f234e71676a7c7ccf938a0d61 \ - --hash=sha256:474da16199f6af66601a01546144922ce402cb17362e07d82f5a6cf8f963e449 \ - --hash=sha256:4e00562e519c09da34c31685f6acc3aa384d4d50604db0f245c14e1b4488bfa2 \ - --hash=sha256:5194c445d0a1c7a6c1a4a4681b6b7c71baad98ff66d96b949097e7513c9d6742 \ - --hash=sha256:5fb10d17e649e1446410895639f3385fd2bf4c3c7dfc9bea937bddcbc3d7b9ba \ - --hash=sha256:65ec32f3d32dfc48c72df4291345dae4f048749bc8d5203ee0a3f347f96c5ce6 \ - --hash=sha256:6680f2dfd4f6182e7d6db161344537da644d1cf85cf293f015c60a17ecf08752 \ - --hash=sha256:6e886000eb4919eae3a44f035e63f0fd8b651234117e8f6f29bad1cd26e7bc45 \ - --hash=sha256:7204fddcbec2fe6598f1c5fdf027e9f259106d05202a959a9f1aecf036adc9f6 \ - --hash=sha256:819fc26862b4b3c73a60d486dbb919202f3d6d98c87cf20c223511429f2d1a97 \ - --hash=sha256:8547e7c57f932e7354a2319fab613981cde910631979f74c9b542bb167a8b9db \ - --hash=sha256:85b0ac3ad17fa3be50abd7e69d583d98792d7edc08367e01445a1e2076005379 \ - --hash=sha256:87b411e42b425b84777718cc41516b8a7e0795abfa8e8e1d573bf0ef014f0812 \ - --hash=sha256:88c22af9e5d5a4f9e027e26772cc7b5922fab8bcc839edb3ae33de404feebd9e \ - --hash=sha256:9244608d27eafe02b20558523ba57f15c689357c85bdcfe920b1828750aa26eb \ - --hash=sha256:979c3a0ff8e5ba254d45d59ebd38cde48fce4f10b5125c680c7a4bfe177aab07 \ - --hash=sha256:9eeb9b5f5997f75507814ed9d298ab23f62cf79f5a3ef90031b1ee2506abdb5b \ - --hash=sha256:9fad7d3578c877d606b1150135c2639e9de9cecd3705caa37b66862977cc3e72 \ - --hash=sha256:a38c3337e00be6fd8a95b4ed66b5d988bac4ec888fd922c2ea9fe5fb1603dd67 \ - --hash=sha256:aabf057c632798832f071a8dde013c2e26284043934f53b00489f1773b33527e \ - --hash=sha256:c17514d11b78be8f7e6331b983a65a7f5ca1fd037b95e27b280921fe5606286a \ - --hash=sha256:c5e8647f60679790c2f5c76be17e2e9247dc6b98ad0d3b065861e082c56e078d \ - --hash=sha256:cacbaddd91fcffde703934897c5cd2c7cb0371fac195d383f4e1f1c5d3f3bd04 \ - --hash=sha256:d7425fcafbc09a03731e1bc05581f5fad988e48c6a861f441b7ab729a49a55ea \ - --hash=sha256:dac97a27520d66c12a34fd90a4fe65f43766c18c0d6e1c0a80f114d2260080e4 \ - --hash=sha256:dbf133ced83889583156566d2bdf7a07ff89228fe0c0cb727f777de92092ec6b \ - --hash=sha256:e8c0b331c2c1f531eb51f1b4fc9ba709521a712cce58f1aa627bc007421a5306 \ - --hash=sha256:eb2651271135154aa24f6481cbae5cc8af1f0dd46e6533fb7b56aa9727b6a232 \ - --hash=sha256:ebb7446a39b3ae0fe8f416a9a3fdc6fba3f11c634f680f16a239c5187bc487c0 \ - --hash=sha256:ec0827aa4d36cb79ff1b81de898e948a51ac0b9b1c43e4a372c0508c38c0f9a3 \ - --hash=sha256:edce1a1cf66298cccdc48a1bdf8fb10a3bf58e8b58d6c3883dd1530e103f87c0 \ - --hash=sha256:eec3842ec9ac9de5917899b277428886042a93db0b227ebbe3a333b64ec7643d \ - --hash=sha256:ef28d815f4d2686503e5f4f00edc387ae58dfd7a2f42e348bb53359538f01558 \ - --hash=sha256:f2a4942b0f5f7c23c7cd641a0ca1955e2ae83dedcff537e3a0259096635e186b \ - --hash=sha256:f3cd947f20fe17013d401b64e857c6b2da83cae567adbb75b9dcba865abc66d8 \ - --hash=sha256:f603d8a5518c7426414d1d8f82e253e454471de682ce5e39c29adb0df1efb86b \ - --hash=sha256:f7df7941d71314e60a481e02d5ebcb3f0185b8d799c70d03d8258f6c80f3d467 \ - --hash=sha256:f9eb55bb97d00f8b7ab95cb64f873eb0bf54d9446264d9f3609130381233483f \ - --hash=sha256:fc02c37a5639ee67d8fb646ffded6d793c06c5622d36b35cfa8fe5ececb8f042 \ - --hash=sha256:fe508b5690e9eaaa9467fc047f833af58f1152ae51a0d0aed67aa5801f4dd7d6 + # via + # feast (pyproject.toml) + # sentence-transformers +scipy==1.17.1 \ + --hash=sha256:010f4333c96c9bb1a4516269e33cb5917b08ef2166d5556ca2fd9f082a9e6ea0 \ + --hash=sha256:02ae3b274fde71c5e92ac4d54bc06c42d80e399fec704383dcd99b301df37458 \ + --hash=sha256:08b900519463543aa604a06bec02461558a6e1cef8fdbb8098f77a48a83c8118 \ + --hash=sha256:131f5aaea57602008f9822e2115029b55d4b5f7c070287699fe45c661d051e39 \ + --hash=sha256:158dd96d2207e21c966063e1635b1063cd7787b627b6f07305315dd73d9c679e \ + --hash=sha256:1cc682cea2ae55524432f3cdff9e9a3be743d52a7443d0cba9017c23c87ae2f6 \ + --hash=sha256:1f95b894f13729334fb990162e911c9e5dc1ab390c58aa6cbecb389c5b5e28ec \ + --hash=sha256:200e1050faffacc162be6a486a984a0497866ec54149a01270adc8a59b7c7d21 \ + --hash=sha256:2040ad4d1795a0ae89bfc7e8429677f365d45aa9fd5e4587cf1ea737f927b4a1 \ + --hash=sha256:2b64ca7d4aee0102a97f3ba22124052b4bd2152522355073580bf4845e2550b6 \ + --hash=sha256:2ceb2d3e01c5f1d83c4189737a42d9cb2fc38a6eeed225e7515eef71ad301dce \ + --hash=sha256:35c3a56d2ef83efc372eaec584314bd0ef2e2f0d2adb21c55e6ad5b344c0dcb8 \ + --hash=sha256:37425bc9175607b0268f493d79a292c39f9d001a357bebb6b88fdfaff13f6448 \ + --hash=sha256:3877ac408e14da24a6196de0ddcace62092bfc12a83823e92e49e40747e52c19 \ + --hash=sha256:3fd1fcdab3ea951b610dc4cef356d416d5802991e7e32b5254828d342f7b7e0b \ + --hash=sha256:41b71f4a3a4cab9d366cd9065b288efc4d4f3c0b37a91a8e0947fb5bd7f31d87 \ + --hash=sha256:43af8d1f3bea642559019edfe64e9b11192a8978efbd1539d7bc2aaa23d92de4 \ + --hash=sha256:45abad819184f07240d8a696117a7aacd39787af9e0b719d00285549ed19a1e9 \ + --hash=sha256:4b400bdc6f79fa02a4d86640310dde87a21fba0c979efff5248908c6f15fad1b \ + --hash=sha256:4eb6c25dd62ee8d5edf68a8e1c171dd71c292fdae95d8aeb3dd7d7de4c364082 \ + --hash=sha256:581b2264fc0aa555f3f435a5944da7504ea3a065d7029ad60e7c3d1ae09c5464 \ + --hash=sha256:5cf36e801231b6a2059bf354720274b7558746f3b1a4efb43fcf557ccd484a87 \ + --hash=sha256:5e3c5c011904115f88a39308379c17f91546f77c1667cea98739fe0fccea804c \ + --hash=sha256:6609bc224e9568f65064cfa72edc0f24ee6655b47575954ec6339534b2798369 \ + --hash=sha256:6e3dcd57ab780c741fde8dc68619de988b966db759a3c3152e8e9142c26295ad \ + --hash=sha256:6fac755ca3d2c3edcb22f479fceaa241704111414831ddd3bc6056e18516892f \ + --hash=sha256:744b2bf3640d907b79f3fd7874efe432d1cf171ee721243e350f55234b4cec4c \ + --hash=sha256:74cbb80d93260fe2ffa334efa24cb8f2f0f622a9b9febf8b483c0b865bfb3475 \ + --hash=sha256:766e0dc5a616d026a3a1cffa379af959671729083882f50307e18175797b3dfd \ + --hash=sha256:7bdf2da170b67fdf10bca777614b1c7d96ae3ca5794fd9587dce41eb2966e866 \ + --hash=sha256:7ff200bf9d24f2e4d5dc6ee8c3ac64d739d3a89e2326ba68aaf6c4a2b838fd7d \ + --hash=sha256:844e165636711ef41f80b4103ed234181646b98a53c8f05da12ca5ca289134f6 \ + --hash=sha256:8a604bae87c6195d8b1045eddece0514d041604b14f2727bbc2b3020172045eb \ + --hash=sha256:94055a11dfebe37c656e70317e1996dc197e1a15bbcc351bcdd4610e128fe1ca \ + --hash=sha256:95d8e012d8cb8816c226aef832200b1d45109ed4464303e997c5b13122b297c0 \ + --hash=sha256:9cdc1a2fcfd5c52cfb3045feb399f7b3ce822abdde3a193a6b9a60b3cb5854ca \ + --hash=sha256:9ecb4efb1cd6e8c4afea0daa91a87fbddbce1b99d2895d151596716c0b2e859d \ + --hash=sha256:a3472cfbca0a54177d0faa68f697d8ba4c80bbdc19908c3465556d9f7efce9ee \ + --hash=sha256:a4328d245944d09fd639771de275701ccadf5f781ba0ff092ad141e017eccda4 \ + --hash=sha256:a48a72c77a310327f6a3a920092fa2b8fd03d7deaa60f093038f22d98e096717 \ + --hash=sha256:a720477885a9d2411f94a93d16f9d89bad0f28ca23c3f8daa521e2dcc3f44d49 \ + --hash=sha256:a77cbd07b940d326d39a1d1b37817e2ee4d79cb30e7338f3d0cddffae70fcaa2 \ + --hash=sha256:a9956e4d4f4a301ebf6cde39850333a6b6110799d470dbbb1e25326ac447f52a \ + --hash=sha256:adb2642e060a6549c343603a3851ba76ef0b74cc8c079a9a58121c7ec9fe2350 \ + --hash=sha256:beeda3d4ae615106d7094f7e7cef6218392e4465cc95d25f900bebabfded0950 \ + --hash=sha256:c80be5ede8f3f8eded4eff73cc99a25c388ce98e555b17d31da05287015ffa5b \ + --hash=sha256:cc90d2e9c7e5c7f1a482c9875007c095c3194b1cfedca3c2f3291cdc2bc7c086 \ + --hash=sha256:cd96a1898c0a47be4520327e01f874acfd61fb48a9420f8aa9f6483412ffa444 \ + --hash=sha256:d2650c1fb97e184d12d8ba010493ee7b322864f7d3d00d3f9bb97d9c21de4068 \ + --hash=sha256:d30e57c72013c2a4fe441c2fcb8e77b14e152ad48b5464858e07e2ad9fbfceff \ + --hash=sha256:d59c30000a16d8edc7e64152e30220bfbd724c9bbb08368c054e24c651314f0a \ + --hash=sha256:dbc12c9f3d185f5c737d801da555fb74b3dcfa1a50b66a1a93e09190f41fab50 \ + --hash=sha256:e18f12c6b0bc5a592ed23d3f7b891f68fd7f8241d69b7883769eb5d5dfb52696 \ + --hash=sha256:e19ebea31758fac5893a2ac360fedd00116cbb7628e650842a6691ba7ca28a21 \ + --hash=sha256:e30bdeaa5deed6bc27b4cc490823cd0347d7dae09119b8803ae576ea0ce52e4c \ + --hash=sha256:eb092099205ef62cd1782b006658db09e2fed75bffcae7cc0d44052d8aa0f484 \ + --hash=sha256:eee2cfda04c00a857206a4330f0c5e3e56535494e30ca445eb19ec624ae75118 \ + --hash=sha256:f4115102802df98b2b0db3cce5cb9b92572633a1197c77b7553e5203f284a5b3 \ + --hash=sha256:f590cd684941912d10becc07325a3eeb77886fe981415660d9265c4c418d0bea \ + --hash=sha256:f8885db0bc2bffa59d5c1b72fad7a6a92d3e80e7257f967dd81abb553a90d293 \ + --hash=sha256:fcb310ddb270a06114bb64bbe53c94926b943f5b7f0842194d585c65eb4edd76 # via # docling # easyocr # great-expectations # scikit-image # scikit-learn -semchunk==2.2.2 \ - --hash=sha256:940e89896e64eeb01de97ba60f51c8c7b96c6a3951dfcf574f25ce2146752f52 \ - --hash=sha256:94ca19020c013c073abdfd06d79a7c13637b91738335f3b8cdb5655ee7cc94d2 + # sentence-transformers +semchunk==3.2.5 \ + --hash=sha256:ee15e9a06a69a411937dd8fcf0a25d7ef389c5195863140436872a02c95b0218 \ + --hash=sha256:fd09cc5f380bd010b8ca773bd81893f7eaf11d37dd8362a83d46cedaf5dae076 # via docling-core send2trash==2.1.0 \ --hash=sha256:0da2f112e6d6bb22de6aa6daa7e144831a4febf2a87261451c4ad849fe9a873c \ --hash=sha256:1c72b39f09457db3c05ce1d19158c2cbef4c32b8bedd02c155e49282b7ea7459 # via jupyter-server +sentence-transformers==5.3.0 \ + --hash=sha256:414a0a881f53a4df0e6cbace75f823bfcb6b94d674c42a384b498959b7c065e2 \ + --hash=sha256:dca6b98db790274a68185d27a65801b58b4caf653a4e556b5f62827509347c7d + # via feast (pyproject.toml) setuptools==80.10.2 \ --hash=sha256:8b0e9d10c784bf7d262c4e5ec5d4ec94127ce206e8738f29a437945fbc219b70 \ --hash=sha256:95b30ddfb717250edb492926c92b5221f7ef3fbcc2b07579bcd4a27da21d0173 @@ -5312,6 +5357,7 @@ setuptools==80.10.2 \ # pydata-google-auth # pymilvus # singlestoredb + # torch shapely==2.1.2 \ --hash=sha256:0036ac886e0923417932c2e6369b6c52e38e0ff5d9120b90eef5cd9a5fc5cae9 \ --hash=sha256:01d0d304b25634d60bd7cf291828119ab55a3bab87dc4af1e44b07fb225f188b \ @@ -5396,9 +5442,9 @@ six==1.17.0 \ # python-dateutil # rfc3339-validator # thriftpy2 -smart-open==7.5.0 \ - --hash=sha256:87e695c5148bbb988f15cec00971602765874163be85acb1c9fb8abc012e6599 \ - --hash=sha256:f394b143851d8091011832ac8113ea4aba6b92e6c35f6e677ddaaccb169d7cb9 +smart-open==7.5.1 \ + --hash=sha256:3e07cbbd9c8a908bcb8e25d48becf1a5cbb4886fa975e9f34c672ed171df2318 \ + --hash=sha256:3f08e16827c4733699e6b2cc40328a3568f900cb12ad9a3ad233ba6c872d9fe7 # via ray sniffio==1.3.1 \ --hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \ @@ -5411,33 +5457,32 @@ snowballstemmer==3.0.1 \ --hash=sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064 \ --hash=sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895 # via sphinx -snowflake-connector-python[pandas]==4.0.0 \ - --hash=sha256:0c0204f639fddc58452b0362ba8821cd5153bd7aaa89434d59104bc39f4fa176 \ - --hash=sha256:1ca2503f705627f7e045da6254d97c37210a3b0a18b43d0f1b29616d0c7aaa01 \ - --hash=sha256:1fea301e3d1e8022b9f2ff87dc3be139d5ed7be5e85fab8a6c59d400a02e6d58 \ - --hash=sha256:2c3e0f6d103fe67c975550ed424f579d3e7ae503d56467e5549f3a1a1e0e8f24 \ - --hash=sha256:4106a66e770e564b3037457b7b01b15ca28aee61afb88560b664aa8af439b533 \ - --hash=sha256:4b10a865c4a5e1fa60c365c7fe41e0433605e6e5edc824e8730a9038f330b3a6 \ - --hash=sha256:4e8c3d2ea4055dd4aecc93514030341e300f557f2e86ca21eb47568c461a6f56 \ - --hash=sha256:54e648bbd506a0f2f8076f9eafe231b2d4284b1a884528c3a0690391ab2bb54e \ - --hash=sha256:5ad5d0f1ebcb2c6b7a7859ee3d4e02203087e40faae539a336bbcb45a3660777 \ - --hash=sha256:65e4e36dd1b0c7235d84cddef8a3c97c5ea0dc8fea85e31e45fc485000b77a83 \ - --hash=sha256:7789df78f7c7abfb351f2709258d05a94652cfe3c2c617fb15f15a11fc1b7b25 \ - --hash=sha256:79b4e7a58e600419f083a63f99e5da89d438faddae1d344e9f9b003754fa231b \ - --hash=sha256:835161dd46ef8f5fc9d2f135ca654c2f3fbdf57b035d3e1980506aa8eac671dc \ - --hash=sha256:985cd2f8b6b2e663ef30dc59f1ba8c1becff7683ebc51bd7f14b962407a9fa88 \ - --hash=sha256:a790f06808e4481c23cfed1396d2c9a786060ddd62408b1fda1a63e1e6bc4b07 \ - --hash=sha256:af89a9e1355ea4dac7927d2f9bc15b2c81e381ad8bcdf8954ba3dd457a4d51d6 \ - --hash=sha256:b95b29589293ad14d0367428518141995524cfc7dc47d8f3d0c47010f5d974da \ - --hash=sha256:bfd3b8523d7adc830f99c5c4c635689ceca61700a05368d5bbb34c6811f2ec54 \ - --hash=sha256:cd23bff2abc74e34c6123a181c004ead9e6cc8ef2661250892afd64bad24533c \ - --hash=sha256:e376bad497c7932448cc29058e75737f02b3f0e25569de9e4ff0616944b4ceba \ - --hash=sha256:e6132986d6965e4005b0167270612fbc7fa4bc4ef42726a40b85a8f57475a78d \ - --hash=sha256:e8d5b66f283967c700fff2303ac5e52d1a3cf41990a634f121ac8b1f1cd9af10 \ - --hash=sha256:eb1bb9729fd3bfaae22364491cec4816dda380376ac3be4559a6f6949c6d2833 \ - --hash=sha256:ebbdeec0d65c2e3f648c8b05839001c062984959417902717f7fc6eed983211d \ - --hash=sha256:f67d844241a6fed764a8f04d32c0273aedf9159d5162b764748526277c7f8831 \ - --hash=sha256:fd0d2d2c5cfd15f041e8522f5f8bdad0be4de7d805dd1646377fccd6bd404fa8 +snowflake-connector-python[pandas]==4.4.0 \ + --hash=sha256:16fdca775f7ca5ce4a973c07c434f5ab72bef5284e81a5e4ae2fb4d54d28965c \ + --hash=sha256:19d0c1ed033abae715a71b74c53010b180a5247c6924f851e4f7d0b0d58066c4 \ + --hash=sha256:2a6f6a514a10c3bb2d4554132f0b639f43d7e9fbb73fa1fae1c8a75333102686 \ + --hash=sha256:307f41326c702f6976746d2001dacf35adaf567f3f12afb3a5778fbb063c7241 \ + --hash=sha256:43e1a2f3ac51d24406d4eb0c23a8ceb9d6f5cb4854c941e5e1375d8c481e2844 \ + --hash=sha256:52efe2d6543a09807283748dd50a36ec01d52b4f342868132f8f9856b9c95a42 \ + --hash=sha256:56ff04dd9e17edc82128f412aa3776687dc94088f3d6b9144971e169952623cb \ + --hash=sha256:648f49029d699591af0f253e81c5bf60efc4411c7b0149ef074a59a038210a3b \ + --hash=sha256:693a1bef97509f09b7e6f42ea6f743d27819413c04fb3dc543b060d029871c56 \ + --hash=sha256:70d4051e2d9c87258b02672e17e21f5873e0cb49ff9705f6194ccfa25ac0d5fd \ + --hash=sha256:7c2984663a733d06c979aa6c8c1d7691621ec0d3521ef345d57c869ff2f1c4b2 \ + --hash=sha256:8304b4818d3e9de552dcfbdd0bca61bae1583e1c9794e242e58fe44bce701604 \ + --hash=sha256:85a01338d282423611f357cd5392dca2219bbda9a66b44761b11d6ae8ebf1e50 \ + --hash=sha256:96fdca994c4d9f7780e82fc7b4bd3398d856b43de3bae57d44e242ff435a2431 \ + --hash=sha256:9b1a28f843c1c0b582db7854789525d0c8aac4ea5c56e31113684e38220d0af9 \ + --hash=sha256:9fa43d330389df27024757c4f97dabddafbedc74b8bcc189b6a86e8b4d036014 \ + --hash=sha256:a088f108da4653ad1396ddb63a1c757ad614d0862c38f6f69cc77344bdcfeccb \ + --hash=sha256:b9f0ac0c00075321e1720d3876e936ee0256f54832e7463c5193a8dfa54913d5 \ + --hash=sha256:c828248214a49f77b903e05acf887d3ccb9d958b5a979f2ed3663bba1bd0f2b3 \ + --hash=sha256:d6fd334e4d8df7fcb30e6746e5ade845e82de2942268862aa8bce974ae2b86a2 \ + --hash=sha256:d8ac1659c8e588b9502f8d3d03c1ded2f274de0da9c09e62fe007cba5b46d6a5 \ + --hash=sha256:e8e7ce0e8b33aec8b1fc6741eb51dbeb54e2c3a6d282a0d459c355a85f089b08 \ + --hash=sha256:ea6e4083ebea0a814b46f029d64a2fb0ba6e7732952cd8af4406041708ce0e21 \ + --hash=sha256:f5d0e90e68a899c13fda5ca842ff77b5759b1674adf2c72702d3c2b53ca9d27b \ + --hash=sha256:fb628d5ea1999e23bfbaabce4125eb44d56605ca5634b8b1d6092ab22d555598 # via feast (pyproject.toml) sortedcontainers==2.4.0 \ --hash=sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88 \ @@ -5475,135 +5520,107 @@ sphinxcontrib-serializinghtml==2.0.0 \ --hash=sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331 \ --hash=sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d # via sphinx -sqlalchemy[mypy]==2.0.46 \ - --hash=sha256:09168817d6c19954d3b7655da6ba87fcb3a62bb575fb396a81a8b6a9fadfe8b5 \ - --hash=sha256:0cc3117db526cad3e61074100bd2867b533e2c7dc1569e95c14089735d6fb4fe \ - --hash=sha256:181903fe8c1b9082995325f1b2e84ac078b1189e2819380c2303a5f90e114a62 \ - --hash=sha256:1bc3f601f0a818d27bfe139f6766487d9c88502062a2cd3a7ee6c342e81d5047 \ - --hash=sha256:1e6199143d51e3e1168bedd98cc698397404a8f7508831b81b6a29b18b051069 \ - --hash=sha256:2347c3f0efc4de367ba00218e0ae5c4ba2306e47216ef80d6e31761ac97cb0b9 \ - --hash=sha256:261c4b1f101b4a411154f1da2b76497d73abbfc42740029205d4d01fa1052684 \ - --hash=sha256:33e462154edb9493f6c3ad2125931e273bbd0be8ae53f3ecd1c161ea9a1dd366 \ - --hash=sha256:37fee2164cf21417478b6a906adc1a91d69ae9aba8f9533e67ce882f4bb1de53 \ - --hash=sha256:3a9a72b0da8387f15d5810f1facca8f879de9b85af8c645138cba61ea147968c \ - --hash=sha256:3aac08f7546179889c62b53b18ebf1148b10244b3405569c93984b0388d016a7 \ - --hash=sha256:3c32e993bc57be6d177f7d5d31edb93f30726d798ad86ff9066d75d9bf2e0b6b \ - --hash=sha256:412f26bb4ba942d52016edc8d12fb15d91d3cd46b0047ba46e424213ad407bcb \ - --hash=sha256:42a1643dc5427b69aca967dae540a90b0fbf57eaf248f13a90ea5930e0966863 \ - --hash=sha256:4396c948d8217e83e2c202fbdcc0389cf8c93d2c1c5e60fa5c5a955eae0e64be \ - --hash=sha256:4dafb537740eef640c4d6a7c254611dca2df87eaf6d14d6a5fca9d1f4c3fc0fa \ - --hash=sha256:4f52f7291a92381e9b4de9050b0a65ce5d6a763333406861e33906b8aa4906bf \ - --hash=sha256:52fe29b3817bd191cc20bad564237c808967972c97fa683c04b28ec8979ae36f \ - --hash=sha256:56bdd261bfd0895452006d5316cbf35739c53b9bb71a170a331fa0ea560b2ada \ - --hash=sha256:585af6afe518732d9ccd3aea33af2edaae4a7aa881af5d8f6f4fe3a368699597 \ - --hash=sha256:590be24e20e2424a4c3c1b0835e9405fa3d0af5823a1a9fc02e5dff56471515f \ - --hash=sha256:64901e08c33462acc9ec3bad27fc7a5c2b6491665f2aa57564e57a4f5d7c52ad \ - --hash=sha256:6ac245604295b521de49b465bab845e3afe6916bcb2147e5929c8041b4ec0545 \ - --hash=sha256:6f827fd687fa1ba7f51699e1132129eac8db8003695513fcf13fc587e1bd47a5 \ - --hash=sha256:70ed2830b169a9960193f4d4322d22be5c0925357d82cbf485b3369893350908 \ - --hash=sha256:716be5bcabf327b6d5d265dbdc6213a01199be587224eb991ad0d37e83d728fd \ - --hash=sha256:7568fe771f974abadce52669ef3a03150ff03186d8eb82613bc8adc435a03f01 \ - --hash=sha256:77f8071d8fbcbb2dd11b7fd40dedd04e8ebe2eb80497916efedba844298065ef \ - --hash=sha256:82ec52100ec1e6ec671563bbd02d7c7c8d0b9e71a0723c72f22ecf52d1755330 \ - --hash=sha256:895296687ad06dc9b11a024cf68e8d9d3943aa0b4964278d2553b86f1b267735 \ - --hash=sha256:8d3b44b3d0ab2f1319d71d9863d76eeb46766f8cf9e921ac293511804d39813f \ - --hash=sha256:8d679b5f318423eacb61f933a9a0f75535bfca7056daeadbf6bd5bcee6183aee \ - --hash=sha256:8e84b09a9b0f19accedcbeff5c2caf36e0dd537341a33aad8d680336152dc34e \ - --hash=sha256:9094c8b3197db12aa6f05c51c05daaad0a92b8c9af5388569847b03b1007fb1b \ - --hash=sha256:90bde6c6b1827565a95fde597da001212ab436f1b2e0c2dcc7246e14db26e2a3 \ - --hash=sha256:9397b381dcee8a2d6b99447ae85ea2530dcac82ca494d1db877087a13e38926d \ - --hash=sha256:93a12da97cca70cea10d4b4fc602589c4511f96c1f8f6c11817620c021d21d00 \ - --hash=sha256:93bb0aae40b52c57fd74ef9c6933c08c040ba98daf23ad33c3f9893494b8d3ce \ - --hash=sha256:94b1e5f3a5f1ff4f42d5daab047428cd45a3380e51e191360a35cef71c9a7a2a \ - --hash=sha256:965c62be8256d10c11f8907e7a8d3e18127a4c527a5919d85fa87fd9ecc2cfdc \ - --hash=sha256:96c7cca1a4babaaf3bfff3e4e606e38578856917e52f0384635a95b226c87764 \ - --hash=sha256:9bcdce05f056622a632f1d44bb47dbdb677f58cad393612280406ce37530eb6d \ - --hash=sha256:9d80ea2ac519c364a7286e8d765d6cd08648f5b21ca855a8017d9871f075542d \ - --hash=sha256:a1e8cc6cc01da346dc92d9509a63033b9b1bda4fed7a7a7807ed385c7dccdc10 \ - --hash=sha256:ab65cb2885a9f80f979b85aa4e9c9165a31381ca322cbde7c638fe6eefd1ec39 \ - --hash=sha256:af865c18752d416798dae13f83f38927c52f085c52e2f32b8ab0fef46fdd02c2 \ - --hash=sha256:b1e14b2f6965a685c7128bd315e27387205429c2e339eeec55cb75ca4ab0ea2e \ - --hash=sha256:b2a9f9aee38039cf4755891a1e50e1effcc42ea6ba053743f452c372c3152b1b \ - --hash=sha256:be6c0466b4c25b44c5d82b0426b5501de3c424d7a3220e86cd32f319ba56798e \ - --hash=sha256:c4e2cc868b7b5208aec6c960950b7bb821f82c2fe66446c92ee0a571765e91a5 \ - --hash=sha256:c805fa6e5d461329fa02f53f88c914d189ea771b6821083937e79550bf31fc19 \ - --hash=sha256:cf36851ee7219c170bb0793dbc3da3e80c582e04a5437bc601bfe8c85c9216d7 \ - --hash=sha256:db23b1bf8cfe1f7fda19018e7207b20cdb5168f83c437ff7e95d19e39289c447 \ - --hash=sha256:e0c05aff5c6b1bb5fb46a87e0f9d2f733f83ef6cbbbcd5c642b6c01678268061 \ - --hash=sha256:e8ac45e8f4eaac0f9f8043ea0e224158855c6a4329fd4ee37c45c61e3beb518e \ - --hash=sha256:ea3cd46b6713a10216323cda3333514944e510aa691c945334713fca6b5279ff \ - --hash=sha256:ebf7e1e78af38047e08836d33502c7a278915698b7c2145d045f780201679999 \ - --hash=sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e \ - --hash=sha256:ff33c6e6ad006bbc0f34f5faf941cfc62c45841c64c0a058ac38c799f15b5ede +sqlalchemy[mypy]==2.0.48 \ + --hash=sha256:01f6bbd4308b23240cf7d3ef117557c8fd097ec9549d5d8a52977544e35b40ad \ + --hash=sha256:07edba08061bc277bfdc772dd2a1a43978f5a45994dd3ede26391b405c15221e \ + --hash=sha256:10853a53a4a00417a00913d270dddda75815fcb80675874285f41051c094d7dd \ + --hash=sha256:1182437cb2d97988cfea04cf6cdc0b0bb9c74f4d56ec3d08b81e23d621a28cc6 \ + --hash=sha256:144921da96c08feb9e2b052c5c5c1d0d151a292c6135623c6b2c041f2a45f9e0 \ + --hash=sha256:1a89ce07ad2d4b8cfc30bd5889ec40613e028ed80ef47da7d9dd2ce969ad30e0 \ + --hash=sha256:1b4c575df7368b3b13e0cebf01d4679f9a28ed2ae6c1cd0b1d5beffb6b2007dc \ + --hash=sha256:1ccd42229aaac2df431562117ac7e667d702e8e44afdb6cf0e50fa3f18160f0b \ + --hash=sha256:2645b7d8a738763b664a12a1542c89c940daa55196e8d73e55b169cc5c99f65f \ + --hash=sha256:288937433bd44e3990e7da2402fabc44a3c6c25d3704da066b85b89a85474ae0 \ + --hash=sha256:34634e196f620c7a61d18d5cf7dc841ca6daa7961aed75d532b7e58b309ac894 \ + --hash=sha256:348174f228b99f33ca1f773e85510e08927620caa59ffe7803b37170df30332b \ + --hash=sha256:36ac4ddc3d33e852da9cb00ffb08cea62ca05c39711dc67062ca2bb1fae35fd8 \ + --hash=sha256:3713e21ea67bca727eecd4a24bf68bcd414c403faae4989442be60994301ded0 \ + --hash=sha256:389b984139278f97757ea9b08993e7b9d1142912e046ab7d82b3fbaeb0209131 \ + --hash=sha256:426c5ca86415d9b8945c7073597e10de9644802e2ff502b8e1f11a7a2642856b \ + --hash=sha256:4599a95f9430ae0de82b52ff0d27304fe898c17cb5f4099f7438a51b9998ac77 \ + --hash=sha256:49b7bddc1eebf011ea5ab722fdbe67a401caa34a350d278cc7733c0e88fecb1f \ + --hash=sha256:53667b5f668991e279d21f94ccfa6e45b4e3f4500e7591ae59a8012d0f010dcb \ + --hash=sha256:546572a1793cc35857a2ffa1fe0e58571af1779bcc1ffa7c9fb0839885ed69a9 \ + --hash=sha256:583849c743e0e3c9bb7446f5b5addeacedc168d657a69b418063dfdb2d90081c \ + --hash=sha256:5aee45fd2c6c0f2b9cdddf48c48535e7471e42d6fb81adfde801da0bd5b93241 \ + --hash=sha256:5b193a7e29fd9fa56e502920dca47dffe60f97c863494946bd698c6058a55658 \ + --hash=sha256:5ca74f37f3369b45e1f6b7b06afb182af1fd5dde009e4ffd831830d98cbe5fe7 \ + --hash=sha256:68549c403f79a8e25984376480959975212a670405e3913830614432b5daa07a \ + --hash=sha256:69f5bc24904d3bc3640961cddd2523e361257ef68585d6e364166dfbe8c78fae \ + --hash=sha256:6bb85c546591569558571aa1b06aba711b26ae62f111e15e56136d69920e1616 \ + --hash=sha256:6f7b7243850edd0b8b97043f04748f31de50cf426e939def5c16bedb540698f7 \ + --hash=sha256:7001dc9d5f6bb4deb756d5928eaefe1930f6f4179da3924cbd95ee0e9f4dce89 \ + --hash=sha256:7a936f1bb23d370b7c8cc079d5fce4c7d18da87a33c6744e51a93b0f9e97e9b3 \ + --hash=sha256:7c998f2ace8bf76b453b75dbcca500d4f4b9dd3908c13e89b86289b37784848b \ + --hash=sha256:7cddca31edf8b0653090cbb54562ca027c421c58ddde2c0685f49ff56a1690e0 \ + --hash=sha256:8183dc57ae7d9edc1346e007e840a9f3d6aa7b7f165203a99e16f447150140d2 \ + --hash=sha256:82745b03b4043e04600a6b665cb98697c4339b24e34d74b0a2ac0a2488b6f94d \ + --hash=sha256:841a94c66577661c1f088ac958cd767d7c9bf507698f45afffe7a4017049de76 \ + --hash=sha256:858e433f12b0e5b3ed2f8da917433b634f4937d0e8793e5cb33c54a1a01df565 \ + --hash=sha256:908a3fa6908716f803b86896a09a2c4dde5f5ce2bb07aacc71ffebb57986ce99 \ + --hash=sha256:9764014ef5e58aab76220c5664abb5d47d5bc858d9debf821e55cfdd0f128485 \ + --hash=sha256:9c7d0a77e36b5f4b01ca398482230ab792061d243d715299b44a0b55c89fe617 \ + --hash=sha256:a5b429eb84339f9f05e06083f119ad814e6d85e27ecbdf9c551dfdbb128eaf8a \ + --hash=sha256:a66fe406437dd65cacd96a72689a3aaaecaebbcd62d81c5ac1c0fdbeac835096 \ + --hash=sha256:a6b764fb312bd35e47797ad2e63f0d323792837a6ac785a4ca967019357d2bc7 \ + --hash=sha256:b19151e76620a412c2ac1c6f977ab1b9fa7ad43140178345136456d5265b32ed \ + --hash=sha256:b8438ec5594980d405251451c5b7ea9aa58dda38eb7ac35fb7e4c696712ee24f \ + --hash=sha256:b8fc3454b4f3bd0a368001d0e968852dad45a873f8b4babd41bc302ec851a099 \ + --hash=sha256:bcb8ebbf2e2c36cfe01a94f2438012c6a9d494cf80f129d9753bcdf33bfc35a6 \ + --hash=sha256:d404dc897ce10e565d647795861762aa2d06ca3f4a728c5e9a835096c7059018 \ + --hash=sha256:d612c976cbc2d17edfcc4c006874b764e85e990c29ce9bd411f926bbfb02b9a2 \ + --hash=sha256:d64177f443594c8697369c10e4bbcac70ef558e0f7921a1de7e4a3d1734bcf67 \ + --hash=sha256:d854b3970067297f3a7fbd7a4683587134aa9b3877ee15aa29eea478dc68f933 \ + --hash=sha256:d8fcccbbc0c13c13702c471da398b8cd72ba740dca5859f148ae8e0e8e0d3e7e \ + --hash=sha256:e004aa9248e8cb0a5f9b96d003ca7c1c0a5da8decd1066e7b53f59eb8ce7c62b \ + --hash=sha256:e214d546c8ecb5fc22d6e6011746082abf13a9cf46eefb45769c7b31407c97b5 \ + --hash=sha256:e2d0d88686e3d35a76f3e15a34e8c12d73fc94c1dea1cd55782e695cc14086dd \ + --hash=sha256:e2f35b4cccd9ed286ad62e0a3c3ac21e06c02abc60e20aa51a3e305a30f5fa79 \ + --hash=sha256:e3070c03701037aa418b55d36532ecb8f8446ed0135acb71c678dbdf12f5b6e4 \ + --hash=sha256:e5e088bf43f6ee6fec7dbf1ef7ff7774a616c236b5c0cb3e00662dd71a56b571 \ + --hash=sha256:e83e3f959aaa1c9df95c22c528096d94848a1bc819f5d0ebf7ee3df0ca63db6c \ + --hash=sha256:f0dcbc588cd5b725162c076eb9119342f6579c7f7f55057bb7e3c6ff27e13121 \ + --hash=sha256:f27f9da0a7d22b9f981108fd4b62f8b5743423388915a563e651c20d06c1f457 \ + --hash=sha256:f8649a14caa5f8a243628b1d61cf530ad9ae4578814ba726816adb1121fc493e \ + --hash=sha256:fac0fa4e4f55f118fd87177dacb1c6522fe39c28d498d259014020fec9164c29 \ + --hash=sha256:fd08b90d211c086181caed76931ecfa2bdfc83eea3cfccdb0f82abc6c4b876cb # via feast (pyproject.toml) -sqlglot[rs]==28.10.1 \ - --hash=sha256:214aef51fd4ce16407022f81cfc80c173409dab6d0f6ae18c52b43f43b31d4dd \ - --hash=sha256:66e0dae43b4bce23314b80e9aef41b8c88fea0e17ada62de095b45262084a8c5 +sqlglot[rs]==30.2.1 \ + --hash=sha256:ef4a67cc6f66a8043085eb8ea95fa9541c1625dffa9145ad4e9815a7ba60a199 \ + --hash=sha256:f23d9ee9427ef9d20df15f9b0ffa57d9eb45e52b012219a349d1e6b50ed926d1 # via # feast (pyproject.toml) # ibis-framework -sqlglotrs==0.12.0 \ - --hash=sha256:011e9c1c1465de06198cc6b3220e64c833a0ebe3565db8bea1ddda70a6515e8d \ - --hash=sha256:033160f03e6a6aa14e8a07a680eb0706e3ed1ad997ba9fb89c7fc8149e83899c \ - --hash=sha256:0c27d654a7dc0d0a06e3fb94798542e3e748a3f2fc41444565d18ba95021b806 \ - --hash=sha256:10a67825f654a599cbac58c8d129b0c7f49acf4e3ca05e471df301ca00b819e7 \ - --hash=sha256:16d581b25d0731aa25681640450f5d305a0aa04c3257a8e0d3a7ecd15e6e1c7f \ - --hash=sha256:1a5147585d909d5640aa2589a470986a7c9cfb3c90e92970942b9ccc512bacad \ - --hash=sha256:1ca61b15c2fd37d21770a02cf7b48e406e887ae597d158f67e8d868ddc79f4d6 \ - --hash=sha256:21d4c25cee14f758f8ca095fc9e61aa239cd93c438eaffc36462d85e94e7d395 \ - --hash=sha256:28d1ecc8afc6323a537d74df8c5f4545641742cf9b965813de1fb72ddc1bfe5c \ - --hash=sha256:2a097e56cbaed9b97901c2a149381e547627aaeb1dc388a0b691543558dad1ab \ - --hash=sha256:2a58221be2d771b6d65a7b3721a0c3020eeff17cd825905a35a47558acad8257 \ - --hash=sha256:2faa9dc5d11b19122189a8635a269efaee6f7bb609ae653d43f7b71be2ff54d0 \ - --hash=sha256:466451fed87ca90a4a2ec1b3e026ac9d4f8a57e4ed9c51583290ef11fc4c1631 \ - --hash=sha256:47b56e8bd5ed85055ae0409c53cdf4d8dbc5f7c3170f238b472173fcb16ddfe0 \ - --hash=sha256:4e5f477522a76fee1d1907b0196510f002f4c339a286de9cd63f8d51265b0f68 \ - --hash=sha256:4f0dac396c68ea9612cc89bb170c0366a7d686d012142a4365ed222401d6b645 \ - --hash=sha256:5312f17e3e2b5c18fac8269d8d5a2c26a0aed79a22854787153d7ff5bff7be66 \ - --hash=sha256:533cbefb35128de669efa7e1e86fec61383121ebd5514e0a1e70aa33bf875987 \ - --hash=sha256:5443e10a41894719778d40fb854192efd569eb99b26ef37e87a4730cc2ee899b \ - --hash=sha256:558720d901a0be3ee69660c0b72fe3dfdf23f557d7911d13f4d3555fdd44ae75 \ - --hash=sha256:6156f621c1c4ea4a46efbaf977f4df52a29f2f414bfb62de8ea878f50d4fd506 \ - --hash=sha256:61751c7f2ca0a1f83e2df041295fe71a88ce0b025bb4e578164657822bead0e1 \ - --hash=sha256:6364c8bfc8c5678e13562bf705a111124afbfaaa1762ce00384dc514e31c6a4a \ - --hash=sha256:656b03b7eae2fd03f0a89770e08a6b815f462d5eef8abf6942442c769bda8ca2 \ - --hash=sha256:672cdcbed0dfa45fa6f3922c8c9d893092dd47e0600f25b8076559e3aeeb1921 \ - --hash=sha256:69470afeaef3a48e1bb87f25c83d2061bc4bd870665e6a2c2e0c0c2b82ab0480 \ - --hash=sha256:6be5fac1f7a01c1b3e40c2478a3db5a125201d39e4601f6075660804a7b40e18 \ - --hash=sha256:6e0be4ceffe2aec98e308df9e872084c47c8f178fa0269d4bf1f1b99eb1c877b \ - --hash=sha256:72b9829ab9dfce9997740d6949a981f619f813d664524314386fa80b72ede7b1 \ - --hash=sha256:7a9f6ffb06b3d617556819f9e14703a0f5a65b8d87613969141be08cdd06b620 \ - --hash=sha256:7fcbc0004986510f4c5c625d053ee8febf836116db1dab3bd407292a69dee375 \ - --hash=sha256:850c408ae94f85f9d8c35a4511d1f67c560c077467c41a6ea66f5046b4b731f9 \ - --hash=sha256:8641bfbcc9b92167aff99d589e0fd2f4d902759e415b13e59352314bf5348770 \ - --hash=sha256:900f9023f8eca065e81665507722a4563e76bab19cc1322837d9248186e1ea90 \ - --hash=sha256:90bee58c15c9144f571e79e4e57b645452d0142cfee35cf2e11ec6124c4e5f07 \ - --hash=sha256:94b02d14c044d3eb22b4c494813f587f47e65d0343a4dc341c9b542a01cfca16 \ - --hash=sha256:a0b78f58b5ea14fef29d03636666e3a749b2aed88a3603df1dadc16215fb5b78 \ - --hash=sha256:a27d106b870d2a28f6caf100af8976054fdea649e6da733c31bcf7730ad928dd \ - --hash=sha256:a6c419d8ae6c234d151a71f1becabc13d0c44d67a76376d8d934aaf350f08858 \ - --hash=sha256:a880b4d4133591e90d40bdd802404e960e396dd24c2eda6a2a04cbba6effc4d5 \ - --hash=sha256:ae6d7e877bf6890fdb35ed00819783e1a1ddce8c8ed7009dc1604323bf24d0ed \ - --hash=sha256:b0e0193d3e13d37ede7969f3b52d3feaeb56d7e3ba78bafb1d75a2c789bf0373 \ - --hash=sha256:ba15622063c60b17bdce8575d53b1c81ad5d31fc77d00e20378c0051d6ffa4cf \ - --hash=sha256:bb7d8e05fe19b5bd157c20289a66a9b218c9eb3314ae78ec6bae2e9525900b30 \ - --hash=sha256:bd6c108d6b64950060570aba6181fa03366e2e458793706cef379d86ebde5670 \ - --hash=sha256:bdc5bb2c4ba35fa76baeb6eb31ee7c5bb349af1bc7c4b51ce5804e1370442e30 \ - --hash=sha256:c08e633850082cc1353fe2c24ec3c6bd229f8b5925662a8d5526cc94073349b4 \ - --hash=sha256:c26f1ff7eca636a55eb79bc2b622422561b9801201a4c2a62512902d818671e8 \ - --hash=sha256:c37796704edaa1ad73ba9e43f308f8e93d2392ade33fa8a51e1d55d8b6136b0f \ - --hash=sha256:c876cd551d3d724daac533b833e11d359f95037b5757487492caf8e600326848 \ - --hash=sha256:ce31216150be347a045ef35358c6c640a87c389482745cef5d481242cbac8f8e \ - --hash=sha256:d08c63e1bebe4963a5efe56e4ed278a441c2e552f9d1d6a768721b52b29cbb4a \ - --hash=sha256:d0bf559389c38aecdaefba14a7e4d59570ef491dbfaa41b8493614c97c1268c5 \ - --hash=sha256:e0f8c959e44f330e9b7000bc9a6926e18bf9d44b6cba2dd81807a6a2d552c597 \ - --hash=sha256:e55cb36ec074fd0abafd6698d2f7cd1d91e01c102384bdc945b977a86d2199a6 \ - --hash=sha256:f36716d090f373eda020b5e130a48da0139f3eede7f5e5b684c58263b83bd7d1 \ - --hash=sha256:f3c937c9ae8fb4ec3bc3bc0bea215dec290dfa0ce033048d25c87f7b632a3d3a \ - --hash=sha256:f4fc40bae51f36818acd8f98a4246eebd8c283081906dc22db353ab1e141f529 \ - --hash=sha256:f7426f61a2596a6f681dde5d8e4d0386aa2bdddee3af8902c6c3266d6249480e \ - --hash=sha256:fa2c04c40af5b209631feea812103a079f8a016e1ddb60eb74e9460d72050bfe \ - --hash=sha256:fb402884d234c0a500c42bb2a5f500604891ef83e58c984ec2b4af8fa76bd72d +sqlglotc==30.2.1 \ + --hash=sha256:052cd7bb41fc9b841eb268d4dd601eb6b5954b7c6d5656795d4350a0f8020d53 \ + --hash=sha256:058f0e9aed2b8dff87dc893b8793e514204c8dfef699b7d3d1704dfbdd949f2b \ + --hash=sha256:0e6be524252894c0fa98d25d4e60dfae6485ba66ca1abd40bf05f16a9cf26baf \ + --hash=sha256:13f8f68808777ba7d845bc908bf09f72a0c9899a19811483dc52f0fa48b38d5a \ + --hash=sha256:1a004086ab871be0cc97766f7b6fb8866729f09dd7272254fd31c05107f3fdc8 \ + --hash=sha256:25c6f62f31cd3a051285635c3f6a01d2f3c73ca2baaa26970815166928042ace \ + --hash=sha256:2b5fe8adc1a1e2fb819e014e94974a274f30dbf9684ceed9f171fb0889f80f0b \ + --hash=sha256:2ffe527bc8664b03cc936bae7ebf965f482beb4acee7a815c2ec2d9aea720b4e \ + --hash=sha256:4aa90e08f53409b1857572836e57a31835ed20e32521c6fafdc6af96199baff7 \ + --hash=sha256:507935a971e0a9e5d4ac7ca14df479f8e270502b44904f71d95c0aaed066006f \ + --hash=sha256:515e092ab8fb522b256fa8a34f471e9b187bb8a50a7c0226a65b036a07d6d188 \ + --hash=sha256:585bb610fde3e3dd1d7e5ff3cce14f70fbd53ced6769cd104679adf8b5c4ab5b \ + --hash=sha256:850e7517dd4739cad9af65bcb9699825f9202e5971407bf955e3248fe4814f96 \ + --hash=sha256:8f063af733cbcc51686380470e7f3f80b589b8c58084baa138efb3b8ca821597 \ + --hash=sha256:b17e3002ed10747388367621b2ecf39c06d5fdc6b3c31a8c32be2f5ef546fc0b \ + --hash=sha256:d577e1635e127febb7012bc42fa1c3b958076e59a1a116ade20048c572a1be42 \ + --hash=sha256:dc292cd73e0c447253877c27f00454a2d09b71324a130ad4c58c145ab753889e \ + --hash=sha256:de168df756a21a028cf1f917f92da2f77bb135f3b6cdd960914460942a5eca10 \ + --hash=sha256:de884dd224220002c3e940ca5bdceb27ef9638e5f02493db133ffb8ae88b5610 \ + --hash=sha256:f33c7d1646ff6531cb9b07f0740b2939f3ecaa31efebfbec8adb6b275f1a45f2 \ + --hash=sha256:f9a1fc7b1ff3b51d0d03a391768a79964f68541b4c2f294a25a6f14e6670ffab \ + --hash=sha256:fae4edad0b7c5f9f963bd63452f722f0d7f77a436c2d334b555b31722f9573ad \ + --hash=sha256:fdc19623a1c7659918c3cee18ea8849fc4af9eaeb87247acf37e0393295d32b7 \ + --hash=sha256:feefc0ab7606d1fe284d23bef09ea4829ce4fad679936959c29324310f23e081 \ + --hash=sha256:ff19b7ecb931aef6c7c6168af5530c07e67915102b701d45ae80446f0695ba54 + # via sqlglot +sqlglotrs==0.13.0 \ + --hash=sha256:6b934a244b16f26fca50974328a2ebc7689583c59f06203cebb46e2e6e8d93a7 \ + --hash=sha256:ad1ad158234af0f8ba5054ca51bd17a7c1e3f81b4798c7970ebf7953fe08ddcb # via sqlglot sqlite-vec==0.1.6 \ --hash=sha256:77491bcaa6d496f2acb5cc0d0ff0b8964434f141523c121e313f9a7d8088dee3 \ @@ -5616,17 +5633,17 @@ sqlparams==6.2.0 \ --hash=sha256:3744a2ad16f71293db6505b21fd5229b4757489a9b09f3553656a1ae97ba7ca5 \ --hash=sha256:63b32ed9051bdc52e7e8b38bc4f78aed51796cdd9135e730f4c6a7db1048dedf # via singlestoredb -sse-starlette==3.2.0 \ - --hash=sha256:5876954bd51920fc2cd51baee47a080eb88a37b5b784e615abb0b283f801cdbf \ - --hash=sha256:8127594edfb51abe44eac9c49e59b0b01f1039d0c7461c6fd91d4e03b70da422 +sse-starlette==3.3.4 \ + --hash=sha256:84bb06e58939a8b38d8341f1bc9792f06c2b53f48c608dd207582b664fc8f3c1 \ + --hash=sha256:aaf92fc067af8a5427192895ac028e947b484ac01edbc3caf00e7e7137c7bef1 # via mcp stack-data==0.6.3 \ --hash=sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9 \ --hash=sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695 # via ipython -starlette==0.52.1 \ - --hash=sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74 \ - --hash=sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933 +starlette==1.0.0 \ + --hash=sha256:6a4beaf1f81bb472fd19ea9b918b50dc3a77a6f2e190a12954b25e6ed5eea149 \ + --hash=sha256:d3ec55e0bb321692d275455ddfd3df75fff145d009685eb40dc91fc66b03d38b # via # fastapi # mcp @@ -5635,9 +5652,9 @@ sympy==1.14.0 \ --hash=sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517 \ --hash=sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5 # via torch -tabulate==0.9.0 \ - --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ - --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f +tabulate==0.10.0 \ + --hash=sha256:e2cfde8f79420f6deeffdeda9aaec3b6bc5abce947655d17ac662b126e48a60d \ + --hash=sha256:f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3 # via # feast (pyproject.toml) # docling-core @@ -5669,14 +5686,18 @@ thriftpy2==0.6.0 \ --hash=sha256:1245c36b82f34aa26f049e6529f40ad34d9be8d12bd0131559847c8476b98ce0 \ --hash=sha256:151d299e8e3694a6cc0f2f2cda01d5744080742649de958c5cdcbebb4306205f \ --hash=sha256:16eecfd34bd541b75172ba0d69ea90b874611a7361d18906fb6d95955089cc30 \ + --hash=sha256:182f54a7248c8ecf1320cf26d1fc9115765df6b1f2589c1d2d0df7049a5b27d4 \ --hash=sha256:210345281d41b3a76d263b555d3e3cc482103738441bdb92a73033a4e9a042e1 \ --hash=sha256:265588b8cdb3fe1097db43bf35fb208edc69d9350a2bec3a737d6357d0a5650d \ --hash=sha256:28fd55960a6d42207060536109928a4615fbbd6874c0ddd8a705b47075f1d2d0 \ --hash=sha256:29ff125e40c8016b4d3bf48e6d727bd93d2892451b47bfe57ba896944ecbdb0c \ --hash=sha256:2ae866adf9b112c7ab30c1a90d878a5d6f2d40244fbc46ec8477425d802f4ac5 \ --hash=sha256:2bf891c2d441b1edddfc62f16ab3031ac7506cba5b77680654179dbe93d8b7ec \ + --hash=sha256:2c88b0d356ea18ce026a52aa7c2110693db77fd52d5ac7553616635a7f165bbd \ --hash=sha256:3090d9cabc2c31c92ae943f36d539a20adfd82697f50e996ce94f0b279e9e1e4 \ + --hash=sha256:3359a7c4eb4c281bf54bd760dcc03c43299f0d529dd2a5018be2f1fbebf0cbbd \ --hash=sha256:375cca06f36f54339838c7f8251b64a777d5ff1277f8b91999487fad1a8e2d73 \ + --hash=sha256:386d8c4a5677fd94fd16c1af2adf39f59698af1e4ef0c3c026083f278540e352 \ --hash=sha256:44365bb5098d0a91c44382e7df0ad44d5b9a588d29d9071aca4a2867f704aaf1 \ --hash=sha256:443e502b428d325c57aec0947991857e8dc0589d0464181f35bd48f870cd5d18 \ --hash=sha256:4550cbb6629c9f6186ab22cb497f262408e1a90ae10b8653599f2717f518f0df \ @@ -5693,6 +5714,7 @@ thriftpy2==0.6.0 \ --hash=sha256:851981ded8bb42da66213cf95d1dd5eaf06c5d6b3a95725a18eddd58ec992b6b \ --hash=sha256:852e538b4866ed776126349161d9fdc37387b1e15ab46805f98dcdee25fee4b5 \ --hash=sha256:8b19d19661fc9a71f19b7c432c413ab65025e5dd11fbd192bd9169afb13b9ce0 \ + --hash=sha256:8e62d9c36bcfe6b85bec7b754accb97e2fa7b6a7c9a0c37f824d85eba699e7b8 \ --hash=sha256:8eb0566b4501c27ea51f2e593531122703946969564fe526a5ff1b18be0ad49a \ --hash=sha256:8f393607d54091e8976e297f8fd7399606d12cd8c2b8852353f07ad5ddac4224 \ --hash=sha256:91df1fa70a99ac08dc449d6fda24a14992a1836d571928f217c40c66fd63fcc8 \ @@ -5707,25 +5729,28 @@ thriftpy2==0.6.0 \ --hash=sha256:b361152c24fd5c791220de9966b00696578c9884a2bb67e4759d4dfe05fd7049 \ --hash=sha256:b51b5259dc344482ab21b768dfc7f54d51d9133665e72890831725068f69f24a \ --hash=sha256:b57f367d7b0e1bc9e5c9b0ff34febdb3fe440f1fe8d75903ae71301bc06072c0 \ + --hash=sha256:b8dc65d2e7951b7e81c17b92857db7c19d6b3dd442d2d8600b5bd5040aa43ce6 \ --hash=sha256:bc320e960347e5f9d27e8b4a9fc7044b2b26bfe4522bb4957e741fc1d1ebd2f0 \ --hash=sha256:bdf77ba7a8987a239eb57cf840d62669741f8b92b61a617e63898caed31da898 \ --hash=sha256:bf96b64400da2f411b43c4c81c2e20b09e3300d86766a52f42393696c8962f11 \ --hash=sha256:c37f5dbfe95579549485c33167854784358f559feda703ccc058719ca0efd8aa \ --hash=sha256:c41312c6edad5e875613719236f1ca6bba9310df40b1adc9308248e1bdb7a1ea \ + --hash=sha256:cafa1d43bcc69129a4855fd3973ab7983bb2274c407e5ff572af5dc196e00313 \ --hash=sha256:cb98556e919be3e6ba9bca629dbddccfaa33b95a0fe7503052849b124e4f88cd \ --hash=sha256:cd2e2c4dcc30c373e317d39b044afa6d9a090bec11d186f25841f70bc520bbb5 \ --hash=sha256:e6c4fb1e7f51f8858f348ed9c31bb408b61274942d18b549ec163bb480c987a0 \ + --hash=sha256:eccab0281667caab0c055882b3bbb8e346bb0181e55f37477e3e5e3f5b7a96dd \ --hash=sha256:f59f74c3779aa47223ba0a9e23ef10d2af5a873ed3624c78303f62a679d1b63e \ --hash=sha256:f6b86112cca7bd04151ce248d781763ea5f74cc18d148476c6d16cee32db81ac \ --hash=sha256:f837ab85ae93b118766b8b28a1cec47a1daddee303e1f986a595c56379062a5c # via happybase -tifffile==2026.2.15 \ - --hash=sha256:28fe145c615fe3d33d40c2d4c9cc848f7631fd30af852583c4186069458895b2 \ - --hash=sha256:d9b427d269a708c58400e8ce5a702b26b2502087537beb88b8e29ba7ba825a90 +tifffile==2026.3.3 \ + --hash=sha256:d9a1266bed6f2ee1dd0abde2018a38b4f8b2935cb843df381d70ac4eac5458b7 \ + --hash=sha256:e8be15c94273113d31ecb7aa3a39822189dd11c4967e3cc88c178f1ad2fd1170 # via scikit-image -timm==1.0.24 \ - --hash=sha256:8301ac783410c6ad72c73c49326af6d71a9e4d1558238552796e825c2464913f \ - --hash=sha256:c7b909f43fe2ef8fe62c505e270cd4f1af230dfbc37f2ee93e3608492b9d9a40 +timm==1.0.26 \ + --hash=sha256:985c330de5ccc3a2aa0224eb7272e6a336084702390bb7e3801f3c91603d3683 \ + --hash=sha256:f66f082f2f381cf68431c22714c8b70f723837fa2a185b155961eab90f2d5b10 # via feast (pyproject.toml) tinycss2==1.4.0 \ --hash=sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7 \ @@ -5761,54 +5786,54 @@ toml==0.10.2 \ --hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \ --hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f # via feast (pyproject.toml) -tomli==2.4.0 \ - --hash=sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729 \ - --hash=sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b \ - --hash=sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d \ - --hash=sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df \ - --hash=sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576 \ - --hash=sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d \ - --hash=sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1 \ - --hash=sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a \ - --hash=sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e \ - --hash=sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc \ - --hash=sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702 \ - --hash=sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6 \ - --hash=sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd \ - --hash=sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4 \ - --hash=sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776 \ - --hash=sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a \ - --hash=sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66 \ - --hash=sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87 \ - --hash=sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2 \ - --hash=sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f \ - --hash=sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475 \ - --hash=sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f \ - --hash=sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95 \ - --hash=sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9 \ - --hash=sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3 \ - --hash=sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9 \ - --hash=sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76 \ - --hash=sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da \ - --hash=sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8 \ - --hash=sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51 \ - --hash=sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86 \ - --hash=sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8 \ - --hash=sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0 \ - --hash=sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b \ - --hash=sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1 \ - --hash=sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e \ - --hash=sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d \ - --hash=sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c \ - --hash=sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867 \ - --hash=sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a \ - --hash=sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c \ - --hash=sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0 \ - --hash=sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4 \ - --hash=sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614 \ - --hash=sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132 \ - --hash=sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa \ - --hash=sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087 +tomli==2.4.1 \ + --hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \ + --hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \ + --hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \ + --hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \ + --hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \ + --hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \ + --hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \ + --hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \ + --hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \ + --hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \ + --hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \ + --hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \ + --hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \ + --hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \ + --hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \ + --hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \ + --hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \ + --hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \ + --hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \ + --hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \ + --hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \ + --hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \ + --hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \ + --hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \ + --hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \ + --hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \ + --hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \ + --hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \ + --hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \ + --hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \ + --hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \ + --hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \ + --hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \ + --hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \ + --hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \ + --hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \ + --hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \ + --hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \ + --hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \ + --hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \ + --hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \ + --hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \ + --hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \ + --hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \ + --hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \ + --hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \ + --hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049 # via # coverage # fastapi-mcp @@ -5824,94 +5849,89 @@ toolz==1.1.0 \ # dask # ibis-framework # partd -torch==2.10.0 \ - --hash=sha256:13ec4add8c3faaed8d13e0574f5cd4a323c11655546f91fbe6afa77b57423574 \ - --hash=sha256:233aed0659a2503b831d8a67e9da66a62c996204c0bba4f4c442ccc0c68a3f60 \ - --hash=sha256:29b7009dba4b7a1c960260fc8ac85022c784250af43af9fb0ebafc9883782ebd \ - --hash=sha256:2b980edd8d7c0a68c4e951ee1856334a43193f98730d97408fbd148c1a933313 \ - --hash=sha256:2c66c61f44c5f903046cc696d088e21062644cbe541c7f1c4eaae88b2ad23547 \ - --hash=sha256:3202429f58309b9fa96a614885eace4b7995729f44beb54d3e4a47773649d382 \ - --hash=sha256:3282d9febd1e4e476630a099692b44fdc214ee9bf8ee5377732d9d9dfe5712e4 \ - --hash=sha256:35e407430795c8d3edb07a1d711c41cc1f9eaddc8b2f1cc0a165a6767a8fb73d \ - --hash=sha256:418997cb02d0a0f1497cf6a09f63166f9f5df9f3e16c8a716ab76a72127c714f \ - --hash=sha256:5276fa790a666ee8becaffff8acb711922252521b28fbce5db7db5cf9cb2026d \ - --hash=sha256:5c4d217b14741e40776dd7074d9006fd28b8a97ef5654db959d8635b2fe5f29b \ - --hash=sha256:5fd4117d89ffd47e3dcc71e71a22efac24828ad781c7e46aaaf56bf7f2796acf \ - --hash=sha256:6021db85958db2f07ec94e1bc77212721ba4920c12a18dc552d2ae36a3eb163f \ - --hash=sha256:6528f13d2a8593a1a412ea07a99812495bec07e9224c28b2a25c0a30c7da025c \ - --hash=sha256:682497e16bdfa6efeec8cde66531bc8d1fbbbb4d8788ec6173c089ed3cc2bfe5 \ - --hash=sha256:6b71486353fce0f9714ca0c9ef1c850a2ae766b409808acd58e9678a3edb7738 \ - --hash=sha256:6d3707a61863d1c4d6ebba7be4ca320f42b869ee657e9b2c21c736bf17000294 \ - --hash=sha256:71283a373f0ee2c89e0f0d5f446039bdabe8dbc3c9ccf35f0f784908b0acd185 \ - --hash=sha256:716b01a176c2a5659c98f6b01bf868244abdd896526f1c692712ab36dbaf9b63 \ - --hash=sha256:787124e7db3b379d4f1ed54dd12ae7c741c16a4d29b49c0226a89bea50923ffb \ - --hash=sha256:a2f9edd8dbc99f62bc4dfb78af7bf89499bca3d753423ac1b4e06592e467b763 \ - --hash=sha256:a4be6a2a190b32ff5c8002a0977a25ea60e64f7ba46b1be37093c141d9c49aeb \ - --hash=sha256:aae1b29cd68e50a9397f5ee897b9c24742e9e306f88a807a27d617f07adb3bd8 \ - --hash=sha256:aaf663927bcd490ae971469a624c322202a2a1e68936eb952535ca4cd3b90444 \ - --hash=sha256:b7bd80f3477b830dd166c707c5b0b82a898e7b16f59a7d9d42778dd058272e8b \ - --hash=sha256:bf0d9ff448b0218e0433aeb198805192346c4fd659c852370d5cc245f602a06a \ - --hash=sha256:c2ee399c644dc92ef7bc0d4f7e74b5360c37cdbe7c5ba11318dda49ffac2bc57 \ - --hash=sha256:cdf2a523d699b70d613243211ecaac14fe9c5df8a0b0a9c02add60fb2a413e0f \ - --hash=sha256:d8f5912ba938233f86361e891789595ff35ca4b4e2ac8fe3670895e5976731d6 \ - --hash=sha256:e521c9f030a3774ed770a9c011751fb47c4d12029a3d6522116e48431f2ff89e \ - --hash=sha256:f5ab4ba32383061be0fb74bda772d470140a12c1c3b58a0cfbf3dae94d164c28 \ - --hash=sha256:ff43db38af76fda183156153983c9a096fc4c78d0cd1e07b14a2314c7f01c2c8 +torch==2.11.0 \ + --hash=sha256:01018087326984a33b64e04c8cb5c2795f9120e0d775ada1f6638840227b04d7 \ + --hash=sha256:0f68f4ac6d95d12e896c3b7a912b5871619542ec54d3649cf48cc1edd4dd2756 \ + --hash=sha256:1b32ceda909818a03b112006709b02be1877240c31750a8d9c6b7bf5f2d8a6e5 \ + --hash=sha256:1e6debd97ccd3205bbb37eb806a9d8219e1139d15419982c09e23ef7d4369d18 \ + --hash=sha256:2658f34ce7e2dabf4ec73b45e2ca68aedad7a5be87ea756ad656eaf32bf1e1ea \ + --hash=sha256:2b4e811728bd0cc58fb2b0948fe939a1ee2bf1422f6025be2fca4c7bd9d79718 \ + --hash=sha256:2bb3cc54bd0dea126b0060bb1ec9de0f9c7f7342d93d436646516b0330cd5be7 \ + --hash=sha256:2c0d7fcfbc0c4e8bb5ebc3907cbc0c6a0da1b8f82b1fc6e14e914fa0b9baf74e \ + --hash=sha256:4b5866312ee6e52ea625cd211dcb97d6a2cdc1131a5f15cc0d87eec948f6dd34 \ + --hash=sha256:4cf8687f4aec3900f748d553483ef40e0ac38411c3c48d0a86a438f6d7a99b18 \ + --hash=sha256:4dc8b3809469b6c30b411bb8c4cad3828efd26236153d9beb6a3ec500f211a60 \ + --hash=sha256:4dda3b3f52d121063a731ddb835f010dc137b920d7fec2778e52f60d8e4bf0cd \ + --hash=sha256:563ed3d25542d7e7bbc5b235ccfacfeb97fb470c7fee257eae599adb8005c8a2 \ + --hash=sha256:63a68fa59de8f87acc7e85a5478bb2dddbb3392b7593ec3e78827c793c4b73fd \ + --hash=sha256:73e24aaf8f36ab90d95cd1761208b2eb70841c2a9ca1a3f9061b39fc5331b708 \ + --hash=sha256:7aa2f9bbc6d4595ba72138026b2074be1233186150e9292865e04b7a63b8c67a \ + --hash=sha256:7b6a60d48062809f58595509c524b88e6ddec3ebe25833d6462eeab81e5f2ce4 \ + --hash=sha256:8245477871c3700d4370352ffec94b103cfcb737229445cf9946cddb7b2ca7cd \ + --hash=sha256:8b394322f49af4362d4f80e424bcaca7efcd049619af03a4cf4501520bdf0fb4 \ + --hash=sha256:98bb213c3084cfe176302949bdc360074b18a9da7ab59ef2edc9d9f742504778 \ + --hash=sha256:a97b94bbf62992949b4730c6cd2cc9aee7b335921ee8dc207d930f2ed09ae2db \ + --hash=sha256:ab9a8482f475f9ba20e12db84b0e55e2f58784bdca43a854a6ccd3fd4b9f75e6 \ + --hash=sha256:b2a43985ff5ef6ddd923bbcf99943e5f58059805787c5c9a2622bf05ca2965b0 \ + --hash=sha256:b3c712ae6fb8e7a949051a953fc412fe0a6940337336c3b6f905e905dac5157f \ + --hash=sha256:cc89b9b173d9adfab59fd227f0ab5e5516d9a52b658ae41d64e59d2e55a418db \ + --hash=sha256:d91aac77f24082809d2c5a93f52a5f085032740a1ebc9252a7b052ef5a4fddc6 \ + --hash=sha256:f99924682ef0aa6a4ab3b1b76f40dc6e273fca09f367d15a524266db100a723f \ + --hash=sha256:fbf39280699d1b869f55eac536deceaa1b60bd6788ba74f399cc67e60a5fab10 # via # feast (pyproject.toml) # accelerate # docling-ibm-models # easyocr # safetensors + # sentence-transformers # timm # torchvision -torchvision==0.25.0 \ - --hash=sha256:0b5e7f50002a8145a98c5694a018e738c50e2972608310c7e88e1bd4c058f6ce \ - --hash=sha256:0d9a3f925a081dd2ebb0b791249b687c2ef2c2717d027946654607494b9b64b6 \ - --hash=sha256:146d02c9876858420adf41f3189fe90e3d6a409cbfa65454c09f25fb33bf7266 \ - --hash=sha256:153c0d2cbc34b7cf2da19d73450f24ba36d2b75ec9211b9962b5022fb9e4ecee \ - --hash=sha256:24e11199e4d84ba9c5ee7825ebdf1cd37ce8deec225117f10243cae984ced3ec \ - --hash=sha256:40a122c3cf4d14b651f095e0f672b688dde78632783fc5cd3d4d5e4f6a828563 \ - --hash=sha256:5e6b449e9fa7d642142c0e27c41e5a43b508d57ed8e79b7c0a0c28652da8678c \ - --hash=sha256:5f271136d2d2c0b7a24c5671795c6e4fd8da4e0ea98aeb1041f62bc04c4370ef \ - --hash=sha256:620a236288d594dcec7634c754484542dc0a5c1b0e0b83a34bda5e91e9b7c3a1 \ - --hash=sha256:632db02300e83793812eee4f61ae6a2686dab10b4cfd628b620dc47747aa9d03 \ - --hash=sha256:846890161b825b38aa85fc37fb3ba5eea74e7091ff28bab378287111483b6443 \ - --hash=sha256:855c0dc6d37f462482da7531c6788518baedca1e0847f3df42a911713acdfe52 \ - --hash=sha256:a8f8061284395ce31bcd460f2169013382ccf411148ceb2ee38e718e9860f5a7 \ - --hash=sha256:a95c47abb817d4e90ea1a8e57bd0d728e3e6b533b3495ae77d84d883c4d11f56 \ - --hash=sha256:acc339aba4a858192998c2b91f635827e40d9c469d9cf1455bafdda6e4c28ea4 \ - --hash=sha256:ad9a8a5877782944d99186e4502a614770fe906626d76e9cd32446a0ac3075f2 \ - --hash=sha256:b57430fbe9e9b697418a395041bb615124d9c007710a2712fda6e35fb310f264 \ - --hash=sha256:b75deafa2dfea3e2c2a525559b04783515e3463f6e830cb71de0fb7ea36fe233 \ - --hash=sha256:c2abe430c90b1d5e552680037d68da4eb80a5852ebb1c811b2b89d299b10573b \ - --hash=sha256:c4d395cb2c4a2712f6eb93a34476cdf7aae74bb6ea2ea1917f858e96344b00aa \ - --hash=sha256:cef0196be31be421f6f462d1e9da1101be7332d91984caa6f8022e6c78a5877f \ - --hash=sha256:d1abd5ed030c708f5dbf4812ad5f6fbe9384b63c40d6bd79f8df41a4a759a917 \ - --hash=sha256:db74a551946b75d19f9996c419a799ffdf6a223ecf17c656f90da011f1d75b20 \ - --hash=sha256:ea580ffd6094cc01914ad32f8c8118174f18974629af905cea08cb6d5d48c7b7 \ - --hash=sha256:f07f01d27375ad89d72aa2b3f2180f07da95dd9d2e4c758e015c0acb2da72977 \ - --hash=sha256:f25aa9e380865b11ea6e9d99d84df86b9cc959f1a007cd966fc6f1ab2ed0e248 \ - --hash=sha256:f49964f96644dbac2506dffe1a0a7ec0f2bf8cf7a588c3319fed26e6329ffdf3 \ - --hash=sha256:f9c55ae8d673ab493325d1267cbd285bb94d56f99626c00ac4644de32a59ede3 +torchvision==0.26.0 \ + --hash=sha256:0f3e572efe62ad645017ea847e0b5e4f2f638d4e39f05bc011d1eb9ac68d4806 \ + --hash=sha256:114bec0c0e98aa4ba446f63e2fe7a2cbca37b39ac933987ee4804f65de121800 \ + --hash=sha256:1c55dc8affbcc0eb2060fbabbe996ae9e5839b24bb6419777f17848945a411b1 \ + --hash=sha256:2adfbe438473236191ff077a4a9a0c767436879c89628aa97137e959b0c11a94 \ + --hash=sha256:358fc4726d0c08615b6d83b3149854f11efb2a564ed1acb6fce882e151412d23 \ + --hash=sha256:3daf9cc149cf3cdcbd4df9c59dae69ffca86c6823250442c3bbfd63fc2e26c61 \ + --hash=sha256:406557718e62fdf10f5706e88d8a5ec000f872da913bf629aab9297622585547 \ + --hash=sha256:4280c35ec8cba1fcc8294fb87e136924708726864c379e4c54494797d86bc474 \ + --hash=sha256:55bd6ad4ae77be01ba67a410b05b51f53b0d0ee45f146eb6a0dfb9007e70ab3c \ + --hash=sha256:5d63dd43162691258b1b3529b9041bac7d54caa37eae0925f997108268cbf7c4 \ + --hash=sha256:7058c5878262937e876f20c25867b33724586aa4499e2853b2d52b99a5e51953 \ + --hash=sha256:7993c01648e7c61d191b018e84d38fe0825c8fcb2720cd0f37caf7ba14404aa1 \ + --hash=sha256:8008474855623c6ba52876589dc52df0aa66e518c25eca841445348e5f79844c \ + --hash=sha256:82c3965eca27e86a316e31e4c3e5a16d353e0bcbe0ef8efa2e66502c54493c4b \ + --hash=sha256:9a904f2131cbfadab4df828088a9f66291ad33f49ff853872aed1f86848ef776 \ + --hash=sha256:a06d4772a8e13e772906ed736cc53ec6639e5e60554f8e5fa6ca165aabebc464 \ + --hash=sha256:a39c7a26538c41fda453f9a9692b5ff9b35a5437db1d94f3027f6f509c160eac \ + --hash=sha256:b6f9ad1ecc0eab52647298b379ee9426845f8903703e6127973f8f3d049a798b \ + --hash=sha256:b7d3e295624a28b3b1769228ce1345d94cf4d390dd31136766f76f2d20f718da \ + --hash=sha256:b7e6213620bbf97742e5f79832f9e9d769e6cf0f744c5b53dad80b76db633691 \ + --hash=sha256:c409e1c3fdebec7a3834465086dbda8bf7680eff79abf7fd2f10c6b59520a7a4 \ + --hash=sha256:d61a5abb6b42a0c0c311996c2ac4b83a94418a97182c83b055a2a4ae985e05aa \ + --hash=sha256:de6424b12887ad884f39a0ee446994ae3cd3b6a00a9cafe1bead85a031132af0 \ + --hash=sha256:e9d0e022c19a78552fb055d0414d47fecb4a649309b9968573daea160ba6869c \ + --hash=sha256:eb61804eb9dbe88c5a2a6c4da8dec1d80d2d0a6f18c999c524e32266cb1ebcd3 \ + --hash=sha256:ebc043cc5a4f0bf22e7680806dbba37ffb19e70f6953bbb44ed1a90aeb5c9bea \ + --hash=sha256:f13f12b3791a266de2d599cb8162925261622a037d87fc03132848343cf68f75 \ + --hash=sha256:fd10b5f994c210f4f6d6761cf686f82d748554adf486cb0979770c3252868c8f # via # feast (pyproject.toml) # docling-ibm-models # easyocr # timm -tornado==6.5.4 \ - --hash=sha256:053e6e16701eb6cbe641f308f4c1a9541f91b6261991160391bfc342e8a551a1 \ - --hash=sha256:1768110f2411d5cd281bac0a090f707223ce77fd110424361092859e089b38d1 \ - --hash=sha256:2d50f63dda1d2cac3ae1fa23d254e16b5e38153758470e9956cbc3d813d40843 \ - --hash=sha256:50ff0a58b0dc97939d29da29cd624da010e7f804746621c78d14b80238669335 \ - --hash=sha256:6076d5dda368c9328ff41ab5d9dd3608e695e8225d1cd0fd1e006f05da3635a8 \ - --hash=sha256:6eb82872335a53dd063a4f10917b3efd28270b56a33db69009606a0312660a6f \ - --hash=sha256:9c86b1643b33a4cd415f8d0fe53045f913bf07b4a3ef646b735a6a86047dda84 \ - --hash=sha256:a22fa9047405d03260b483980635f0b041989d8bcc9a313f8fe18b411d84b1d7 \ - --hash=sha256:d1cf66105dc6acb5af613c054955b8137e34a03698aa53272dbda4afe252be17 \ - --hash=sha256:d6241c1a16b1c9e4cc28148b1cda97dd1c6cb4fb7068ac1bedc610768dff0ba9 \ - --hash=sha256:e5fb5e04efa54cf0baabdd10061eb4148e0be137166146fff835745f59ab9f7f \ - --hash=sha256:fa07d31e0cd85c60713f2b995da613588aa03e1303d75705dca6af8babc18ddc +tornado==6.5.5 \ + --hash=sha256:192b8f3ea91bd7f1f50c06955416ed76c6b72f96779b962f07f911b91e8d30e9 \ + --hash=sha256:2c9a876e094109333f888539ddb2de4361743e5d21eece20688e3e351e4990a6 \ + --hash=sha256:36abed1754faeb80fbd6e64db2758091e1320f6bba74a4cf8c09cd18ccce8aca \ + --hash=sha256:3f54aa540bdbfee7b9eb268ead60e7d199de5021facd276819c193c0fb28ea4e \ + --hash=sha256:435319e9e340276428bbdb4e7fa732c2d399386d1de5686cb331ec8eee754f07 \ + --hash=sha256:487dc9cc380e29f58c7ab88f9e27cdeef04b2140862e5076a66fb6bb68bb1bfa \ + --hash=sha256:6443a794ba961a9f619b1ae926a2e900ac20c34483eea67be4ed8f1e58d3ef7b \ + --hash=sha256:65a7f1d46d4bb41df1ac99f5fcb685fb25c7e61613742d5108b010975a9a6521 \ + --hash=sha256:dd3eafaaeec1c7f2f8fdcd5f964e8907ad788fe8a5a32c4426fbbdda621223b7 \ + --hash=sha256:e74c92e8e65086b338fd56333fb9a68b9f6f2fe7ad532645a290a464bcf46be5 # via # ipykernel # jupyter-client @@ -5932,6 +5952,7 @@ tqdm==4.67.3 \ # milvus-lite # mpire # semchunk + # sentence-transformers # transformers traitlets==5.14.3 \ --hash=sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7 \ @@ -5956,6 +5977,7 @@ transformers==4.57.6 \ # feast (pyproject.toml) # docling-core # docling-ibm-models + # sentence-transformers tree-sitter==0.25.2 \ --hash=sha256:0628671f0de69bb279558ef6b640bcfc97864fe0026d840f872728a86cd6b6cd \ --hash=sha256:0c8b6682cac77e37cfe5cf7ec388844957f48b7bd8d6321d0ca2d852994e10d5 \ @@ -6036,13 +6058,13 @@ tree-sitter-typescript==0.23.2 \ --hash=sha256:c7cc1b0ff5d91bac863b0e38b1578d5505e718156c9db577c8baea2557f66de8 \ --hash=sha256:e96d36b85bcacdeb8ff5c2618d75593ef12ebaf1b4eace3477e2bdb2abb1752c # via docling-core -trino==0.336.0 \ - --hash=sha256:389150841446949119c3c2c13c1a51bb4be1a27818e40ae40dd3701f36c02550 \ - --hash=sha256:e82339e9fffe5c6c51de3bfdf28f083e3ae5945a4502739ab2094a0d08d68070 +trino==0.337.0 \ + --hash=sha256:3a0bd03a09b7ea5dccd41ca6e58abfb127c6303f3a48a258ff794d411dd83a3c \ + --hash=sha256:868f2b8137d4d1baa84c9bc341f2cdf29039462aa69d7c089a0b821b5a91f29c # via feast (pyproject.toml) -typeguard==4.5.0 \ - --hash=sha256:749bea21cdb2553e12831bc29f1eae980b22c7de8331ab67ae7db9e85470b5a7 \ - --hash=sha256:cfda388fc88a9ce42a41890900d6f31ee124bea9b73bb84701a32438e92165c3 +typeguard==4.5.1 \ + --hash=sha256:44d2bf329d49a244110a090b55f5f91aa82d9a9834ebfd30bcc73651e4a8cc40 \ + --hash=sha256:f6f8ecbbc819c9bc749983cc67c02391e16a9b43b8b27f15dc70ed7c4a007274 # via feast (pyproject.toml) typer==0.12.5 \ --hash=sha256:62fe4e471711b147e3365034133904df3e235698399bc4de2b36c8579298d52b \ @@ -6051,9 +6073,9 @@ typer==0.12.5 \ # docling # docling-core # fastapi-mcp -types-cffi==1.17.0.20250915 \ - --hash=sha256:4362e20368f78dabd5c56bca8004752cc890e07a71605d9e0d9e069dbaac8c06 \ - --hash=sha256:cef4af1116c83359c11bb4269283c50f0688e9fc1d7f0eeb390f3661546da52c +types-cffi==2.0.0.20260402 \ + --hash=sha256:47e1320c009f630c59c55c8e3d2b8c501e280babf52e92f6109cbfb0864ba367 \ + --hash=sha256:f647a400fba0a31d603479169d82ee5359db79bd1136e41dc7e6489296e3a2b2 # via types-pyopenssl types-protobuf==3.19.22 \ --hash=sha256:d291388678af91bb045fafa864f142dc4ac22f5d4cdca097c7d8d8a32fa9b3ab \ @@ -6069,13 +6091,13 @@ types-pyopenssl==24.1.0.20240722 \ --hash=sha256:47913b4678a01d879f503a12044468221ed8576263c1540dcb0484ca21b08c39 \ --hash=sha256:6a7a5d2ec042537934cfb4c9d4deb0e16c4c6250b09358df1f083682fe6fda54 # via types-redis -types-python-dateutil==2.9.0.20260124 \ - --hash=sha256:7d2db9f860820c30e5b8152bfe78dbdf795f7d1c6176057424e8b3fdd1f581af \ - --hash=sha256:f802977ae08bf2260142e7ca1ab9d4403772a254409f7bbdf652229997124951 +types-python-dateutil==2.9.0.20260402 \ + --hash=sha256:7827e6a9c93587cc18e766944254d1351a2396262e4abe1510cbbd7601c5e01f \ + --hash=sha256:a980142b9966713acb382c467e35c5cc4208a2f91b10b8d785a0ae6765df6c0b # via feast (pyproject.toml) -types-pytz==2025.2.0.20251108 \ - --hash=sha256:0f1c9792cab4eb0e46c52f8845c8f77cf1e313cb3d68bf826aa867fe4717d91c \ - --hash=sha256:fca87917836ae843f07129567b74c1929f1870610681b4c92cb86a3df5817bdb +types-pytz==2026.1.1.20260402 \ + --hash=sha256:0d9a60ed1c6ad4fce7c6395b5bd2d9827db41d4b83de7c0322cf85869c2bfda3 \ + --hash=sha256:79209aa51dc003a4a6a764234d92b14e5c09a1b7f24e0f00c493929fd33618e8 # via feast (pyproject.toml) types-pyyaml==6.0.12.20250915 \ --hash=sha256:0f8b54a528c303f0e6f7165687dd33fafa81c807fcac23f632b63aa624ced1d3 \ @@ -6089,15 +6111,15 @@ types-requests==2.30.0.0 \ --hash=sha256:c6cf08e120ca9f0dc4fa4e32c3f953c3fba222bcc1db6b97695bce8da1ba9864 \ --hash=sha256:dec781054324a70ba64430ae9e62e7e9c8e4618c185a5cb3f87a6738251b5a31 # via feast (pyproject.toml) -types-setuptools==82.0.0.20260210 \ - --hash=sha256:5124a7daf67f195c6054e0f00f1d97c69caad12fdcf9113eba33eff0bce8cd2b \ - --hash=sha256:d9719fbbeb185254480ade1f25327c4654f8c00efda3fec36823379cebcdee58 +types-setuptools==82.0.0.20260402 \ + --hash=sha256:4b9a9f6c3c4c65107a3956ad6a6acbccec38e398ff6d5f78d5df7f103dadb8d6 \ + --hash=sha256:63d2b10ba7958396ad79bbc24d2f6311484e452daad4637ffd40407983a27069 # via # feast (pyproject.toml) # types-cffi -types-tabulate==0.9.0.20241207 \ - --hash=sha256:ac1ac174750c0a385dfd248edc6279fa328aaf4ea317915ab879a2ec47833230 \ - --hash=sha256:b8dad1343c2a8ba5861c5441370c3e35908edd234ff036d4298708a1d4cf8a85 +types-tabulate==0.10.0.20260308 \ + --hash=sha256:724dcb1330ffba5f46d3cf6e29f45089fccb8e85801e6e7ac9efb1195bf7bea1 \ + --hash=sha256:94a9795965bc6290f844d61e8680a1270040664b88fd12014624090fd847e13c # via feast (pyproject.toml) types-urllib3==1.26.25.14 \ --hash=sha256:229b7f577c951b8c1b92c1bc2b2fdb0b49847bd2af6d1cc2a2e3dd340f3bda8f \ @@ -6127,6 +6149,7 @@ typing-extensions==4.15.0 \ # opentelemetry-api # opentelemetry-sdk # opentelemetry-semantic-conventions + # oracledb # psycopg # psycopg-pool # pydantic @@ -6135,6 +6158,7 @@ typing-extensions==4.15.0 \ # python-docx # python-pptx # referencing + # sentence-transformers # snowflake-connector-python # sqlalchemy # starlette @@ -6164,91 +6188,85 @@ tzlocal==5.3.1 \ # via # great-expectations # trino -ujson==5.11.0 \ - --hash=sha256:0180a480a7d099082501cad1fe85252e4d4bf926b40960fb3d9e87a3a6fbbc80 \ - --hash=sha256:04c41afc195fd477a59db3a84d5b83a871bd648ef371cf8c6f43072d89144eef \ - --hash=sha256:0654a2691fc252c3c525e3d034bb27b8a7546c9d3eb33cd29ce6c9feda361a6a \ - --hash=sha256:090b4d11b380ae25453100b722d0609d5051ffe98f80ec52853ccf8249dfd840 \ - --hash=sha256:109f59885041b14ee9569bf0bb3f98579c3fa0652317b355669939e5fc5ede53 \ - --hash=sha256:10f29e71ecf4ecd93a6610bd8efa8e7b6467454a363c3d6416db65de883eb076 \ - --hash=sha256:1194b943e951092db611011cb8dbdb6cf94a3b816ed07906e14d3bc6ce0e90ab \ - --hash=sha256:12b5e7e22a1fe01058000d1b317d3b65cc3daf61bd2ea7a2b76721fe160fa74d \ - --hash=sha256:16ccb973b7ada0455201808ff11d48fe9c3f034a6ab5bd93b944443c88299f89 \ - --hash=sha256:181fb5b15703a8b9370b25345d2a1fd1359f0f18776b3643d24e13ed9c036d4c \ - --hash=sha256:185f93ebccffebc8baf8302c869fac70dd5dd78694f3b875d03a31b03b062cdb \ - --hash=sha256:1a0a9b76a89827a592656fe12e000cf4f12da9692f51a841a4a07aa4c7ecc41c \ - --hash=sha256:1a325fd2c3a056cf6c8e023f74a0c478dd282a93141356ae7f16d5309f5ff823 \ - --hash=sha256:1aa8a2ab482f09f6c10fba37112af5f957689a79ea598399c85009f2f29898b5 \ - --hash=sha256:1d663b96eb34c93392e9caae19c099ec4133ba21654b081956613327f0e973ac \ - --hash=sha256:29113c003ca33ab71b1b480bde952fbab2a0b6b03a4ee4c3d71687cdcbd1a29d \ - --hash=sha256:30f607c70091483550fbd669a0b37471e5165b317d6c16e75dba2aa967608723 \ - --hash=sha256:3134b783ab314d2298d58cda7e47e7a0f7f71fc6ade6ac86d5dbeaf4b9770fa6 \ - --hash=sha256:34032aeca4510a7c7102bd5933f59a37f63891f30a0706fb46487ab6f0edf8f0 \ - --hash=sha256:3772e4fe6b0c1e025ba3c50841a0ca4786825a4894c8411bf8d3afe3a8061328 \ - --hash=sha256:3d2720e9785f84312b8e2cb0c2b87f1a0b1c53aaab3b2af3ab817d54409012e0 \ - --hash=sha256:416389ec19ef5f2013592f791486bef712ebce0cd59299bf9df1ba40bb2f6e04 \ - --hash=sha256:446e8c11c06048611c9d29ef1237065de0af07cabdd97e6b5b527b957692ec25 \ - --hash=sha256:4598bf3965fc1a936bd84034312bcbe00ba87880ef1ee33e33c1e88f2c398b49 \ - --hash=sha256:48055e1061c1bb1f79e75b4ac39e821f3f35a9b82de17fce92c3140149009bec \ - --hash=sha256:4843f3ab4fe1cc596bb7e02228ef4c25d35b4bb0809d6a260852a4bfcab37ba3 \ - --hash=sha256:49e56ef8066f11b80d620985ae36869a3ff7e4b74c3b6129182ec5d1df0255f3 \ - --hash=sha256:4b42c115c7c6012506e8168315150d1e3f76e7ba0f4f95616f4ee599a1372bbc \ - --hash=sha256:4c9f5d6a27d035dd90a146f7761c2272cf7103de5127c9ab9c4cd39ea61e878a \ - --hash=sha256:5600202a731af24a25e2d7b6eb3f648e4ecd4bb67c4d5cf12f8fab31677469c9 \ - --hash=sha256:65724738c73645db88f70ba1f2e6fb678f913281804d5da2fd02c8c5839af302 \ - --hash=sha256:65f3c279f4ed4bf9131b11972040200c66ae040368abdbb21596bf1564899694 \ - --hash=sha256:674f306e3e6089f92b126eb2fe41bcb65e42a15432c143365c729fdb50518547 \ - --hash=sha256:683f57f0dd3acdd7d9aff1de0528d603aafcb0e6d126e3dc7ce8b020a28f5d01 \ - --hash=sha256:6b6ec7e7321d7fc19abdda3ad809baef935f49673951a8bab486aea975007e02 \ - --hash=sha256:6cd2df62f24c506a0ba322d5e4fe4466d47a9467b57e881ee15a31f7ecf68ff6 \ - --hash=sha256:6dd703c3e86dc6f7044c5ac0b3ae079ed96bf297974598116aa5fb7f655c3a60 \ - --hash=sha256:6eff24e1abd79e0ec6d7eae651dd675ddbc41f9e43e29ef81e16b421da896915 \ - --hash=sha256:7855ccea3f8dad5e66d8445d754fc1cf80265a4272b5f8059ebc7ec29b8d0835 \ - --hash=sha256:787aff4a84da301b7f3bac09bc696e2e5670df829c6f8ecf39916b4e7e24e701 \ - --hash=sha256:7895f0d2d53bd6aea11743bd56e3cb82d729980636cd0ed9b89418bf66591702 \ - --hash=sha256:78c684fb21255b9b90320ba7e199780f653e03f6c2528663768965f4126a5b50 \ - --hash=sha256:7e0ec1646db172beb8d3df4c32a9d78015e671d2000af548252769e33079d9a6 \ - --hash=sha256:7e3cff632c1d78023b15f7e3a81c3745cd3f94c044d1e8fa8efbd6b161997bbc \ - --hash=sha256:7f1a27ab91083b4770e160d17f61b407f587548f2c2b5fbf19f94794c495594a \ - --hash=sha256:80017e870d882d5517d28995b62e4e518a894f932f1e242cbc802a2fd64d365c \ - --hash=sha256:8254e858437c00f17cb72e7a644fc42dad0ebb21ea981b71df6e84b1072aaa7c \ - --hash=sha256:837da4d27fed5fdc1b630bd18f519744b23a0b5ada1bbde1a36ba463f2900c03 \ - --hash=sha256:849e65b696f0d242833f1df4182096cedc50d414215d1371fca85c541fbff629 \ - --hash=sha256:85e6796631165f719084a9af00c79195d3ebf108151452fefdcb1c8bb50f0105 \ - --hash=sha256:86baf341d90b566d61a394869ce77188cc8668f76d7bb2c311d77a00f4bdf844 \ - --hash=sha256:8fa2af7c1459204b7a42e98263b069bd535ea0cd978b4d6982f35af5a04a4241 \ - --hash=sha256:94fcae844f1e302f6f8095c5d1c45a2f0bfb928cccf9f1b99e3ace634b980a2a \ - --hash=sha256:952c0be400229940248c0f5356514123d428cba1946af6fa2bbd7503395fef26 \ - --hash=sha256:99c49400572cd77050894e16864a335225191fd72a818ea6423ae1a06467beac \ - --hash=sha256:9aacbeb23fdbc4b256a7d12e0beb9063a1ba5d9e0dbb2cfe16357c98b4334596 \ - --hash=sha256:a0af6574fc1d9d53f4ff371f58c96673e6d988ed2b5bf666a6143c782fa007e9 \ - --hash=sha256:a31c6b8004438e8c20fc55ac1c0e07dad42941db24176fe9acf2815971f8e752 \ - --hash=sha256:a4df61a6df0a4a8eb5b9b1ffd673429811f50b235539dac586bb7e9e91994138 \ - --hash=sha256:a638425d3c6eed0318df663df44480f4a40dc87cc7c6da44d221418312f6413b \ - --hash=sha256:aa6b3d4f1c0d3f82930f4cbd7fe46d905a4a9205a7c13279789c1263faf06dba \ - --hash=sha256:aa6d7a5e09217ff93234e050e3e380da62b084e26b9f2e277d2606406a2fc2e5 \ - --hash=sha256:ab2cb8351d976e788669c8281465d44d4e94413718af497b4e7342d7b2f78018 \ - --hash=sha256:abae0fb58cc820092a0e9e8ba0051ac4583958495bfa5262a12f628249e3b362 \ - --hash=sha256:b16930f6a0753cdc7d637b33b4e8f10d5e351e1fb83872ba6375f1e87be39746 \ - --hash=sha256:b7b136cc6abc7619124fd897ef75f8e63105298b5ca9bdf43ebd0e1fa0ee105f \ - --hash=sha256:be6b0eaf92cae8cdee4d4c9e074bde43ef1c590ed5ba037ea26c9632fb479c88 \ - --hash=sha256:c44c703842024d796b4c78542a6fcd5c3cb948b9fc2a73ee65b9c86a22ee3638 \ - --hash=sha256:c6618f480f7c9ded05e78a1938873fde68baf96cdd74e6d23c7e0a8441175c4b \ - --hash=sha256:ce076f2df2e1aa62b685086fbad67f2b1d3048369664b4cdccc50707325401f9 \ - --hash=sha256:d06e87eded62ff0e5f5178c916337d2262fdbc03b31688142a3433eabb6511db \ - --hash=sha256:d7c46cb0fe5e7056b9acb748a4c35aa1b428025853032540bb7e41f46767321f \ - --hash=sha256:d8951bb7a505ab2a700e26f691bdfacf395bc7e3111e3416d325b513eea03a58 \ - --hash=sha256:da473b23e3a54448b008d33f742bcd6d5fb2a897e42d1fc6e7bf306ea5d18b1b \ - --hash=sha256:de6e88f62796372fba1de973c11138f197d3e0e1d80bcb2b8aae1e826096d433 \ - --hash=sha256:e204ae6f909f099ba6b6b942131cee359ddda2b6e4ea39c12eb8b991fe2010e0 \ - --hash=sha256:e73df8648c9470af2b6a6bf5250d4744ad2cf3d774dcf8c6e31f018bdd04d764 \ - --hash=sha256:e750c436fb90edf85585f5c62a35b35082502383840962c6983403d1bd96a02c \ - --hash=sha256:e979fbc469a7f77f04ec2f4e853ba00c441bf2b06720aa259f0f720561335e34 \ - --hash=sha256:ecd6ff8a3b5a90c292c2396c2d63c687fd0ecdf17de390d852524393cd9ed052 \ - --hash=sha256:f278b31a7c52eb0947b2db55a5133fbc46b6f0ef49972cd1a80843b72e135aba \ - --hash=sha256:f62b9976fabbcde3ab6e413f4ec2ff017749819a0786d84d7510171109f2d53c \ - --hash=sha256:fa79fdb47701942c2132a9dd2297a1a85941d966d8c87bfd9e29b0cf423f26cc \ - --hash=sha256:fac6c0649d6b7c3682a0a6e18d3de6857977378dce8d419f57a0b20e3d775b39 +ujson==5.12.0 \ + --hash=sha256:006428d3813b87477d72d306c40c09f898a41b968e57b15a7d88454ecc42a3fb \ + --hash=sha256:02f93da7a4115e24f886b04fd56df1ee8741c2ce4ea491b7ab3152f744ad8f8e \ + --hash=sha256:0727363b05ab05ee737a28f6200dc4078bce6b0508e10bd8aab507995a15df61 \ + --hash=sha256:085b6ce182cdd6657481c7c4003a417e0655c4f6e58b76f26ee18f0ae21db827 \ + --hash=sha256:09b4beff9cc91d445d5818632907b85fb06943b61cb346919ce202668bf6794a \ + --hash=sha256:0a3ae28f0b209be5af50b54ca3e2123a3de3a57d87b75f1e5aa3d7961e041983 \ + --hash=sha256:0d2e8db5ade3736a163906154ca686203acc7d1d30736cbf577c730d13653d84 \ + --hash=sha256:0e00cec383eab2406c9e006bd4edb55d284e94bb943fda558326048178d26961 \ + --hash=sha256:0fe6b8b8968e11dd9b2348bd508f0f57cf49ab3512064b36bc4117328218718e \ + --hash=sha256:0fe9128e75c6aa6e9ae06c1408d6edd9179a2fef0fe6d9cda3166b887eba521d \ + --hash=sha256:14b2e1eb528d77bc0f4c5bd1a7ebc05e02b5b41beefb7e8567c9675b8b13bcf4 \ + --hash=sha256:15d416440148f3e56b9b244fdaf8a09fcf5a72e4944b8e119f5bf60417a2bfc8 \ + --hash=sha256:15e555c4caca42411270b2ed2b2ebc7b3a42bb04138cef6c956e1f1d49709fe2 \ + --hash=sha256:16b4fe9c97dc605f5e1887a9e1224287291e35c56cbc379f8aa44b6b7bcfe2bb \ + --hash=sha256:1b5c6ceb65fecd28a1d20d1eba9dbfa992612b86594e4b6d47bb580d2dd6bcb3 \ + --hash=sha256:1d072a403d82aef8090c6d4f728e3a727dfdba1ad3b7fa3a052c3ecbd37e73cb \ + --hash=sha256:2324d9a0502317ffc35d38e153c1b2fa9610ae03775c9d0f8d0cca7b8572b04e \ + --hash=sha256:2a248750abce1c76fbd11b2e1d88b95401e72819295c3b851ec73399d6849b3d \ + --hash=sha256:2ea6206043385343aff0b7da65cf73677f6f5e50de8f1c879e557f4298cac36a \ + --hash=sha256:31348a0ffbfc815ce78daac569d893349d85a0b57e1cd2cdbba50b7f333784da \ + --hash=sha256:38051f36423f084b909aaadb3b41c9c6a2958e86956ba21a8489636911e87504 \ + --hash=sha256:3c2f947e55d3c7cfe124dd4521ee481516f3007d13c6ad4bf6aeb722e190eb1b \ + --hash=sha256:3ed5cb149892141b1e77ef312924a327f2cc718b34247dae346ed66329e1b8be \ + --hash=sha256:3ff4ede90ed771140caa7e1890de17431763a483c54b3c1f88bd30f0cc1affc0 \ + --hash=sha256:40aa43a7a3a8d2f05e79900858053d697a88a605e3887be178b43acbcd781161 \ + --hash=sha256:42d875388fbd091c7ea01edfff260f839ba303038ffb23475ef392012e4d63dd \ + --hash=sha256:457fabc2700a8e6ddb85bc5a1d30d3345fe0d3ec3ee8161a4e032ec585801dfa \ + --hash=sha256:460e76a4daff214ae33ab959494962c93918cb44714ea3e3f748b14aa37f8a87 \ + --hash=sha256:50524f4f6a1c839714dbaff5386a1afb245d2d5ec8213a01fbc99cea7307811e \ + --hash=sha256:51acc750ec7a2df786cdc868fb16fa04abd6269a01d58cf59bafc57978773d8e \ + --hash=sha256:55ede2a7a051b3b7e71a394978a098d71b3783e6b904702ff45483fad434ae2d \ + --hash=sha256:561f89cc82deeae82e37d4a4764184926fb432f740a9691563a391b13f7339a4 \ + --hash=sha256:56ba3f7abbd6b0bb282a544dc38406d1a188d8bb9164f49fdb9c2fee62cb29da \ + --hash=sha256:57930ac9519099b852e190d2c04b1fb5d97ea128db33bce77ed874eccb4c7f09 \ + --hash=sha256:58a11cb49482f1a095a2bd9a1d81dd7c8fb5d2357f959ece85db4e46a825fd00 \ + --hash=sha256:64df53eef4ac857eb5816a56e2885ccf0d7dff6333c94065c93b39c51063e01d \ + --hash=sha256:6879aed770557f0961b252648d36f6fdaab41079d37a2296b5649fd1b35608e0 \ + --hash=sha256:6ad57654570464eb1b040b5c353dee442608e06cff9102b8fcb105565a44c9ed \ + --hash=sha256:6c0aed6a4439994c9666fb8a5b6c4eac94d4ef6ddc95f9b806a599ef83547e3b \ + --hash=sha256:76bf3e7406cf23a3e1ca6a23fb1fb9ea82f4f6bd226fe226e09146b0194f85dc \ + --hash=sha256:7bbf05c38debc90d1a195b11340cc85cb43ab3e753dc47558a3a84a38cbc72da \ + --hash=sha256:7ddb08b3c2f9213df1f2e3eb2fbea4963d80ec0f8de21f0b59898e34f3b3d96d \ + --hash=sha256:7e07f6f644d2c44d53b7a320a084eef98063651912c1b9449b5f45fcbdc6ccd2 \ + --hash=sha256:85833bca01aa5cae326ac759276dc175c5fa3f7b3733b7d543cf27f2df12d1ef \ + --hash=sha256:8712b61eb1b74a4478cfd1c54f576056199e9f093659334aeb5c4a6b385338e5 \ + --hash=sha256:871c0e5102e47995b0e37e8df7819a894a6c3da0d097545cd1f9f1f7d7079927 \ + --hash=sha256:89e302abd3749f6d6699691747969a5d85f7c73081d5ed7e2624c7bd9721a2ab \ + --hash=sha256:937794042342006f707837f38d721426b11b0774d327a2a45c0bd389eb750a87 \ + --hash=sha256:93bc91fdadcf046da37a214eaa714574e7e9b1913568e93bb09527b2ceb7f759 \ + --hash=sha256:94c5f1621cbcab83c03be46441f090b68b9f307b6c7ec44d4e3f6d5997383df4 \ + --hash=sha256:973b7d7145b1ac553a7466a64afa8b31ec2693d7c7fff6a755059e0a2885dfd2 \ + --hash=sha256:99cc80facad240b0c2fb5a633044420878aac87a8e7c348b9486450cba93f27c \ + --hash=sha256:9a5fcbe7b949f2e95c47ea8a80b410fcdf2da61c98553b45a4ee875580418b68 \ + --hash=sha256:9b3b86ec3e818f3dd3e13a9de628e88a9990f4af68ecb0b12dd3de81227f0a26 \ + --hash=sha256:9b3cf13facf6f77c283af0e1713e5e8c47a0fe295af81326cb3cb4380212e797 \ + --hash=sha256:9c5a52987a990eb1bae55f9000994f1afdb0326c154fb089992f839ab3c30688 \ + --hash=sha256:a2d79c6635ccffcbfc1d5c045874ba36b594589be81d50d43472570bb8de9c57 \ + --hash=sha256:a6ec5bf6bc361f2f0f9644907a36ce527715b488988a8df534120e5c34eeda94 \ + --hash=sha256:a7bf9cc97f05048ac8f3e02cd58f0fe62b901453c24345bfde287f4305dcc31c \ + --hash=sha256:ab9056d94e5db513d9313b34394f3a3b83e6301a581c28ad67773434f3faccab \ + --hash=sha256:adf28d13a33f9d750fe7a78fb481cac298fa257d8863d8727b2ea4455ea41235 \ + --hash=sha256:b62cb9a7501e1f5c9ffe190485501349c33e8862dde4377df774e40b8166871f \ + --hash=sha256:bacbd3c69862478cbe1c7ed4325caedec580d8acf31b8ee1b9a1e02a56295cad \ + --hash=sha256:bb349dbba57c76eec25e5917e07f35aabaf0a33b9e67fc13d188002500106487 \ + --hash=sha256:bd03472c36fa3a386a6deb887113b9e3fa40efba8203eb4fe786d3c0ccc724f6 \ + --hash=sha256:bf85a00ac3b56a1e7a19c5be7b02b5180a0895ac4d3c234d717a55e86960691c \ + --hash=sha256:ca0c7ce828bb76ab78b3991904b477c2fd0f711d7815c252d1ef28ff9450b052 \ + --hash=sha256:ccbfd94e59aad4a2566c71912b55f0547ac1680bfac25eb138e6703eb3dd434e \ + --hash=sha256:d1831c07bd4dce53c4b666fa846c7eba4b7c414f2e641a4585b7f50b72f502dc \ + --hash=sha256:d22cad98c2a10bbf6aa083a8980db6ed90d4285a841c4de892890c2b28286ef9 \ + --hash=sha256:d30ad4359413c8821cc7b3707f7ca38aa8bc852ba3b9c5a759ee2d7740157315 \ + --hash=sha256:e0dd3676ea0837cd70ea1879765e9e9f6be063be0436de9b3ea4b775caf83654 \ + --hash=sha256:e584d0cdd37cac355aca52ed788d1a2d939d6837e2870d3b70e585db24025a50 \ + --hash=sha256:e6369ac293d2cc40d52577e4fa3d75a70c1aae2d01fa3580a34a4e6eff9286b9 \ + --hash=sha256:efae5df7a8cc8bdb1037b0f786b044ce281081441df5418c3a0f0e1f86fe7bb3 \ + --hash=sha256:f19b3af31d02a2e79c5f9a6deaab0fb3c116456aeb9277d11720ad433de6dfc6 \ + --hash=sha256:f7a0430d765f9bda043e6aefaba5944d5f21ec43ff4774417d7e296f61917382 \ + --hash=sha256:fb94245a715b4d6e24689de12772b85329a1f9946cbf6187923a64ecdea39e65 # via pymilvus uri-template==1.3.0 \ --hash=sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7 \ @@ -6264,6 +6282,7 @@ urllib3==2.6.3 \ # docker # elastic-transport # great-expectations + # kube-authkit # kubernetes # minio # qdrant-client @@ -6534,9 +6553,9 @@ websockets==16.0 \ --hash=sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da \ --hash=sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4 # via uvicorn -werkzeug==3.1.5 \ - --hash=sha256:5111e36e91086ece91f93268bb39b4a35c1e6f1feac762c9c822ded0a4e322dc \ - --hash=sha256:6a548b0e88955dd07ccb25539d7d0cc97417ee9e179677d22c7041c8f078ce67 +werkzeug==3.1.8 \ + --hash=sha256:63a77fb8892bf28ebc3178683445222aa500e48ebad5ec77b0ad80f8726b1f50 \ + --hash=sha256:9bad61a4268dac112f1c5cd4630a56ede601b6ed420300677a869083d70a4c44 # via moto wheel==0.46.3 \ --hash=sha256:4b399d56c9d9338230118d705d9737a2a468ccca63d5e813e2a4fc7815d8bc4d \ @@ -6638,9 +6657,9 @@ xlsxwriter==3.2.9 \ --hash=sha256:254b1c37a368c444eac6e2f867405cc9e461b0ed97a3233b2ac1e574efb4140c \ --hash=sha256:9a5db42bc5dff014806c58a20b9eae7322a134abb6fce3c92c181bfb275ec5b3 # via python-pptx -xmltodict==1.0.3 \ - --hash=sha256:35d65d5c08f2a1121df338a0c4e49ca638480fa7c1b899ded45e0759bf32e40e \ - --hash=sha256:3bf1f49c7836df34cf6d9cc7e690c4351f7dfff2ab0b8a1988bba4a9b9474909 +xmltodict==1.0.4 \ + --hash=sha256:6d94c9f834dd9e44514162799d344d815a3a4faec913717a9ecbfa5be1bb8e61 \ + --hash=sha256:a4a00d300b0e1c59fc2bfccb53d7b2e88c32f200df138a0dd2229f842497026a # via moto xxhash==3.6.0 \ --hash=sha256:01262da8798422d0685f7cef03b2bd3f4f46511b02830861df548d7def4402ad \ @@ -6784,137 +6803,135 @@ xxhash==3.6.0 \ --hash=sha256:fba27a198363a7ef87f8c0f6b171ec36b674fe9053742c58dd7e3201c1ab30ee \ --hash=sha256:ffc578717a347baf25be8397cb10d2528802d24f94cfc005c0e44fef44b5cdd6 # via datasets -yarl==1.22.0 \ - --hash=sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a \ - --hash=sha256:029866bde8d7b0878b9c160e72305bbf0a7342bcd20b9999381704ae03308dc8 \ - --hash=sha256:078278b9b0b11568937d9509b589ee83ef98ed6d561dfe2020e24a9fd08eaa2b \ - --hash=sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da \ - --hash=sha256:07a524d84df0c10f41e3ee918846e1974aba4ec017f990dc735aad487a0bdfdf \ - --hash=sha256:088e4e08f033db4be2ccd1f34cf29fe994772fb54cfe004bbf54db320af56890 \ - --hash=sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093 \ - --hash=sha256:0cf71bf877efeac18b38d3930594c0948c82b64547c1cf420ba48722fe5509f6 \ - --hash=sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79 \ - --hash=sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683 \ - --hash=sha256:10619d9fdee46d20edc49d3479e2f8269d0779f1b031e6f7c2aa1c76be04b7ed \ - --hash=sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2 \ - --hash=sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff \ - --hash=sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02 \ - --hash=sha256:14291620375b1060613f4aab9ebf21850058b6b1b438f386cc814813d901c60b \ - --hash=sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03 \ - --hash=sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511 \ - --hash=sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c \ - --hash=sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124 \ - --hash=sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c \ - --hash=sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da \ - --hash=sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2 \ - --hash=sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0 \ - --hash=sha256:2e4e1f6f0b4da23e61188676e3ed027ef0baa833a2e633c29ff8530800edccba \ - --hash=sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d \ - --hash=sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53 \ - --hash=sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138 \ - --hash=sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4 \ - --hash=sha256:3aa27acb6de7a23785d81557577491f6c38a5209a254d1191519d07d8fe51748 \ - --hash=sha256:3b06bcadaac49c70f4c88af4ffcfbe3dc155aab3163e75777818092478bcbbe7 \ - --hash=sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d \ - --hash=sha256:3e2daa88dc91870215961e96a039ec73e4937da13cf77ce17f9cad0c18df3503 \ - --hash=sha256:3ea66b1c11c9150f1372f69afb6b8116f2dd7286f38e14ea71a44eee9ec51b9d \ - --hash=sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2 \ - --hash=sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa \ - --hash=sha256:437840083abe022c978470b942ff832c3940b2ad3734d424b7eaffcd07f76737 \ - --hash=sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f \ - --hash=sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1 \ - --hash=sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d \ - --hash=sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694 \ - --hash=sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3 \ - --hash=sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a \ - --hash=sha256:4c52a6e78aef5cf47a98ef8e934755abf53953379b7d53e68b15ff4420e6683d \ - --hash=sha256:4dcc74149ccc8bba31ce1944acee24813e93cfdee2acda3c172df844948ddf7b \ - --hash=sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a \ - --hash=sha256:51af598701f5299012b8416486b40fceef8c26fc87dc6d7d1f6fc30609ea0aa6 \ - --hash=sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b \ - --hash=sha256:595697f68bd1f0c1c159fcb97b661fc9c3f5db46498043555d04805430e79bea \ - --hash=sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5 \ - --hash=sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f \ - --hash=sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df \ - --hash=sha256:5cdac20da754f3a723cceea5b3448e1a2074866406adeb4ef35b469d089adb8f \ - --hash=sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b \ - --hash=sha256:5dbeefd6ca588b33576a01b0ad58aa934bc1b41ef89dee505bf2932b22ddffba \ - --hash=sha256:62441e55958977b8167b2709c164c91a6363e25da322d87ae6dd9c6019ceecf9 \ - --hash=sha256:663e1cadaddae26be034a6ab6072449a8426ddb03d500f43daf952b74553bba0 \ - --hash=sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6 \ - --hash=sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b \ - --hash=sha256:6944b2dc72c4d7f7052683487e3677456050ff77fcf5e6204e98caf785ad1967 \ - --hash=sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2 \ - --hash=sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708 \ - --hash=sha256:6dcbb0829c671f305be48a7227918cfcd11276c2d637a8033a99a02b67bf9eda \ - --hash=sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8 \ - --hash=sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10 \ - --hash=sha256:75976c6945d85dbb9ee6308cd7ff7b1fb9409380c82d6119bd778d8fcfe2931c \ - --hash=sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b \ - --hash=sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028 \ - --hash=sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e \ - --hash=sha256:80ddf7a5f8c86cb3eb4bc9028b07bbbf1f08a96c5c0bc1244be5e8fefcb94147 \ - --hash=sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33 \ - --hash=sha256:84fc3ec96fce86ce5aa305eb4aa9358279d1aa644b71fab7b8ed33fe3ba1a7ca \ - --hash=sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590 \ - --hash=sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c \ - --hash=sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53 \ - --hash=sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74 \ - --hash=sha256:99b6fc1d55782461b78221e95fc357b47ad98b041e8e20f47c1411d0aacddc60 \ - --hash=sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f \ - --hash=sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1 \ - --hash=sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27 \ - --hash=sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520 \ - --hash=sha256:a4fcfc8eb2c34148c118dfa02e6427ca278bfd0f3df7c5f99e33d2c0e81eae3e \ - --hash=sha256:a899cbd98dce6f5d8de1aad31cb712ec0a530abc0a86bd6edaa47c1090138467 \ - --hash=sha256:a9b1ba5610a4e20f655258d5a1fdc7ebe3d837bb0e45b581398b99eb98b1f5ca \ - --hash=sha256:af74f05666a5e531289cb1cc9c883d1de2088b8e5b4de48004e5ca8a830ac859 \ - --hash=sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273 \ - --hash=sha256:b266bd01fedeffeeac01a79ae181719ff848a5a13ce10075adbefc8f1daee70e \ - --hash=sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601 \ - --hash=sha256:b580e71cac3f8113d3135888770903eaf2f507e9421e5697d6ee6d8cd1c7f054 \ - --hash=sha256:b6a6f620cfe13ccec221fa312139135166e47ae169f8253f72a0abc0dae94376 \ - --hash=sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7 \ - --hash=sha256:b85b982afde6df99ecc996990d4ad7ccbdbb70e2a4ba4de0aecde5922ba98a0b \ - --hash=sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb \ - --hash=sha256:ba440ae430c00eee41509353628600212112cd5018d5def7e9b05ea7ac34eb65 \ - --hash=sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784 \ - --hash=sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71 \ - --hash=sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b \ - --hash=sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a \ - --hash=sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c \ - --hash=sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face \ - --hash=sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d \ - --hash=sha256:c7bd6683587567e5a49ee6e336e0612bec8329be1b7d4c8af5687dcdeb67ee1e \ - --hash=sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e \ - --hash=sha256:cb95a9b1adaa48e41815a55ae740cfda005758104049a640a398120bf02515ca \ - --hash=sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9 \ - --hash=sha256:d332fc2e3c94dad927f2112395772a4e4fedbcf8f80efc21ed7cdfae4d574fdb \ - --hash=sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95 \ - --hash=sha256:d5372ca1df0f91a86b047d1277c2aaf1edb32d78bbcefffc81b40ffd18f027ed \ - --hash=sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf \ - --hash=sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca \ - --hash=sha256:dd7afd3f8b0bfb4e0d9fc3c31bfe8a4ec7debe124cfd90619305def3c8ca8cd2 \ - --hash=sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62 \ - --hash=sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df \ - --hash=sha256:e1b329cb8146d7b736677a2440e422eadd775d1806a81db2d4cded80a48efc1a \ - --hash=sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67 \ - --hash=sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f \ - --hash=sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529 \ - --hash=sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486 \ - --hash=sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a \ - --hash=sha256:e6438cc8f23a9c1478633d216b16104a586b9761db62bfacb6425bac0a36679e \ - --hash=sha256:e81fda2fb4a07eda1a2252b216aa0df23ebcd4d584894e9612e80999a78fd95b \ - --hash=sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74 \ - --hash=sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d \ - --hash=sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b \ - --hash=sha256:f0d97c18dfd9a9af4490631905a3f131a8e4c9e80a39353919e2cfed8f00aedc \ - --hash=sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2 \ - --hash=sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e \ - --hash=sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8 \ - --hash=sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82 \ - --hash=sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd \ - --hash=sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249 +yarl==1.23.0 \ + --hash=sha256:03214408cfa590df47728b84c679ae4ef00be2428e11630277be0727eba2d7cc \ + --hash=sha256:041b1a4cefacf65840b4e295c6985f334ba83c30607441ae3cf206a0eed1a2e4 \ + --hash=sha256:0793e2bd0cf14234983bbb371591e6bea9e876ddf6896cdcc93450996b0b5c85 \ + --hash=sha256:0e1fdaa14ef51366d7757b45bde294e95f6c8c049194e793eedb8387c86d5993 \ + --hash=sha256:0e40111274f340d32ebcc0a5668d54d2b552a6cca84c9475859d364b380e3222 \ + --hash=sha256:115136c4a426f9da976187d238e84139ff6b51a20839aa6e3720cd1026d768de \ + --hash=sha256:13a563739ae600a631c36ce096615fe307f131344588b0bc0daec108cdb47b25 \ + --hash=sha256:16c6994ac35c3e74fb0ae93323bf8b9c2a9088d55946109489667c510a7d010e \ + --hash=sha256:170e26584b060879e29fac213e4228ef063f39128723807a312e5c7fec28eff2 \ + --hash=sha256:17235362f580149742739cc3828b80e24029d08cbb9c4bda0242c7b5bc610a8e \ + --hash=sha256:1932b6b8bba8d0160a9d1078aae5838a66039e8832d41d2992daa9a3a08f7860 \ + --hash=sha256:1b6b572edd95b4fa8df75de10b04bc81acc87c1c7d16bcdd2035b09d30acc957 \ + --hash=sha256:1c3a3598a832590c5a3ce56ab5576361b5688c12cb1d39429cf5dba30b510760 \ + --hash=sha256:1c57676bdedc94cd3bc37724cf6f8cd2779f02f6aba48de45feca073e714fe52 \ + --hash=sha256:1dc702e42d0684f42d6519c8d581e49c96cefaaab16691f03566d30658ee8788 \ + --hash=sha256:21d1b7305a71a15b4794b5ff22e8eef96ff4a6d7f9657155e5aa419444b28912 \ + --hash=sha256:23f371bd662cf44a7630d4d113101eafc0cfa7518a2760d20760b26021454719 \ + --hash=sha256:2569b67d616eab450d262ca7cb9f9e19d2f718c70a8b88712859359d0ab17035 \ + --hash=sha256:263cd4f47159c09b8b685890af949195b51d1aa82ba451c5847ca9bc6413c220 \ + --hash=sha256:2803ed8b21ca47a43da80a6fd1ed3019d30061f7061daa35ac54f63933409412 \ + --hash=sha256:2a6940a074fb3c48356ed0158a3ca5699c955ee4185b4d7d619be3c327143e05 \ + --hash=sha256:2e27c8841126e017dd2a054a95771569e6070b9ee1b133366d8b31beb5018a41 \ + --hash=sha256:31c9921eb8bd12633b41ad27686bbb0b1a2a9b8452bfdf221e34f311e9942ed4 \ + --hash=sha256:34b6cf500e61c90f305094911f9acc9c86da1a05a7a3f5be9f68817043f486e4 \ + --hash=sha256:3650dc2480f94f7116c364096bc84b1d602f44224ef7d5c7208425915c0475dd \ + --hash=sha256:389871e65468400d6283c0308e791a640b5ab5c83bcee02a2f51295f95e09748 \ + --hash=sha256:39004f0ad156da43e86aa71f44e033de68a44e5a31fc53507b36dd253970054a \ + --hash=sha256:394906945aa8b19fc14a61cf69743a868bb8c465efe85eee687109cc540b98f4 \ + --hash=sha256:3ceb13c5c858d01321b5d9bb65e4cf37a92169ea470b70fec6f236b2c9dd7e34 \ + --hash=sha256:411225bae281f114067578891bc75534cfb3d92a3b4dfef7a6ca78ba354e6069 \ + --hash=sha256:44bb7bef4ea409384e3f8bc36c063d77ea1b8d4a5b2706956c0d6695f07dcc25 \ + --hash=sha256:4503053d296bc6e4cbd1fad61cf3b6e33b939886c4f249ba7c78b602214fabe2 \ + --hash=sha256:4764a6a7588561a9aef92f65bda2c4fb58fe7c675c0883862e6df97559de0bfb \ + --hash=sha256:4966242ec68afc74c122f8459abd597afd7d8a60dc93d695c1334c5fd25f762f \ + --hash=sha256:4a42e651629dafb64fd5b0286a3580613702b5809ad3f24934ea87595804f2c5 \ + --hash=sha256:4a59ba56f340334766f3a4442e0efd0af895fae9e2b204741ef885c446b3a1a8 \ + --hash=sha256:4c41e021bc6d7affb3364dc1e1e5fa9582b470f283748784bd6ea0558f87f42c \ + --hash=sha256:5023346c4ee7992febc0068e7593de5fa2bf611848c08404b35ebbb76b1b0512 \ + --hash=sha256:50f9d8d531dfb767c565f348f33dd5139a6c43f5cbdf3f67da40d54241df93f6 \ + --hash=sha256:51430653db848d258336cfa0244427b17d12db63d42603a55f0d4546f50f25b5 \ + --hash=sha256:531ef597132086b6cf96faa7c6c1dcd0361dd5f1694e5cc30375907b9b7d3ea9 \ + --hash=sha256:53ad387048f6f09a8969631e4de3f1bf70c50e93545d64af4f751b2498755072 \ + --hash=sha256:53b1ea6ca88ebd4420379c330aea57e258408dd0df9af0992e5de2078dc9f5d5 \ + --hash=sha256:575aa4405a656e61a540f4a80eaa5260f2a38fff7bfdc4b5f611840d76e9e277 \ + --hash=sha256:578110dd426f0d209d1509244e6d4a3f1a3e9077655d98c5f22583d63252a08a \ + --hash=sha256:5ec2f42d41ccbd5df0270d7df31618a8ee267bfa50997f5d720ddba86c4a83a6 \ + --hash=sha256:5ee586fb17ff8f90c91cf73c6108a434b02d69925f44f5f8e0d7f2f260607eae \ + --hash=sha256:5f10fd85e4b75967468af655228fbfd212bdf66db1c0d135065ce288982eda26 \ + --hash=sha256:609d3614d78d74ebe35f54953c5bbd2ac647a7ddb9c30a5d877580f5e86b22f2 \ + --hash=sha256:62694e275c93d54f7ccedcfef57d42761b2aad5234b6be1f3e3026cae4001cd4 \ + --hash=sha256:63e92247f383c85ab00dd0091e8c3fa331a96e865459f5ee80353c70a4a42d70 \ + --hash=sha256:682bae25f0a0dd23a056739f23a134db9f52a63e2afd6bfb37ddc76292bbd723 \ + --hash=sha256:6b41389c19b07c760c7e427a3462e8ab83c4bb087d127f0e854c706ce1b9215c \ + --hash=sha256:6e87a6e8735b44816e7db0b2fbc9686932df473c826b0d9743148432e10bb9b9 \ + --hash=sha256:6f0fd84de0c957b2d280143522c4f91a73aada1923caee763e24a2b3fda9f8a5 \ + --hash=sha256:70efd20be968c76ece7baa8dafe04c5be06abc57f754d6f36f3741f7aa7a208e \ + --hash=sha256:71d006bee8397a4a89f469b8deb22469fe7508132d3c17fa6ed871e79832691c \ + --hash=sha256:73309162a6a571d4cbd3b6a1dcc703c7311843ae0d1578df6f09be4e98df38d4 \ + --hash=sha256:75e3026ab649bf48f9a10c0134512638725b521340293f202a69b567518d94e0 \ + --hash=sha256:76855800ac56f878847a09ce6dba727c93ca2d89c9e9d63002d26b916810b0a2 \ + --hash=sha256:7c6b9461a2a8b47c65eef63bb1c76a4f1c119618ffa99ea79bc5bb1e46c5821b \ + --hash=sha256:803a3c3ce4acc62eaf01eaca1208dcf0783025ef27572c3336502b9c232005e7 \ + --hash=sha256:80e6d33a3d42a7549b409f199857b4fb54e2103fc44fb87605b6663b7a7ff750 \ + --hash=sha256:8419ebd326430d1cbb7efb5292330a2cf39114e82df5cc3d83c9a0d5ebeaf2f2 \ + --hash=sha256:85610b4f27f69984932a7abbe52703688de3724d9f72bceb1cca667deff27474 \ + --hash=sha256:85e9beda1f591bc73e77ea1c51965c68e98dafd0fec72cdd745f77d727466716 \ + --hash=sha256:877b0738624280e34c55680d6054a307aa94f7d52fa0e3034a9cc6e790871da7 \ + --hash=sha256:88f9fb0116fbfcefcab70f85cf4b74a2b6ce5d199c41345296f49d974ddb4123 \ + --hash=sha256:8c4fe09e0780c6c3bf2b7d4af02ee2394439d11a523bbcf095cf4747c2932007 \ + --hash=sha256:93a784271881035ab4406a172edb0faecb6e7d00f4b53dc2f55919d6c9688595 \ + --hash=sha256:94f8575fbdf81749008d980c17796097e645574a3b8c28ee313931068dad14fe \ + --hash=sha256:95451e6ce06c3e104556d73b559f5da6c34a069b6b62946d3ad66afcd51642ea \ + --hash=sha256:99c8a9ed30f4164bc4c14b37a90208836cbf50d4ce2a57c71d0f52c7fb4f7598 \ + --hash=sha256:9a18d6f9359e45722c064c97464ec883eb0e0366d33eda61cb19a244bf222679 \ + --hash=sha256:9cbf44c5cb4a7633d078788e1b56387e3d3cf2b8139a3be38040b22d6c3221c8 \ + --hash=sha256:9ee33b875f0b390564c1fb7bc528abf18c8ee6073b201c6ae8524aca778e2d83 \ + --hash=sha256:a0e317df055958a0c1e79e5d2aa5a5eaa4a6d05a20d4b0c9c3f48918139c9fc6 \ + --hash=sha256:a2df6afe50dea8ae15fa34c9f824a3ee958d785fd5d089063d960bae1daa0a3f \ + --hash=sha256:a31de1613658308efdb21ada98cbc86a97c181aa050ba22a808120bb5be3ab94 \ + --hash=sha256:a3d2bff8f37f8d0f96c7ec554d16945050d54462d6e95414babaa18bfafc7f51 \ + --hash=sha256:a41bcf68efd19073376eb8cf948b8d9be0af26256403e512bb18f3966f1f9120 \ + --hash=sha256:a82836cab5f197a0514235aaf7ffccdc886ccdaa2324bc0aafdd4ae898103039 \ + --hash=sha256:a8d00f29b42f534cc8aa3931cfe773b13b23e561e10d2b26f27a8d309b0e82a1 \ + --hash=sha256:aafe5dcfda86c8af00386d7781d4c2181b5011b7be3f2add5e99899ea925df05 \ + --hash=sha256:ab5f043cb8a2d71c981c09c510da013bc79fd661f5c60139f00dd3c3cc4f2ffb \ + --hash=sha256:ac09d42f48f80c9ee1635b2fcaa819496a44502737660d3c0f2ade7526d29144 \ + --hash=sha256:aecfed0b41aa72b7881712c65cf764e39ce2ec352324f5e0837c7048d9e6daaa \ + --hash=sha256:b2c6b50c7b0464165472b56b42d4c76a7b864597007d9c085e8b63e185cf4a7a \ + --hash=sha256:b35d13d549077713e4414f927cdc388d62e543987c572baee613bf82f11a4b99 \ + --hash=sha256:b39cb32a6582750b6cc77bfb3c49c0f8760dc18dc96ec9fb55fbb0f04e08b928 \ + --hash=sha256:b5405bb8f0e783a988172993cfc627e4d9d00432d6bbac65a923041edacf997d \ + --hash=sha256:baaf55442359053c7d62f6f8413a62adba3205119bcb6f49594894d8be47e5e3 \ + --hash=sha256:bd654fad46d8d9e823afbb4f87c79160b5a374ed1ff5bde24e542e6ba8f41434 \ + --hash=sha256:be61f6fff406ca40e3b1d84716fde398fc08bc63dd96d15f3a14230a0973ed86 \ + --hash=sha256:bf49a3ae946a87083ef3a34c8f677ae4243f5b824bfc4c69672e72b3d6719d46 \ + --hash=sha256:c4a80f77dc1acaaa61f0934176fccca7096d9b1ff08c8ba9cddf5ae034a24319 \ + --hash=sha256:c75eb09e8d55bceb4367e83496ff8ef2bc7ea6960efb38e978e8073ea59ecb67 \ + --hash=sha256:c7f8dc16c498ff06497c015642333219871effba93e4a2e8604a06264aca5c5c \ + --hash=sha256:c8aa34a5c864db1087d911a0b902d60d203ea3607d91f615acd3f3108ac32169 \ + --hash=sha256:cbb0fef01f0c6b38cb0f39b1f78fc90b807e0e3c86a7ff3ce74ad77ce5c7880c \ + --hash=sha256:cde9a2ecd91668bcb7f077c4966d8ceddb60af01b52e6e3e2680e4cf00ad1a59 \ + --hash=sha256:cff6d44cb13d39db2663a22b22305d10855efa0fa8015ddeacc40bc59b9d8107 \ + --hash=sha256:d1009abedb49ae95b136a8904a3f71b342f849ffeced2d3747bf29caeda218c4 \ + --hash=sha256:d38c1e8231722c4ce40d7593f28d92b5fc72f3e9774fe73d7e800ec32299f63a \ + --hash=sha256:d53834e23c015ee83a99377db6e5e37d8484f333edb03bd15b4bc312cc7254fb \ + --hash=sha256:d7504f2b476d21653e4d143f44a175f7f751cd41233525312696c76aa3dbb23f \ + --hash=sha256:dbf507e9ef5688bada447a24d68b4b58dd389ba93b7afc065a2ba892bea54769 \ + --hash=sha256:dc52310451fc7c629e13c4e061cbe2dd01684d91f2f8ee2821b083c58bd72432 \ + --hash=sha256:dd00607bffbf30250fe108065f07453ec124dbf223420f57f5e749b04295e090 \ + --hash=sha256:dda608c88cf709b1d406bdfcd84d8d63cff7c9e577a403c6108ce8ce9dcc8764 \ + --hash=sha256:debe9c4f41c32990771be5c22b56f810659f9ddf3d63f67abfdcaa2c6c9c5c1d \ + --hash=sha256:e09fd068c2e169a7070d83d3bde728a4d48de0549f975290be3c108c02e499b4 \ + --hash=sha256:e0fd068364a6759bc794459f0a735ab151d11304346332489c7972bacbe9e72b \ + --hash=sha256:e4c53f8347cd4200f0d70a48ad059cabaf24f5adc6ba08622a23423bc7efa10d \ + --hash=sha256:e5723c01a56c5028c807c701aa66722916d2747ad737a046853f6c46f4875543 \ + --hash=sha256:e7b0460976dc75cb87ad9cc1f9899a4b97751e7d4e77ab840fc9b6d377b8fd24 \ + --hash=sha256:e9d9a4d06d3481eab79803beb4d9bd6f6a8e781ec078ac70d7ef2dcc29d1bea5 \ + --hash=sha256:ead11956716a940c1abc816b7df3fa2b84d06eaed8832ca32f5c5e058c65506b \ + --hash=sha256:ed5f69ce7be7902e5c70ea19eb72d20abf7d725ab5d49777d696e32d4fc1811d \ + --hash=sha256:f2af5c81a1f124609d5f33507082fc3f739959d4719b56877ab1ee7e7b3d602b \ + --hash=sha256:f40e782d49630ad384db66d4d8b73ff4f1b8955dc12e26b09a3e3af064b3b9d6 \ + --hash=sha256:f514f6474e04179d3d33175ed3f3e31434d3130d42ec153540d5b157deefd735 \ + --hash=sha256:f69f57305656a4852f2a7203efc661d8c042e6cc67f7acd97d8667fb448a426e \ + --hash=sha256:fb1e8b8d66c278b21d13b0a7ca22c41dd757a7c209c6b12c313e445c31dd3b28 \ + --hash=sha256:fb4948814a2a98e3912505f09c9e7493b1506226afb1f881825368d6fb776ee3 \ + --hash=sha256:fda207c815b253e34f7e1909840fd14299567b1c0eb4908f8c2ce01a41265401 \ + --hash=sha256:fe8f8f5e70e6dbdfca9882cd9deaac058729bcf323cf7a58660901e55c9c94f6 \ + --hash=sha256:fffc45637bcd6538de8b85f51e3df3223e4ad89bccbfca0481c08c7fc8b7ed7d # via aiohttp zipp==3.23.0 \ --hash=sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e \ diff --git a/sdk/python/requirements/py3.11-minimal-requirements.txt b/sdk/python/requirements/py3.11-minimal-requirements.txt index e6ae289dd43..741d147c860 100644 --- a/sdk/python/requirements/py3.11-minimal-requirements.txt +++ b/sdk/python/requirements/py3.11-minimal-requirements.txt @@ -8,127 +8,127 @@ aiohappyeyeballs==2.6.1 \ --hash=sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558 \ --hash=sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8 # via aiohttp -aiohttp==3.13.3 \ - --hash=sha256:01ad2529d4b5035578f5081606a465f3b814c542882804e2e8cda61adf5c71bf \ - --hash=sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c \ - --hash=sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c \ - --hash=sha256:084911a532763e9d3dd95adf78a78f4096cd5f58cdc18e6fdbc1b58417a45423 \ - --hash=sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f \ - --hash=sha256:0db318f7a6f065d84cb1e02662c526294450b314a02bd9e2a8e67f0d8564ce40 \ - --hash=sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2 \ - --hash=sha256:1449ceddcdbcf2e0446957863af03ebaaa03f94c090f945411b61269e2cb5daf \ - --hash=sha256:147e422fd1223005c22b4fe080f5d93ced44460f5f9c105406b753612b587821 \ - --hash=sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64 \ - --hash=sha256:215a685b6fbbfcf71dfe96e3eba7a6f58f10da1dfdf4889c7dd856abe430dca7 \ - --hash=sha256:2712039939ec963c237286113c68dbad80a82a4281543f3abf766d9d73228998 \ - --hash=sha256:27234ef6d85c914f9efeb77ff616dbf4ad2380be0cda40b4db086ffc7ddd1b7d \ - --hash=sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea \ - --hash=sha256:2b8d8ddba8f95ba17582226f80e2de99c7a7948e66490ef8d947e272a93e9463 \ - --hash=sha256:2ba0eea45eb5cc3172dbfc497c066f19c41bac70963ea1a67d51fc92e4cf9a80 \ - --hash=sha256:2be0e9ccf23e8a94f6f0650ce06042cefc6ac703d0d7ab6c7a917289f2539ad4 \ - --hash=sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767 \ - --hash=sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43 \ - --hash=sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592 \ - --hash=sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a \ - --hash=sha256:31a83ea4aead760dfcb6962efb1d861db48c34379f2ff72db9ddddd4cda9ea2e \ - --hash=sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687 \ - --hash=sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8 \ - --hash=sha256:37239e9f9a7ea9ac5bf6b92b0260b01f8a22281996da609206a84df860bc1261 \ - --hash=sha256:37da61e244d1749798c151421602884db5270faf479cf0ef03af0ff68954c9dd \ - --hash=sha256:3b61b7169ababd7802f9568ed96142616a9118dd2be0d1866e920e77ec8fa92a \ - --hash=sha256:3d9908a48eb7416dc1f4524e69f1d32e5d90e3981e4e37eb0aa1cd18f9cfa2a4 \ - --hash=sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587 \ - --hash=sha256:4021b51936308aeea0367b8f006dc999ca02bc118a0cc78c303f50a2ff6afb91 \ - --hash=sha256:40c5e40ecc29ba010656c18052b877a1c28f84344825efa106705e835c28530f \ - --hash=sha256:425c126c0dc43861e22cb1c14ba4c8e45d09516d0a3ae0a3f7494b79f5f233a3 \ - --hash=sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344 \ - --hash=sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6 \ - --hash=sha256:49a03727c1bba9a97d3e93c9f93ca03a57300f484b6e935463099841261195d3 \ - --hash=sha256:4ae5b5a0e1926e504c81c5b84353e7a5516d8778fbbff00429fe7b05bb25cbce \ - --hash=sha256:4e239d501f73d6db1522599e14b9b321a7e3b1de66ce33d53a765d975e9f4808 \ - --hash=sha256:56339a36b9f1fc708260c76c87e593e2afb30d26de9ae1eb445b5e051b98a7a1 \ - --hash=sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29 \ - --hash=sha256:5b179331a481cb5529fca8b432d8d3c7001cb217513c94cd72d668d1248688a3 \ - --hash=sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b \ - --hash=sha256:5d2d94f1f5fcbe40838ac51a6ab5704a6f9ea42e72ceda48de5e6b898521da51 \ - --hash=sha256:5dff64413671b0d3e7d5918ea490bdccb97a4ad29b3f311ed423200b2203e01c \ - --hash=sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926 \ - --hash=sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64 \ - --hash=sha256:642f752c3eb117b105acbd87e2c143de710987e09860d674e068c4c2c441034f \ - --hash=sha256:65d2ccb7eabee90ce0503c17716fc77226be026dcc3e65cce859a30db715025b \ - --hash=sha256:693781c45a4033d31d4187d2436f5ac701e7bbfe5df40d917736108c1cc7436e \ - --hash=sha256:694976222c711d1d00ba131904beb60534f93966562f64440d0c9d41b8cdb440 \ - --hash=sha256:697753042d57f4bf7122cab985bf15d0cef23c770864580f5af4f52023a56bd6 \ - --hash=sha256:69c56fbc1993fa17043e24a546959c0178fe2b5782405ad4559e6c13975c15e3 \ - --hash=sha256:6de499a1a44e7de70735d0b39f67c8f25eb3d91eb3103be99ca0fa882cdd987d \ - --hash=sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415 \ - --hash=sha256:75ca857eba4e20ce9f546cd59c7007b33906a4cd48f2ff6ccf1ccfc3b646f279 \ - --hash=sha256:7a4a94eb787e606d0a09404b9c38c113d3b099d508021faa615d70a0131907ce \ - --hash=sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603 \ - --hash=sha256:7bfdc049127717581866fa4708791220970ce291c23e28ccf3922c700740fdc0 \ - --hash=sha256:7e63f210bc1b57ef699035f2b4b6d9ce096b5914414a49b0997c839b2bd2223c \ - --hash=sha256:7f9120f7093c2a32d9647abcaf21e6ad275b4fbec5b55969f978b1a97c7c86bf \ - --hash=sha256:8057c98e0c8472d8846b9c79f56766bcc57e3e8ac7bfd510482332366c56c591 \ - --hash=sha256:80dd4c21b0f6237676449c6baaa1039abae86b91636b6c91a7f8e61c87f89540 \ - --hash=sha256:81e97251d9298386c2b7dbeb490d3d1badbdc69107fb8c9299dd04eb39bddc0e \ - --hash=sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26 \ - --hash=sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a \ - --hash=sha256:859bd3f2156e81dd01432f5849fc73e2243d4a487c4fd26609b1299534ee1845 \ - --hash=sha256:87797e645d9d8e222e04160ee32aa06bc5c163e8499f24db719e7852ec23093a \ - --hash=sha256:87b9aab6d6ed88235aa2970294f496ff1a1f9adcd724d800e9b952395a80ffd9 \ - --hash=sha256:8a60e60746623925eab7d25823329941aee7242d559baa119ca2b253c88a7bd6 \ - --hash=sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba \ - --hash=sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df \ - --hash=sha256:947c26539750deeaee933b000fb6517cc770bbd064bad6033f1cff4803881e43 \ - --hash=sha256:96d604498a7c782cb15a51c406acaea70d8c027ee6b90c569baa6e7b93073679 \ - --hash=sha256:988a8c5e317544fdf0d39871559e67b6341065b87fceac641108c2096d5506b7 \ - --hash=sha256:9a9dc347e5a3dc7dfdbc1f82da0ef29e388ddb2ed281bfce9dd8248a313e62b7 \ - --hash=sha256:9ae8dd55c8e6c4257eae3a20fd2c8f41edaea5992ed67156642493b8daf3cecc \ - --hash=sha256:9af5e68ee47d6534d36791bbe9b646d2a7c7deb6fc24d7943628edfbb3581f29 \ - --hash=sha256:9b174f267b5cfb9a7dba9ee6859cecd234e9a681841eb85068059bc867fb8f02 \ - --hash=sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984 \ - --hash=sha256:9d4c940f02f49483b18b079d1c27ab948721852b281f8b015c058100e9421dd1 \ - --hash=sha256:9ebf57d09e131f5323464bd347135a88622d1c0976e88ce15b670e7ad57e4bd6 \ - --hash=sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632 \ - --hash=sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56 \ - --hash=sha256:a2212ad43c0833a873d0fb3c63fa1bacedd4cf6af2fee62bf4b739ceec3ab239 \ - --hash=sha256:a45530014d7a1e09f4a55f4f43097ba0fd155089372e105e4bff4ca76cb1b168 \ - --hash=sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88 \ - --hash=sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc \ - --hash=sha256:af71fff7bac6bb7508956696dce8f6eec2bbb045eceb40343944b1ae62b5ef11 \ - --hash=sha256:b04be762396457bef43f3597c991e192ee7da460a4953d7e647ee4b1c28e7046 \ - --hash=sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0 \ - --hash=sha256:b1a6102b4d3ebc07dad44fbf07b45bb600300f15b552ddf1851b5390202ea2e3 \ - --hash=sha256:b46020d11d23fe16551466c77823df9cc2f2c1e63cc965daf67fa5eec6ca1877 \ - --hash=sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1 \ - --hash=sha256:b903a4dfee7d347e2d87697d0713be59e0b87925be030c9178c5faa58ea58d5c \ - --hash=sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25 \ - --hash=sha256:b99281b0704c103d4e11e72a76f1b543d4946fea7dd10767e7e1b5f00d4e5704 \ - --hash=sha256:bae5c2ed2eae26cc382020edad80d01f36cb8e746da40b292e68fec40421dc6a \ - --hash=sha256:bb4f7475e359992b580559e008c598091c45b5088f28614e855e42d39c2f1033 \ - --hash=sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1 \ - --hash=sha256:bfc1cc2fe31a6026a8a88e4ecfb98d7f6b1fec150cfd708adbfd1d2f42257c29 \ - --hash=sha256:c014c7ea7fb775dd015b2d3137378b7be0249a448a1612268b5a90c2d81de04d \ - --hash=sha256:c048058117fd649334d81b4b526e94bde3ccaddb20463a815ced6ecbb7d11160 \ - --hash=sha256:c0e2d366af265797506f0283487223146af57815b388623f0357ef7eac9b209d \ - --hash=sha256:c19b90316ad3b24c69cd78d5c9b4f3aa4497643685901185b65166293d36a00f \ - --hash=sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f \ - --hash=sha256:c6b8568a3bb5819a0ad087f16d40e5a3fb6099f39ea1d5625a3edc1e923fc538 \ - --hash=sha256:d32764c6c9aafb7fb55366a224756387cd50bfa720f32b88e0e6fa45b27dcf29 \ - --hash=sha256:d5a372fd5afd301b3a89582817fdcdb6c34124787c70dbcc616f259013e7eef7 \ - --hash=sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72 \ - --hash=sha256:dca68018bf48c251ba17c72ed479f4dafe9dbd5a73707ad8d28a38d11f3d42af \ - --hash=sha256:de2c184bb1fe2cbd2cefba613e9db29a5ab559323f994b6737e370d3da0ac455 \ - --hash=sha256:e3531d63d3bdfa7e3ac5e9b27b2dd7ec9df3206a98e0b3445fa906f233264c57 \ - --hash=sha256:e50a2e1404f063427c9d027378472316201a2290959a295169bcf25992d04558 \ - --hash=sha256:e636b3c5f61da31a92bf0d91da83e58fdfa96f178ba682f11d24f31944cdd28c \ - --hash=sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808 \ - --hash=sha256:f33ed1a2bf1997a36661874b017f5c4b760f41266341af36febaf271d179f6d7 \ - --hash=sha256:f76c1e3fe7d7c8afad7ed193f89a292e1999608170dcc9751a7462a87dfd5bc0 \ - --hash=sha256:f9444f105664c4ce47a2a7171a2418bce5b7bae45fb610f4e2c36045d85911d3 \ - --hash=sha256:fc290605db2a917f6e81b0e1e0796469871f5af381ce15c604a3c5c7e51cb730 \ - --hash=sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa \ - --hash=sha256:fee0c6bc7db1de362252affec009707a17478a00ec69f797d23ca256e36d5940 +aiohttp==3.13.5 \ + --hash=sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5 \ + --hash=sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b \ + --hash=sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9 \ + --hash=sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b \ + --hash=sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8 \ + --hash=sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a \ + --hash=sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2 \ + --hash=sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1 \ + --hash=sha256:147b4f501d0292077f29d5268c16bb7c864a1f054d7001c4c1812c0421ea1ed0 \ + --hash=sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037 \ + --hash=sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416 \ + --hash=sha256:178c7b5e62b454c2bc790786e6058c3cc968613b4419251b478c153a4aec32b1 \ + --hash=sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9 \ + --hash=sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a \ + --hash=sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36 \ + --hash=sha256:206b7b3ef96e4ce211754f0cd003feb28b7d81f0ad26b8d077a5d5161436067f \ + --hash=sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b \ + --hash=sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174 \ + --hash=sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b \ + --hash=sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8 \ + --hash=sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e \ + --hash=sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6 \ + --hash=sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c \ + --hash=sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe \ + --hash=sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9 \ + --hash=sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc \ + --hash=sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800 \ + --hash=sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286 \ + --hash=sha256:347542f0ea3f95b2a955ee6656461fa1c776e401ac50ebce055a6c38454a0adf \ + --hash=sha256:39380e12bd1f2fdab4285b6e055ad48efbaed5c836433b142ed4f5b9be71036a \ + --hash=sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc \ + --hash=sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9 \ + --hash=sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665 \ + --hash=sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832 \ + --hash=sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297 \ + --hash=sha256:4e704c52438f66fdd89588346183d898bb42167cf88f8b7ff1c0f9fc957c348f \ + --hash=sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73 \ + --hash=sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b \ + --hash=sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9 \ + --hash=sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090 \ + --hash=sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49 \ + --hash=sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d \ + --hash=sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46 \ + --hash=sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83 \ + --hash=sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796 \ + --hash=sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be \ + --hash=sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d \ + --hash=sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf \ + --hash=sha256:6f497a6876aa4b1a102b04996ce4c1170c7040d83faa9387dd921c16e30d5c83 \ + --hash=sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25 \ + --hash=sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06 \ + --hash=sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3 \ + --hash=sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6 \ + --hash=sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb \ + --hash=sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88 \ + --hash=sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9 \ + --hash=sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be \ + --hash=sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14 \ + --hash=sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a \ + --hash=sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c \ + --hash=sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3 \ + --hash=sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f \ + --hash=sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d \ + --hash=sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670 \ + --hash=sha256:912d4b6af530ddb1338a66229dac3a25ff11d4448be3ec3d6340583995f56031 \ + --hash=sha256:9277145d36a01653863899c665243871434694bcc3431922c3b35c978061bdb8 \ + --hash=sha256:95d14ca7abefde230f7639ec136ade282655431fd5db03c343b19dda72dd1643 \ + --hash=sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d \ + --hash=sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8 \ + --hash=sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8 \ + --hash=sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1 \ + --hash=sha256:9efcc0f11d850cefcafdd9275b9576ad3bfb539bed96807663b32ad99c4d4b88 \ + --hash=sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb \ + --hash=sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61 \ + --hash=sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4 \ + --hash=sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7 \ + --hash=sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9 \ + --hash=sha256:a8a4d3427e8de1312ddf309cc482186466c79895b3a139fed3259fc01dfa9a5b \ + --hash=sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500 \ + --hash=sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6 \ + --hash=sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2 \ + --hash=sha256:af545c2cffdb0967a96b6249e6f5f7b0d92cdfd267f9d5238d5b9ca63e8edb10 \ + --hash=sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1 \ + --hash=sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3 \ + --hash=sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e \ + --hash=sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a \ + --hash=sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5 \ + --hash=sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95 \ + --hash=sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074 \ + --hash=sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5 \ + --hash=sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b \ + --hash=sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772 \ + --hash=sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a \ + --hash=sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274 \ + --hash=sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94 \ + --hash=sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13 \ + --hash=sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac \ + --hash=sha256:cb979826071c0986a5f08333a36104153478ce6018c58cba7f9caddaf63d5d67 \ + --hash=sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76 \ + --hash=sha256:d147004fede1b12f6013a6dbb2a26a986a671a03c6ea740ddc76500e5f1c399f \ + --hash=sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8 \ + --hash=sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7 \ + --hash=sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8 \ + --hash=sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3 \ + --hash=sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be \ + --hash=sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b \ + --hash=sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c \ + --hash=sha256:e999f0c88a458c836d5fb521814e92ed2172c649200336a6df514987c1488258 \ + --hash=sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c \ + --hash=sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6 \ + --hash=sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56 \ + --hash=sha256:ee5e86776273de1795947d17bddd6bb19e0365fd2af4289c0d2c5454b6b1d36b \ + --hash=sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d \ + --hash=sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a \ + --hash=sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162 \ + --hash=sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1 \ + --hash=sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6 \ + --hash=sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5 \ + --hash=sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540 \ + --hash=sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254 # via aiobotocore aioitertools==0.13.0 \ --hash=sha256:0be0292b856f08dfac90e31f4739432f4cb6d7520ab9eb73e143f4f2fa5259be \ @@ -148,9 +148,9 @@ annotated-types==0.7.0 \ --hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \ --hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89 # via pydantic -anyio==4.12.1 \ - --hash=sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703 \ - --hash=sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c +anyio==4.13.0 \ + --hash=sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708 \ + --hash=sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc # via # httpx # mcp @@ -169,16 +169,16 @@ atpublic==7.0.0 \ --hash=sha256:466ef10d0c8bbd14fd02a5fbd5a8b6af6a846373d91106d3a07c16d72d96b63e \ --hash=sha256:6702bd9e7245eb4e8220a3e222afcef7f87412154732271ee7deee4433b72b4b # via ibis-framework -attrs==25.4.0 \ - --hash=sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11 \ - --hash=sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373 +attrs==26.1.0 \ + --hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \ + --hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32 # via # aiohttp # jsonschema # referencing -bigtree==1.3.1 \ - --hash=sha256:a22a0ecd9b0abb283f4a1515370dbf1ec93adee70746767272e2c49d7af9f407 \ - --hash=sha256:c8b766b00188c532d3499bfd9e9666b357428db507fc701f088031a0d5c614d5 +bigtree==1.4.0 \ + --hash=sha256:d0d99550ae64ce4529f132602ab875c2ab472c96c942f5704f8c72a17450d3ea \ + --hash=sha256:e5ae2e948168da671d99601c9ed87ab3b48d9d4ea8a98f111e5748e98064c31c # via feast (pyproject.toml) boto3==1.38.27 \ --hash=sha256:94bd7fdd92d5701b362d4df100d21e28f8307a67ff56b6a8b0398119cf22f859 \ @@ -194,9 +194,9 @@ botocore==1.38.46 \ # boto3 # s3transfer # snowflake-connector-python -certifi==2026.1.4 \ - --hash=sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c \ - --hash=sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120 +certifi==2026.2.25 \ + --hash=sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa \ + --hash=sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7 # via # httpcore # httpx @@ -291,120 +291,136 @@ cffi==2.0.0 \ # via # feast (pyproject.toml) # cryptography -charset-normalizer==3.4.4 \ - --hash=sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad \ - --hash=sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93 \ - --hash=sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394 \ - --hash=sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89 \ - --hash=sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc \ - --hash=sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86 \ - --hash=sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63 \ - --hash=sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d \ - --hash=sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f \ - --hash=sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8 \ - --hash=sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0 \ - --hash=sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505 \ - --hash=sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161 \ - --hash=sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af \ - --hash=sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152 \ - --hash=sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318 \ - --hash=sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72 \ - --hash=sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4 \ - --hash=sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e \ - --hash=sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3 \ - --hash=sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576 \ - --hash=sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c \ - --hash=sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1 \ - --hash=sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8 \ - --hash=sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1 \ - --hash=sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2 \ - --hash=sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44 \ - --hash=sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26 \ - --hash=sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88 \ - --hash=sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016 \ - --hash=sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede \ - --hash=sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf \ - --hash=sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a \ - --hash=sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc \ - --hash=sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0 \ - --hash=sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84 \ - --hash=sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db \ - --hash=sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1 \ - --hash=sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7 \ - --hash=sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed \ - --hash=sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8 \ - --hash=sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133 \ - --hash=sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e \ - --hash=sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef \ - --hash=sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14 \ - --hash=sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2 \ - --hash=sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0 \ - --hash=sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d \ - --hash=sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828 \ - --hash=sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f \ - --hash=sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf \ - --hash=sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6 \ - --hash=sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328 \ - --hash=sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090 \ - --hash=sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa \ - --hash=sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381 \ - --hash=sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c \ - --hash=sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb \ - --hash=sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc \ - --hash=sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a \ - --hash=sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec \ - --hash=sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc \ - --hash=sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac \ - --hash=sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e \ - --hash=sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313 \ - --hash=sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569 \ - --hash=sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3 \ - --hash=sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d \ - --hash=sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525 \ - --hash=sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894 \ - --hash=sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3 \ - --hash=sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9 \ - --hash=sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a \ - --hash=sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9 \ - --hash=sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14 \ - --hash=sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25 \ - --hash=sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50 \ - --hash=sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf \ - --hash=sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1 \ - --hash=sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3 \ - --hash=sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac \ - --hash=sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e \ - --hash=sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815 \ - --hash=sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c \ - --hash=sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6 \ - --hash=sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6 \ - --hash=sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e \ - --hash=sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4 \ - --hash=sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84 \ - --hash=sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69 \ - --hash=sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15 \ - --hash=sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191 \ - --hash=sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0 \ - --hash=sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897 \ - --hash=sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd \ - --hash=sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2 \ - --hash=sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794 \ - --hash=sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d \ - --hash=sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074 \ - --hash=sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3 \ - --hash=sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224 \ - --hash=sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838 \ - --hash=sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a \ - --hash=sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d \ - --hash=sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d \ - --hash=sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f \ - --hash=sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8 \ - --hash=sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490 \ - --hash=sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966 \ - --hash=sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9 \ - --hash=sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3 \ - --hash=sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e \ - --hash=sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608 +charset-normalizer==3.4.7 \ + --hash=sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc \ + --hash=sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c \ + --hash=sha256:07d9e39b01743c3717745f4c530a6349eadbfa043c7577eef86c502c15df2c67 \ + --hash=sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4 \ + --hash=sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0 \ + --hash=sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c \ + --hash=sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5 \ + --hash=sha256:12a6fff75f6bc66711b73a2f0addfc4c8c15a20e805146a02d147a318962c444 \ + --hash=sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153 \ + --hash=sha256:14265bfe1f09498b9d8ec91e9ec9fa52775edf90fcbde092b25f4a33d444fea9 \ + --hash=sha256:16d971e29578a5e97d7117866d15889a4a07befe0e87e703ed63cd90cb348c01 \ + --hash=sha256:177a0ba5f0211d488e295aaf82707237e331c24788d8d76c96c5a41594723217 \ + --hash=sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b \ + --hash=sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c \ + --hash=sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a \ + --hash=sha256:1dc8b0ea451d6e69735094606991f32867807881400f808a106ee1d963c46a83 \ + --hash=sha256:1efde3cae86c8c273f1eb3b287be7d8499420cf2fe7585c41d370d3e790054a5 \ + --hash=sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7 \ + --hash=sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb \ + --hash=sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c \ + --hash=sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1 \ + --hash=sha256:2cd4a60d0e2fb04537162c62bbbb4182f53541fe0ede35cdf270a1c1e723cc42 \ + --hash=sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab \ + --hash=sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df \ + --hash=sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e \ + --hash=sha256:320ade88cfb846b8cd6b4ddf5ee9e80ee0c1f52401f2456b84ae1ae6a1a5f207 \ + --hash=sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18 \ + --hash=sha256:36836d6ff945a00b88ba1e4572d721e60b5b8c98c155d465f56ad19d68f23734 \ + --hash=sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38 \ + --hash=sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110 \ + --hash=sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18 \ + --hash=sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44 \ + --hash=sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d \ + --hash=sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48 \ + --hash=sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e \ + --hash=sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5 \ + --hash=sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d \ + --hash=sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53 \ + --hash=sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790 \ + --hash=sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c \ + --hash=sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b \ + --hash=sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116 \ + --hash=sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d \ + --hash=sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10 \ + --hash=sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6 \ + --hash=sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2 \ + --hash=sha256:6370e8686f662e6a3941ee48ed4742317cafbe5707e36406e9df792cdb535776 \ + --hash=sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a \ + --hash=sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265 \ + --hash=sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008 \ + --hash=sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943 \ + --hash=sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374 \ + --hash=sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246 \ + --hash=sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e \ + --hash=sha256:6e0d51f618228538a3e8f46bd246f87a6cd030565e015803691603f55e12afb5 \ + --hash=sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616 \ + --hash=sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15 \ + --hash=sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41 \ + --hash=sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960 \ + --hash=sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752 \ + --hash=sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e \ + --hash=sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72 \ + --hash=sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7 \ + --hash=sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8 \ + --hash=sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b \ + --hash=sha256:813c0e0132266c08eb87469a642cb30aaff57c5f426255419572aaeceeaa7bf4 \ + --hash=sha256:82b271f5137d07749f7bf32f70b17ab6eaabedd297e75dce75081a24f76eb545 \ + --hash=sha256:84c018e49c3bf790f9c2771c45e9313a08c2c2a6342b162cd650258b57817706 \ + --hash=sha256:8751d2787c9131302398b11e6c8068053dcb55d5a8964e114b6e196cf16cb366 \ + --hash=sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb \ + --hash=sha256:87fad7d9ba98c86bcb41b2dc8dbb326619be2562af1f8ff50776a39e55721c5a \ + --hash=sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e \ + --hash=sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00 \ + --hash=sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f \ + --hash=sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a \ + --hash=sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1 \ + --hash=sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66 \ + --hash=sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356 \ + --hash=sha256:a6c5863edfbe888d9eff9c8b8087354e27618d9da76425c119293f11712a6319 \ + --hash=sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4 \ + --hash=sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad \ + --hash=sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d \ + --hash=sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5 \ + --hash=sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7 \ + --hash=sha256:aef65cd602a6d0e0ff6f9930fcb1c8fec60dd2cfcb6facaf4bdb0e5873042db0 \ + --hash=sha256:af21eb4409a119e365397b2adbaca4c9ccab56543a65d5dbd9f920d6ac29f686 \ + --hash=sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34 \ + --hash=sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49 \ + --hash=sha256:bb8cc7534f51d9a017b93e3e85b260924f909601c3df002bcdb58ddb4dc41a5c \ + --hash=sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1 \ + --hash=sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e \ + --hash=sha256:bd9b23791fe793e4968dba0c447e12f78e425c59fc0e3b97f6450f4781f3ee60 \ + --hash=sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0 \ + --hash=sha256:c0f081d69a6e58272819b70288d3221a6ee64b98df852631c80f293514d3b274 \ + --hash=sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d \ + --hash=sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0 \ + --hash=sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae \ + --hash=sha256:c593052c465475e64bbfe5dbd81680f64a67fdc752c56d7a0ae205dc8aeefe0f \ + --hash=sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d \ + --hash=sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe \ + --hash=sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3 \ + --hash=sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393 \ + --hash=sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1 \ + --hash=sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af \ + --hash=sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44 \ + --hash=sha256:d61f00a0869d77422d9b2aba989e2d24afa6ffd552af442e0e58de4f35ea6d00 \ + --hash=sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c \ + --hash=sha256:dca4bbc466a95ba9c0234ef56d7dd9509f63da22274589ebd4ed7f1f4d4c54e3 \ + --hash=sha256:dd915403e231e6b1809fe9b6d9fc55cf8fb5e02765ac625d9cd623342a7905d7 \ + --hash=sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd \ + --hash=sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e \ + --hash=sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b \ + --hash=sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8 \ + --hash=sha256:e5f4d355f0a2b1a31bc3edec6795b46324349c9cb25eed068049e4f472fb4259 \ + --hash=sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859 \ + --hash=sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46 \ + --hash=sha256:e80c8378d8f3d83cd3164da1ad2df9e37a666cdde7b1cb2298ed0b558064be30 \ + --hash=sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b \ + --hash=sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46 \ + --hash=sha256:ed065083d0898c9d5b4bbec7b026fd755ff7454e6e8b73a67f8c744b13986e24 \ + --hash=sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a \ + --hash=sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24 \ + --hash=sha256:f22dec1690b584cea26fade98b2435c132c1b5f68e39f5a0b7627cd7ae31f1dc \ + --hash=sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215 \ + --hash=sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063 \ + --hash=sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832 \ + --hash=sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6 \ + --hash=sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79 \ + --hash=sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464 # via # requests # snowflake-connector-python @@ -424,68 +440,68 @@ colorama==0.4.6 \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 # via feast (pyproject.toml) -cryptography==46.0.5 \ - --hash=sha256:02f547fce831f5096c9a567fd41bc12ca8f11df260959ecc7c3202555cc47a72 \ - --hash=sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235 \ - --hash=sha256:1abfdb89b41c3be0365328a410baa9df3ff8a9110fb75e7b52e66803ddabc9a9 \ - --hash=sha256:2ae6971afd6246710480e3f15824ed3029a60fc16991db250034efd0b9fb4356 \ - --hash=sha256:2b7a67c9cd56372f3249b39699f2ad479f6991e62ea15800973b956f4b73e257 \ - --hash=sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad \ - --hash=sha256:38946c54b16c885c72c4f59846be9743d699eee2b69b6988e0a00a01f46a61a4 \ - --hash=sha256:3b4995dc971c9fb83c25aa44cf45f02ba86f71ee600d81091c2f0cbae116b06c \ - --hash=sha256:3ce58ba46e1bc2aac4f7d9290223cead56743fa6ab94a5d53292ffaac6a91614 \ - --hash=sha256:3ee190460e2fbe447175cda91b88b84ae8322a104fc27766ad09428754a618ed \ - --hash=sha256:4108d4c09fbbf2789d0c926eb4152ae1760d5a2d97612b92d508d96c861e4d31 \ - --hash=sha256:420d0e909050490d04359e7fdb5ed7e667ca5c3c402b809ae2563d7e66a92229 \ - --hash=sha256:47fb8a66058b80e509c47118ef8a75d14c455e81ac369050f20ba0d23e77fee0 \ - --hash=sha256:4c3341037c136030cb46e4b1e17b7418ea4cbd9dd207e4a6f3b2b24e0d4ac731 \ - --hash=sha256:4d7e3d356b8cd4ea5aff04f129d5f66ebdc7b6f8eae802b93739ed520c47c79b \ - --hash=sha256:4d8ae8659ab18c65ced284993c2265910f6c9e650189d4e3f68445ef82a810e4 \ - --hash=sha256:4e817a8920bfbcff8940ecfd60f23d01836408242b30f1a708d93198393a80b4 \ - --hash=sha256:50bfb6925eff619c9c023b967d5b77a54e04256c4281b0e21336a130cd7fc263 \ - --hash=sha256:556e106ee01aa13484ce9b0239bca667be5004efb0aabbed28d353df86445595 \ - --hash=sha256:582f5fcd2afa31622f317f80426a027f30dc792e9c80ffee87b993200ea115f1 \ - --hash=sha256:5be7bf2fb40769e05739dd0046e7b26f9d4670badc7b032d6ce4db64dddc0678 \ - --hash=sha256:60ee7e19e95104d4c03871d7d7dfb3d22ef8a9b9c6778c94e1c8fcc8365afd48 \ - --hash=sha256:61aa400dce22cb001a98014f647dc21cda08f7915ceb95df0c9eaf84b4b6af76 \ - --hash=sha256:68f68d13f2e1cb95163fa3b4db4bf9a159a418f5f6e7242564fc75fcae667fd0 \ - --hash=sha256:7d1f30a86d2757199cb2d56e48cce14deddf1f9c95f1ef1b64ee91ea43fe2e18 \ - --hash=sha256:7d731d4b107030987fd61a7f8ab512b25b53cef8f233a97379ede116f30eb67d \ - --hash=sha256:803812e111e75d1aa73690d2facc295eaefd4439be1023fefc4995eaea2af90d \ - --hash=sha256:80a8d7bfdf38f87ca30a5391c0c9ce4ed2926918e017c29ddf643d0ed2778ea1 \ - --hash=sha256:8293f3dea7fc929ef7240796ba231413afa7b68ce38fd21da2995549f5961981 \ - --hash=sha256:8456928655f856c6e1533ff59d5be76578a7157224dbd9ce6872f25055ab9ab7 \ - --hash=sha256:890bcb4abd5a2d3f852196437129eb3667d62630333aacc13dfd470fad3aaa82 \ - --hash=sha256:94a76daa32eb78d61339aff7952ea819b1734b46f73646a07decb40e5b3448e2 \ - --hash=sha256:9f16fbdf4da055efb21c22d81b89f155f02ba420558db21288b3d0035bafd5f4 \ - --hash=sha256:a3d1fae9863299076f05cb8a778c467578262fae09f9dc0ee9b12eb4268ce663 \ - --hash=sha256:a3d507bb6a513ca96ba84443226af944b0f7f47dcc9a399d110cd6146481d24c \ - --hash=sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d \ - --hash=sha256:ba2a27ff02f48193fc4daeadf8ad2590516fa3d0adeeb34336b96f7fa64c1e3a \ - --hash=sha256:bc84e875994c3b445871ea7181d424588171efec3e185dced958dad9e001950a \ - --hash=sha256:bfd56bb4b37ed4f330b82402f6f435845a5f5648edf1ad497da51a8452d5d62d \ - --hash=sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b \ - --hash=sha256:c3bcce8521d785d510b2aad26ae2c966092b7daa8f45dd8f44734a104dc0bc1a \ - --hash=sha256:c4143987a42a2397f2fc3b4d7e3a7d313fbe684f67ff443999e803dd75a76826 \ - --hash=sha256:c69fd885df7d089548a42d5ec05be26050ebcd2283d89b3d30676eb32ff87dee \ - --hash=sha256:ced80795227d70549a411a4ab66e8ce307899fad2220ce5ab2f296e687eacde9 \ - --hash=sha256:d66e421495fdb797610a08f43b05269e0a5ea7f5e652a89bfd5a7d3c1dee3648 \ - --hash=sha256:d861ee9e76ace6cf36a6a89b959ec08e7bc2493ee39d07ffe5acb23ef46d27da \ - --hash=sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2 \ - --hash=sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2 \ - --hash=sha256:fe346b143ff9685e40192a4960938545c699054ba11d4f9029f94751e3f71d87 +cryptography==46.0.6 \ + --hash=sha256:02fad249cb0e090b574e30b276a3da6a149e04ee2f049725b1f69e7b8351ec70 \ + --hash=sha256:063b67749f338ca9c5a0b7fe438a52c25f9526b851e24e6c9310e7195aad3b4d \ + --hash=sha256:12cae594e9473bca1a7aceb90536060643128bb274fcea0fc459ab90f7d1ae7a \ + --hash=sha256:12f0fa16cc247b13c43d56d7b35287ff1569b5b1f4c5e87e92cc4fcc00cd10c0 \ + --hash=sha256:22259338084d6ae497a19bae5d4c66b7ca1387d3264d1c2c0e72d9e9b6a77b97 \ + --hash=sha256:26031f1e5ca62fcb9d1fcb34b2b60b390d1aacaa15dc8b895a9ed00968b97b30 \ + --hash=sha256:27550628a518c5c6c903d84f637fbecf287f6cb9ced3804838a1295dc1fd0759 \ + --hash=sha256:2b417edbe8877cda9022dde3a008e2deb50be9c407eef034aeeb3a8b11d9db3c \ + --hash=sha256:2ea0f37e9a9cf0df2952893ad145fd9627d326a59daec9b0802480fa3bcd2ead \ + --hash=sha256:2ef9e69886cbb137c2aef9772c2e7138dc581fad4fcbcf13cc181eb5a3ab6275 \ + --hash=sha256:341359d6c9e68834e204ceaf25936dffeafea3829ab80e9503860dcc4f4dac58 \ + --hash=sha256:380343e0653b1c9d7e1f55b52aaa2dbb2fdf2730088d48c43ca1c7c0abb7cc2f \ + --hash=sha256:3c21d92ed15e9cfc6eb64c1f5a0326db22ca9c2566ca46d845119b45b4400361 \ + --hash=sha256:3dfa6567f2e9e4c5dceb8ccb5a708158a2a871052fa75c8b78cb0977063f1507 \ + --hash=sha256:456b3215172aeefb9284550b162801d62f5f264a081049a3e94307fe20792cfa \ + --hash=sha256:4668298aef7cddeaf5c6ecc244c2302a2b8e40f384255505c22875eebb47888b \ + --hash=sha256:50575a76e2951fe7dbd1f56d181f8c5ceeeb075e9ff88e7ad997d2f42af06e7b \ + --hash=sha256:639301950939d844a9e1c4464d7e07f902fe9a7f6b215bb0d4f28584729935d8 \ + --hash=sha256:64235194bad039a10bb6d2d930ab3323baaec67e2ce36215fd0952fad0930ca8 \ + --hash=sha256:6617f67b1606dfd9fe4dbfa354a9508d4a6d37afe30306fe6c101b7ce3274b72 \ + --hash=sha256:67177e8a9f421aa2d3a170c3e56eca4e0128883cf52a071a7cbf53297f18b175 \ + --hash=sha256:6728c49e3b2c180ef26f8e9f0a883a2c585638db64cf265b49c9ba10652d430e \ + --hash=sha256:6739d56300662c468fddb0e5e291f9b4d084bead381667b9e654c7dd81705124 \ + --hash=sha256:69cf0056d6947edc6e6760e5f17afe4bea06b56a9ac8a06de9d2bd6b532d4f3a \ + --hash=sha256:760997a4b950ff00d418398ad73fbc91aa2894b5c1db7ccb45b4f68b42a63b3c \ + --hash=sha256:79e865c642cfc5c0b3eb12af83c35c5aeff4fa5c672dc28c43721c2c9fdd2f0f \ + --hash=sha256:7e6142674f2a9291463e5e150090b95a8519b2fb6e6aaec8917dd8d094ce750d \ + --hash=sha256:7f417f034f91dcec1cb6c5c35b07cdbb2ef262557f701b4ecd803ee8cefed4f4 \ + --hash=sha256:7f6690b6c55e9c5332c0b59b9c8a3fb232ebf059094c17f9019a51e9827df91c \ + --hash=sha256:8927ccfbe967c7df312ade694f987e7e9e22b2425976ddbf28271d7e58845290 \ + --hash=sha256:8ce35b77aaf02f3b59c90b2c8a05c73bac12cea5b4e8f3fbece1f5fddea5f0ca \ + --hash=sha256:8e7304c4f4e9490e11efe56af6713983460ee0780f16c63f219984dab3af9d2d \ + --hash=sha256:90e5f0a7b3be5f40c3a0a0eafb32c681d8d2c181fc2a1bdabe9b3f611d9f6b1a \ + --hash=sha256:97c8115b27e19e592a05c45d0dd89c57f81f841cc9880e353e0d3bf25b2139ed \ + --hash=sha256:9a693028b9cbe51b5a1136232ee8f2bc242e4e19d456ded3fa7c86e43c713b4a \ + --hash=sha256:9a9c42a2723999a710445bc0d974e345c32adfd8d2fac6d8a251fa829ad31cfb \ + --hash=sha256:a3e84d5ec9ba01f8fd03802b2147ba77f0c8f2617b2aff254cedd551844209c8 \ + --hash=sha256:aad75154a7ac9039936d50cf431719a2f8d4ed3d3c277ac03f3339ded1a5e707 \ + --hash=sha256:b12c6b1e1651e42ab5de8b1e00dc3b6354fdfd778e7fa60541ddacc27cd21410 \ + --hash=sha256:b928a3ca837c77a10e81a814a693f2295200adb3352395fad024559b7be7a736 \ + --hash=sha256:bcb87663e1f7b075e48c3be3ecb5f0b46c8fc50b50a97cf264e7f60242dca3f2 \ + --hash=sha256:c797e2517cb7880f8297e2c0f43bb910e91381339336f75d2c1c2cbf811b70b4 \ + --hash=sha256:c89eb37fae9216985d8734c1afd172ba4927f5a05cfd9bf0e4863c6d5465b013 \ + --hash=sha256:cdcd3edcbc5d55757e5f5f3d330dd00007ae463a7e7aa5bf132d1f22a4b62b19 \ + --hash=sha256:d24c13369e856b94892a89ddf70b332e0b70ad4a5c43cf3e9cb71d6d7ffa1f7b \ + --hash=sha256:d4e4aadb7fc1f88687f47ca20bb7227981b03afaae69287029da08096853b738 \ + --hash=sha256:d9528b535a6c4f8ff37847144b8986a9a143585f0540fbcb1a98115b543aa463 \ + --hash=sha256:ed3775295fb91f70b4027aeba878d79b3e55c0b3e97eaa4de71f8f23a9f2eb77 \ + --hash=sha256:ed418c37d095aeddf5336898a132fba01091f0ac5844e3e8018506f014b6d2c4 # via # google-auth # pyjwt # pyopenssl # snowflake-connector-python -dask[dataframe]==2026.1.2 \ - --hash=sha256:1136683de2750d98ea792670f7434e6c1cfce90cab2cc2f2495a9e60fd25a4fc \ - --hash=sha256:46a0cf3b8d87f78a3d2e6b145aea4418a6d6d606fe6a16c79bd8ca2bb862bc91 +dask[dataframe]==2026.3.0 \ + --hash=sha256:be614b9242b0b38288060fb2d7696125946469c98a1c30e174883fd199e0428d \ + --hash=sha256:f7d96c8274e8a900d217c1ff6ea8d1bbf0b4c2c21e74a409644498d925eb8f85 # via feast (pyproject.toml) -db-dtypes==1.5.0 \ - --hash=sha256:abdbb2e4eb965800ed6f98af0c5c1cafff9063ace09114be2d26a7f046be2c8a \ - --hash=sha256:ad9e94243f53e104bc77dbf9ae44b580d83a770d3694483aba59c9767966daa5 +db-dtypes==1.5.1 \ + --hash=sha256:901099b807c9312bc61a5bddbfb07512884e6c6d5a9edacf24d50bcf303aa5f7 \ + --hash=sha256:ad71a6645e3c1f06d4d32023940576648f43119822f825f0d22587c6ef8afe15 # via # google-cloud-bigquery # pandas-gbq @@ -493,56 +509,50 @@ dill==0.3.9 \ --hash=sha256:468dff3b89520b474c0397703366b7b95eebe6303f108adf9b19da1f702be87a \ --hash=sha256:81aa267dddf68cbfe8029c42ca9ec6a4ab3b22371d1c450abc54422577b4512c # via feast (pyproject.toml) -duckdb==1.4.4 \ - --hash=sha256:0509b39ea7af8cff0198a99d206dca753c62844adab54e545984c2e2c1381616 \ - --hash=sha256:0d636ceda422e7babd5e2f7275f6a0d1a3405e6a01873f00d38b72118d30c10b \ - --hash=sha256:1af6e76fe8bd24875dc56dd8e38300d64dc708cd2e772f67b9fbc635cc3066a3 \ - --hash=sha256:1f8d55843cc940e36261689054f7dfb6ce35b1f5b0953b0d355b6adb654b0d52 \ - --hash=sha256:25874f8b1355e96178079e37312c3ba6d61a2354f51319dae860cf21335c3a20 \ - --hash=sha256:337f8b24e89bc2e12dadcfe87b4eb1c00fd920f68ab07bc9b70960d6523b8bc3 \ - --hash=sha256:452c5b5d6c349dc5d1154eb2062ee547296fcbd0c20e9df1ed00b5e1809089da \ - --hash=sha256:453b115f4777467f35103d8081770ac2f223fb5799178db5b06186e3ab51d1f2 \ - --hash=sha256:47dd4162da6a2be59a0aef640eb08d6360df1cf83c317dcc127836daaf3b7f7c \ - --hash=sha256:49123b579e4a6323e65139210cd72dddc593a72d840211556b60f9703bda8526 \ - --hash=sha256:4c25d5b0febda02b7944e94fdae95aecf952797afc8cb920f677b46a7c251955 \ - --hash=sha256:50f2eb173c573811b44aba51176da7a4e5c487113982be6a6a1c37337ec5fa57 \ - --hash=sha256:53cd6423136ab44383ec9955aefe7599b3fb3dd1fe006161e6396d8167e0e0d4 \ - --hash=sha256:5536eb952a8aa6ae56469362e344d4e6403cc945a80bc8c5c2ebdd85d85eb64b \ - --hash=sha256:59c8d76016dde854beab844935b1ec31de358d4053e792988108e995b18c08e7 \ - --hash=sha256:5ba684f498d4e924c7e8f30dd157da8da34c8479746c5011b6c0e037e9c60ad2 \ - --hash=sha256:5cdc4126ec925edf3112bc656ac9ed23745294b854935fa7a643a216e4455af6 \ - --hash=sha256:5e1933fac5293fea5926b0ee75a55b8cfe7f516d867310a5b251831ab61fe62b \ - --hash=sha256:6703dd1bb650025b3771552333d305d62ddd7ff182de121483d4e042ea6e2e00 \ - --hash=sha256:6792ca647216bd5c4ff16396e4591cfa9b4a72e5ad7cdd312cec6d67e8431a7c \ - --hash=sha256:6cb357cfa3403910e79e2eb46c8e445bb1ee2fd62e9e9588c6b999df4256abc1 \ - --hash=sha256:6fb1225a9ea5877421481d59a6c556a9532c32c16c7ae6ca8d127e2b878c9389 \ - --hash=sha256:707530f6637e91dc4b8125260595299ec9dd157c09f5d16c4186c5988bfbd09a \ - --hash=sha256:7df7351328ffb812a4a289732f500d621e7de9942a3a2c9b6d4afcf4c0e72526 \ - --hash=sha256:7eec0bf271ac622e57b7f6554a27a6e7d1dd2f43d1871f7962c74bcbbede15ba \ - --hash=sha256:8097201bc5fd0779d7fcc2f3f4736c349197235f4cb7171622936343a1aa8dbf \ - --hash=sha256:8bba52fd2acb67668a4615ee17ee51814124223de836d9e2fdcbc4c9021b3d3c \ - --hash=sha256:8e5c2d8a0452df55e092959c0bfc8ab8897ac3ea0f754cb3b0ab3e165cd79aff \ - --hash=sha256:a3c8542db7ffb128aceb7f3b35502ebaddcd4f73f1227569306cc34bad06680c \ - --hash=sha256:b297eff642503fd435a9de5a9cb7db4eccb6f61d61a55b30d2636023f149855f \ - --hash=sha256:bf138201f56e5d6fc276a25138341b3523e2f84733613fc43f02c54465619a95 \ - --hash=sha256:c65d15c440c31e06baaebfd2c06d71ce877e132779d309f1edf0a85d23c07e92 \ - --hash=sha256:c9566a4ed834ec7999db5849f53da0a7ee83d86830c33f471bf0211a1148ca12 \ - --hash=sha256:cd1be3d48577f5b40eb9706c6b2ae10edfe18e78eb28e31a3b922dcff1183597 \ - --hash=sha256:d0440f59e0cd9936a9ebfcf7a13312eda480c79214ffed3878d75947fc3b7d6d \ - --hash=sha256:d525de5f282b03aa8be6db86b1abffdceae5f1055113a03d5b50cd2fb8cf2ef8 \ - --hash=sha256:ddcfd9c6ff234da603a1edd5fd8ae6107f4d042f74951b65f91bc5e2643856b3 \ - --hash=sha256:e041f2fbd6888da090eca96ac167a7eb62d02f778385dd9155ed859f1c6b6dc8 \ - --hash=sha256:e870a441cb1c41d556205deb665749f26347ed13b3a247b53714f5d589596977 \ - --hash=sha256:f28a18cc790217e5b347bb91b2cab27aafc557c58d3d8382e04b4fe55d0c3f66 \ - --hash=sha256:fb94de6d023de9d79b7edc1ae07ee1d0b4f5fa8a9dcec799650b5befdf7aafec +duckdb==1.5.1 \ + --hash=sha256:054ad424b051b334052afac58cb216f3b1ebb8579fc8c641e60f0182e8725ea9 \ + --hash=sha256:05fc91767d0cfc4cf2fa68966ab5b479ac07561752e42dd0ae30327bd160f64a \ + --hash=sha256:0a6acc2040bec1f05de62a2f3f68f4c12f3ec7d6012b4317d0ab1a195af26225 \ + --hash=sha256:26e56b5f0c96189e3288d83cf7b476e23615987902f801e5788dee15ee9f24a9 \ + --hash=sha256:36e8e32621a9e2a9abe75dc15a4b54a3997f2d8b1e53ad754bae48a083c91130 \ + --hash=sha256:40c5220ec93790b18ec6278da9c6ac2608d997ee6d6f7cd44c5c3992764e8e71 \ + --hash=sha256:446d500a2977c6ae2077f340c510a25956da5c77597175c316edfa87248ceda3 \ + --hash=sha256:46f92ada9023e59f27edc048167b31ac9a03911978b1296c845a34462a27f096 \ + --hash=sha256:482f8a13f2600f527e427f73c42b5aa75536f9892868068f0aaf573055a0135f \ + --hash=sha256:553c273a6a8f140adaa6da6a6135c7f95bdc8c2e5f95252fcdf9832d758e2141 \ + --hash=sha256:5ae7c0d744d64e2753149634787cc4ab60f05ef1e542b060eeab719f3cdb7723 \ + --hash=sha256:5d4147422d91ccdc2d2abf6ed24196025e020259d1d267970ae20c13c2ce84b1 \ + --hash=sha256:6af347debc8b721aa72e48671166282da979d5e5ae52dbc660ab417282b48e23 \ + --hash=sha256:6ba302115f63f6482c000ccfd62efdb6c41d9d182a5bcd4a90e7ab8cd13856eb \ + --hash=sha256:6f7361d66cc801d9eb4df734b139cd7b0e3c257a16f3573ebd550ddb255549e6 \ + --hash=sha256:715f05ea198d20d7f8b407b9b84e0023d17f2b9096c194cea702b7840e74f1f7 \ + --hash=sha256:71dddcebbc5a70e946a06c30b59b5dd7999c9833d307168f90fb4e4b672ab63e \ + --hash=sha256:8150c569b2aa4573b51ba8475e814aa41fd53a3d510c1ffb96f1139f46faf611 \ + --hash=sha256:8843bd9594e1387f1e601439e19ad73abdf57356104fd1e53a708255bb95a13d \ + --hash=sha256:8c0088765747ae5d6c9f89987bb36f9fb83564f07090d721344ce8e1abedffea \ + --hash=sha256:972d0dbf283508f9bc446ee09c3838cb7c7f114b5bdceee41753288c97fe2f7c \ + --hash=sha256:a28531cee2a5a42d89f9ba4da53bfeb15681f12acc0263476c8705380dadce07 \ + --hash=sha256:a3be2072315982e232bfe49c9d3db0a59ba67b2240a537ef42656cc772a887c7 \ + --hash=sha256:ac2804043bd1bc10b5da18f8f4c706877197263a510c41be9b4c0062f5783dcc \ + --hash=sha256:afab8b4b1f4469c3879bb049dd039f8fce402712050324e9524a43d7324c5e87 \ + --hash=sha256:b370d1620a34a4538ef66524fcee9de8171fa263c701036a92bc0b4c1f2f9c6d \ + --hash=sha256:b8b0808dba0c63b7633bdaefb34e08fe0612622224f9feb0e7518904b1615101 \ + --hash=sha256:bc7ca6a1a40e7e4c933017e6c09ef18032add793df4e42624c6c0c87e0bebdad \ + --hash=sha256:caa65e1f5bf007430bf657c37cab7ab81a4ddf8d337e3062bcc5085d17ef038b \ + --hash=sha256:d68c5a01a283cb13b79eafe016fe5869aa11bff8c46e7141c70aa0aac808010f \ + --hash=sha256:da137802688190835b4c863cafa77fd7e29dff662ee6d905a9ffc14f00299c91 \ + --hash=sha256:e56a20ab6cdb90a95b0c99652e28de3504ce77129087319c03c9098266183ae5 \ + --hash=sha256:e878ccb7d20872065e1597935fdb5e65efa43220c8edd0d9c4a1a7ff1f3eb277 \ + --hash=sha256:eba81e0b3011c1f23df7ea47ef4ffaa8239817959ae291515b6efd068bde2161 \ + --hash=sha256:ed6d23a3f806898e69c77430ebd8da0c79c219f97b9acbc9a29a653e09740c59 # via ibis-framework durationpy==0.10 \ --hash=sha256:1fa6893409a6e739c9c72334fc65cca1f355dbdd93405d30f726deb5bde42fba \ --hash=sha256:3b41e1b601234296b4fb368338fdcd3e13e0b4fb5b67345948f4f2bf9868b286 # via kubernetes -fastapi==0.129.0 \ - --hash=sha256:61315cebd2e65df5f97ec298c888f9de30430dd0612d59d6480beafbc10655af \ - --hash=sha256:b4946880e48f462692b31c083be0432275cbfb6e2274566b1be91479cc1a84ec +fastapi==0.135.3 \ + --hash=sha256:9b0f590c813acd13d0ab43dd8494138eb58e484bfac405db1f3187cfc5810d98 \ + --hash=sha256:bd6d7caf1a2bdd8d676843cdcd2287729572a1ef524fc4d65c17ae002a1be654 # via # feast (pyproject.toml) # fastapi-mcp @@ -550,9 +560,9 @@ fastapi-mcp==0.4.0 \ --hash=sha256:d4a3fe7966af24d44e4b412720561c95eb12bed999a4443a88221834b3b15aec \ --hash=sha256:d4ca9410996f4c7b8ea0d7b20fdf79878dc359ebf89cbf3b222e0b675a55097d # via feast (pyproject.toml) -filelock==3.24.2 \ - --hash=sha256:667d7dc0b7d1e1064dd5f8f8e80bdac157a6482e8d2e02cd16fd3b6b33bd6556 \ - --hash=sha256:c22803117490f156e59fafce621f0550a7a853e2bbf4f87f112b11d469b6c81b +filelock==3.25.2 \ + --hash=sha256:b64ece2b38f4ca29dd3e810287aa8c48182bbecd1ae6e9ae126c9b35f1382694 \ + --hash=sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70 # via snowflake-connector-python frozenlist==1.8.0 \ --hash=sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686 \ @@ -694,9 +704,9 @@ fsspec==2024.9.0 \ # via # feast (pyproject.toml) # dask -google-api-core[grpc]==2.29.0 \ - --hash=sha256:84181be0f8e6b04006df75ddfe728f24489f0af57c96a529ff7cf45bc28797f7 \ - --hash=sha256:d30bc60980daa36e314b5d5a3e5958b0200cb44ca8fa1be2b614e932b75a3ea9 +google-api-core[grpc]==2.30.2 \ + --hash=sha256:9a8113e1a88bdc09a7ff629707f2214d98d61c7f6ceb0ea38c42a095d02dc0f9 \ + --hash=sha256:a4c226766d6af2580577db1f1a51bf53cd262f722b49731ce7414c43068a9594 # via # feast (pyproject.toml) # google-cloud-bigquery @@ -706,9 +716,9 @@ google-api-core[grpc]==2.29.0 \ # google-cloud-datastore # google-cloud-storage # pandas-gbq -google-auth==2.48.0 \ - --hash=sha256:2e2a537873d449434252a9632c28bfc268b0adb1e53f9fb62afc5333a975903f \ - --hash=sha256:4f7e706b0cd3208a3d940a19a822c37a476ddba5450156c3e6624a71f7c841ce +google-auth==2.49.1 \ + --hash=sha256:16d40da1c3c5a0533f57d268fe72e0ebb0ae1cc3b567024122651c045d879b64 \ + --hash=sha256:195ebe3dca18eddd1b3db5edc5189b76c13e96f29e73043b923ebcf3f1a860f7 # via # google-api-core # google-auth-oauthlib @@ -720,37 +730,37 @@ google-auth==2.48.0 \ # google-cloud-storage # pandas-gbq # pydata-google-auth -google-auth-oauthlib==1.2.4 \ - --hash=sha256:0e922eea5f2baacaf8867febb782e46e7b153236c21592ed76ab3ddb77ffd772 \ - --hash=sha256:3ca93859c6cc9003c8e12b2a0868915209d7953f05a70f4880ab57d57e56ee3e +google-auth-oauthlib==1.3.1 \ + --hash=sha256:14c22c7b3dd3d06dbe44264144409039465effdd1eef94f7ce3710e486cc4bfa \ + --hash=sha256:1a139ef23f1318756805b0e95f655c238bffd29655329a2978218248da4ee7f8 # via # pandas-gbq # pydata-google-auth -google-cloud-bigquery[pandas]==3.40.1 \ - --hash=sha256:75afcfb6e007238fe1deefb2182105249321145ff921784fe7b1de2b4ba24506 \ - --hash=sha256:9082a6b8193aba87bed6a2c79cf1152b524c99bb7e7ac33a785e333c09eac868 +google-cloud-bigquery[pandas]==3.41.0 \ + --hash=sha256:2217e488b47ed576360c9b2cc07d59d883a54b83167c0ef37f915c26b01a06fe \ + --hash=sha256:2a5b5a737b401cbd824a6e5eac7554100b878668d908e6548836b5d8aaa4dcaa # via # feast (pyproject.toml) # pandas-gbq -google-cloud-bigquery-storage==2.36.1 \ - --hash=sha256:99ad6b8810d028f0cf368ea0cc54b3cda20e856f05eb4cda51f1db2a70692286 \ - --hash=sha256:fd3917584a41f7a9d9c633b31ff43103869b108224e8a4b765537eb1ea83148c +google-cloud-bigquery-storage==2.37.0 \ + --hash=sha256:1e319c27ef60fc31030f6e0b52e5e891e1cdd50551effe8c6f673a4c3c56fcb6 \ + --hash=sha256:f88ee7f1e49db1e639da3d9a8b79835ca4bc47afbb514fb2adfc0ccb41a7fd97 # via feast (pyproject.toml) -google-cloud-bigtable==2.35.0 \ - --hash=sha256:f355bfce1f239453ec2bb3839b0f4f9937cf34ef06ef29e1ca63d58fd38d0c50 \ - --hash=sha256:f5699012c5fea4bd4bdf7e80e5e3a812a847eb8f41bf8dc2f43095d6d876b83b +google-cloud-bigtable==2.36.0 \ + --hash=sha256:21b2f41231b7368a550b44d5b493b811b3507fcb23eb26d00005cd3f205f2207 \ + --hash=sha256:d5987733c2f60c739f93f259d2037858411cc994ac37cdfbccb6bb159f3ca43e # via feast (pyproject.toml) -google-cloud-core==2.5.0 \ - --hash=sha256:67d977b41ae6c7211ee830c7912e41003ea8194bff15ae7d72fd6f51e57acabc \ - --hash=sha256:7c1b7ef5c92311717bd05301aa1a91ffbc565673d3b0b4163a52d8413a186963 +google-cloud-core==2.5.1 \ + --hash=sha256:3dc94bdec9d05a31d9f355045ed0f369fbc0d8c665076c734f065d729800f811 \ + --hash=sha256:ea62cdf502c20e3e14be8a32c05ed02113d7bef454e40ff3fab6fe1ec9f1f4e7 # via # google-cloud-bigquery # google-cloud-bigtable # google-cloud-datastore # google-cloud-storage -google-cloud-datastore==2.23.0 \ - --hash=sha256:24a1b1d29b902148fe41b109699f76fd3aa60591e9d547c0f8b87d7bf9ff213f \ - --hash=sha256:80049883a4ae928fdcc661ba6803ec267665dc0e6f3ce2da91441079a6bb6387 +google-cloud-datastore==2.24.0 \ + --hash=sha256:81f1d1c12c2906f59507f72742545ab04c38f62ed70b0542057e3cf04a53aa65 \ + --hash=sha256:f087c02a6aa4ac68bbf17f0c048ae3ee355856bf09c51439bfba193741387792 # via feast (pyproject.toml) google-cloud-storage==2.19.0 \ --hash=sha256:aeb971b5c29cf8ab98445082cbfe7b161a1f48ed275822f59ed3f1524ea54fba \ @@ -794,23 +804,23 @@ google-crc32c==1.8.0 \ # google-cloud-bigtable # google-cloud-storage # google-resumable-media -google-resumable-media==2.8.0 \ - --hash=sha256:dd14a116af303845a8d932ddae161a26e86cc229645bc98b39f026f9b1717582 \ - --hash=sha256:f1157ed8b46994d60a1bc432544db62352043113684d4e030ee02e77ebe9a1ae +google-resumable-media==2.8.2 \ + --hash=sha256:82b6d8ccd11765268cdd2a2123f417ec806b8eef3000a9a38dfe3033da5fb220 \ + --hash=sha256:f3354a182ebd193ae3f42e3ef95e6c9b10f128320de23ac7637236713b1acd70 # via # google-cloud-bigquery # google-cloud-storage -googleapis-common-protos[grpc]==1.72.0 \ - --hash=sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038 \ - --hash=sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5 +googleapis-common-protos[grpc]==1.74.0 \ + --hash=sha256:57971e4eeeba6aad1163c1f0fc88543f965bb49129b8bb55b2b7b26ecab084f1 \ + --hash=sha256:702216f78610bb510e3f12ac3cafd281b7ac45cc5d86e90ad87e4d301a3426b5 # via # feast (pyproject.toml) # google-api-core # grpc-google-iam-v1 # grpcio-status -grpc-google-iam-v1==0.14.3 \ - --hash=sha256:7a7f697e017a067206a3dfef44e4c634a34d3dee135fe7d7a4613fe3e59217e6 \ - --hash=sha256:879ac4ef33136c5491a6300e27575a9ec760f6cdf9a2518798c1b8977a5dc389 +grpc-google-iam-v1==0.14.4 \ + --hash=sha256:392b3796947ed6334e61171d9ab06bf7eb357f554e5fc7556ad7aab6d0e17038 \ + --hash=sha256:412facc320fcbd94034b4df3d557662051d4d8adfa86e0ddb4dca70a3f739964 # via google-cloud-bigtable grpcio==1.62.3 \ --hash=sha256:059444f0ed5dba73ab7dd0ee7e8e6b606df4130d2b0a9f010f84da4ab9f6c2d8 \ @@ -891,9 +901,9 @@ grpcio-status==1.62.3 \ --hash=sha256:289bdd7b2459794a12cf95dc0cb727bd4a1742c37bd823f760236c937e53a485 \ --hash=sha256:f9049b762ba8de6b1086789d8315846e094edac2c50beaf462338b301a8fd4b8 # via google-api-core -gunicorn==25.1.0 \ - --hash=sha256:1426611d959fa77e7de89f8c0f32eed6aa03ee735f98c01efba3e281b1c47616 \ - --hash=sha256:d0b1236ccf27f72cfe14bce7caadf467186f19e865094ca84221424e839b8b8b +gunicorn==25.3.0 \ + --hash=sha256:cacea387dab08cd6776501621c295a904fe8e3b7aae9a1a3cbb26f4e7ed54660 \ + --hash=sha256:f74e1b2f9f76f6cd1ca01198968bd2dd65830edc24b6e8e4d78de8320e2fe889 # via # feast (pyproject.toml) # uvicorn-worker @@ -1071,9 +1081,9 @@ idna==3.11 \ # requests # snowflake-connector-python # yarl -importlib-metadata==8.7.1 \ - --hash=sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb \ - --hash=sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151 +importlib-metadata==9.0.0 \ + --hash=sha256:2d21d1cc5a017bd0559e36150c21c830ab1dc304dedd1b7ea85d20f45ef3edd7 \ + --hash=sha256:a4f57ab599e6a2e3016d7595cfd72eb4661a5106e787a95bcc90c7105b831efc # via dask jinja2==3.1.6 \ --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ @@ -1100,97 +1110,97 @@ kubernetes==35.0.0 \ --hash=sha256:39e2b33b46e5834ef6c3985ebfe2047ab39135d41de51ce7641a7ca5b372a13d \ --hash=sha256:3d00d344944239821458b9efd484d6df9f011da367ecb155dadf9513f05f09ee # via feast (pyproject.toml) -librt==0.8.0 \ - --hash=sha256:001e5330093d887b8b9165823eca6c5c4db183fe4edea4fdc0680bbac5f46944 \ - --hash=sha256:015e2dde6e096d27c10238bf9f6492ba6c65822dfb69d2bf74c41a8e88b7ddef \ - --hash=sha256:02a9fe85410cc9bef045e7cb7fd26fdde6669e6d173f99df659aa7f6335961e9 \ - --hash=sha256:0583aef7e9a720dd40f26a2ad5a1bf2ccbb90059dac2b32ac516df232c701db3 \ - --hash=sha256:05a3dd3f116747f7e1a2b475ccdc6fb637fd4987126d109e03013a79d40bf9e6 \ - --hash=sha256:0a33335eb59921e77c9acc05d0e654e4e32e45b014a4d61517897c11591094f8 \ - --hash=sha256:0ce33a9778e294507f3a0e3468eccb6a698b5166df7db85661543eca1cfc5369 \ - --hash=sha256:1566dbb9d1eb0987264c9b9460d212e809ba908d2f4a3999383a84d765f2f3f1 \ - --hash=sha256:17269dd2745dbe8e42475acb28e419ad92dfa38214224b1b01020b8cac70b645 \ - --hash=sha256:178707cda89d910c3b28bf5aa5f69d3d4734e0f6ae102f753ad79edef83a83c7 \ - --hash=sha256:1c25a131013eadd3c600686a0c0333eb2896483cbc7f65baa6a7ee761017aef9 \ - --hash=sha256:1e6811cac1dcb27ca4c74e0ca4a5917a8e06db0d8408d30daee3a41724bfde7a \ - --hash=sha256:1ef3bd856373cf8e7382402731f43bfe978a8613b4039e49e166e1e0dc590216 \ - --hash=sha256:20f73d4fecba969efc15cdefd030e382502d56bb6f1fc66b580cce582836c9fa \ - --hash=sha256:21b14464bee0b604d80a638cf1ee3148d84ca4cc163dcdcecb46060c1b3605e4 \ - --hash=sha256:24a01c13a2a9bdad20997a4443ebe6e329df063d1978bbe2ebbf637878a46d1e \ - --hash=sha256:25b3e667cbfc9000c4740b282df599ebd91dbdcc1aa6785050e4c1d6be5329ab \ - --hash=sha256:25e82d920d4d62ad741592fcf8d0f3bda0e3fc388a184cb7d2f566c681c5f7b9 \ - --hash=sha256:2b37437e7e4ef5e15a297b36ba9e577f73e29564131d86dd75875705e97402b5 \ - --hash=sha256:2ccdd20d9a72c562ffb73098ac411de351b53a6fbb3390903b2d33078ef90447 \ - --hash=sha256:2e0ffe88ebb5962f8fb0ddcbaaff30f1ea06a79501069310e1e030eafb1ad787 \ - --hash=sha256:375eda7acfce1f15f5ed56cfc960669eefa1ec8732e3e9087c3c4c3f2066759c \ - --hash=sha256:3d2720335020219197380ccfa5c895f079ac364b4c429e96952cd6509934d8eb \ - --hash=sha256:3e36a8da17134ffc29373775d88c04832f9ecfab1880470661813e6c7991ef79 \ - --hash=sha256:3e8b77b5f54d0937b26512774916041756c9eb3e66f1031971e626eea49d0bf4 \ - --hash=sha256:41064a0c07b4cc7a81355ccc305cb097d6027002209ffca51306e65ee8293630 \ - --hash=sha256:421765e8c6b18e64d21c8ead315708a56fc24f44075059702e421d164575fdda \ - --hash=sha256:4831c44b8919e75ca0dfb52052897c1ef59fdae19d3589893fbd068f1e41afbf \ - --hash=sha256:48f84830a8f8ad7918afd743fd7c4eb558728bceab7b0e38fd5a5cf78206a556 \ - --hash=sha256:4b705f85311ee76acec5ee70806990a51f0deb519ea0c29c1d1652d79127604d \ - --hash=sha256:4d3e38797eb482485b486898f89415a6ab163bc291476bd95712e42cf4383c05 \ - --hash=sha256:4eb5e06ebcc668677ed6389164f52f13f71737fc8be471101fa8b4ce77baeb0c \ - --hash=sha256:4f6e975377fbc4c9567cb33ea9ab826031b6c7ec0515bfae66a4fb110d40d6da \ - --hash=sha256:4f764b2424cb04524ff7a486b9c391e93f93dc1bd8305b2136d25e582e99aa2f \ - --hash=sha256:507e94f4bec00b2f590fbe55f48cd518a208e2474a3b90a60aa8f29136ddbada \ - --hash=sha256:56901f1eec031396f230db71c59a01d450715cbbef9856bf636726994331195d \ - --hash=sha256:5cb11061a736a9db45e3c1293cfcb1e3caf205912dfa085734ba750f2197ff9a \ - --hash=sha256:5d0f76fc73480d42285c609c0ea74d79856c160fa828ff9aceab574ea4ecfd7b \ - --hash=sha256:667e2513cf69bfd1e1ed9a00d6c736d5108714ec071192afb737987955888a25 \ - --hash=sha256:671a6152edf3b924d98a5ed5e6982ec9cb30894085482acadce0975f031d4c5c \ - --hash=sha256:693697133c3b32aa9b27f040e3691be210e9ac4d905061859a9ed519b1d5a376 \ - --hash=sha256:6a3146c63220d814c4a2c7d6a1eacc8d5c14aed0ff85115c1dfea868080cd18f \ - --hash=sha256:6b6caff69e25d80c269b1952be8493b4d94ef745f438fa619d7931066bdd26de \ - --hash=sha256:6e1af31a710e17891d9adf0dbd9a5fcd94901a3922a96499abdbf7ce658f4e01 \ - --hash=sha256:70defb797c4d5402166787a6b3c66dfb3fa7f93d118c0509ffafa35a392f4258 \ - --hash=sha256:71fc517efc14f75c2f74b1f0a5d5eb4a8e06aa135c34d18eaf3522f4a53cd62d \ - --hash=sha256:75d1a8cab20b2043f03f7aab730551e9e440adc034d776f15f6f8d582b0a5ad4 \ - --hash=sha256:789911e8fa40a2e82f41120c936b1965f3213c67f5a483fc5a41f5839a05dcbb \ - --hash=sha256:7bd68cebf3131bb920d5984f75fe302d758db33264e44b45ad139385662d7bc3 \ - --hash=sha256:7ce0a8cb67e702dcb06342b2aaaa3da9fb0ddc670417879adfa088b44cf7b3b6 \ - --hash=sha256:7f820210e21e3a8bf8fde2ae3c3d10106d4de9ead28cbfdf6d0f0f41f5b12fa1 \ - --hash=sha256:8070aa3368559de81061ef752770d03ca1f5fc9467d4d512d405bd0483bfffe6 \ - --hash=sha256:82e61cd1c563745ad495387c3b65806bfd453badb4adbc019df3389dddee1bf6 \ - --hash=sha256:82fb4602d1b3e303a58bfe6165992b5a78d823ec646445356c332cd5f5bbaa61 \ - --hash=sha256:88c6e75540f1f10f5e0fc5e87b4b6c290f0e90d1db8c6734f670840494764af8 \ - --hash=sha256:8992ca186a1678107b0af3d0c9303d8c7305981b9914989b9788319ed4d89546 \ - --hash=sha256:92249938ab744a5890580d3cb2b22042f0dce71cdaa7c1369823df62bedf7cbc \ - --hash=sha256:95a719a049f0eefaf1952673223cf00d442952273cbd20cf2ed7ec423a0ef58d \ - --hash=sha256:9646178cd794704d722306c2c920c221abbf080fede3ba539d5afdec16c46dad \ - --hash=sha256:9726305d3e53419d27fc8cdfcd3f9571f0ceae22fa6b5ea1b3662c2e538f833e \ - --hash=sha256:995d24caa6bbb34bcdd4a41df98ac6d1af637cfa8975cb0790e47d6623e70e3e \ - --hash=sha256:9ab3a3475a55b89b87ffd7e6665838e8458e0b596c22e0177e0f961434ec474a \ - --hash=sha256:9f09d4884f882baa39a7e36bbf3eae124c4ca2a223efb91e567381d1c55c6b06 \ - --hash=sha256:a512c88900bdb1d448882f5623a0b1ad27ba81a9bd75dacfe17080b72272ca1f \ - --hash=sha256:a905091a13e0884701226860836d0386b88c72ce5c2fdfba6618e14c72be9f25 \ - --hash=sha256:aaadec87f45a3612b6818d1db5fbfe93630669b7ee5d6bdb6427ae08a1aa2141 \ - --hash=sha256:b055bb3abaf69abed25743d8fc1ab691e4f51a912ee0a6f9a6c84f4bbddb283d \ - --hash=sha256:b4bb00bd71b448f16749909b08a0ff16f58b079e2261c2e1000f2bbb2a4f0a45 \ - --hash=sha256:b9aef96d7593584e31ef6ac1eb9775355b0099fee7651fae3a15bc8657b67b52 \ - --hash=sha256:ba581acad5ac8f33e2ff1746e8a57e001b47c6721873121bf8bbcf7ba8bd3aa4 \ - --hash=sha256:ba9d9e60651615bc614be5e21a82cdb7b1769a029369cf4b4d861e4f19686fb6 \ - --hash=sha256:bbebd2bba5c6ae02907df49150e55870fdd7440d727b6192c46b6f754723dde9 \ - --hash=sha256:bd32add59b58fba3439d48d6f36ac695830388e3da3e92e4fc26d2d02670d19c \ - --hash=sha256:bdab762e2c0b48bab76f1a08acb3f4c77afd2123bedac59446aeaaeed3d086cf \ - --hash=sha256:c5512aae4648152abaf4d48b59890503fcbe86e85abc12fb9b096fe948bdd816 \ - --hash=sha256:c6e4c10761ddbc0d67d2f6e2753daf99908db85d8b901729bf2bf5eaa60e0567 \ - --hash=sha256:cb4b3ad543084ed79f186741470b251b9d269cd8b03556f15a8d1a99a64b7de5 \ - --hash=sha256:cb74cdcbc0103fc988e04e5c58b0b31e8e5dd2babb9182b6f9490488eb36324b \ - --hash=sha256:cc3d107f603b5ee7a79b6aa6f166551b99b32fb4a5303c4dfcb4222fc6a0335e \ - --hash=sha256:d920789eca7ef71df7f31fd547ec0d3002e04d77f30ba6881e08a630e7b2c30e \ - --hash=sha256:daae5e955764be8fd70a93e9e5133c75297f8bce1e802e1d3683b98f77e1c5ab \ - --hash=sha256:db63cf3586a24241e89ca1ce0b56baaec9d371a328bd186c529b27c914c9a1ef \ - --hash=sha256:db953b675079884ffda33d1dca7189fb961b6d372153750beb81880384300817 \ - --hash=sha256:de076eaba208d16efb5962f99539867f8e2c73480988cb513fcf1b5dbb0c9dcf \ - --hash=sha256:e79dbc8f57de360f0ed987dc7de7be814b4803ef0e8fc6d3ff86e16798c99935 \ - --hash=sha256:e9a3a38eb4134ad33122a6d575e6324831f930a771d951a15ce232e0237412c2 \ - --hash=sha256:f04ca50e847abc486fa8f4107250566441e693779a5374ba211e96e238f298b9 \ - --hash=sha256:f1178e0de0c271231a660fbef9be6acdfa1d596803464706862bef6644cc1cae \ - --hash=sha256:f4617cef654fca552f00ce5ffdf4f4b68770f18950e4246ce94629b789b92467 \ - --hash=sha256:fa37f99bff354ff191c6bcdffbc9d7cdd4fc37faccfc9be0ef3a4fd5613977da +librt==0.8.1 \ + --hash=sha256:01170b6729a438f0dedc4a26ed342e3dc4f02d1000b4b19f980e1877f0c297e6 \ + --hash=sha256:039b9f2c506bd0ab0f8725aa5ba339c6f0cd19d3b514b50d134789809c24285d \ + --hash=sha256:05bd41cdee35b0c59c259f870f6da532a2c5ca57db95b5f23689fcb5c9e42440 \ + --hash=sha256:086a32dbb71336627e78cc1d6ee305a68d038ef7d4c39aaff41ae8c9aa46e91a \ + --hash=sha256:08eec3a1fc435f0d09c87b6bf1ec798986a3544f446b864e4099633a56fcd9ed \ + --hash=sha256:0bf69d79a23f4f40b8673a947a234baeeb133b5078b483b7297c5916539cf5d5 \ + --hash=sha256:0c3811485fccfda840861905b8c70bba5ec094e02825598bb9d4ca3936857a04 \ + --hash=sha256:0d2f82168e55ddefd27c01c654ce52379c0750ddc31ee86b4b266bcf4d65f2a3 \ + --hash=sha256:0f2ae3725904f7377e11cc37722d5d401e8b3d5851fb9273d7f4fe04f6b3d37d \ + --hash=sha256:10c42e1f6fd06733ef65ae7bebce2872bcafd8d6e6b0a08fe0a05a23b044fb14 \ + --hash=sha256:153188fe98a72f206042be10a2c6026139852805215ed9539186312d50a8e972 \ + --hash=sha256:172d57ec04346b047ca6af181e1ea4858086c80bdf455f61994c4aa6fc3f866c \ + --hash=sha256:190b109bb69592a3401fe1ffdea41a2e73370ace2ffdc4a0e8e2b39cdea81b78 \ + --hash=sha256:1d3a7da44baf692f0c6aeb5b2a09c5e6fc7a703bca9ffa337ddd2e2da53f7732 \ + --hash=sha256:228c2409c079f8c11fb2e5d7b277077f694cb93443eb760e00b3b83cb8b3176c \ + --hash=sha256:22b46eabd76c1986ee7d231b0765ad387d7673bbd996aa0d0d054b38ac65d8f6 \ + --hash=sha256:237796479f4d0637d6b9cbcb926ff424a97735e68ade6facf402df4ec93375ed \ + --hash=sha256:2c74a2da57a094bd48d03fa5d196da83d2815678385d2978657499063709abe1 \ + --hash=sha256:2cc68eeeef5e906839c7bb0815748b5b0a974ec27125beefc0f942715785b551 \ + --hash=sha256:2eb345e8b33fb748227409c9f1233d4df354d6e54091f0e8fc53acdb2ffedeb7 \ + --hash=sha256:31362dbfe297b23590530007062c32c6f6176f6099646bb2c95ab1b00a57c382 \ + --hash=sha256:3dff3d3ca8db20e783b1bc7de49c0a2ab0b8387f31236d6a026597d07fcd68ac \ + --hash=sha256:43353b943613c5d9c49a25aaffdba46f888ec354e71e3529a00cca3f04d66a7a \ + --hash=sha256:439352ba9373f11cb8e1933da194dcc6206daf779ff8df0ed69c5e39113e6a99 \ + --hash=sha256:4998009e7cb9e896569f4be7004f09d0ed70d386fa99d42b6d363f6d200501ac \ + --hash=sha256:4be2a5c926b9770c9e08e717f05737a269b9d0ebc5d2f0060f0fe3fe9ce47acb \ + --hash=sha256:4beb04b8c66c6ae62f8c1e0b2f097c1ebad9295c929a8d5286c05eae7c2fc7dc \ + --hash=sha256:4c8dfa264b9193c4ee19113c985c95f876fae5e51f731494fc4e0cf594990ba7 \ + --hash=sha256:5212a5bd7fae98dae95710032902edcd2ec4dc994e883294f75c857b83f9aba0 \ + --hash=sha256:52c224e14614b750c0a6d97368e16804a98c684657c7518752c356834fff83bb \ + --hash=sha256:56e04c14b696300d47b3bc5f1d10a00e86ae978886d0cee14e5714fafb5df5d2 \ + --hash=sha256:5bb54f1205a3a6ab41a6fd71dfcdcbd278670d3a90ca502a30d9da583105b6f7 \ + --hash=sha256:5cdc0f588ff4b663ea96c26d2a230c525c6fc62b28314edaaaca8ed5af931ad0 \ + --hash=sha256:5db05697c82b3a2ec53f6e72b2ed373132b0c2e05135f0696784e97d7f5d48e7 \ + --hash=sha256:5e4af413908f77294605e28cfd98063f54b2c790561383971d2f52d113d9c363 \ + --hash=sha256:5fc48998000cbc39ec0d5311312dda93ecf92b39aaf184c5e817d5d440b29624 \ + --hash=sha256:60a78b694c9aee2a0f1aaeaa7d101cf713e92e8423a941d2897f4fa37908dab9 \ + --hash=sha256:64548cde61b692dc0dc379f4b5f59a2f582c2ebe7890d09c1ae3b9e66fa015b7 \ + --hash=sha256:681dc2451d6d846794a828c16c22dc452d924e9f700a485b7ecb887a30aad1fd \ + --hash=sha256:6b1977c4ea97ce5eb7755a78fae68d87e4102e4aaf54985e8b56806849cc06a3 \ + --hash=sha256:6cfa7fe54fd4d1f47130017351a959fe5804bda7a0bc7e07a2cdbc3fdd28d34f \ + --hash=sha256:738f08021b3142c2918c03692608baed43bc51144c29e35807682f8070ee2a3a \ + --hash=sha256:747328be0c5b7075cde86a0e09d7a9196029800ba75a1689332348e998fb85c0 \ + --hash=sha256:758509ea3f1eba2a57558e7e98f4659d0ea7670bff49673b0dde18a3c7e6c0eb \ + --hash=sha256:785ae29c1f5c6e7c2cde2c7c0e148147f4503da3abc5d44d482068da5322fd9e \ + --hash=sha256:7aae78ab5e3206181780e56912d1b9bb9f90a7249ce12f0e8bf531d0462dd0fc \ + --hash=sha256:7b02679a0d783bdae30d443025b94465d8c3dc512f32f5b5031f93f57ac32071 \ + --hash=sha256:7e2f3edca35664499fbb36e4770650c4bd4a08abc1f4458eab9df4ec56389730 \ + --hash=sha256:7e6bad1cd94f6764e1e21950542f818a09316645337fd5ab9a7acc45d99a8f35 \ + --hash=sha256:81fd938344fecb9373ba1b155968c8a329491d2ce38e7ddb76f30ffb938f12dc \ + --hash=sha256:82210adabbc331dbb65d7868b105185464ef13f56f7f76688565ad79f648b0fe \ + --hash=sha256:89815a22daf9c51884fb5dbe4f1ef65ee6a146e0b6a8df05f753e2e4a9359bf4 \ + --hash=sha256:8f1125e6bbf2f1657d9a2f3ccc4a2c9b0c8b176965bb565dd4d86be67eddb4b6 \ + --hash=sha256:8f4bb453f408137d7581be309b2fbc6868a80e7ef60c88e689078ee3a296ae71 \ + --hash=sha256:924817ab3141aca17893386ee13261f1d100d1ef410d70afe4389f2359fea4f0 \ + --hash=sha256:93c2af9e01e0ef80d95ae3c720be101227edae5f2fe7e3dc63d8857fadfc5a1d \ + --hash=sha256:97c2b54ff6717a7a563b72627990bec60d8029df17df423f0ed37d56a17a176b \ + --hash=sha256:9be2f15e53ce4e83cc08adc29b26fb5978db62ef2a366fbdf716c8a6c8901040 \ + --hash=sha256:9e2c6f77b9ad48ce5603b83b7da9ee3e36b3ab425353f695cba13200c5d96596 \ + --hash=sha256:a28f2612ab566b17f3698b0da021ff9960610301607c9a5e8eaca62f5e1c350a \ + --hash=sha256:a355d99c4c0d8e5b770313b8b247411ed40949ca44e33e46a4789b9293a907ee \ + --hash=sha256:a3b4350b13cc0e6f5bec8fa7caf29a8fb8cdc051a3bae45cfbfd7ce64f009965 \ + --hash=sha256:aaab0e307e344cb28d800957ef3ec16605146ef0e59e059a60a176d19543d1b7 \ + --hash=sha256:ac1e7817fd0ed3d14fd7c5df91daed84c48e4c2a11ee99c0547f9f62fdae13da \ + --hash=sha256:adfab487facf03f0d0857b8710cf82d0704a309d8ffc33b03d9302b4c64e91a9 \ + --hash=sha256:b6d7ab1f01aa753188605b09a51faa44a3327400b00b8cce424c71910fc0a128 \ + --hash=sha256:bacdb58d9939d95cc557b4dbaa86527c9db2ac1ed76a18bc8d26f6dc8647d851 \ + --hash=sha256:be46a14693955b3bd96014ccbdb8339ee8c9346fbe11c1b78901b55125f14c73 \ + --hash=sha256:bf512a71a23504ed08103a13c941f763db13fb11177beb3d9244c98c29fb4a61 \ + --hash=sha256:c00e5c884f528c9932d278d5c9cbbea38a6b81eb62c02e06ae53751a83a4d52b \ + --hash=sha256:c25d9e338d5bed46c1632f851babf3d13c78f49a225462017cf5e11e845c5891 \ + --hash=sha256:c336d61d2fe74a3195edc1646d53ff1cddd3a9600b09fa6ab75e5514ba4862a7 \ + --hash=sha256:cc3656283d11540ab0ea01978378e73e10002145117055e03722417aeab30994 \ + --hash=sha256:cf450f498c30af55551ba4f66b9123b7185362ec8b625a773b3d39aa1a717583 \ + --hash=sha256:d0ee06b5b5291f609ddb37b9750985b27bc567791bc87c76a569b3feed8481ac \ + --hash=sha256:d480de377f5b687b6b1bc0c0407426da556e2a757633cc7e4d2e1a057aa688f3 \ + --hash=sha256:d56bc4011975f7460bea7b33e1ff425d2f1adf419935ff6707273c77f8a4ada6 \ + --hash=sha256:dd3c41254ee98604b08bd5b3af5bf0a89740d4ee0711de95b65166bf44091921 \ + --hash=sha256:e0d138c7ae532908cbb342162b2611dbd4d90c941cd25ab82084aaf71d2c0bd0 \ + --hash=sha256:e11769a1dbda4da7b00a76cfffa67aa47cfa66921d2724539eee4b9ede780b79 \ + --hash=sha256:e3f0a41487fd5fad7e760b9e8a90e251e27c2816fbc2cff36a22a0e6bcbbd9dd \ + --hash=sha256:e692aa2d1d604e6ca12d35e51fdc36f4cda6345e28e36374579f7ef3611b3012 \ + --hash=sha256:e70a57ecf89a0f64c24e37f38d3fe217a58169d2fe6ed6d70554964042474023 \ + --hash=sha256:e96baa6820280077a78244b2e06e416480ed859bbd8e5d641cf5742919d8beb4 \ + --hash=sha256:eb5656019db7c4deacf0c1a55a898c5bb8f989be904597fcb5232a2f4828fa05 \ + --hash=sha256:eca45e982fa074090057132e30585a7e8674e9e885d402eae85633e9f449ce6c \ + --hash=sha256:f0af2bd2bc204fa27f3d6711d0f360e6b8c684a035206257a81673ab924aa11e \ + --hash=sha256:f7cdf7f26c2286ffb02e46d7bac56c94655540b26347673bea15fa52a6af17e9 \ + --hash=sha256:fd1a720332ea335ceb544cf0a03f81df92abd4bb887679fd1e460976b0e6214b \ + --hash=sha256:ff8baf1f8d3f4b6b7257fcb75a501f2a5499d0dda57645baa09d4d0d34b19444 # via mypy locket==1.0.0 \ --hash=sha256:5c0d4c052a8bbbf750e056a8e65ccd309086f4f0f18a2eac306a8dfa4112a632 \ @@ -1291,9 +1301,9 @@ markupsafe==3.0.3 \ --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \ --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50 # via jinja2 -mcp==1.26.0 \ - --hash=sha256:904a21c33c25aa98ddbeb47273033c435e595bbacfdb177f4bd87f6dceebe1ca \ - --hash=sha256:db6e2ef491eecc1a0d93711a76f28dec2e05999f93afd48795da1c1137142c66 +mcp==1.27.0 \ + --hash=sha256:5ce1fa81614958e267b21fb2aa34e0aea8e2c6ede60d52aba45fd47246b4d741 \ + --hash=sha256:d3dc35a7eec0d458c1da4976a48f982097ddaab87e278c5511d5a4a56e852b83 # via fastapi-mcp mdurl==0.1.2 \ --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ @@ -1307,128 +1317,114 @@ milvus-lite==2.4.12 \ # via # feast (pyproject.toml) # pymilvus -mmh3==5.2.0 \ - --hash=sha256:03e08c6ebaf666ec1e3d6ea657a2d363bb01effd1a9acfe41f9197decaef0051 \ - --hash=sha256:097e13c8b8a66c5753c6968b7640faefe85d8e38992703c1f666eda6ef4c3762 \ - --hash=sha256:0b898cecff57442724a0f52bf42c2de42de63083a91008fb452887e372f9c328 \ - --hash=sha256:10983c10f5c77683bd845751905ba535ec47409874acc759d5ce3ff7ef34398a \ - --hash=sha256:11730eeb16dfcf9674fdea9bb6b8e6dd9b40813b7eb839bc35113649eef38aeb \ - --hash=sha256:127c95336f2a98c51e7682341ab7cb0be3adb9df0819ab8505a726ed1801876d \ - --hash=sha256:12da42c0a55c9d86ab566395324213c319c73ecb0c239fad4726324212b9441c \ - --hash=sha256:132dd943451a7c7546978863d2f5a64977928410782e1a87d583cb60eb89e667 \ - --hash=sha256:1556e31e4bd0ac0c17eaf220be17a09c171d7396919c3794274cb3415a9d3646 \ - --hash=sha256:1a5f4d2e59d6bba8ef01b013c472741835ad961e7c28f50c82b27c57748744a4 \ - --hash=sha256:1ba55d6ca32eeef8b2625e1e4bfc3b3db52bc63014bd7e5df8cc11bf2b036b12 \ - --hash=sha256:1efc8fec8478e9243a78bb993422cf79f8ff85cb4cf6b79647480a31e0d950a8 \ - --hash=sha256:1f8d8b627799f4e2fcc7c034fed8f5f24dc7724ff52f69838a3d6d15f1ad4765 \ - --hash=sha256:1fae471339ae1b9c641f19cf46dfe6ffd7f64b1fba7c4333b99fa3dd7f21ae0a \ - --hash=sha256:1fdb36b940e9261aff0b5177c5b74a36936b902f473180f6c15bde26143681a9 \ - --hash=sha256:2421b9d665a0b1ad724ec7332fb5a98d075f50bc51a6ff854f3a1882bd650d49 \ - --hash=sha256:29c2b9ce61886809d0492a274a5a53047742dea0f703f9c4d5d223c3ea6377d3 \ - --hash=sha256:2c9da0d568569cc87315cb063486d761e38458b8ad513fedd3dc9263e1b81bcd \ - --hash=sha256:2ebfc46b39168ab1cd44670a32ea5489bcbc74a25795c61b6d888c5c2cf654ed \ - --hash=sha256:3193752fc05ea72366c2b63ff24b9a190f422e32d75fdeae71087c08fff26115 \ - --hash=sha256:33576136c06b46a7046b6d83a3d75fbca7d25f84cec743f1ae156362608dc6d2 \ - --hash=sha256:37a358cc881fe796e099c1db6ce07ff757f088827b4e8467ac52b7a7ffdca647 \ - --hash=sha256:382a6bb3f8c6532ea084e7acc5be6ae0c6effa529240836d59352398f002e3fc \ - --hash=sha256:384eda9361a7bf83a85e09447e1feafe081034af9dd428893701b959230d84be \ - --hash=sha256:38d899a156549da8ef6a9f1d6f7ef231228d29f8f69bce2ee12f5fba6d6fd7c5 \ - --hash=sha256:3bc244802ccab5220008cb712ca1508cb6a12f0eb64ad62997156410579a1770 \ - --hash=sha256:3c6041fd9d5fb5fcac57d5c80f521a36b74aea06b8566431c63e4ffc49aced51 \ - --hash=sha256:3ca975c51c5028947bbcfc24966517aac06a01d6c921e30f7c5383c195f87991 \ - --hash=sha256:3d6bfd9662a20c054bc216f861fa330c2dac7c81e7fb8307b5e32ab5b9b4d2e0 \ - --hash=sha256:419005f84ba1cab47a77465a2a843562dadadd6671b8758bf179d82a15ca63eb \ - --hash=sha256:45b590e31bc552c6f8e2150ff1ad0c28dd151e9f87589e7eaf508fbdd8e8e908 \ - --hash=sha256:49037d417419863b222ae47ee562b2de9c3416add0a45c8d7f4e864be8dc4f89 \ - --hash=sha256:4a5f5536b1cbfa72318ab3bfc8a8188b949260baed186b75f0abc75b95d8c051 \ - --hash=sha256:582f9dbeefe15c32a5fa528b79b088b599a1dfe290a4436351c6090f90ddebb8 \ - --hash=sha256:58477cf9ef16664d1ce2b038f87d2dc96d70fe50733a34a7f07da6c9a5e3538c \ - --hash=sha256:58981d6ea9646dbbf9e59a30890cbf9f610df0e4a57dbfe09215116fd90b0093 \ - --hash=sha256:5a5dba98e514fb26241868f6eb90a7f7ca0e039aed779342965ce24ea32ba513 \ - --hash=sha256:5b0b58215befe0f0e120b828f7645e97719bbba9f23b69e268ed0ac7adde8645 \ - --hash=sha256:61ac226af521a572700f863d6ecddc6ece97220ce7174e311948ff8c8919a363 \ - --hash=sha256:63830f846797187c5d3e2dae50f0848fdc86032f5bfdc58ae352f02f857e9025 \ - --hash=sha256:69fc339d7202bea69ef9bd7c39bfdf9fdabc8e6822a01eba62fb43233c1b3932 \ - --hash=sha256:6d541038b3fc360ec538fc116de87462627944765a6750308118f8b509a8eec7 \ - --hash=sha256:6ecb4e750d712abde046858ee6992b65c93f1f71b397fce7975c3860c07365d2 \ - --hash=sha256:72d80005b7634a3a2220f81fbeb94775ebd12794623bb2e1451701ea732b4aa3 \ - --hash=sha256:7303aab41e97adcf010a09efd8f1403e719e59b7705d5e3cfed3dd7571589290 \ - --hash=sha256:7434a27754049144539d2099a6d2da5d88b8bdeedf935180bf42ad59b3607aa3 \ - --hash=sha256:746a5ee71c6d1103d9b560fa147881b5e68fd35da56e54e03d5acefad0e7c055 \ - --hash=sha256:7733ec52296fc1ba22e9b90a245c821adbb943e98c91d8a330a2254612726106 \ - --hash=sha256:7901c893e704ee3c65f92d39b951f8f34ccf8e8566768c58103fb10e55afb8c1 \ - --hash=sha256:7aa18cdb58983ee660c9c400b46272e14fa253c675ed963d3812487f8ca42037 \ - --hash=sha256:7b986d506a8e8ea345791897ba5d8ba0d9d8820cd4fc3e52dbe6de19388de2e7 \ - --hash=sha256:7bbb0df897944b5ec830f3ad883e32c5a7375370a521565f5fe24443bfb2c4f7 \ - --hash=sha256:7c7f0b342fd06044bedd0b6e72177ddc0076f54fd89ee239447f8b271d919d9b \ - --hash=sha256:7e5634565367b6d98dc4aa2983703526ef556b3688ba3065edb4b9b90ede1c54 \ - --hash=sha256:7fddccd4113e7b736706e17a239a696332360cbaddf25ae75b57ba1acce65081 \ - --hash=sha256:81c504ad11c588c8629536b032940f2a359dda3b6cbfd4ad8f74cb24dcd1b0bc \ - --hash=sha256:81df0dae22cd0da87f1c978602750f33d17fb3d21fb0f326c89dc89834fea79b \ - --hash=sha256:86d1be5d63232e6eb93c50881aea55ff06eb86d8e08f9b5417c8c9b10db9db96 \ - --hash=sha256:8b0c53fe0994beade1ad7c0f13bd6fec980a0664bfbe5a6a7d64500b9ab76772 \ - --hash=sha256:8ebf241072cf2777a492d0e09252f8cc2b3edd07dfdb9404b9757bffeb4f2cee \ - --hash=sha256:931d47e08c9c8a67bf75d82f0ada8399eac18b03388818b62bfa42882d571d72 \ - --hash=sha256:932a6eec1d2e2c3c9e630d10f7128d80e70e2d47fe6b8c7ea5e1afbd98733e65 \ - --hash=sha256:941603bfd75a46023807511c1ac2f1b0f39cccc393c15039969806063b27e6db \ - --hash=sha256:956127e663d05edbeec54df38885d943dfa27406594c411139690485128525de \ - --hash=sha256:96f1e1ac44cbb42bcc406e509f70c9af42c594e72ccc7b1257f97554204445f0 \ - --hash=sha256:99bb6a4d809aa4e528ddfe2c85dd5239b78b9dd14be62cca0329db78505e7b50 \ - --hash=sha256:9f64bf06f4bf623325fda3a6d02d36cd69199b9ace99b04bb2d7fd9f89688504 \ - --hash=sha256:a094319ec0db52a04af9fdc391b4d39a1bc72bc8424b47c4411afb05413a44b5 \ - --hash=sha256:a367d4741ac0103f8198c82f429bccb9359f543ca542b06a51f4f0332e8de279 \ - --hash=sha256:a7c0c7845566b9686480e6a7e9044db4afb60038d5fabd19227443f0104eeee4 \ - --hash=sha256:aa6e5d31fdc5ed9e3e95f9873508615a778fe9b523d52c17fc770a3eb39ab6e4 \ - --hash=sha256:ae9d032488fcec32d22be6542d1a836f00247f40f320844dbb361393b5b22773 \ - --hash=sha256:b0271ac12415afd3171ab9a3c7cbfc71dee2c68760a7dc9d05bf8ed6ddfa3a7a \ - --hash=sha256:b0d753ad566c721faa33db7e2e0eddd74b224cdd3eaf8481d76c926603c7a00e \ - --hash=sha256:b29044e1ffdb84fe164d0a7ea05c7316afea93c00f8ed9449cf357c36fc4f814 \ - --hash=sha256:b5995088dd7023d2d9f310a0c67de5a2b2e06a570ecfd00f9ff4ab94a67cde43 \ - --hash=sha256:b5f317a727bba0e633a12e71228bc6a4acb4f471a98b1c003163b917311ea9a9 \ - --hash=sha256:b9a87025121d1c448f24f27ff53a5fe7b6ef980574b4a4f11acaabe702420d63 \ - --hash=sha256:bb0fdc451fb6d86d81ab8f23d881b8d6e37fc373a2deae1c02d27002d2ad7a05 \ - --hash=sha256:bb4fe46bdc6104fbc28db7a6bacb115ee6368ff993366bbd8a2a7f0076e6f0c0 \ - --hash=sha256:bc44fc2b886243d7c0d8daeb37864e16f232e5b56aaec27cc781d848264cfd28 \ - --hash=sha256:bdde97310d59604f2a9119322f61b31546748499a21b44f6715e8ced9308a6c5 \ - --hash=sha256:be1374df449465c9f2500e62eee73a39db62152a8bdfbe12ec5b5c1cd451344d \ - --hash=sha256:be7d3dca9358e01dab1bad881fb2b4e8730cec58d36dd44482bc068bfcd3bc65 \ - --hash=sha256:bf7bee43e17e81671c447e9c83499f53d99bf440bc6d9dc26a841e21acfbe094 \ - --hash=sha256:c3dca4cb5b946ee91b3d6bb700d137b1cd85c20827f89fdf9c16258253489044 \ - --hash=sha256:c3f563e8901960e2eaa64c8e8821895818acabeb41c96f2efbb936f65dbe486c \ - --hash=sha256:c463d7c1c4cfc9d751efeaadd936bbba07b5b0ed81a012b3a9f5a12f0872bd6e \ - --hash=sha256:c4a2f3d83879e3de2eb8cbf562e71563a8ed15ee9b9c2e77ca5d9f73072ac15c \ - --hash=sha256:c5584061fd3da584659b13587f26c6cad25a096246a481636d64375d0c1f6c07 \ - --hash=sha256:c677d78887244bf3095020b73c42b505b700f801c690f8eaa90ad12d3179612f \ - --hash=sha256:c903e71fd8debb35ad2a4184c1316b3cb22f64ce517b4e6747f25b0a34e41266 \ - --hash=sha256:c9ff37ba9f15637e424c2ab57a1a590c52897c845b768e4e0a4958084ec87f22 \ - --hash=sha256:cadc16e8ea64b5d9a47363013e2bea469e121e6e7cb416a7593aeb24f2ad122e \ - --hash=sha256:cedac4f4054b8f7859e5aed41aaa31ad03fce6851901a7fdc2af0275ac533c10 \ - --hash=sha256:d22c9dcafed659fadc605538946c041722b6d1104fe619dbf5cc73b3c8a0ded8 \ - --hash=sha256:d765058da196f68dc721116cab335e696e87e76720e6ef8ee5a24801af65e63d \ - --hash=sha256:d86651fa45799530885ba4dab3d21144486ed15285e8784181a0ab37a4552384 \ - --hash=sha256:dd966df3489ec13848d6c6303429bbace94a153f43d1ae2a55115fd36fd5ca5d \ - --hash=sha256:ddc63328889bcaee77b743309e5c7d2d52cee0d7d577837c91b6e7cc9e755e0b \ - --hash=sha256:dfbead5575f6470c17e955b94f92d62a03dfc3d07f2e6f817d9b93dc211a1515 \ - --hash=sha256:e0f3ed828d709f5b82d8bfe14f8856120718ec4bd44a5b26102c3030a1e12501 \ - --hash=sha256:e1861fb6b1d0453ed7293200139c0a9011eeb1376632e048e3766945b13313c5 \ - --hash=sha256:e5015f0bb6eb50008bed2d4b1ce0f2a294698a926111e4bb202c0987b4f89078 \ - --hash=sha256:e651e17bfde5840e9e4174b01e9e080ce49277b70d424308b36a7969d0d1af73 \ - --hash=sha256:e7884931fe5e788163e7b3c511614130c2c59feffdc21112290a194487efb2e9 \ - --hash=sha256:e79c00eba78f7258e5b354eccd4d7907d60317ced924ea4a5f2e9d83f5453065 \ - --hash=sha256:e912b19cf2378f2967d0c08e86ff4c6c360129887f678e27e4dde970d21b3f4d \ - --hash=sha256:e9a011469b47b752e7d20de296bb34591cdfcbe76c99c2e863ceaa2aa61113d2 \ - --hash=sha256:eb756caf8975882630ce4e9fbbeb9d3401242a72528230422c9ab3a0d278e60c \ - --hash=sha256:eba01ec3bd4a49b9ac5ca2bc6a73ff5f3af53374b8556fcc2966dd2af9eb7779 \ - --hash=sha256:ecbfc0437ddfdced5e7822d1ce4855c9c64f46819d0fdc4482c53f56c707b935 \ - --hash=sha256:eed4bba7ff8a0d37106ba931ab03bdd3915fbb025bcf4e1f0aa02bc8114960c5 \ - --hash=sha256:f35727c5118aba95f0397e18a1a5b8405425581bfe53e821f0fb444cbdc2bc9b \ - --hash=sha256:f698733a8a494466432d611a8f0d1e026f5286dee051beea4b3c3146817e35d5 \ - --hash=sha256:f7f9034c7cf05ddfaac8d7a2e63a3c97a840d4615d0a0e65ba8bdf6f8576e3be \ - --hash=sha256:fa0c966ee727aad5406d516375593c5f058c766b21236ab8985693934bb5085b \ - --hash=sha256:fc9c5f280438cf1c1a8f9abb87dc8ce9630a964120cfb5dd50d1e7ce79690c7a \ - --hash=sha256:fd6e6c3d90660d085f7e73710eab6f5545d4854b81b0135a3526e797009dbda3 \ - --hash=sha256:fdfd3fb739f4e22746e13ad7ba0c6eedf5f454b18d11249724a388868e308ee4 \ - --hash=sha256:ff3d50dc3fe8a98059f99b445dfb62792b5d006c5e0b8f03c6de2813b8376110 +mmh3==5.2.1 \ + --hash=sha256:022aa1a528604e6c83d0a7705fdef0b5355d897a9e0fa3a8d26709ceaa06965d \ + --hash=sha256:0634581290e6714c068f4aa24020acf7880927d1f0084fa753d9799ae9610082 \ + --hash=sha256:08043f7cb1fb9467c3fbbbaea7896986e7fbc81f4d3fd9289a73d9110ab6207a \ + --hash=sha256:0a3984146e414684a6be2862d84fcb1035f4984851cb81b26d933bab6119bf00 \ + --hash=sha256:0bbc17250b10d3466875a40a52520a6bac3c02334ca709207648abd3c223ed5c \ + --hash=sha256:0cc21533878e5586b80d74c281d7f8da7932bc8ace50b8d5f6dbf7e3935f63f1 \ + --hash=sha256:0d0b7e803191db5f714d264044e06189c8ccd3219e936cc184f07106bd17fd7b \ + --hash=sha256:113f78e7463a36dbbcea05bfe688efd7fa759d0f0c56e73c974d60dcfec3dfcc \ + --hash=sha256:169e0d178cb59314456ab30772429a802b25d13227088085b0d49b9fe1533104 \ + --hash=sha256:17fbb47f0885ace8327ce1235d0416dc86a211dcd8cc1e703f41523be32cfec8 \ + --hash=sha256:19bbd3b841174ae6ed588536ab5e1b1fe83d046e668602c20266547298d939a9 \ + --hash=sha256:1d9f9a3ce559a5267014b04b82956993270f63ec91765e13e9fd73daf2d2738e \ + --hash=sha256:1e4ecee40ba19e6975e1120829796770325841c2f153c0e9aecca927194c6a2a \ + --hash=sha256:22b0f9971ec4e07e8223f2beebe96a6cfc779d940b6f27d26604040dd74d3a44 \ + --hash=sha256:26fb5b9c3946bf7f1daed7b37e0c03898a6f062149127570f8ede346390a0825 \ + --hash=sha256:2778fed822d7db23ac5008b181441af0c869455b2e7d001f4019636ac31b6fe4 \ + --hash=sha256:28cfab66577000b9505a0d068c731aee7ca85cd26d4d63881fab17857e0fe1fb \ + --hash=sha256:29bc3973676ae334412efdd367fcd11d036b7be3efc1ce2407ef8676dabfeb82 \ + --hash=sha256:2bd9f19f7f1fcebd74e830f4af0f28adad4975d40d80620be19ffb2b2af56c9f \ + --hash=sha256:2d5d542bf2abd0fd0361e8017d03f7cb5786214ceb4a40eef1539d6585d93386 \ + --hash=sha256:30e4d2084df019880d55f6f7bea35328d9b464ebee090baa372c096dc77556fb \ + --hash=sha256:3619473a0e0d329fd4aec8075628f8f616be2da41605300696206d6f36920c3d \ + --hash=sha256:368625fb01666655985391dbad3860dc0ba7c0d6b9125819f3121ee7292b4ac8 \ + --hash=sha256:3737303ca9ea0f7cb83028781148fcda4f1dac7821db0c47672971dabcf63593 \ + --hash=sha256:3a9fed49c6ce4ed7e73f13182760c65c816da006debe67f37635580dfb0fae00 \ + --hash=sha256:3c38d142c706201db5b2345166eeef1e7740e3e2422b470b8ba5c8727a9b4c7a \ + --hash=sha256:3cb61db880ec11e984348227b333259994c2c85caa775eb7875decb3768db890 \ + --hash=sha256:3d74a03fb57757ece25aa4b3c1c60157a1cece37a020542785f942e2f827eed5 \ + --hash=sha256:3f796b535008708846044c43302719c6956f39ca2d93f2edda5319e79a29efbb \ + --hash=sha256:41105377f6282e8297f182e393a79cfffd521dde37ace52b106373bdcd9ca5cb \ + --hash=sha256:41aac7002a749f08727cb91babff1daf8deac317c0b1f317adc69be0e6c375d1 \ + --hash=sha256:44983e45310ee5b9f73397350251cdf6e63a466406a105f1d16cb5baa659270b \ + --hash=sha256:4cbbde66f1183db040daede83dd86c06d663c5bb2af6de1142b7c8c37923dd74 \ + --hash=sha256:4eda76074cfca2787c8cf1bec603eaebdddd8b061ad5502f85cddae998d54f00 \ + --hash=sha256:4fc6cd65dc4d2fdb2625e288939a3566e36127a84811a4913f02f3d5931da52d \ + --hash=sha256:50885073e2909251d4718634a191c49ae5f527e5e1736d738e365c3e8be8f22b \ + --hash=sha256:5174a697ce042fa77c407e05efe41e03aa56dae9ec67388055820fb48cf4c3ba \ + --hash=sha256:54b64fb2433bc71488e7a449603bf8bd31fbcf9cb56fbe1eb6d459e90b86c37b \ + --hash=sha256:54fe8518abe06a4c3852754bfd498b30cc58e667f376c513eac89a244ce781a4 \ + --hash=sha256:55dbbd8ffbc40d1697d5e2d0375b08599dae8746b0b08dea05eee4ce81648fac \ + --hash=sha256:57b52603e89355ff318025dd55158f6e71396c0f1f609d548e9ea9c94cc6ce0a \ + --hash=sha256:58370d05d033ee97224c81263af123dea3d931025030fd34b61227a768a8858a \ + --hash=sha256:5d87a3584093e1a89987e3d36d82c98d9621b2cb944e22a420aa1401e096758f \ + --hash=sha256:623f938f6a039536cc02b7582a07a080f13fdfd48f87e63201d92d7e34d09a18 \ + --hash=sha256:62815d2c67f2dd1be76a253d88af4e1da19aeaa1820146dec52cf8bee2958b16 \ + --hash=sha256:6290289fa5fb4c70fd7f72016e03633d60388185483ff3b162912c81205ae2cf \ + --hash=sha256:67e41a497bac88cc1de96eeba56eeb933c39d54bc227352f8455aa87c4ca4000 \ + --hash=sha256:6c85c38a279ca9295a69b9b088a2e48aa49737bb1b34e6a9dc6297c110e8d912 \ + --hash=sha256:6f01f044112d43a20be2f13a11683666d87151542ad627fe41a18b9791d2802f \ + --hash=sha256:707151644085dd0f20fe4f4b573d28e5130c4aaa5f587e95b60989c5926653b5 \ + --hash=sha256:723b2681ed4cc07d3401bbea9c201ad4f2a4ca6ba8cddaff6789f715dd2b391e \ + --hash=sha256:72d1cc63bcc91e14933f77d51b3df899d6a07d184ec515ea7f56bff659e124d7 \ + --hash=sha256:7374d6e3ef72afe49697ecd683f3da12f4fc06af2d75433d0580c6746d2fa025 \ + --hash=sha256:7501e9be34cb21e72fcfe672aafd0eee65c16ba2afa9dcb5500a587d3a0580f0 \ + --hash=sha256:76219cd1eefb9bf4af7856e3ae563d15158efa145c0aab01e9933051a1954045 \ + --hash=sha256:7aec798c2b01aaa65a55f1124f3405804184373abb318a3091325aece235f67c \ + --hash=sha256:7be6dfb49e48fd0a7d91ff758a2b51336f1cd21f9d44b20f6801f072bd080cdd \ + --hash=sha256:7e4e1f580033335c6f76d1e0d6b56baf009d1a64d6a4816347e4271ba951f46d \ + --hash=sha256:7e8ec5f606e0809426d2440e0683509fb605a8820a21ebd120dcdba61b74ef7f \ + --hash=sha256:7f196cd7910d71e9d9860da0ff7a77f64d22c1ad931f1dd18559a06e03109fc0 \ + --hash=sha256:82f3802bfc4751f420d591c5c864de538b71cea117fce67e4595c2afede08a15 \ + --hash=sha256:85ffc9920ffc39c5eee1e3ac9100c913a0973996fbad5111f939bbda49204bb7 \ + --hash=sha256:8e6c219e375f6341d0959af814296372d265a8ca1af63825f65e2e87c618f006 \ + --hash=sha256:8f767ba0911602ddef289404e33835a61168314ebd3c729833db2ed685824211 \ + --hash=sha256:8ff038d52ef6aa0f309feeba00c5095c9118d0abf787e8e8454d6048db2037fc \ + --hash=sha256:915e7a2418f10bd1151b1953df06d896db9783c9cfdb9a8ee1f9b3a4331ab503 \ + --hash=sha256:92883836caf50d5255be03d988d75bc93e3f86ba247b7ca137347c323f731deb \ + --hash=sha256:960b1b3efa39872ac8b6cc3a556edd6fb90ed74f08c9c45e028f1005b26aa55d \ + --hash=sha256:9aeaf53eaa075dd63e81512522fd180097312fb2c9f476333309184285c49ce0 \ + --hash=sha256:9d8089d853c7963a8ce87fff93e2a67075c0bc08684a08ea6ad13577c38ffc38 \ + --hash=sha256:a4130d0b9ce5fad6af07421b1aecc7e079519f70d6c05729ab871794eded8617 \ + --hash=sha256:a482ac121de6973897c92c2f31defc6bafb11c83825109275cffce54bb64933f \ + --hash=sha256:add7ac388d1e0bf57259afbcf9ed05621a3bf11ce5ee337e7536f1e1aaf056b0 \ + --hash=sha256:b1f12bd684887a0a5d55e6363ca87056f361e45451105012d329b86ec19dbe0b \ + --hash=sha256:b3f99e1756fc48ad507b95e5d86f2fb21b3d495012ff13e6592ebac14033f166 \ + --hash=sha256:b4cce60d0223074803c9dbe0721ad3fa51dafe7d462fee4b656a1aa01ee07518 \ + --hash=sha256:baeb47635cb33375dee4924cd93d7f5dcaa786c740b08423b0209b824a1ee728 \ + --hash=sha256:bbea5b775f0ac84945191fb83f845a6fd9a21a03ea7f2e187defac7e401616ad \ + --hash=sha256:bbfcb95d9a744e6e2827dfc66ad10e1020e0cac255eb7f85652832d5a264c2fc \ + --hash=sha256:bd6e7d363aa93bd3421b30b6af97064daf47bc96005bddba67c5ffbc6df426b8 \ + --hash=sha256:be77c402d5e882b6fbacfd90823f13da8e0a69658405a39a569c6b58fdb17b03 \ + --hash=sha256:c302245fd6c33d96bd169c7ccf2513c20f4c1e417c07ce9dce107c8bc3f8411f \ + --hash=sha256:c88653877aeb514c089d1b3d473451677b8b9a6d1497dbddf1ae7934518b06d2 \ + --hash=sha256:cae6383181f1e345317742d2ddd88f9e7d2682fa4c9432e3a74e47d92dce0229 \ + --hash=sha256:cd471ede0d802dd936b6fab28188302b2d497f68436025857ca72cd3810423fe \ + --hash=sha256:d106493a60dcb4aef35a0fac85105e150a11cf8bc2b0d388f5a33272d756c966 \ + --hash=sha256:d30b650595fdbe32366b94cb14f30bb2b625e512bd4e1df00611f99dc5c27fd4 \ + --hash=sha256:d51fde50a77f81330523562e3c2734ffdca9c4c9e9d355478117905e1cfe16c6 \ + --hash=sha256:d57dea657357230cc780e13920d7fa7db059d58fe721c80020f94476da4ca0a1 \ + --hash=sha256:d771f085fcdf4035786adfb1d8db026df1eb4b41dac1c3d070d1e49512843227 \ + --hash=sha256:dae0f0bd7d30c0ad61b9a504e8e272cb8391eed3f1587edf933f4f6b33437450 \ + --hash=sha256:db0562c5f71d18596dcd45e854cf2eeba27d7543e1a3acdafb7eef728f7fe85d \ + --hash=sha256:dfd51b4c56b673dfbc43d7d27ef857dd91124801e2806c69bb45585ce0fa019b \ + --hash=sha256:e080c0637aea036f35507e803a4778f119a9b436617694ae1c5c366805f1e997 \ + --hash=sha256:e48d4dbe0f88e53081da605ae68644e5182752803bbc2beb228cca7f1c4454d6 \ + --hash=sha256:e8b4b5580280b9265af3e0409974fb79c64cf7523632d03fbf11df18f8b0181e \ + --hash=sha256:e8b5378de2b139c3a830f0209c1e91f7705919a4b3e563a10955104f5097a70a \ + --hash=sha256:e904f2417f0d6f6d514f3f8b836416c360f306ddaee1f84de8eef1e722d212e5 \ + --hash=sha256:eee884572b06bbe8a2b54f424dbd996139442cf83c76478e1ec162512e0dd2c7 \ + --hash=sha256:f1fbb0a99125b1287c6d9747f937dc66621426836d1a2d50d05aecfc81911b57 \ + --hash=sha256:f40a95186a72fa0b67d15fef0f157bfcda00b4f59c8a07cbe5530d41ac35d105 \ + --hash=sha256:f6e0bfe77d238308839699944164b96a2eeccaf55f2af400f54dc20669d8d5f2 \ + --hash=sha256:f963eafc0a77a6c0562397da004f5876a9bcf7265a7bcc3205e29636bc4a1312 \ + --hash=sha256:fb9d44c25244e11c8be3f12c938ca8ba8404620ef8092245d2093c6ab3df260f \ + --hash=sha256:fc78739b5ec6e4fb02301984a3d442a91406e7700efbe305071e7fd1c78278f2 \ + --hash=sha256:fceef7fe67c81e1585198215e42ad3fdba3a25644beda8fbdaf85f4d7b93175a \ + --hash=sha256:fd96476f04db5ceba1cfa0f21228f67c1f7402296f0e73fee3513aa680ad237b # via feast (pyproject.toml) multidict==6.7.1 \ --hash=sha256:026d264228bcd637d4e060844e39cdc60f86c479e463d49075dedc21b18fbbe0 \ @@ -1581,123 +1577,129 @@ multidict==6.7.1 \ # aiobotocore # aiohttp # yarl -mypy==1.19.1 \ - --hash=sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd \ - --hash=sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b \ - --hash=sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1 \ - --hash=sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba \ - --hash=sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b \ - --hash=sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045 \ - --hash=sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac \ - --hash=sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6 \ - --hash=sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a \ - --hash=sha256:409088884802d511ee52ca067707b90c883426bd95514e8cfda8281dc2effe24 \ - --hash=sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957 \ - --hash=sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042 \ - --hash=sha256:4f28f99c824ecebcdaa2e55d82953e38ff60ee5ec938476796636b86afa3956e \ - --hash=sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec \ - --hash=sha256:7bcfc336a03a1aaa26dfce9fff3e287a3ba99872a157561cbfcebe67c13308e3 \ - --hash=sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718 \ - --hash=sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f \ - --hash=sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331 \ - --hash=sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1 \ - --hash=sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1 \ - --hash=sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13 \ - --hash=sha256:b13cfdd6c87fc3efb69ea4ec18ef79c74c3f98b4e5498ca9b85ab3b2c2329a67 \ - --hash=sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2 \ - --hash=sha256:b7951a701c07ea584c4fe327834b92a30825514c868b1f69c30445093fdd9d5a \ - --hash=sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b \ - --hash=sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8 \ - --hash=sha256:c608937067d2fc5a4dd1a5ce92fd9e1398691b8c5d012d66e1ddd430e9244376 \ - --hash=sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef \ - --hash=sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288 \ - --hash=sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75 \ - --hash=sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74 \ - --hash=sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250 \ - --hash=sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab \ - --hash=sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6 \ - --hash=sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247 \ - --hash=sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925 \ - --hash=sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e \ - --hash=sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e +mypy==1.20.0 \ + --hash=sha256:002b613ae19f4ac7d18b7e168ffe1cb9013b37c57f7411984abbd3b817b0a214 \ + --hash=sha256:00e047c74d3ec6e71a2eb88e9ea551a2edb90c21f993aefa9e0d2a898e0bb732 \ + --hash=sha256:02cca0761c75b42a20a2757ae58713276605eb29a08dd8a6e092aa347c4115ca \ + --hash=sha256:0ecd63f75fdd30327e4ad8b5704bd6d91fc6c1b2e029f8ee14705e1207212489 \ + --hash=sha256:0f42dfaab7ec1baff3b383ad7af562ab0de573c5f6edb44b2dab016082b89948 \ + --hash=sha256:1973868d2adbb4584a3835780b27436f06d1dc606af5be09f187aaa25be1070f \ + --hash=sha256:26c8b52627b6552f47ff11adb4e1509605f094e29815323e487fc0053ebe93d1 \ + --hash=sha256:2721f0ce49cb74a38f00c50da67cb7d36317b5eda38877a49614dc018e91c787 \ + --hash=sha256:2fcedb16d456106e545b2bfd7ef9d24e70b38ec252d2a629823a4d07ebcdb69e \ + --hash=sha256:31b5dbb55293c1bd27c0fc813a0d2bb5ceef9d65ac5afa2e58f829dab7921fd5 \ + --hash=sha256:34506397dbf40c15dc567635d18a21d33827e9ab29014fb83d292a8f4f8953b6 \ + --hash=sha256:367e5c993ba34d5054d11937d0485ad6dfc60ba760fa326c01090fc256adf15c \ + --hash=sha256:379edf079ce44ac8d2805bcf9b3dd7340d4f97aad3a5e0ebabbf9d125b84b442 \ + --hash=sha256:39362cdb4ba5f916e7976fccecaab1ba3a83e35f60fa68b64e9a70e221bb2436 \ + --hash=sha256:4525e7010b1b38334516181c5b81e16180b8e149e6684cee5a727c78186b4e3b \ + --hash=sha256:47781555a7aa5fedcc2d16bcd72e0dc83eb272c10dd657f9fb3f9cc08e2e6abb \ + --hash=sha256:49d11c6f573a5a08f77fad13faff2139f6d0730ebed2cfa9b3d2702671dd7188 \ + --hash=sha256:555493c44a4f5a1b58d611a43333e71a9981c6dbe26270377b6f8174126a0526 \ + --hash=sha256:555658c611099455b2da507582ea20d2043dfdfe7f5ad0add472b1c6238b433f \ + --hash=sha256:697f102c5c1d526bdd761a69f17c6070f9892eebcb94b1a5963d679288c09e78 \ + --hash=sha256:76a70bf840495729be47510856b978f1b0ec7d08f257ca38c9d932720bf6b43e \ + --hash=sha256:7d3243c406773185144527f83be0e0aefc7bf4601b0b2b956665608bf7c98a83 \ + --hash=sha256:931a7630bba591593dcf6e97224a21ff80fb357e7982628d25e3c618e7f598ef \ + --hash=sha256:9804c3ad27f78e54e58b32e7cb532d128b43dbfb9f3f9f06262b821a0f6bd3f5 \ + --hash=sha256:a17c5d0bdcca61ce24a35beb828a2d0d323d3fcf387d7512206888c900193367 \ + --hash=sha256:a6e0641147cbfa7e4e94efdb95c2dab1aff8cfc159ded13e07f308ddccc8c48e \ + --hash=sha256:a79c1eba7ac4209f2d850f0edd0a2f8bba88cbfdfefe6fb76a19e9d4fe5e71a2 \ + --hash=sha256:a9336b5e6712f4adaf5afc3203a99a40b379049104349d747eb3e5a3aa23ac2e \ + --hash=sha256:b20c8b0fd5877abdf402e79a3af987053de07e6fb208c18df6659f708b535134 \ + --hash=sha256:b3a49064504be59e59da664c5e149edc1f26c67c4f8e8456f6ba6aba55033018 \ + --hash=sha256:b503ab55a836136b619b5fc21c8803d810c5b87551af8600b72eecafb0059cb0 \ + --hash=sha256:bd0212976dc57a5bfeede7c219e7cd66568a32c05c9129686dd487c059c1b88a \ + --hash=sha256:c70380fe5d64010f79fb863b9081c7004dd65225d2277333c219d93a10dad4dd \ + --hash=sha256:d99f515f95fd03a90875fdb2cca12ff074aa04490db4d190905851bdf8a549a8 \ + --hash=sha256:e80cf77847d0d3e6e3111b7b25db32a7f8762fd4b9a3a72ce53fe16a2863b281 \ + --hash=sha256:eb96c84efcc33f0b5e0e04beacf00129dd963b67226b01c00b9dfc8affb464c3 \ + --hash=sha256:ebea00201737ad4391142808ed16e875add5c17f676e0912b387739f84991e13 \ + --hash=sha256:efe8d70949c3023698c3fca1e94527e7e790a361ab8116f90d11221421cd8726 \ + --hash=sha256:f13b3e41bce9d257eded794c0f12878af3129d80aacd8a3ee0dee51f3a978651 \ + --hash=sha256:f194db59657c58593a3c47c6dfd7bad4ef4ac12dbc94d01b3a95521f78177e33 \ + --hash=sha256:f49590891d2c2f8a9de15614e32e459a794bcba84693c2394291a2038bbaaa69 \ + --hash=sha256:f75ff57defcd0f1d6e006d721ccdec6c88d4f6a7816eb92f1c4890d979d9ee62 \ + --hash=sha256:f799d9db89fc00446f03281f84a221e50018fc40113a3ba9864b132895619ebe \ + --hash=sha256:f8426d4d75d68714abc17a4292d922f6ba2cfb984b72c2278c437f6dae797865 # via sqlalchemy mypy-extensions==1.1.0 \ --hash=sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505 \ --hash=sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558 # via mypy -numpy==2.4.2 \ - --hash=sha256:00ab83c56211a1d7c07c25e3217ea6695e50a3e2f255053686b081dc0b091a82 \ - --hash=sha256:068cdb2d0d644cdb45670810894f6a0600797a69c05f1ac478e8d31670b8ee75 \ - --hash=sha256:0f01dcf33e73d80bd8dc0f20a71303abbafa26a19e23f6b68d1aa9990af90257 \ - --hash=sha256:0fece1d1f0a89c16b03442eae5c56dc0be0c7883b5d388e0c03f53019a4bfd71 \ - --hash=sha256:12e26134a0331d8dbd9351620f037ec470b7c75929cb8a1537f6bfe411152a1a \ - --hash=sha256:1ae241bbfc6ae276f94a170b14785e561cb5e7f626b6688cf076af4110887413 \ - --hash=sha256:1f92f53998a17265194018d1cc321b2e96e900ca52d54c7c77837b71b9465181 \ - --hash=sha256:209fae046e62d0ce6435fcfe3b1a10537e858249b3d9b05829e2a05218296a85 \ - --hash=sha256:20abd069b9cda45874498b245c8015b18ace6de8546bf50dfa8cea1696ed06ef \ - --hash=sha256:21982668592194c609de53ba4933a7471880ccbaadcc52352694a59ecc860b3a \ - --hash=sha256:25f2059807faea4b077a2b6837391b5d830864b3543627f381821c646f31a63c \ - --hash=sha256:2653de5c24910e49c2b106499803124dde62a5a1fe0eedeaecf4309a5f639390 \ - --hash=sha256:2b8f157c8a6f20eb657e240f8985cc135598b2b46985c5bccbde7616dc9c6b1e \ - --hash=sha256:2fb882da679409066b4603579619341c6d6898fc83a8995199d5249f986e8e8f \ - --hash=sha256:40397bda92382fcec844066efb11f13e1c9a3e2a8e8f318fb72ed8b6db9f60f1 \ - --hash=sha256:444be170853f1f9d528428eceb55f12918e4fda5d8805480f36a002f1415e09b \ - --hash=sha256:47c5a6ed21d9452b10227e5e8a0e1c22979811cad7dcc19d8e3e2fb8fa03f1a3 \ - --hash=sha256:4f069069931240b3fc703f1e23df63443dbd6390614c8c44a87d96cd0ec81eb1 \ - --hash=sha256:52b913ec40ff7ae845687b0b34d8d93b60cb66dcee06996dd5c99f2fc9328657 \ - --hash=sha256:5633c0da313330fd20c484c78cdd3f9b175b55e1a766c4a174230c6b70ad8262 \ - --hash=sha256:5daf6f3914a733336dab21a05cdec343144600e964d2fcdabaac0c0269874b2a \ - --hash=sha256:5eea80d908b2c1f91486eb95b3fb6fab187e569ec9752ab7d9333d2e66bf2d6b \ - --hash=sha256:602f65afdef699cda27ec0b9224ae5dc43e328f4c24c689deaf77133dbee74d0 \ - --hash=sha256:659a6107e31a83c4e33f763942275fd278b21d095094044eb35569e86a21ddae \ - --hash=sha256:66cb9422236317f9d44b67b4d18f44efe6e9c7f8794ac0462978513359461554 \ - --hash=sha256:6d82351358ffbcdcd7b686b90742a9b86632d6c1c051016484fa0b326a0a1548 \ - --hash=sha256:6e9f61981ace1360e42737e2bae58b27bf28a1b27e781721047d84bd754d32e7 \ - --hash=sha256:6ed0be1ee58eef41231a5c943d7d1375f093142702d5723ca2eb07db9b934b05 \ - --hash=sha256:7cdde6de52fb6664b00b056341265441192d1291c130e99183ec0d4b110ff8b1 \ - --hash=sha256:7df2de1e4fba69a51c06c28f5a3de36731eb9639feb8e1cf7e4a7b0daf4cf622 \ - --hash=sha256:7edc794af8b36ca37ef5fcb5e0d128c7e0595c7b96a2318d1badb6fcd8ee86b1 \ - --hash=sha256:7f54844851cdb630ceb623dcec4db3240d1ac13d4990532446761baede94996a \ - --hash=sha256:805cc8de9fd6e7a22da5aed858e0ab16be5a4db6c873dde1d7451c541553aa27 \ - --hash=sha256:8906e71fd8afcb76580404e2a950caef2685df3d2a57fe82a86ac8d33cc007ba \ - --hash=sha256:89f7268c009bc492f506abd6f5265defa7cb3f7487dc21d357c3d290add45082 \ - --hash=sha256:8c50dd1fc8826f5b26a5ee4d77ca55d88a895f4e4819c7ecc2a9f5905047a443 \ - --hash=sha256:8e4549f8a3c6d13d55041925e912bfd834285ef1dd64d6bc7d542583355e2e98 \ - --hash=sha256:8e9afaeb0beff068b4d9cd20d322ba0ee1cecfb0b08db145e4ab4dd44a6b5110 \ - --hash=sha256:98f16a80e917003a12c0580f97b5f875853ebc33e2eaa4bccfc8201ac6869308 \ - --hash=sha256:9e35d3e0144137d9fdae62912e869136164534d64a169f86438bc9561b6ad49f \ - --hash=sha256:9e4424677ce4b47fe73c8b5556d876571f7c6945d264201180db2dc34f676ab5 \ - --hash=sha256:adb6ed2ad29b9e15321d167d152ee909ec73395901b70936f029c3bc6d7f4460 \ - --hash=sha256:aea4f66ff44dfddf8c2cffd66ba6538c5ec67d389285292fe428cb2c738c8aef \ - --hash=sha256:b21041e8cb6a1eb5312dd1d2f80a94d91efffb7a06b70597d44f1bd2dfc315ab \ - --hash=sha256:b2f0073ed0868db1dcd86e052d37279eef185b9c8db5bf61f30f46adac63c909 \ - --hash=sha256:b3a24467af63c67829bfaa61eecf18d5432d4f11992688537be59ecd6ad32f5e \ - --hash=sha256:b9c618d56a29c9cb1c4da979e9899be7578d2e0b3c24d52079c166324c9e8695 \ - --hash=sha256:bba37bc29d4d85761deed3954a1bc62be7cf462b9510b51d367b769a8c8df325 \ - --hash=sha256:bd3a7a9f5847d2fb8c2c6d1c862fa109c31a9abeca1a3c2bd5a64572955b2979 \ - --hash=sha256:be71bf1edb48ebbbf7f6337b5bfd2f895d1902f6335a5830b20141fc126ffba0 \ - --hash=sha256:c02ef4401a506fb60b411467ad501e1429a3487abca4664871d9ae0b46c8ba32 \ - --hash=sha256:c3cd545784805de05aafe1dde61752ea49a359ccba9760c1e5d1c88a93bbf2b7 \ - --hash=sha256:c7ac672d699bf36275c035e16b65539931347d68b70667d28984c9fb34e07fa7 \ - --hash=sha256:cb7bbb88aa74908950d979eeaa24dbdf1a865e3c7e45ff0121d8f70387b55f73 \ - --hash=sha256:cd2bd2bbed13e213d6b55dc1d035a4f91748a7d3edc9480c13898b0353708920 \ - --hash=sha256:cda077c2e5b780200b6b3e09d0b42205a3d1c68f30c6dceb90401c13bff8fe74 \ - --hash=sha256:cf28c0c1d4c4bf00f509fa7eb02c58d7caf221b50b467bcb0d9bbf1584d5c821 \ - --hash=sha256:d0d9b7c93578baafcbc5f0b83eaf17b79d345c6f36917ba0c67f45226911d499 \ - --hash=sha256:d1240d50adff70c2a88217698ca844723068533f3f5c5fa6ee2e3220e3bdb000 \ - --hash=sha256:d30291931c915b2ab5717c2974bb95ee891a1cf22ebc16a8006bd59cd210d40a \ - --hash=sha256:d9f64d786b3b1dd742c946c42d15b07497ed14af1a1f3ce840cce27daa0ce913 \ - --hash=sha256:da6cad4e82cb893db4b69105c604d805e0c3ce11501a55b5e9f9083b47d2ffe8 \ - --hash=sha256:df1b10187212b198dd45fa943d8985a3c8cf854aed4923796e0e019e113a1bda \ - --hash=sha256:e04ae107ac591763a47398bb45b568fc38f02dbc4aa44c063f67a131f99346cb \ - --hash=sha256:e6dee3bb76aa4009d5a912180bf5b2de012532998d094acee25d9cb8dee3e44a \ - --hash=sha256:e7e88598032542bd49af7c4747541422884219056c268823ef6e5e89851c8825 \ - --hash=sha256:e98c97502435b53741540a5717a6749ac2ada901056c7db951d33e11c885cc7d \ - --hash=sha256:ec055f6dae239a6299cace477b479cca2fc125c5675482daf1dd886933a1076f \ - --hash=sha256:f74f0f7779cc7ae07d1810aab8ac6b1464c3eafb9e283a40da7309d5e6e48fbb \ - --hash=sha256:fbde1b0c6e81d56f5dccd95dd4a711d9b95df1ae4009a60887e56b27e8d903fa \ - --hash=sha256:fcf92bee92742edd401ba41135185866f7026c502617f422eb432cfeca4fe236 \ - --hash=sha256:fd49860271d52127d61197bb50b64f58454e9f578cb4b2c001a6de8b1f50b0b1 +numpy==2.4.4 \ + --hash=sha256:07077278157d02f65c43b1b26a3886bce886f95d20aabd11f87932750dfb14ed \ + --hash=sha256:08f2e31ed5e6f04b118e49821397f12767934cfdd12a1ce86a058f91e004ee50 \ + --hash=sha256:0aec54fd785890ecca25a6003fd9a5aed47ad607bbac5cd64f836ad8666f4959 \ + --hash=sha256:0d35aea54ad1d420c812bfa0385c71cd7cc5bcf7c65fed95fc2cd02fe8c79827 \ + --hash=sha256:0d4e437e295f18ec29bc79daf55e8a47a9113df44d66f702f02a293d93a2d6dd \ + --hash=sha256:0dfd3f9d3adbe2920b68b5cd3d51444e13a10792ec7154cd0a2f6e74d4ab3233 \ + --hash=sha256:1378871da56ca8943c2ba674530924bb8ca40cd228358a3b5f302ad60cf875fc \ + --hash=sha256:15716cfef24d3a9762e3acdf87e27f58dc823d1348f765bbea6bef8c639bfa1b \ + --hash=sha256:19710a9ca9992d7174e9c52f643d4272dcd1558c5f7af7f6f8190f633bd651a7 \ + --hash=sha256:23cbfd4c17357c81021f21540da84ee282b9c8fba38a03b7b9d09ba6b951421e \ + --hash=sha256:2483e4584a1cb3092da4470b38866634bafb223cbcd551ee047633fd2584599a \ + --hash=sha256:27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d \ + --hash=sha256:28a650663f7314afc3e6ec620f44f333c386aad9f6fc472030865dc0ebb26ee3 \ + --hash=sha256:2aa0613a5177c264ff5921051a5719d20095ea586ca88cc802c5c218d1c67d3e \ + --hash=sha256:2c194dd721e54ecad9ad387c1d35e63dce5c4450c6dc7dd5611283dda239aabb \ + --hash=sha256:2d19e6e2095506d1736b7d80595e0f252d76b89f5e715c35e06e937679ea7d7a \ + --hash=sha256:2d390634c5182175533585cc89f3608a4682ccb173cc9bb940b2881c8d6f8fa0 \ + --hash=sha256:30caa73029a225b2d40d9fae193e008e24b2026b7ee1a867b7ee8d96ca1a448e \ + --hash=sha256:42c16925aa5a02362f986765f9ebabf20de75cdefdca827d14315c568dcab113 \ + --hash=sha256:45dbed2ab436a9e826e302fcdcbe9133f9b0006e5af7168afb8963a6520da103 \ + --hash=sha256:4636de7fd195197b7535f231b5de9e4b36d2c440b6e566d2e4e4746e6af0ca93 \ + --hash=sha256:4a19d9dba1a76618dd86b164d608566f393f8ec6ac7c44f0cc879011c45e65af \ + --hash=sha256:4bbc7f303d125971f60ec0aaad5e12c62d0d2c925f0ab1273debd0e4ba37aba5 \ + --hash=sha256:4d6d57903571f86180eb98f8f0c839fa9ebbfb031356d87f1361be91e433f5b7 \ + --hash=sha256:4e874c976154687c1f71715b034739b45c7711bec81db01914770373d125e392 \ + --hash=sha256:51fc224f7ca4d92656d5a5eb315f12eb5fe2c97a66249aa7b5f562528a3be38c \ + --hash=sha256:58c8b5929fcb8287cbd6f0a3fae19c6e03a5c48402ae792962ac465224a629a4 \ + --hash=sha256:5a285b3b96f951841799528cd1f4f01cd70e7e0204b4abebac9463eecfcf2a40 \ + --hash=sha256:5c70f1cc1c4efbe316a572e2d8b9b9cc44e89b95f79ca3331553fbb63716e2bf \ + --hash=sha256:62d6b0f03b694173f9fcb1fb317f7222fd0b0b103e784c6549f5e53a27718c44 \ + --hash=sha256:6a246d5914aa1c820c9443ddcee9c02bec3e203b0c080349533fae17727dfd1b \ + --hash=sha256:6aa3236c78803afbcb255045fbef97a9e25a1f6c9888357d205ddc42f4d6eba5 \ + --hash=sha256:6bbe4eb67390b0a0265a2c25458f6b90a409d5d069f1041e6aff1e27e3d9a79e \ + --hash=sha256:715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74 \ + --hash=sha256:72944b19f2324114e9dc86a159787333b77874143efcf89a5167ef83cfee8af0 \ + --hash=sha256:81f4a14bee47aec54f883e0cad2d73986640c1590eb9bfaaba7ad17394481e6e \ + --hash=sha256:846300f379b5b12cc769334464656bc882e0735d27d9726568bc932fdc49d5ec \ + --hash=sha256:86b6f55f5a352b48d7fbfd2dbc3d5b780b2d79f4d3c121f33eb6efb22e9a2015 \ + --hash=sha256:874f200b2a981c647340f841730fc3a2b54c9d940566a3c4149099591e2c4c3d \ + --hash=sha256:8a87ec22c87be071b6bdbd27920b129b94f2fc964358ce38f3822635a3e2e03d \ + --hash=sha256:8b3b60bb7cba2c8c81837661c488637eee696f59a877788a396d33150c35d842 \ + --hash=sha256:8e3ed142f2728df44263aaf5fb1f5b0b99f4070c553a0d7f033be65338329150 \ + --hash=sha256:93e15038125dc1e5345d9b5b68aa7f996ec33b98118d18c6ca0d0b7d6198b7e8 \ + --hash=sha256:989824e9faf85f96ec9c7761cd8d29c531ad857bfa1daa930cba85baaecf1a9a \ + --hash=sha256:99d838547ace2c4aace6c4f76e879ddfe02bb58a80c1549928477862b7a6d6ed \ + --hash=sha256:9b2aec6af35c113b05695ebb5749a787acd63cafc83086a05771d1e1cd1e555f \ + --hash=sha256:9c585a1790d5436a5374bac930dad6ed244c046ed91b2b2a3634eb2971d21008 \ + --hash=sha256:a7164afb23be6e37ad90b2f10426149fd75aee07ca55653d2aa41e66c4ef697e \ + --hash=sha256:ac6b31e35612a26483e20750126d30d0941f949426974cace8e6b5c58a3657b0 \ + --hash=sha256:ad2e2ef14e0b04e544ea2fa0a36463f847f113d314aa02e5b402fdf910ef309e \ + --hash=sha256:b268594bccac7d7cf5844c7732e3f20c50921d94e36d7ec9b79e9857694b1b2f \ + --hash=sha256:b5f0362dc928a6ecd9db58868fca5e48485205e3855957bdedea308f8672ea4a \ + --hash=sha256:ba1f4fc670ed79f876f70082eff4f9583c15fb9a4b89d6188412de4d18ae2f40 \ + --hash=sha256:ba203255017337d39f89bdd58417f03c4426f12beed0440cfd933cb15f8669c7 \ + --hash=sha256:c901b15172510173f5cb310eae652908340f8dede90fff9e3bf6c0d8dfd92f83 \ + --hash=sha256:c9b39d38a9bd2ae1becd7eac1303d031c5c110ad31f2b319c6e7d98b135c934d \ + --hash=sha256:d2a8490669bfe99a233298348acc2d824d496dee0e66e31b66a6022c2ad74a5c \ + --hash=sha256:dddbbd259598d7240b18c9d87c56a9d2fb3b02fe266f49a7c101532e78c1d871 \ + --hash=sha256:df3775294accfdd75f32c74ae39fcba920c9a378a2fc18a12b6820aa8c1fb502 \ + --hash=sha256:e44319a2953c738205bf3354537979eaa3998ed673395b964c1176083dd46252 \ + --hash=sha256:e4a010c27ff6f210ff4c6ef34394cd61470d01014439b192ec22552ee867f2a8 \ + --hash=sha256:e823b8b6edc81e747526f70f71a9c0a07ac4e7ad13020aa736bb7c9d67196115 \ + --hash=sha256:e892aff75639bbef0d2a2cfd55535510df26ff92f63c92cd84ef8d4ba5a5557f \ + --hash=sha256:eea7ac5d2dce4189771cedb559c738a71512768210dc4e4753b107a2048b3d0e \ + --hash=sha256:ef4059d6e5152fa1a39f888e344c73fdc926e1b2dd58c771d67b0acfbf2aa67d \ + --hash=sha256:f169b9a863d34f5d11b8698ead99febeaa17a13ca044961aa8e2662a6c7766a0 \ + --hash=sha256:f2cf083b324a467e1ab358c105f6cad5ea950f50524668a80c486ff1db24e119 \ + --hash=sha256:f8474c4241bc18b750be2abea9d7a9ec84f46ef861dbacf86a4f6e043401f79e \ + --hash=sha256:f983334aea213c99992053ede6168500e5f086ce74fbc4acc3f2b00f5762e9db \ + --hash=sha256:f9e75681b59ddaa5e659898085ae0eaea229d054f2ac0c7e563a62205a700121 \ + --hash=sha256:fbc356aae7adf9e6336d336b9c8111d390a05df88f1805573ebb0807bd06fd1d \ + --hash=sha256:fcfe2045fd2e8f3cb0ce9d4ba6dba6333b8fa05bb8a4939c908cd43322d14c7e # via # feast (pyproject.toml) # dask @@ -1785,9 +1787,9 @@ pandas==2.3.3 \ # pandas-gbq # pymilvus # snowflake-connector-python -pandas-gbq==0.33.0 \ - --hash=sha256:499ad18a7b1917e2cc04bbd763ec37c11ecc49030348c45cebb9cbbdb7f909af \ - --hash=sha256:61357e11d73e0ae57cbff31e71fc3ed83da3d16b58b653f715b32ad760527e34 +pandas-gbq==0.34.1 \ + --hash=sha256:6bea5b85937251b976cf9db38151ea59abbff98771179183488d4614694bff67 \ + --hash=sha256:b74932c6ee35dfc81582f39c792e3a68c9ef9bee8c85f25667d9d05dfadd0daf # via google-cloud-bigquery parsy==2.2 \ --hash=sha256:5e981613d9d2d8b68012d1dd0afe928967bea2e4eefdb76c2f545af0dd02a9e7 \ @@ -1801,9 +1803,9 @@ pathspec==1.0.4 \ --hash=sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645 \ --hash=sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723 # via mypy -platformdirs==4.9.2 \ - --hash=sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd \ - --hash=sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291 +platformdirs==4.9.4 \ + --hash=sha256:1ec356301b7dc906d83f371c8f487070e99d3ccf9e501686456394622a01a934 \ + --hash=sha256:68a9a4619a666ea6439f2ff250c12a853cd1cbd5158d258bd824a7df6be2f868 # via snowflake-connector-python prometheus-client==0.24.1 \ --hash=sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055 \ @@ -1935,25 +1937,25 @@ propcache==0.4.1 \ # via # aiohttp # yarl -proto-plus==1.27.1 \ - --hash=sha256:912a7460446625b792f6448bade9e55cd4e41e6ac10e27009ef71a7f317fa147 \ - --hash=sha256:e4643061f3a4d0de092d62aa4ad09fa4756b2cbb89d4627f3985018216f9fefc +proto-plus==1.27.2 \ + --hash=sha256:6432f75893d3b9e70b9c412f1d2f03f65b11fb164b793d14ae2ca01821d22718 \ + --hash=sha256:b2adde53adadf75737c44d3dcb0104fde65250dfc83ad59168b4aa3e574b6a24 # via # google-api-core # google-cloud-bigquery-storage # google-cloud-bigtable # google-cloud-datastore -protobuf==6.33.5 \ - --hash=sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c \ - --hash=sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02 \ - --hash=sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c \ - --hash=sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd \ - --hash=sha256:8f04fa32763dcdb4973d537d6b54e615cc61108c7cb38fe59310c3192d29510a \ - --hash=sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190 \ - --hash=sha256:a3157e62729aafb8df6da2c03aa5c0937c7266c626ce11a278b6eb7963c4e37c \ - --hash=sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5 \ - --hash=sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0 \ - --hash=sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b +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) # google-api-core @@ -2066,12 +2068,10 @@ pyarrow-hotfix==0.7 \ --hash=sha256:3236f3b5f1260f0e2ac070a55c1a7b339c4bb7267839bd2015e283234e758100 \ --hash=sha256:59399cd58bdd978b2e42816a4183a55c6472d4e33d183351b6069f11ed42661d # via ibis-framework -pyasn1==0.6.2 \ - --hash=sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf \ - --hash=sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b - # via - # pyasn1-modules - # rsa +pyasn1==0.6.3 \ + --hash=sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf \ + --hash=sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde + # via pyasn1-modules pyasn1-modules==0.4.2 \ --hash=sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a \ --hash=sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6 @@ -2212,9 +2212,9 @@ pydantic-core==2.41.5 \ --hash=sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425 \ --hash=sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52 # via pydantic -pydantic-settings==2.13.0 \ - --hash=sha256:95d875514610e8595672800a5c40b073e99e4aae467fa7c8f9c263061ea2e1fe \ - --hash=sha256:d67b576fff39cd086b595441bf9c75d4193ca9c0ed643b90360694d0f1240246 +pydantic-settings==2.13.1 \ + --hash=sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025 \ + --hash=sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237 # via # fastapi-mcp # mcp @@ -2222,15 +2222,15 @@ pydata-google-auth==1.9.1 \ --hash=sha256:0a51ce41c601ca0bc69b8795bf58bedff74b4a6a007c9106c7cbcdec00eaced2 \ --hash=sha256:75ffce5d106e34b717b31844c1639ea505b7d9550dc23b96fb6c20d086b53fa3 # via pandas-gbq -pygments==2.19.2 \ - --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \ - --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b +pygments==2.20.0 \ + --hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \ + --hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176 # via # feast (pyproject.toml) # rich -pyjwt[crypto]==2.11.0 \ - --hash=sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623 \ - --hash=sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469 +pyjwt[crypto]==2.12.1 \ + --hash=sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c \ + --hash=sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b # via # feast (pyproject.toml) # mcp @@ -2243,9 +2243,9 @@ pymysql==1.1.2 \ --hash=sha256:4961d3e165614ae65014e361811a724e2044ad3ea3739de9903ae7c21f539f03 \ --hash=sha256:e6b1d89711dd51f8f74b1631fe08f039e7d76cf67a42a323d3178f0f25762ed9 # via feast (pyproject.toml) -pyopenssl==25.3.0 \ - --hash=sha256:1fda6fc034d5e3d179d39e59c1895c9faeaf40a79de5fc4cbbfbe0d36f4a77b6 \ - --hash=sha256:c981cb0a3fd84e8602d7afc209522773b94c1c2446a3c710a75b06fe1beae329 +pyopenssl==26.0.0 \ + --hash=sha256:df94d28498848b98cc1c0ffb8ef1e71e40210d3b0a8064c9d29571ed2904bf81 \ + --hash=sha256:f293934e52936f2e3413b89c6ce36df66a0b34ae1ea3a053b8c5020ff2f513fc # via snowflake-connector-python python-dateutil==2.9.0.post0 \ --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ @@ -2257,9 +2257,9 @@ python-dateutil==2.9.0.post0 \ # ibis-framework # kubernetes # pandas -python-dotenv==1.2.1 \ - --hash=sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6 \ - --hash=sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61 +python-dotenv==1.2.2 \ + --hash=sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a \ + --hash=sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3 # via # pydantic-settings # pymilvus @@ -2268,9 +2268,9 @@ python-multipart==0.0.22 \ --hash=sha256:2b2cd894c83d21bf49d702499531c7bafd057d730c201782048f7945d82de155 \ --hash=sha256:7340bef99a7e0032613f56dc36027b959fd3b30a787ed62d310e951f7c3a3a58 # via mcp -pytz==2025.2 \ - --hash=sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3 \ - --hash=sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00 +pytz==2026.1.post1 \ + --hash=sha256:3378dde6a0c3d26719182142c56e60c7f9af7e968076f31aae569d72a0358ee1 \ + --hash=sha256:f2fd16142fda348286a75e1a524be810bb05d444e5a081f37f7affc635035f7a # via # pandas # snowflake-connector-python @@ -2363,9 +2363,9 @@ referencing==0.37.0 \ # via # jsonschema # jsonschema-specifications -requests==2.32.5 \ - --hash=sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6 \ - --hash=sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf +requests==2.33.1 \ + --hash=sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517 \ + --hash=sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a # via # feast (pyproject.toml) # fastapi-mcp @@ -2381,9 +2381,9 @@ requests-oauthlib==2.0.0 \ # via # google-auth-oauthlib # kubernetes -rich==14.3.2 \ - --hash=sha256:08e67c3e90884651da3239ea668222d19bea7b589149d8014a21c633420dbb69 \ - --hash=sha256:e712f11c1a562a11843306f5ed999475f09ac31ffb64281f73ab29ffdda8b3b8 +rich==14.3.3 \ + --hash=sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d \ + --hash=sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b # via # fastapi-mcp # ibis-framework @@ -2507,10 +2507,6 @@ rpds-py==0.30.0 \ # via # jsonschema # referencing -rsa==4.9.1 \ - --hash=sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762 \ - --hash=sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75 - # via google-auth s3transfer==0.13.1 \ --hash=sha256:a981aa7429be23fe6dfc13e80e4020057cbab622b08c0315288758d67cabc724 \ --hash=sha256:c3fdba22ba1bd367922f27ec8032d6a1cf5f10c934fb5d68cf60fd5a23d936cf @@ -2533,117 +2529,120 @@ six==1.17.0 \ # via # kubernetes # python-dateutil -snowflake-connector-python[pandas]==4.3.0 \ - --hash=sha256:08f5167a10d380fe66330d5b19d19bd8b4f4af27e9648e3b254e61da025646bf \ - --hash=sha256:120463ca391d9deda3bdb185104ba847e12f73c86ef411cfcf827ce49b64d1af \ - --hash=sha256:26a65c5c93d14c4d221b780fdb2f07b4dd83e848f39eabd4832778bf0e2694d4 \ - --hash=sha256:2e0f66acee330388815fb842f91a46c9cacdefdf02c816354e6adeca8c2c3f86 \ - --hash=sha256:3e2ce47485862fa14ffbf2732f0fd02aa69a7c68a50d5f6286f34ed17527cf87 \ - --hash=sha256:486d17332b9228d2e5975755b434e6a282756a447e0c6605d4e797944fa919da \ - --hash=sha256:55163c5d9b93e10d7217aabd56f776b16c0fe13774f8d5db9188824731da9586 \ - --hash=sha256:676b56eedcc268b7e25a447e736eb8bf8bcacfbc71196c94d6f45746672ee6d5 \ - --hash=sha256:726435b2769135b6282601efb2cd8fd53f7deb1ff2fb7da93d28141fa3c8b17e \ - --hash=sha256:762ffa9673465ccc630aba438d648e0b1a2452ba49669a54a60d1625f36898f3 \ - --hash=sha256:7763c0d5f8e6326ec31f8972cc806fb6d3e07b06ca59f67dfcdf02a34219bcbc \ - --hash=sha256:79cbf5e359cfc33b4c4307df1fe8f78cd5aee56f5c50b98a647fa0cd9ba82cfc \ - --hash=sha256:79f150297b39cfd2481b732554fc4d68b43c83c82eb01e670cc4051cffc089d6 \ - --hash=sha256:7c18b5021ffa6de8313f2c7f0ae6050c36bcee7cb33bb23d40a7fdf3e0a751f2 \ - --hash=sha256:9faa9280e41258fb479ec5395b6a17d3dbb316146832e436aed582b300de655e \ - --hash=sha256:ac18b37e03a29014a9c91aac10c7dbdfa11134c620c6f93dd16f4b99b6a38c2a \ - --hash=sha256:b5a8d91c3e0127360bc3de605df9d02ea4d87e4524a50bf2e7c5c4200f9abf78 \ - --hash=sha256:c1356a2c615e120f913e5235fe87ff8aadbb479ad5a5ac5c0a84881d5fbe981d \ - --hash=sha256:c6fa80373b82125552e691f47b603766ed783f3d90a5782564854aa224aee9d1 \ - --hash=sha256:ca9d22c61f4e3d171b0adad3e9211747917c3a978dfb99564307c1ceadb0f0cd \ - --hash=sha256:ce55b93120f8b429010bf39cc02e739610b6da2ccdd34fcfc0df04849d0fd9d4 \ - --hash=sha256:e3044e6a237b35f750394f199f5e3800dfeb3227c4c8562584877e814d2dc89a \ - --hash=sha256:e42dd9af46fa3ad0e61c1aa6a227357cace481916797ecb92dbb14adb61931e1 \ - --hash=sha256:e5d360d65d42dd97cf82e688a1a7f235b9bc048b4949c9c5c7052ff2783c444e \ - --hash=sha256:e96aaf23f2b021e0d2aac8ac1b541975cd1f6896d9115eefe0938114e694a562 \ - --hash=sha256:f5291c00f610b266ab8c79b1e008b3d0cb29bb5b86a0007529320921b4a3fc3c +snowflake-connector-python[pandas]==4.4.0 \ + --hash=sha256:16fdca775f7ca5ce4a973c07c434f5ab72bef5284e81a5e4ae2fb4d54d28965c \ + --hash=sha256:19d0c1ed033abae715a71b74c53010b180a5247c6924f851e4f7d0b0d58066c4 \ + --hash=sha256:2a6f6a514a10c3bb2d4554132f0b639f43d7e9fbb73fa1fae1c8a75333102686 \ + --hash=sha256:307f41326c702f6976746d2001dacf35adaf567f3f12afb3a5778fbb063c7241 \ + --hash=sha256:43e1a2f3ac51d24406d4eb0c23a8ceb9d6f5cb4854c941e5e1375d8c481e2844 \ + --hash=sha256:52efe2d6543a09807283748dd50a36ec01d52b4f342868132f8f9856b9c95a42 \ + --hash=sha256:56ff04dd9e17edc82128f412aa3776687dc94088f3d6b9144971e169952623cb \ + --hash=sha256:648f49029d699591af0f253e81c5bf60efc4411c7b0149ef074a59a038210a3b \ + --hash=sha256:693a1bef97509f09b7e6f42ea6f743d27819413c04fb3dc543b060d029871c56 \ + --hash=sha256:70d4051e2d9c87258b02672e17e21f5873e0cb49ff9705f6194ccfa25ac0d5fd \ + --hash=sha256:7c2984663a733d06c979aa6c8c1d7691621ec0d3521ef345d57c869ff2f1c4b2 \ + --hash=sha256:8304b4818d3e9de552dcfbdd0bca61bae1583e1c9794e242e58fe44bce701604 \ + --hash=sha256:85a01338d282423611f357cd5392dca2219bbda9a66b44761b11d6ae8ebf1e50 \ + --hash=sha256:96fdca994c4d9f7780e82fc7b4bd3398d856b43de3bae57d44e242ff435a2431 \ + --hash=sha256:9b1a28f843c1c0b582db7854789525d0c8aac4ea5c56e31113684e38220d0af9 \ + --hash=sha256:9fa43d330389df27024757c4f97dabddafbedc74b8bcc189b6a86e8b4d036014 \ + --hash=sha256:a088f108da4653ad1396ddb63a1c757ad614d0862c38f6f69cc77344bdcfeccb \ + --hash=sha256:b9f0ac0c00075321e1720d3876e936ee0256f54832e7463c5193a8dfa54913d5 \ + --hash=sha256:c828248214a49f77b903e05acf887d3ccb9d958b5a979f2ed3663bba1bd0f2b3 \ + --hash=sha256:d6fd334e4d8df7fcb30e6746e5ade845e82de2942268862aa8bce974ae2b86a2 \ + --hash=sha256:d8ac1659c8e588b9502f8d3d03c1ded2f274de0da9c09e62fe007cba5b46d6a5 \ + --hash=sha256:e8e7ce0e8b33aec8b1fc6741eb51dbeb54e2c3a6d282a0d459c355a85f089b08 \ + --hash=sha256:ea6e4083ebea0a814b46f029d64a2fb0ba6e7732952cd8af4406041708ce0e21 \ + --hash=sha256:f5d0e90e68a899c13fda5ca842ff77b5759b1674adf2c72702d3c2b53ca9d27b \ + --hash=sha256:fb628d5ea1999e23bfbaabce4125eb44d56605ca5634b8b1d6092ab22d555598 # via feast (pyproject.toml) sortedcontainers==2.4.0 \ --hash=sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88 \ --hash=sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0 # via snowflake-connector-python -sqlalchemy[mypy]==2.0.46 \ - --hash=sha256:09168817d6c19954d3b7655da6ba87fcb3a62bb575fb396a81a8b6a9fadfe8b5 \ - --hash=sha256:0cc3117db526cad3e61074100bd2867b533e2c7dc1569e95c14089735d6fb4fe \ - --hash=sha256:181903fe8c1b9082995325f1b2e84ac078b1189e2819380c2303a5f90e114a62 \ - --hash=sha256:1bc3f601f0a818d27bfe139f6766487d9c88502062a2cd3a7ee6c342e81d5047 \ - --hash=sha256:1e6199143d51e3e1168bedd98cc698397404a8f7508831b81b6a29b18b051069 \ - --hash=sha256:2347c3f0efc4de367ba00218e0ae5c4ba2306e47216ef80d6e31761ac97cb0b9 \ - --hash=sha256:261c4b1f101b4a411154f1da2b76497d73abbfc42740029205d4d01fa1052684 \ - --hash=sha256:33e462154edb9493f6c3ad2125931e273bbd0be8ae53f3ecd1c161ea9a1dd366 \ - --hash=sha256:37fee2164cf21417478b6a906adc1a91d69ae9aba8f9533e67ce882f4bb1de53 \ - --hash=sha256:3a9a72b0da8387f15d5810f1facca8f879de9b85af8c645138cba61ea147968c \ - --hash=sha256:3aac08f7546179889c62b53b18ebf1148b10244b3405569c93984b0388d016a7 \ - --hash=sha256:3c32e993bc57be6d177f7d5d31edb93f30726d798ad86ff9066d75d9bf2e0b6b \ - --hash=sha256:412f26bb4ba942d52016edc8d12fb15d91d3cd46b0047ba46e424213ad407bcb \ - --hash=sha256:42a1643dc5427b69aca967dae540a90b0fbf57eaf248f13a90ea5930e0966863 \ - --hash=sha256:4396c948d8217e83e2c202fbdcc0389cf8c93d2c1c5e60fa5c5a955eae0e64be \ - --hash=sha256:4dafb537740eef640c4d6a7c254611dca2df87eaf6d14d6a5fca9d1f4c3fc0fa \ - --hash=sha256:4f52f7291a92381e9b4de9050b0a65ce5d6a763333406861e33906b8aa4906bf \ - --hash=sha256:52fe29b3817bd191cc20bad564237c808967972c97fa683c04b28ec8979ae36f \ - --hash=sha256:56bdd261bfd0895452006d5316cbf35739c53b9bb71a170a331fa0ea560b2ada \ - --hash=sha256:585af6afe518732d9ccd3aea33af2edaae4a7aa881af5d8f6f4fe3a368699597 \ - --hash=sha256:590be24e20e2424a4c3c1b0835e9405fa3d0af5823a1a9fc02e5dff56471515f \ - --hash=sha256:64901e08c33462acc9ec3bad27fc7a5c2b6491665f2aa57564e57a4f5d7c52ad \ - --hash=sha256:6ac245604295b521de49b465bab845e3afe6916bcb2147e5929c8041b4ec0545 \ - --hash=sha256:6f827fd687fa1ba7f51699e1132129eac8db8003695513fcf13fc587e1bd47a5 \ - --hash=sha256:70ed2830b169a9960193f4d4322d22be5c0925357d82cbf485b3369893350908 \ - --hash=sha256:716be5bcabf327b6d5d265dbdc6213a01199be587224eb991ad0d37e83d728fd \ - --hash=sha256:7568fe771f974abadce52669ef3a03150ff03186d8eb82613bc8adc435a03f01 \ - --hash=sha256:77f8071d8fbcbb2dd11b7fd40dedd04e8ebe2eb80497916efedba844298065ef \ - --hash=sha256:82ec52100ec1e6ec671563bbd02d7c7c8d0b9e71a0723c72f22ecf52d1755330 \ - --hash=sha256:895296687ad06dc9b11a024cf68e8d9d3943aa0b4964278d2553b86f1b267735 \ - --hash=sha256:8d3b44b3d0ab2f1319d71d9863d76eeb46766f8cf9e921ac293511804d39813f \ - --hash=sha256:8d679b5f318423eacb61f933a9a0f75535bfca7056daeadbf6bd5bcee6183aee \ - --hash=sha256:8e84b09a9b0f19accedcbeff5c2caf36e0dd537341a33aad8d680336152dc34e \ - --hash=sha256:9094c8b3197db12aa6f05c51c05daaad0a92b8c9af5388569847b03b1007fb1b \ - --hash=sha256:90bde6c6b1827565a95fde597da001212ab436f1b2e0c2dcc7246e14db26e2a3 \ - --hash=sha256:9397b381dcee8a2d6b99447ae85ea2530dcac82ca494d1db877087a13e38926d \ - --hash=sha256:93a12da97cca70cea10d4b4fc602589c4511f96c1f8f6c11817620c021d21d00 \ - --hash=sha256:93bb0aae40b52c57fd74ef9c6933c08c040ba98daf23ad33c3f9893494b8d3ce \ - --hash=sha256:94b1e5f3a5f1ff4f42d5daab047428cd45a3380e51e191360a35cef71c9a7a2a \ - --hash=sha256:965c62be8256d10c11f8907e7a8d3e18127a4c527a5919d85fa87fd9ecc2cfdc \ - --hash=sha256:96c7cca1a4babaaf3bfff3e4e606e38578856917e52f0384635a95b226c87764 \ - --hash=sha256:9bcdce05f056622a632f1d44bb47dbdb677f58cad393612280406ce37530eb6d \ - --hash=sha256:9d80ea2ac519c364a7286e8d765d6cd08648f5b21ca855a8017d9871f075542d \ - --hash=sha256:a1e8cc6cc01da346dc92d9509a63033b9b1bda4fed7a7a7807ed385c7dccdc10 \ - --hash=sha256:ab65cb2885a9f80f979b85aa4e9c9165a31381ca322cbde7c638fe6eefd1ec39 \ - --hash=sha256:af865c18752d416798dae13f83f38927c52f085c52e2f32b8ab0fef46fdd02c2 \ - --hash=sha256:b1e14b2f6965a685c7128bd315e27387205429c2e339eeec55cb75ca4ab0ea2e \ - --hash=sha256:b2a9f9aee38039cf4755891a1e50e1effcc42ea6ba053743f452c372c3152b1b \ - --hash=sha256:be6c0466b4c25b44c5d82b0426b5501de3c424d7a3220e86cd32f319ba56798e \ - --hash=sha256:c4e2cc868b7b5208aec6c960950b7bb821f82c2fe66446c92ee0a571765e91a5 \ - --hash=sha256:c805fa6e5d461329fa02f53f88c914d189ea771b6821083937e79550bf31fc19 \ - --hash=sha256:cf36851ee7219c170bb0793dbc3da3e80c582e04a5437bc601bfe8c85c9216d7 \ - --hash=sha256:db23b1bf8cfe1f7fda19018e7207b20cdb5168f83c437ff7e95d19e39289c447 \ - --hash=sha256:e0c05aff5c6b1bb5fb46a87e0f9d2f733f83ef6cbbbcd5c642b6c01678268061 \ - --hash=sha256:e8ac45e8f4eaac0f9f8043ea0e224158855c6a4329fd4ee37c45c61e3beb518e \ - --hash=sha256:ea3cd46b6713a10216323cda3333514944e510aa691c945334713fca6b5279ff \ - --hash=sha256:ebf7e1e78af38047e08836d33502c7a278915698b7c2145d045f780201679999 \ - --hash=sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e \ - --hash=sha256:ff33c6e6ad006bbc0f34f5faf941cfc62c45841c64c0a058ac38c799f15b5ede +sqlalchemy[mypy]==2.0.48 \ + --hash=sha256:01f6bbd4308b23240cf7d3ef117557c8fd097ec9549d5d8a52977544e35b40ad \ + --hash=sha256:07edba08061bc277bfdc772dd2a1a43978f5a45994dd3ede26391b405c15221e \ + --hash=sha256:10853a53a4a00417a00913d270dddda75815fcb80675874285f41051c094d7dd \ + --hash=sha256:1182437cb2d97988cfea04cf6cdc0b0bb9c74f4d56ec3d08b81e23d621a28cc6 \ + --hash=sha256:144921da96c08feb9e2b052c5c5c1d0d151a292c6135623c6b2c041f2a45f9e0 \ + --hash=sha256:1a89ce07ad2d4b8cfc30bd5889ec40613e028ed80ef47da7d9dd2ce969ad30e0 \ + --hash=sha256:1b4c575df7368b3b13e0cebf01d4679f9a28ed2ae6c1cd0b1d5beffb6b2007dc \ + --hash=sha256:1ccd42229aaac2df431562117ac7e667d702e8e44afdb6cf0e50fa3f18160f0b \ + --hash=sha256:2645b7d8a738763b664a12a1542c89c940daa55196e8d73e55b169cc5c99f65f \ + --hash=sha256:288937433bd44e3990e7da2402fabc44a3c6c25d3704da066b85b89a85474ae0 \ + --hash=sha256:34634e196f620c7a61d18d5cf7dc841ca6daa7961aed75d532b7e58b309ac894 \ + --hash=sha256:348174f228b99f33ca1f773e85510e08927620caa59ffe7803b37170df30332b \ + --hash=sha256:36ac4ddc3d33e852da9cb00ffb08cea62ca05c39711dc67062ca2bb1fae35fd8 \ + --hash=sha256:3713e21ea67bca727eecd4a24bf68bcd414c403faae4989442be60994301ded0 \ + --hash=sha256:389b984139278f97757ea9b08993e7b9d1142912e046ab7d82b3fbaeb0209131 \ + --hash=sha256:426c5ca86415d9b8945c7073597e10de9644802e2ff502b8e1f11a7a2642856b \ + --hash=sha256:4599a95f9430ae0de82b52ff0d27304fe898c17cb5f4099f7438a51b9998ac77 \ + --hash=sha256:49b7bddc1eebf011ea5ab722fdbe67a401caa34a350d278cc7733c0e88fecb1f \ + --hash=sha256:53667b5f668991e279d21f94ccfa6e45b4e3f4500e7591ae59a8012d0f010dcb \ + --hash=sha256:546572a1793cc35857a2ffa1fe0e58571af1779bcc1ffa7c9fb0839885ed69a9 \ + --hash=sha256:583849c743e0e3c9bb7446f5b5addeacedc168d657a69b418063dfdb2d90081c \ + --hash=sha256:5aee45fd2c6c0f2b9cdddf48c48535e7471e42d6fb81adfde801da0bd5b93241 \ + --hash=sha256:5b193a7e29fd9fa56e502920dca47dffe60f97c863494946bd698c6058a55658 \ + --hash=sha256:5ca74f37f3369b45e1f6b7b06afb182af1fd5dde009e4ffd831830d98cbe5fe7 \ + --hash=sha256:68549c403f79a8e25984376480959975212a670405e3913830614432b5daa07a \ + --hash=sha256:69f5bc24904d3bc3640961cddd2523e361257ef68585d6e364166dfbe8c78fae \ + --hash=sha256:6bb85c546591569558571aa1b06aba711b26ae62f111e15e56136d69920e1616 \ + --hash=sha256:6f7b7243850edd0b8b97043f04748f31de50cf426e939def5c16bedb540698f7 \ + --hash=sha256:7001dc9d5f6bb4deb756d5928eaefe1930f6f4179da3924cbd95ee0e9f4dce89 \ + --hash=sha256:7a936f1bb23d370b7c8cc079d5fce4c7d18da87a33c6744e51a93b0f9e97e9b3 \ + --hash=sha256:7c998f2ace8bf76b453b75dbcca500d4f4b9dd3908c13e89b86289b37784848b \ + --hash=sha256:7cddca31edf8b0653090cbb54562ca027c421c58ddde2c0685f49ff56a1690e0 \ + --hash=sha256:8183dc57ae7d9edc1346e007e840a9f3d6aa7b7f165203a99e16f447150140d2 \ + --hash=sha256:82745b03b4043e04600a6b665cb98697c4339b24e34d74b0a2ac0a2488b6f94d \ + --hash=sha256:841a94c66577661c1f088ac958cd767d7c9bf507698f45afffe7a4017049de76 \ + --hash=sha256:858e433f12b0e5b3ed2f8da917433b634f4937d0e8793e5cb33c54a1a01df565 \ + --hash=sha256:908a3fa6908716f803b86896a09a2c4dde5f5ce2bb07aacc71ffebb57986ce99 \ + --hash=sha256:9764014ef5e58aab76220c5664abb5d47d5bc858d9debf821e55cfdd0f128485 \ + --hash=sha256:9c7d0a77e36b5f4b01ca398482230ab792061d243d715299b44a0b55c89fe617 \ + --hash=sha256:a5b429eb84339f9f05e06083f119ad814e6d85e27ecbdf9c551dfdbb128eaf8a \ + --hash=sha256:a66fe406437dd65cacd96a72689a3aaaecaebbcd62d81c5ac1c0fdbeac835096 \ + --hash=sha256:a6b764fb312bd35e47797ad2e63f0d323792837a6ac785a4ca967019357d2bc7 \ + --hash=sha256:b19151e76620a412c2ac1c6f977ab1b9fa7ad43140178345136456d5265b32ed \ + --hash=sha256:b8438ec5594980d405251451c5b7ea9aa58dda38eb7ac35fb7e4c696712ee24f \ + --hash=sha256:b8fc3454b4f3bd0a368001d0e968852dad45a873f8b4babd41bc302ec851a099 \ + --hash=sha256:bcb8ebbf2e2c36cfe01a94f2438012c6a9d494cf80f129d9753bcdf33bfc35a6 \ + --hash=sha256:d404dc897ce10e565d647795861762aa2d06ca3f4a728c5e9a835096c7059018 \ + --hash=sha256:d612c976cbc2d17edfcc4c006874b764e85e990c29ce9bd411f926bbfb02b9a2 \ + --hash=sha256:d64177f443594c8697369c10e4bbcac70ef558e0f7921a1de7e4a3d1734bcf67 \ + --hash=sha256:d854b3970067297f3a7fbd7a4683587134aa9b3877ee15aa29eea478dc68f933 \ + --hash=sha256:d8fcccbbc0c13c13702c471da398b8cd72ba740dca5859f148ae8e0e8e0d3e7e \ + --hash=sha256:e004aa9248e8cb0a5f9b96d003ca7c1c0a5da8decd1066e7b53f59eb8ce7c62b \ + --hash=sha256:e214d546c8ecb5fc22d6e6011746082abf13a9cf46eefb45769c7b31407c97b5 \ + --hash=sha256:e2d0d88686e3d35a76f3e15a34e8c12d73fc94c1dea1cd55782e695cc14086dd \ + --hash=sha256:e2f35b4cccd9ed286ad62e0a3c3ac21e06c02abc60e20aa51a3e305a30f5fa79 \ + --hash=sha256:e3070c03701037aa418b55d36532ecb8f8446ed0135acb71c678dbdf12f5b6e4 \ + --hash=sha256:e5e088bf43f6ee6fec7dbf1ef7ff7774a616c236b5c0cb3e00662dd71a56b571 \ + --hash=sha256:e83e3f959aaa1c9df95c22c528096d94848a1bc819f5d0ebf7ee3df0ca63db6c \ + --hash=sha256:f0dcbc588cd5b725162c076eb9119342f6579c7f7f55057bb7e3c6ff27e13121 \ + --hash=sha256:f27f9da0a7d22b9f981108fd4b62f8b5743423388915a563e651c20d06c1f457 \ + --hash=sha256:f8649a14caa5f8a243628b1d61cf530ad9ae4578814ba726816adb1121fc493e \ + --hash=sha256:fac0fa4e4f55f118fd87177dacb1c6522fe39c28d498d259014020fec9164c29 \ + --hash=sha256:fd08b90d211c086181caed76931ecfa2bdfc83eea3cfccdb0f82abc6c4b876cb # via feast (pyproject.toml) -sqlglot==28.10.1 \ - --hash=sha256:214aef51fd4ce16407022f81cfc80c173409dab6d0f6ae18c52b43f43b31d4dd \ - --hash=sha256:66e0dae43b4bce23314b80e9aef41b8c88fea0e17ada62de095b45262084a8c5 +sqlglot==30.2.1 \ + --hash=sha256:ef4a67cc6f66a8043085eb8ea95fa9541c1625dffa9145ad4e9815a7ba60a199 \ + --hash=sha256:f23d9ee9427ef9d20df15f9b0ffa57d9eb45e52b012219a349d1e6b50ed926d1 # via ibis-framework -sse-starlette==3.2.0 \ - --hash=sha256:5876954bd51920fc2cd51baee47a080eb88a37b5b784e615abb0b283f801cdbf \ - --hash=sha256:8127594edfb51abe44eac9c49e59b0b01f1039d0c7461c6fd91d4e03b70da422 +sse-starlette==3.3.4 \ + --hash=sha256:84bb06e58939a8b38d8341f1bc9792f06c2b53f48c608dd207582b664fc8f3c1 \ + --hash=sha256:aaf92fc067af8a5427192895ac028e947b484ac01edbc3caf00e7e7137c7bef1 # via mcp -starlette==0.52.1 \ - --hash=sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74 \ - --hash=sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933 +starlette==1.0.0 \ + --hash=sha256:6a4beaf1f81bb472fd19ea9b918b50dc3a77a6f2e190a12954b25e6ed5eea149 \ + --hash=sha256:d3ec55e0bb321692d275455ddfd3df75fff145d009685eb40dc91fc66b03d38b # via # fastapi # mcp # sse-starlette -tabulate==0.9.0 \ - --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ - --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f +tabulate==0.10.0 \ + --hash=sha256:e2cfde8f79420f6deeffdeda9aaec3b6bc5abce947655d17ac662b126e48a60d \ + --hash=sha256:f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3 # via feast (pyproject.toml) tenacity==8.5.0 \ --hash=sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78 \ @@ -2653,54 +2652,54 @@ toml==0.10.2 \ --hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \ --hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f # via feast (pyproject.toml) -tomli==2.4.0 \ - --hash=sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729 \ - --hash=sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b \ - --hash=sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d \ - --hash=sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df \ - --hash=sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576 \ - --hash=sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d \ - --hash=sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1 \ - --hash=sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a \ - --hash=sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e \ - --hash=sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc \ - --hash=sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702 \ - --hash=sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6 \ - --hash=sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd \ - --hash=sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4 \ - --hash=sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776 \ - --hash=sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a \ - --hash=sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66 \ - --hash=sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87 \ - --hash=sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2 \ - --hash=sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f \ - --hash=sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475 \ - --hash=sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f \ - --hash=sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95 \ - --hash=sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9 \ - --hash=sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3 \ - --hash=sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9 \ - --hash=sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76 \ - --hash=sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da \ - --hash=sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8 \ - --hash=sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51 \ - --hash=sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86 \ - --hash=sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8 \ - --hash=sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0 \ - --hash=sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b \ - --hash=sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1 \ - --hash=sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e \ - --hash=sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d \ - --hash=sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c \ - --hash=sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867 \ - --hash=sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a \ - --hash=sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c \ - --hash=sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0 \ - --hash=sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4 \ - --hash=sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614 \ - --hash=sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132 \ - --hash=sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa \ - --hash=sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087 +tomli==2.4.1 \ + --hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \ + --hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \ + --hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \ + --hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \ + --hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \ + --hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \ + --hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \ + --hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \ + --hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \ + --hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \ + --hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \ + --hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \ + --hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \ + --hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \ + --hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \ + --hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \ + --hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \ + --hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \ + --hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \ + --hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \ + --hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \ + --hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \ + --hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \ + --hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \ + --hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \ + --hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \ + --hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \ + --hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \ + --hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \ + --hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \ + --hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \ + --hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \ + --hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \ + --hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \ + --hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \ + --hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \ + --hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \ + --hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \ + --hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \ + --hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \ + --hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \ + --hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \ + --hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \ + --hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \ + --hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \ + --hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \ + --hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049 # via fastapi-mcp tomlkit==0.14.0 \ --hash=sha256:592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680 \ @@ -2719,13 +2718,13 @@ tqdm==4.67.3 \ # via # feast (pyproject.toml) # milvus-lite -typeguard==4.5.0 \ - --hash=sha256:749bea21cdb2553e12831bc29f1eae980b22c7de8331ab67ae7db9e85470b5a7 \ - --hash=sha256:cfda388fc88a9ce42a41890900d6f31ee124bea9b73bb84701a32438e92165c3 +typeguard==4.5.1 \ + --hash=sha256:44d2bf329d49a244110a090b55f5f91aa82d9a9834ebfd30bcc73651e4a8cc40 \ + --hash=sha256:f6f8ecbbc819c9bc749983cc67c02391e16a9b43b8b27f15dc70ed7c4a007274 # via feast (pyproject.toml) -typer==0.23.1 \ - --hash=sha256:2070374e4d31c83e7b61362fd859aa683576432fd5b026b060ad6b4cd3b86134 \ - --hash=sha256:3291ad0d3c701cbf522012faccfbb29352ff16ad262db2139e6b01f15781f14e +typer==0.24.1 \ + --hash=sha256:112c1f0ce578bfb4cab9ffdabc68f031416ebcc216536611ba21f04e9aa84c9e \ + --hash=sha256:e39b4732d65fbdcde189ae76cf7cd48aeae72919dea1fdfc16593be016256b45 # via fastapi-mcp types-pymysql==1.1.0.20251220 \ --hash=sha256:ae1c3df32a777489431e2e9963880a0df48f6591e0aa2fd3a6fabd9dee6eca54 \ @@ -2766,91 +2765,85 @@ tzdata==2025.3 \ # via # ibis-framework # pandas -ujson==5.11.0 \ - --hash=sha256:0180a480a7d099082501cad1fe85252e4d4bf926b40960fb3d9e87a3a6fbbc80 \ - --hash=sha256:04c41afc195fd477a59db3a84d5b83a871bd648ef371cf8c6f43072d89144eef \ - --hash=sha256:0654a2691fc252c3c525e3d034bb27b8a7546c9d3eb33cd29ce6c9feda361a6a \ - --hash=sha256:090b4d11b380ae25453100b722d0609d5051ffe98f80ec52853ccf8249dfd840 \ - --hash=sha256:109f59885041b14ee9569bf0bb3f98579c3fa0652317b355669939e5fc5ede53 \ - --hash=sha256:10f29e71ecf4ecd93a6610bd8efa8e7b6467454a363c3d6416db65de883eb076 \ - --hash=sha256:1194b943e951092db611011cb8dbdb6cf94a3b816ed07906e14d3bc6ce0e90ab \ - --hash=sha256:12b5e7e22a1fe01058000d1b317d3b65cc3daf61bd2ea7a2b76721fe160fa74d \ - --hash=sha256:16ccb973b7ada0455201808ff11d48fe9c3f034a6ab5bd93b944443c88299f89 \ - --hash=sha256:181fb5b15703a8b9370b25345d2a1fd1359f0f18776b3643d24e13ed9c036d4c \ - --hash=sha256:185f93ebccffebc8baf8302c869fac70dd5dd78694f3b875d03a31b03b062cdb \ - --hash=sha256:1a0a9b76a89827a592656fe12e000cf4f12da9692f51a841a4a07aa4c7ecc41c \ - --hash=sha256:1a325fd2c3a056cf6c8e023f74a0c478dd282a93141356ae7f16d5309f5ff823 \ - --hash=sha256:1aa8a2ab482f09f6c10fba37112af5f957689a79ea598399c85009f2f29898b5 \ - --hash=sha256:1d663b96eb34c93392e9caae19c099ec4133ba21654b081956613327f0e973ac \ - --hash=sha256:29113c003ca33ab71b1b480bde952fbab2a0b6b03a4ee4c3d71687cdcbd1a29d \ - --hash=sha256:30f607c70091483550fbd669a0b37471e5165b317d6c16e75dba2aa967608723 \ - --hash=sha256:3134b783ab314d2298d58cda7e47e7a0f7f71fc6ade6ac86d5dbeaf4b9770fa6 \ - --hash=sha256:34032aeca4510a7c7102bd5933f59a37f63891f30a0706fb46487ab6f0edf8f0 \ - --hash=sha256:3772e4fe6b0c1e025ba3c50841a0ca4786825a4894c8411bf8d3afe3a8061328 \ - --hash=sha256:3d2720e9785f84312b8e2cb0c2b87f1a0b1c53aaab3b2af3ab817d54409012e0 \ - --hash=sha256:416389ec19ef5f2013592f791486bef712ebce0cd59299bf9df1ba40bb2f6e04 \ - --hash=sha256:446e8c11c06048611c9d29ef1237065de0af07cabdd97e6b5b527b957692ec25 \ - --hash=sha256:4598bf3965fc1a936bd84034312bcbe00ba87880ef1ee33e33c1e88f2c398b49 \ - --hash=sha256:48055e1061c1bb1f79e75b4ac39e821f3f35a9b82de17fce92c3140149009bec \ - --hash=sha256:4843f3ab4fe1cc596bb7e02228ef4c25d35b4bb0809d6a260852a4bfcab37ba3 \ - --hash=sha256:49e56ef8066f11b80d620985ae36869a3ff7e4b74c3b6129182ec5d1df0255f3 \ - --hash=sha256:4b42c115c7c6012506e8168315150d1e3f76e7ba0f4f95616f4ee599a1372bbc \ - --hash=sha256:4c9f5d6a27d035dd90a146f7761c2272cf7103de5127c9ab9c4cd39ea61e878a \ - --hash=sha256:5600202a731af24a25e2d7b6eb3f648e4ecd4bb67c4d5cf12f8fab31677469c9 \ - --hash=sha256:65724738c73645db88f70ba1f2e6fb678f913281804d5da2fd02c8c5839af302 \ - --hash=sha256:65f3c279f4ed4bf9131b11972040200c66ae040368abdbb21596bf1564899694 \ - --hash=sha256:674f306e3e6089f92b126eb2fe41bcb65e42a15432c143365c729fdb50518547 \ - --hash=sha256:683f57f0dd3acdd7d9aff1de0528d603aafcb0e6d126e3dc7ce8b020a28f5d01 \ - --hash=sha256:6b6ec7e7321d7fc19abdda3ad809baef935f49673951a8bab486aea975007e02 \ - --hash=sha256:6cd2df62f24c506a0ba322d5e4fe4466d47a9467b57e881ee15a31f7ecf68ff6 \ - --hash=sha256:6dd703c3e86dc6f7044c5ac0b3ae079ed96bf297974598116aa5fb7f655c3a60 \ - --hash=sha256:6eff24e1abd79e0ec6d7eae651dd675ddbc41f9e43e29ef81e16b421da896915 \ - --hash=sha256:7855ccea3f8dad5e66d8445d754fc1cf80265a4272b5f8059ebc7ec29b8d0835 \ - --hash=sha256:787aff4a84da301b7f3bac09bc696e2e5670df829c6f8ecf39916b4e7e24e701 \ - --hash=sha256:7895f0d2d53bd6aea11743bd56e3cb82d729980636cd0ed9b89418bf66591702 \ - --hash=sha256:78c684fb21255b9b90320ba7e199780f653e03f6c2528663768965f4126a5b50 \ - --hash=sha256:7e0ec1646db172beb8d3df4c32a9d78015e671d2000af548252769e33079d9a6 \ - --hash=sha256:7e3cff632c1d78023b15f7e3a81c3745cd3f94c044d1e8fa8efbd6b161997bbc \ - --hash=sha256:7f1a27ab91083b4770e160d17f61b407f587548f2c2b5fbf19f94794c495594a \ - --hash=sha256:80017e870d882d5517d28995b62e4e518a894f932f1e242cbc802a2fd64d365c \ - --hash=sha256:8254e858437c00f17cb72e7a644fc42dad0ebb21ea981b71df6e84b1072aaa7c \ - --hash=sha256:837da4d27fed5fdc1b630bd18f519744b23a0b5ada1bbde1a36ba463f2900c03 \ - --hash=sha256:849e65b696f0d242833f1df4182096cedc50d414215d1371fca85c541fbff629 \ - --hash=sha256:85e6796631165f719084a9af00c79195d3ebf108151452fefdcb1c8bb50f0105 \ - --hash=sha256:86baf341d90b566d61a394869ce77188cc8668f76d7bb2c311d77a00f4bdf844 \ - --hash=sha256:8fa2af7c1459204b7a42e98263b069bd535ea0cd978b4d6982f35af5a04a4241 \ - --hash=sha256:94fcae844f1e302f6f8095c5d1c45a2f0bfb928cccf9f1b99e3ace634b980a2a \ - --hash=sha256:952c0be400229940248c0f5356514123d428cba1946af6fa2bbd7503395fef26 \ - --hash=sha256:99c49400572cd77050894e16864a335225191fd72a818ea6423ae1a06467beac \ - --hash=sha256:9aacbeb23fdbc4b256a7d12e0beb9063a1ba5d9e0dbb2cfe16357c98b4334596 \ - --hash=sha256:a0af6574fc1d9d53f4ff371f58c96673e6d988ed2b5bf666a6143c782fa007e9 \ - --hash=sha256:a31c6b8004438e8c20fc55ac1c0e07dad42941db24176fe9acf2815971f8e752 \ - --hash=sha256:a4df61a6df0a4a8eb5b9b1ffd673429811f50b235539dac586bb7e9e91994138 \ - --hash=sha256:a638425d3c6eed0318df663df44480f4a40dc87cc7c6da44d221418312f6413b \ - --hash=sha256:aa6b3d4f1c0d3f82930f4cbd7fe46d905a4a9205a7c13279789c1263faf06dba \ - --hash=sha256:aa6d7a5e09217ff93234e050e3e380da62b084e26b9f2e277d2606406a2fc2e5 \ - --hash=sha256:ab2cb8351d976e788669c8281465d44d4e94413718af497b4e7342d7b2f78018 \ - --hash=sha256:abae0fb58cc820092a0e9e8ba0051ac4583958495bfa5262a12f628249e3b362 \ - --hash=sha256:b16930f6a0753cdc7d637b33b4e8f10d5e351e1fb83872ba6375f1e87be39746 \ - --hash=sha256:b7b136cc6abc7619124fd897ef75f8e63105298b5ca9bdf43ebd0e1fa0ee105f \ - --hash=sha256:be6b0eaf92cae8cdee4d4c9e074bde43ef1c590ed5ba037ea26c9632fb479c88 \ - --hash=sha256:c44c703842024d796b4c78542a6fcd5c3cb948b9fc2a73ee65b9c86a22ee3638 \ - --hash=sha256:c6618f480f7c9ded05e78a1938873fde68baf96cdd74e6d23c7e0a8441175c4b \ - --hash=sha256:ce076f2df2e1aa62b685086fbad67f2b1d3048369664b4cdccc50707325401f9 \ - --hash=sha256:d06e87eded62ff0e5f5178c916337d2262fdbc03b31688142a3433eabb6511db \ - --hash=sha256:d7c46cb0fe5e7056b9acb748a4c35aa1b428025853032540bb7e41f46767321f \ - --hash=sha256:d8951bb7a505ab2a700e26f691bdfacf395bc7e3111e3416d325b513eea03a58 \ - --hash=sha256:da473b23e3a54448b008d33f742bcd6d5fb2a897e42d1fc6e7bf306ea5d18b1b \ - --hash=sha256:de6e88f62796372fba1de973c11138f197d3e0e1d80bcb2b8aae1e826096d433 \ - --hash=sha256:e204ae6f909f099ba6b6b942131cee359ddda2b6e4ea39c12eb8b991fe2010e0 \ - --hash=sha256:e73df8648c9470af2b6a6bf5250d4744ad2cf3d774dcf8c6e31f018bdd04d764 \ - --hash=sha256:e750c436fb90edf85585f5c62a35b35082502383840962c6983403d1bd96a02c \ - --hash=sha256:e979fbc469a7f77f04ec2f4e853ba00c441bf2b06720aa259f0f720561335e34 \ - --hash=sha256:ecd6ff8a3b5a90c292c2396c2d63c687fd0ecdf17de390d852524393cd9ed052 \ - --hash=sha256:f278b31a7c52eb0947b2db55a5133fbc46b6f0ef49972cd1a80843b72e135aba \ - --hash=sha256:f62b9976fabbcde3ab6e413f4ec2ff017749819a0786d84d7510171109f2d53c \ - --hash=sha256:fa79fdb47701942c2132a9dd2297a1a85941d966d8c87bfd9e29b0cf423f26cc \ - --hash=sha256:fac6c0649d6b7c3682a0a6e18d3de6857977378dce8d419f57a0b20e3d775b39 +ujson==5.12.0 \ + --hash=sha256:006428d3813b87477d72d306c40c09f898a41b968e57b15a7d88454ecc42a3fb \ + --hash=sha256:02f93da7a4115e24f886b04fd56df1ee8741c2ce4ea491b7ab3152f744ad8f8e \ + --hash=sha256:0727363b05ab05ee737a28f6200dc4078bce6b0508e10bd8aab507995a15df61 \ + --hash=sha256:085b6ce182cdd6657481c7c4003a417e0655c4f6e58b76f26ee18f0ae21db827 \ + --hash=sha256:09b4beff9cc91d445d5818632907b85fb06943b61cb346919ce202668bf6794a \ + --hash=sha256:0a3ae28f0b209be5af50b54ca3e2123a3de3a57d87b75f1e5aa3d7961e041983 \ + --hash=sha256:0d2e8db5ade3736a163906154ca686203acc7d1d30736cbf577c730d13653d84 \ + --hash=sha256:0e00cec383eab2406c9e006bd4edb55d284e94bb943fda558326048178d26961 \ + --hash=sha256:0fe6b8b8968e11dd9b2348bd508f0f57cf49ab3512064b36bc4117328218718e \ + --hash=sha256:0fe9128e75c6aa6e9ae06c1408d6edd9179a2fef0fe6d9cda3166b887eba521d \ + --hash=sha256:14b2e1eb528d77bc0f4c5bd1a7ebc05e02b5b41beefb7e8567c9675b8b13bcf4 \ + --hash=sha256:15d416440148f3e56b9b244fdaf8a09fcf5a72e4944b8e119f5bf60417a2bfc8 \ + --hash=sha256:15e555c4caca42411270b2ed2b2ebc7b3a42bb04138cef6c956e1f1d49709fe2 \ + --hash=sha256:16b4fe9c97dc605f5e1887a9e1224287291e35c56cbc379f8aa44b6b7bcfe2bb \ + --hash=sha256:1b5c6ceb65fecd28a1d20d1eba9dbfa992612b86594e4b6d47bb580d2dd6bcb3 \ + --hash=sha256:1d072a403d82aef8090c6d4f728e3a727dfdba1ad3b7fa3a052c3ecbd37e73cb \ + --hash=sha256:2324d9a0502317ffc35d38e153c1b2fa9610ae03775c9d0f8d0cca7b8572b04e \ + --hash=sha256:2a248750abce1c76fbd11b2e1d88b95401e72819295c3b851ec73399d6849b3d \ + --hash=sha256:2ea6206043385343aff0b7da65cf73677f6f5e50de8f1c879e557f4298cac36a \ + --hash=sha256:31348a0ffbfc815ce78daac569d893349d85a0b57e1cd2cdbba50b7f333784da \ + --hash=sha256:38051f36423f084b909aaadb3b41c9c6a2958e86956ba21a8489636911e87504 \ + --hash=sha256:3c2f947e55d3c7cfe124dd4521ee481516f3007d13c6ad4bf6aeb722e190eb1b \ + --hash=sha256:3ed5cb149892141b1e77ef312924a327f2cc718b34247dae346ed66329e1b8be \ + --hash=sha256:3ff4ede90ed771140caa7e1890de17431763a483c54b3c1f88bd30f0cc1affc0 \ + --hash=sha256:40aa43a7a3a8d2f05e79900858053d697a88a605e3887be178b43acbcd781161 \ + --hash=sha256:42d875388fbd091c7ea01edfff260f839ba303038ffb23475ef392012e4d63dd \ + --hash=sha256:457fabc2700a8e6ddb85bc5a1d30d3345fe0d3ec3ee8161a4e032ec585801dfa \ + --hash=sha256:460e76a4daff214ae33ab959494962c93918cb44714ea3e3f748b14aa37f8a87 \ + --hash=sha256:50524f4f6a1c839714dbaff5386a1afb245d2d5ec8213a01fbc99cea7307811e \ + --hash=sha256:51acc750ec7a2df786cdc868fb16fa04abd6269a01d58cf59bafc57978773d8e \ + --hash=sha256:55ede2a7a051b3b7e71a394978a098d71b3783e6b904702ff45483fad434ae2d \ + --hash=sha256:561f89cc82deeae82e37d4a4764184926fb432f740a9691563a391b13f7339a4 \ + --hash=sha256:56ba3f7abbd6b0bb282a544dc38406d1a188d8bb9164f49fdb9c2fee62cb29da \ + --hash=sha256:57930ac9519099b852e190d2c04b1fb5d97ea128db33bce77ed874eccb4c7f09 \ + --hash=sha256:58a11cb49482f1a095a2bd9a1d81dd7c8fb5d2357f959ece85db4e46a825fd00 \ + --hash=sha256:64df53eef4ac857eb5816a56e2885ccf0d7dff6333c94065c93b39c51063e01d \ + --hash=sha256:6879aed770557f0961b252648d36f6fdaab41079d37a2296b5649fd1b35608e0 \ + --hash=sha256:6ad57654570464eb1b040b5c353dee442608e06cff9102b8fcb105565a44c9ed \ + --hash=sha256:6c0aed6a4439994c9666fb8a5b6c4eac94d4ef6ddc95f9b806a599ef83547e3b \ + --hash=sha256:76bf3e7406cf23a3e1ca6a23fb1fb9ea82f4f6bd226fe226e09146b0194f85dc \ + --hash=sha256:7bbf05c38debc90d1a195b11340cc85cb43ab3e753dc47558a3a84a38cbc72da \ + --hash=sha256:7ddb08b3c2f9213df1f2e3eb2fbea4963d80ec0f8de21f0b59898e34f3b3d96d \ + --hash=sha256:7e07f6f644d2c44d53b7a320a084eef98063651912c1b9449b5f45fcbdc6ccd2 \ + --hash=sha256:85833bca01aa5cae326ac759276dc175c5fa3f7b3733b7d543cf27f2df12d1ef \ + --hash=sha256:8712b61eb1b74a4478cfd1c54f576056199e9f093659334aeb5c4a6b385338e5 \ + --hash=sha256:871c0e5102e47995b0e37e8df7819a894a6c3da0d097545cd1f9f1f7d7079927 \ + --hash=sha256:89e302abd3749f6d6699691747969a5d85f7c73081d5ed7e2624c7bd9721a2ab \ + --hash=sha256:937794042342006f707837f38d721426b11b0774d327a2a45c0bd389eb750a87 \ + --hash=sha256:93bc91fdadcf046da37a214eaa714574e7e9b1913568e93bb09527b2ceb7f759 \ + --hash=sha256:94c5f1621cbcab83c03be46441f090b68b9f307b6c7ec44d4e3f6d5997383df4 \ + --hash=sha256:973b7d7145b1ac553a7466a64afa8b31ec2693d7c7fff6a755059e0a2885dfd2 \ + --hash=sha256:99cc80facad240b0c2fb5a633044420878aac87a8e7c348b9486450cba93f27c \ + --hash=sha256:9a5fcbe7b949f2e95c47ea8a80b410fcdf2da61c98553b45a4ee875580418b68 \ + --hash=sha256:9b3b86ec3e818f3dd3e13a9de628e88a9990f4af68ecb0b12dd3de81227f0a26 \ + --hash=sha256:9b3cf13facf6f77c283af0e1713e5e8c47a0fe295af81326cb3cb4380212e797 \ + --hash=sha256:9c5a52987a990eb1bae55f9000994f1afdb0326c154fb089992f839ab3c30688 \ + --hash=sha256:a2d79c6635ccffcbfc1d5c045874ba36b594589be81d50d43472570bb8de9c57 \ + --hash=sha256:a6ec5bf6bc361f2f0f9644907a36ce527715b488988a8df534120e5c34eeda94 \ + --hash=sha256:a7bf9cc97f05048ac8f3e02cd58f0fe62b901453c24345bfde287f4305dcc31c \ + --hash=sha256:ab9056d94e5db513d9313b34394f3a3b83e6301a581c28ad67773434f3faccab \ + --hash=sha256:adf28d13a33f9d750fe7a78fb481cac298fa257d8863d8727b2ea4455ea41235 \ + --hash=sha256:b62cb9a7501e1f5c9ffe190485501349c33e8862dde4377df774e40b8166871f \ + --hash=sha256:bacbd3c69862478cbe1c7ed4325caedec580d8acf31b8ee1b9a1e02a56295cad \ + --hash=sha256:bb349dbba57c76eec25e5917e07f35aabaf0a33b9e67fc13d188002500106487 \ + --hash=sha256:bd03472c36fa3a386a6deb887113b9e3fa40efba8203eb4fe786d3c0ccc724f6 \ + --hash=sha256:bf85a00ac3b56a1e7a19c5be7b02b5180a0895ac4d3c234d717a55e86960691c \ + --hash=sha256:ca0c7ce828bb76ab78b3991904b477c2fd0f711d7815c252d1ef28ff9450b052 \ + --hash=sha256:ccbfd94e59aad4a2566c71912b55f0547ac1680bfac25eb138e6703eb3dd434e \ + --hash=sha256:d1831c07bd4dce53c4b666fa846c7eba4b7c414f2e641a4585b7f50b72f502dc \ + --hash=sha256:d22cad98c2a10bbf6aa083a8980db6ed90d4285a841c4de892890c2b28286ef9 \ + --hash=sha256:d30ad4359413c8821cc7b3707f7ca38aa8bc852ba3b9c5a759ee2d7740157315 \ + --hash=sha256:e0dd3676ea0837cd70ea1879765e9e9f6be063be0436de9b3ea4b775caf83654 \ + --hash=sha256:e584d0cdd37cac355aca52ed788d1a2d939d6837e2870d3b70e585db24025a50 \ + --hash=sha256:e6369ac293d2cc40d52577e4fa3d75a70c1aae2d01fa3580a34a4e6eff9286b9 \ + --hash=sha256:efae5df7a8cc8bdb1037b0f786b044ce281081441df5418c3a0f0e1f86fe7bb3 \ + --hash=sha256:f19b3af31d02a2e79c5f9a6deaab0fb3c116456aeb9277d11720ad433de6dfc6 \ + --hash=sha256:f7a0430d765f9bda043e6aefaba5944d5f21ec43ff4774417d7e296f61917382 \ + --hash=sha256:fb94245a715b4d6e24689de12772b85329a1f9946cbf6187923a64ecdea39e65 # via pymilvus urllib3==2.6.3 \ --hash=sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed \ @@ -3183,137 +3176,135 @@ wrapt==1.17.3 \ --hash=sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10 \ --hash=sha256:fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c # via aiobotocore -yarl==1.22.0 \ - --hash=sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a \ - --hash=sha256:029866bde8d7b0878b9c160e72305bbf0a7342bcd20b9999381704ae03308dc8 \ - --hash=sha256:078278b9b0b11568937d9509b589ee83ef98ed6d561dfe2020e24a9fd08eaa2b \ - --hash=sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da \ - --hash=sha256:07a524d84df0c10f41e3ee918846e1974aba4ec017f990dc735aad487a0bdfdf \ - --hash=sha256:088e4e08f033db4be2ccd1f34cf29fe994772fb54cfe004bbf54db320af56890 \ - --hash=sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093 \ - --hash=sha256:0cf71bf877efeac18b38d3930594c0948c82b64547c1cf420ba48722fe5509f6 \ - --hash=sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79 \ - --hash=sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683 \ - --hash=sha256:10619d9fdee46d20edc49d3479e2f8269d0779f1b031e6f7c2aa1c76be04b7ed \ - --hash=sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2 \ - --hash=sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff \ - --hash=sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02 \ - --hash=sha256:14291620375b1060613f4aab9ebf21850058b6b1b438f386cc814813d901c60b \ - --hash=sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03 \ - --hash=sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511 \ - --hash=sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c \ - --hash=sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124 \ - --hash=sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c \ - --hash=sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da \ - --hash=sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2 \ - --hash=sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0 \ - --hash=sha256:2e4e1f6f0b4da23e61188676e3ed027ef0baa833a2e633c29ff8530800edccba \ - --hash=sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d \ - --hash=sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53 \ - --hash=sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138 \ - --hash=sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4 \ - --hash=sha256:3aa27acb6de7a23785d81557577491f6c38a5209a254d1191519d07d8fe51748 \ - --hash=sha256:3b06bcadaac49c70f4c88af4ffcfbe3dc155aab3163e75777818092478bcbbe7 \ - --hash=sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d \ - --hash=sha256:3e2daa88dc91870215961e96a039ec73e4937da13cf77ce17f9cad0c18df3503 \ - --hash=sha256:3ea66b1c11c9150f1372f69afb6b8116f2dd7286f38e14ea71a44eee9ec51b9d \ - --hash=sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2 \ - --hash=sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa \ - --hash=sha256:437840083abe022c978470b942ff832c3940b2ad3734d424b7eaffcd07f76737 \ - --hash=sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f \ - --hash=sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1 \ - --hash=sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d \ - --hash=sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694 \ - --hash=sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3 \ - --hash=sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a \ - --hash=sha256:4c52a6e78aef5cf47a98ef8e934755abf53953379b7d53e68b15ff4420e6683d \ - --hash=sha256:4dcc74149ccc8bba31ce1944acee24813e93cfdee2acda3c172df844948ddf7b \ - --hash=sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a \ - --hash=sha256:51af598701f5299012b8416486b40fceef8c26fc87dc6d7d1f6fc30609ea0aa6 \ - --hash=sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b \ - --hash=sha256:595697f68bd1f0c1c159fcb97b661fc9c3f5db46498043555d04805430e79bea \ - --hash=sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5 \ - --hash=sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f \ - --hash=sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df \ - --hash=sha256:5cdac20da754f3a723cceea5b3448e1a2074866406adeb4ef35b469d089adb8f \ - --hash=sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b \ - --hash=sha256:5dbeefd6ca588b33576a01b0ad58aa934bc1b41ef89dee505bf2932b22ddffba \ - --hash=sha256:62441e55958977b8167b2709c164c91a6363e25da322d87ae6dd9c6019ceecf9 \ - --hash=sha256:663e1cadaddae26be034a6ab6072449a8426ddb03d500f43daf952b74553bba0 \ - --hash=sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6 \ - --hash=sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b \ - --hash=sha256:6944b2dc72c4d7f7052683487e3677456050ff77fcf5e6204e98caf785ad1967 \ - --hash=sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2 \ - --hash=sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708 \ - --hash=sha256:6dcbb0829c671f305be48a7227918cfcd11276c2d637a8033a99a02b67bf9eda \ - --hash=sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8 \ - --hash=sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10 \ - --hash=sha256:75976c6945d85dbb9ee6308cd7ff7b1fb9409380c82d6119bd778d8fcfe2931c \ - --hash=sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b \ - --hash=sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028 \ - --hash=sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e \ - --hash=sha256:80ddf7a5f8c86cb3eb4bc9028b07bbbf1f08a96c5c0bc1244be5e8fefcb94147 \ - --hash=sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33 \ - --hash=sha256:84fc3ec96fce86ce5aa305eb4aa9358279d1aa644b71fab7b8ed33fe3ba1a7ca \ - --hash=sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590 \ - --hash=sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c \ - --hash=sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53 \ - --hash=sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74 \ - --hash=sha256:99b6fc1d55782461b78221e95fc357b47ad98b041e8e20f47c1411d0aacddc60 \ - --hash=sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f \ - --hash=sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1 \ - --hash=sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27 \ - --hash=sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520 \ - --hash=sha256:a4fcfc8eb2c34148c118dfa02e6427ca278bfd0f3df7c5f99e33d2c0e81eae3e \ - --hash=sha256:a899cbd98dce6f5d8de1aad31cb712ec0a530abc0a86bd6edaa47c1090138467 \ - --hash=sha256:a9b1ba5610a4e20f655258d5a1fdc7ebe3d837bb0e45b581398b99eb98b1f5ca \ - --hash=sha256:af74f05666a5e531289cb1cc9c883d1de2088b8e5b4de48004e5ca8a830ac859 \ - --hash=sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273 \ - --hash=sha256:b266bd01fedeffeeac01a79ae181719ff848a5a13ce10075adbefc8f1daee70e \ - --hash=sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601 \ - --hash=sha256:b580e71cac3f8113d3135888770903eaf2f507e9421e5697d6ee6d8cd1c7f054 \ - --hash=sha256:b6a6f620cfe13ccec221fa312139135166e47ae169f8253f72a0abc0dae94376 \ - --hash=sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7 \ - --hash=sha256:b85b982afde6df99ecc996990d4ad7ccbdbb70e2a4ba4de0aecde5922ba98a0b \ - --hash=sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb \ - --hash=sha256:ba440ae430c00eee41509353628600212112cd5018d5def7e9b05ea7ac34eb65 \ - --hash=sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784 \ - --hash=sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71 \ - --hash=sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b \ - --hash=sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a \ - --hash=sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c \ - --hash=sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face \ - --hash=sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d \ - --hash=sha256:c7bd6683587567e5a49ee6e336e0612bec8329be1b7d4c8af5687dcdeb67ee1e \ - --hash=sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e \ - --hash=sha256:cb95a9b1adaa48e41815a55ae740cfda005758104049a640a398120bf02515ca \ - --hash=sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9 \ - --hash=sha256:d332fc2e3c94dad927f2112395772a4e4fedbcf8f80efc21ed7cdfae4d574fdb \ - --hash=sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95 \ - --hash=sha256:d5372ca1df0f91a86b047d1277c2aaf1edb32d78bbcefffc81b40ffd18f027ed \ - --hash=sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf \ - --hash=sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca \ - --hash=sha256:dd7afd3f8b0bfb4e0d9fc3c31bfe8a4ec7debe124cfd90619305def3c8ca8cd2 \ - --hash=sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62 \ - --hash=sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df \ - --hash=sha256:e1b329cb8146d7b736677a2440e422eadd775d1806a81db2d4cded80a48efc1a \ - --hash=sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67 \ - --hash=sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f \ - --hash=sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529 \ - --hash=sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486 \ - --hash=sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a \ - --hash=sha256:e6438cc8f23a9c1478633d216b16104a586b9761db62bfacb6425bac0a36679e \ - --hash=sha256:e81fda2fb4a07eda1a2252b216aa0df23ebcd4d584894e9612e80999a78fd95b \ - --hash=sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74 \ - --hash=sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d \ - --hash=sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b \ - --hash=sha256:f0d97c18dfd9a9af4490631905a3f131a8e4c9e80a39353919e2cfed8f00aedc \ - --hash=sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2 \ - --hash=sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e \ - --hash=sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8 \ - --hash=sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82 \ - --hash=sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd \ - --hash=sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249 +yarl==1.23.0 \ + --hash=sha256:03214408cfa590df47728b84c679ae4ef00be2428e11630277be0727eba2d7cc \ + --hash=sha256:041b1a4cefacf65840b4e295c6985f334ba83c30607441ae3cf206a0eed1a2e4 \ + --hash=sha256:0793e2bd0cf14234983bbb371591e6bea9e876ddf6896cdcc93450996b0b5c85 \ + --hash=sha256:0e1fdaa14ef51366d7757b45bde294e95f6c8c049194e793eedb8387c86d5993 \ + --hash=sha256:0e40111274f340d32ebcc0a5668d54d2b552a6cca84c9475859d364b380e3222 \ + --hash=sha256:115136c4a426f9da976187d238e84139ff6b51a20839aa6e3720cd1026d768de \ + --hash=sha256:13a563739ae600a631c36ce096615fe307f131344588b0bc0daec108cdb47b25 \ + --hash=sha256:16c6994ac35c3e74fb0ae93323bf8b9c2a9088d55946109489667c510a7d010e \ + --hash=sha256:170e26584b060879e29fac213e4228ef063f39128723807a312e5c7fec28eff2 \ + --hash=sha256:17235362f580149742739cc3828b80e24029d08cbb9c4bda0242c7b5bc610a8e \ + --hash=sha256:1932b6b8bba8d0160a9d1078aae5838a66039e8832d41d2992daa9a3a08f7860 \ + --hash=sha256:1b6b572edd95b4fa8df75de10b04bc81acc87c1c7d16bcdd2035b09d30acc957 \ + --hash=sha256:1c3a3598a832590c5a3ce56ab5576361b5688c12cb1d39429cf5dba30b510760 \ + --hash=sha256:1c57676bdedc94cd3bc37724cf6f8cd2779f02f6aba48de45feca073e714fe52 \ + --hash=sha256:1dc702e42d0684f42d6519c8d581e49c96cefaaab16691f03566d30658ee8788 \ + --hash=sha256:21d1b7305a71a15b4794b5ff22e8eef96ff4a6d7f9657155e5aa419444b28912 \ + --hash=sha256:23f371bd662cf44a7630d4d113101eafc0cfa7518a2760d20760b26021454719 \ + --hash=sha256:2569b67d616eab450d262ca7cb9f9e19d2f718c70a8b88712859359d0ab17035 \ + --hash=sha256:263cd4f47159c09b8b685890af949195b51d1aa82ba451c5847ca9bc6413c220 \ + --hash=sha256:2803ed8b21ca47a43da80a6fd1ed3019d30061f7061daa35ac54f63933409412 \ + --hash=sha256:2a6940a074fb3c48356ed0158a3ca5699c955ee4185b4d7d619be3c327143e05 \ + --hash=sha256:2e27c8841126e017dd2a054a95771569e6070b9ee1b133366d8b31beb5018a41 \ + --hash=sha256:31c9921eb8bd12633b41ad27686bbb0b1a2a9b8452bfdf221e34f311e9942ed4 \ + --hash=sha256:34b6cf500e61c90f305094911f9acc9c86da1a05a7a3f5be9f68817043f486e4 \ + --hash=sha256:3650dc2480f94f7116c364096bc84b1d602f44224ef7d5c7208425915c0475dd \ + --hash=sha256:389871e65468400d6283c0308e791a640b5ab5c83bcee02a2f51295f95e09748 \ + --hash=sha256:39004f0ad156da43e86aa71f44e033de68a44e5a31fc53507b36dd253970054a \ + --hash=sha256:394906945aa8b19fc14a61cf69743a868bb8c465efe85eee687109cc540b98f4 \ + --hash=sha256:3ceb13c5c858d01321b5d9bb65e4cf37a92169ea470b70fec6f236b2c9dd7e34 \ + --hash=sha256:411225bae281f114067578891bc75534cfb3d92a3b4dfef7a6ca78ba354e6069 \ + --hash=sha256:44bb7bef4ea409384e3f8bc36c063d77ea1b8d4a5b2706956c0d6695f07dcc25 \ + --hash=sha256:4503053d296bc6e4cbd1fad61cf3b6e33b939886c4f249ba7c78b602214fabe2 \ + --hash=sha256:4764a6a7588561a9aef92f65bda2c4fb58fe7c675c0883862e6df97559de0bfb \ + --hash=sha256:4966242ec68afc74c122f8459abd597afd7d8a60dc93d695c1334c5fd25f762f \ + --hash=sha256:4a42e651629dafb64fd5b0286a3580613702b5809ad3f24934ea87595804f2c5 \ + --hash=sha256:4a59ba56f340334766f3a4442e0efd0af895fae9e2b204741ef885c446b3a1a8 \ + --hash=sha256:4c41e021bc6d7affb3364dc1e1e5fa9582b470f283748784bd6ea0558f87f42c \ + --hash=sha256:5023346c4ee7992febc0068e7593de5fa2bf611848c08404b35ebbb76b1b0512 \ + --hash=sha256:50f9d8d531dfb767c565f348f33dd5139a6c43f5cbdf3f67da40d54241df93f6 \ + --hash=sha256:51430653db848d258336cfa0244427b17d12db63d42603a55f0d4546f50f25b5 \ + --hash=sha256:531ef597132086b6cf96faa7c6c1dcd0361dd5f1694e5cc30375907b9b7d3ea9 \ + --hash=sha256:53ad387048f6f09a8969631e4de3f1bf70c50e93545d64af4f751b2498755072 \ + --hash=sha256:53b1ea6ca88ebd4420379c330aea57e258408dd0df9af0992e5de2078dc9f5d5 \ + --hash=sha256:575aa4405a656e61a540f4a80eaa5260f2a38fff7bfdc4b5f611840d76e9e277 \ + --hash=sha256:578110dd426f0d209d1509244e6d4a3f1a3e9077655d98c5f22583d63252a08a \ + --hash=sha256:5ec2f42d41ccbd5df0270d7df31618a8ee267bfa50997f5d720ddba86c4a83a6 \ + --hash=sha256:5ee586fb17ff8f90c91cf73c6108a434b02d69925f44f5f8e0d7f2f260607eae \ + --hash=sha256:5f10fd85e4b75967468af655228fbfd212bdf66db1c0d135065ce288982eda26 \ + --hash=sha256:609d3614d78d74ebe35f54953c5bbd2ac647a7ddb9c30a5d877580f5e86b22f2 \ + --hash=sha256:62694e275c93d54f7ccedcfef57d42761b2aad5234b6be1f3e3026cae4001cd4 \ + --hash=sha256:63e92247f383c85ab00dd0091e8c3fa331a96e865459f5ee80353c70a4a42d70 \ + --hash=sha256:682bae25f0a0dd23a056739f23a134db9f52a63e2afd6bfb37ddc76292bbd723 \ + --hash=sha256:6b41389c19b07c760c7e427a3462e8ab83c4bb087d127f0e854c706ce1b9215c \ + --hash=sha256:6e87a6e8735b44816e7db0b2fbc9686932df473c826b0d9743148432e10bb9b9 \ + --hash=sha256:6f0fd84de0c957b2d280143522c4f91a73aada1923caee763e24a2b3fda9f8a5 \ + --hash=sha256:70efd20be968c76ece7baa8dafe04c5be06abc57f754d6f36f3741f7aa7a208e \ + --hash=sha256:71d006bee8397a4a89f469b8deb22469fe7508132d3c17fa6ed871e79832691c \ + --hash=sha256:73309162a6a571d4cbd3b6a1dcc703c7311843ae0d1578df6f09be4e98df38d4 \ + --hash=sha256:75e3026ab649bf48f9a10c0134512638725b521340293f202a69b567518d94e0 \ + --hash=sha256:76855800ac56f878847a09ce6dba727c93ca2d89c9e9d63002d26b916810b0a2 \ + --hash=sha256:7c6b9461a2a8b47c65eef63bb1c76a4f1c119618ffa99ea79bc5bb1e46c5821b \ + --hash=sha256:803a3c3ce4acc62eaf01eaca1208dcf0783025ef27572c3336502b9c232005e7 \ + --hash=sha256:80e6d33a3d42a7549b409f199857b4fb54e2103fc44fb87605b6663b7a7ff750 \ + --hash=sha256:8419ebd326430d1cbb7efb5292330a2cf39114e82df5cc3d83c9a0d5ebeaf2f2 \ + --hash=sha256:85610b4f27f69984932a7abbe52703688de3724d9f72bceb1cca667deff27474 \ + --hash=sha256:85e9beda1f591bc73e77ea1c51965c68e98dafd0fec72cdd745f77d727466716 \ + --hash=sha256:877b0738624280e34c55680d6054a307aa94f7d52fa0e3034a9cc6e790871da7 \ + --hash=sha256:88f9fb0116fbfcefcab70f85cf4b74a2b6ce5d199c41345296f49d974ddb4123 \ + --hash=sha256:8c4fe09e0780c6c3bf2b7d4af02ee2394439d11a523bbcf095cf4747c2932007 \ + --hash=sha256:93a784271881035ab4406a172edb0faecb6e7d00f4b53dc2f55919d6c9688595 \ + --hash=sha256:94f8575fbdf81749008d980c17796097e645574a3b8c28ee313931068dad14fe \ + --hash=sha256:95451e6ce06c3e104556d73b559f5da6c34a069b6b62946d3ad66afcd51642ea \ + --hash=sha256:99c8a9ed30f4164bc4c14b37a90208836cbf50d4ce2a57c71d0f52c7fb4f7598 \ + --hash=sha256:9a18d6f9359e45722c064c97464ec883eb0e0366d33eda61cb19a244bf222679 \ + --hash=sha256:9cbf44c5cb4a7633d078788e1b56387e3d3cf2b8139a3be38040b22d6c3221c8 \ + --hash=sha256:9ee33b875f0b390564c1fb7bc528abf18c8ee6073b201c6ae8524aca778e2d83 \ + --hash=sha256:a0e317df055958a0c1e79e5d2aa5a5eaa4a6d05a20d4b0c9c3f48918139c9fc6 \ + --hash=sha256:a2df6afe50dea8ae15fa34c9f824a3ee958d785fd5d089063d960bae1daa0a3f \ + --hash=sha256:a31de1613658308efdb21ada98cbc86a97c181aa050ba22a808120bb5be3ab94 \ + --hash=sha256:a3d2bff8f37f8d0f96c7ec554d16945050d54462d6e95414babaa18bfafc7f51 \ + --hash=sha256:a41bcf68efd19073376eb8cf948b8d9be0af26256403e512bb18f3966f1f9120 \ + --hash=sha256:a82836cab5f197a0514235aaf7ffccdc886ccdaa2324bc0aafdd4ae898103039 \ + --hash=sha256:a8d00f29b42f534cc8aa3931cfe773b13b23e561e10d2b26f27a8d309b0e82a1 \ + --hash=sha256:aafe5dcfda86c8af00386d7781d4c2181b5011b7be3f2add5e99899ea925df05 \ + --hash=sha256:ab5f043cb8a2d71c981c09c510da013bc79fd661f5c60139f00dd3c3cc4f2ffb \ + --hash=sha256:ac09d42f48f80c9ee1635b2fcaa819496a44502737660d3c0f2ade7526d29144 \ + --hash=sha256:aecfed0b41aa72b7881712c65cf764e39ce2ec352324f5e0837c7048d9e6daaa \ + --hash=sha256:b2c6b50c7b0464165472b56b42d4c76a7b864597007d9c085e8b63e185cf4a7a \ + --hash=sha256:b35d13d549077713e4414f927cdc388d62e543987c572baee613bf82f11a4b99 \ + --hash=sha256:b39cb32a6582750b6cc77bfb3c49c0f8760dc18dc96ec9fb55fbb0f04e08b928 \ + --hash=sha256:b5405bb8f0e783a988172993cfc627e4d9d00432d6bbac65a923041edacf997d \ + --hash=sha256:baaf55442359053c7d62f6f8413a62adba3205119bcb6f49594894d8be47e5e3 \ + --hash=sha256:bd654fad46d8d9e823afbb4f87c79160b5a374ed1ff5bde24e542e6ba8f41434 \ + --hash=sha256:be61f6fff406ca40e3b1d84716fde398fc08bc63dd96d15f3a14230a0973ed86 \ + --hash=sha256:bf49a3ae946a87083ef3a34c8f677ae4243f5b824bfc4c69672e72b3d6719d46 \ + --hash=sha256:c4a80f77dc1acaaa61f0934176fccca7096d9b1ff08c8ba9cddf5ae034a24319 \ + --hash=sha256:c75eb09e8d55bceb4367e83496ff8ef2bc7ea6960efb38e978e8073ea59ecb67 \ + --hash=sha256:c7f8dc16c498ff06497c015642333219871effba93e4a2e8604a06264aca5c5c \ + --hash=sha256:c8aa34a5c864db1087d911a0b902d60d203ea3607d91f615acd3f3108ac32169 \ + --hash=sha256:cbb0fef01f0c6b38cb0f39b1f78fc90b807e0e3c86a7ff3ce74ad77ce5c7880c \ + --hash=sha256:cde9a2ecd91668bcb7f077c4966d8ceddb60af01b52e6e3e2680e4cf00ad1a59 \ + --hash=sha256:cff6d44cb13d39db2663a22b22305d10855efa0fa8015ddeacc40bc59b9d8107 \ + --hash=sha256:d1009abedb49ae95b136a8904a3f71b342f849ffeced2d3747bf29caeda218c4 \ + --hash=sha256:d38c1e8231722c4ce40d7593f28d92b5fc72f3e9774fe73d7e800ec32299f63a \ + --hash=sha256:d53834e23c015ee83a99377db6e5e37d8484f333edb03bd15b4bc312cc7254fb \ + --hash=sha256:d7504f2b476d21653e4d143f44a175f7f751cd41233525312696c76aa3dbb23f \ + --hash=sha256:dbf507e9ef5688bada447a24d68b4b58dd389ba93b7afc065a2ba892bea54769 \ + --hash=sha256:dc52310451fc7c629e13c4e061cbe2dd01684d91f2f8ee2821b083c58bd72432 \ + --hash=sha256:dd00607bffbf30250fe108065f07453ec124dbf223420f57f5e749b04295e090 \ + --hash=sha256:dda608c88cf709b1d406bdfcd84d8d63cff7c9e577a403c6108ce8ce9dcc8764 \ + --hash=sha256:debe9c4f41c32990771be5c22b56f810659f9ddf3d63f67abfdcaa2c6c9c5c1d \ + --hash=sha256:e09fd068c2e169a7070d83d3bde728a4d48de0549f975290be3c108c02e499b4 \ + --hash=sha256:e0fd068364a6759bc794459f0a735ab151d11304346332489c7972bacbe9e72b \ + --hash=sha256:e4c53f8347cd4200f0d70a48ad059cabaf24f5adc6ba08622a23423bc7efa10d \ + --hash=sha256:e5723c01a56c5028c807c701aa66722916d2747ad737a046853f6c46f4875543 \ + --hash=sha256:e7b0460976dc75cb87ad9cc1f9899a4b97751e7d4e77ab840fc9b6d377b8fd24 \ + --hash=sha256:e9d9a4d06d3481eab79803beb4d9bd6f6a8e781ec078ac70d7ef2dcc29d1bea5 \ + --hash=sha256:ead11956716a940c1abc816b7df3fa2b84d06eaed8832ca32f5c5e058c65506b \ + --hash=sha256:ed5f69ce7be7902e5c70ea19eb72d20abf7d725ab5d49777d696e32d4fc1811d \ + --hash=sha256:f2af5c81a1f124609d5f33507082fc3f739959d4719b56877ab1ee7e7b3d602b \ + --hash=sha256:f40e782d49630ad384db66d4d8b73ff4f1b8955dc12e26b09a3e3af064b3b9d6 \ + --hash=sha256:f514f6474e04179d3d33175ed3f3e31434d3130d42ec153540d5b157deefd735 \ + --hash=sha256:f69f57305656a4852f2a7203efc661d8c042e6cc67f7acd97d8667fb448a426e \ + --hash=sha256:fb1e8b8d66c278b21d13b0a7ca22c41dd757a7c209c6b12c313e445c31dd3b28 \ + --hash=sha256:fb4948814a2a98e3912505f09c9e7493b1506226afb1f881825368d6fb776ee3 \ + --hash=sha256:fda207c815b253e34f7e1909840fd14299567b1c0eb4908f8c2ce01a41265401 \ + --hash=sha256:fe8f8f5e70e6dbdfca9882cd9deaac058729bcf323cf7a58660901e55c9c94f6 \ + --hash=sha256:fffc45637bcd6538de8b85f51e3df3223e4ad89bccbfca0481c08c7fc8b7ed7d # via aiohttp zipp==3.23.0 \ --hash=sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e \ diff --git a/sdk/python/requirements/py3.11-minimal-sdist-requirements-build.txt b/sdk/python/requirements/py3.11-minimal-sdist-requirements-build.txt index 26a3f9f0b15..f1eaaa0c05a 100644 --- a/sdk/python/requirements/py3.11-minimal-sdist-requirements-build.txt +++ b/sdk/python/requirements/py3.11-minimal-sdist-requirements-build.txt @@ -287,9 +287,9 @@ hatch-vcs==0.5.0 \ # via # filelock # platformdirs -hatchling==1.28.0 \ - --hash=sha256:4d50b02aece6892b8cd0b3ce6c82cb218594d3ec5836dbde75bf41a21ab004c8 \ - --hash=sha256:dc48722b68b3f4bbfa3ff618ca07cdea6750e7d03481289ffa8be1521d18a961 +hatchling==1.29.0 \ + --hash=sha256:50af9343281f34785fab12da82e445ed987a6efb34fd8c2fc0f6e6630dbcc1b0 \ + --hash=sha256:793c31816d952cee405b83488ce001c719f325d9cda69f1fc4cd750527640ea6 # via # annotated-types # atpublic @@ -326,97 +326,97 @@ jinja2==3.1.6 \ --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 # via uv-dynamic-versioning -librt==0.8.0 \ - --hash=sha256:001e5330093d887b8b9165823eca6c5c4db183fe4edea4fdc0680bbac5f46944 \ - --hash=sha256:015e2dde6e096d27c10238bf9f6492ba6c65822dfb69d2bf74c41a8e88b7ddef \ - --hash=sha256:02a9fe85410cc9bef045e7cb7fd26fdde6669e6d173f99df659aa7f6335961e9 \ - --hash=sha256:0583aef7e9a720dd40f26a2ad5a1bf2ccbb90059dac2b32ac516df232c701db3 \ - --hash=sha256:05a3dd3f116747f7e1a2b475ccdc6fb637fd4987126d109e03013a79d40bf9e6 \ - --hash=sha256:0a33335eb59921e77c9acc05d0e654e4e32e45b014a4d61517897c11591094f8 \ - --hash=sha256:0ce33a9778e294507f3a0e3468eccb6a698b5166df7db85661543eca1cfc5369 \ - --hash=sha256:1566dbb9d1eb0987264c9b9460d212e809ba908d2f4a3999383a84d765f2f3f1 \ - --hash=sha256:17269dd2745dbe8e42475acb28e419ad92dfa38214224b1b01020b8cac70b645 \ - --hash=sha256:178707cda89d910c3b28bf5aa5f69d3d4734e0f6ae102f753ad79edef83a83c7 \ - --hash=sha256:1c25a131013eadd3c600686a0c0333eb2896483cbc7f65baa6a7ee761017aef9 \ - --hash=sha256:1e6811cac1dcb27ca4c74e0ca4a5917a8e06db0d8408d30daee3a41724bfde7a \ - --hash=sha256:1ef3bd856373cf8e7382402731f43bfe978a8613b4039e49e166e1e0dc590216 \ - --hash=sha256:20f73d4fecba969efc15cdefd030e382502d56bb6f1fc66b580cce582836c9fa \ - --hash=sha256:21b14464bee0b604d80a638cf1ee3148d84ca4cc163dcdcecb46060c1b3605e4 \ - --hash=sha256:24a01c13a2a9bdad20997a4443ebe6e329df063d1978bbe2ebbf637878a46d1e \ - --hash=sha256:25b3e667cbfc9000c4740b282df599ebd91dbdcc1aa6785050e4c1d6be5329ab \ - --hash=sha256:25e82d920d4d62ad741592fcf8d0f3bda0e3fc388a184cb7d2f566c681c5f7b9 \ - --hash=sha256:2b37437e7e4ef5e15a297b36ba9e577f73e29564131d86dd75875705e97402b5 \ - --hash=sha256:2ccdd20d9a72c562ffb73098ac411de351b53a6fbb3390903b2d33078ef90447 \ - --hash=sha256:2e0ffe88ebb5962f8fb0ddcbaaff30f1ea06a79501069310e1e030eafb1ad787 \ - --hash=sha256:375eda7acfce1f15f5ed56cfc960669eefa1ec8732e3e9087c3c4c3f2066759c \ - --hash=sha256:3d2720335020219197380ccfa5c895f079ac364b4c429e96952cd6509934d8eb \ - --hash=sha256:3e36a8da17134ffc29373775d88c04832f9ecfab1880470661813e6c7991ef79 \ - --hash=sha256:3e8b77b5f54d0937b26512774916041756c9eb3e66f1031971e626eea49d0bf4 \ - --hash=sha256:41064a0c07b4cc7a81355ccc305cb097d6027002209ffca51306e65ee8293630 \ - --hash=sha256:421765e8c6b18e64d21c8ead315708a56fc24f44075059702e421d164575fdda \ - --hash=sha256:4831c44b8919e75ca0dfb52052897c1ef59fdae19d3589893fbd068f1e41afbf \ - --hash=sha256:48f84830a8f8ad7918afd743fd7c4eb558728bceab7b0e38fd5a5cf78206a556 \ - --hash=sha256:4b705f85311ee76acec5ee70806990a51f0deb519ea0c29c1d1652d79127604d \ - --hash=sha256:4d3e38797eb482485b486898f89415a6ab163bc291476bd95712e42cf4383c05 \ - --hash=sha256:4eb5e06ebcc668677ed6389164f52f13f71737fc8be471101fa8b4ce77baeb0c \ - --hash=sha256:4f6e975377fbc4c9567cb33ea9ab826031b6c7ec0515bfae66a4fb110d40d6da \ - --hash=sha256:4f764b2424cb04524ff7a486b9c391e93f93dc1bd8305b2136d25e582e99aa2f \ - --hash=sha256:507e94f4bec00b2f590fbe55f48cd518a208e2474a3b90a60aa8f29136ddbada \ - --hash=sha256:56901f1eec031396f230db71c59a01d450715cbbef9856bf636726994331195d \ - --hash=sha256:5cb11061a736a9db45e3c1293cfcb1e3caf205912dfa085734ba750f2197ff9a \ - --hash=sha256:5d0f76fc73480d42285c609c0ea74d79856c160fa828ff9aceab574ea4ecfd7b \ - --hash=sha256:667e2513cf69bfd1e1ed9a00d6c736d5108714ec071192afb737987955888a25 \ - --hash=sha256:671a6152edf3b924d98a5ed5e6982ec9cb30894085482acadce0975f031d4c5c \ - --hash=sha256:693697133c3b32aa9b27f040e3691be210e9ac4d905061859a9ed519b1d5a376 \ - --hash=sha256:6a3146c63220d814c4a2c7d6a1eacc8d5c14aed0ff85115c1dfea868080cd18f \ - --hash=sha256:6b6caff69e25d80c269b1952be8493b4d94ef745f438fa619d7931066bdd26de \ - --hash=sha256:6e1af31a710e17891d9adf0dbd9a5fcd94901a3922a96499abdbf7ce658f4e01 \ - --hash=sha256:70defb797c4d5402166787a6b3c66dfb3fa7f93d118c0509ffafa35a392f4258 \ - --hash=sha256:71fc517efc14f75c2f74b1f0a5d5eb4a8e06aa135c34d18eaf3522f4a53cd62d \ - --hash=sha256:75d1a8cab20b2043f03f7aab730551e9e440adc034d776f15f6f8d582b0a5ad4 \ - --hash=sha256:789911e8fa40a2e82f41120c936b1965f3213c67f5a483fc5a41f5839a05dcbb \ - --hash=sha256:7bd68cebf3131bb920d5984f75fe302d758db33264e44b45ad139385662d7bc3 \ - --hash=sha256:7ce0a8cb67e702dcb06342b2aaaa3da9fb0ddc670417879adfa088b44cf7b3b6 \ - --hash=sha256:7f820210e21e3a8bf8fde2ae3c3d10106d4de9ead28cbfdf6d0f0f41f5b12fa1 \ - --hash=sha256:8070aa3368559de81061ef752770d03ca1f5fc9467d4d512d405bd0483bfffe6 \ - --hash=sha256:82e61cd1c563745ad495387c3b65806bfd453badb4adbc019df3389dddee1bf6 \ - --hash=sha256:82fb4602d1b3e303a58bfe6165992b5a78d823ec646445356c332cd5f5bbaa61 \ - --hash=sha256:88c6e75540f1f10f5e0fc5e87b4b6c290f0e90d1db8c6734f670840494764af8 \ - --hash=sha256:8992ca186a1678107b0af3d0c9303d8c7305981b9914989b9788319ed4d89546 \ - --hash=sha256:92249938ab744a5890580d3cb2b22042f0dce71cdaa7c1369823df62bedf7cbc \ - --hash=sha256:95a719a049f0eefaf1952673223cf00d442952273cbd20cf2ed7ec423a0ef58d \ - --hash=sha256:9646178cd794704d722306c2c920c221abbf080fede3ba539d5afdec16c46dad \ - --hash=sha256:9726305d3e53419d27fc8cdfcd3f9571f0ceae22fa6b5ea1b3662c2e538f833e \ - --hash=sha256:995d24caa6bbb34bcdd4a41df98ac6d1af637cfa8975cb0790e47d6623e70e3e \ - --hash=sha256:9ab3a3475a55b89b87ffd7e6665838e8458e0b596c22e0177e0f961434ec474a \ - --hash=sha256:9f09d4884f882baa39a7e36bbf3eae124c4ca2a223efb91e567381d1c55c6b06 \ - --hash=sha256:a512c88900bdb1d448882f5623a0b1ad27ba81a9bd75dacfe17080b72272ca1f \ - --hash=sha256:a905091a13e0884701226860836d0386b88c72ce5c2fdfba6618e14c72be9f25 \ - --hash=sha256:aaadec87f45a3612b6818d1db5fbfe93630669b7ee5d6bdb6427ae08a1aa2141 \ - --hash=sha256:b055bb3abaf69abed25743d8fc1ab691e4f51a912ee0a6f9a6c84f4bbddb283d \ - --hash=sha256:b4bb00bd71b448f16749909b08a0ff16f58b079e2261c2e1000f2bbb2a4f0a45 \ - --hash=sha256:b9aef96d7593584e31ef6ac1eb9775355b0099fee7651fae3a15bc8657b67b52 \ - --hash=sha256:ba581acad5ac8f33e2ff1746e8a57e001b47c6721873121bf8bbcf7ba8bd3aa4 \ - --hash=sha256:ba9d9e60651615bc614be5e21a82cdb7b1769a029369cf4b4d861e4f19686fb6 \ - --hash=sha256:bbebd2bba5c6ae02907df49150e55870fdd7440d727b6192c46b6f754723dde9 \ - --hash=sha256:bd32add59b58fba3439d48d6f36ac695830388e3da3e92e4fc26d2d02670d19c \ - --hash=sha256:bdab762e2c0b48bab76f1a08acb3f4c77afd2123bedac59446aeaaeed3d086cf \ - --hash=sha256:c5512aae4648152abaf4d48b59890503fcbe86e85abc12fb9b096fe948bdd816 \ - --hash=sha256:c6e4c10761ddbc0d67d2f6e2753daf99908db85d8b901729bf2bf5eaa60e0567 \ - --hash=sha256:cb4b3ad543084ed79f186741470b251b9d269cd8b03556f15a8d1a99a64b7de5 \ - --hash=sha256:cb74cdcbc0103fc988e04e5c58b0b31e8e5dd2babb9182b6f9490488eb36324b \ - --hash=sha256:cc3d107f603b5ee7a79b6aa6f166551b99b32fb4a5303c4dfcb4222fc6a0335e \ - --hash=sha256:d920789eca7ef71df7f31fd547ec0d3002e04d77f30ba6881e08a630e7b2c30e \ - --hash=sha256:daae5e955764be8fd70a93e9e5133c75297f8bce1e802e1d3683b98f77e1c5ab \ - --hash=sha256:db63cf3586a24241e89ca1ce0b56baaec9d371a328bd186c529b27c914c9a1ef \ - --hash=sha256:db953b675079884ffda33d1dca7189fb961b6d372153750beb81880384300817 \ - --hash=sha256:de076eaba208d16efb5962f99539867f8e2c73480988cb513fcf1b5dbb0c9dcf \ - --hash=sha256:e79dbc8f57de360f0ed987dc7de7be814b4803ef0e8fc6d3ff86e16798c99935 \ - --hash=sha256:e9a3a38eb4134ad33122a6d575e6324831f930a771d951a15ce232e0237412c2 \ - --hash=sha256:f04ca50e847abc486fa8f4107250566441e693779a5374ba211e96e238f298b9 \ - --hash=sha256:f1178e0de0c271231a660fbef9be6acdfa1d596803464706862bef6644cc1cae \ - --hash=sha256:f4617cef654fca552f00ce5ffdf4f4b68770f18950e4246ce94629b789b92467 \ - --hash=sha256:fa37f99bff354ff191c6bcdffbc9d7cdd4fc37faccfc9be0ef3a4fd5613977da +librt==0.8.1 \ + --hash=sha256:01170b6729a438f0dedc4a26ed342e3dc4f02d1000b4b19f980e1877f0c297e6 \ + --hash=sha256:039b9f2c506bd0ab0f8725aa5ba339c6f0cd19d3b514b50d134789809c24285d \ + --hash=sha256:05bd41cdee35b0c59c259f870f6da532a2c5ca57db95b5f23689fcb5c9e42440 \ + --hash=sha256:086a32dbb71336627e78cc1d6ee305a68d038ef7d4c39aaff41ae8c9aa46e91a \ + --hash=sha256:08eec3a1fc435f0d09c87b6bf1ec798986a3544f446b864e4099633a56fcd9ed \ + --hash=sha256:0bf69d79a23f4f40b8673a947a234baeeb133b5078b483b7297c5916539cf5d5 \ + --hash=sha256:0c3811485fccfda840861905b8c70bba5ec094e02825598bb9d4ca3936857a04 \ + --hash=sha256:0d2f82168e55ddefd27c01c654ce52379c0750ddc31ee86b4b266bcf4d65f2a3 \ + --hash=sha256:0f2ae3725904f7377e11cc37722d5d401e8b3d5851fb9273d7f4fe04f6b3d37d \ + --hash=sha256:10c42e1f6fd06733ef65ae7bebce2872bcafd8d6e6b0a08fe0a05a23b044fb14 \ + --hash=sha256:153188fe98a72f206042be10a2c6026139852805215ed9539186312d50a8e972 \ + --hash=sha256:172d57ec04346b047ca6af181e1ea4858086c80bdf455f61994c4aa6fc3f866c \ + --hash=sha256:190b109bb69592a3401fe1ffdea41a2e73370ace2ffdc4a0e8e2b39cdea81b78 \ + --hash=sha256:1d3a7da44baf692f0c6aeb5b2a09c5e6fc7a703bca9ffa337ddd2e2da53f7732 \ + --hash=sha256:228c2409c079f8c11fb2e5d7b277077f694cb93443eb760e00b3b83cb8b3176c \ + --hash=sha256:22b46eabd76c1986ee7d231b0765ad387d7673bbd996aa0d0d054b38ac65d8f6 \ + --hash=sha256:237796479f4d0637d6b9cbcb926ff424a97735e68ade6facf402df4ec93375ed \ + --hash=sha256:2c74a2da57a094bd48d03fa5d196da83d2815678385d2978657499063709abe1 \ + --hash=sha256:2cc68eeeef5e906839c7bb0815748b5b0a974ec27125beefc0f942715785b551 \ + --hash=sha256:2eb345e8b33fb748227409c9f1233d4df354d6e54091f0e8fc53acdb2ffedeb7 \ + --hash=sha256:31362dbfe297b23590530007062c32c6f6176f6099646bb2c95ab1b00a57c382 \ + --hash=sha256:3dff3d3ca8db20e783b1bc7de49c0a2ab0b8387f31236d6a026597d07fcd68ac \ + --hash=sha256:43353b943613c5d9c49a25aaffdba46f888ec354e71e3529a00cca3f04d66a7a \ + --hash=sha256:439352ba9373f11cb8e1933da194dcc6206daf779ff8df0ed69c5e39113e6a99 \ + --hash=sha256:4998009e7cb9e896569f4be7004f09d0ed70d386fa99d42b6d363f6d200501ac \ + --hash=sha256:4be2a5c926b9770c9e08e717f05737a269b9d0ebc5d2f0060f0fe3fe9ce47acb \ + --hash=sha256:4beb04b8c66c6ae62f8c1e0b2f097c1ebad9295c929a8d5286c05eae7c2fc7dc \ + --hash=sha256:4c8dfa264b9193c4ee19113c985c95f876fae5e51f731494fc4e0cf594990ba7 \ + --hash=sha256:5212a5bd7fae98dae95710032902edcd2ec4dc994e883294f75c857b83f9aba0 \ + --hash=sha256:52c224e14614b750c0a6d97368e16804a98c684657c7518752c356834fff83bb \ + --hash=sha256:56e04c14b696300d47b3bc5f1d10a00e86ae978886d0cee14e5714fafb5df5d2 \ + --hash=sha256:5bb54f1205a3a6ab41a6fd71dfcdcbd278670d3a90ca502a30d9da583105b6f7 \ + --hash=sha256:5cdc0f588ff4b663ea96c26d2a230c525c6fc62b28314edaaaca8ed5af931ad0 \ + --hash=sha256:5db05697c82b3a2ec53f6e72b2ed373132b0c2e05135f0696784e97d7f5d48e7 \ + --hash=sha256:5e4af413908f77294605e28cfd98063f54b2c790561383971d2f52d113d9c363 \ + --hash=sha256:5fc48998000cbc39ec0d5311312dda93ecf92b39aaf184c5e817d5d440b29624 \ + --hash=sha256:60a78b694c9aee2a0f1aaeaa7d101cf713e92e8423a941d2897f4fa37908dab9 \ + --hash=sha256:64548cde61b692dc0dc379f4b5f59a2f582c2ebe7890d09c1ae3b9e66fa015b7 \ + --hash=sha256:681dc2451d6d846794a828c16c22dc452d924e9f700a485b7ecb887a30aad1fd \ + --hash=sha256:6b1977c4ea97ce5eb7755a78fae68d87e4102e4aaf54985e8b56806849cc06a3 \ + --hash=sha256:6cfa7fe54fd4d1f47130017351a959fe5804bda7a0bc7e07a2cdbc3fdd28d34f \ + --hash=sha256:738f08021b3142c2918c03692608baed43bc51144c29e35807682f8070ee2a3a \ + --hash=sha256:747328be0c5b7075cde86a0e09d7a9196029800ba75a1689332348e998fb85c0 \ + --hash=sha256:758509ea3f1eba2a57558e7e98f4659d0ea7670bff49673b0dde18a3c7e6c0eb \ + --hash=sha256:785ae29c1f5c6e7c2cde2c7c0e148147f4503da3abc5d44d482068da5322fd9e \ + --hash=sha256:7aae78ab5e3206181780e56912d1b9bb9f90a7249ce12f0e8bf531d0462dd0fc \ + --hash=sha256:7b02679a0d783bdae30d443025b94465d8c3dc512f32f5b5031f93f57ac32071 \ + --hash=sha256:7e2f3edca35664499fbb36e4770650c4bd4a08abc1f4458eab9df4ec56389730 \ + --hash=sha256:7e6bad1cd94f6764e1e21950542f818a09316645337fd5ab9a7acc45d99a8f35 \ + --hash=sha256:81fd938344fecb9373ba1b155968c8a329491d2ce38e7ddb76f30ffb938f12dc \ + --hash=sha256:82210adabbc331dbb65d7868b105185464ef13f56f7f76688565ad79f648b0fe \ + --hash=sha256:89815a22daf9c51884fb5dbe4f1ef65ee6a146e0b6a8df05f753e2e4a9359bf4 \ + --hash=sha256:8f1125e6bbf2f1657d9a2f3ccc4a2c9b0c8b176965bb565dd4d86be67eddb4b6 \ + --hash=sha256:8f4bb453f408137d7581be309b2fbc6868a80e7ef60c88e689078ee3a296ae71 \ + --hash=sha256:924817ab3141aca17893386ee13261f1d100d1ef410d70afe4389f2359fea4f0 \ + --hash=sha256:93c2af9e01e0ef80d95ae3c720be101227edae5f2fe7e3dc63d8857fadfc5a1d \ + --hash=sha256:97c2b54ff6717a7a563b72627990bec60d8029df17df423f0ed37d56a17a176b \ + --hash=sha256:9be2f15e53ce4e83cc08adc29b26fb5978db62ef2a366fbdf716c8a6c8901040 \ + --hash=sha256:9e2c6f77b9ad48ce5603b83b7da9ee3e36b3ab425353f695cba13200c5d96596 \ + --hash=sha256:a28f2612ab566b17f3698b0da021ff9960610301607c9a5e8eaca62f5e1c350a \ + --hash=sha256:a355d99c4c0d8e5b770313b8b247411ed40949ca44e33e46a4789b9293a907ee \ + --hash=sha256:a3b4350b13cc0e6f5bec8fa7caf29a8fb8cdc051a3bae45cfbfd7ce64f009965 \ + --hash=sha256:aaab0e307e344cb28d800957ef3ec16605146ef0e59e059a60a176d19543d1b7 \ + --hash=sha256:ac1e7817fd0ed3d14fd7c5df91daed84c48e4c2a11ee99c0547f9f62fdae13da \ + --hash=sha256:adfab487facf03f0d0857b8710cf82d0704a309d8ffc33b03d9302b4c64e91a9 \ + --hash=sha256:b6d7ab1f01aa753188605b09a51faa44a3327400b00b8cce424c71910fc0a128 \ + --hash=sha256:bacdb58d9939d95cc557b4dbaa86527c9db2ac1ed76a18bc8d26f6dc8647d851 \ + --hash=sha256:be46a14693955b3bd96014ccbdb8339ee8c9346fbe11c1b78901b55125f14c73 \ + --hash=sha256:bf512a71a23504ed08103a13c941f763db13fb11177beb3d9244c98c29fb4a61 \ + --hash=sha256:c00e5c884f528c9932d278d5c9cbbea38a6b81eb62c02e06ae53751a83a4d52b \ + --hash=sha256:c25d9e338d5bed46c1632f851babf3d13c78f49a225462017cf5e11e845c5891 \ + --hash=sha256:c336d61d2fe74a3195edc1646d53ff1cddd3a9600b09fa6ab75e5514ba4862a7 \ + --hash=sha256:cc3656283d11540ab0ea01978378e73e10002145117055e03722417aeab30994 \ + --hash=sha256:cf450f498c30af55551ba4f66b9123b7185362ec8b625a773b3d39aa1a717583 \ + --hash=sha256:d0ee06b5b5291f609ddb37b9750985b27bc567791bc87c76a569b3feed8481ac \ + --hash=sha256:d480de377f5b687b6b1bc0c0407426da556e2a757633cc7e4d2e1a057aa688f3 \ + --hash=sha256:d56bc4011975f7460bea7b33e1ff425d2f1adf419935ff6707273c77f8a4ada6 \ + --hash=sha256:dd3c41254ee98604b08bd5b3af5bf0a89740d4ee0711de95b65166bf44091921 \ + --hash=sha256:e0d138c7ae532908cbb342162b2611dbd4d90c941cd25ab82084aaf71d2c0bd0 \ + --hash=sha256:e11769a1dbda4da7b00a76cfffa67aa47cfa66921d2724539eee4b9ede780b79 \ + --hash=sha256:e3f0a41487fd5fad7e760b9e8a90e251e27c2816fbc2cff36a22a0e6bcbbd9dd \ + --hash=sha256:e692aa2d1d604e6ca12d35e51fdc36f4cda6345e28e36374579f7ef3611b3012 \ + --hash=sha256:e70a57ecf89a0f64c24e37f38d3fe217a58169d2fe6ed6d70554964042474023 \ + --hash=sha256:e96baa6820280077a78244b2e06e416480ed859bbd8e5d641cf5742919d8beb4 \ + --hash=sha256:eb5656019db7c4deacf0c1a55a898c5bb8f989be904597fcb5232a2f4828fa05 \ + --hash=sha256:eca45e982fa074090057132e30585a7e8674e9e885d402eae85633e9f449ce6c \ + --hash=sha256:f0af2bd2bc204fa27f3d6711d0f360e6b8c684a035206257a81673ab924aa11e \ + --hash=sha256:f7cdf7f26c2286ffb02e46d7bac56c94655540b26347673bea15fa52a6af17e9 \ + --hash=sha256:fd1a720332ea335ceb544cf0a03f81df92abd4bb887679fd1e460976b0e6214b \ + --hash=sha256:ff8baf1f8d3f4b6b7257fcb75a501f2a5499d0dda57645baa09d4d0d34b19444 # via mypy markupsafe==3.0.3 \ --hash=sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f \ @@ -509,21 +509,21 @@ markupsafe==3.0.3 \ --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \ --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50 # via jinja2 -maturin==1.12.2 \ - --hash=sha256:04c9c4f9c9f904f007cbfcd4640c406e53f19d04c220f5940d1537edb914d325 \ - --hash=sha256:0ed31b6a392928ad23645a470edc4f3814b952a416e41f8e5daac42d7bfbabc6 \ - --hash=sha256:134e895578258a693ba1d55b166c2ba96e9f51067e106b8a74d422432653d45b \ - --hash=sha256:39665d622dcc950ab17b9569e8cab84a4d64eea6a18b540a8b49e00c0f7dda02 \ - --hash=sha256:4bdc486b9ab80d8b50143ecc9a1924b890866fe95be150dd9a59fa22a6b37238 \ - --hash=sha256:6af778e7ee048612e55a1255488db7678741bea2ba881e66a19712f59f2534cb \ - --hash=sha256:72aad9efe09a6392de9930f2bea80bfcc36fd98e18caa621f512571179c02d41 \ - --hash=sha256:9763d277e143409cf0ce309eb1a493fc4e1e75777364d67ccac39a161b51b5b0 \ - --hash=sha256:a882cc80c241b1e2c27bd1acd713b09e9ac9266a3159cc1e34e8c7b77f049bba \ - --hash=sha256:c06d218931985035d7ab4d0211ba96027e1bc7e4b01a87c8c4e30a57790403ec \ - --hash=sha256:ca3b20bcc3aff115c9eaf97340e78bff58829ea1efa16764940dd0d858dcf6af \ - --hash=sha256:d1617989b4a5dc543fea6d23c28b2f07fadb2c726ff00fe959538ee71a301384 \ - --hash=sha256:d6253079f53dbb692395a13abddc0f2d3d96af32f8c0b32e2912849713c55794 \ - --hash=sha256:f1c2e4ee43bf286b052091a3b2356a157978985837c7aed42354deb2947a4006 +maturin==1.12.6 \ + --hash=sha256:06fc8d089f98623ce924c669b70911dfed30f9a29956c362945f727f9abc546b \ + --hash=sha256:2cb41139295eed6411d3cdafc7430738094c2721f34b7eeb44f33cac516115dc \ + --hash=sha256:351f3af1488a7cbdcff3b6d8482c17164273ac981378a13a4a9937a49aec7d71 \ + --hash=sha256:3f32e0a3720b81423c9d35c14e728cb1f954678124749776dc72d533ea1115e8 \ + --hash=sha256:6892b4176992fcc143f9d1c1c874a816e9a041248eef46433db87b0f0aff4278 \ + --hash=sha256:6dbddfe4dc7ddee60bbac854870bd7cfec660acb54d015d24597d59a1c828f61 \ + --hash=sha256:75133e56274d43b9227fd49dca9a86e32f1fd56a7b55544910c4ce978c2bb5aa \ + --hash=sha256:8fdb0f63e77ee3df0f027a120e9af78dbc31edf0eb0f263d55783c250c33b728 \ + --hash=sha256:977290159d252db946054a0555263c59b3d0c7957135c69e690f4b1558ee9983 \ + --hash=sha256:bae91976cdc8148038e13c881e1e844e5c63e58e026e8b9945aa2d19b3b4ae89 \ + --hash=sha256:c0c742beeeef7fb93b6a81bd53e75507887e396fd1003c45117658d063812dad \ + --hash=sha256:d37be3a811a7f2ee28a0fa0964187efa50e90f21da0c6135c27787fa0b6a89db \ + --hash=sha256:e90dc12bc6a38e9495692a36c9e231c4d7e0c9bfde60719468ab7d8673db3c45 \ + --hash=sha256:fa84b7493a2e80759cacc2e668fa5b444d55b9994e90707c42904f55d6322c1e # via # cryptography # pydantic-core @@ -547,79 +547,79 @@ mypy-extensions==1.1.0 \ --hash=sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505 \ --hash=sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558 # via mypy -numpy==2.4.2 \ - --hash=sha256:00ab83c56211a1d7c07c25e3217ea6695e50a3e2f255053686b081dc0b091a82 \ - --hash=sha256:068cdb2d0d644cdb45670810894f6a0600797a69c05f1ac478e8d31670b8ee75 \ - --hash=sha256:0f01dcf33e73d80bd8dc0f20a71303abbafa26a19e23f6b68d1aa9990af90257 \ - --hash=sha256:0fece1d1f0a89c16b03442eae5c56dc0be0c7883b5d388e0c03f53019a4bfd71 \ - --hash=sha256:12e26134a0331d8dbd9351620f037ec470b7c75929cb8a1537f6bfe411152a1a \ - --hash=sha256:1ae241bbfc6ae276f94a170b14785e561cb5e7f626b6688cf076af4110887413 \ - --hash=sha256:1f92f53998a17265194018d1cc321b2e96e900ca52d54c7c77837b71b9465181 \ - --hash=sha256:209fae046e62d0ce6435fcfe3b1a10537e858249b3d9b05829e2a05218296a85 \ - --hash=sha256:20abd069b9cda45874498b245c8015b18ace6de8546bf50dfa8cea1696ed06ef \ - --hash=sha256:21982668592194c609de53ba4933a7471880ccbaadcc52352694a59ecc860b3a \ - --hash=sha256:25f2059807faea4b077a2b6837391b5d830864b3543627f381821c646f31a63c \ - --hash=sha256:2653de5c24910e49c2b106499803124dde62a5a1fe0eedeaecf4309a5f639390 \ - --hash=sha256:2b8f157c8a6f20eb657e240f8985cc135598b2b46985c5bccbde7616dc9c6b1e \ - --hash=sha256:2fb882da679409066b4603579619341c6d6898fc83a8995199d5249f986e8e8f \ - --hash=sha256:40397bda92382fcec844066efb11f13e1c9a3e2a8e8f318fb72ed8b6db9f60f1 \ - --hash=sha256:444be170853f1f9d528428eceb55f12918e4fda5d8805480f36a002f1415e09b \ - --hash=sha256:47c5a6ed21d9452b10227e5e8a0e1c22979811cad7dcc19d8e3e2fb8fa03f1a3 \ - --hash=sha256:4f069069931240b3fc703f1e23df63443dbd6390614c8c44a87d96cd0ec81eb1 \ - --hash=sha256:52b913ec40ff7ae845687b0b34d8d93b60cb66dcee06996dd5c99f2fc9328657 \ - --hash=sha256:5633c0da313330fd20c484c78cdd3f9b175b55e1a766c4a174230c6b70ad8262 \ - --hash=sha256:5daf6f3914a733336dab21a05cdec343144600e964d2fcdabaac0c0269874b2a \ - --hash=sha256:5eea80d908b2c1f91486eb95b3fb6fab187e569ec9752ab7d9333d2e66bf2d6b \ - --hash=sha256:602f65afdef699cda27ec0b9224ae5dc43e328f4c24c689deaf77133dbee74d0 \ - --hash=sha256:659a6107e31a83c4e33f763942275fd278b21d095094044eb35569e86a21ddae \ - --hash=sha256:66cb9422236317f9d44b67b4d18f44efe6e9c7f8794ac0462978513359461554 \ - --hash=sha256:6d82351358ffbcdcd7b686b90742a9b86632d6c1c051016484fa0b326a0a1548 \ - --hash=sha256:6e9f61981ace1360e42737e2bae58b27bf28a1b27e781721047d84bd754d32e7 \ - --hash=sha256:6ed0be1ee58eef41231a5c943d7d1375f093142702d5723ca2eb07db9b934b05 \ - --hash=sha256:7cdde6de52fb6664b00b056341265441192d1291c130e99183ec0d4b110ff8b1 \ - --hash=sha256:7df2de1e4fba69a51c06c28f5a3de36731eb9639feb8e1cf7e4a7b0daf4cf622 \ - --hash=sha256:7edc794af8b36ca37ef5fcb5e0d128c7e0595c7b96a2318d1badb6fcd8ee86b1 \ - --hash=sha256:7f54844851cdb630ceb623dcec4db3240d1ac13d4990532446761baede94996a \ - --hash=sha256:805cc8de9fd6e7a22da5aed858e0ab16be5a4db6c873dde1d7451c541553aa27 \ - --hash=sha256:8906e71fd8afcb76580404e2a950caef2685df3d2a57fe82a86ac8d33cc007ba \ - --hash=sha256:89f7268c009bc492f506abd6f5265defa7cb3f7487dc21d357c3d290add45082 \ - --hash=sha256:8c50dd1fc8826f5b26a5ee4d77ca55d88a895f4e4819c7ecc2a9f5905047a443 \ - --hash=sha256:8e4549f8a3c6d13d55041925e912bfd834285ef1dd64d6bc7d542583355e2e98 \ - --hash=sha256:8e9afaeb0beff068b4d9cd20d322ba0ee1cecfb0b08db145e4ab4dd44a6b5110 \ - --hash=sha256:98f16a80e917003a12c0580f97b5f875853ebc33e2eaa4bccfc8201ac6869308 \ - --hash=sha256:9e35d3e0144137d9fdae62912e869136164534d64a169f86438bc9561b6ad49f \ - --hash=sha256:9e4424677ce4b47fe73c8b5556d876571f7c6945d264201180db2dc34f676ab5 \ - --hash=sha256:adb6ed2ad29b9e15321d167d152ee909ec73395901b70936f029c3bc6d7f4460 \ - --hash=sha256:aea4f66ff44dfddf8c2cffd66ba6538c5ec67d389285292fe428cb2c738c8aef \ - --hash=sha256:b21041e8cb6a1eb5312dd1d2f80a94d91efffb7a06b70597d44f1bd2dfc315ab \ - --hash=sha256:b2f0073ed0868db1dcd86e052d37279eef185b9c8db5bf61f30f46adac63c909 \ - --hash=sha256:b3a24467af63c67829bfaa61eecf18d5432d4f11992688537be59ecd6ad32f5e \ - --hash=sha256:b9c618d56a29c9cb1c4da979e9899be7578d2e0b3c24d52079c166324c9e8695 \ - --hash=sha256:bba37bc29d4d85761deed3954a1bc62be7cf462b9510b51d367b769a8c8df325 \ - --hash=sha256:bd3a7a9f5847d2fb8c2c6d1c862fa109c31a9abeca1a3c2bd5a64572955b2979 \ - --hash=sha256:be71bf1edb48ebbbf7f6337b5bfd2f895d1902f6335a5830b20141fc126ffba0 \ - --hash=sha256:c02ef4401a506fb60b411467ad501e1429a3487abca4664871d9ae0b46c8ba32 \ - --hash=sha256:c3cd545784805de05aafe1dde61752ea49a359ccba9760c1e5d1c88a93bbf2b7 \ - --hash=sha256:c7ac672d699bf36275c035e16b65539931347d68b70667d28984c9fb34e07fa7 \ - --hash=sha256:cb7bbb88aa74908950d979eeaa24dbdf1a865e3c7e45ff0121d8f70387b55f73 \ - --hash=sha256:cd2bd2bbed13e213d6b55dc1d035a4f91748a7d3edc9480c13898b0353708920 \ - --hash=sha256:cda077c2e5b780200b6b3e09d0b42205a3d1c68f30c6dceb90401c13bff8fe74 \ - --hash=sha256:cf28c0c1d4c4bf00f509fa7eb02c58d7caf221b50b467bcb0d9bbf1584d5c821 \ - --hash=sha256:d0d9b7c93578baafcbc5f0b83eaf17b79d345c6f36917ba0c67f45226911d499 \ - --hash=sha256:d1240d50adff70c2a88217698ca844723068533f3f5c5fa6ee2e3220e3bdb000 \ - --hash=sha256:d30291931c915b2ab5717c2974bb95ee891a1cf22ebc16a8006bd59cd210d40a \ - --hash=sha256:d9f64d786b3b1dd742c946c42d15b07497ed14af1a1f3ce840cce27daa0ce913 \ - --hash=sha256:da6cad4e82cb893db4b69105c604d805e0c3ce11501a55b5e9f9083b47d2ffe8 \ - --hash=sha256:df1b10187212b198dd45fa943d8985a3c8cf854aed4923796e0e019e113a1bda \ - --hash=sha256:e04ae107ac591763a47398bb45b568fc38f02dbc4aa44c063f67a131f99346cb \ - --hash=sha256:e6dee3bb76aa4009d5a912180bf5b2de012532998d094acee25d9cb8dee3e44a \ - --hash=sha256:e7e88598032542bd49af7c4747541422884219056c268823ef6e5e89851c8825 \ - --hash=sha256:e98c97502435b53741540a5717a6749ac2ada901056c7db951d33e11c885cc7d \ - --hash=sha256:ec055f6dae239a6299cace477b479cca2fc125c5675482daf1dd886933a1076f \ - --hash=sha256:f74f0f7779cc7ae07d1810aab8ac6b1464c3eafb9e283a40da7309d5e6e48fbb \ - --hash=sha256:fbde1b0c6e81d56f5dccd95dd4a711d9b95df1ae4009a60887e56b27e8d903fa \ - --hash=sha256:fcf92bee92742edd401ba41135185866f7026c502617f422eb432cfeca4fe236 \ - --hash=sha256:fd49860271d52127d61197bb50b64f58454e9f578cb4b2c001a6de8b1f50b0b1 +numpy==2.4.4 \ + --hash=sha256:07077278157d02f65c43b1b26a3886bce886f95d20aabd11f87932750dfb14ed \ + --hash=sha256:08f2e31ed5e6f04b118e49821397f12767934cfdd12a1ce86a058f91e004ee50 \ + --hash=sha256:0aec54fd785890ecca25a6003fd9a5aed47ad607bbac5cd64f836ad8666f4959 \ + --hash=sha256:0d35aea54ad1d420c812bfa0385c71cd7cc5bcf7c65fed95fc2cd02fe8c79827 \ + --hash=sha256:0d4e437e295f18ec29bc79daf55e8a47a9113df44d66f702f02a293d93a2d6dd \ + --hash=sha256:0dfd3f9d3adbe2920b68b5cd3d51444e13a10792ec7154cd0a2f6e74d4ab3233 \ + --hash=sha256:1378871da56ca8943c2ba674530924bb8ca40cd228358a3b5f302ad60cf875fc \ + --hash=sha256:15716cfef24d3a9762e3acdf87e27f58dc823d1348f765bbea6bef8c639bfa1b \ + --hash=sha256:19710a9ca9992d7174e9c52f643d4272dcd1558c5f7af7f6f8190f633bd651a7 \ + --hash=sha256:23cbfd4c17357c81021f21540da84ee282b9c8fba38a03b7b9d09ba6b951421e \ + --hash=sha256:2483e4584a1cb3092da4470b38866634bafb223cbcd551ee047633fd2584599a \ + --hash=sha256:27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d \ + --hash=sha256:28a650663f7314afc3e6ec620f44f333c386aad9f6fc472030865dc0ebb26ee3 \ + --hash=sha256:2aa0613a5177c264ff5921051a5719d20095ea586ca88cc802c5c218d1c67d3e \ + --hash=sha256:2c194dd721e54ecad9ad387c1d35e63dce5c4450c6dc7dd5611283dda239aabb \ + --hash=sha256:2d19e6e2095506d1736b7d80595e0f252d76b89f5e715c35e06e937679ea7d7a \ + --hash=sha256:2d390634c5182175533585cc89f3608a4682ccb173cc9bb940b2881c8d6f8fa0 \ + --hash=sha256:30caa73029a225b2d40d9fae193e008e24b2026b7ee1a867b7ee8d96ca1a448e \ + --hash=sha256:42c16925aa5a02362f986765f9ebabf20de75cdefdca827d14315c568dcab113 \ + --hash=sha256:45dbed2ab436a9e826e302fcdcbe9133f9b0006e5af7168afb8963a6520da103 \ + --hash=sha256:4636de7fd195197b7535f231b5de9e4b36d2c440b6e566d2e4e4746e6af0ca93 \ + --hash=sha256:4a19d9dba1a76618dd86b164d608566f393f8ec6ac7c44f0cc879011c45e65af \ + --hash=sha256:4bbc7f303d125971f60ec0aaad5e12c62d0d2c925f0ab1273debd0e4ba37aba5 \ + --hash=sha256:4d6d57903571f86180eb98f8f0c839fa9ebbfb031356d87f1361be91e433f5b7 \ + --hash=sha256:4e874c976154687c1f71715b034739b45c7711bec81db01914770373d125e392 \ + --hash=sha256:51fc224f7ca4d92656d5a5eb315f12eb5fe2c97a66249aa7b5f562528a3be38c \ + --hash=sha256:58c8b5929fcb8287cbd6f0a3fae19c6e03a5c48402ae792962ac465224a629a4 \ + --hash=sha256:5a285b3b96f951841799528cd1f4f01cd70e7e0204b4abebac9463eecfcf2a40 \ + --hash=sha256:5c70f1cc1c4efbe316a572e2d8b9b9cc44e89b95f79ca3331553fbb63716e2bf \ + --hash=sha256:62d6b0f03b694173f9fcb1fb317f7222fd0b0b103e784c6549f5e53a27718c44 \ + --hash=sha256:6a246d5914aa1c820c9443ddcee9c02bec3e203b0c080349533fae17727dfd1b \ + --hash=sha256:6aa3236c78803afbcb255045fbef97a9e25a1f6c9888357d205ddc42f4d6eba5 \ + --hash=sha256:6bbe4eb67390b0a0265a2c25458f6b90a409d5d069f1041e6aff1e27e3d9a79e \ + --hash=sha256:715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74 \ + --hash=sha256:72944b19f2324114e9dc86a159787333b77874143efcf89a5167ef83cfee8af0 \ + --hash=sha256:81f4a14bee47aec54f883e0cad2d73986640c1590eb9bfaaba7ad17394481e6e \ + --hash=sha256:846300f379b5b12cc769334464656bc882e0735d27d9726568bc932fdc49d5ec \ + --hash=sha256:86b6f55f5a352b48d7fbfd2dbc3d5b780b2d79f4d3c121f33eb6efb22e9a2015 \ + --hash=sha256:874f200b2a981c647340f841730fc3a2b54c9d940566a3c4149099591e2c4c3d \ + --hash=sha256:8a87ec22c87be071b6bdbd27920b129b94f2fc964358ce38f3822635a3e2e03d \ + --hash=sha256:8b3b60bb7cba2c8c81837661c488637eee696f59a877788a396d33150c35d842 \ + --hash=sha256:8e3ed142f2728df44263aaf5fb1f5b0b99f4070c553a0d7f033be65338329150 \ + --hash=sha256:93e15038125dc1e5345d9b5b68aa7f996ec33b98118d18c6ca0d0b7d6198b7e8 \ + --hash=sha256:989824e9faf85f96ec9c7761cd8d29c531ad857bfa1daa930cba85baaecf1a9a \ + --hash=sha256:99d838547ace2c4aace6c4f76e879ddfe02bb58a80c1549928477862b7a6d6ed \ + --hash=sha256:9b2aec6af35c113b05695ebb5749a787acd63cafc83086a05771d1e1cd1e555f \ + --hash=sha256:9c585a1790d5436a5374bac930dad6ed244c046ed91b2b2a3634eb2971d21008 \ + --hash=sha256:a7164afb23be6e37ad90b2f10426149fd75aee07ca55653d2aa41e66c4ef697e \ + --hash=sha256:ac6b31e35612a26483e20750126d30d0941f949426974cace8e6b5c58a3657b0 \ + --hash=sha256:ad2e2ef14e0b04e544ea2fa0a36463f847f113d314aa02e5b402fdf910ef309e \ + --hash=sha256:b268594bccac7d7cf5844c7732e3f20c50921d94e36d7ec9b79e9857694b1b2f \ + --hash=sha256:b5f0362dc928a6ecd9db58868fca5e48485205e3855957bdedea308f8672ea4a \ + --hash=sha256:ba1f4fc670ed79f876f70082eff4f9583c15fb9a4b89d6188412de4d18ae2f40 \ + --hash=sha256:ba203255017337d39f89bdd58417f03c4426f12beed0440cfd933cb15f8669c7 \ + --hash=sha256:c901b15172510173f5cb310eae652908340f8dede90fff9e3bf6c0d8dfd92f83 \ + --hash=sha256:c9b39d38a9bd2ae1becd7eac1303d031c5c110ad31f2b319c6e7d98b135c934d \ + --hash=sha256:d2a8490669bfe99a233298348acc2d824d496dee0e66e31b66a6022c2ad74a5c \ + --hash=sha256:dddbbd259598d7240b18c9d87c56a9d2fb3b02fe266f49a7c101532e78c1d871 \ + --hash=sha256:df3775294accfdd75f32c74ae39fcba920c9a378a2fc18a12b6820aa8c1fb502 \ + --hash=sha256:e44319a2953c738205bf3354537979eaa3998ed673395b964c1176083dd46252 \ + --hash=sha256:e4a010c27ff6f210ff4c6ef34394cd61470d01014439b192ec22552ee867f2a8 \ + --hash=sha256:e823b8b6edc81e747526f70f71a9c0a07ac4e7ad13020aa736bb7c9d67196115 \ + --hash=sha256:e892aff75639bbef0d2a2cfd55535510df26ff92f63c92cd84ef8d4ba5a5557f \ + --hash=sha256:eea7ac5d2dce4189771cedb559c738a71512768210dc4e4753b107a2048b3d0e \ + --hash=sha256:ef4059d6e5152fa1a39f888e344c73fdc926e1b2dd58c771d67b0acfbf2aa67d \ + --hash=sha256:f169b9a863d34f5d11b8698ead99febeaa17a13ca044961aa8e2662a6c7766a0 \ + --hash=sha256:f2cf083b324a467e1ab358c105f6cad5ea950f50524668a80c486ff1db24e119 \ + --hash=sha256:f8474c4241bc18b750be2abea9d7a9ec84f46ef861dbacf86a4f6e043401f79e \ + --hash=sha256:f983334aea213c99992053ede6168500e5f086ce74fbc4acc3f2b00f5762e9db \ + --hash=sha256:f9e75681b59ddaa5e659898085ae0eaea229d054f2ac0c7e563a62205a700121 \ + --hash=sha256:fbc356aae7adf9e6336d336b9c8111d390a05df88f1805573ebb0807bd06fd1d \ + --hash=sha256:fcfe2045fd2e8f3cb0ce9d4ba6dba6333b8fa05bb8a4939c908cd43322d14c7e # via # pandas # pyarrow @@ -633,6 +633,7 @@ packaging==26.0 \ # scikit-build-core # setuptools-git-versioning # setuptools-scm + # vcs-versioning # wheel pathspec==1.0.4 \ --hash=sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645 \ @@ -641,38 +642,37 @@ pathspec==1.0.4 \ # hatchling # mypy # scikit-build-core -pdm-backend==2.4.7 \ - --hash=sha256:1599e3afa6f229b30cb4d3bd9caeca42229c42eb5730abd13e0b5256ec93c9f7 \ - --hash=sha256:a509d083850378ce919d41e7a2faddfc57a1764d376913c66731125d6b14110f +pdm-backend==2.4.8 \ + --hash=sha256:502a395859587b4f47ba36aded330aeda410da8d33751a56cb97c8c679276f8f \ + --hash=sha256:d8ef85d2c4306ee67195412d701fae9983e84ec6574598e26798ae26b7b3c7e0 # via # annotated-doc # fastapi # typer -pkgconfig==1.5.5 \ - --hash=sha256:d20023bbeb42ee6d428a0fac6e0904631f545985a10cdd71a20aa58bc47a4209 \ - --hash=sha256:deb4163ef11f75b520d822d9505c1f462761b4309b1bb713d08689759ea8b899 +pkgconfig==1.6.0 \ + --hash=sha256:4a5a6631ce937fafac457104a40d558785a658bbdca5c49b6295bc3fd651907f \ + --hash=sha256:98e71754855e9563838d952a160eb577edabb57782e49853edb5381927e6bea1 # via aiohttp pluggy==1.6.0 \ --hash=sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3 \ --hash=sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746 # via hatchling -poetry-core==2.3.1 \ - --hash=sha256:96f791d5d7d4e040f3983d76779425cf9532690e2756a24fd5ca0f86af19ef82 \ - --hash=sha256:db1cf63b782570deb38bfba61e2304a553eef0740dc17959a50cc0f5115ee634 +poetry-core==2.3.2 \ + --hash=sha256:20cb71be27b774628da9f384effd9183dfceb53bcef84063248a8672aa47031f \ + --hash=sha256:23df641b64f87fbb4ce1873c1915a4d4bb1b7d808c596e4307edc073e68d7234 # via # aiohappyeyeballs # dunamai # pkgconfig # rich - # rsa # tomlkit -pybind11-global==3.0.1 \ - --hash=sha256:0e8d5a68d084c50bf145ce5efdbdd00704dbe6315035d0b7a255708ddeb9faca \ - --hash=sha256:eb6ef4e8f5a60f4c0b6a9396cb7806f78d42f8d081e42a93c0bb62288f6cf403 +pybind11-global==3.0.3 \ + --hash=sha256:141adb150fdb84f6eba3e27241da886f4582574a3d1c30568bf33c1ed3ec8b82 \ + --hash=sha256:7a75ee81e903ea15bdf05db1342c37400751a72316b6620c800b66d70be45632 # via pybind11 -pybind11==3.0.1 \ - --hash=sha256:9c0f40056a016da59bab516efb523089139fcc6f2ba7e4930854c61efb932051 \ - --hash=sha256:aa8f0aa6e0a94d3b64adfc38f560f33f15e589be2175e103c0a33c6bce55ee89 +pybind11==3.0.3 \ + --hash=sha256:00471cdb816882c484708bc5dde80815c8c11cea540ab2cc6410f5ddea434755 \ + --hash=sha256:fb5f8e4a64946b4dcc0451c83a8c384f803bc0a62dd1ba02f199e97dbc9aad4c # via duckdb pycparser==3.0 \ --hash=sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29 \ @@ -682,9 +682,9 @@ pyproject-metadata==0.11.0 \ --hash=sha256:85bbecca8694e2c00f63b492c96921d6c228454057c88e7c352b2077fcaa4096 \ --hash=sha256:c72fa49418bb7c5a10f25e050c418009898d1c051721d19f98a6fb6da59a66cf # via meson-python -scikit-build-core==0.11.6 \ - --hash=sha256:5982ccd839735be99cfd3b92a8847c6c196692f476c215da84b79d2ad12f9f1b \ - --hash=sha256:ce6d8fe64e6b4c759ea0fb95d2f8a68f60d2df31c2989838633b8ec930736360 +scikit-build-core==0.12.2 \ + --hash=sha256:562e0bbc9de1a354c87825ccf732080268d6582a0200f648e8c4a2dcb1e3736d \ + --hash=sha256:6ea4730da400f9a998ec3287bd3ebc1d751fe45ad0a93451bead8618adbc02b1 # via # duckdb # patchelf @@ -698,17 +698,13 @@ setuptools-git-versioning==3.0.1 \ --hash=sha256:737c4d17e848edd46e28764a19dc424d8537fcb2257022e5f4f5c0c8e9b64c80 \ --hash=sha256:c8a599bacf163b5d215552b5701faf5480ffc4d65426a5711a010b802e1590eb # via toolz -setuptools-rust==1.12.0 \ - --hash=sha256:7e7db90547f224a835b45f5ad90c983340828a345554a9a660bdb2de8605dcdd \ - --hash=sha256:d94a93f0c97751c17014565f07bdc324bee45d396cd1bba83d8e7af92b945f0c +setuptools-rust==1.12.1 \ + --hash=sha256:85ae70989d96c9cfeb5ef79cf3bac2d5200bc5564f720a06edceedbdf6664640 \ + --hash=sha256:b7ebd6a182e7aefa97a072e880530c9b0ec8fcca8617e0bb8ff299c1a064f693 # via maturin -setuptools-scm==7.1.0 \ - --hash=sha256:6c508345a771aad7d56ebff0e70628bf2b0ec7573762be9960214730de278f27 \ - --hash=sha256:73988b6d848709e2af142aa48c986ea29592bbcfca5375678064708205253d8e - # via python-dateutil -setuptools-scm==9.2.2 \ - --hash=sha256:1c674ab4665686a0887d7e24c03ab25f24201c213e82ea689d2f3e169ef7ef57 \ - --hash=sha256:30e8f84d2ab1ba7cb0e653429b179395d0c33775d54807fc5f1dd6671801aef7 +setuptools-scm==10.0.5 \ + --hash=sha256:bbba8fe754516cdefd017f4456721775e6ef9662bd7887fb52ae26813d4838c3 \ + --hash=sha256:f611037d8aae618221503b8fa89319f073438252ae3420e01c9ceec249131a0a # via # anyio # dask @@ -727,60 +723,69 @@ setuptools-scm==9.2.2 \ # tqdm # typeguard # ujson - # urllib3 # zipp -smmap==5.0.2 \ - --hash=sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5 \ - --hash=sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e +setuptools-scm==7.1.0 \ + --hash=sha256:6c508345a771aad7d56ebff0e70628bf2b0ec7573762be9960214730de278f27 \ + --hash=sha256:73988b6d848709e2af142aa48c986ea29592bbcfca5375678064708205253d8e + # via python-dateutil +setuptools-scm==9.2.2 \ + --hash=sha256:1c674ab4665686a0887d7e24c03ab25f24201c213e82ea689d2f3e169ef7ef57 \ + --hash=sha256:30e8f84d2ab1ba7cb0e653429b179395d0c33775d54807fc5f1dd6671801aef7 + # via + # hatch-vcs + # urllib3 +smmap==5.0.3 \ + --hash=sha256:4d9debb8b99007ae47165abc08670bd74cb74b5227dda7f643eccc4e9eb5642c \ + --hash=sha256:c106e05d5a61449cf6ba9a1e650227ecfb141590d2a98412103ff35d89fc7b2f # via gitdb -tomli==2.4.0 \ - --hash=sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729 \ - --hash=sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b \ - --hash=sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d \ - --hash=sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df \ - --hash=sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576 \ - --hash=sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d \ - --hash=sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1 \ - --hash=sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a \ - --hash=sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e \ - --hash=sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc \ - --hash=sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702 \ - --hash=sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6 \ - --hash=sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd \ - --hash=sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4 \ - --hash=sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776 \ - --hash=sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a \ - --hash=sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66 \ - --hash=sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87 \ - --hash=sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2 \ - --hash=sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f \ - --hash=sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475 \ - --hash=sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f \ - --hash=sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95 \ - --hash=sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9 \ - --hash=sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3 \ - --hash=sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9 \ - --hash=sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76 \ - --hash=sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da \ - --hash=sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8 \ - --hash=sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51 \ - --hash=sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86 \ - --hash=sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8 \ - --hash=sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0 \ - --hash=sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b \ - --hash=sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1 \ - --hash=sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e \ - --hash=sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d \ - --hash=sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c \ - --hash=sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867 \ - --hash=sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a \ - --hash=sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c \ - --hash=sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0 \ - --hash=sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4 \ - --hash=sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614 \ - --hash=sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132 \ - --hash=sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa \ - --hash=sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087 +tomli==2.4.1 \ + --hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \ + --hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \ + --hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \ + --hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \ + --hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \ + --hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \ + --hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \ + --hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \ + --hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \ + --hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \ + --hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \ + --hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \ + --hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \ + --hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \ + --hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \ + --hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \ + --hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \ + --hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \ + --hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \ + --hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \ + --hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \ + --hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \ + --hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \ + --hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \ + --hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \ + --hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \ + --hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \ + --hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \ + --hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \ + --hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \ + --hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \ + --hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \ + --hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \ + --hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \ + --hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \ + --hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \ + --hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \ + --hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \ + --hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \ + --hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \ + --hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \ + --hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \ + --hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \ + --hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \ + --hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \ + --hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \ + --hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049 # via fastapi-mcp tomlkit==0.14.0 \ --hash=sha256:592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680 \ @@ -794,9 +799,9 @@ types-psutil==7.0.0.20250218 \ --hash=sha256:1447a30c282aafefcf8941ece854e1100eee7b0296a9d9be9977292f0269b121 \ --hash=sha256:1e642cdafe837b240295b23b1cbd4691d80b08a07d29932143cbbae30eb0db9c # via mypy -types-setuptools==82.0.0.20260210 \ - --hash=sha256:5124a7daf67f195c6054e0f00f1d97c69caad12fdcf9113eba33eff0bce8cd2b \ - --hash=sha256:d9719fbbeb185254480ade1f25327c4654f8c00efda3fec36823379cebcdee58 +types-setuptools==82.0.0.20260402 \ + --hash=sha256:4b9a9f6c3c4c65107a3956ad6a6acbccec38e398ff6d5f78d5df7f103dadb8d6 \ + --hash=sha256:63d2b10ba7958396ad79bbc24d2f6311484e452daad4637ffd40407983a27069 # via mypy typing-extensions==4.15.0 \ --hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \ @@ -804,10 +809,14 @@ typing-extensions==4.15.0 \ # via # mypy # setuptools-scm -uv-dynamic-versioning==0.13.0 \ - --hash=sha256:3220cbf10987d862d78e9931957782a274fa438d33efb1fa26b8155353749e06 \ - --hash=sha256:86d37b89fa2b6836a515301f74ea2d56a1bc59a46a74d66a24c869d1fc8f7585 +uv-dynamic-versioning==0.14.0 \ + --hash=sha256:574fbc07e87ace45c01d55967ad3b864871257b98ff5b8ac87c261227ac8db5b \ + --hash=sha256:e087c346a786e98d41292ac2315180fb700cedfb30565fc973d64ce11a112387 # via mcp +vcs-versioning==1.1.1 \ + --hash=sha256:b541e2ba79fc6aaa3850f8a7f88af43d97c1c80649c01142ee4146eddbc599e4 \ + --hash=sha256:fabd75a3cab7dd8ac02fe24a3a9ba936bf258667b5a62ed468c9a1da0f5775bc + # via setuptools-scm versioneer==0.29 \ --hash=sha256:0f1a137bb5d6811e96a79bb0486798aeae9b9c6efc24b389659cebb0ee396cb9 \ --hash=sha256:5ab283b9857211d61b53318b7c792cf68e798e765ee17c27ade9f6c924235731 @@ -833,7 +842,6 @@ wheel==0.46.3 \ # setuptools-git-versioning # shellingham # snowflake-connector-python - # tabulate # tzdata # uvloop @@ -892,6 +900,7 @@ setuptools==80.10.2 \ # pymysql # python-dotenv # pyyaml + # requests # setuptools-git-versioning # setuptools-rust # setuptools-scm @@ -907,9 +916,10 @@ setuptools==80.10.2 \ # trove-classifiers # typeguard # types-pymysql - # types-setuptools # tzdata + # ujson # uvloop + # vcs-versioning # versioneer # websockets # wrapt @@ -919,10 +929,9 @@ setuptools==80.9.0 \ --hash=sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922 \ --hash=sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c # via httptools -setuptools==82.0.0 \ - --hash=sha256:22e0a2d69474c6ae4feb01951cb69d515ed23728cf96d05513d36e42b62b37cb \ - --hash=sha256:70b18734b607bd1da571d097d236cfcfacaf01de45717d59e6e04b96877532e0 +setuptools==82.0.1 \ + --hash=sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9 \ + --hash=sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb # via # python-dateutil - # setuptools-scm - # ujson + # types-setuptools diff --git a/sdk/python/requirements/py3.11-minimal-sdist-requirements.txt b/sdk/python/requirements/py3.11-minimal-sdist-requirements.txt index c77e5c1b558..34cda10c5fb 100644 --- a/sdk/python/requirements/py3.11-minimal-sdist-requirements.txt +++ b/sdk/python/requirements/py3.11-minimal-sdist-requirements.txt @@ -8,127 +8,127 @@ aiohappyeyeballs==2.6.1 \ --hash=sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558 \ --hash=sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8 # via aiohttp -aiohttp==3.13.3 \ - --hash=sha256:01ad2529d4b5035578f5081606a465f3b814c542882804e2e8cda61adf5c71bf \ - --hash=sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c \ - --hash=sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c \ - --hash=sha256:084911a532763e9d3dd95adf78a78f4096cd5f58cdc18e6fdbc1b58417a45423 \ - --hash=sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f \ - --hash=sha256:0db318f7a6f065d84cb1e02662c526294450b314a02bd9e2a8e67f0d8564ce40 \ - --hash=sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2 \ - --hash=sha256:1449ceddcdbcf2e0446957863af03ebaaa03f94c090f945411b61269e2cb5daf \ - --hash=sha256:147e422fd1223005c22b4fe080f5d93ced44460f5f9c105406b753612b587821 \ - --hash=sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64 \ - --hash=sha256:215a685b6fbbfcf71dfe96e3eba7a6f58f10da1dfdf4889c7dd856abe430dca7 \ - --hash=sha256:2712039939ec963c237286113c68dbad80a82a4281543f3abf766d9d73228998 \ - --hash=sha256:27234ef6d85c914f9efeb77ff616dbf4ad2380be0cda40b4db086ffc7ddd1b7d \ - --hash=sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea \ - --hash=sha256:2b8d8ddba8f95ba17582226f80e2de99c7a7948e66490ef8d947e272a93e9463 \ - --hash=sha256:2ba0eea45eb5cc3172dbfc497c066f19c41bac70963ea1a67d51fc92e4cf9a80 \ - --hash=sha256:2be0e9ccf23e8a94f6f0650ce06042cefc6ac703d0d7ab6c7a917289f2539ad4 \ - --hash=sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767 \ - --hash=sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43 \ - --hash=sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592 \ - --hash=sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a \ - --hash=sha256:31a83ea4aead760dfcb6962efb1d861db48c34379f2ff72db9ddddd4cda9ea2e \ - --hash=sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687 \ - --hash=sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8 \ - --hash=sha256:37239e9f9a7ea9ac5bf6b92b0260b01f8a22281996da609206a84df860bc1261 \ - --hash=sha256:37da61e244d1749798c151421602884db5270faf479cf0ef03af0ff68954c9dd \ - --hash=sha256:3b61b7169ababd7802f9568ed96142616a9118dd2be0d1866e920e77ec8fa92a \ - --hash=sha256:3d9908a48eb7416dc1f4524e69f1d32e5d90e3981e4e37eb0aa1cd18f9cfa2a4 \ - --hash=sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587 \ - --hash=sha256:4021b51936308aeea0367b8f006dc999ca02bc118a0cc78c303f50a2ff6afb91 \ - --hash=sha256:40c5e40ecc29ba010656c18052b877a1c28f84344825efa106705e835c28530f \ - --hash=sha256:425c126c0dc43861e22cb1c14ba4c8e45d09516d0a3ae0a3f7494b79f5f233a3 \ - --hash=sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344 \ - --hash=sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6 \ - --hash=sha256:49a03727c1bba9a97d3e93c9f93ca03a57300f484b6e935463099841261195d3 \ - --hash=sha256:4ae5b5a0e1926e504c81c5b84353e7a5516d8778fbbff00429fe7b05bb25cbce \ - --hash=sha256:4e239d501f73d6db1522599e14b9b321a7e3b1de66ce33d53a765d975e9f4808 \ - --hash=sha256:56339a36b9f1fc708260c76c87e593e2afb30d26de9ae1eb445b5e051b98a7a1 \ - --hash=sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29 \ - --hash=sha256:5b179331a481cb5529fca8b432d8d3c7001cb217513c94cd72d668d1248688a3 \ - --hash=sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b \ - --hash=sha256:5d2d94f1f5fcbe40838ac51a6ab5704a6f9ea42e72ceda48de5e6b898521da51 \ - --hash=sha256:5dff64413671b0d3e7d5918ea490bdccb97a4ad29b3f311ed423200b2203e01c \ - --hash=sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926 \ - --hash=sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64 \ - --hash=sha256:642f752c3eb117b105acbd87e2c143de710987e09860d674e068c4c2c441034f \ - --hash=sha256:65d2ccb7eabee90ce0503c17716fc77226be026dcc3e65cce859a30db715025b \ - --hash=sha256:693781c45a4033d31d4187d2436f5ac701e7bbfe5df40d917736108c1cc7436e \ - --hash=sha256:694976222c711d1d00ba131904beb60534f93966562f64440d0c9d41b8cdb440 \ - --hash=sha256:697753042d57f4bf7122cab985bf15d0cef23c770864580f5af4f52023a56bd6 \ - --hash=sha256:69c56fbc1993fa17043e24a546959c0178fe2b5782405ad4559e6c13975c15e3 \ - --hash=sha256:6de499a1a44e7de70735d0b39f67c8f25eb3d91eb3103be99ca0fa882cdd987d \ - --hash=sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415 \ - --hash=sha256:75ca857eba4e20ce9f546cd59c7007b33906a4cd48f2ff6ccf1ccfc3b646f279 \ - --hash=sha256:7a4a94eb787e606d0a09404b9c38c113d3b099d508021faa615d70a0131907ce \ - --hash=sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603 \ - --hash=sha256:7bfdc049127717581866fa4708791220970ce291c23e28ccf3922c700740fdc0 \ - --hash=sha256:7e63f210bc1b57ef699035f2b4b6d9ce096b5914414a49b0997c839b2bd2223c \ - --hash=sha256:7f9120f7093c2a32d9647abcaf21e6ad275b4fbec5b55969f978b1a97c7c86bf \ - --hash=sha256:8057c98e0c8472d8846b9c79f56766bcc57e3e8ac7bfd510482332366c56c591 \ - --hash=sha256:80dd4c21b0f6237676449c6baaa1039abae86b91636b6c91a7f8e61c87f89540 \ - --hash=sha256:81e97251d9298386c2b7dbeb490d3d1badbdc69107fb8c9299dd04eb39bddc0e \ - --hash=sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26 \ - --hash=sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a \ - --hash=sha256:859bd3f2156e81dd01432f5849fc73e2243d4a487c4fd26609b1299534ee1845 \ - --hash=sha256:87797e645d9d8e222e04160ee32aa06bc5c163e8499f24db719e7852ec23093a \ - --hash=sha256:87b9aab6d6ed88235aa2970294f496ff1a1f9adcd724d800e9b952395a80ffd9 \ - --hash=sha256:8a60e60746623925eab7d25823329941aee7242d559baa119ca2b253c88a7bd6 \ - --hash=sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba \ - --hash=sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df \ - --hash=sha256:947c26539750deeaee933b000fb6517cc770bbd064bad6033f1cff4803881e43 \ - --hash=sha256:96d604498a7c782cb15a51c406acaea70d8c027ee6b90c569baa6e7b93073679 \ - --hash=sha256:988a8c5e317544fdf0d39871559e67b6341065b87fceac641108c2096d5506b7 \ - --hash=sha256:9a9dc347e5a3dc7dfdbc1f82da0ef29e388ddb2ed281bfce9dd8248a313e62b7 \ - --hash=sha256:9ae8dd55c8e6c4257eae3a20fd2c8f41edaea5992ed67156642493b8daf3cecc \ - --hash=sha256:9af5e68ee47d6534d36791bbe9b646d2a7c7deb6fc24d7943628edfbb3581f29 \ - --hash=sha256:9b174f267b5cfb9a7dba9ee6859cecd234e9a681841eb85068059bc867fb8f02 \ - --hash=sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984 \ - --hash=sha256:9d4c940f02f49483b18b079d1c27ab948721852b281f8b015c058100e9421dd1 \ - --hash=sha256:9ebf57d09e131f5323464bd347135a88622d1c0976e88ce15b670e7ad57e4bd6 \ - --hash=sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632 \ - --hash=sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56 \ - --hash=sha256:a2212ad43c0833a873d0fb3c63fa1bacedd4cf6af2fee62bf4b739ceec3ab239 \ - --hash=sha256:a45530014d7a1e09f4a55f4f43097ba0fd155089372e105e4bff4ca76cb1b168 \ - --hash=sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88 \ - --hash=sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc \ - --hash=sha256:af71fff7bac6bb7508956696dce8f6eec2bbb045eceb40343944b1ae62b5ef11 \ - --hash=sha256:b04be762396457bef43f3597c991e192ee7da460a4953d7e647ee4b1c28e7046 \ - --hash=sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0 \ - --hash=sha256:b1a6102b4d3ebc07dad44fbf07b45bb600300f15b552ddf1851b5390202ea2e3 \ - --hash=sha256:b46020d11d23fe16551466c77823df9cc2f2c1e63cc965daf67fa5eec6ca1877 \ - --hash=sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1 \ - --hash=sha256:b903a4dfee7d347e2d87697d0713be59e0b87925be030c9178c5faa58ea58d5c \ - --hash=sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25 \ - --hash=sha256:b99281b0704c103d4e11e72a76f1b543d4946fea7dd10767e7e1b5f00d4e5704 \ - --hash=sha256:bae5c2ed2eae26cc382020edad80d01f36cb8e746da40b292e68fec40421dc6a \ - --hash=sha256:bb4f7475e359992b580559e008c598091c45b5088f28614e855e42d39c2f1033 \ - --hash=sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1 \ - --hash=sha256:bfc1cc2fe31a6026a8a88e4ecfb98d7f6b1fec150cfd708adbfd1d2f42257c29 \ - --hash=sha256:c014c7ea7fb775dd015b2d3137378b7be0249a448a1612268b5a90c2d81de04d \ - --hash=sha256:c048058117fd649334d81b4b526e94bde3ccaddb20463a815ced6ecbb7d11160 \ - --hash=sha256:c0e2d366af265797506f0283487223146af57815b388623f0357ef7eac9b209d \ - --hash=sha256:c19b90316ad3b24c69cd78d5c9b4f3aa4497643685901185b65166293d36a00f \ - --hash=sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f \ - --hash=sha256:c6b8568a3bb5819a0ad087f16d40e5a3fb6099f39ea1d5625a3edc1e923fc538 \ - --hash=sha256:d32764c6c9aafb7fb55366a224756387cd50bfa720f32b88e0e6fa45b27dcf29 \ - --hash=sha256:d5a372fd5afd301b3a89582817fdcdb6c34124787c70dbcc616f259013e7eef7 \ - --hash=sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72 \ - --hash=sha256:dca68018bf48c251ba17c72ed479f4dafe9dbd5a73707ad8d28a38d11f3d42af \ - --hash=sha256:de2c184bb1fe2cbd2cefba613e9db29a5ab559323f994b6737e370d3da0ac455 \ - --hash=sha256:e3531d63d3bdfa7e3ac5e9b27b2dd7ec9df3206a98e0b3445fa906f233264c57 \ - --hash=sha256:e50a2e1404f063427c9d027378472316201a2290959a295169bcf25992d04558 \ - --hash=sha256:e636b3c5f61da31a92bf0d91da83e58fdfa96f178ba682f11d24f31944cdd28c \ - --hash=sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808 \ - --hash=sha256:f33ed1a2bf1997a36661874b017f5c4b760f41266341af36febaf271d179f6d7 \ - --hash=sha256:f76c1e3fe7d7c8afad7ed193f89a292e1999608170dcc9751a7462a87dfd5bc0 \ - --hash=sha256:f9444f105664c4ce47a2a7171a2418bce5b7bae45fb610f4e2c36045d85911d3 \ - --hash=sha256:fc290605db2a917f6e81b0e1e0796469871f5af381ce15c604a3c5c7e51cb730 \ - --hash=sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa \ - --hash=sha256:fee0c6bc7db1de362252affec009707a17478a00ec69f797d23ca256e36d5940 +aiohttp==3.13.5 \ + --hash=sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5 \ + --hash=sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b \ + --hash=sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9 \ + --hash=sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b \ + --hash=sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8 \ + --hash=sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a \ + --hash=sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2 \ + --hash=sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1 \ + --hash=sha256:147b4f501d0292077f29d5268c16bb7c864a1f054d7001c4c1812c0421ea1ed0 \ + --hash=sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037 \ + --hash=sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416 \ + --hash=sha256:178c7b5e62b454c2bc790786e6058c3cc968613b4419251b478c153a4aec32b1 \ + --hash=sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9 \ + --hash=sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a \ + --hash=sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36 \ + --hash=sha256:206b7b3ef96e4ce211754f0cd003feb28b7d81f0ad26b8d077a5d5161436067f \ + --hash=sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b \ + --hash=sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174 \ + --hash=sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b \ + --hash=sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8 \ + --hash=sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e \ + --hash=sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6 \ + --hash=sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c \ + --hash=sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe \ + --hash=sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9 \ + --hash=sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc \ + --hash=sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800 \ + --hash=sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286 \ + --hash=sha256:347542f0ea3f95b2a955ee6656461fa1c776e401ac50ebce055a6c38454a0adf \ + --hash=sha256:39380e12bd1f2fdab4285b6e055ad48efbaed5c836433b142ed4f5b9be71036a \ + --hash=sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc \ + --hash=sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9 \ + --hash=sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665 \ + --hash=sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832 \ + --hash=sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297 \ + --hash=sha256:4e704c52438f66fdd89588346183d898bb42167cf88f8b7ff1c0f9fc957c348f \ + --hash=sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73 \ + --hash=sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b \ + --hash=sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9 \ + --hash=sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090 \ + --hash=sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49 \ + --hash=sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d \ + --hash=sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46 \ + --hash=sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83 \ + --hash=sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796 \ + --hash=sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be \ + --hash=sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d \ + --hash=sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf \ + --hash=sha256:6f497a6876aa4b1a102b04996ce4c1170c7040d83faa9387dd921c16e30d5c83 \ + --hash=sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25 \ + --hash=sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06 \ + --hash=sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3 \ + --hash=sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6 \ + --hash=sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb \ + --hash=sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88 \ + --hash=sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9 \ + --hash=sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be \ + --hash=sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14 \ + --hash=sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a \ + --hash=sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c \ + --hash=sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3 \ + --hash=sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f \ + --hash=sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d \ + --hash=sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670 \ + --hash=sha256:912d4b6af530ddb1338a66229dac3a25ff11d4448be3ec3d6340583995f56031 \ + --hash=sha256:9277145d36a01653863899c665243871434694bcc3431922c3b35c978061bdb8 \ + --hash=sha256:95d14ca7abefde230f7639ec136ade282655431fd5db03c343b19dda72dd1643 \ + --hash=sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d \ + --hash=sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8 \ + --hash=sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8 \ + --hash=sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1 \ + --hash=sha256:9efcc0f11d850cefcafdd9275b9576ad3bfb539bed96807663b32ad99c4d4b88 \ + --hash=sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb \ + --hash=sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61 \ + --hash=sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4 \ + --hash=sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7 \ + --hash=sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9 \ + --hash=sha256:a8a4d3427e8de1312ddf309cc482186466c79895b3a139fed3259fc01dfa9a5b \ + --hash=sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500 \ + --hash=sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6 \ + --hash=sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2 \ + --hash=sha256:af545c2cffdb0967a96b6249e6f5f7b0d92cdfd267f9d5238d5b9ca63e8edb10 \ + --hash=sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1 \ + --hash=sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3 \ + --hash=sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e \ + --hash=sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a \ + --hash=sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5 \ + --hash=sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95 \ + --hash=sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074 \ + --hash=sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5 \ + --hash=sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b \ + --hash=sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772 \ + --hash=sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a \ + --hash=sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274 \ + --hash=sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94 \ + --hash=sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13 \ + --hash=sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac \ + --hash=sha256:cb979826071c0986a5f08333a36104153478ce6018c58cba7f9caddaf63d5d67 \ + --hash=sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76 \ + --hash=sha256:d147004fede1b12f6013a6dbb2a26a986a671a03c6ea740ddc76500e5f1c399f \ + --hash=sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8 \ + --hash=sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7 \ + --hash=sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8 \ + --hash=sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3 \ + --hash=sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be \ + --hash=sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b \ + --hash=sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c \ + --hash=sha256:e999f0c88a458c836d5fb521814e92ed2172c649200336a6df514987c1488258 \ + --hash=sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c \ + --hash=sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6 \ + --hash=sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56 \ + --hash=sha256:ee5e86776273de1795947d17bddd6bb19e0365fd2af4289c0d2c5454b6b1d36b \ + --hash=sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d \ + --hash=sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a \ + --hash=sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162 \ + --hash=sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1 \ + --hash=sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6 \ + --hash=sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5 \ + --hash=sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540 \ + --hash=sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254 # via aiobotocore aioitertools==0.13.0 \ --hash=sha256:0be0292b856f08dfac90e31f4739432f4cb6d7520ab9eb73e143f4f2fa5259be \ @@ -152,9 +152,9 @@ annotated-types==0.7.0 \ --hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \ --hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89 # via pydantic -anyio==4.12.1 \ - --hash=sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703 \ - --hash=sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c +anyio==4.13.0 \ + --hash=sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708 \ + --hash=sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc # via # httpx # mcp @@ -173,9 +173,9 @@ atpublic==7.0.0 \ --hash=sha256:466ef10d0c8bbd14fd02a5fbd5a8b6af6a846373d91106d3a07c16d72d96b63e \ --hash=sha256:6702bd9e7245eb4e8220a3e222afcef7f87412154732271ee7deee4433b72b4b # via ibis-framework -attrs==25.4.0 \ - --hash=sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11 \ - --hash=sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373 +attrs==26.1.0 \ + --hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \ + --hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32 # via # aiohttp # jsonschema @@ -184,9 +184,9 @@ babel==2.18.0 \ --hash=sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d \ --hash=sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35 # via sphinx -bigtree==1.3.1 \ - --hash=sha256:a22a0ecd9b0abb283f4a1515370dbf1ec93adee70746767272e2c49d7af9f407 \ - --hash=sha256:c8b766b00188c532d3499bfd9e9666b357428db507fc701f088031a0d5c614d5 +bigtree==1.4.0 \ + --hash=sha256:d0d99550ae64ce4529f132602ab875c2ab472c96c942f5704f8c72a17450d3ea \ + --hash=sha256:e5ae2e948168da671d99601c9ed87ab3b48d9d4ea8a98f111e5748e98064c31c # via feast (pyproject.toml) boto3==1.38.27 \ --hash=sha256:94bd7fdd92d5701b362d4df100d21e28f8307a67ff56b6a8b0398119cf22f859 \ @@ -206,9 +206,9 @@ calver==2025.3.31 \ --hash=sha256:07511edf5e7fa75ae97445c8c5921240e0fe62937289a3ebe6963eddd3c691b6 \ --hash=sha256:255d1a70bba8f97dc1eee3af4240ed35980508da69257feef94c79e5c6545fc7 # via feast (pyproject.toml) -certifi==2026.1.4 \ - --hash=sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c \ - --hash=sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120 +certifi==2026.2.25 \ + --hash=sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa \ + --hash=sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7 # via # httpcore # httpx @@ -303,120 +303,136 @@ cffi==2.0.0 \ # via # feast (pyproject.toml) # cryptography -charset-normalizer==3.4.4 \ - --hash=sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad \ - --hash=sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93 \ - --hash=sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394 \ - --hash=sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89 \ - --hash=sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc \ - --hash=sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86 \ - --hash=sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63 \ - --hash=sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d \ - --hash=sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f \ - --hash=sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8 \ - --hash=sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0 \ - --hash=sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505 \ - --hash=sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161 \ - --hash=sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af \ - --hash=sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152 \ - --hash=sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318 \ - --hash=sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72 \ - --hash=sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4 \ - --hash=sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e \ - --hash=sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3 \ - --hash=sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576 \ - --hash=sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c \ - --hash=sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1 \ - --hash=sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8 \ - --hash=sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1 \ - --hash=sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2 \ - --hash=sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44 \ - --hash=sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26 \ - --hash=sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88 \ - --hash=sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016 \ - --hash=sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede \ - --hash=sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf \ - --hash=sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a \ - --hash=sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc \ - --hash=sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0 \ - --hash=sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84 \ - --hash=sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db \ - --hash=sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1 \ - --hash=sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7 \ - --hash=sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed \ - --hash=sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8 \ - --hash=sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133 \ - --hash=sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e \ - --hash=sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef \ - --hash=sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14 \ - --hash=sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2 \ - --hash=sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0 \ - --hash=sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d \ - --hash=sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828 \ - --hash=sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f \ - --hash=sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf \ - --hash=sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6 \ - --hash=sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328 \ - --hash=sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090 \ - --hash=sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa \ - --hash=sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381 \ - --hash=sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c \ - --hash=sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb \ - --hash=sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc \ - --hash=sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a \ - --hash=sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec \ - --hash=sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc \ - --hash=sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac \ - --hash=sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e \ - --hash=sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313 \ - --hash=sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569 \ - --hash=sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3 \ - --hash=sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d \ - --hash=sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525 \ - --hash=sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894 \ - --hash=sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3 \ - --hash=sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9 \ - --hash=sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a \ - --hash=sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9 \ - --hash=sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14 \ - --hash=sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25 \ - --hash=sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50 \ - --hash=sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf \ - --hash=sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1 \ - --hash=sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3 \ - --hash=sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac \ - --hash=sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e \ - --hash=sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815 \ - --hash=sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c \ - --hash=sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6 \ - --hash=sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6 \ - --hash=sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e \ - --hash=sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4 \ - --hash=sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84 \ - --hash=sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69 \ - --hash=sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15 \ - --hash=sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191 \ - --hash=sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0 \ - --hash=sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897 \ - --hash=sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd \ - --hash=sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2 \ - --hash=sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794 \ - --hash=sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d \ - --hash=sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074 \ - --hash=sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3 \ - --hash=sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224 \ - --hash=sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838 \ - --hash=sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a \ - --hash=sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d \ - --hash=sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d \ - --hash=sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f \ - --hash=sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8 \ - --hash=sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490 \ - --hash=sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966 \ - --hash=sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9 \ - --hash=sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3 \ - --hash=sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e \ - --hash=sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608 +charset-normalizer==3.4.7 \ + --hash=sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc \ + --hash=sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c \ + --hash=sha256:07d9e39b01743c3717745f4c530a6349eadbfa043c7577eef86c502c15df2c67 \ + --hash=sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4 \ + --hash=sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0 \ + --hash=sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c \ + --hash=sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5 \ + --hash=sha256:12a6fff75f6bc66711b73a2f0addfc4c8c15a20e805146a02d147a318962c444 \ + --hash=sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153 \ + --hash=sha256:14265bfe1f09498b9d8ec91e9ec9fa52775edf90fcbde092b25f4a33d444fea9 \ + --hash=sha256:16d971e29578a5e97d7117866d15889a4a07befe0e87e703ed63cd90cb348c01 \ + --hash=sha256:177a0ba5f0211d488e295aaf82707237e331c24788d8d76c96c5a41594723217 \ + --hash=sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b \ + --hash=sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c \ + --hash=sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a \ + --hash=sha256:1dc8b0ea451d6e69735094606991f32867807881400f808a106ee1d963c46a83 \ + --hash=sha256:1efde3cae86c8c273f1eb3b287be7d8499420cf2fe7585c41d370d3e790054a5 \ + --hash=sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7 \ + --hash=sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb \ + --hash=sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c \ + --hash=sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1 \ + --hash=sha256:2cd4a60d0e2fb04537162c62bbbb4182f53541fe0ede35cdf270a1c1e723cc42 \ + --hash=sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab \ + --hash=sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df \ + --hash=sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e \ + --hash=sha256:320ade88cfb846b8cd6b4ddf5ee9e80ee0c1f52401f2456b84ae1ae6a1a5f207 \ + --hash=sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18 \ + --hash=sha256:36836d6ff945a00b88ba1e4572d721e60b5b8c98c155d465f56ad19d68f23734 \ + --hash=sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38 \ + --hash=sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110 \ + --hash=sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18 \ + --hash=sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44 \ + --hash=sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d \ + --hash=sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48 \ + --hash=sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e \ + --hash=sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5 \ + --hash=sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d \ + --hash=sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53 \ + --hash=sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790 \ + --hash=sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c \ + --hash=sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b \ + --hash=sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116 \ + --hash=sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d \ + --hash=sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10 \ + --hash=sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6 \ + --hash=sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2 \ + --hash=sha256:6370e8686f662e6a3941ee48ed4742317cafbe5707e36406e9df792cdb535776 \ + --hash=sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a \ + --hash=sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265 \ + --hash=sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008 \ + --hash=sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943 \ + --hash=sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374 \ + --hash=sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246 \ + --hash=sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e \ + --hash=sha256:6e0d51f618228538a3e8f46bd246f87a6cd030565e015803691603f55e12afb5 \ + --hash=sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616 \ + --hash=sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15 \ + --hash=sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41 \ + --hash=sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960 \ + --hash=sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752 \ + --hash=sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e \ + --hash=sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72 \ + --hash=sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7 \ + --hash=sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8 \ + --hash=sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b \ + --hash=sha256:813c0e0132266c08eb87469a642cb30aaff57c5f426255419572aaeceeaa7bf4 \ + --hash=sha256:82b271f5137d07749f7bf32f70b17ab6eaabedd297e75dce75081a24f76eb545 \ + --hash=sha256:84c018e49c3bf790f9c2771c45e9313a08c2c2a6342b162cd650258b57817706 \ + --hash=sha256:8751d2787c9131302398b11e6c8068053dcb55d5a8964e114b6e196cf16cb366 \ + --hash=sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb \ + --hash=sha256:87fad7d9ba98c86bcb41b2dc8dbb326619be2562af1f8ff50776a39e55721c5a \ + --hash=sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e \ + --hash=sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00 \ + --hash=sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f \ + --hash=sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a \ + --hash=sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1 \ + --hash=sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66 \ + --hash=sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356 \ + --hash=sha256:a6c5863edfbe888d9eff9c8b8087354e27618d9da76425c119293f11712a6319 \ + --hash=sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4 \ + --hash=sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad \ + --hash=sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d \ + --hash=sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5 \ + --hash=sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7 \ + --hash=sha256:aef65cd602a6d0e0ff6f9930fcb1c8fec60dd2cfcb6facaf4bdb0e5873042db0 \ + --hash=sha256:af21eb4409a119e365397b2adbaca4c9ccab56543a65d5dbd9f920d6ac29f686 \ + --hash=sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34 \ + --hash=sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49 \ + --hash=sha256:bb8cc7534f51d9a017b93e3e85b260924f909601c3df002bcdb58ddb4dc41a5c \ + --hash=sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1 \ + --hash=sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e \ + --hash=sha256:bd9b23791fe793e4968dba0c447e12f78e425c59fc0e3b97f6450f4781f3ee60 \ + --hash=sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0 \ + --hash=sha256:c0f081d69a6e58272819b70288d3221a6ee64b98df852631c80f293514d3b274 \ + --hash=sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d \ + --hash=sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0 \ + --hash=sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae \ + --hash=sha256:c593052c465475e64bbfe5dbd81680f64a67fdc752c56d7a0ae205dc8aeefe0f \ + --hash=sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d \ + --hash=sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe \ + --hash=sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3 \ + --hash=sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393 \ + --hash=sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1 \ + --hash=sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af \ + --hash=sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44 \ + --hash=sha256:d61f00a0869d77422d9b2aba989e2d24afa6ffd552af442e0e58de4f35ea6d00 \ + --hash=sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c \ + --hash=sha256:dca4bbc466a95ba9c0234ef56d7dd9509f63da22274589ebd4ed7f1f4d4c54e3 \ + --hash=sha256:dd915403e231e6b1809fe9b6d9fc55cf8fb5e02765ac625d9cd623342a7905d7 \ + --hash=sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd \ + --hash=sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e \ + --hash=sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b \ + --hash=sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8 \ + --hash=sha256:e5f4d355f0a2b1a31bc3edec6795b46324349c9cb25eed068049e4f472fb4259 \ + --hash=sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859 \ + --hash=sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46 \ + --hash=sha256:e80c8378d8f3d83cd3164da1ad2df9e37a666cdde7b1cb2298ed0b558064be30 \ + --hash=sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b \ + --hash=sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46 \ + --hash=sha256:ed065083d0898c9d5b4bbec7b026fd755ff7454e6e8b73a67f8c744b13986e24 \ + --hash=sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a \ + --hash=sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24 \ + --hash=sha256:f22dec1690b584cea26fade98b2435c132c1b5f68e39f5a0b7627cd7ae31f1dc \ + --hash=sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215 \ + --hash=sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063 \ + --hash=sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832 \ + --hash=sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6 \ + --hash=sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79 \ + --hash=sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464 # via # requests # snowflake-connector-python @@ -436,56 +452,56 @@ colorama==0.4.6 \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 # via feast (pyproject.toml) -cryptography==46.0.5 \ - --hash=sha256:02f547fce831f5096c9a567fd41bc12ca8f11df260959ecc7c3202555cc47a72 \ - --hash=sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235 \ - --hash=sha256:1abfdb89b41c3be0365328a410baa9df3ff8a9110fb75e7b52e66803ddabc9a9 \ - --hash=sha256:2ae6971afd6246710480e3f15824ed3029a60fc16991db250034efd0b9fb4356 \ - --hash=sha256:2b7a67c9cd56372f3249b39699f2ad479f6991e62ea15800973b956f4b73e257 \ - --hash=sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad \ - --hash=sha256:38946c54b16c885c72c4f59846be9743d699eee2b69b6988e0a00a01f46a61a4 \ - --hash=sha256:3b4995dc971c9fb83c25aa44cf45f02ba86f71ee600d81091c2f0cbae116b06c \ - --hash=sha256:3ce58ba46e1bc2aac4f7d9290223cead56743fa6ab94a5d53292ffaac6a91614 \ - --hash=sha256:3ee190460e2fbe447175cda91b88b84ae8322a104fc27766ad09428754a618ed \ - --hash=sha256:4108d4c09fbbf2789d0c926eb4152ae1760d5a2d97612b92d508d96c861e4d31 \ - --hash=sha256:420d0e909050490d04359e7fdb5ed7e667ca5c3c402b809ae2563d7e66a92229 \ - --hash=sha256:47fb8a66058b80e509c47118ef8a75d14c455e81ac369050f20ba0d23e77fee0 \ - --hash=sha256:4c3341037c136030cb46e4b1e17b7418ea4cbd9dd207e4a6f3b2b24e0d4ac731 \ - --hash=sha256:4d7e3d356b8cd4ea5aff04f129d5f66ebdc7b6f8eae802b93739ed520c47c79b \ - --hash=sha256:4d8ae8659ab18c65ced284993c2265910f6c9e650189d4e3f68445ef82a810e4 \ - --hash=sha256:4e817a8920bfbcff8940ecfd60f23d01836408242b30f1a708d93198393a80b4 \ - --hash=sha256:50bfb6925eff619c9c023b967d5b77a54e04256c4281b0e21336a130cd7fc263 \ - --hash=sha256:556e106ee01aa13484ce9b0239bca667be5004efb0aabbed28d353df86445595 \ - --hash=sha256:582f5fcd2afa31622f317f80426a027f30dc792e9c80ffee87b993200ea115f1 \ - --hash=sha256:5be7bf2fb40769e05739dd0046e7b26f9d4670badc7b032d6ce4db64dddc0678 \ - --hash=sha256:60ee7e19e95104d4c03871d7d7dfb3d22ef8a9b9c6778c94e1c8fcc8365afd48 \ - --hash=sha256:61aa400dce22cb001a98014f647dc21cda08f7915ceb95df0c9eaf84b4b6af76 \ - --hash=sha256:68f68d13f2e1cb95163fa3b4db4bf9a159a418f5f6e7242564fc75fcae667fd0 \ - --hash=sha256:7d1f30a86d2757199cb2d56e48cce14deddf1f9c95f1ef1b64ee91ea43fe2e18 \ - --hash=sha256:7d731d4b107030987fd61a7f8ab512b25b53cef8f233a97379ede116f30eb67d \ - --hash=sha256:803812e111e75d1aa73690d2facc295eaefd4439be1023fefc4995eaea2af90d \ - --hash=sha256:80a8d7bfdf38f87ca30a5391c0c9ce4ed2926918e017c29ddf643d0ed2778ea1 \ - --hash=sha256:8293f3dea7fc929ef7240796ba231413afa7b68ce38fd21da2995549f5961981 \ - --hash=sha256:8456928655f856c6e1533ff59d5be76578a7157224dbd9ce6872f25055ab9ab7 \ - --hash=sha256:890bcb4abd5a2d3f852196437129eb3667d62630333aacc13dfd470fad3aaa82 \ - --hash=sha256:94a76daa32eb78d61339aff7952ea819b1734b46f73646a07decb40e5b3448e2 \ - --hash=sha256:9f16fbdf4da055efb21c22d81b89f155f02ba420558db21288b3d0035bafd5f4 \ - --hash=sha256:a3d1fae9863299076f05cb8a778c467578262fae09f9dc0ee9b12eb4268ce663 \ - --hash=sha256:a3d507bb6a513ca96ba84443226af944b0f7f47dcc9a399d110cd6146481d24c \ - --hash=sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d \ - --hash=sha256:ba2a27ff02f48193fc4daeadf8ad2590516fa3d0adeeb34336b96f7fa64c1e3a \ - --hash=sha256:bc84e875994c3b445871ea7181d424588171efec3e185dced958dad9e001950a \ - --hash=sha256:bfd56bb4b37ed4f330b82402f6f435845a5f5648edf1ad497da51a8452d5d62d \ - --hash=sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b \ - --hash=sha256:c3bcce8521d785d510b2aad26ae2c966092b7daa8f45dd8f44734a104dc0bc1a \ - --hash=sha256:c4143987a42a2397f2fc3b4d7e3a7d313fbe684f67ff443999e803dd75a76826 \ - --hash=sha256:c69fd885df7d089548a42d5ec05be26050ebcd2283d89b3d30676eb32ff87dee \ - --hash=sha256:ced80795227d70549a411a4ab66e8ce307899fad2220ce5ab2f296e687eacde9 \ - --hash=sha256:d66e421495fdb797610a08f43b05269e0a5ea7f5e652a89bfd5a7d3c1dee3648 \ - --hash=sha256:d861ee9e76ace6cf36a6a89b959ec08e7bc2493ee39d07ffe5acb23ef46d27da \ - --hash=sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2 \ - --hash=sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2 \ - --hash=sha256:fe346b143ff9685e40192a4960938545c699054ba11d4f9029f94751e3f71d87 +cryptography==46.0.6 \ + --hash=sha256:02fad249cb0e090b574e30b276a3da6a149e04ee2f049725b1f69e7b8351ec70 \ + --hash=sha256:063b67749f338ca9c5a0b7fe438a52c25f9526b851e24e6c9310e7195aad3b4d \ + --hash=sha256:12cae594e9473bca1a7aceb90536060643128bb274fcea0fc459ab90f7d1ae7a \ + --hash=sha256:12f0fa16cc247b13c43d56d7b35287ff1569b5b1f4c5e87e92cc4fcc00cd10c0 \ + --hash=sha256:22259338084d6ae497a19bae5d4c66b7ca1387d3264d1c2c0e72d9e9b6a77b97 \ + --hash=sha256:26031f1e5ca62fcb9d1fcb34b2b60b390d1aacaa15dc8b895a9ed00968b97b30 \ + --hash=sha256:27550628a518c5c6c903d84f637fbecf287f6cb9ced3804838a1295dc1fd0759 \ + --hash=sha256:2b417edbe8877cda9022dde3a008e2deb50be9c407eef034aeeb3a8b11d9db3c \ + --hash=sha256:2ea0f37e9a9cf0df2952893ad145fd9627d326a59daec9b0802480fa3bcd2ead \ + --hash=sha256:2ef9e69886cbb137c2aef9772c2e7138dc581fad4fcbcf13cc181eb5a3ab6275 \ + --hash=sha256:341359d6c9e68834e204ceaf25936dffeafea3829ab80e9503860dcc4f4dac58 \ + --hash=sha256:380343e0653b1c9d7e1f55b52aaa2dbb2fdf2730088d48c43ca1c7c0abb7cc2f \ + --hash=sha256:3c21d92ed15e9cfc6eb64c1f5a0326db22ca9c2566ca46d845119b45b4400361 \ + --hash=sha256:3dfa6567f2e9e4c5dceb8ccb5a708158a2a871052fa75c8b78cb0977063f1507 \ + --hash=sha256:456b3215172aeefb9284550b162801d62f5f264a081049a3e94307fe20792cfa \ + --hash=sha256:4668298aef7cddeaf5c6ecc244c2302a2b8e40f384255505c22875eebb47888b \ + --hash=sha256:50575a76e2951fe7dbd1f56d181f8c5ceeeb075e9ff88e7ad997d2f42af06e7b \ + --hash=sha256:639301950939d844a9e1c4464d7e07f902fe9a7f6b215bb0d4f28584729935d8 \ + --hash=sha256:64235194bad039a10bb6d2d930ab3323baaec67e2ce36215fd0952fad0930ca8 \ + --hash=sha256:6617f67b1606dfd9fe4dbfa354a9508d4a6d37afe30306fe6c101b7ce3274b72 \ + --hash=sha256:67177e8a9f421aa2d3a170c3e56eca4e0128883cf52a071a7cbf53297f18b175 \ + --hash=sha256:6728c49e3b2c180ef26f8e9f0a883a2c585638db64cf265b49c9ba10652d430e \ + --hash=sha256:6739d56300662c468fddb0e5e291f9b4d084bead381667b9e654c7dd81705124 \ + --hash=sha256:69cf0056d6947edc6e6760e5f17afe4bea06b56a9ac8a06de9d2bd6b532d4f3a \ + --hash=sha256:760997a4b950ff00d418398ad73fbc91aa2894b5c1db7ccb45b4f68b42a63b3c \ + --hash=sha256:79e865c642cfc5c0b3eb12af83c35c5aeff4fa5c672dc28c43721c2c9fdd2f0f \ + --hash=sha256:7e6142674f2a9291463e5e150090b95a8519b2fb6e6aaec8917dd8d094ce750d \ + --hash=sha256:7f417f034f91dcec1cb6c5c35b07cdbb2ef262557f701b4ecd803ee8cefed4f4 \ + --hash=sha256:7f6690b6c55e9c5332c0b59b9c8a3fb232ebf059094c17f9019a51e9827df91c \ + --hash=sha256:8927ccfbe967c7df312ade694f987e7e9e22b2425976ddbf28271d7e58845290 \ + --hash=sha256:8ce35b77aaf02f3b59c90b2c8a05c73bac12cea5b4e8f3fbece1f5fddea5f0ca \ + --hash=sha256:8e7304c4f4e9490e11efe56af6713983460ee0780f16c63f219984dab3af9d2d \ + --hash=sha256:90e5f0a7b3be5f40c3a0a0eafb32c681d8d2c181fc2a1bdabe9b3f611d9f6b1a \ + --hash=sha256:97c8115b27e19e592a05c45d0dd89c57f81f841cc9880e353e0d3bf25b2139ed \ + --hash=sha256:9a693028b9cbe51b5a1136232ee8f2bc242e4e19d456ded3fa7c86e43c713b4a \ + --hash=sha256:9a9c42a2723999a710445bc0d974e345c32adfd8d2fac6d8a251fa829ad31cfb \ + --hash=sha256:a3e84d5ec9ba01f8fd03802b2147ba77f0c8f2617b2aff254cedd551844209c8 \ + --hash=sha256:aad75154a7ac9039936d50cf431719a2f8d4ed3d3c277ac03f3339ded1a5e707 \ + --hash=sha256:b12c6b1e1651e42ab5de8b1e00dc3b6354fdfd778e7fa60541ddacc27cd21410 \ + --hash=sha256:b928a3ca837c77a10e81a814a693f2295200adb3352395fad024559b7be7a736 \ + --hash=sha256:bcb87663e1f7b075e48c3be3ecb5f0b46c8fc50b50a97cf264e7f60242dca3f2 \ + --hash=sha256:c797e2517cb7880f8297e2c0f43bb910e91381339336f75d2c1c2cbf811b70b4 \ + --hash=sha256:c89eb37fae9216985d8734c1afd172ba4927f5a05cfd9bf0e4863c6d5465b013 \ + --hash=sha256:cdcd3edcbc5d55757e5f5f3d330dd00007ae463a7e7aa5bf132d1f22a4b62b19 \ + --hash=sha256:d24c13369e856b94892a89ddf70b332e0b70ad4a5c43cf3e9cb71d6d7ffa1f7b \ + --hash=sha256:d4e4aadb7fc1f88687f47ca20bb7227981b03afaae69287029da08096853b738 \ + --hash=sha256:d9528b535a6c4f8ff37847144b8986a9a143585f0540fbcb1a98115b543aa463 \ + --hash=sha256:ed3775295fb91f70b4027aeba878d79b3e55c0b3e97eaa4de71f8f23a9f2eb77 \ + --hash=sha256:ed418c37d095aeddf5336898a132fba01091f0ac5844e3e8018506f014b6d2c4 # via # google-auth # pyjwt @@ -557,13 +573,13 @@ cython==3.0.12 \ --hash=sha256:feb86122a823937cc06e4c029d80ff69f082ebb0b959ab52a5af6cdd271c5dc3 \ --hash=sha256:ff5c0b6a65b08117d0534941d404833d516dac422eee88c6b4fd55feb409a5ed # via feast (pyproject.toml) -dask[dataframe]==2026.1.2 \ - --hash=sha256:1136683de2750d98ea792670f7434e6c1cfce90cab2cc2f2495a9e60fd25a4fc \ - --hash=sha256:46a0cf3b8d87f78a3d2e6b145aea4418a6d6d606fe6a16c79bd8ca2bb862bc91 +dask[dataframe]==2026.3.0 \ + --hash=sha256:be614b9242b0b38288060fb2d7696125946469c98a1c30e174883fd199e0428d \ + --hash=sha256:f7d96c8274e8a900d217c1ff6ea8d1bbf0b4c2c21e74a409644498d925eb8f85 # via feast (pyproject.toml) -db-dtypes==1.5.0 \ - --hash=sha256:abdbb2e4eb965800ed6f98af0c5c1cafff9063ace09114be2d26a7f046be2c8a \ - --hash=sha256:ad9e94243f53e104bc77dbf9ae44b580d83a770d3694483aba59c9767966daa5 +db-dtypes==1.5.1 \ + --hash=sha256:901099b807c9312bc61a5bddbfb07512884e6c6d5a9edacf24d50bcf303aa5f7 \ + --hash=sha256:ad71a6645e3c1f06d4d32023940576648f43119822f825f0d22587c6ef8afe15 # via # google-cloud-bigquery # pandas-gbq @@ -575,56 +591,50 @@ docutils==0.22.4 \ --hash=sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968 \ --hash=sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de # via sphinx -duckdb==1.4.4 \ - --hash=sha256:0509b39ea7af8cff0198a99d206dca753c62844adab54e545984c2e2c1381616 \ - --hash=sha256:0d636ceda422e7babd5e2f7275f6a0d1a3405e6a01873f00d38b72118d30c10b \ - --hash=sha256:1af6e76fe8bd24875dc56dd8e38300d64dc708cd2e772f67b9fbc635cc3066a3 \ - --hash=sha256:1f8d55843cc940e36261689054f7dfb6ce35b1f5b0953b0d355b6adb654b0d52 \ - --hash=sha256:25874f8b1355e96178079e37312c3ba6d61a2354f51319dae860cf21335c3a20 \ - --hash=sha256:337f8b24e89bc2e12dadcfe87b4eb1c00fd920f68ab07bc9b70960d6523b8bc3 \ - --hash=sha256:452c5b5d6c349dc5d1154eb2062ee547296fcbd0c20e9df1ed00b5e1809089da \ - --hash=sha256:453b115f4777467f35103d8081770ac2f223fb5799178db5b06186e3ab51d1f2 \ - --hash=sha256:47dd4162da6a2be59a0aef640eb08d6360df1cf83c317dcc127836daaf3b7f7c \ - --hash=sha256:49123b579e4a6323e65139210cd72dddc593a72d840211556b60f9703bda8526 \ - --hash=sha256:4c25d5b0febda02b7944e94fdae95aecf952797afc8cb920f677b46a7c251955 \ - --hash=sha256:50f2eb173c573811b44aba51176da7a4e5c487113982be6a6a1c37337ec5fa57 \ - --hash=sha256:53cd6423136ab44383ec9955aefe7599b3fb3dd1fe006161e6396d8167e0e0d4 \ - --hash=sha256:5536eb952a8aa6ae56469362e344d4e6403cc945a80bc8c5c2ebdd85d85eb64b \ - --hash=sha256:59c8d76016dde854beab844935b1ec31de358d4053e792988108e995b18c08e7 \ - --hash=sha256:5ba684f498d4e924c7e8f30dd157da8da34c8479746c5011b6c0e037e9c60ad2 \ - --hash=sha256:5cdc4126ec925edf3112bc656ac9ed23745294b854935fa7a643a216e4455af6 \ - --hash=sha256:5e1933fac5293fea5926b0ee75a55b8cfe7f516d867310a5b251831ab61fe62b \ - --hash=sha256:6703dd1bb650025b3771552333d305d62ddd7ff182de121483d4e042ea6e2e00 \ - --hash=sha256:6792ca647216bd5c4ff16396e4591cfa9b4a72e5ad7cdd312cec6d67e8431a7c \ - --hash=sha256:6cb357cfa3403910e79e2eb46c8e445bb1ee2fd62e9e9588c6b999df4256abc1 \ - --hash=sha256:6fb1225a9ea5877421481d59a6c556a9532c32c16c7ae6ca8d127e2b878c9389 \ - --hash=sha256:707530f6637e91dc4b8125260595299ec9dd157c09f5d16c4186c5988bfbd09a \ - --hash=sha256:7df7351328ffb812a4a289732f500d621e7de9942a3a2c9b6d4afcf4c0e72526 \ - --hash=sha256:7eec0bf271ac622e57b7f6554a27a6e7d1dd2f43d1871f7962c74bcbbede15ba \ - --hash=sha256:8097201bc5fd0779d7fcc2f3f4736c349197235f4cb7171622936343a1aa8dbf \ - --hash=sha256:8bba52fd2acb67668a4615ee17ee51814124223de836d9e2fdcbc4c9021b3d3c \ - --hash=sha256:8e5c2d8a0452df55e092959c0bfc8ab8897ac3ea0f754cb3b0ab3e165cd79aff \ - --hash=sha256:a3c8542db7ffb128aceb7f3b35502ebaddcd4f73f1227569306cc34bad06680c \ - --hash=sha256:b297eff642503fd435a9de5a9cb7db4eccb6f61d61a55b30d2636023f149855f \ - --hash=sha256:bf138201f56e5d6fc276a25138341b3523e2f84733613fc43f02c54465619a95 \ - --hash=sha256:c65d15c440c31e06baaebfd2c06d71ce877e132779d309f1edf0a85d23c07e92 \ - --hash=sha256:c9566a4ed834ec7999db5849f53da0a7ee83d86830c33f471bf0211a1148ca12 \ - --hash=sha256:cd1be3d48577f5b40eb9706c6b2ae10edfe18e78eb28e31a3b922dcff1183597 \ - --hash=sha256:d0440f59e0cd9936a9ebfcf7a13312eda480c79214ffed3878d75947fc3b7d6d \ - --hash=sha256:d525de5f282b03aa8be6db86b1abffdceae5f1055113a03d5b50cd2fb8cf2ef8 \ - --hash=sha256:ddcfd9c6ff234da603a1edd5fd8ae6107f4d042f74951b65f91bc5e2643856b3 \ - --hash=sha256:e041f2fbd6888da090eca96ac167a7eb62d02f778385dd9155ed859f1c6b6dc8 \ - --hash=sha256:e870a441cb1c41d556205deb665749f26347ed13b3a247b53714f5d589596977 \ - --hash=sha256:f28a18cc790217e5b347bb91b2cab27aafc557c58d3d8382e04b4fe55d0c3f66 \ - --hash=sha256:fb94de6d023de9d79b7edc1ae07ee1d0b4f5fa8a9dcec799650b5befdf7aafec +duckdb==1.5.1 \ + --hash=sha256:054ad424b051b334052afac58cb216f3b1ebb8579fc8c641e60f0182e8725ea9 \ + --hash=sha256:05fc91767d0cfc4cf2fa68966ab5b479ac07561752e42dd0ae30327bd160f64a \ + --hash=sha256:0a6acc2040bec1f05de62a2f3f68f4c12f3ec7d6012b4317d0ab1a195af26225 \ + --hash=sha256:26e56b5f0c96189e3288d83cf7b476e23615987902f801e5788dee15ee9f24a9 \ + --hash=sha256:36e8e32621a9e2a9abe75dc15a4b54a3997f2d8b1e53ad754bae48a083c91130 \ + --hash=sha256:40c5220ec93790b18ec6278da9c6ac2608d997ee6d6f7cd44c5c3992764e8e71 \ + --hash=sha256:446d500a2977c6ae2077f340c510a25956da5c77597175c316edfa87248ceda3 \ + --hash=sha256:46f92ada9023e59f27edc048167b31ac9a03911978b1296c845a34462a27f096 \ + --hash=sha256:482f8a13f2600f527e427f73c42b5aa75536f9892868068f0aaf573055a0135f \ + --hash=sha256:553c273a6a8f140adaa6da6a6135c7f95bdc8c2e5f95252fcdf9832d758e2141 \ + --hash=sha256:5ae7c0d744d64e2753149634787cc4ab60f05ef1e542b060eeab719f3cdb7723 \ + --hash=sha256:5d4147422d91ccdc2d2abf6ed24196025e020259d1d267970ae20c13c2ce84b1 \ + --hash=sha256:6af347debc8b721aa72e48671166282da979d5e5ae52dbc660ab417282b48e23 \ + --hash=sha256:6ba302115f63f6482c000ccfd62efdb6c41d9d182a5bcd4a90e7ab8cd13856eb \ + --hash=sha256:6f7361d66cc801d9eb4df734b139cd7b0e3c257a16f3573ebd550ddb255549e6 \ + --hash=sha256:715f05ea198d20d7f8b407b9b84e0023d17f2b9096c194cea702b7840e74f1f7 \ + --hash=sha256:71dddcebbc5a70e946a06c30b59b5dd7999c9833d307168f90fb4e4b672ab63e \ + --hash=sha256:8150c569b2aa4573b51ba8475e814aa41fd53a3d510c1ffb96f1139f46faf611 \ + --hash=sha256:8843bd9594e1387f1e601439e19ad73abdf57356104fd1e53a708255bb95a13d \ + --hash=sha256:8c0088765747ae5d6c9f89987bb36f9fb83564f07090d721344ce8e1abedffea \ + --hash=sha256:972d0dbf283508f9bc446ee09c3838cb7c7f114b5bdceee41753288c97fe2f7c \ + --hash=sha256:a28531cee2a5a42d89f9ba4da53bfeb15681f12acc0263476c8705380dadce07 \ + --hash=sha256:a3be2072315982e232bfe49c9d3db0a59ba67b2240a537ef42656cc772a887c7 \ + --hash=sha256:ac2804043bd1bc10b5da18f8f4c706877197263a510c41be9b4c0062f5783dcc \ + --hash=sha256:afab8b4b1f4469c3879bb049dd039f8fce402712050324e9524a43d7324c5e87 \ + --hash=sha256:b370d1620a34a4538ef66524fcee9de8171fa263c701036a92bc0b4c1f2f9c6d \ + --hash=sha256:b8b0808dba0c63b7633bdaefb34e08fe0612622224f9feb0e7518904b1615101 \ + --hash=sha256:bc7ca6a1a40e7e4c933017e6c09ef18032add793df4e42624c6c0c87e0bebdad \ + --hash=sha256:caa65e1f5bf007430bf657c37cab7ab81a4ddf8d337e3062bcc5085d17ef038b \ + --hash=sha256:d68c5a01a283cb13b79eafe016fe5869aa11bff8c46e7141c70aa0aac808010f \ + --hash=sha256:da137802688190835b4c863cafa77fd7e29dff662ee6d905a9ffc14f00299c91 \ + --hash=sha256:e56a20ab6cdb90a95b0c99652e28de3504ce77129087319c03c9098266183ae5 \ + --hash=sha256:e878ccb7d20872065e1597935fdb5e65efa43220c8edd0d9c4a1a7ff1f3eb277 \ + --hash=sha256:eba81e0b3011c1f23df7ea47ef4ffaa8239817959ae291515b6efd068bde2161 \ + --hash=sha256:ed6d23a3f806898e69c77430ebd8da0c79c219f97b9acbc9a29a653e09740c59 # via ibis-framework durationpy==0.10 \ --hash=sha256:1fa6893409a6e739c9c72334fc65cca1f355dbdd93405d30f726deb5bde42fba \ --hash=sha256:3b41e1b601234296b4fb368338fdcd3e13e0b4fb5b67345948f4f2bf9868b286 # via kubernetes -fastapi==0.129.0 \ - --hash=sha256:61315cebd2e65df5f97ec298c888f9de30430dd0612d59d6480beafbc10655af \ - --hash=sha256:b4946880e48f462692b31c083be0432275cbfb6e2274566b1be91479cc1a84ec +fastapi==0.135.3 \ + --hash=sha256:9b0f590c813acd13d0ab43dd8494138eb58e484bfac405db1f3187cfc5810d98 \ + --hash=sha256:bd6d7caf1a2bdd8d676843cdcd2287729572a1ef524fc4d65c17ae002a1be654 # via # feast (pyproject.toml) # fastapi-mcp @@ -632,9 +642,9 @@ fastapi-mcp==0.4.0 \ --hash=sha256:d4a3fe7966af24d44e4b412720561c95eb12bed999a4443a88221834b3b15aec \ --hash=sha256:d4ca9410996f4c7b8ea0d7b20fdf79878dc359ebf89cbf3b222e0b675a55097d # via feast (pyproject.toml) -filelock==3.24.2 \ - --hash=sha256:667d7dc0b7d1e1064dd5f8f8e80bdac157a6482e8d2e02cd16fd3b6b33bd6556 \ - --hash=sha256:c22803117490f156e59fafce621f0550a7a853e2bbf4f87f112b11d469b6c81b +filelock==3.25.2 \ + --hash=sha256:b64ece2b38f4ca29dd3e810287aa8c48182bbecd1ae6e9ae126c9b35f1382694 \ + --hash=sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70 # via snowflake-connector-python flit-core==3.12.0 \ --hash=sha256:18f63100d6f94385c6ed57a72073443e1a71a4acb4339491615d0f16d6ff01b2 \ @@ -780,9 +790,9 @@ fsspec==2024.9.0 \ # via # feast (pyproject.toml) # dask -google-api-core[grpc]==2.29.0 \ - --hash=sha256:84181be0f8e6b04006df75ddfe728f24489f0af57c96a529ff7cf45bc28797f7 \ - --hash=sha256:d30bc60980daa36e314b5d5a3e5958b0200cb44ca8fa1be2b614e932b75a3ea9 +google-api-core[grpc]==2.30.2 \ + --hash=sha256:9a8113e1a88bdc09a7ff629707f2214d98d61c7f6ceb0ea38c42a095d02dc0f9 \ + --hash=sha256:a4c226766d6af2580577db1f1a51bf53cd262f722b49731ce7414c43068a9594 # via # feast (pyproject.toml) # google-cloud-bigquery @@ -792,9 +802,9 @@ google-api-core[grpc]==2.29.0 \ # google-cloud-datastore # google-cloud-storage # pandas-gbq -google-auth==2.48.0 \ - --hash=sha256:2e2a537873d449434252a9632c28bfc268b0adb1e53f9fb62afc5333a975903f \ - --hash=sha256:4f7e706b0cd3208a3d940a19a822c37a476ddba5450156c3e6624a71f7c841ce +google-auth==2.49.1 \ + --hash=sha256:16d40da1c3c5a0533f57d268fe72e0ebb0ae1cc3b567024122651c045d879b64 \ + --hash=sha256:195ebe3dca18eddd1b3db5edc5189b76c13e96f29e73043b923ebcf3f1a860f7 # via # google-api-core # google-auth-oauthlib @@ -806,37 +816,37 @@ google-auth==2.48.0 \ # google-cloud-storage # pandas-gbq # pydata-google-auth -google-auth-oauthlib==1.2.4 \ - --hash=sha256:0e922eea5f2baacaf8867febb782e46e7b153236c21592ed76ab3ddb77ffd772 \ - --hash=sha256:3ca93859c6cc9003c8e12b2a0868915209d7953f05a70f4880ab57d57e56ee3e +google-auth-oauthlib==1.3.1 \ + --hash=sha256:14c22c7b3dd3d06dbe44264144409039465effdd1eef94f7ce3710e486cc4bfa \ + --hash=sha256:1a139ef23f1318756805b0e95f655c238bffd29655329a2978218248da4ee7f8 # via # pandas-gbq # pydata-google-auth -google-cloud-bigquery[pandas]==3.40.1 \ - --hash=sha256:75afcfb6e007238fe1deefb2182105249321145ff921784fe7b1de2b4ba24506 \ - --hash=sha256:9082a6b8193aba87bed6a2c79cf1152b524c99bb7e7ac33a785e333c09eac868 +google-cloud-bigquery[pandas]==3.41.0 \ + --hash=sha256:2217e488b47ed576360c9b2cc07d59d883a54b83167c0ef37f915c26b01a06fe \ + --hash=sha256:2a5b5a737b401cbd824a6e5eac7554100b878668d908e6548836b5d8aaa4dcaa # via # feast (pyproject.toml) # pandas-gbq -google-cloud-bigquery-storage==2.36.1 \ - --hash=sha256:99ad6b8810d028f0cf368ea0cc54b3cda20e856f05eb4cda51f1db2a70692286 \ - --hash=sha256:fd3917584a41f7a9d9c633b31ff43103869b108224e8a4b765537eb1ea83148c +google-cloud-bigquery-storage==2.37.0 \ + --hash=sha256:1e319c27ef60fc31030f6e0b52e5e891e1cdd50551effe8c6f673a4c3c56fcb6 \ + --hash=sha256:f88ee7f1e49db1e639da3d9a8b79835ca4bc47afbb514fb2adfc0ccb41a7fd97 # via feast (pyproject.toml) -google-cloud-bigtable==2.35.0 \ - --hash=sha256:f355bfce1f239453ec2bb3839b0f4f9937cf34ef06ef29e1ca63d58fd38d0c50 \ - --hash=sha256:f5699012c5fea4bd4bdf7e80e5e3a812a847eb8f41bf8dc2f43095d6d876b83b +google-cloud-bigtable==2.36.0 \ + --hash=sha256:21b2f41231b7368a550b44d5b493b811b3507fcb23eb26d00005cd3f205f2207 \ + --hash=sha256:d5987733c2f60c739f93f259d2037858411cc994ac37cdfbccb6bb159f3ca43e # via feast (pyproject.toml) -google-cloud-core==2.5.0 \ - --hash=sha256:67d977b41ae6c7211ee830c7912e41003ea8194bff15ae7d72fd6f51e57acabc \ - --hash=sha256:7c1b7ef5c92311717bd05301aa1a91ffbc565673d3b0b4163a52d8413a186963 +google-cloud-core==2.5.1 \ + --hash=sha256:3dc94bdec9d05a31d9f355045ed0f369fbc0d8c665076c734f065d729800f811 \ + --hash=sha256:ea62cdf502c20e3e14be8a32c05ed02113d7bef454e40ff3fab6fe1ec9f1f4e7 # via # google-cloud-bigquery # google-cloud-bigtable # google-cloud-datastore # google-cloud-storage -google-cloud-datastore==2.23.0 \ - --hash=sha256:24a1b1d29b902148fe41b109699f76fd3aa60591e9d547c0f8b87d7bf9ff213f \ - --hash=sha256:80049883a4ae928fdcc661ba6803ec267665dc0e6f3ce2da91441079a6bb6387 +google-cloud-datastore==2.24.0 \ + --hash=sha256:81f1d1c12c2906f59507f72742545ab04c38f62ed70b0542057e3cf04a53aa65 \ + --hash=sha256:f087c02a6aa4ac68bbf17f0c048ae3ee355856bf09c51439bfba193741387792 # via feast (pyproject.toml) google-cloud-storage==2.19.0 \ --hash=sha256:aeb971b5c29cf8ab98445082cbfe7b161a1f48ed275822f59ed3f1524ea54fba \ @@ -880,78 +890,78 @@ google-crc32c==1.8.0 \ # google-cloud-bigtable # google-cloud-storage # google-resumable-media -google-resumable-media==2.8.0 \ - --hash=sha256:dd14a116af303845a8d932ddae161a26e86cc229645bc98b39f026f9b1717582 \ - --hash=sha256:f1157ed8b46994d60a1bc432544db62352043113684d4e030ee02e77ebe9a1ae +google-resumable-media==2.8.2 \ + --hash=sha256:82b6d8ccd11765268cdd2a2123f417ec806b8eef3000a9a38dfe3033da5fb220 \ + --hash=sha256:f3354a182ebd193ae3f42e3ef95e6c9b10f128320de23ac7637236713b1acd70 # via # google-cloud-bigquery # google-cloud-storage -googleapis-common-protos[grpc]==1.72.0 \ - --hash=sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038 \ - --hash=sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5 +googleapis-common-protos[grpc]==1.74.0 \ + --hash=sha256:57971e4eeeba6aad1163c1f0fc88543f965bb49129b8bb55b2b7b26ecab084f1 \ + --hash=sha256:702216f78610bb510e3f12ac3cafd281b7ac45cc5d86e90ad87e4d301a3426b5 # via # feast (pyproject.toml) # google-api-core # grpc-google-iam-v1 # grpcio-status -greenlet==3.3.1 \ - --hash=sha256:02925a0bfffc41e542c70aa14c7eda3593e4d7e274bfcccca1827e6c0875902e \ - --hash=sha256:04bee4775f40ecefcdaa9d115ab44736cd4b9c5fba733575bfe9379419582e13 \ - --hash=sha256:070472cd156f0656f86f92e954591644e158fd65aa415ffbe2d44ca77656a8f5 \ - --hash=sha256:09f51496a0bfbaa9d74d36a52d2580d1ef5ed4fdfcff0a73730abfbbbe1403dd \ - --hash=sha256:1108b61b06b5224656121c3c8ee8876161c491cbe74e5c519e0634c837cf93d5 \ - --hash=sha256:12184c61e5d64268a160226fb4818af4df02cfead8379d7f8b99a56c3a54ff3e \ - --hash=sha256:14194f5f4305800ff329cbf02c5fcc88f01886cadd29941b807668a45f0d2336 \ - --hash=sha256:20fedaadd422fa02695f82093f9a98bad3dab5fcda793c658b945fcde2ab27ba \ - --hash=sha256:27289986f4e5b0edec7b5a91063c109f0276abb09a7e9bdab08437525977c946 \ - --hash=sha256:2f080e028001c5273e0b42690eaf359aeef9cb1389da0f171ea51a5dc3c7608d \ - --hash=sha256:301860987846c24cb8964bdec0e31a96ad4a2a801b41b4ef40963c1b44f33451 \ - --hash=sha256:32e4ca9777c5addcbf42ff3915d99030d8e00173a56f80001fb3875998fe410b \ - --hash=sha256:33a956fe78bbbda82bfc95e128d61129b32d66bcf0a20a1f0c08aa4839ffa951 \ - --hash=sha256:34a729e2e4e4ffe9ae2408d5ecaf12f944853f40ad724929b7585bca808a9d6f \ - --hash=sha256:39eda9ba259cc9801da05351eaa8576e9aa83eb9411e8f0c299e05d712a210f2 \ - --hash=sha256:3a300354f27dd86bae5fbf7002e6dd2b3255cd372e9242c933faf5e859b703fe \ - --hash=sha256:3e0f3878ca3a3ff63ab4ea478585942b53df66ddde327b59ecb191b19dbbd62d \ - --hash=sha256:3e63252943c921b90abb035ebe9de832c436401d9c45f262d80e2d06cc659242 \ - --hash=sha256:41848f3230b58c08bb43dee542e74a2a2e34d3c59dc3076cec9151aeeedcae98 \ - --hash=sha256:49f4ad195d45f4a66a0eb9c1ba4832bb380570d361912fa3554746830d332149 \ - --hash=sha256:4b065d3284be43728dd280f6f9a13990b56470b81be20375a207cdc814a983f2 \ - --hash=sha256:4b9721549a95db96689458a1e0ae32412ca18776ed004463df3a9299c1b257ab \ - --hash=sha256:50e1457f4fed12a50e427988a07f0f9df53cf0ee8da23fab16e6732c2ec909d4 \ - --hash=sha256:59913f1e5ada20fde795ba906916aea25d442abcc0593fba7e26c92b7ad76249 \ - --hash=sha256:5fd23b9bc6d37b563211c6abbb1b3cab27db385a4449af5c32e932f93017080c \ - --hash=sha256:6423481193bbbe871313de5fd06a082f2649e7ce6e08015d2a76c1e9186ca5b3 \ - --hash=sha256:65be2f026ca6a176f88fb935ee23c18333ccea97048076aef4db1ef5bc0713ac \ - --hash=sha256:67ea3fc73c8cd92f42467a72b75e8f05ed51a0e9b1d15398c913416f2dafd49f \ - --hash=sha256:71c767cf281a80d02b6c1bdc41c9468e1f5a494fb11bc8688c360524e273d7b1 \ - --hash=sha256:76e39058e68eb125de10c92524573924e827927df5d3891fbc97bd55764a8774 \ - --hash=sha256:7932f5f57609b6a3b82cc11877709aa7a98e3308983ed93552a1c377069b20c8 \ - --hash=sha256:7a3ae05b3d225b4155bda56b072ceb09d05e974bc74be6c3fc15463cf69f33fd \ - --hash=sha256:7ab327905cabb0622adca5971e488064e35115430cec2c35a50fd36e72a315b3 \ - --hash=sha256:7b2fe4150a0cf59f847a67db8c155ac36aed89080a6a639e9f16df5d6c6096f1 \ - --hash=sha256:7e806ca53acf6d15a888405880766ec84721aa4181261cd11a457dfe9a7a4975 \ - --hash=sha256:80aa4d79eb5564f2e0a6144fcc744b5a37c56c4a92d60920720e99210d88db0f \ - --hash=sha256:92497c78adf3ac703b57f1e3813c2d874f27f71a178f9ea5887855da413cd6d2 \ - --hash=sha256:96aff77af063b607f2489473484e39a0bbae730f2ea90c9e5606c9b73c44174a \ - --hash=sha256:aec9ab04e82918e623415947921dea15851b152b822661cce3f8e4393c3df683 \ - --hash=sha256:b066e8b50e28b503f604fa538adc764a638b38cf8e81e025011d26e8a627fa79 \ - --hash=sha256:b31c05dd84ef6871dd47120386aed35323c944d86c3d91a17c4b8d23df62f15b \ - --hash=sha256:bd59acd8529b372775cd0fcbc5f420ae20681c5b045ce25bd453ed8455ab99b5 \ - --hash=sha256:bfb2d1763d777de5ee495c85309460f6fd8146e50ec9d0ae0183dbf6f0a829d1 \ - --hash=sha256:c620051669fd04ac6b60ebc70478210119c56e2d5d5df848baec4312e260e4ca \ - --hash=sha256:c9f9d5e7a9310b7a2f416dd13d2e3fd8b42d803968ea580b7c0f322ccb389b97 \ - --hash=sha256:cb0feb07fe6e6a74615ee62a880007d976cf739b6669cce95daa7373d4fc69c5 \ - --hash=sha256:cc98b9c4e4870fa983436afa999d4eb16b12872fab7071423d5262fa7120d57a \ - --hash=sha256:d842c94b9155f1c9b3058036c24ffb8ff78b428414a19792b2380be9cecf4f36 \ - --hash=sha256:da19609432f353fed186cc1b85e9440db93d489f198b4bdf42ae19cc9d9ac9b4 \ - --hash=sha256:e0093bd1a06d899892427217f0ff2a3c8f306182b8c754336d32e2d587c131b4 \ - --hash=sha256:e2e7e882f83149f0a71ac822ebf156d902e7a5d22c9045e3e0d1daf59cee2cc9 \ - --hash=sha256:e84b51cbebf9ae573b5fbd15df88887815e3253fc000a7d0ff95170e8f7e9729 \ - --hash=sha256:ed6b402bc74d6557a705e197d47f9063733091ed6357b3de33619d8a8d93ac53 +greenlet==3.3.2 \ + --hash=sha256:02b0a8682aecd4d3c6c18edf52bc8e51eacdd75c8eac52a790a210b06aa295fd \ + --hash=sha256:18cb1b7337bca281915b3c5d5ae19f4e76d35e1df80f4ad3c1a7be91fadf1082 \ + --hash=sha256:1a9172f5bf6bd88e6ba5a84e0a68afeac9dc7b6b412b245dd64f52d83c81e55b \ + --hash=sha256:1e692b2dae4cc7077cbb11b47d258533b48c8fde69a33d0d8a82e2fe8d8531d5 \ + --hash=sha256:1ebd458fa8285960f382841da585e02201b53a5ec2bac6b156fc623b5ce4499f \ + --hash=sha256:1fb39a11ee2e4d94be9a76671482be9398560955c9e568550de0224e41104727 \ + --hash=sha256:20154044d9085151bc309e7689d6f7ba10027f8f5a8c0676ad398b951913d89e \ + --hash=sha256:2eaf067fc6d886931c7962e8c6bede15d2f01965560f3359b27c80bde2d151f2 \ + --hash=sha256:34308836d8370bddadb41f5a7ce96879b72e2fdfb4e87729330c6ab52376409f \ + --hash=sha256:394ead29063ee3515b4e775216cb756b2e3b4a7e55ae8fd884f17fa579e6b327 \ + --hash=sha256:3ceec72030dae6ac0c8ed7591b96b70410a8be370b6a477b1dbc072856ad02bd \ + --hash=sha256:4375a58e49522698d3e70cc0b801c19433021b5c37686f7ce9c65b0d5c8677d2 \ + --hash=sha256:43e99d1749147ac21dde49b99c9abffcbc1e2d55c67501465ef0930d6e78e070 \ + --hash=sha256:442b6057453c8cb29b4fb36a2ac689382fc71112273726e2423f7f17dc73bf99 \ + --hash=sha256:45abe8eb6339518180d5a7fa47fa01945414d7cca5ecb745346fc6a87d2750be \ + --hash=sha256:4c956a19350e2c37f2c48b336a3afb4bff120b36076d9d7fb68cb44e05d95b79 \ + --hash=sha256:508c7f01f1791fbc8e011bd508f6794cb95397fdb198a46cb6635eb5b78d85a7 \ + --hash=sha256:527fec58dc9f90efd594b9b700662ed3fb2493c2122067ac9c740d98080a620e \ + --hash=sha256:59b3e2c40f6706b05a9cd299c836c6aa2378cabe25d021acd80f13abf81181cf \ + --hash=sha256:5d0e35379f93a6d0222de929a25ab47b5eb35b5ef4721c2b9cbcc4036129ff1f \ + --hash=sha256:63d10328839d1973e5ba35e98cccbca71b232b14051fd957b6f8b6e8e80d0506 \ + --hash=sha256:64970c33a50551c7c50491671265d8954046cb6e8e2999aacdd60e439b70418a \ + --hash=sha256:6c6f8ba97d17a1e7d664151284cb3315fc5f8353e75221ed4324f84eb162b395 \ + --hash=sha256:8b466dff7a4ffda6ca975979bab80bdadde979e29fc947ac3be4451428d8b0e4 \ + --hash=sha256:8c1fdd7d1b309ff0da81d60a9688a8bd044ac4e18b250320a96fc68d31c209ca \ + --hash=sha256:8c4dd0f3997cf2512f7601563cc90dfb8957c0cff1e3a1b23991d4ea1776c492 \ + --hash=sha256:8d1658d7291f9859beed69a776c10822a0a799bc4bfe1bd4272bb60e62507dab \ + --hash=sha256:8e2cd90d413acbf5e77ae41e5d3c9b3ac1d011a756d7284d7f3f2b806bbd6358 \ + --hash=sha256:8e4ab3cfb02993c8cc248ea73d7dae6cec0253e9afa311c9b37e603ca9fad2ce \ + --hash=sha256:94ad81f0fd3c0c0681a018a976e5c2bd2ca2d9d94895f23e7bb1af4e8af4e2d5 \ + --hash=sha256:97245cc10e5515dbc8c3104b2928f7f02b6813002770cfaffaf9a6e0fc2b94ef \ + --hash=sha256:9bc885b89709d901859cf95179ec9f6bb67a3d2bb1f0e88456461bd4b7f8fd0d \ + --hash=sha256:a2a5be83a45ce6188c045bcc44b0ee037d6a518978de9a5d97438548b953a1ac \ + --hash=sha256:a443358b33c4ec7b05b79a7c8b466f5d275025e750298be7340f8fc63dff2a55 \ + --hash=sha256:a7945dd0eab63ded0a48e4dcade82939783c172290a7903ebde9e184333ca124 \ + --hash=sha256:aa6ac98bdfd716a749b84d4034486863fd81c3abde9aa3cf8eff9127981a4ae4 \ + --hash=sha256:ab0c7e7901a00bc0a7284907273dc165b32e0d109a6713babd04471327ff7986 \ + --hash=sha256:ac8d61d4343b799d1e526db579833d72f23759c71e07181c2d2944e429eb09cd \ + --hash=sha256:ad0c8917dd42a819fe77e6bdfcb84e3379c0de956469301d9fd36427a1ca501f \ + --hash=sha256:ae9e21c84035c490506c17002f5c8ab25f980205c3e61ddb3a2a2a2e6c411fcb \ + --hash=sha256:b26b0f4428b871a751968285a1ac9648944cea09807177ac639b030bddebcea4 \ + --hash=sha256:b568183cf65b94919be4438dc28416b234b678c608cafac8874dfeeb2a9bbe13 \ + --hash=sha256:b6997d360a4e6a4e936c0f9625b1c20416b8a0ea18a8e19cabbefc712e7397ab \ + --hash=sha256:b8bddc5b73c9720bea487b3bffdb1840fe4e3656fba3bd40aa1489e9f37877ff \ + --hash=sha256:c04c5e06ec3e022cbfe2cd4a846e1d4e50087444f875ff6d2c2ad8445495cf1a \ + --hash=sha256:c2e47408e8ce1c6f1ceea0dffcdf6ebb85cc09e55c7af407c99f1112016e45e9 \ + --hash=sha256:c56692189a7d1c7606cb794be0a8381470d95c57ce5be03fb3d0ef57c7853b86 \ + --hash=sha256:ccd21bb86944ca9be6d967cf7691e658e43417782bce90b5d2faeda0ff78a7dd \ + --hash=sha256:cd6f9e2bbd46321ba3bbb4c8a15794d32960e3b0ae2cc4d49a1a53d314805d71 \ + --hash=sha256:d248d8c23c67d2291ffd47af766e2a3aa9fa1c6703155c099feb11f526c63a92 \ + --hash=sha256:d3a62fa76a32b462a97198e4c9e99afb9ab375115e74e9a83ce180e7a496f643 \ + --hash=sha256:e26e72bec7ab387ac80caa7496e0f908ff954f31065b0ffc1f8ecb1338b11b54 \ + --hash=sha256:e3cb43ce200f59483eb82949bf1835a99cf43d7571e900d7c8d5c62cdf25d2f9 # via feast (pyproject.toml) -grpc-google-iam-v1==0.14.3 \ - --hash=sha256:7a7f697e017a067206a3dfef44e4c634a34d3dee135fe7d7a4613fe3e59217e6 \ - --hash=sha256:879ac4ef33136c5491a6300e27575a9ec760f6cdf9a2518798c1b8977a5dc389 +grpc-google-iam-v1==0.14.4 \ + --hash=sha256:392b3796947ed6334e61171d9ab06bf7eb357f554e5fc7556ad7aab6d0e17038 \ + --hash=sha256:412facc320fcbd94034b4df3d557662051d4d8adfa86e0ddb4dca70a3f739964 # via google-cloud-bigtable grpcio==1.62.3 \ --hash=sha256:059444f0ed5dba73ab7dd0ee7e8e6b606df4130d2b0a9f010f84da4ab9f6c2d8 \ @@ -1032,9 +1042,9 @@ grpcio-status==1.62.3 \ --hash=sha256:289bdd7b2459794a12cf95dc0cb727bd4a1742c37bd823f760236c937e53a485 \ --hash=sha256:f9049b762ba8de6b1086789d8315846e094edac2c50beaf462338b301a8fd4b8 # via google-api-core -gunicorn==25.1.0 \ - --hash=sha256:1426611d959fa77e7de89f8c0f32eed6aa03ee735f98c01efba3e281b1c47616 \ - --hash=sha256:d0b1236ccf27f72cfe14bce7caadf467186f19e865094ca84221424e839b8b8b +gunicorn==25.3.0 \ + --hash=sha256:cacea387dab08cd6776501621c295a904fe8e3b7aae9a1a3cbb26f4e7ed54660 \ + --hash=sha256:f74e1b2f9f76f6cd1ca01198968bd2dd65830edc24b6e8e4d78de8320e2fe889 # via # feast (pyproject.toml) # uvicorn-worker @@ -1052,9 +1062,9 @@ hatch-vcs==0.4.0 \ --hash=sha256:093810748fe01db0d451fabcf2c1ac2688caefd232d4ede967090b1c1b07d9f7 \ --hash=sha256:b8a2b6bee54cf6f9fc93762db73890017ae59c9081d1038a41f16235ceaf8b2c # via feast (pyproject.toml) -hatchling==1.28.0 \ - --hash=sha256:4d50b02aece6892b8cd0b3ce6c82cb218594d3ec5836dbde75bf41a21ab004c8 \ - --hash=sha256:dc48722b68b3f4bbfa3ff618ca07cdea6750e7d03481289ffa8be1521d18a961 +hatchling==1.29.0 \ + --hash=sha256:50af9343281f34785fab12da82e445ed987a6efb34fd8c2fc0f6e6630dbcc1b0 \ + --hash=sha256:793c31816d952cee405b83488ce001c719f325d9cda69f1fc4cd750527640ea6 # via # feast (pyproject.toml) # hatch-fancy-pypi-readme @@ -1227,13 +1237,13 @@ idna==3.11 \ # requests # snowflake-connector-python # yarl -imagesize==1.4.1 \ - --hash=sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b \ - --hash=sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a +imagesize==2.0.0 \ + --hash=sha256:5667c5bbb57ab3f1fa4bc366f4fbc971db3d5ed011fd2715fd8001f782718d96 \ + --hash=sha256:8e8358c4a05c304f1fccf7ff96f036e7243a189e9e42e90851993c558cfe9ee3 # via sphinx -importlib-metadata==8.7.1 \ - --hash=sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb \ - --hash=sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151 +importlib-metadata==9.0.0 \ + --hash=sha256:2d21d1cc5a017bd0559e36150c21c830ab1dc304dedd1b7ea85d20f45ef3edd7 \ + --hash=sha256:a4f57ab599e6a2e3016d7595cfd72eb4661a5106e787a95bcc90c7105b831efc # via dask jinja2==3.1.6 \ --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ @@ -1262,97 +1272,97 @@ kubernetes==35.0.0 \ --hash=sha256:39e2b33b46e5834ef6c3985ebfe2047ab39135d41de51ce7641a7ca5b372a13d \ --hash=sha256:3d00d344944239821458b9efd484d6df9f011da367ecb155dadf9513f05f09ee # via feast (pyproject.toml) -librt==0.8.0 \ - --hash=sha256:001e5330093d887b8b9165823eca6c5c4db183fe4edea4fdc0680bbac5f46944 \ - --hash=sha256:015e2dde6e096d27c10238bf9f6492ba6c65822dfb69d2bf74c41a8e88b7ddef \ - --hash=sha256:02a9fe85410cc9bef045e7cb7fd26fdde6669e6d173f99df659aa7f6335961e9 \ - --hash=sha256:0583aef7e9a720dd40f26a2ad5a1bf2ccbb90059dac2b32ac516df232c701db3 \ - --hash=sha256:05a3dd3f116747f7e1a2b475ccdc6fb637fd4987126d109e03013a79d40bf9e6 \ - --hash=sha256:0a33335eb59921e77c9acc05d0e654e4e32e45b014a4d61517897c11591094f8 \ - --hash=sha256:0ce33a9778e294507f3a0e3468eccb6a698b5166df7db85661543eca1cfc5369 \ - --hash=sha256:1566dbb9d1eb0987264c9b9460d212e809ba908d2f4a3999383a84d765f2f3f1 \ - --hash=sha256:17269dd2745dbe8e42475acb28e419ad92dfa38214224b1b01020b8cac70b645 \ - --hash=sha256:178707cda89d910c3b28bf5aa5f69d3d4734e0f6ae102f753ad79edef83a83c7 \ - --hash=sha256:1c25a131013eadd3c600686a0c0333eb2896483cbc7f65baa6a7ee761017aef9 \ - --hash=sha256:1e6811cac1dcb27ca4c74e0ca4a5917a8e06db0d8408d30daee3a41724bfde7a \ - --hash=sha256:1ef3bd856373cf8e7382402731f43bfe978a8613b4039e49e166e1e0dc590216 \ - --hash=sha256:20f73d4fecba969efc15cdefd030e382502d56bb6f1fc66b580cce582836c9fa \ - --hash=sha256:21b14464bee0b604d80a638cf1ee3148d84ca4cc163dcdcecb46060c1b3605e4 \ - --hash=sha256:24a01c13a2a9bdad20997a4443ebe6e329df063d1978bbe2ebbf637878a46d1e \ - --hash=sha256:25b3e667cbfc9000c4740b282df599ebd91dbdcc1aa6785050e4c1d6be5329ab \ - --hash=sha256:25e82d920d4d62ad741592fcf8d0f3bda0e3fc388a184cb7d2f566c681c5f7b9 \ - --hash=sha256:2b37437e7e4ef5e15a297b36ba9e577f73e29564131d86dd75875705e97402b5 \ - --hash=sha256:2ccdd20d9a72c562ffb73098ac411de351b53a6fbb3390903b2d33078ef90447 \ - --hash=sha256:2e0ffe88ebb5962f8fb0ddcbaaff30f1ea06a79501069310e1e030eafb1ad787 \ - --hash=sha256:375eda7acfce1f15f5ed56cfc960669eefa1ec8732e3e9087c3c4c3f2066759c \ - --hash=sha256:3d2720335020219197380ccfa5c895f079ac364b4c429e96952cd6509934d8eb \ - --hash=sha256:3e36a8da17134ffc29373775d88c04832f9ecfab1880470661813e6c7991ef79 \ - --hash=sha256:3e8b77b5f54d0937b26512774916041756c9eb3e66f1031971e626eea49d0bf4 \ - --hash=sha256:41064a0c07b4cc7a81355ccc305cb097d6027002209ffca51306e65ee8293630 \ - --hash=sha256:421765e8c6b18e64d21c8ead315708a56fc24f44075059702e421d164575fdda \ - --hash=sha256:4831c44b8919e75ca0dfb52052897c1ef59fdae19d3589893fbd068f1e41afbf \ - --hash=sha256:48f84830a8f8ad7918afd743fd7c4eb558728bceab7b0e38fd5a5cf78206a556 \ - --hash=sha256:4b705f85311ee76acec5ee70806990a51f0deb519ea0c29c1d1652d79127604d \ - --hash=sha256:4d3e38797eb482485b486898f89415a6ab163bc291476bd95712e42cf4383c05 \ - --hash=sha256:4eb5e06ebcc668677ed6389164f52f13f71737fc8be471101fa8b4ce77baeb0c \ - --hash=sha256:4f6e975377fbc4c9567cb33ea9ab826031b6c7ec0515bfae66a4fb110d40d6da \ - --hash=sha256:4f764b2424cb04524ff7a486b9c391e93f93dc1bd8305b2136d25e582e99aa2f \ - --hash=sha256:507e94f4bec00b2f590fbe55f48cd518a208e2474a3b90a60aa8f29136ddbada \ - --hash=sha256:56901f1eec031396f230db71c59a01d450715cbbef9856bf636726994331195d \ - --hash=sha256:5cb11061a736a9db45e3c1293cfcb1e3caf205912dfa085734ba750f2197ff9a \ - --hash=sha256:5d0f76fc73480d42285c609c0ea74d79856c160fa828ff9aceab574ea4ecfd7b \ - --hash=sha256:667e2513cf69bfd1e1ed9a00d6c736d5108714ec071192afb737987955888a25 \ - --hash=sha256:671a6152edf3b924d98a5ed5e6982ec9cb30894085482acadce0975f031d4c5c \ - --hash=sha256:693697133c3b32aa9b27f040e3691be210e9ac4d905061859a9ed519b1d5a376 \ - --hash=sha256:6a3146c63220d814c4a2c7d6a1eacc8d5c14aed0ff85115c1dfea868080cd18f \ - --hash=sha256:6b6caff69e25d80c269b1952be8493b4d94ef745f438fa619d7931066bdd26de \ - --hash=sha256:6e1af31a710e17891d9adf0dbd9a5fcd94901a3922a96499abdbf7ce658f4e01 \ - --hash=sha256:70defb797c4d5402166787a6b3c66dfb3fa7f93d118c0509ffafa35a392f4258 \ - --hash=sha256:71fc517efc14f75c2f74b1f0a5d5eb4a8e06aa135c34d18eaf3522f4a53cd62d \ - --hash=sha256:75d1a8cab20b2043f03f7aab730551e9e440adc034d776f15f6f8d582b0a5ad4 \ - --hash=sha256:789911e8fa40a2e82f41120c936b1965f3213c67f5a483fc5a41f5839a05dcbb \ - --hash=sha256:7bd68cebf3131bb920d5984f75fe302d758db33264e44b45ad139385662d7bc3 \ - --hash=sha256:7ce0a8cb67e702dcb06342b2aaaa3da9fb0ddc670417879adfa088b44cf7b3b6 \ - --hash=sha256:7f820210e21e3a8bf8fde2ae3c3d10106d4de9ead28cbfdf6d0f0f41f5b12fa1 \ - --hash=sha256:8070aa3368559de81061ef752770d03ca1f5fc9467d4d512d405bd0483bfffe6 \ - --hash=sha256:82e61cd1c563745ad495387c3b65806bfd453badb4adbc019df3389dddee1bf6 \ - --hash=sha256:82fb4602d1b3e303a58bfe6165992b5a78d823ec646445356c332cd5f5bbaa61 \ - --hash=sha256:88c6e75540f1f10f5e0fc5e87b4b6c290f0e90d1db8c6734f670840494764af8 \ - --hash=sha256:8992ca186a1678107b0af3d0c9303d8c7305981b9914989b9788319ed4d89546 \ - --hash=sha256:92249938ab744a5890580d3cb2b22042f0dce71cdaa7c1369823df62bedf7cbc \ - --hash=sha256:95a719a049f0eefaf1952673223cf00d442952273cbd20cf2ed7ec423a0ef58d \ - --hash=sha256:9646178cd794704d722306c2c920c221abbf080fede3ba539d5afdec16c46dad \ - --hash=sha256:9726305d3e53419d27fc8cdfcd3f9571f0ceae22fa6b5ea1b3662c2e538f833e \ - --hash=sha256:995d24caa6bbb34bcdd4a41df98ac6d1af637cfa8975cb0790e47d6623e70e3e \ - --hash=sha256:9ab3a3475a55b89b87ffd7e6665838e8458e0b596c22e0177e0f961434ec474a \ - --hash=sha256:9f09d4884f882baa39a7e36bbf3eae124c4ca2a223efb91e567381d1c55c6b06 \ - --hash=sha256:a512c88900bdb1d448882f5623a0b1ad27ba81a9bd75dacfe17080b72272ca1f \ - --hash=sha256:a905091a13e0884701226860836d0386b88c72ce5c2fdfba6618e14c72be9f25 \ - --hash=sha256:aaadec87f45a3612b6818d1db5fbfe93630669b7ee5d6bdb6427ae08a1aa2141 \ - --hash=sha256:b055bb3abaf69abed25743d8fc1ab691e4f51a912ee0a6f9a6c84f4bbddb283d \ - --hash=sha256:b4bb00bd71b448f16749909b08a0ff16f58b079e2261c2e1000f2bbb2a4f0a45 \ - --hash=sha256:b9aef96d7593584e31ef6ac1eb9775355b0099fee7651fae3a15bc8657b67b52 \ - --hash=sha256:ba581acad5ac8f33e2ff1746e8a57e001b47c6721873121bf8bbcf7ba8bd3aa4 \ - --hash=sha256:ba9d9e60651615bc614be5e21a82cdb7b1769a029369cf4b4d861e4f19686fb6 \ - --hash=sha256:bbebd2bba5c6ae02907df49150e55870fdd7440d727b6192c46b6f754723dde9 \ - --hash=sha256:bd32add59b58fba3439d48d6f36ac695830388e3da3e92e4fc26d2d02670d19c \ - --hash=sha256:bdab762e2c0b48bab76f1a08acb3f4c77afd2123bedac59446aeaaeed3d086cf \ - --hash=sha256:c5512aae4648152abaf4d48b59890503fcbe86e85abc12fb9b096fe948bdd816 \ - --hash=sha256:c6e4c10761ddbc0d67d2f6e2753daf99908db85d8b901729bf2bf5eaa60e0567 \ - --hash=sha256:cb4b3ad543084ed79f186741470b251b9d269cd8b03556f15a8d1a99a64b7de5 \ - --hash=sha256:cb74cdcbc0103fc988e04e5c58b0b31e8e5dd2babb9182b6f9490488eb36324b \ - --hash=sha256:cc3d107f603b5ee7a79b6aa6f166551b99b32fb4a5303c4dfcb4222fc6a0335e \ - --hash=sha256:d920789eca7ef71df7f31fd547ec0d3002e04d77f30ba6881e08a630e7b2c30e \ - --hash=sha256:daae5e955764be8fd70a93e9e5133c75297f8bce1e802e1d3683b98f77e1c5ab \ - --hash=sha256:db63cf3586a24241e89ca1ce0b56baaec9d371a328bd186c529b27c914c9a1ef \ - --hash=sha256:db953b675079884ffda33d1dca7189fb961b6d372153750beb81880384300817 \ - --hash=sha256:de076eaba208d16efb5962f99539867f8e2c73480988cb513fcf1b5dbb0c9dcf \ - --hash=sha256:e79dbc8f57de360f0ed987dc7de7be814b4803ef0e8fc6d3ff86e16798c99935 \ - --hash=sha256:e9a3a38eb4134ad33122a6d575e6324831f930a771d951a15ce232e0237412c2 \ - --hash=sha256:f04ca50e847abc486fa8f4107250566441e693779a5374ba211e96e238f298b9 \ - --hash=sha256:f1178e0de0c271231a660fbef9be6acdfa1d596803464706862bef6644cc1cae \ - --hash=sha256:f4617cef654fca552f00ce5ffdf4f4b68770f18950e4246ce94629b789b92467 \ - --hash=sha256:fa37f99bff354ff191c6bcdffbc9d7cdd4fc37faccfc9be0ef3a4fd5613977da +librt==0.8.1 \ + --hash=sha256:01170b6729a438f0dedc4a26ed342e3dc4f02d1000b4b19f980e1877f0c297e6 \ + --hash=sha256:039b9f2c506bd0ab0f8725aa5ba339c6f0cd19d3b514b50d134789809c24285d \ + --hash=sha256:05bd41cdee35b0c59c259f870f6da532a2c5ca57db95b5f23689fcb5c9e42440 \ + --hash=sha256:086a32dbb71336627e78cc1d6ee305a68d038ef7d4c39aaff41ae8c9aa46e91a \ + --hash=sha256:08eec3a1fc435f0d09c87b6bf1ec798986a3544f446b864e4099633a56fcd9ed \ + --hash=sha256:0bf69d79a23f4f40b8673a947a234baeeb133b5078b483b7297c5916539cf5d5 \ + --hash=sha256:0c3811485fccfda840861905b8c70bba5ec094e02825598bb9d4ca3936857a04 \ + --hash=sha256:0d2f82168e55ddefd27c01c654ce52379c0750ddc31ee86b4b266bcf4d65f2a3 \ + --hash=sha256:0f2ae3725904f7377e11cc37722d5d401e8b3d5851fb9273d7f4fe04f6b3d37d \ + --hash=sha256:10c42e1f6fd06733ef65ae7bebce2872bcafd8d6e6b0a08fe0a05a23b044fb14 \ + --hash=sha256:153188fe98a72f206042be10a2c6026139852805215ed9539186312d50a8e972 \ + --hash=sha256:172d57ec04346b047ca6af181e1ea4858086c80bdf455f61994c4aa6fc3f866c \ + --hash=sha256:190b109bb69592a3401fe1ffdea41a2e73370ace2ffdc4a0e8e2b39cdea81b78 \ + --hash=sha256:1d3a7da44baf692f0c6aeb5b2a09c5e6fc7a703bca9ffa337ddd2e2da53f7732 \ + --hash=sha256:228c2409c079f8c11fb2e5d7b277077f694cb93443eb760e00b3b83cb8b3176c \ + --hash=sha256:22b46eabd76c1986ee7d231b0765ad387d7673bbd996aa0d0d054b38ac65d8f6 \ + --hash=sha256:237796479f4d0637d6b9cbcb926ff424a97735e68ade6facf402df4ec93375ed \ + --hash=sha256:2c74a2da57a094bd48d03fa5d196da83d2815678385d2978657499063709abe1 \ + --hash=sha256:2cc68eeeef5e906839c7bb0815748b5b0a974ec27125beefc0f942715785b551 \ + --hash=sha256:2eb345e8b33fb748227409c9f1233d4df354d6e54091f0e8fc53acdb2ffedeb7 \ + --hash=sha256:31362dbfe297b23590530007062c32c6f6176f6099646bb2c95ab1b00a57c382 \ + --hash=sha256:3dff3d3ca8db20e783b1bc7de49c0a2ab0b8387f31236d6a026597d07fcd68ac \ + --hash=sha256:43353b943613c5d9c49a25aaffdba46f888ec354e71e3529a00cca3f04d66a7a \ + --hash=sha256:439352ba9373f11cb8e1933da194dcc6206daf779ff8df0ed69c5e39113e6a99 \ + --hash=sha256:4998009e7cb9e896569f4be7004f09d0ed70d386fa99d42b6d363f6d200501ac \ + --hash=sha256:4be2a5c926b9770c9e08e717f05737a269b9d0ebc5d2f0060f0fe3fe9ce47acb \ + --hash=sha256:4beb04b8c66c6ae62f8c1e0b2f097c1ebad9295c929a8d5286c05eae7c2fc7dc \ + --hash=sha256:4c8dfa264b9193c4ee19113c985c95f876fae5e51f731494fc4e0cf594990ba7 \ + --hash=sha256:5212a5bd7fae98dae95710032902edcd2ec4dc994e883294f75c857b83f9aba0 \ + --hash=sha256:52c224e14614b750c0a6d97368e16804a98c684657c7518752c356834fff83bb \ + --hash=sha256:56e04c14b696300d47b3bc5f1d10a00e86ae978886d0cee14e5714fafb5df5d2 \ + --hash=sha256:5bb54f1205a3a6ab41a6fd71dfcdcbd278670d3a90ca502a30d9da583105b6f7 \ + --hash=sha256:5cdc0f588ff4b663ea96c26d2a230c525c6fc62b28314edaaaca8ed5af931ad0 \ + --hash=sha256:5db05697c82b3a2ec53f6e72b2ed373132b0c2e05135f0696784e97d7f5d48e7 \ + --hash=sha256:5e4af413908f77294605e28cfd98063f54b2c790561383971d2f52d113d9c363 \ + --hash=sha256:5fc48998000cbc39ec0d5311312dda93ecf92b39aaf184c5e817d5d440b29624 \ + --hash=sha256:60a78b694c9aee2a0f1aaeaa7d101cf713e92e8423a941d2897f4fa37908dab9 \ + --hash=sha256:64548cde61b692dc0dc379f4b5f59a2f582c2ebe7890d09c1ae3b9e66fa015b7 \ + --hash=sha256:681dc2451d6d846794a828c16c22dc452d924e9f700a485b7ecb887a30aad1fd \ + --hash=sha256:6b1977c4ea97ce5eb7755a78fae68d87e4102e4aaf54985e8b56806849cc06a3 \ + --hash=sha256:6cfa7fe54fd4d1f47130017351a959fe5804bda7a0bc7e07a2cdbc3fdd28d34f \ + --hash=sha256:738f08021b3142c2918c03692608baed43bc51144c29e35807682f8070ee2a3a \ + --hash=sha256:747328be0c5b7075cde86a0e09d7a9196029800ba75a1689332348e998fb85c0 \ + --hash=sha256:758509ea3f1eba2a57558e7e98f4659d0ea7670bff49673b0dde18a3c7e6c0eb \ + --hash=sha256:785ae29c1f5c6e7c2cde2c7c0e148147f4503da3abc5d44d482068da5322fd9e \ + --hash=sha256:7aae78ab5e3206181780e56912d1b9bb9f90a7249ce12f0e8bf531d0462dd0fc \ + --hash=sha256:7b02679a0d783bdae30d443025b94465d8c3dc512f32f5b5031f93f57ac32071 \ + --hash=sha256:7e2f3edca35664499fbb36e4770650c4bd4a08abc1f4458eab9df4ec56389730 \ + --hash=sha256:7e6bad1cd94f6764e1e21950542f818a09316645337fd5ab9a7acc45d99a8f35 \ + --hash=sha256:81fd938344fecb9373ba1b155968c8a329491d2ce38e7ddb76f30ffb938f12dc \ + --hash=sha256:82210adabbc331dbb65d7868b105185464ef13f56f7f76688565ad79f648b0fe \ + --hash=sha256:89815a22daf9c51884fb5dbe4f1ef65ee6a146e0b6a8df05f753e2e4a9359bf4 \ + --hash=sha256:8f1125e6bbf2f1657d9a2f3ccc4a2c9b0c8b176965bb565dd4d86be67eddb4b6 \ + --hash=sha256:8f4bb453f408137d7581be309b2fbc6868a80e7ef60c88e689078ee3a296ae71 \ + --hash=sha256:924817ab3141aca17893386ee13261f1d100d1ef410d70afe4389f2359fea4f0 \ + --hash=sha256:93c2af9e01e0ef80d95ae3c720be101227edae5f2fe7e3dc63d8857fadfc5a1d \ + --hash=sha256:97c2b54ff6717a7a563b72627990bec60d8029df17df423f0ed37d56a17a176b \ + --hash=sha256:9be2f15e53ce4e83cc08adc29b26fb5978db62ef2a366fbdf716c8a6c8901040 \ + --hash=sha256:9e2c6f77b9ad48ce5603b83b7da9ee3e36b3ab425353f695cba13200c5d96596 \ + --hash=sha256:a28f2612ab566b17f3698b0da021ff9960610301607c9a5e8eaca62f5e1c350a \ + --hash=sha256:a355d99c4c0d8e5b770313b8b247411ed40949ca44e33e46a4789b9293a907ee \ + --hash=sha256:a3b4350b13cc0e6f5bec8fa7caf29a8fb8cdc051a3bae45cfbfd7ce64f009965 \ + --hash=sha256:aaab0e307e344cb28d800957ef3ec16605146ef0e59e059a60a176d19543d1b7 \ + --hash=sha256:ac1e7817fd0ed3d14fd7c5df91daed84c48e4c2a11ee99c0547f9f62fdae13da \ + --hash=sha256:adfab487facf03f0d0857b8710cf82d0704a309d8ffc33b03d9302b4c64e91a9 \ + --hash=sha256:b6d7ab1f01aa753188605b09a51faa44a3327400b00b8cce424c71910fc0a128 \ + --hash=sha256:bacdb58d9939d95cc557b4dbaa86527c9db2ac1ed76a18bc8d26f6dc8647d851 \ + --hash=sha256:be46a14693955b3bd96014ccbdb8339ee8c9346fbe11c1b78901b55125f14c73 \ + --hash=sha256:bf512a71a23504ed08103a13c941f763db13fb11177beb3d9244c98c29fb4a61 \ + --hash=sha256:c00e5c884f528c9932d278d5c9cbbea38a6b81eb62c02e06ae53751a83a4d52b \ + --hash=sha256:c25d9e338d5bed46c1632f851babf3d13c78f49a225462017cf5e11e845c5891 \ + --hash=sha256:c336d61d2fe74a3195edc1646d53ff1cddd3a9600b09fa6ab75e5514ba4862a7 \ + --hash=sha256:cc3656283d11540ab0ea01978378e73e10002145117055e03722417aeab30994 \ + --hash=sha256:cf450f498c30af55551ba4f66b9123b7185362ec8b625a773b3d39aa1a717583 \ + --hash=sha256:d0ee06b5b5291f609ddb37b9750985b27bc567791bc87c76a569b3feed8481ac \ + --hash=sha256:d480de377f5b687b6b1bc0c0407426da556e2a757633cc7e4d2e1a057aa688f3 \ + --hash=sha256:d56bc4011975f7460bea7b33e1ff425d2f1adf419935ff6707273c77f8a4ada6 \ + --hash=sha256:dd3c41254ee98604b08bd5b3af5bf0a89740d4ee0711de95b65166bf44091921 \ + --hash=sha256:e0d138c7ae532908cbb342162b2611dbd4d90c941cd25ab82084aaf71d2c0bd0 \ + --hash=sha256:e11769a1dbda4da7b00a76cfffa67aa47cfa66921d2724539eee4b9ede780b79 \ + --hash=sha256:e3f0a41487fd5fad7e760b9e8a90e251e27c2816fbc2cff36a22a0e6bcbbd9dd \ + --hash=sha256:e692aa2d1d604e6ca12d35e51fdc36f4cda6345e28e36374579f7ef3611b3012 \ + --hash=sha256:e70a57ecf89a0f64c24e37f38d3fe217a58169d2fe6ed6d70554964042474023 \ + --hash=sha256:e96baa6820280077a78244b2e06e416480ed859bbd8e5d641cf5742919d8beb4 \ + --hash=sha256:eb5656019db7c4deacf0c1a55a898c5bb8f989be904597fcb5232a2f4828fa05 \ + --hash=sha256:eca45e982fa074090057132e30585a7e8674e9e885d402eae85633e9f449ce6c \ + --hash=sha256:f0af2bd2bc204fa27f3d6711d0f360e6b8c684a035206257a81673ab924aa11e \ + --hash=sha256:f7cdf7f26c2286ffb02e46d7bac56c94655540b26347673bea15fa52a6af17e9 \ + --hash=sha256:fd1a720332ea335ceb544cf0a03f81df92abd4bb887679fd1e460976b0e6214b \ + --hash=sha256:ff8baf1f8d3f4b6b7257fcb75a501f2a5499d0dda57645baa09d4d0d34b19444 # via mypy locket==1.0.0 \ --hash=sha256:5c0d4c052a8bbbf750e056a8e65ccd309086f4f0f18a2eac306a8dfa4112a632 \ @@ -1453,9 +1463,9 @@ markupsafe==3.0.3 \ --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \ --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50 # via jinja2 -mcp==1.26.0 \ - --hash=sha256:904a21c33c25aa98ddbeb47273033c435e595bbacfdb177f4bd87f6dceebe1ca \ - --hash=sha256:db6e2ef491eecc1a0d93711a76f28dec2e05999f93afd48795da1c1137142c66 +mcp==1.27.0 \ + --hash=sha256:5ce1fa81614958e267b21fb2aa34e0aea8e2c6ede60d52aba45fd47246b4d741 \ + --hash=sha256:d3dc35a7eec0d458c1da4976a48f982097ddaab87e278c5511d5a4a56e852b83 # via fastapi-mcp mdurl==0.1.2 \ --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ @@ -1471,128 +1481,114 @@ meson-python==0.15.0 \ --hash=sha256:3ae38253ff02b2e947a05e362a2eaf5a9a09d133c5666b4123399ee5fbf2e591 \ --hash=sha256:fddb73eecd49e89c1c41c87937cd89c2d0b65a1c63ba28238681d4bd9484d26f # via feast (pyproject.toml) -mmh3==5.2.0 \ - --hash=sha256:03e08c6ebaf666ec1e3d6ea657a2d363bb01effd1a9acfe41f9197decaef0051 \ - --hash=sha256:097e13c8b8a66c5753c6968b7640faefe85d8e38992703c1f666eda6ef4c3762 \ - --hash=sha256:0b898cecff57442724a0f52bf42c2de42de63083a91008fb452887e372f9c328 \ - --hash=sha256:10983c10f5c77683bd845751905ba535ec47409874acc759d5ce3ff7ef34398a \ - --hash=sha256:11730eeb16dfcf9674fdea9bb6b8e6dd9b40813b7eb839bc35113649eef38aeb \ - --hash=sha256:127c95336f2a98c51e7682341ab7cb0be3adb9df0819ab8505a726ed1801876d \ - --hash=sha256:12da42c0a55c9d86ab566395324213c319c73ecb0c239fad4726324212b9441c \ - --hash=sha256:132dd943451a7c7546978863d2f5a64977928410782e1a87d583cb60eb89e667 \ - --hash=sha256:1556e31e4bd0ac0c17eaf220be17a09c171d7396919c3794274cb3415a9d3646 \ - --hash=sha256:1a5f4d2e59d6bba8ef01b013c472741835ad961e7c28f50c82b27c57748744a4 \ - --hash=sha256:1ba55d6ca32eeef8b2625e1e4bfc3b3db52bc63014bd7e5df8cc11bf2b036b12 \ - --hash=sha256:1efc8fec8478e9243a78bb993422cf79f8ff85cb4cf6b79647480a31e0d950a8 \ - --hash=sha256:1f8d8b627799f4e2fcc7c034fed8f5f24dc7724ff52f69838a3d6d15f1ad4765 \ - --hash=sha256:1fae471339ae1b9c641f19cf46dfe6ffd7f64b1fba7c4333b99fa3dd7f21ae0a \ - --hash=sha256:1fdb36b940e9261aff0b5177c5b74a36936b902f473180f6c15bde26143681a9 \ - --hash=sha256:2421b9d665a0b1ad724ec7332fb5a98d075f50bc51a6ff854f3a1882bd650d49 \ - --hash=sha256:29c2b9ce61886809d0492a274a5a53047742dea0f703f9c4d5d223c3ea6377d3 \ - --hash=sha256:2c9da0d568569cc87315cb063486d761e38458b8ad513fedd3dc9263e1b81bcd \ - --hash=sha256:2ebfc46b39168ab1cd44670a32ea5489bcbc74a25795c61b6d888c5c2cf654ed \ - --hash=sha256:3193752fc05ea72366c2b63ff24b9a190f422e32d75fdeae71087c08fff26115 \ - --hash=sha256:33576136c06b46a7046b6d83a3d75fbca7d25f84cec743f1ae156362608dc6d2 \ - --hash=sha256:37a358cc881fe796e099c1db6ce07ff757f088827b4e8467ac52b7a7ffdca647 \ - --hash=sha256:382a6bb3f8c6532ea084e7acc5be6ae0c6effa529240836d59352398f002e3fc \ - --hash=sha256:384eda9361a7bf83a85e09447e1feafe081034af9dd428893701b959230d84be \ - --hash=sha256:38d899a156549da8ef6a9f1d6f7ef231228d29f8f69bce2ee12f5fba6d6fd7c5 \ - --hash=sha256:3bc244802ccab5220008cb712ca1508cb6a12f0eb64ad62997156410579a1770 \ - --hash=sha256:3c6041fd9d5fb5fcac57d5c80f521a36b74aea06b8566431c63e4ffc49aced51 \ - --hash=sha256:3ca975c51c5028947bbcfc24966517aac06a01d6c921e30f7c5383c195f87991 \ - --hash=sha256:3d6bfd9662a20c054bc216f861fa330c2dac7c81e7fb8307b5e32ab5b9b4d2e0 \ - --hash=sha256:419005f84ba1cab47a77465a2a843562dadadd6671b8758bf179d82a15ca63eb \ - --hash=sha256:45b590e31bc552c6f8e2150ff1ad0c28dd151e9f87589e7eaf508fbdd8e8e908 \ - --hash=sha256:49037d417419863b222ae47ee562b2de9c3416add0a45c8d7f4e864be8dc4f89 \ - --hash=sha256:4a5f5536b1cbfa72318ab3bfc8a8188b949260baed186b75f0abc75b95d8c051 \ - --hash=sha256:582f9dbeefe15c32a5fa528b79b088b599a1dfe290a4436351c6090f90ddebb8 \ - --hash=sha256:58477cf9ef16664d1ce2b038f87d2dc96d70fe50733a34a7f07da6c9a5e3538c \ - --hash=sha256:58981d6ea9646dbbf9e59a30890cbf9f610df0e4a57dbfe09215116fd90b0093 \ - --hash=sha256:5a5dba98e514fb26241868f6eb90a7f7ca0e039aed779342965ce24ea32ba513 \ - --hash=sha256:5b0b58215befe0f0e120b828f7645e97719bbba9f23b69e268ed0ac7adde8645 \ - --hash=sha256:61ac226af521a572700f863d6ecddc6ece97220ce7174e311948ff8c8919a363 \ - --hash=sha256:63830f846797187c5d3e2dae50f0848fdc86032f5bfdc58ae352f02f857e9025 \ - --hash=sha256:69fc339d7202bea69ef9bd7c39bfdf9fdabc8e6822a01eba62fb43233c1b3932 \ - --hash=sha256:6d541038b3fc360ec538fc116de87462627944765a6750308118f8b509a8eec7 \ - --hash=sha256:6ecb4e750d712abde046858ee6992b65c93f1f71b397fce7975c3860c07365d2 \ - --hash=sha256:72d80005b7634a3a2220f81fbeb94775ebd12794623bb2e1451701ea732b4aa3 \ - --hash=sha256:7303aab41e97adcf010a09efd8f1403e719e59b7705d5e3cfed3dd7571589290 \ - --hash=sha256:7434a27754049144539d2099a6d2da5d88b8bdeedf935180bf42ad59b3607aa3 \ - --hash=sha256:746a5ee71c6d1103d9b560fa147881b5e68fd35da56e54e03d5acefad0e7c055 \ - --hash=sha256:7733ec52296fc1ba22e9b90a245c821adbb943e98c91d8a330a2254612726106 \ - --hash=sha256:7901c893e704ee3c65f92d39b951f8f34ccf8e8566768c58103fb10e55afb8c1 \ - --hash=sha256:7aa18cdb58983ee660c9c400b46272e14fa253c675ed963d3812487f8ca42037 \ - --hash=sha256:7b986d506a8e8ea345791897ba5d8ba0d9d8820cd4fc3e52dbe6de19388de2e7 \ - --hash=sha256:7bbb0df897944b5ec830f3ad883e32c5a7375370a521565f5fe24443bfb2c4f7 \ - --hash=sha256:7c7f0b342fd06044bedd0b6e72177ddc0076f54fd89ee239447f8b271d919d9b \ - --hash=sha256:7e5634565367b6d98dc4aa2983703526ef556b3688ba3065edb4b9b90ede1c54 \ - --hash=sha256:7fddccd4113e7b736706e17a239a696332360cbaddf25ae75b57ba1acce65081 \ - --hash=sha256:81c504ad11c588c8629536b032940f2a359dda3b6cbfd4ad8f74cb24dcd1b0bc \ - --hash=sha256:81df0dae22cd0da87f1c978602750f33d17fb3d21fb0f326c89dc89834fea79b \ - --hash=sha256:86d1be5d63232e6eb93c50881aea55ff06eb86d8e08f9b5417c8c9b10db9db96 \ - --hash=sha256:8b0c53fe0994beade1ad7c0f13bd6fec980a0664bfbe5a6a7d64500b9ab76772 \ - --hash=sha256:8ebf241072cf2777a492d0e09252f8cc2b3edd07dfdb9404b9757bffeb4f2cee \ - --hash=sha256:931d47e08c9c8a67bf75d82f0ada8399eac18b03388818b62bfa42882d571d72 \ - --hash=sha256:932a6eec1d2e2c3c9e630d10f7128d80e70e2d47fe6b8c7ea5e1afbd98733e65 \ - --hash=sha256:941603bfd75a46023807511c1ac2f1b0f39cccc393c15039969806063b27e6db \ - --hash=sha256:956127e663d05edbeec54df38885d943dfa27406594c411139690485128525de \ - --hash=sha256:96f1e1ac44cbb42bcc406e509f70c9af42c594e72ccc7b1257f97554204445f0 \ - --hash=sha256:99bb6a4d809aa4e528ddfe2c85dd5239b78b9dd14be62cca0329db78505e7b50 \ - --hash=sha256:9f64bf06f4bf623325fda3a6d02d36cd69199b9ace99b04bb2d7fd9f89688504 \ - --hash=sha256:a094319ec0db52a04af9fdc391b4d39a1bc72bc8424b47c4411afb05413a44b5 \ - --hash=sha256:a367d4741ac0103f8198c82f429bccb9359f543ca542b06a51f4f0332e8de279 \ - --hash=sha256:a7c0c7845566b9686480e6a7e9044db4afb60038d5fabd19227443f0104eeee4 \ - --hash=sha256:aa6e5d31fdc5ed9e3e95f9873508615a778fe9b523d52c17fc770a3eb39ab6e4 \ - --hash=sha256:ae9d032488fcec32d22be6542d1a836f00247f40f320844dbb361393b5b22773 \ - --hash=sha256:b0271ac12415afd3171ab9a3c7cbfc71dee2c68760a7dc9d05bf8ed6ddfa3a7a \ - --hash=sha256:b0d753ad566c721faa33db7e2e0eddd74b224cdd3eaf8481d76c926603c7a00e \ - --hash=sha256:b29044e1ffdb84fe164d0a7ea05c7316afea93c00f8ed9449cf357c36fc4f814 \ - --hash=sha256:b5995088dd7023d2d9f310a0c67de5a2b2e06a570ecfd00f9ff4ab94a67cde43 \ - --hash=sha256:b5f317a727bba0e633a12e71228bc6a4acb4f471a98b1c003163b917311ea9a9 \ - --hash=sha256:b9a87025121d1c448f24f27ff53a5fe7b6ef980574b4a4f11acaabe702420d63 \ - --hash=sha256:bb0fdc451fb6d86d81ab8f23d881b8d6e37fc373a2deae1c02d27002d2ad7a05 \ - --hash=sha256:bb4fe46bdc6104fbc28db7a6bacb115ee6368ff993366bbd8a2a7f0076e6f0c0 \ - --hash=sha256:bc44fc2b886243d7c0d8daeb37864e16f232e5b56aaec27cc781d848264cfd28 \ - --hash=sha256:bdde97310d59604f2a9119322f61b31546748499a21b44f6715e8ced9308a6c5 \ - --hash=sha256:be1374df449465c9f2500e62eee73a39db62152a8bdfbe12ec5b5c1cd451344d \ - --hash=sha256:be7d3dca9358e01dab1bad881fb2b4e8730cec58d36dd44482bc068bfcd3bc65 \ - --hash=sha256:bf7bee43e17e81671c447e9c83499f53d99bf440bc6d9dc26a841e21acfbe094 \ - --hash=sha256:c3dca4cb5b946ee91b3d6bb700d137b1cd85c20827f89fdf9c16258253489044 \ - --hash=sha256:c3f563e8901960e2eaa64c8e8821895818acabeb41c96f2efbb936f65dbe486c \ - --hash=sha256:c463d7c1c4cfc9d751efeaadd936bbba07b5b0ed81a012b3a9f5a12f0872bd6e \ - --hash=sha256:c4a2f3d83879e3de2eb8cbf562e71563a8ed15ee9b9c2e77ca5d9f73072ac15c \ - --hash=sha256:c5584061fd3da584659b13587f26c6cad25a096246a481636d64375d0c1f6c07 \ - --hash=sha256:c677d78887244bf3095020b73c42b505b700f801c690f8eaa90ad12d3179612f \ - --hash=sha256:c903e71fd8debb35ad2a4184c1316b3cb22f64ce517b4e6747f25b0a34e41266 \ - --hash=sha256:c9ff37ba9f15637e424c2ab57a1a590c52897c845b768e4e0a4958084ec87f22 \ - --hash=sha256:cadc16e8ea64b5d9a47363013e2bea469e121e6e7cb416a7593aeb24f2ad122e \ - --hash=sha256:cedac4f4054b8f7859e5aed41aaa31ad03fce6851901a7fdc2af0275ac533c10 \ - --hash=sha256:d22c9dcafed659fadc605538946c041722b6d1104fe619dbf5cc73b3c8a0ded8 \ - --hash=sha256:d765058da196f68dc721116cab335e696e87e76720e6ef8ee5a24801af65e63d \ - --hash=sha256:d86651fa45799530885ba4dab3d21144486ed15285e8784181a0ab37a4552384 \ - --hash=sha256:dd966df3489ec13848d6c6303429bbace94a153f43d1ae2a55115fd36fd5ca5d \ - --hash=sha256:ddc63328889bcaee77b743309e5c7d2d52cee0d7d577837c91b6e7cc9e755e0b \ - --hash=sha256:dfbead5575f6470c17e955b94f92d62a03dfc3d07f2e6f817d9b93dc211a1515 \ - --hash=sha256:e0f3ed828d709f5b82d8bfe14f8856120718ec4bd44a5b26102c3030a1e12501 \ - --hash=sha256:e1861fb6b1d0453ed7293200139c0a9011eeb1376632e048e3766945b13313c5 \ - --hash=sha256:e5015f0bb6eb50008bed2d4b1ce0f2a294698a926111e4bb202c0987b4f89078 \ - --hash=sha256:e651e17bfde5840e9e4174b01e9e080ce49277b70d424308b36a7969d0d1af73 \ - --hash=sha256:e7884931fe5e788163e7b3c511614130c2c59feffdc21112290a194487efb2e9 \ - --hash=sha256:e79c00eba78f7258e5b354eccd4d7907d60317ced924ea4a5f2e9d83f5453065 \ - --hash=sha256:e912b19cf2378f2967d0c08e86ff4c6c360129887f678e27e4dde970d21b3f4d \ - --hash=sha256:e9a011469b47b752e7d20de296bb34591cdfcbe76c99c2e863ceaa2aa61113d2 \ - --hash=sha256:eb756caf8975882630ce4e9fbbeb9d3401242a72528230422c9ab3a0d278e60c \ - --hash=sha256:eba01ec3bd4a49b9ac5ca2bc6a73ff5f3af53374b8556fcc2966dd2af9eb7779 \ - --hash=sha256:ecbfc0437ddfdced5e7822d1ce4855c9c64f46819d0fdc4482c53f56c707b935 \ - --hash=sha256:eed4bba7ff8a0d37106ba931ab03bdd3915fbb025bcf4e1f0aa02bc8114960c5 \ - --hash=sha256:f35727c5118aba95f0397e18a1a5b8405425581bfe53e821f0fb444cbdc2bc9b \ - --hash=sha256:f698733a8a494466432d611a8f0d1e026f5286dee051beea4b3c3146817e35d5 \ - --hash=sha256:f7f9034c7cf05ddfaac8d7a2e63a3c97a840d4615d0a0e65ba8bdf6f8576e3be \ - --hash=sha256:fa0c966ee727aad5406d516375593c5f058c766b21236ab8985693934bb5085b \ - --hash=sha256:fc9c5f280438cf1c1a8f9abb87dc8ce9630a964120cfb5dd50d1e7ce79690c7a \ - --hash=sha256:fd6e6c3d90660d085f7e73710eab6f5545d4854b81b0135a3526e797009dbda3 \ - --hash=sha256:fdfd3fb739f4e22746e13ad7ba0c6eedf5f454b18d11249724a388868e308ee4 \ - --hash=sha256:ff3d50dc3fe8a98059f99b445dfb62792b5d006c5e0b8f03c6de2813b8376110 +mmh3==5.2.1 \ + --hash=sha256:022aa1a528604e6c83d0a7705fdef0b5355d897a9e0fa3a8d26709ceaa06965d \ + --hash=sha256:0634581290e6714c068f4aa24020acf7880927d1f0084fa753d9799ae9610082 \ + --hash=sha256:08043f7cb1fb9467c3fbbbaea7896986e7fbc81f4d3fd9289a73d9110ab6207a \ + --hash=sha256:0a3984146e414684a6be2862d84fcb1035f4984851cb81b26d933bab6119bf00 \ + --hash=sha256:0bbc17250b10d3466875a40a52520a6bac3c02334ca709207648abd3c223ed5c \ + --hash=sha256:0cc21533878e5586b80d74c281d7f8da7932bc8ace50b8d5f6dbf7e3935f63f1 \ + --hash=sha256:0d0b7e803191db5f714d264044e06189c8ccd3219e936cc184f07106bd17fd7b \ + --hash=sha256:113f78e7463a36dbbcea05bfe688efd7fa759d0f0c56e73c974d60dcfec3dfcc \ + --hash=sha256:169e0d178cb59314456ab30772429a802b25d13227088085b0d49b9fe1533104 \ + --hash=sha256:17fbb47f0885ace8327ce1235d0416dc86a211dcd8cc1e703f41523be32cfec8 \ + --hash=sha256:19bbd3b841174ae6ed588536ab5e1b1fe83d046e668602c20266547298d939a9 \ + --hash=sha256:1d9f9a3ce559a5267014b04b82956993270f63ec91765e13e9fd73daf2d2738e \ + --hash=sha256:1e4ecee40ba19e6975e1120829796770325841c2f153c0e9aecca927194c6a2a \ + --hash=sha256:22b0f9971ec4e07e8223f2beebe96a6cfc779d940b6f27d26604040dd74d3a44 \ + --hash=sha256:26fb5b9c3946bf7f1daed7b37e0c03898a6f062149127570f8ede346390a0825 \ + --hash=sha256:2778fed822d7db23ac5008b181441af0c869455b2e7d001f4019636ac31b6fe4 \ + --hash=sha256:28cfab66577000b9505a0d068c731aee7ca85cd26d4d63881fab17857e0fe1fb \ + --hash=sha256:29bc3973676ae334412efdd367fcd11d036b7be3efc1ce2407ef8676dabfeb82 \ + --hash=sha256:2bd9f19f7f1fcebd74e830f4af0f28adad4975d40d80620be19ffb2b2af56c9f \ + --hash=sha256:2d5d542bf2abd0fd0361e8017d03f7cb5786214ceb4a40eef1539d6585d93386 \ + --hash=sha256:30e4d2084df019880d55f6f7bea35328d9b464ebee090baa372c096dc77556fb \ + --hash=sha256:3619473a0e0d329fd4aec8075628f8f616be2da41605300696206d6f36920c3d \ + --hash=sha256:368625fb01666655985391dbad3860dc0ba7c0d6b9125819f3121ee7292b4ac8 \ + --hash=sha256:3737303ca9ea0f7cb83028781148fcda4f1dac7821db0c47672971dabcf63593 \ + --hash=sha256:3a9fed49c6ce4ed7e73f13182760c65c816da006debe67f37635580dfb0fae00 \ + --hash=sha256:3c38d142c706201db5b2345166eeef1e7740e3e2422b470b8ba5c8727a9b4c7a \ + --hash=sha256:3cb61db880ec11e984348227b333259994c2c85caa775eb7875decb3768db890 \ + --hash=sha256:3d74a03fb57757ece25aa4b3c1c60157a1cece37a020542785f942e2f827eed5 \ + --hash=sha256:3f796b535008708846044c43302719c6956f39ca2d93f2edda5319e79a29efbb \ + --hash=sha256:41105377f6282e8297f182e393a79cfffd521dde37ace52b106373bdcd9ca5cb \ + --hash=sha256:41aac7002a749f08727cb91babff1daf8deac317c0b1f317adc69be0e6c375d1 \ + --hash=sha256:44983e45310ee5b9f73397350251cdf6e63a466406a105f1d16cb5baa659270b \ + --hash=sha256:4cbbde66f1183db040daede83dd86c06d663c5bb2af6de1142b7c8c37923dd74 \ + --hash=sha256:4eda76074cfca2787c8cf1bec603eaebdddd8b061ad5502f85cddae998d54f00 \ + --hash=sha256:4fc6cd65dc4d2fdb2625e288939a3566e36127a84811a4913f02f3d5931da52d \ + --hash=sha256:50885073e2909251d4718634a191c49ae5f527e5e1736d738e365c3e8be8f22b \ + --hash=sha256:5174a697ce042fa77c407e05efe41e03aa56dae9ec67388055820fb48cf4c3ba \ + --hash=sha256:54b64fb2433bc71488e7a449603bf8bd31fbcf9cb56fbe1eb6d459e90b86c37b \ + --hash=sha256:54fe8518abe06a4c3852754bfd498b30cc58e667f376c513eac89a244ce781a4 \ + --hash=sha256:55dbbd8ffbc40d1697d5e2d0375b08599dae8746b0b08dea05eee4ce81648fac \ + --hash=sha256:57b52603e89355ff318025dd55158f6e71396c0f1f609d548e9ea9c94cc6ce0a \ + --hash=sha256:58370d05d033ee97224c81263af123dea3d931025030fd34b61227a768a8858a \ + --hash=sha256:5d87a3584093e1a89987e3d36d82c98d9621b2cb944e22a420aa1401e096758f \ + --hash=sha256:623f938f6a039536cc02b7582a07a080f13fdfd48f87e63201d92d7e34d09a18 \ + --hash=sha256:62815d2c67f2dd1be76a253d88af4e1da19aeaa1820146dec52cf8bee2958b16 \ + --hash=sha256:6290289fa5fb4c70fd7f72016e03633d60388185483ff3b162912c81205ae2cf \ + --hash=sha256:67e41a497bac88cc1de96eeba56eeb933c39d54bc227352f8455aa87c4ca4000 \ + --hash=sha256:6c85c38a279ca9295a69b9b088a2e48aa49737bb1b34e6a9dc6297c110e8d912 \ + --hash=sha256:6f01f044112d43a20be2f13a11683666d87151542ad627fe41a18b9791d2802f \ + --hash=sha256:707151644085dd0f20fe4f4b573d28e5130c4aaa5f587e95b60989c5926653b5 \ + --hash=sha256:723b2681ed4cc07d3401bbea9c201ad4f2a4ca6ba8cddaff6789f715dd2b391e \ + --hash=sha256:72d1cc63bcc91e14933f77d51b3df899d6a07d184ec515ea7f56bff659e124d7 \ + --hash=sha256:7374d6e3ef72afe49697ecd683f3da12f4fc06af2d75433d0580c6746d2fa025 \ + --hash=sha256:7501e9be34cb21e72fcfe672aafd0eee65c16ba2afa9dcb5500a587d3a0580f0 \ + --hash=sha256:76219cd1eefb9bf4af7856e3ae563d15158efa145c0aab01e9933051a1954045 \ + --hash=sha256:7aec798c2b01aaa65a55f1124f3405804184373abb318a3091325aece235f67c \ + --hash=sha256:7be6dfb49e48fd0a7d91ff758a2b51336f1cd21f9d44b20f6801f072bd080cdd \ + --hash=sha256:7e4e1f580033335c6f76d1e0d6b56baf009d1a64d6a4816347e4271ba951f46d \ + --hash=sha256:7e8ec5f606e0809426d2440e0683509fb605a8820a21ebd120dcdba61b74ef7f \ + --hash=sha256:7f196cd7910d71e9d9860da0ff7a77f64d22c1ad931f1dd18559a06e03109fc0 \ + --hash=sha256:82f3802bfc4751f420d591c5c864de538b71cea117fce67e4595c2afede08a15 \ + --hash=sha256:85ffc9920ffc39c5eee1e3ac9100c913a0973996fbad5111f939bbda49204bb7 \ + --hash=sha256:8e6c219e375f6341d0959af814296372d265a8ca1af63825f65e2e87c618f006 \ + --hash=sha256:8f767ba0911602ddef289404e33835a61168314ebd3c729833db2ed685824211 \ + --hash=sha256:8ff038d52ef6aa0f309feeba00c5095c9118d0abf787e8e8454d6048db2037fc \ + --hash=sha256:915e7a2418f10bd1151b1953df06d896db9783c9cfdb9a8ee1f9b3a4331ab503 \ + --hash=sha256:92883836caf50d5255be03d988d75bc93e3f86ba247b7ca137347c323f731deb \ + --hash=sha256:960b1b3efa39872ac8b6cc3a556edd6fb90ed74f08c9c45e028f1005b26aa55d \ + --hash=sha256:9aeaf53eaa075dd63e81512522fd180097312fb2c9f476333309184285c49ce0 \ + --hash=sha256:9d8089d853c7963a8ce87fff93e2a67075c0bc08684a08ea6ad13577c38ffc38 \ + --hash=sha256:a4130d0b9ce5fad6af07421b1aecc7e079519f70d6c05729ab871794eded8617 \ + --hash=sha256:a482ac121de6973897c92c2f31defc6bafb11c83825109275cffce54bb64933f \ + --hash=sha256:add7ac388d1e0bf57259afbcf9ed05621a3bf11ce5ee337e7536f1e1aaf056b0 \ + --hash=sha256:b1f12bd684887a0a5d55e6363ca87056f361e45451105012d329b86ec19dbe0b \ + --hash=sha256:b3f99e1756fc48ad507b95e5d86f2fb21b3d495012ff13e6592ebac14033f166 \ + --hash=sha256:b4cce60d0223074803c9dbe0721ad3fa51dafe7d462fee4b656a1aa01ee07518 \ + --hash=sha256:baeb47635cb33375dee4924cd93d7f5dcaa786c740b08423b0209b824a1ee728 \ + --hash=sha256:bbea5b775f0ac84945191fb83f845a6fd9a21a03ea7f2e187defac7e401616ad \ + --hash=sha256:bbfcb95d9a744e6e2827dfc66ad10e1020e0cac255eb7f85652832d5a264c2fc \ + --hash=sha256:bd6e7d363aa93bd3421b30b6af97064daf47bc96005bddba67c5ffbc6df426b8 \ + --hash=sha256:be77c402d5e882b6fbacfd90823f13da8e0a69658405a39a569c6b58fdb17b03 \ + --hash=sha256:c302245fd6c33d96bd169c7ccf2513c20f4c1e417c07ce9dce107c8bc3f8411f \ + --hash=sha256:c88653877aeb514c089d1b3d473451677b8b9a6d1497dbddf1ae7934518b06d2 \ + --hash=sha256:cae6383181f1e345317742d2ddd88f9e7d2682fa4c9432e3a74e47d92dce0229 \ + --hash=sha256:cd471ede0d802dd936b6fab28188302b2d497f68436025857ca72cd3810423fe \ + --hash=sha256:d106493a60dcb4aef35a0fac85105e150a11cf8bc2b0d388f5a33272d756c966 \ + --hash=sha256:d30b650595fdbe32366b94cb14f30bb2b625e512bd4e1df00611f99dc5c27fd4 \ + --hash=sha256:d51fde50a77f81330523562e3c2734ffdca9c4c9e9d355478117905e1cfe16c6 \ + --hash=sha256:d57dea657357230cc780e13920d7fa7db059d58fe721c80020f94476da4ca0a1 \ + --hash=sha256:d771f085fcdf4035786adfb1d8db026df1eb4b41dac1c3d070d1e49512843227 \ + --hash=sha256:dae0f0bd7d30c0ad61b9a504e8e272cb8391eed3f1587edf933f4f6b33437450 \ + --hash=sha256:db0562c5f71d18596dcd45e854cf2eeba27d7543e1a3acdafb7eef728f7fe85d \ + --hash=sha256:dfd51b4c56b673dfbc43d7d27ef857dd91124801e2806c69bb45585ce0fa019b \ + --hash=sha256:e080c0637aea036f35507e803a4778f119a9b436617694ae1c5c366805f1e997 \ + --hash=sha256:e48d4dbe0f88e53081da605ae68644e5182752803bbc2beb228cca7f1c4454d6 \ + --hash=sha256:e8b4b5580280b9265af3e0409974fb79c64cf7523632d03fbf11df18f8b0181e \ + --hash=sha256:e8b5378de2b139c3a830f0209c1e91f7705919a4b3e563a10955104f5097a70a \ + --hash=sha256:e904f2417f0d6f6d514f3f8b836416c360f306ddaee1f84de8eef1e722d212e5 \ + --hash=sha256:eee884572b06bbe8a2b54f424dbd996139442cf83c76478e1ec162512e0dd2c7 \ + --hash=sha256:f1fbb0a99125b1287c6d9747f937dc66621426836d1a2d50d05aecfc81911b57 \ + --hash=sha256:f40a95186a72fa0b67d15fef0f157bfcda00b4f59c8a07cbe5530d41ac35d105 \ + --hash=sha256:f6e0bfe77d238308839699944164b96a2eeccaf55f2af400f54dc20669d8d5f2 \ + --hash=sha256:f963eafc0a77a6c0562397da004f5876a9bcf7265a7bcc3205e29636bc4a1312 \ + --hash=sha256:fb9d44c25244e11c8be3f12c938ca8ba8404620ef8092245d2093c6ab3df260f \ + --hash=sha256:fc78739b5ec6e4fb02301984a3d442a91406e7700efbe305071e7fd1c78278f2 \ + --hash=sha256:fceef7fe67c81e1585198215e42ad3fdba3a25644beda8fbdaf85f4d7b93175a \ + --hash=sha256:fd96476f04db5ceba1cfa0f21228f67c1f7402296f0e73fee3513aa680ad237b # via feast (pyproject.toml) multidict==6.7.1 \ --hash=sha256:026d264228bcd637d4e060844e39cdc60f86c479e463d49075dedc21b18fbbe0 \ @@ -1745,123 +1741,129 @@ multidict==6.7.1 \ # aiobotocore # aiohttp # yarl -mypy==1.19.1 \ - --hash=sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd \ - --hash=sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b \ - --hash=sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1 \ - --hash=sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba \ - --hash=sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b \ - --hash=sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045 \ - --hash=sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac \ - --hash=sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6 \ - --hash=sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a \ - --hash=sha256:409088884802d511ee52ca067707b90c883426bd95514e8cfda8281dc2effe24 \ - --hash=sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957 \ - --hash=sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042 \ - --hash=sha256:4f28f99c824ecebcdaa2e55d82953e38ff60ee5ec938476796636b86afa3956e \ - --hash=sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec \ - --hash=sha256:7bcfc336a03a1aaa26dfce9fff3e287a3ba99872a157561cbfcebe67c13308e3 \ - --hash=sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718 \ - --hash=sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f \ - --hash=sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331 \ - --hash=sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1 \ - --hash=sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1 \ - --hash=sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13 \ - --hash=sha256:b13cfdd6c87fc3efb69ea4ec18ef79c74c3f98b4e5498ca9b85ab3b2c2329a67 \ - --hash=sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2 \ - --hash=sha256:b7951a701c07ea584c4fe327834b92a30825514c868b1f69c30445093fdd9d5a \ - --hash=sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b \ - --hash=sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8 \ - --hash=sha256:c608937067d2fc5a4dd1a5ce92fd9e1398691b8c5d012d66e1ddd430e9244376 \ - --hash=sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef \ - --hash=sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288 \ - --hash=sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75 \ - --hash=sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74 \ - --hash=sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250 \ - --hash=sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab \ - --hash=sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6 \ - --hash=sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247 \ - --hash=sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925 \ - --hash=sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e \ - --hash=sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e +mypy==1.20.0 \ + --hash=sha256:002b613ae19f4ac7d18b7e168ffe1cb9013b37c57f7411984abbd3b817b0a214 \ + --hash=sha256:00e047c74d3ec6e71a2eb88e9ea551a2edb90c21f993aefa9e0d2a898e0bb732 \ + --hash=sha256:02cca0761c75b42a20a2757ae58713276605eb29a08dd8a6e092aa347c4115ca \ + --hash=sha256:0ecd63f75fdd30327e4ad8b5704bd6d91fc6c1b2e029f8ee14705e1207212489 \ + --hash=sha256:0f42dfaab7ec1baff3b383ad7af562ab0de573c5f6edb44b2dab016082b89948 \ + --hash=sha256:1973868d2adbb4584a3835780b27436f06d1dc606af5be09f187aaa25be1070f \ + --hash=sha256:26c8b52627b6552f47ff11adb4e1509605f094e29815323e487fc0053ebe93d1 \ + --hash=sha256:2721f0ce49cb74a38f00c50da67cb7d36317b5eda38877a49614dc018e91c787 \ + --hash=sha256:2fcedb16d456106e545b2bfd7ef9d24e70b38ec252d2a629823a4d07ebcdb69e \ + --hash=sha256:31b5dbb55293c1bd27c0fc813a0d2bb5ceef9d65ac5afa2e58f829dab7921fd5 \ + --hash=sha256:34506397dbf40c15dc567635d18a21d33827e9ab29014fb83d292a8f4f8953b6 \ + --hash=sha256:367e5c993ba34d5054d11937d0485ad6dfc60ba760fa326c01090fc256adf15c \ + --hash=sha256:379edf079ce44ac8d2805bcf9b3dd7340d4f97aad3a5e0ebabbf9d125b84b442 \ + --hash=sha256:39362cdb4ba5f916e7976fccecaab1ba3a83e35f60fa68b64e9a70e221bb2436 \ + --hash=sha256:4525e7010b1b38334516181c5b81e16180b8e149e6684cee5a727c78186b4e3b \ + --hash=sha256:47781555a7aa5fedcc2d16bcd72e0dc83eb272c10dd657f9fb3f9cc08e2e6abb \ + --hash=sha256:49d11c6f573a5a08f77fad13faff2139f6d0730ebed2cfa9b3d2702671dd7188 \ + --hash=sha256:555493c44a4f5a1b58d611a43333e71a9981c6dbe26270377b6f8174126a0526 \ + --hash=sha256:555658c611099455b2da507582ea20d2043dfdfe7f5ad0add472b1c6238b433f \ + --hash=sha256:697f102c5c1d526bdd761a69f17c6070f9892eebcb94b1a5963d679288c09e78 \ + --hash=sha256:76a70bf840495729be47510856b978f1b0ec7d08f257ca38c9d932720bf6b43e \ + --hash=sha256:7d3243c406773185144527f83be0e0aefc7bf4601b0b2b956665608bf7c98a83 \ + --hash=sha256:931a7630bba591593dcf6e97224a21ff80fb357e7982628d25e3c618e7f598ef \ + --hash=sha256:9804c3ad27f78e54e58b32e7cb532d128b43dbfb9f3f9f06262b821a0f6bd3f5 \ + --hash=sha256:a17c5d0bdcca61ce24a35beb828a2d0d323d3fcf387d7512206888c900193367 \ + --hash=sha256:a6e0641147cbfa7e4e94efdb95c2dab1aff8cfc159ded13e07f308ddccc8c48e \ + --hash=sha256:a79c1eba7ac4209f2d850f0edd0a2f8bba88cbfdfefe6fb76a19e9d4fe5e71a2 \ + --hash=sha256:a9336b5e6712f4adaf5afc3203a99a40b379049104349d747eb3e5a3aa23ac2e \ + --hash=sha256:b20c8b0fd5877abdf402e79a3af987053de07e6fb208c18df6659f708b535134 \ + --hash=sha256:b3a49064504be59e59da664c5e149edc1f26c67c4f8e8456f6ba6aba55033018 \ + --hash=sha256:b503ab55a836136b619b5fc21c8803d810c5b87551af8600b72eecafb0059cb0 \ + --hash=sha256:bd0212976dc57a5bfeede7c219e7cd66568a32c05c9129686dd487c059c1b88a \ + --hash=sha256:c70380fe5d64010f79fb863b9081c7004dd65225d2277333c219d93a10dad4dd \ + --hash=sha256:d99f515f95fd03a90875fdb2cca12ff074aa04490db4d190905851bdf8a549a8 \ + --hash=sha256:e80cf77847d0d3e6e3111b7b25db32a7f8762fd4b9a3a72ce53fe16a2863b281 \ + --hash=sha256:eb96c84efcc33f0b5e0e04beacf00129dd963b67226b01c00b9dfc8affb464c3 \ + --hash=sha256:ebea00201737ad4391142808ed16e875add5c17f676e0912b387739f84991e13 \ + --hash=sha256:efe8d70949c3023698c3fca1e94527e7e790a361ab8116f90d11221421cd8726 \ + --hash=sha256:f13b3e41bce9d257eded794c0f12878af3129d80aacd8a3ee0dee51f3a978651 \ + --hash=sha256:f194db59657c58593a3c47c6dfd7bad4ef4ac12dbc94d01b3a95521f78177e33 \ + --hash=sha256:f49590891d2c2f8a9de15614e32e459a794bcba84693c2394291a2038bbaaa69 \ + --hash=sha256:f75ff57defcd0f1d6e006d721ccdec6c88d4f6a7816eb92f1c4890d979d9ee62 \ + --hash=sha256:f799d9db89fc00446f03281f84a221e50018fc40113a3ba9864b132895619ebe \ + --hash=sha256:f8426d4d75d68714abc17a4292d922f6ba2cfb984b72c2278c437f6dae797865 # via sqlalchemy mypy-extensions==1.1.0 \ --hash=sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505 \ --hash=sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558 # via mypy -numpy==2.4.2 \ - --hash=sha256:00ab83c56211a1d7c07c25e3217ea6695e50a3e2f255053686b081dc0b091a82 \ - --hash=sha256:068cdb2d0d644cdb45670810894f6a0600797a69c05f1ac478e8d31670b8ee75 \ - --hash=sha256:0f01dcf33e73d80bd8dc0f20a71303abbafa26a19e23f6b68d1aa9990af90257 \ - --hash=sha256:0fece1d1f0a89c16b03442eae5c56dc0be0c7883b5d388e0c03f53019a4bfd71 \ - --hash=sha256:12e26134a0331d8dbd9351620f037ec470b7c75929cb8a1537f6bfe411152a1a \ - --hash=sha256:1ae241bbfc6ae276f94a170b14785e561cb5e7f626b6688cf076af4110887413 \ - --hash=sha256:1f92f53998a17265194018d1cc321b2e96e900ca52d54c7c77837b71b9465181 \ - --hash=sha256:209fae046e62d0ce6435fcfe3b1a10537e858249b3d9b05829e2a05218296a85 \ - --hash=sha256:20abd069b9cda45874498b245c8015b18ace6de8546bf50dfa8cea1696ed06ef \ - --hash=sha256:21982668592194c609de53ba4933a7471880ccbaadcc52352694a59ecc860b3a \ - --hash=sha256:25f2059807faea4b077a2b6837391b5d830864b3543627f381821c646f31a63c \ - --hash=sha256:2653de5c24910e49c2b106499803124dde62a5a1fe0eedeaecf4309a5f639390 \ - --hash=sha256:2b8f157c8a6f20eb657e240f8985cc135598b2b46985c5bccbde7616dc9c6b1e \ - --hash=sha256:2fb882da679409066b4603579619341c6d6898fc83a8995199d5249f986e8e8f \ - --hash=sha256:40397bda92382fcec844066efb11f13e1c9a3e2a8e8f318fb72ed8b6db9f60f1 \ - --hash=sha256:444be170853f1f9d528428eceb55f12918e4fda5d8805480f36a002f1415e09b \ - --hash=sha256:47c5a6ed21d9452b10227e5e8a0e1c22979811cad7dcc19d8e3e2fb8fa03f1a3 \ - --hash=sha256:4f069069931240b3fc703f1e23df63443dbd6390614c8c44a87d96cd0ec81eb1 \ - --hash=sha256:52b913ec40ff7ae845687b0b34d8d93b60cb66dcee06996dd5c99f2fc9328657 \ - --hash=sha256:5633c0da313330fd20c484c78cdd3f9b175b55e1a766c4a174230c6b70ad8262 \ - --hash=sha256:5daf6f3914a733336dab21a05cdec343144600e964d2fcdabaac0c0269874b2a \ - --hash=sha256:5eea80d908b2c1f91486eb95b3fb6fab187e569ec9752ab7d9333d2e66bf2d6b \ - --hash=sha256:602f65afdef699cda27ec0b9224ae5dc43e328f4c24c689deaf77133dbee74d0 \ - --hash=sha256:659a6107e31a83c4e33f763942275fd278b21d095094044eb35569e86a21ddae \ - --hash=sha256:66cb9422236317f9d44b67b4d18f44efe6e9c7f8794ac0462978513359461554 \ - --hash=sha256:6d82351358ffbcdcd7b686b90742a9b86632d6c1c051016484fa0b326a0a1548 \ - --hash=sha256:6e9f61981ace1360e42737e2bae58b27bf28a1b27e781721047d84bd754d32e7 \ - --hash=sha256:6ed0be1ee58eef41231a5c943d7d1375f093142702d5723ca2eb07db9b934b05 \ - --hash=sha256:7cdde6de52fb6664b00b056341265441192d1291c130e99183ec0d4b110ff8b1 \ - --hash=sha256:7df2de1e4fba69a51c06c28f5a3de36731eb9639feb8e1cf7e4a7b0daf4cf622 \ - --hash=sha256:7edc794af8b36ca37ef5fcb5e0d128c7e0595c7b96a2318d1badb6fcd8ee86b1 \ - --hash=sha256:7f54844851cdb630ceb623dcec4db3240d1ac13d4990532446761baede94996a \ - --hash=sha256:805cc8de9fd6e7a22da5aed858e0ab16be5a4db6c873dde1d7451c541553aa27 \ - --hash=sha256:8906e71fd8afcb76580404e2a950caef2685df3d2a57fe82a86ac8d33cc007ba \ - --hash=sha256:89f7268c009bc492f506abd6f5265defa7cb3f7487dc21d357c3d290add45082 \ - --hash=sha256:8c50dd1fc8826f5b26a5ee4d77ca55d88a895f4e4819c7ecc2a9f5905047a443 \ - --hash=sha256:8e4549f8a3c6d13d55041925e912bfd834285ef1dd64d6bc7d542583355e2e98 \ - --hash=sha256:8e9afaeb0beff068b4d9cd20d322ba0ee1cecfb0b08db145e4ab4dd44a6b5110 \ - --hash=sha256:98f16a80e917003a12c0580f97b5f875853ebc33e2eaa4bccfc8201ac6869308 \ - --hash=sha256:9e35d3e0144137d9fdae62912e869136164534d64a169f86438bc9561b6ad49f \ - --hash=sha256:9e4424677ce4b47fe73c8b5556d876571f7c6945d264201180db2dc34f676ab5 \ - --hash=sha256:adb6ed2ad29b9e15321d167d152ee909ec73395901b70936f029c3bc6d7f4460 \ - --hash=sha256:aea4f66ff44dfddf8c2cffd66ba6538c5ec67d389285292fe428cb2c738c8aef \ - --hash=sha256:b21041e8cb6a1eb5312dd1d2f80a94d91efffb7a06b70597d44f1bd2dfc315ab \ - --hash=sha256:b2f0073ed0868db1dcd86e052d37279eef185b9c8db5bf61f30f46adac63c909 \ - --hash=sha256:b3a24467af63c67829bfaa61eecf18d5432d4f11992688537be59ecd6ad32f5e \ - --hash=sha256:b9c618d56a29c9cb1c4da979e9899be7578d2e0b3c24d52079c166324c9e8695 \ - --hash=sha256:bba37bc29d4d85761deed3954a1bc62be7cf462b9510b51d367b769a8c8df325 \ - --hash=sha256:bd3a7a9f5847d2fb8c2c6d1c862fa109c31a9abeca1a3c2bd5a64572955b2979 \ - --hash=sha256:be71bf1edb48ebbbf7f6337b5bfd2f895d1902f6335a5830b20141fc126ffba0 \ - --hash=sha256:c02ef4401a506fb60b411467ad501e1429a3487abca4664871d9ae0b46c8ba32 \ - --hash=sha256:c3cd545784805de05aafe1dde61752ea49a359ccba9760c1e5d1c88a93bbf2b7 \ - --hash=sha256:c7ac672d699bf36275c035e16b65539931347d68b70667d28984c9fb34e07fa7 \ - --hash=sha256:cb7bbb88aa74908950d979eeaa24dbdf1a865e3c7e45ff0121d8f70387b55f73 \ - --hash=sha256:cd2bd2bbed13e213d6b55dc1d035a4f91748a7d3edc9480c13898b0353708920 \ - --hash=sha256:cda077c2e5b780200b6b3e09d0b42205a3d1c68f30c6dceb90401c13bff8fe74 \ - --hash=sha256:cf28c0c1d4c4bf00f509fa7eb02c58d7caf221b50b467bcb0d9bbf1584d5c821 \ - --hash=sha256:d0d9b7c93578baafcbc5f0b83eaf17b79d345c6f36917ba0c67f45226911d499 \ - --hash=sha256:d1240d50adff70c2a88217698ca844723068533f3f5c5fa6ee2e3220e3bdb000 \ - --hash=sha256:d30291931c915b2ab5717c2974bb95ee891a1cf22ebc16a8006bd59cd210d40a \ - --hash=sha256:d9f64d786b3b1dd742c946c42d15b07497ed14af1a1f3ce840cce27daa0ce913 \ - --hash=sha256:da6cad4e82cb893db4b69105c604d805e0c3ce11501a55b5e9f9083b47d2ffe8 \ - --hash=sha256:df1b10187212b198dd45fa943d8985a3c8cf854aed4923796e0e019e113a1bda \ - --hash=sha256:e04ae107ac591763a47398bb45b568fc38f02dbc4aa44c063f67a131f99346cb \ - --hash=sha256:e6dee3bb76aa4009d5a912180bf5b2de012532998d094acee25d9cb8dee3e44a \ - --hash=sha256:e7e88598032542bd49af7c4747541422884219056c268823ef6e5e89851c8825 \ - --hash=sha256:e98c97502435b53741540a5717a6749ac2ada901056c7db951d33e11c885cc7d \ - --hash=sha256:ec055f6dae239a6299cace477b479cca2fc125c5675482daf1dd886933a1076f \ - --hash=sha256:f74f0f7779cc7ae07d1810aab8ac6b1464c3eafb9e283a40da7309d5e6e48fbb \ - --hash=sha256:fbde1b0c6e81d56f5dccd95dd4a711d9b95df1ae4009a60887e56b27e8d903fa \ - --hash=sha256:fcf92bee92742edd401ba41135185866f7026c502617f422eb432cfeca4fe236 \ - --hash=sha256:fd49860271d52127d61197bb50b64f58454e9f578cb4b2c001a6de8b1f50b0b1 +numpy==2.4.4 \ + --hash=sha256:07077278157d02f65c43b1b26a3886bce886f95d20aabd11f87932750dfb14ed \ + --hash=sha256:08f2e31ed5e6f04b118e49821397f12767934cfdd12a1ce86a058f91e004ee50 \ + --hash=sha256:0aec54fd785890ecca25a6003fd9a5aed47ad607bbac5cd64f836ad8666f4959 \ + --hash=sha256:0d35aea54ad1d420c812bfa0385c71cd7cc5bcf7c65fed95fc2cd02fe8c79827 \ + --hash=sha256:0d4e437e295f18ec29bc79daf55e8a47a9113df44d66f702f02a293d93a2d6dd \ + --hash=sha256:0dfd3f9d3adbe2920b68b5cd3d51444e13a10792ec7154cd0a2f6e74d4ab3233 \ + --hash=sha256:1378871da56ca8943c2ba674530924bb8ca40cd228358a3b5f302ad60cf875fc \ + --hash=sha256:15716cfef24d3a9762e3acdf87e27f58dc823d1348f765bbea6bef8c639bfa1b \ + --hash=sha256:19710a9ca9992d7174e9c52f643d4272dcd1558c5f7af7f6f8190f633bd651a7 \ + --hash=sha256:23cbfd4c17357c81021f21540da84ee282b9c8fba38a03b7b9d09ba6b951421e \ + --hash=sha256:2483e4584a1cb3092da4470b38866634bafb223cbcd551ee047633fd2584599a \ + --hash=sha256:27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d \ + --hash=sha256:28a650663f7314afc3e6ec620f44f333c386aad9f6fc472030865dc0ebb26ee3 \ + --hash=sha256:2aa0613a5177c264ff5921051a5719d20095ea586ca88cc802c5c218d1c67d3e \ + --hash=sha256:2c194dd721e54ecad9ad387c1d35e63dce5c4450c6dc7dd5611283dda239aabb \ + --hash=sha256:2d19e6e2095506d1736b7d80595e0f252d76b89f5e715c35e06e937679ea7d7a \ + --hash=sha256:2d390634c5182175533585cc89f3608a4682ccb173cc9bb940b2881c8d6f8fa0 \ + --hash=sha256:30caa73029a225b2d40d9fae193e008e24b2026b7ee1a867b7ee8d96ca1a448e \ + --hash=sha256:42c16925aa5a02362f986765f9ebabf20de75cdefdca827d14315c568dcab113 \ + --hash=sha256:45dbed2ab436a9e826e302fcdcbe9133f9b0006e5af7168afb8963a6520da103 \ + --hash=sha256:4636de7fd195197b7535f231b5de9e4b36d2c440b6e566d2e4e4746e6af0ca93 \ + --hash=sha256:4a19d9dba1a76618dd86b164d608566f393f8ec6ac7c44f0cc879011c45e65af \ + --hash=sha256:4bbc7f303d125971f60ec0aaad5e12c62d0d2c925f0ab1273debd0e4ba37aba5 \ + --hash=sha256:4d6d57903571f86180eb98f8f0c839fa9ebbfb031356d87f1361be91e433f5b7 \ + --hash=sha256:4e874c976154687c1f71715b034739b45c7711bec81db01914770373d125e392 \ + --hash=sha256:51fc224f7ca4d92656d5a5eb315f12eb5fe2c97a66249aa7b5f562528a3be38c \ + --hash=sha256:58c8b5929fcb8287cbd6f0a3fae19c6e03a5c48402ae792962ac465224a629a4 \ + --hash=sha256:5a285b3b96f951841799528cd1f4f01cd70e7e0204b4abebac9463eecfcf2a40 \ + --hash=sha256:5c70f1cc1c4efbe316a572e2d8b9b9cc44e89b95f79ca3331553fbb63716e2bf \ + --hash=sha256:62d6b0f03b694173f9fcb1fb317f7222fd0b0b103e784c6549f5e53a27718c44 \ + --hash=sha256:6a246d5914aa1c820c9443ddcee9c02bec3e203b0c080349533fae17727dfd1b \ + --hash=sha256:6aa3236c78803afbcb255045fbef97a9e25a1f6c9888357d205ddc42f4d6eba5 \ + --hash=sha256:6bbe4eb67390b0a0265a2c25458f6b90a409d5d069f1041e6aff1e27e3d9a79e \ + --hash=sha256:715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74 \ + --hash=sha256:72944b19f2324114e9dc86a159787333b77874143efcf89a5167ef83cfee8af0 \ + --hash=sha256:81f4a14bee47aec54f883e0cad2d73986640c1590eb9bfaaba7ad17394481e6e \ + --hash=sha256:846300f379b5b12cc769334464656bc882e0735d27d9726568bc932fdc49d5ec \ + --hash=sha256:86b6f55f5a352b48d7fbfd2dbc3d5b780b2d79f4d3c121f33eb6efb22e9a2015 \ + --hash=sha256:874f200b2a981c647340f841730fc3a2b54c9d940566a3c4149099591e2c4c3d \ + --hash=sha256:8a87ec22c87be071b6bdbd27920b129b94f2fc964358ce38f3822635a3e2e03d \ + --hash=sha256:8b3b60bb7cba2c8c81837661c488637eee696f59a877788a396d33150c35d842 \ + --hash=sha256:8e3ed142f2728df44263aaf5fb1f5b0b99f4070c553a0d7f033be65338329150 \ + --hash=sha256:93e15038125dc1e5345d9b5b68aa7f996ec33b98118d18c6ca0d0b7d6198b7e8 \ + --hash=sha256:989824e9faf85f96ec9c7761cd8d29c531ad857bfa1daa930cba85baaecf1a9a \ + --hash=sha256:99d838547ace2c4aace6c4f76e879ddfe02bb58a80c1549928477862b7a6d6ed \ + --hash=sha256:9b2aec6af35c113b05695ebb5749a787acd63cafc83086a05771d1e1cd1e555f \ + --hash=sha256:9c585a1790d5436a5374bac930dad6ed244c046ed91b2b2a3634eb2971d21008 \ + --hash=sha256:a7164afb23be6e37ad90b2f10426149fd75aee07ca55653d2aa41e66c4ef697e \ + --hash=sha256:ac6b31e35612a26483e20750126d30d0941f949426974cace8e6b5c58a3657b0 \ + --hash=sha256:ad2e2ef14e0b04e544ea2fa0a36463f847f113d314aa02e5b402fdf910ef309e \ + --hash=sha256:b268594bccac7d7cf5844c7732e3f20c50921d94e36d7ec9b79e9857694b1b2f \ + --hash=sha256:b5f0362dc928a6ecd9db58868fca5e48485205e3855957bdedea308f8672ea4a \ + --hash=sha256:ba1f4fc670ed79f876f70082eff4f9583c15fb9a4b89d6188412de4d18ae2f40 \ + --hash=sha256:ba203255017337d39f89bdd58417f03c4426f12beed0440cfd933cb15f8669c7 \ + --hash=sha256:c901b15172510173f5cb310eae652908340f8dede90fff9e3bf6c0d8dfd92f83 \ + --hash=sha256:c9b39d38a9bd2ae1becd7eac1303d031c5c110ad31f2b319c6e7d98b135c934d \ + --hash=sha256:d2a8490669bfe99a233298348acc2d824d496dee0e66e31b66a6022c2ad74a5c \ + --hash=sha256:dddbbd259598d7240b18c9d87c56a9d2fb3b02fe266f49a7c101532e78c1d871 \ + --hash=sha256:df3775294accfdd75f32c74ae39fcba920c9a378a2fc18a12b6820aa8c1fb502 \ + --hash=sha256:e44319a2953c738205bf3354537979eaa3998ed673395b964c1176083dd46252 \ + --hash=sha256:e4a010c27ff6f210ff4c6ef34394cd61470d01014439b192ec22552ee867f2a8 \ + --hash=sha256:e823b8b6edc81e747526f70f71a9c0a07ac4e7ad13020aa736bb7c9d67196115 \ + --hash=sha256:e892aff75639bbef0d2a2cfd55535510df26ff92f63c92cd84ef8d4ba5a5557f \ + --hash=sha256:eea7ac5d2dce4189771cedb559c738a71512768210dc4e4753b107a2048b3d0e \ + --hash=sha256:ef4059d6e5152fa1a39f888e344c73fdc926e1b2dd58c771d67b0acfbf2aa67d \ + --hash=sha256:f169b9a863d34f5d11b8698ead99febeaa17a13ca044961aa8e2662a6c7766a0 \ + --hash=sha256:f2cf083b324a467e1ab358c105f6cad5ea950f50524668a80c486ff1db24e119 \ + --hash=sha256:f8474c4241bc18b750be2abea9d7a9ec84f46ef861dbacf86a4f6e043401f79e \ + --hash=sha256:f983334aea213c99992053ede6168500e5f086ce74fbc4acc3f2b00f5762e9db \ + --hash=sha256:f9e75681b59ddaa5e659898085ae0eaea229d054f2ac0c7e563a62205a700121 \ + --hash=sha256:fbc356aae7adf9e6336d336b9c8111d390a05df88f1805573ebb0807bd06fd1d \ + --hash=sha256:fcfe2045fd2e8f3cb0ce9d4ba6dba6333b8fa05bb8a4939c908cd43322d14c7e # via # feast (pyproject.toml) # dask @@ -1889,6 +1891,7 @@ packaging==26.0 \ # setuptools-scm # snowflake-connector-python # sphinx + # vcs-versioning pandas==2.3.3 \ --hash=sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7 \ --hash=sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593 \ @@ -1954,9 +1957,9 @@ pandas==2.3.3 \ # pandas-gbq # pymilvus # snowflake-connector-python -pandas-gbq==0.33.0 \ - --hash=sha256:499ad18a7b1917e2cc04bbd763ec37c11ecc49030348c45cebb9cbbdb7f909af \ - --hash=sha256:61357e11d73e0ae57cbff31e71fc3ed83da3d16b58b653f715b32ad760527e34 +pandas-gbq==0.34.1 \ + --hash=sha256:6bea5b85937251b976cf9db38151ea59abbff98771179183488d4614694bff67 \ + --hash=sha256:b74932c6ee35dfc81582f39c792e3a68c9ef9bee8c85f25667d9d05dfadd0daf # via google-cloud-bigquery parsy==2.2 \ --hash=sha256:5e981613d9d2d8b68012d1dd0afe928967bea2e4eefdb76c2f545af0dd02a9e7 \ @@ -1984,9 +1987,9 @@ pathspec==1.0.4 \ # hatchling # mypy # scikit-build-core -platformdirs==4.9.2 \ - --hash=sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd \ - --hash=sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291 +platformdirs==4.9.4 \ + --hash=sha256:1ec356301b7dc906d83f371c8f487070e99d3ccf9e501686456394622a01a934 \ + --hash=sha256:68a9a4619a666ea6439f2ff250c12a853cd1cbd5158d258bd824a7df6be2f868 # via snowflake-connector-python pluggy==1.6.0 \ --hash=sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3 \ @@ -2122,25 +2125,25 @@ propcache==0.4.1 \ # via # aiohttp # yarl -proto-plus==1.27.1 \ - --hash=sha256:912a7460446625b792f6448bade9e55cd4e41e6ac10e27009ef71a7f317fa147 \ - --hash=sha256:e4643061f3a4d0de092d62aa4ad09fa4756b2cbb89d4627f3985018216f9fefc +proto-plus==1.27.2 \ + --hash=sha256:6432f75893d3b9e70b9c412f1d2f03f65b11fb164b793d14ae2ca01821d22718 \ + --hash=sha256:b2adde53adadf75737c44d3dcb0104fde65250dfc83ad59168b4aa3e574b6a24 # via # google-api-core # google-cloud-bigquery-storage # google-cloud-bigtable # google-cloud-datastore -protobuf==6.33.5 \ - --hash=sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c \ - --hash=sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02 \ - --hash=sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c \ - --hash=sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd \ - --hash=sha256:8f04fa32763dcdb4973d537d6b54e615cc61108c7cb38fe59310c3192d29510a \ - --hash=sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190 \ - --hash=sha256:a3157e62729aafb8df6da2c03aa5c0937c7266c626ce11a278b6eb7963c4e37c \ - --hash=sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5 \ - --hash=sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0 \ - --hash=sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b +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) # google-api-core @@ -2253,12 +2256,10 @@ pyarrow-hotfix==0.7 \ --hash=sha256:3236f3b5f1260f0e2ac070a55c1a7b339c4bb7267839bd2015e283234e758100 \ --hash=sha256:59399cd58bdd978b2e42816a4183a55c6472d4e33d183351b6069f11ed42661d # via ibis-framework -pyasn1==0.6.2 \ - --hash=sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf \ - --hash=sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b - # via - # pyasn1-modules - # rsa +pyasn1==0.6.3 \ + --hash=sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf \ + --hash=sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde + # via pyasn1-modules pyasn1-modules==0.4.2 \ --hash=sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a \ --hash=sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6 @@ -2403,9 +2404,9 @@ pydantic-core==2.41.5 \ --hash=sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425 \ --hash=sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52 # via pydantic -pydantic-settings==2.13.0 \ - --hash=sha256:95d875514610e8595672800a5c40b073e99e4aae467fa7c8f9c263061ea2e1fe \ - --hash=sha256:d67b576fff39cd086b595441bf9c75d4193ca9c0ed643b90360694d0f1240246 +pydantic-settings==2.13.1 \ + --hash=sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025 \ + --hash=sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237 # via # fastapi-mcp # mcp @@ -2413,16 +2414,16 @@ pydata-google-auth==1.9.1 \ --hash=sha256:0a51ce41c601ca0bc69b8795bf58bedff74b4a6a007c9106c7cbcdec00eaced2 \ --hash=sha256:75ffce5d106e34b717b31844c1639ea505b7d9550dc23b96fb6c20d086b53fa3 # via pandas-gbq -pygments==2.19.2 \ - --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \ - --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b +pygments==2.20.0 \ + --hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \ + --hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176 # via # feast (pyproject.toml) # rich # sphinx -pyjwt[crypto]==2.11.0 \ - --hash=sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623 \ - --hash=sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469 +pyjwt[crypto]==2.12.1 \ + --hash=sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c \ + --hash=sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b # via # feast (pyproject.toml) # mcp @@ -2435,9 +2436,9 @@ pymysql==1.1.2 \ --hash=sha256:4961d3e165614ae65014e361811a724e2044ad3ea3739de9903ae7c21f539f03 \ --hash=sha256:e6b1d89711dd51f8f74b1631fe08f039e7d76cf67a42a323d3178f0f25762ed9 # via feast (pyproject.toml) -pyopenssl==25.3.0 \ - --hash=sha256:1fda6fc034d5e3d179d39e59c1895c9faeaf40a79de5fc4cbbfbe0d36f4a77b6 \ - --hash=sha256:c981cb0a3fd84e8602d7afc209522773b94c1c2446a3c710a75b06fe1beae329 +pyopenssl==26.0.0 \ + --hash=sha256:df94d28498848b98cc1c0ffb8ef1e71e40210d3b0a8064c9d29571ed2904bf81 \ + --hash=sha256:f293934e52936f2e3413b89c6ce36df66a0b34ae1ea3a053b8c5020ff2f513fc # via snowflake-connector-python pyproject-metadata==0.11.0 \ --hash=sha256:85bbecca8694e2c00f63b492c96921d6c228454057c88e7c352b2077fcaa4096 \ @@ -2453,9 +2454,9 @@ python-dateutil==2.9.0.post0 \ # ibis-framework # kubernetes # pandas -python-dotenv==1.2.1 \ - --hash=sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6 \ - --hash=sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61 +python-dotenv==1.2.2 \ + --hash=sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a \ + --hash=sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3 # via # pydantic-settings # pymilvus @@ -2464,9 +2465,9 @@ python-multipart==0.0.22 \ --hash=sha256:2b2cd894c83d21bf49d702499531c7bafd057d730c201782048f7945d82de155 \ --hash=sha256:7340bef99a7e0032613f56dc36027b959fd3b30a787ed62d310e951f7c3a3a58 # via mcp -pytz==2025.2 \ - --hash=sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3 \ - --hash=sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00 +pytz==2026.1.post1 \ + --hash=sha256:3378dde6a0c3d26719182142c56e60c7f9af7e968076f31aae569d72a0358ee1 \ + --hash=sha256:f2fd16142fda348286a75e1a524be810bb05d444e5a081f37f7affc635035f7a # via # pandas # snowflake-connector-python @@ -2559,9 +2560,9 @@ referencing==0.37.0 \ # via # jsonschema # jsonschema-specifications -requests==2.32.5 \ - --hash=sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6 \ - --hash=sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf +requests==2.33.1 \ + --hash=sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517 \ + --hash=sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a # via # feast (pyproject.toml) # fastapi-mcp @@ -2578,9 +2579,9 @@ requests-oauthlib==2.0.0 \ # via # google-auth-oauthlib # kubernetes -rich==14.3.2 \ - --hash=sha256:08e67c3e90884651da3239ea668222d19bea7b589149d8014a21c633420dbb69 \ - --hash=sha256:e712f11c1a562a11843306f5ed999475f09ac31ffb64281f73ab29ffdda8b3b8 +rich==14.3.3 \ + --hash=sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d \ + --hash=sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b # via # fastapi-mcp # ibis-framework @@ -2708,17 +2709,13 @@ rpds-py==0.30.0 \ # via # jsonschema # referencing -rsa==4.9.1 \ - --hash=sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762 \ - --hash=sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75 - # via google-auth s3transfer==0.13.1 \ --hash=sha256:a981aa7429be23fe6dfc13e80e4020057cbab622b08c0315288758d67cabc724 \ --hash=sha256:c3fdba22ba1bd367922f27ec8032d6a1cf5f10c934fb5d68cf60fd5a23d936cf # via boto3 -scikit-build-core==0.11.6 \ - --hash=sha256:5982ccd839735be99cfd3b92a8847c6c196692f476c215da84b79d2ad12f9f1b \ - --hash=sha256:ce6d8fe64e6b4c759ea0fb95d2f8a68f60d2df31c2989838633b8ec930736360 +scikit-build-core==0.12.2 \ + --hash=sha256:562e0bbc9de1a354c87825ccf732080268d6582a0200f648e8c4a2dcb1e3736d \ + --hash=sha256:6ea4730da400f9a998ec3287bd3ebc1d751fe45ad0a93451bead8618adbc02b1 # via feast (pyproject.toml) setuptools==80.10.2 \ --hash=sha256:8b0e9d10c784bf7d262c4e5ec5d4ec94127ce206e8738f29a437945fbc219b70 \ @@ -2729,9 +2726,9 @@ setuptools==80.10.2 \ # pydata-google-auth # pymilvus # setuptools-scm -setuptools-scm==9.2.2 \ - --hash=sha256:1c674ab4665686a0887d7e24c03ab25f24201c213e82ea689d2f3e169ef7ef57 \ - --hash=sha256:30e8f84d2ab1ba7cb0e653429b179395d0c33775d54807fc5f1dd6671801aef7 +setuptools-scm==10.0.5 \ + --hash=sha256:bbba8fe754516cdefd017f4456721775e6ef9662bd7887fb52ae26813d4838c3 \ + --hash=sha256:f611037d8aae618221503b8fa89319f073438252ae3420e01c9ceec249131a0a # via hatch-vcs shellingham==1.5.4 \ --hash=sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686 \ @@ -2747,33 +2744,32 @@ snowballstemmer==3.0.1 \ --hash=sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064 \ --hash=sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895 # via sphinx -snowflake-connector-python[pandas]==4.3.0 \ - --hash=sha256:08f5167a10d380fe66330d5b19d19bd8b4f4af27e9648e3b254e61da025646bf \ - --hash=sha256:120463ca391d9deda3bdb185104ba847e12f73c86ef411cfcf827ce49b64d1af \ - --hash=sha256:26a65c5c93d14c4d221b780fdb2f07b4dd83e848f39eabd4832778bf0e2694d4 \ - --hash=sha256:2e0f66acee330388815fb842f91a46c9cacdefdf02c816354e6adeca8c2c3f86 \ - --hash=sha256:3e2ce47485862fa14ffbf2732f0fd02aa69a7c68a50d5f6286f34ed17527cf87 \ - --hash=sha256:486d17332b9228d2e5975755b434e6a282756a447e0c6605d4e797944fa919da \ - --hash=sha256:55163c5d9b93e10d7217aabd56f776b16c0fe13774f8d5db9188824731da9586 \ - --hash=sha256:676b56eedcc268b7e25a447e736eb8bf8bcacfbc71196c94d6f45746672ee6d5 \ - --hash=sha256:726435b2769135b6282601efb2cd8fd53f7deb1ff2fb7da93d28141fa3c8b17e \ - --hash=sha256:762ffa9673465ccc630aba438d648e0b1a2452ba49669a54a60d1625f36898f3 \ - --hash=sha256:7763c0d5f8e6326ec31f8972cc806fb6d3e07b06ca59f67dfcdf02a34219bcbc \ - --hash=sha256:79cbf5e359cfc33b4c4307df1fe8f78cd5aee56f5c50b98a647fa0cd9ba82cfc \ - --hash=sha256:79f150297b39cfd2481b732554fc4d68b43c83c82eb01e670cc4051cffc089d6 \ - --hash=sha256:7c18b5021ffa6de8313f2c7f0ae6050c36bcee7cb33bb23d40a7fdf3e0a751f2 \ - --hash=sha256:9faa9280e41258fb479ec5395b6a17d3dbb316146832e436aed582b300de655e \ - --hash=sha256:ac18b37e03a29014a9c91aac10c7dbdfa11134c620c6f93dd16f4b99b6a38c2a \ - --hash=sha256:b5a8d91c3e0127360bc3de605df9d02ea4d87e4524a50bf2e7c5c4200f9abf78 \ - --hash=sha256:c1356a2c615e120f913e5235fe87ff8aadbb479ad5a5ac5c0a84881d5fbe981d \ - --hash=sha256:c6fa80373b82125552e691f47b603766ed783f3d90a5782564854aa224aee9d1 \ - --hash=sha256:ca9d22c61f4e3d171b0adad3e9211747917c3a978dfb99564307c1ceadb0f0cd \ - --hash=sha256:ce55b93120f8b429010bf39cc02e739610b6da2ccdd34fcfc0df04849d0fd9d4 \ - --hash=sha256:e3044e6a237b35f750394f199f5e3800dfeb3227c4c8562584877e814d2dc89a \ - --hash=sha256:e42dd9af46fa3ad0e61c1aa6a227357cace481916797ecb92dbb14adb61931e1 \ - --hash=sha256:e5d360d65d42dd97cf82e688a1a7f235b9bc048b4949c9c5c7052ff2783c444e \ - --hash=sha256:e96aaf23f2b021e0d2aac8ac1b541975cd1f6896d9115eefe0938114e694a562 \ - --hash=sha256:f5291c00f610b266ab8c79b1e008b3d0cb29bb5b86a0007529320921b4a3fc3c +snowflake-connector-python[pandas]==4.4.0 \ + --hash=sha256:16fdca775f7ca5ce4a973c07c434f5ab72bef5284e81a5e4ae2fb4d54d28965c \ + --hash=sha256:19d0c1ed033abae715a71b74c53010b180a5247c6924f851e4f7d0b0d58066c4 \ + --hash=sha256:2a6f6a514a10c3bb2d4554132f0b639f43d7e9fbb73fa1fae1c8a75333102686 \ + --hash=sha256:307f41326c702f6976746d2001dacf35adaf567f3f12afb3a5778fbb063c7241 \ + --hash=sha256:43e1a2f3ac51d24406d4eb0c23a8ceb9d6f5cb4854c941e5e1375d8c481e2844 \ + --hash=sha256:52efe2d6543a09807283748dd50a36ec01d52b4f342868132f8f9856b9c95a42 \ + --hash=sha256:56ff04dd9e17edc82128f412aa3776687dc94088f3d6b9144971e169952623cb \ + --hash=sha256:648f49029d699591af0f253e81c5bf60efc4411c7b0149ef074a59a038210a3b \ + --hash=sha256:693a1bef97509f09b7e6f42ea6f743d27819413c04fb3dc543b060d029871c56 \ + --hash=sha256:70d4051e2d9c87258b02672e17e21f5873e0cb49ff9705f6194ccfa25ac0d5fd \ + --hash=sha256:7c2984663a733d06c979aa6c8c1d7691621ec0d3521ef345d57c869ff2f1c4b2 \ + --hash=sha256:8304b4818d3e9de552dcfbdd0bca61bae1583e1c9794e242e58fe44bce701604 \ + --hash=sha256:85a01338d282423611f357cd5392dca2219bbda9a66b44761b11d6ae8ebf1e50 \ + --hash=sha256:96fdca994c4d9f7780e82fc7b4bd3398d856b43de3bae57d44e242ff435a2431 \ + --hash=sha256:9b1a28f843c1c0b582db7854789525d0c8aac4ea5c56e31113684e38220d0af9 \ + --hash=sha256:9fa43d330389df27024757c4f97dabddafbedc74b8bcc189b6a86e8b4d036014 \ + --hash=sha256:a088f108da4653ad1396ddb63a1c757ad614d0862c38f6f69cc77344bdcfeccb \ + --hash=sha256:b9f0ac0c00075321e1720d3876e936ee0256f54832e7463c5193a8dfa54913d5 \ + --hash=sha256:c828248214a49f77b903e05acf887d3ccb9d958b5a979f2ed3663bba1bd0f2b3 \ + --hash=sha256:d6fd334e4d8df7fcb30e6746e5ade845e82de2942268862aa8bce974ae2b86a2 \ + --hash=sha256:d8ac1659c8e588b9502f8d3d03c1ded2f274de0da9c09e62fe007cba5b46d6a5 \ + --hash=sha256:e8e7ce0e8b33aec8b1fc6741eb51dbeb54e2c3a6d282a0d459c355a85f089b08 \ + --hash=sha256:ea6e4083ebea0a814b46f029d64a2fb0ba6e7732952cd8af4406041708ce0e21 \ + --hash=sha256:f5d0e90e68a899c13fda5ca842ff77b5759b1674adf2c72702d3c2b53ca9d27b \ + --hash=sha256:fb628d5ea1999e23bfbaabce4125eb44d56605ca5634b8b1d6092ab22d555598 # via feast (pyproject.toml) sortedcontainers==2.4.0 \ --hash=sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88 \ @@ -2807,85 +2803,89 @@ sphinxcontrib-serializinghtml==2.0.0 \ --hash=sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331 \ --hash=sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d # via sphinx -sqlalchemy[mypy]==2.0.46 \ - --hash=sha256:09168817d6c19954d3b7655da6ba87fcb3a62bb575fb396a81a8b6a9fadfe8b5 \ - --hash=sha256:0cc3117db526cad3e61074100bd2867b533e2c7dc1569e95c14089735d6fb4fe \ - --hash=sha256:181903fe8c1b9082995325f1b2e84ac078b1189e2819380c2303a5f90e114a62 \ - --hash=sha256:1bc3f601f0a818d27bfe139f6766487d9c88502062a2cd3a7ee6c342e81d5047 \ - --hash=sha256:1e6199143d51e3e1168bedd98cc698397404a8f7508831b81b6a29b18b051069 \ - --hash=sha256:2347c3f0efc4de367ba00218e0ae5c4ba2306e47216ef80d6e31761ac97cb0b9 \ - --hash=sha256:261c4b1f101b4a411154f1da2b76497d73abbfc42740029205d4d01fa1052684 \ - --hash=sha256:33e462154edb9493f6c3ad2125931e273bbd0be8ae53f3ecd1c161ea9a1dd366 \ - --hash=sha256:37fee2164cf21417478b6a906adc1a91d69ae9aba8f9533e67ce882f4bb1de53 \ - --hash=sha256:3a9a72b0da8387f15d5810f1facca8f879de9b85af8c645138cba61ea147968c \ - --hash=sha256:3aac08f7546179889c62b53b18ebf1148b10244b3405569c93984b0388d016a7 \ - --hash=sha256:3c32e993bc57be6d177f7d5d31edb93f30726d798ad86ff9066d75d9bf2e0b6b \ - --hash=sha256:412f26bb4ba942d52016edc8d12fb15d91d3cd46b0047ba46e424213ad407bcb \ - --hash=sha256:42a1643dc5427b69aca967dae540a90b0fbf57eaf248f13a90ea5930e0966863 \ - --hash=sha256:4396c948d8217e83e2c202fbdcc0389cf8c93d2c1c5e60fa5c5a955eae0e64be \ - --hash=sha256:4dafb537740eef640c4d6a7c254611dca2df87eaf6d14d6a5fca9d1f4c3fc0fa \ - --hash=sha256:4f52f7291a92381e9b4de9050b0a65ce5d6a763333406861e33906b8aa4906bf \ - --hash=sha256:52fe29b3817bd191cc20bad564237c808967972c97fa683c04b28ec8979ae36f \ - --hash=sha256:56bdd261bfd0895452006d5316cbf35739c53b9bb71a170a331fa0ea560b2ada \ - --hash=sha256:585af6afe518732d9ccd3aea33af2edaae4a7aa881af5d8f6f4fe3a368699597 \ - --hash=sha256:590be24e20e2424a4c3c1b0835e9405fa3d0af5823a1a9fc02e5dff56471515f \ - --hash=sha256:64901e08c33462acc9ec3bad27fc7a5c2b6491665f2aa57564e57a4f5d7c52ad \ - --hash=sha256:6ac245604295b521de49b465bab845e3afe6916bcb2147e5929c8041b4ec0545 \ - --hash=sha256:6f827fd687fa1ba7f51699e1132129eac8db8003695513fcf13fc587e1bd47a5 \ - --hash=sha256:70ed2830b169a9960193f4d4322d22be5c0925357d82cbf485b3369893350908 \ - --hash=sha256:716be5bcabf327b6d5d265dbdc6213a01199be587224eb991ad0d37e83d728fd \ - --hash=sha256:7568fe771f974abadce52669ef3a03150ff03186d8eb82613bc8adc435a03f01 \ - --hash=sha256:77f8071d8fbcbb2dd11b7fd40dedd04e8ebe2eb80497916efedba844298065ef \ - --hash=sha256:82ec52100ec1e6ec671563bbd02d7c7c8d0b9e71a0723c72f22ecf52d1755330 \ - --hash=sha256:895296687ad06dc9b11a024cf68e8d9d3943aa0b4964278d2553b86f1b267735 \ - --hash=sha256:8d3b44b3d0ab2f1319d71d9863d76eeb46766f8cf9e921ac293511804d39813f \ - --hash=sha256:8d679b5f318423eacb61f933a9a0f75535bfca7056daeadbf6bd5bcee6183aee \ - --hash=sha256:8e84b09a9b0f19accedcbeff5c2caf36e0dd537341a33aad8d680336152dc34e \ - --hash=sha256:9094c8b3197db12aa6f05c51c05daaad0a92b8c9af5388569847b03b1007fb1b \ - --hash=sha256:90bde6c6b1827565a95fde597da001212ab436f1b2e0c2dcc7246e14db26e2a3 \ - --hash=sha256:9397b381dcee8a2d6b99447ae85ea2530dcac82ca494d1db877087a13e38926d \ - --hash=sha256:93a12da97cca70cea10d4b4fc602589c4511f96c1f8f6c11817620c021d21d00 \ - --hash=sha256:93bb0aae40b52c57fd74ef9c6933c08c040ba98daf23ad33c3f9893494b8d3ce \ - --hash=sha256:94b1e5f3a5f1ff4f42d5daab047428cd45a3380e51e191360a35cef71c9a7a2a \ - --hash=sha256:965c62be8256d10c11f8907e7a8d3e18127a4c527a5919d85fa87fd9ecc2cfdc \ - --hash=sha256:96c7cca1a4babaaf3bfff3e4e606e38578856917e52f0384635a95b226c87764 \ - --hash=sha256:9bcdce05f056622a632f1d44bb47dbdb677f58cad393612280406ce37530eb6d \ - --hash=sha256:9d80ea2ac519c364a7286e8d765d6cd08648f5b21ca855a8017d9871f075542d \ - --hash=sha256:a1e8cc6cc01da346dc92d9509a63033b9b1bda4fed7a7a7807ed385c7dccdc10 \ - --hash=sha256:ab65cb2885a9f80f979b85aa4e9c9165a31381ca322cbde7c638fe6eefd1ec39 \ - --hash=sha256:af865c18752d416798dae13f83f38927c52f085c52e2f32b8ab0fef46fdd02c2 \ - --hash=sha256:b1e14b2f6965a685c7128bd315e27387205429c2e339eeec55cb75ca4ab0ea2e \ - --hash=sha256:b2a9f9aee38039cf4755891a1e50e1effcc42ea6ba053743f452c372c3152b1b \ - --hash=sha256:be6c0466b4c25b44c5d82b0426b5501de3c424d7a3220e86cd32f319ba56798e \ - --hash=sha256:c4e2cc868b7b5208aec6c960950b7bb821f82c2fe66446c92ee0a571765e91a5 \ - --hash=sha256:c805fa6e5d461329fa02f53f88c914d189ea771b6821083937e79550bf31fc19 \ - --hash=sha256:cf36851ee7219c170bb0793dbc3da3e80c582e04a5437bc601bfe8c85c9216d7 \ - --hash=sha256:db23b1bf8cfe1f7fda19018e7207b20cdb5168f83c437ff7e95d19e39289c447 \ - --hash=sha256:e0c05aff5c6b1bb5fb46a87e0f9d2f733f83ef6cbbbcd5c642b6c01678268061 \ - --hash=sha256:e8ac45e8f4eaac0f9f8043ea0e224158855c6a4329fd4ee37c45c61e3beb518e \ - --hash=sha256:ea3cd46b6713a10216323cda3333514944e510aa691c945334713fca6b5279ff \ - --hash=sha256:ebf7e1e78af38047e08836d33502c7a278915698b7c2145d045f780201679999 \ - --hash=sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e \ - --hash=sha256:ff33c6e6ad006bbc0f34f5faf941cfc62c45841c64c0a058ac38c799f15b5ede +sqlalchemy[mypy]==2.0.48 \ + --hash=sha256:01f6bbd4308b23240cf7d3ef117557c8fd097ec9549d5d8a52977544e35b40ad \ + --hash=sha256:07edba08061bc277bfdc772dd2a1a43978f5a45994dd3ede26391b405c15221e \ + --hash=sha256:10853a53a4a00417a00913d270dddda75815fcb80675874285f41051c094d7dd \ + --hash=sha256:1182437cb2d97988cfea04cf6cdc0b0bb9c74f4d56ec3d08b81e23d621a28cc6 \ + --hash=sha256:144921da96c08feb9e2b052c5c5c1d0d151a292c6135623c6b2c041f2a45f9e0 \ + --hash=sha256:1a89ce07ad2d4b8cfc30bd5889ec40613e028ed80ef47da7d9dd2ce969ad30e0 \ + --hash=sha256:1b4c575df7368b3b13e0cebf01d4679f9a28ed2ae6c1cd0b1d5beffb6b2007dc \ + --hash=sha256:1ccd42229aaac2df431562117ac7e667d702e8e44afdb6cf0e50fa3f18160f0b \ + --hash=sha256:2645b7d8a738763b664a12a1542c89c940daa55196e8d73e55b169cc5c99f65f \ + --hash=sha256:288937433bd44e3990e7da2402fabc44a3c6c25d3704da066b85b89a85474ae0 \ + --hash=sha256:34634e196f620c7a61d18d5cf7dc841ca6daa7961aed75d532b7e58b309ac894 \ + --hash=sha256:348174f228b99f33ca1f773e85510e08927620caa59ffe7803b37170df30332b \ + --hash=sha256:36ac4ddc3d33e852da9cb00ffb08cea62ca05c39711dc67062ca2bb1fae35fd8 \ + --hash=sha256:3713e21ea67bca727eecd4a24bf68bcd414c403faae4989442be60994301ded0 \ + --hash=sha256:389b984139278f97757ea9b08993e7b9d1142912e046ab7d82b3fbaeb0209131 \ + --hash=sha256:426c5ca86415d9b8945c7073597e10de9644802e2ff502b8e1f11a7a2642856b \ + --hash=sha256:4599a95f9430ae0de82b52ff0d27304fe898c17cb5f4099f7438a51b9998ac77 \ + --hash=sha256:49b7bddc1eebf011ea5ab722fdbe67a401caa34a350d278cc7733c0e88fecb1f \ + --hash=sha256:53667b5f668991e279d21f94ccfa6e45b4e3f4500e7591ae59a8012d0f010dcb \ + --hash=sha256:546572a1793cc35857a2ffa1fe0e58571af1779bcc1ffa7c9fb0839885ed69a9 \ + --hash=sha256:583849c743e0e3c9bb7446f5b5addeacedc168d657a69b418063dfdb2d90081c \ + --hash=sha256:5aee45fd2c6c0f2b9cdddf48c48535e7471e42d6fb81adfde801da0bd5b93241 \ + --hash=sha256:5b193a7e29fd9fa56e502920dca47dffe60f97c863494946bd698c6058a55658 \ + --hash=sha256:5ca74f37f3369b45e1f6b7b06afb182af1fd5dde009e4ffd831830d98cbe5fe7 \ + --hash=sha256:68549c403f79a8e25984376480959975212a670405e3913830614432b5daa07a \ + --hash=sha256:69f5bc24904d3bc3640961cddd2523e361257ef68585d6e364166dfbe8c78fae \ + --hash=sha256:6bb85c546591569558571aa1b06aba711b26ae62f111e15e56136d69920e1616 \ + --hash=sha256:6f7b7243850edd0b8b97043f04748f31de50cf426e939def5c16bedb540698f7 \ + --hash=sha256:7001dc9d5f6bb4deb756d5928eaefe1930f6f4179da3924cbd95ee0e9f4dce89 \ + --hash=sha256:7a936f1bb23d370b7c8cc079d5fce4c7d18da87a33c6744e51a93b0f9e97e9b3 \ + --hash=sha256:7c998f2ace8bf76b453b75dbcca500d4f4b9dd3908c13e89b86289b37784848b \ + --hash=sha256:7cddca31edf8b0653090cbb54562ca027c421c58ddde2c0685f49ff56a1690e0 \ + --hash=sha256:8183dc57ae7d9edc1346e007e840a9f3d6aa7b7f165203a99e16f447150140d2 \ + --hash=sha256:82745b03b4043e04600a6b665cb98697c4339b24e34d74b0a2ac0a2488b6f94d \ + --hash=sha256:841a94c66577661c1f088ac958cd767d7c9bf507698f45afffe7a4017049de76 \ + --hash=sha256:858e433f12b0e5b3ed2f8da917433b634f4937d0e8793e5cb33c54a1a01df565 \ + --hash=sha256:908a3fa6908716f803b86896a09a2c4dde5f5ce2bb07aacc71ffebb57986ce99 \ + --hash=sha256:9764014ef5e58aab76220c5664abb5d47d5bc858d9debf821e55cfdd0f128485 \ + --hash=sha256:9c7d0a77e36b5f4b01ca398482230ab792061d243d715299b44a0b55c89fe617 \ + --hash=sha256:a5b429eb84339f9f05e06083f119ad814e6d85e27ecbdf9c551dfdbb128eaf8a \ + --hash=sha256:a66fe406437dd65cacd96a72689a3aaaecaebbcd62d81c5ac1c0fdbeac835096 \ + --hash=sha256:a6b764fb312bd35e47797ad2e63f0d323792837a6ac785a4ca967019357d2bc7 \ + --hash=sha256:b19151e76620a412c2ac1c6f977ab1b9fa7ad43140178345136456d5265b32ed \ + --hash=sha256:b8438ec5594980d405251451c5b7ea9aa58dda38eb7ac35fb7e4c696712ee24f \ + --hash=sha256:b8fc3454b4f3bd0a368001d0e968852dad45a873f8b4babd41bc302ec851a099 \ + --hash=sha256:bcb8ebbf2e2c36cfe01a94f2438012c6a9d494cf80f129d9753bcdf33bfc35a6 \ + --hash=sha256:d404dc897ce10e565d647795861762aa2d06ca3f4a728c5e9a835096c7059018 \ + --hash=sha256:d612c976cbc2d17edfcc4c006874b764e85e990c29ce9bd411f926bbfb02b9a2 \ + --hash=sha256:d64177f443594c8697369c10e4bbcac70ef558e0f7921a1de7e4a3d1734bcf67 \ + --hash=sha256:d854b3970067297f3a7fbd7a4683587134aa9b3877ee15aa29eea478dc68f933 \ + --hash=sha256:d8fcccbbc0c13c13702c471da398b8cd72ba740dca5859f148ae8e0e8e0d3e7e \ + --hash=sha256:e004aa9248e8cb0a5f9b96d003ca7c1c0a5da8decd1066e7b53f59eb8ce7c62b \ + --hash=sha256:e214d546c8ecb5fc22d6e6011746082abf13a9cf46eefb45769c7b31407c97b5 \ + --hash=sha256:e2d0d88686e3d35a76f3e15a34e8c12d73fc94c1dea1cd55782e695cc14086dd \ + --hash=sha256:e2f35b4cccd9ed286ad62e0a3c3ac21e06c02abc60e20aa51a3e305a30f5fa79 \ + --hash=sha256:e3070c03701037aa418b55d36532ecb8f8446ed0135acb71c678dbdf12f5b6e4 \ + --hash=sha256:e5e088bf43f6ee6fec7dbf1ef7ff7774a616c236b5c0cb3e00662dd71a56b571 \ + --hash=sha256:e83e3f959aaa1c9df95c22c528096d94848a1bc819f5d0ebf7ee3df0ca63db6c \ + --hash=sha256:f0dcbc588cd5b725162c076eb9119342f6579c7f7f55057bb7e3c6ff27e13121 \ + --hash=sha256:f27f9da0a7d22b9f981108fd4b62f8b5743423388915a563e651c20d06c1f457 \ + --hash=sha256:f8649a14caa5f8a243628b1d61cf530ad9ae4578814ba726816adb1121fc493e \ + --hash=sha256:fac0fa4e4f55f118fd87177dacb1c6522fe39c28d498d259014020fec9164c29 \ + --hash=sha256:fd08b90d211c086181caed76931ecfa2bdfc83eea3cfccdb0f82abc6c4b876cb # via feast (pyproject.toml) -sqlglot==28.10.1 \ - --hash=sha256:214aef51fd4ce16407022f81cfc80c173409dab6d0f6ae18c52b43f43b31d4dd \ - --hash=sha256:66e0dae43b4bce23314b80e9aef41b8c88fea0e17ada62de095b45262084a8c5 +sqlglot==30.2.1 \ + --hash=sha256:ef4a67cc6f66a8043085eb8ea95fa9541c1625dffa9145ad4e9815a7ba60a199 \ + --hash=sha256:f23d9ee9427ef9d20df15f9b0ffa57d9eb45e52b012219a349d1e6b50ed926d1 # via ibis-framework -sse-starlette==3.2.0 \ - --hash=sha256:5876954bd51920fc2cd51baee47a080eb88a37b5b784e615abb0b283f801cdbf \ - --hash=sha256:8127594edfb51abe44eac9c49e59b0b01f1039d0c7461c6fd91d4e03b70da422 +sse-starlette==3.3.4 \ + --hash=sha256:84bb06e58939a8b38d8341f1bc9792f06c2b53f48c608dd207582b664fc8f3c1 \ + --hash=sha256:aaf92fc067af8a5427192895ac028e947b484ac01edbc3caf00e7e7137c7bef1 # via mcp -starlette==0.52.1 \ - --hash=sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74 \ - --hash=sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933 +starlette==1.0.0 \ + --hash=sha256:6a4beaf1f81bb472fd19ea9b918b50dc3a77a6f2e190a12954b25e6ed5eea149 \ + --hash=sha256:d3ec55e0bb321692d275455ddfd3df75fff145d009685eb40dc91fc66b03d38b # via # fastapi # mcp # sse-starlette -tabulate==0.9.0 \ - --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ - --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f +tabulate==0.10.0 \ + --hash=sha256:e2cfde8f79420f6deeffdeda9aaec3b6bc5abce947655d17ac662b126e48a60d \ + --hash=sha256:f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3 # via feast (pyproject.toml) tenacity==8.5.0 \ --hash=sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78 \ @@ -2895,54 +2895,54 @@ toml==0.10.2 \ --hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \ --hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f # via feast (pyproject.toml) -tomli==2.4.0 \ - --hash=sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729 \ - --hash=sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b \ - --hash=sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d \ - --hash=sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df \ - --hash=sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576 \ - --hash=sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d \ - --hash=sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1 \ - --hash=sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a \ - --hash=sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e \ - --hash=sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc \ - --hash=sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702 \ - --hash=sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6 \ - --hash=sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd \ - --hash=sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4 \ - --hash=sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776 \ - --hash=sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a \ - --hash=sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66 \ - --hash=sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87 \ - --hash=sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2 \ - --hash=sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f \ - --hash=sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475 \ - --hash=sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f \ - --hash=sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95 \ - --hash=sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9 \ - --hash=sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3 \ - --hash=sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9 \ - --hash=sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76 \ - --hash=sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da \ - --hash=sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8 \ - --hash=sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51 \ - --hash=sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86 \ - --hash=sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8 \ - --hash=sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0 \ - --hash=sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b \ - --hash=sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1 \ - --hash=sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e \ - --hash=sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d \ - --hash=sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c \ - --hash=sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867 \ - --hash=sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a \ - --hash=sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c \ - --hash=sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0 \ - --hash=sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4 \ - --hash=sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614 \ - --hash=sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132 \ - --hash=sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa \ - --hash=sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087 +tomli==2.4.1 \ + --hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \ + --hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \ + --hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \ + --hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \ + --hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \ + --hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \ + --hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \ + --hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \ + --hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \ + --hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \ + --hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \ + --hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \ + --hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \ + --hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \ + --hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \ + --hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \ + --hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \ + --hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \ + --hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \ + --hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \ + --hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \ + --hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \ + --hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \ + --hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \ + --hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \ + --hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \ + --hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \ + --hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \ + --hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \ + --hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \ + --hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \ + --hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \ + --hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \ + --hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \ + --hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \ + --hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \ + --hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \ + --hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \ + --hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \ + --hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \ + --hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \ + --hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \ + --hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \ + --hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \ + --hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \ + --hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \ + --hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049 # via fastapi-mcp tomlkit==0.14.0 \ --hash=sha256:592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680 \ @@ -2965,13 +2965,13 @@ trove-classifiers==2026.1.14.14 \ --hash=sha256:00492545a1402b09d4858605ba190ea33243d361e2b01c9c296ce06b5c3325f3 \ --hash=sha256:1f9553927f18d0513d8e5ff80ab8980b8202ce37ecae0e3274ed2ef11880e74d # via hatchling -typeguard==4.5.0 \ - --hash=sha256:749bea21cdb2553e12831bc29f1eae980b22c7de8331ab67ae7db9e85470b5a7 \ - --hash=sha256:cfda388fc88a9ce42a41890900d6f31ee124bea9b73bb84701a32438e92165c3 +typeguard==4.5.1 \ + --hash=sha256:44d2bf329d49a244110a090b55f5f91aa82d9a9834ebfd30bcc73651e4a8cc40 \ + --hash=sha256:f6f8ecbbc819c9bc749983cc67c02391e16a9b43b8b27f15dc70ed7c4a007274 # via feast (pyproject.toml) -typer==0.23.1 \ - --hash=sha256:2070374e4d31c83e7b61362fd859aa683576432fd5b026b060ad6b4cd3b86134 \ - --hash=sha256:3291ad0d3c701cbf522012faccfbb29352ff16ad262db2139e6b01f15781f14e +typer==0.24.1 \ + --hash=sha256:112c1f0ce578bfb4cab9ffdabc68f031416ebcc216536611ba21f04e9aa84c9e \ + --hash=sha256:e39b4732d65fbdcde189ae76cf7cd48aeae72919dea1fdfc16593be016256b45 # via fastapi-mcp types-psutil==7.0.0.20250218 \ --hash=sha256:1447a30c282aafefcf8941ece854e1100eee7b0296a9d9be9977292f0269b121 \ @@ -3016,91 +3016,85 @@ tzdata==2025.3 \ # via # ibis-framework # pandas -ujson==5.11.0 \ - --hash=sha256:0180a480a7d099082501cad1fe85252e4d4bf926b40960fb3d9e87a3a6fbbc80 \ - --hash=sha256:04c41afc195fd477a59db3a84d5b83a871bd648ef371cf8c6f43072d89144eef \ - --hash=sha256:0654a2691fc252c3c525e3d034bb27b8a7546c9d3eb33cd29ce6c9feda361a6a \ - --hash=sha256:090b4d11b380ae25453100b722d0609d5051ffe98f80ec52853ccf8249dfd840 \ - --hash=sha256:109f59885041b14ee9569bf0bb3f98579c3fa0652317b355669939e5fc5ede53 \ - --hash=sha256:10f29e71ecf4ecd93a6610bd8efa8e7b6467454a363c3d6416db65de883eb076 \ - --hash=sha256:1194b943e951092db611011cb8dbdb6cf94a3b816ed07906e14d3bc6ce0e90ab \ - --hash=sha256:12b5e7e22a1fe01058000d1b317d3b65cc3daf61bd2ea7a2b76721fe160fa74d \ - --hash=sha256:16ccb973b7ada0455201808ff11d48fe9c3f034a6ab5bd93b944443c88299f89 \ - --hash=sha256:181fb5b15703a8b9370b25345d2a1fd1359f0f18776b3643d24e13ed9c036d4c \ - --hash=sha256:185f93ebccffebc8baf8302c869fac70dd5dd78694f3b875d03a31b03b062cdb \ - --hash=sha256:1a0a9b76a89827a592656fe12e000cf4f12da9692f51a841a4a07aa4c7ecc41c \ - --hash=sha256:1a325fd2c3a056cf6c8e023f74a0c478dd282a93141356ae7f16d5309f5ff823 \ - --hash=sha256:1aa8a2ab482f09f6c10fba37112af5f957689a79ea598399c85009f2f29898b5 \ - --hash=sha256:1d663b96eb34c93392e9caae19c099ec4133ba21654b081956613327f0e973ac \ - --hash=sha256:29113c003ca33ab71b1b480bde952fbab2a0b6b03a4ee4c3d71687cdcbd1a29d \ - --hash=sha256:30f607c70091483550fbd669a0b37471e5165b317d6c16e75dba2aa967608723 \ - --hash=sha256:3134b783ab314d2298d58cda7e47e7a0f7f71fc6ade6ac86d5dbeaf4b9770fa6 \ - --hash=sha256:34032aeca4510a7c7102bd5933f59a37f63891f30a0706fb46487ab6f0edf8f0 \ - --hash=sha256:3772e4fe6b0c1e025ba3c50841a0ca4786825a4894c8411bf8d3afe3a8061328 \ - --hash=sha256:3d2720e9785f84312b8e2cb0c2b87f1a0b1c53aaab3b2af3ab817d54409012e0 \ - --hash=sha256:416389ec19ef5f2013592f791486bef712ebce0cd59299bf9df1ba40bb2f6e04 \ - --hash=sha256:446e8c11c06048611c9d29ef1237065de0af07cabdd97e6b5b527b957692ec25 \ - --hash=sha256:4598bf3965fc1a936bd84034312bcbe00ba87880ef1ee33e33c1e88f2c398b49 \ - --hash=sha256:48055e1061c1bb1f79e75b4ac39e821f3f35a9b82de17fce92c3140149009bec \ - --hash=sha256:4843f3ab4fe1cc596bb7e02228ef4c25d35b4bb0809d6a260852a4bfcab37ba3 \ - --hash=sha256:49e56ef8066f11b80d620985ae36869a3ff7e4b74c3b6129182ec5d1df0255f3 \ - --hash=sha256:4b42c115c7c6012506e8168315150d1e3f76e7ba0f4f95616f4ee599a1372bbc \ - --hash=sha256:4c9f5d6a27d035dd90a146f7761c2272cf7103de5127c9ab9c4cd39ea61e878a \ - --hash=sha256:5600202a731af24a25e2d7b6eb3f648e4ecd4bb67c4d5cf12f8fab31677469c9 \ - --hash=sha256:65724738c73645db88f70ba1f2e6fb678f913281804d5da2fd02c8c5839af302 \ - --hash=sha256:65f3c279f4ed4bf9131b11972040200c66ae040368abdbb21596bf1564899694 \ - --hash=sha256:674f306e3e6089f92b126eb2fe41bcb65e42a15432c143365c729fdb50518547 \ - --hash=sha256:683f57f0dd3acdd7d9aff1de0528d603aafcb0e6d126e3dc7ce8b020a28f5d01 \ - --hash=sha256:6b6ec7e7321d7fc19abdda3ad809baef935f49673951a8bab486aea975007e02 \ - --hash=sha256:6cd2df62f24c506a0ba322d5e4fe4466d47a9467b57e881ee15a31f7ecf68ff6 \ - --hash=sha256:6dd703c3e86dc6f7044c5ac0b3ae079ed96bf297974598116aa5fb7f655c3a60 \ - --hash=sha256:6eff24e1abd79e0ec6d7eae651dd675ddbc41f9e43e29ef81e16b421da896915 \ - --hash=sha256:7855ccea3f8dad5e66d8445d754fc1cf80265a4272b5f8059ebc7ec29b8d0835 \ - --hash=sha256:787aff4a84da301b7f3bac09bc696e2e5670df829c6f8ecf39916b4e7e24e701 \ - --hash=sha256:7895f0d2d53bd6aea11743bd56e3cb82d729980636cd0ed9b89418bf66591702 \ - --hash=sha256:78c684fb21255b9b90320ba7e199780f653e03f6c2528663768965f4126a5b50 \ - --hash=sha256:7e0ec1646db172beb8d3df4c32a9d78015e671d2000af548252769e33079d9a6 \ - --hash=sha256:7e3cff632c1d78023b15f7e3a81c3745cd3f94c044d1e8fa8efbd6b161997bbc \ - --hash=sha256:7f1a27ab91083b4770e160d17f61b407f587548f2c2b5fbf19f94794c495594a \ - --hash=sha256:80017e870d882d5517d28995b62e4e518a894f932f1e242cbc802a2fd64d365c \ - --hash=sha256:8254e858437c00f17cb72e7a644fc42dad0ebb21ea981b71df6e84b1072aaa7c \ - --hash=sha256:837da4d27fed5fdc1b630bd18f519744b23a0b5ada1bbde1a36ba463f2900c03 \ - --hash=sha256:849e65b696f0d242833f1df4182096cedc50d414215d1371fca85c541fbff629 \ - --hash=sha256:85e6796631165f719084a9af00c79195d3ebf108151452fefdcb1c8bb50f0105 \ - --hash=sha256:86baf341d90b566d61a394869ce77188cc8668f76d7bb2c311d77a00f4bdf844 \ - --hash=sha256:8fa2af7c1459204b7a42e98263b069bd535ea0cd978b4d6982f35af5a04a4241 \ - --hash=sha256:94fcae844f1e302f6f8095c5d1c45a2f0bfb928cccf9f1b99e3ace634b980a2a \ - --hash=sha256:952c0be400229940248c0f5356514123d428cba1946af6fa2bbd7503395fef26 \ - --hash=sha256:99c49400572cd77050894e16864a335225191fd72a818ea6423ae1a06467beac \ - --hash=sha256:9aacbeb23fdbc4b256a7d12e0beb9063a1ba5d9e0dbb2cfe16357c98b4334596 \ - --hash=sha256:a0af6574fc1d9d53f4ff371f58c96673e6d988ed2b5bf666a6143c782fa007e9 \ - --hash=sha256:a31c6b8004438e8c20fc55ac1c0e07dad42941db24176fe9acf2815971f8e752 \ - --hash=sha256:a4df61a6df0a4a8eb5b9b1ffd673429811f50b235539dac586bb7e9e91994138 \ - --hash=sha256:a638425d3c6eed0318df663df44480f4a40dc87cc7c6da44d221418312f6413b \ - --hash=sha256:aa6b3d4f1c0d3f82930f4cbd7fe46d905a4a9205a7c13279789c1263faf06dba \ - --hash=sha256:aa6d7a5e09217ff93234e050e3e380da62b084e26b9f2e277d2606406a2fc2e5 \ - --hash=sha256:ab2cb8351d976e788669c8281465d44d4e94413718af497b4e7342d7b2f78018 \ - --hash=sha256:abae0fb58cc820092a0e9e8ba0051ac4583958495bfa5262a12f628249e3b362 \ - --hash=sha256:b16930f6a0753cdc7d637b33b4e8f10d5e351e1fb83872ba6375f1e87be39746 \ - --hash=sha256:b7b136cc6abc7619124fd897ef75f8e63105298b5ca9bdf43ebd0e1fa0ee105f \ - --hash=sha256:be6b0eaf92cae8cdee4d4c9e074bde43ef1c590ed5ba037ea26c9632fb479c88 \ - --hash=sha256:c44c703842024d796b4c78542a6fcd5c3cb948b9fc2a73ee65b9c86a22ee3638 \ - --hash=sha256:c6618f480f7c9ded05e78a1938873fde68baf96cdd74e6d23c7e0a8441175c4b \ - --hash=sha256:ce076f2df2e1aa62b685086fbad67f2b1d3048369664b4cdccc50707325401f9 \ - --hash=sha256:d06e87eded62ff0e5f5178c916337d2262fdbc03b31688142a3433eabb6511db \ - --hash=sha256:d7c46cb0fe5e7056b9acb748a4c35aa1b428025853032540bb7e41f46767321f \ - --hash=sha256:d8951bb7a505ab2a700e26f691bdfacf395bc7e3111e3416d325b513eea03a58 \ - --hash=sha256:da473b23e3a54448b008d33f742bcd6d5fb2a897e42d1fc6e7bf306ea5d18b1b \ - --hash=sha256:de6e88f62796372fba1de973c11138f197d3e0e1d80bcb2b8aae1e826096d433 \ - --hash=sha256:e204ae6f909f099ba6b6b942131cee359ddda2b6e4ea39c12eb8b991fe2010e0 \ - --hash=sha256:e73df8648c9470af2b6a6bf5250d4744ad2cf3d774dcf8c6e31f018bdd04d764 \ - --hash=sha256:e750c436fb90edf85585f5c62a35b35082502383840962c6983403d1bd96a02c \ - --hash=sha256:e979fbc469a7f77f04ec2f4e853ba00c441bf2b06720aa259f0f720561335e34 \ - --hash=sha256:ecd6ff8a3b5a90c292c2396c2d63c687fd0ecdf17de390d852524393cd9ed052 \ - --hash=sha256:f278b31a7c52eb0947b2db55a5133fbc46b6f0ef49972cd1a80843b72e135aba \ - --hash=sha256:f62b9976fabbcde3ab6e413f4ec2ff017749819a0786d84d7510171109f2d53c \ - --hash=sha256:fa79fdb47701942c2132a9dd2297a1a85941d966d8c87bfd9e29b0cf423f26cc \ - --hash=sha256:fac6c0649d6b7c3682a0a6e18d3de6857977378dce8d419f57a0b20e3d775b39 +ujson==5.12.0 \ + --hash=sha256:006428d3813b87477d72d306c40c09f898a41b968e57b15a7d88454ecc42a3fb \ + --hash=sha256:02f93da7a4115e24f886b04fd56df1ee8741c2ce4ea491b7ab3152f744ad8f8e \ + --hash=sha256:0727363b05ab05ee737a28f6200dc4078bce6b0508e10bd8aab507995a15df61 \ + --hash=sha256:085b6ce182cdd6657481c7c4003a417e0655c4f6e58b76f26ee18f0ae21db827 \ + --hash=sha256:09b4beff9cc91d445d5818632907b85fb06943b61cb346919ce202668bf6794a \ + --hash=sha256:0a3ae28f0b209be5af50b54ca3e2123a3de3a57d87b75f1e5aa3d7961e041983 \ + --hash=sha256:0d2e8db5ade3736a163906154ca686203acc7d1d30736cbf577c730d13653d84 \ + --hash=sha256:0e00cec383eab2406c9e006bd4edb55d284e94bb943fda558326048178d26961 \ + --hash=sha256:0fe6b8b8968e11dd9b2348bd508f0f57cf49ab3512064b36bc4117328218718e \ + --hash=sha256:0fe9128e75c6aa6e9ae06c1408d6edd9179a2fef0fe6d9cda3166b887eba521d \ + --hash=sha256:14b2e1eb528d77bc0f4c5bd1a7ebc05e02b5b41beefb7e8567c9675b8b13bcf4 \ + --hash=sha256:15d416440148f3e56b9b244fdaf8a09fcf5a72e4944b8e119f5bf60417a2bfc8 \ + --hash=sha256:15e555c4caca42411270b2ed2b2ebc7b3a42bb04138cef6c956e1f1d49709fe2 \ + --hash=sha256:16b4fe9c97dc605f5e1887a9e1224287291e35c56cbc379f8aa44b6b7bcfe2bb \ + --hash=sha256:1b5c6ceb65fecd28a1d20d1eba9dbfa992612b86594e4b6d47bb580d2dd6bcb3 \ + --hash=sha256:1d072a403d82aef8090c6d4f728e3a727dfdba1ad3b7fa3a052c3ecbd37e73cb \ + --hash=sha256:2324d9a0502317ffc35d38e153c1b2fa9610ae03775c9d0f8d0cca7b8572b04e \ + --hash=sha256:2a248750abce1c76fbd11b2e1d88b95401e72819295c3b851ec73399d6849b3d \ + --hash=sha256:2ea6206043385343aff0b7da65cf73677f6f5e50de8f1c879e557f4298cac36a \ + --hash=sha256:31348a0ffbfc815ce78daac569d893349d85a0b57e1cd2cdbba50b7f333784da \ + --hash=sha256:38051f36423f084b909aaadb3b41c9c6a2958e86956ba21a8489636911e87504 \ + --hash=sha256:3c2f947e55d3c7cfe124dd4521ee481516f3007d13c6ad4bf6aeb722e190eb1b \ + --hash=sha256:3ed5cb149892141b1e77ef312924a327f2cc718b34247dae346ed66329e1b8be \ + --hash=sha256:3ff4ede90ed771140caa7e1890de17431763a483c54b3c1f88bd30f0cc1affc0 \ + --hash=sha256:40aa43a7a3a8d2f05e79900858053d697a88a605e3887be178b43acbcd781161 \ + --hash=sha256:42d875388fbd091c7ea01edfff260f839ba303038ffb23475ef392012e4d63dd \ + --hash=sha256:457fabc2700a8e6ddb85bc5a1d30d3345fe0d3ec3ee8161a4e032ec585801dfa \ + --hash=sha256:460e76a4daff214ae33ab959494962c93918cb44714ea3e3f748b14aa37f8a87 \ + --hash=sha256:50524f4f6a1c839714dbaff5386a1afb245d2d5ec8213a01fbc99cea7307811e \ + --hash=sha256:51acc750ec7a2df786cdc868fb16fa04abd6269a01d58cf59bafc57978773d8e \ + --hash=sha256:55ede2a7a051b3b7e71a394978a098d71b3783e6b904702ff45483fad434ae2d \ + --hash=sha256:561f89cc82deeae82e37d4a4764184926fb432f740a9691563a391b13f7339a4 \ + --hash=sha256:56ba3f7abbd6b0bb282a544dc38406d1a188d8bb9164f49fdb9c2fee62cb29da \ + --hash=sha256:57930ac9519099b852e190d2c04b1fb5d97ea128db33bce77ed874eccb4c7f09 \ + --hash=sha256:58a11cb49482f1a095a2bd9a1d81dd7c8fb5d2357f959ece85db4e46a825fd00 \ + --hash=sha256:64df53eef4ac857eb5816a56e2885ccf0d7dff6333c94065c93b39c51063e01d \ + --hash=sha256:6879aed770557f0961b252648d36f6fdaab41079d37a2296b5649fd1b35608e0 \ + --hash=sha256:6ad57654570464eb1b040b5c353dee442608e06cff9102b8fcb105565a44c9ed \ + --hash=sha256:6c0aed6a4439994c9666fb8a5b6c4eac94d4ef6ddc95f9b806a599ef83547e3b \ + --hash=sha256:76bf3e7406cf23a3e1ca6a23fb1fb9ea82f4f6bd226fe226e09146b0194f85dc \ + --hash=sha256:7bbf05c38debc90d1a195b11340cc85cb43ab3e753dc47558a3a84a38cbc72da \ + --hash=sha256:7ddb08b3c2f9213df1f2e3eb2fbea4963d80ec0f8de21f0b59898e34f3b3d96d \ + --hash=sha256:7e07f6f644d2c44d53b7a320a084eef98063651912c1b9449b5f45fcbdc6ccd2 \ + --hash=sha256:85833bca01aa5cae326ac759276dc175c5fa3f7b3733b7d543cf27f2df12d1ef \ + --hash=sha256:8712b61eb1b74a4478cfd1c54f576056199e9f093659334aeb5c4a6b385338e5 \ + --hash=sha256:871c0e5102e47995b0e37e8df7819a894a6c3da0d097545cd1f9f1f7d7079927 \ + --hash=sha256:89e302abd3749f6d6699691747969a5d85f7c73081d5ed7e2624c7bd9721a2ab \ + --hash=sha256:937794042342006f707837f38d721426b11b0774d327a2a45c0bd389eb750a87 \ + --hash=sha256:93bc91fdadcf046da37a214eaa714574e7e9b1913568e93bb09527b2ceb7f759 \ + --hash=sha256:94c5f1621cbcab83c03be46441f090b68b9f307b6c7ec44d4e3f6d5997383df4 \ + --hash=sha256:973b7d7145b1ac553a7466a64afa8b31ec2693d7c7fff6a755059e0a2885dfd2 \ + --hash=sha256:99cc80facad240b0c2fb5a633044420878aac87a8e7c348b9486450cba93f27c \ + --hash=sha256:9a5fcbe7b949f2e95c47ea8a80b410fcdf2da61c98553b45a4ee875580418b68 \ + --hash=sha256:9b3b86ec3e818f3dd3e13a9de628e88a9990f4af68ecb0b12dd3de81227f0a26 \ + --hash=sha256:9b3cf13facf6f77c283af0e1713e5e8c47a0fe295af81326cb3cb4380212e797 \ + --hash=sha256:9c5a52987a990eb1bae55f9000994f1afdb0326c154fb089992f839ab3c30688 \ + --hash=sha256:a2d79c6635ccffcbfc1d5c045874ba36b594589be81d50d43472570bb8de9c57 \ + --hash=sha256:a6ec5bf6bc361f2f0f9644907a36ce527715b488988a8df534120e5c34eeda94 \ + --hash=sha256:a7bf9cc97f05048ac8f3e02cd58f0fe62b901453c24345bfde287f4305dcc31c \ + --hash=sha256:ab9056d94e5db513d9313b34394f3a3b83e6301a581c28ad67773434f3faccab \ + --hash=sha256:adf28d13a33f9d750fe7a78fb481cac298fa257d8863d8727b2ea4455ea41235 \ + --hash=sha256:b62cb9a7501e1f5c9ffe190485501349c33e8862dde4377df774e40b8166871f \ + --hash=sha256:bacbd3c69862478cbe1c7ed4325caedec580d8acf31b8ee1b9a1e02a56295cad \ + --hash=sha256:bb349dbba57c76eec25e5917e07f35aabaf0a33b9e67fc13d188002500106487 \ + --hash=sha256:bd03472c36fa3a386a6deb887113b9e3fa40efba8203eb4fe786d3c0ccc724f6 \ + --hash=sha256:bf85a00ac3b56a1e7a19c5be7b02b5180a0895ac4d3c234d717a55e86960691c \ + --hash=sha256:ca0c7ce828bb76ab78b3991904b477c2fd0f711d7815c252d1ef28ff9450b052 \ + --hash=sha256:ccbfd94e59aad4a2566c71912b55f0547ac1680bfac25eb138e6703eb3dd434e \ + --hash=sha256:d1831c07bd4dce53c4b666fa846c7eba4b7c414f2e641a4585b7f50b72f502dc \ + --hash=sha256:d22cad98c2a10bbf6aa083a8980db6ed90d4285a841c4de892890c2b28286ef9 \ + --hash=sha256:d30ad4359413c8821cc7b3707f7ca38aa8bc852ba3b9c5a759ee2d7740157315 \ + --hash=sha256:e0dd3676ea0837cd70ea1879765e9e9f6be063be0436de9b3ea4b775caf83654 \ + --hash=sha256:e584d0cdd37cac355aca52ed788d1a2d939d6837e2870d3b70e585db24025a50 \ + --hash=sha256:e6369ac293d2cc40d52577e4fa3d75a70c1aae2d01fa3580a34a4e6eff9286b9 \ + --hash=sha256:efae5df7a8cc8bdb1037b0f786b044ce281081441df5418c3a0f0e1f86fe7bb3 \ + --hash=sha256:f19b3af31d02a2e79c5f9a6deaab0fb3c116456aeb9277d11720ad433de6dfc6 \ + --hash=sha256:f7a0430d765f9bda043e6aefaba5944d5f21ec43ff4774417d7e296f61917382 \ + --hash=sha256:fb94245a715b4d6e24689de12772b85329a1f9946cbf6187923a64ecdea39e65 # via pymilvus urllib3==2.6.3 \ --hash=sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed \ @@ -3172,6 +3166,10 @@ uvloop==0.22.1 \ --hash=sha256:ef6f0d4cc8a9fa1f6a910230cd53545d9a14479311e87e3cb225495952eb672c \ --hash=sha256:fe94b4564e865d968414598eea1a6de60adba0c040ba4ed05ac1300de402cd42 # via uvicorn +vcs-versioning==1.1.1 \ + --hash=sha256:b541e2ba79fc6aaa3850f8a7f88af43d97c1c80649c01142ee4146eddbc599e4 \ + --hash=sha256:fabd75a3cab7dd8ac02fe24a3a9ba936bf258667b5a62ed468c9a1da0f5775bc + # via setuptools-scm watchfiles==1.1.1 \ --hash=sha256:00485f441d183717038ed2e887a7c868154f216877653121068107b227a2f64c \ --hash=sha256:03fa0f5237118a0c5e496185cafa92878568b652a2e9a9382a5151b1a0380a43 \ @@ -3433,137 +3431,135 @@ wrapt==1.17.3 \ --hash=sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10 \ --hash=sha256:fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c # via aiobotocore -yarl==1.22.0 \ - --hash=sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a \ - --hash=sha256:029866bde8d7b0878b9c160e72305bbf0a7342bcd20b9999381704ae03308dc8 \ - --hash=sha256:078278b9b0b11568937d9509b589ee83ef98ed6d561dfe2020e24a9fd08eaa2b \ - --hash=sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da \ - --hash=sha256:07a524d84df0c10f41e3ee918846e1974aba4ec017f990dc735aad487a0bdfdf \ - --hash=sha256:088e4e08f033db4be2ccd1f34cf29fe994772fb54cfe004bbf54db320af56890 \ - --hash=sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093 \ - --hash=sha256:0cf71bf877efeac18b38d3930594c0948c82b64547c1cf420ba48722fe5509f6 \ - --hash=sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79 \ - --hash=sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683 \ - --hash=sha256:10619d9fdee46d20edc49d3479e2f8269d0779f1b031e6f7c2aa1c76be04b7ed \ - --hash=sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2 \ - --hash=sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff \ - --hash=sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02 \ - --hash=sha256:14291620375b1060613f4aab9ebf21850058b6b1b438f386cc814813d901c60b \ - --hash=sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03 \ - --hash=sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511 \ - --hash=sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c \ - --hash=sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124 \ - --hash=sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c \ - --hash=sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da \ - --hash=sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2 \ - --hash=sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0 \ - --hash=sha256:2e4e1f6f0b4da23e61188676e3ed027ef0baa833a2e633c29ff8530800edccba \ - --hash=sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d \ - --hash=sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53 \ - --hash=sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138 \ - --hash=sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4 \ - --hash=sha256:3aa27acb6de7a23785d81557577491f6c38a5209a254d1191519d07d8fe51748 \ - --hash=sha256:3b06bcadaac49c70f4c88af4ffcfbe3dc155aab3163e75777818092478bcbbe7 \ - --hash=sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d \ - --hash=sha256:3e2daa88dc91870215961e96a039ec73e4937da13cf77ce17f9cad0c18df3503 \ - --hash=sha256:3ea66b1c11c9150f1372f69afb6b8116f2dd7286f38e14ea71a44eee9ec51b9d \ - --hash=sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2 \ - --hash=sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa \ - --hash=sha256:437840083abe022c978470b942ff832c3940b2ad3734d424b7eaffcd07f76737 \ - --hash=sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f \ - --hash=sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1 \ - --hash=sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d \ - --hash=sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694 \ - --hash=sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3 \ - --hash=sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a \ - --hash=sha256:4c52a6e78aef5cf47a98ef8e934755abf53953379b7d53e68b15ff4420e6683d \ - --hash=sha256:4dcc74149ccc8bba31ce1944acee24813e93cfdee2acda3c172df844948ddf7b \ - --hash=sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a \ - --hash=sha256:51af598701f5299012b8416486b40fceef8c26fc87dc6d7d1f6fc30609ea0aa6 \ - --hash=sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b \ - --hash=sha256:595697f68bd1f0c1c159fcb97b661fc9c3f5db46498043555d04805430e79bea \ - --hash=sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5 \ - --hash=sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f \ - --hash=sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df \ - --hash=sha256:5cdac20da754f3a723cceea5b3448e1a2074866406adeb4ef35b469d089adb8f \ - --hash=sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b \ - --hash=sha256:5dbeefd6ca588b33576a01b0ad58aa934bc1b41ef89dee505bf2932b22ddffba \ - --hash=sha256:62441e55958977b8167b2709c164c91a6363e25da322d87ae6dd9c6019ceecf9 \ - --hash=sha256:663e1cadaddae26be034a6ab6072449a8426ddb03d500f43daf952b74553bba0 \ - --hash=sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6 \ - --hash=sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b \ - --hash=sha256:6944b2dc72c4d7f7052683487e3677456050ff77fcf5e6204e98caf785ad1967 \ - --hash=sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2 \ - --hash=sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708 \ - --hash=sha256:6dcbb0829c671f305be48a7227918cfcd11276c2d637a8033a99a02b67bf9eda \ - --hash=sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8 \ - --hash=sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10 \ - --hash=sha256:75976c6945d85dbb9ee6308cd7ff7b1fb9409380c82d6119bd778d8fcfe2931c \ - --hash=sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b \ - --hash=sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028 \ - --hash=sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e \ - --hash=sha256:80ddf7a5f8c86cb3eb4bc9028b07bbbf1f08a96c5c0bc1244be5e8fefcb94147 \ - --hash=sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33 \ - --hash=sha256:84fc3ec96fce86ce5aa305eb4aa9358279d1aa644b71fab7b8ed33fe3ba1a7ca \ - --hash=sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590 \ - --hash=sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c \ - --hash=sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53 \ - --hash=sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74 \ - --hash=sha256:99b6fc1d55782461b78221e95fc357b47ad98b041e8e20f47c1411d0aacddc60 \ - --hash=sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f \ - --hash=sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1 \ - --hash=sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27 \ - --hash=sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520 \ - --hash=sha256:a4fcfc8eb2c34148c118dfa02e6427ca278bfd0f3df7c5f99e33d2c0e81eae3e \ - --hash=sha256:a899cbd98dce6f5d8de1aad31cb712ec0a530abc0a86bd6edaa47c1090138467 \ - --hash=sha256:a9b1ba5610a4e20f655258d5a1fdc7ebe3d837bb0e45b581398b99eb98b1f5ca \ - --hash=sha256:af74f05666a5e531289cb1cc9c883d1de2088b8e5b4de48004e5ca8a830ac859 \ - --hash=sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273 \ - --hash=sha256:b266bd01fedeffeeac01a79ae181719ff848a5a13ce10075adbefc8f1daee70e \ - --hash=sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601 \ - --hash=sha256:b580e71cac3f8113d3135888770903eaf2f507e9421e5697d6ee6d8cd1c7f054 \ - --hash=sha256:b6a6f620cfe13ccec221fa312139135166e47ae169f8253f72a0abc0dae94376 \ - --hash=sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7 \ - --hash=sha256:b85b982afde6df99ecc996990d4ad7ccbdbb70e2a4ba4de0aecde5922ba98a0b \ - --hash=sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb \ - --hash=sha256:ba440ae430c00eee41509353628600212112cd5018d5def7e9b05ea7ac34eb65 \ - --hash=sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784 \ - --hash=sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71 \ - --hash=sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b \ - --hash=sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a \ - --hash=sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c \ - --hash=sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face \ - --hash=sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d \ - --hash=sha256:c7bd6683587567e5a49ee6e336e0612bec8329be1b7d4c8af5687dcdeb67ee1e \ - --hash=sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e \ - --hash=sha256:cb95a9b1adaa48e41815a55ae740cfda005758104049a640a398120bf02515ca \ - --hash=sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9 \ - --hash=sha256:d332fc2e3c94dad927f2112395772a4e4fedbcf8f80efc21ed7cdfae4d574fdb \ - --hash=sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95 \ - --hash=sha256:d5372ca1df0f91a86b047d1277c2aaf1edb32d78bbcefffc81b40ffd18f027ed \ - --hash=sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf \ - --hash=sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca \ - --hash=sha256:dd7afd3f8b0bfb4e0d9fc3c31bfe8a4ec7debe124cfd90619305def3c8ca8cd2 \ - --hash=sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62 \ - --hash=sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df \ - --hash=sha256:e1b329cb8146d7b736677a2440e422eadd775d1806a81db2d4cded80a48efc1a \ - --hash=sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67 \ - --hash=sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f \ - --hash=sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529 \ - --hash=sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486 \ - --hash=sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a \ - --hash=sha256:e6438cc8f23a9c1478633d216b16104a586b9761db62bfacb6425bac0a36679e \ - --hash=sha256:e81fda2fb4a07eda1a2252b216aa0df23ebcd4d584894e9612e80999a78fd95b \ - --hash=sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74 \ - --hash=sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d \ - --hash=sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b \ - --hash=sha256:f0d97c18dfd9a9af4490631905a3f131a8e4c9e80a39353919e2cfed8f00aedc \ - --hash=sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2 \ - --hash=sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e \ - --hash=sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8 \ - --hash=sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82 \ - --hash=sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd \ - --hash=sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249 +yarl==1.23.0 \ + --hash=sha256:03214408cfa590df47728b84c679ae4ef00be2428e11630277be0727eba2d7cc \ + --hash=sha256:041b1a4cefacf65840b4e295c6985f334ba83c30607441ae3cf206a0eed1a2e4 \ + --hash=sha256:0793e2bd0cf14234983bbb371591e6bea9e876ddf6896cdcc93450996b0b5c85 \ + --hash=sha256:0e1fdaa14ef51366d7757b45bde294e95f6c8c049194e793eedb8387c86d5993 \ + --hash=sha256:0e40111274f340d32ebcc0a5668d54d2b552a6cca84c9475859d364b380e3222 \ + --hash=sha256:115136c4a426f9da976187d238e84139ff6b51a20839aa6e3720cd1026d768de \ + --hash=sha256:13a563739ae600a631c36ce096615fe307f131344588b0bc0daec108cdb47b25 \ + --hash=sha256:16c6994ac35c3e74fb0ae93323bf8b9c2a9088d55946109489667c510a7d010e \ + --hash=sha256:170e26584b060879e29fac213e4228ef063f39128723807a312e5c7fec28eff2 \ + --hash=sha256:17235362f580149742739cc3828b80e24029d08cbb9c4bda0242c7b5bc610a8e \ + --hash=sha256:1932b6b8bba8d0160a9d1078aae5838a66039e8832d41d2992daa9a3a08f7860 \ + --hash=sha256:1b6b572edd95b4fa8df75de10b04bc81acc87c1c7d16bcdd2035b09d30acc957 \ + --hash=sha256:1c3a3598a832590c5a3ce56ab5576361b5688c12cb1d39429cf5dba30b510760 \ + --hash=sha256:1c57676bdedc94cd3bc37724cf6f8cd2779f02f6aba48de45feca073e714fe52 \ + --hash=sha256:1dc702e42d0684f42d6519c8d581e49c96cefaaab16691f03566d30658ee8788 \ + --hash=sha256:21d1b7305a71a15b4794b5ff22e8eef96ff4a6d7f9657155e5aa419444b28912 \ + --hash=sha256:23f371bd662cf44a7630d4d113101eafc0cfa7518a2760d20760b26021454719 \ + --hash=sha256:2569b67d616eab450d262ca7cb9f9e19d2f718c70a8b88712859359d0ab17035 \ + --hash=sha256:263cd4f47159c09b8b685890af949195b51d1aa82ba451c5847ca9bc6413c220 \ + --hash=sha256:2803ed8b21ca47a43da80a6fd1ed3019d30061f7061daa35ac54f63933409412 \ + --hash=sha256:2a6940a074fb3c48356ed0158a3ca5699c955ee4185b4d7d619be3c327143e05 \ + --hash=sha256:2e27c8841126e017dd2a054a95771569e6070b9ee1b133366d8b31beb5018a41 \ + --hash=sha256:31c9921eb8bd12633b41ad27686bbb0b1a2a9b8452bfdf221e34f311e9942ed4 \ + --hash=sha256:34b6cf500e61c90f305094911f9acc9c86da1a05a7a3f5be9f68817043f486e4 \ + --hash=sha256:3650dc2480f94f7116c364096bc84b1d602f44224ef7d5c7208425915c0475dd \ + --hash=sha256:389871e65468400d6283c0308e791a640b5ab5c83bcee02a2f51295f95e09748 \ + --hash=sha256:39004f0ad156da43e86aa71f44e033de68a44e5a31fc53507b36dd253970054a \ + --hash=sha256:394906945aa8b19fc14a61cf69743a868bb8c465efe85eee687109cc540b98f4 \ + --hash=sha256:3ceb13c5c858d01321b5d9bb65e4cf37a92169ea470b70fec6f236b2c9dd7e34 \ + --hash=sha256:411225bae281f114067578891bc75534cfb3d92a3b4dfef7a6ca78ba354e6069 \ + --hash=sha256:44bb7bef4ea409384e3f8bc36c063d77ea1b8d4a5b2706956c0d6695f07dcc25 \ + --hash=sha256:4503053d296bc6e4cbd1fad61cf3b6e33b939886c4f249ba7c78b602214fabe2 \ + --hash=sha256:4764a6a7588561a9aef92f65bda2c4fb58fe7c675c0883862e6df97559de0bfb \ + --hash=sha256:4966242ec68afc74c122f8459abd597afd7d8a60dc93d695c1334c5fd25f762f \ + --hash=sha256:4a42e651629dafb64fd5b0286a3580613702b5809ad3f24934ea87595804f2c5 \ + --hash=sha256:4a59ba56f340334766f3a4442e0efd0af895fae9e2b204741ef885c446b3a1a8 \ + --hash=sha256:4c41e021bc6d7affb3364dc1e1e5fa9582b470f283748784bd6ea0558f87f42c \ + --hash=sha256:5023346c4ee7992febc0068e7593de5fa2bf611848c08404b35ebbb76b1b0512 \ + --hash=sha256:50f9d8d531dfb767c565f348f33dd5139a6c43f5cbdf3f67da40d54241df93f6 \ + --hash=sha256:51430653db848d258336cfa0244427b17d12db63d42603a55f0d4546f50f25b5 \ + --hash=sha256:531ef597132086b6cf96faa7c6c1dcd0361dd5f1694e5cc30375907b9b7d3ea9 \ + --hash=sha256:53ad387048f6f09a8969631e4de3f1bf70c50e93545d64af4f751b2498755072 \ + --hash=sha256:53b1ea6ca88ebd4420379c330aea57e258408dd0df9af0992e5de2078dc9f5d5 \ + --hash=sha256:575aa4405a656e61a540f4a80eaa5260f2a38fff7bfdc4b5f611840d76e9e277 \ + --hash=sha256:578110dd426f0d209d1509244e6d4a3f1a3e9077655d98c5f22583d63252a08a \ + --hash=sha256:5ec2f42d41ccbd5df0270d7df31618a8ee267bfa50997f5d720ddba86c4a83a6 \ + --hash=sha256:5ee586fb17ff8f90c91cf73c6108a434b02d69925f44f5f8e0d7f2f260607eae \ + --hash=sha256:5f10fd85e4b75967468af655228fbfd212bdf66db1c0d135065ce288982eda26 \ + --hash=sha256:609d3614d78d74ebe35f54953c5bbd2ac647a7ddb9c30a5d877580f5e86b22f2 \ + --hash=sha256:62694e275c93d54f7ccedcfef57d42761b2aad5234b6be1f3e3026cae4001cd4 \ + --hash=sha256:63e92247f383c85ab00dd0091e8c3fa331a96e865459f5ee80353c70a4a42d70 \ + --hash=sha256:682bae25f0a0dd23a056739f23a134db9f52a63e2afd6bfb37ddc76292bbd723 \ + --hash=sha256:6b41389c19b07c760c7e427a3462e8ab83c4bb087d127f0e854c706ce1b9215c \ + --hash=sha256:6e87a6e8735b44816e7db0b2fbc9686932df473c826b0d9743148432e10bb9b9 \ + --hash=sha256:6f0fd84de0c957b2d280143522c4f91a73aada1923caee763e24a2b3fda9f8a5 \ + --hash=sha256:70efd20be968c76ece7baa8dafe04c5be06abc57f754d6f36f3741f7aa7a208e \ + --hash=sha256:71d006bee8397a4a89f469b8deb22469fe7508132d3c17fa6ed871e79832691c \ + --hash=sha256:73309162a6a571d4cbd3b6a1dcc703c7311843ae0d1578df6f09be4e98df38d4 \ + --hash=sha256:75e3026ab649bf48f9a10c0134512638725b521340293f202a69b567518d94e0 \ + --hash=sha256:76855800ac56f878847a09ce6dba727c93ca2d89c9e9d63002d26b916810b0a2 \ + --hash=sha256:7c6b9461a2a8b47c65eef63bb1c76a4f1c119618ffa99ea79bc5bb1e46c5821b \ + --hash=sha256:803a3c3ce4acc62eaf01eaca1208dcf0783025ef27572c3336502b9c232005e7 \ + --hash=sha256:80e6d33a3d42a7549b409f199857b4fb54e2103fc44fb87605b6663b7a7ff750 \ + --hash=sha256:8419ebd326430d1cbb7efb5292330a2cf39114e82df5cc3d83c9a0d5ebeaf2f2 \ + --hash=sha256:85610b4f27f69984932a7abbe52703688de3724d9f72bceb1cca667deff27474 \ + --hash=sha256:85e9beda1f591bc73e77ea1c51965c68e98dafd0fec72cdd745f77d727466716 \ + --hash=sha256:877b0738624280e34c55680d6054a307aa94f7d52fa0e3034a9cc6e790871da7 \ + --hash=sha256:88f9fb0116fbfcefcab70f85cf4b74a2b6ce5d199c41345296f49d974ddb4123 \ + --hash=sha256:8c4fe09e0780c6c3bf2b7d4af02ee2394439d11a523bbcf095cf4747c2932007 \ + --hash=sha256:93a784271881035ab4406a172edb0faecb6e7d00f4b53dc2f55919d6c9688595 \ + --hash=sha256:94f8575fbdf81749008d980c17796097e645574a3b8c28ee313931068dad14fe \ + --hash=sha256:95451e6ce06c3e104556d73b559f5da6c34a069b6b62946d3ad66afcd51642ea \ + --hash=sha256:99c8a9ed30f4164bc4c14b37a90208836cbf50d4ce2a57c71d0f52c7fb4f7598 \ + --hash=sha256:9a18d6f9359e45722c064c97464ec883eb0e0366d33eda61cb19a244bf222679 \ + --hash=sha256:9cbf44c5cb4a7633d078788e1b56387e3d3cf2b8139a3be38040b22d6c3221c8 \ + --hash=sha256:9ee33b875f0b390564c1fb7bc528abf18c8ee6073b201c6ae8524aca778e2d83 \ + --hash=sha256:a0e317df055958a0c1e79e5d2aa5a5eaa4a6d05a20d4b0c9c3f48918139c9fc6 \ + --hash=sha256:a2df6afe50dea8ae15fa34c9f824a3ee958d785fd5d089063d960bae1daa0a3f \ + --hash=sha256:a31de1613658308efdb21ada98cbc86a97c181aa050ba22a808120bb5be3ab94 \ + --hash=sha256:a3d2bff8f37f8d0f96c7ec554d16945050d54462d6e95414babaa18bfafc7f51 \ + --hash=sha256:a41bcf68efd19073376eb8cf948b8d9be0af26256403e512bb18f3966f1f9120 \ + --hash=sha256:a82836cab5f197a0514235aaf7ffccdc886ccdaa2324bc0aafdd4ae898103039 \ + --hash=sha256:a8d00f29b42f534cc8aa3931cfe773b13b23e561e10d2b26f27a8d309b0e82a1 \ + --hash=sha256:aafe5dcfda86c8af00386d7781d4c2181b5011b7be3f2add5e99899ea925df05 \ + --hash=sha256:ab5f043cb8a2d71c981c09c510da013bc79fd661f5c60139f00dd3c3cc4f2ffb \ + --hash=sha256:ac09d42f48f80c9ee1635b2fcaa819496a44502737660d3c0f2ade7526d29144 \ + --hash=sha256:aecfed0b41aa72b7881712c65cf764e39ce2ec352324f5e0837c7048d9e6daaa \ + --hash=sha256:b2c6b50c7b0464165472b56b42d4c76a7b864597007d9c085e8b63e185cf4a7a \ + --hash=sha256:b35d13d549077713e4414f927cdc388d62e543987c572baee613bf82f11a4b99 \ + --hash=sha256:b39cb32a6582750b6cc77bfb3c49c0f8760dc18dc96ec9fb55fbb0f04e08b928 \ + --hash=sha256:b5405bb8f0e783a988172993cfc627e4d9d00432d6bbac65a923041edacf997d \ + --hash=sha256:baaf55442359053c7d62f6f8413a62adba3205119bcb6f49594894d8be47e5e3 \ + --hash=sha256:bd654fad46d8d9e823afbb4f87c79160b5a374ed1ff5bde24e542e6ba8f41434 \ + --hash=sha256:be61f6fff406ca40e3b1d84716fde398fc08bc63dd96d15f3a14230a0973ed86 \ + --hash=sha256:bf49a3ae946a87083ef3a34c8f677ae4243f5b824bfc4c69672e72b3d6719d46 \ + --hash=sha256:c4a80f77dc1acaaa61f0934176fccca7096d9b1ff08c8ba9cddf5ae034a24319 \ + --hash=sha256:c75eb09e8d55bceb4367e83496ff8ef2bc7ea6960efb38e978e8073ea59ecb67 \ + --hash=sha256:c7f8dc16c498ff06497c015642333219871effba93e4a2e8604a06264aca5c5c \ + --hash=sha256:c8aa34a5c864db1087d911a0b902d60d203ea3607d91f615acd3f3108ac32169 \ + --hash=sha256:cbb0fef01f0c6b38cb0f39b1f78fc90b807e0e3c86a7ff3ce74ad77ce5c7880c \ + --hash=sha256:cde9a2ecd91668bcb7f077c4966d8ceddb60af01b52e6e3e2680e4cf00ad1a59 \ + --hash=sha256:cff6d44cb13d39db2663a22b22305d10855efa0fa8015ddeacc40bc59b9d8107 \ + --hash=sha256:d1009abedb49ae95b136a8904a3f71b342f849ffeced2d3747bf29caeda218c4 \ + --hash=sha256:d38c1e8231722c4ce40d7593f28d92b5fc72f3e9774fe73d7e800ec32299f63a \ + --hash=sha256:d53834e23c015ee83a99377db6e5e37d8484f333edb03bd15b4bc312cc7254fb \ + --hash=sha256:d7504f2b476d21653e4d143f44a175f7f751cd41233525312696c76aa3dbb23f \ + --hash=sha256:dbf507e9ef5688bada447a24d68b4b58dd389ba93b7afc065a2ba892bea54769 \ + --hash=sha256:dc52310451fc7c629e13c4e061cbe2dd01684d91f2f8ee2821b083c58bd72432 \ + --hash=sha256:dd00607bffbf30250fe108065f07453ec124dbf223420f57f5e749b04295e090 \ + --hash=sha256:dda608c88cf709b1d406bdfcd84d8d63cff7c9e577a403c6108ce8ce9dcc8764 \ + --hash=sha256:debe9c4f41c32990771be5c22b56f810659f9ddf3d63f67abfdcaa2c6c9c5c1d \ + --hash=sha256:e09fd068c2e169a7070d83d3bde728a4d48de0549f975290be3c108c02e499b4 \ + --hash=sha256:e0fd068364a6759bc794459f0a735ab151d11304346332489c7972bacbe9e72b \ + --hash=sha256:e4c53f8347cd4200f0d70a48ad059cabaf24f5adc6ba08622a23423bc7efa10d \ + --hash=sha256:e5723c01a56c5028c807c701aa66722916d2747ad737a046853f6c46f4875543 \ + --hash=sha256:e7b0460976dc75cb87ad9cc1f9899a4b97751e7d4e77ab840fc9b6d377b8fd24 \ + --hash=sha256:e9d9a4d06d3481eab79803beb4d9bd6f6a8e781ec078ac70d7ef2dcc29d1bea5 \ + --hash=sha256:ead11956716a940c1abc816b7df3fa2b84d06eaed8832ca32f5c5e058c65506b \ + --hash=sha256:ed5f69ce7be7902e5c70ea19eb72d20abf7d725ab5d49777d696e32d4fc1811d \ + --hash=sha256:f2af5c81a1f124609d5f33507082fc3f739959d4719b56877ab1ee7e7b3d602b \ + --hash=sha256:f40e782d49630ad384db66d4d8b73ff4f1b8955dc12e26b09a3e3af064b3b9d6 \ + --hash=sha256:f514f6474e04179d3d33175ed3f3e31434d3130d42ec153540d5b157deefd735 \ + --hash=sha256:f69f57305656a4852f2a7203efc661d8c042e6cc67f7acd97d8667fb448a426e \ + --hash=sha256:fb1e8b8d66c278b21d13b0a7ca22c41dd757a7c209c6b12c313e445c31dd3b28 \ + --hash=sha256:fb4948814a2a98e3912505f09c9e7493b1506226afb1f881825368d6fb776ee3 \ + --hash=sha256:fda207c815b253e34f7e1909840fd14299567b1c0eb4908f8c2ce01a41265401 \ + --hash=sha256:fe8f8f5e70e6dbdfca9882cd9deaac058729bcf323cf7a58660901e55c9c94f6 \ + --hash=sha256:fffc45637bcd6538de8b85f51e3df3223e4ad89bccbfca0481c08c7fc8b7ed7d # via aiohttp zipp==3.23.0 \ --hash=sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e \ diff --git a/sdk/python/requirements/py3.11-requirements.txt b/sdk/python/requirements/py3.11-requirements.txt index 9fc7d9ee07b..ec293cec030 100644 --- a/sdk/python/requirements/py3.11-requirements.txt +++ b/sdk/python/requirements/py3.11-requirements.txt @@ -8,140 +8,156 @@ annotated-types==0.7.0 \ --hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \ --hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89 # via pydantic -anyio==4.12.1 \ - --hash=sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703 \ - --hash=sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c +anyio==4.13.0 \ + --hash=sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708 \ + --hash=sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc # via # starlette # watchfiles -attrs==25.4.0 \ - --hash=sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11 \ - --hash=sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373 +attrs==26.1.0 \ + --hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \ + --hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32 # via # jsonschema # referencing -bigtree==1.3.1 \ - --hash=sha256:a22a0ecd9b0abb283f4a1515370dbf1ec93adee70746767272e2c49d7af9f407 \ - --hash=sha256:c8b766b00188c532d3499bfd9e9666b357428db507fc701f088031a0d5c614d5 +bigtree==1.4.0 \ + --hash=sha256:d0d99550ae64ce4529f132602ab875c2ab472c96c942f5704f8c72a17450d3ea \ + --hash=sha256:e5ae2e948168da671d99601c9ed87ab3b48d9d4ea8a98f111e5748e98064c31c # via feast (pyproject.toml) -certifi==2026.1.4 \ - --hash=sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c \ - --hash=sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120 +certifi==2026.2.25 \ + --hash=sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa \ + --hash=sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7 # via requests -charset-normalizer==3.4.4 \ - --hash=sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad \ - --hash=sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93 \ - --hash=sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394 \ - --hash=sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89 \ - --hash=sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc \ - --hash=sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86 \ - --hash=sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63 \ - --hash=sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d \ - --hash=sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f \ - --hash=sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8 \ - --hash=sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0 \ - --hash=sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505 \ - --hash=sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161 \ - --hash=sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af \ - --hash=sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152 \ - --hash=sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318 \ - --hash=sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72 \ - --hash=sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4 \ - --hash=sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e \ - --hash=sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3 \ - --hash=sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576 \ - --hash=sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c \ - --hash=sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1 \ - --hash=sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8 \ - --hash=sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1 \ - --hash=sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2 \ - --hash=sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44 \ - --hash=sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26 \ - --hash=sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88 \ - --hash=sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016 \ - --hash=sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede \ - --hash=sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf \ - --hash=sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a \ - --hash=sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc \ - --hash=sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0 \ - --hash=sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84 \ - --hash=sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db \ - --hash=sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1 \ - --hash=sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7 \ - --hash=sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed \ - --hash=sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8 \ - --hash=sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133 \ - --hash=sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e \ - --hash=sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef \ - --hash=sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14 \ - --hash=sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2 \ - --hash=sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0 \ - --hash=sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d \ - --hash=sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828 \ - --hash=sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f \ - --hash=sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf \ - --hash=sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6 \ - --hash=sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328 \ - --hash=sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090 \ - --hash=sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa \ - --hash=sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381 \ - --hash=sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c \ - --hash=sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb \ - --hash=sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc \ - --hash=sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a \ - --hash=sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec \ - --hash=sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc \ - --hash=sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac \ - --hash=sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e \ - --hash=sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313 \ - --hash=sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569 \ - --hash=sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3 \ - --hash=sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d \ - --hash=sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525 \ - --hash=sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894 \ - --hash=sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3 \ - --hash=sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9 \ - --hash=sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a \ - --hash=sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9 \ - --hash=sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14 \ - --hash=sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25 \ - --hash=sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50 \ - --hash=sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf \ - --hash=sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1 \ - --hash=sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3 \ - --hash=sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac \ - --hash=sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e \ - --hash=sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815 \ - --hash=sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c \ - --hash=sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6 \ - --hash=sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6 \ - --hash=sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e \ - --hash=sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4 \ - --hash=sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84 \ - --hash=sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69 \ - --hash=sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15 \ - --hash=sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191 \ - --hash=sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0 \ - --hash=sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897 \ - --hash=sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd \ - --hash=sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2 \ - --hash=sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794 \ - --hash=sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d \ - --hash=sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074 \ - --hash=sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3 \ - --hash=sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224 \ - --hash=sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838 \ - --hash=sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a \ - --hash=sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d \ - --hash=sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d \ - --hash=sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f \ - --hash=sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8 \ - --hash=sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490 \ - --hash=sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966 \ - --hash=sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9 \ - --hash=sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3 \ - --hash=sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e \ - --hash=sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608 +charset-normalizer==3.4.7 \ + --hash=sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc \ + --hash=sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c \ + --hash=sha256:07d9e39b01743c3717745f4c530a6349eadbfa043c7577eef86c502c15df2c67 \ + --hash=sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4 \ + --hash=sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0 \ + --hash=sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c \ + --hash=sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5 \ + --hash=sha256:12a6fff75f6bc66711b73a2f0addfc4c8c15a20e805146a02d147a318962c444 \ + --hash=sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153 \ + --hash=sha256:14265bfe1f09498b9d8ec91e9ec9fa52775edf90fcbde092b25f4a33d444fea9 \ + --hash=sha256:16d971e29578a5e97d7117866d15889a4a07befe0e87e703ed63cd90cb348c01 \ + --hash=sha256:177a0ba5f0211d488e295aaf82707237e331c24788d8d76c96c5a41594723217 \ + --hash=sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b \ + --hash=sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c \ + --hash=sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a \ + --hash=sha256:1dc8b0ea451d6e69735094606991f32867807881400f808a106ee1d963c46a83 \ + --hash=sha256:1efde3cae86c8c273f1eb3b287be7d8499420cf2fe7585c41d370d3e790054a5 \ + --hash=sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7 \ + --hash=sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb \ + --hash=sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c \ + --hash=sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1 \ + --hash=sha256:2cd4a60d0e2fb04537162c62bbbb4182f53541fe0ede35cdf270a1c1e723cc42 \ + --hash=sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab \ + --hash=sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df \ + --hash=sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e \ + --hash=sha256:320ade88cfb846b8cd6b4ddf5ee9e80ee0c1f52401f2456b84ae1ae6a1a5f207 \ + --hash=sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18 \ + --hash=sha256:36836d6ff945a00b88ba1e4572d721e60b5b8c98c155d465f56ad19d68f23734 \ + --hash=sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38 \ + --hash=sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110 \ + --hash=sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18 \ + --hash=sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44 \ + --hash=sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d \ + --hash=sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48 \ + --hash=sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e \ + --hash=sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5 \ + --hash=sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d \ + --hash=sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53 \ + --hash=sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790 \ + --hash=sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c \ + --hash=sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b \ + --hash=sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116 \ + --hash=sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d \ + --hash=sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10 \ + --hash=sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6 \ + --hash=sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2 \ + --hash=sha256:6370e8686f662e6a3941ee48ed4742317cafbe5707e36406e9df792cdb535776 \ + --hash=sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a \ + --hash=sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265 \ + --hash=sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008 \ + --hash=sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943 \ + --hash=sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374 \ + --hash=sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246 \ + --hash=sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e \ + --hash=sha256:6e0d51f618228538a3e8f46bd246f87a6cd030565e015803691603f55e12afb5 \ + --hash=sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616 \ + --hash=sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15 \ + --hash=sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41 \ + --hash=sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960 \ + --hash=sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752 \ + --hash=sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e \ + --hash=sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72 \ + --hash=sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7 \ + --hash=sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8 \ + --hash=sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b \ + --hash=sha256:813c0e0132266c08eb87469a642cb30aaff57c5f426255419572aaeceeaa7bf4 \ + --hash=sha256:82b271f5137d07749f7bf32f70b17ab6eaabedd297e75dce75081a24f76eb545 \ + --hash=sha256:84c018e49c3bf790f9c2771c45e9313a08c2c2a6342b162cd650258b57817706 \ + --hash=sha256:8751d2787c9131302398b11e6c8068053dcb55d5a8964e114b6e196cf16cb366 \ + --hash=sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb \ + --hash=sha256:87fad7d9ba98c86bcb41b2dc8dbb326619be2562af1f8ff50776a39e55721c5a \ + --hash=sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e \ + --hash=sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00 \ + --hash=sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f \ + --hash=sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a \ + --hash=sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1 \ + --hash=sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66 \ + --hash=sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356 \ + --hash=sha256:a6c5863edfbe888d9eff9c8b8087354e27618d9da76425c119293f11712a6319 \ + --hash=sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4 \ + --hash=sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad \ + --hash=sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d \ + --hash=sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5 \ + --hash=sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7 \ + --hash=sha256:aef65cd602a6d0e0ff6f9930fcb1c8fec60dd2cfcb6facaf4bdb0e5873042db0 \ + --hash=sha256:af21eb4409a119e365397b2adbaca4c9ccab56543a65d5dbd9f920d6ac29f686 \ + --hash=sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34 \ + --hash=sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49 \ + --hash=sha256:bb8cc7534f51d9a017b93e3e85b260924f909601c3df002bcdb58ddb4dc41a5c \ + --hash=sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1 \ + --hash=sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e \ + --hash=sha256:bd9b23791fe793e4968dba0c447e12f78e425c59fc0e3b97f6450f4781f3ee60 \ + --hash=sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0 \ + --hash=sha256:c0f081d69a6e58272819b70288d3221a6ee64b98df852631c80f293514d3b274 \ + --hash=sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d \ + --hash=sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0 \ + --hash=sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae \ + --hash=sha256:c593052c465475e64bbfe5dbd81680f64a67fdc752c56d7a0ae205dc8aeefe0f \ + --hash=sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d \ + --hash=sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe \ + --hash=sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3 \ + --hash=sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393 \ + --hash=sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1 \ + --hash=sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af \ + --hash=sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44 \ + --hash=sha256:d61f00a0869d77422d9b2aba989e2d24afa6ffd552af442e0e58de4f35ea6d00 \ + --hash=sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c \ + --hash=sha256:dca4bbc466a95ba9c0234ef56d7dd9509f63da22274589ebd4ed7f1f4d4c54e3 \ + --hash=sha256:dd915403e231e6b1809fe9b6d9fc55cf8fb5e02765ac625d9cd623342a7905d7 \ + --hash=sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd \ + --hash=sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e \ + --hash=sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b \ + --hash=sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8 \ + --hash=sha256:e5f4d355f0a2b1a31bc3edec6795b46324349c9cb25eed068049e4f472fb4259 \ + --hash=sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859 \ + --hash=sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46 \ + --hash=sha256:e80c8378d8f3d83cd3164da1ad2df9e37a666cdde7b1cb2298ed0b558064be30 \ + --hash=sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b \ + --hash=sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46 \ + --hash=sha256:ed065083d0898c9d5b4bbec7b026fd755ff7454e6e8b73a67f8c744b13986e24 \ + --hash=sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a \ + --hash=sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24 \ + --hash=sha256:f22dec1690b584cea26fade98b2435c132c1b5f68e39f5a0b7627cd7ae31f1dc \ + --hash=sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215 \ + --hash=sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063 \ + --hash=sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832 \ + --hash=sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6 \ + --hash=sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79 \ + --hash=sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464 # via requests click==8.3.1 \ --hash=sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a \ @@ -158,25 +174,25 @@ colorama==0.4.6 \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 # via feast (pyproject.toml) -dask[dataframe]==2026.1.2 \ - --hash=sha256:1136683de2750d98ea792670f7434e6c1cfce90cab2cc2f2495a9e60fd25a4fc \ - --hash=sha256:46a0cf3b8d87f78a3d2e6b145aea4418a6d6d606fe6a16c79bd8ca2bb862bc91 +dask[dataframe]==2026.3.0 \ + --hash=sha256:be614b9242b0b38288060fb2d7696125946469c98a1c30e174883fd199e0428d \ + --hash=sha256:f7d96c8274e8a900d217c1ff6ea8d1bbf0b4c2c21e74a409644498d925eb8f85 # via feast (pyproject.toml) dill==0.3.9 \ --hash=sha256:468dff3b89520b474c0397703366b7b95eebe6303f108adf9b19da1f702be87a \ --hash=sha256:81aa267dddf68cbfe8029c42ca9ec6a4ab3b22371d1c450abc54422577b4512c # via feast (pyproject.toml) -fastapi==0.129.0 \ - --hash=sha256:61315cebd2e65df5f97ec298c888f9de30430dd0612d59d6480beafbc10655af \ - --hash=sha256:b4946880e48f462692b31c083be0432275cbfb6e2274566b1be91479cc1a84ec +fastapi==0.135.3 \ + --hash=sha256:9b0f590c813acd13d0ab43dd8494138eb58e484bfac405db1f3187cfc5810d98 \ + --hash=sha256:bd6d7caf1a2bdd8d676843cdcd2287729572a1ef524fc4d65c17ae002a1be654 # via feast (pyproject.toml) -fsspec==2026.2.0 \ - --hash=sha256:6544e34b16869f5aacd5b90bdf1a71acb37792ea3ddf6125ee69a22a53fb8bff \ - --hash=sha256:98de475b5cb3bd66bedd5c4679e87b4fdfe1a3bf4d707b151b3c07e58c9a2437 +fsspec==2026.3.0 \ + --hash=sha256:1ee6a0e28677557f8c2f994e3eea77db6392b4de9cd1f5d7a9e87a0ae9d01b41 \ + --hash=sha256:d2ceafaad1b3457968ed14efa28798162f1638dbb5d2a6868a2db002a5ee39a4 # via dask -gunicorn==25.1.0 \ - --hash=sha256:1426611d959fa77e7de89f8c0f32eed6aa03ee735f98c01efba3e281b1c47616 \ - --hash=sha256:d0b1236ccf27f72cfe14bce7caadf467186f19e865094ca84221424e839b8b8b +gunicorn==25.3.0 \ + --hash=sha256:cacea387dab08cd6776501621c295a904fe8e3b7aae9a1a3cbb26f4e7ed54660 \ + --hash=sha256:f74e1b2f9f76f6cd1ca01198968bd2dd65830edc24b6e8e4d78de8320e2fe889 # via # feast (pyproject.toml) # uvicorn-worker @@ -235,9 +251,9 @@ idna==3.11 \ # via # anyio # requests -importlib-metadata==8.7.1 \ - --hash=sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb \ - --hash=sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151 +importlib-metadata==9.0.0 \ + --hash=sha256:2d21d1cc5a017bd0559e36150c21c830ab1dc304dedd1b7ea85d20f45ef3edd7 \ + --hash=sha256:a4f57ab599e6a2e3016d7595cfd72eb4661a5106e787a95bcc90c7105b831efc # via dask jinja2==3.1.6 \ --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ @@ -251,97 +267,97 @@ jsonschema-specifications==2025.9.1 \ --hash=sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe \ --hash=sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d # via jsonschema -librt==0.8.0 \ - --hash=sha256:001e5330093d887b8b9165823eca6c5c4db183fe4edea4fdc0680bbac5f46944 \ - --hash=sha256:015e2dde6e096d27c10238bf9f6492ba6c65822dfb69d2bf74c41a8e88b7ddef \ - --hash=sha256:02a9fe85410cc9bef045e7cb7fd26fdde6669e6d173f99df659aa7f6335961e9 \ - --hash=sha256:0583aef7e9a720dd40f26a2ad5a1bf2ccbb90059dac2b32ac516df232c701db3 \ - --hash=sha256:05a3dd3f116747f7e1a2b475ccdc6fb637fd4987126d109e03013a79d40bf9e6 \ - --hash=sha256:0a33335eb59921e77c9acc05d0e654e4e32e45b014a4d61517897c11591094f8 \ - --hash=sha256:0ce33a9778e294507f3a0e3468eccb6a698b5166df7db85661543eca1cfc5369 \ - --hash=sha256:1566dbb9d1eb0987264c9b9460d212e809ba908d2f4a3999383a84d765f2f3f1 \ - --hash=sha256:17269dd2745dbe8e42475acb28e419ad92dfa38214224b1b01020b8cac70b645 \ - --hash=sha256:178707cda89d910c3b28bf5aa5f69d3d4734e0f6ae102f753ad79edef83a83c7 \ - --hash=sha256:1c25a131013eadd3c600686a0c0333eb2896483cbc7f65baa6a7ee761017aef9 \ - --hash=sha256:1e6811cac1dcb27ca4c74e0ca4a5917a8e06db0d8408d30daee3a41724bfde7a \ - --hash=sha256:1ef3bd856373cf8e7382402731f43bfe978a8613b4039e49e166e1e0dc590216 \ - --hash=sha256:20f73d4fecba969efc15cdefd030e382502d56bb6f1fc66b580cce582836c9fa \ - --hash=sha256:21b14464bee0b604d80a638cf1ee3148d84ca4cc163dcdcecb46060c1b3605e4 \ - --hash=sha256:24a01c13a2a9bdad20997a4443ebe6e329df063d1978bbe2ebbf637878a46d1e \ - --hash=sha256:25b3e667cbfc9000c4740b282df599ebd91dbdcc1aa6785050e4c1d6be5329ab \ - --hash=sha256:25e82d920d4d62ad741592fcf8d0f3bda0e3fc388a184cb7d2f566c681c5f7b9 \ - --hash=sha256:2b37437e7e4ef5e15a297b36ba9e577f73e29564131d86dd75875705e97402b5 \ - --hash=sha256:2ccdd20d9a72c562ffb73098ac411de351b53a6fbb3390903b2d33078ef90447 \ - --hash=sha256:2e0ffe88ebb5962f8fb0ddcbaaff30f1ea06a79501069310e1e030eafb1ad787 \ - --hash=sha256:375eda7acfce1f15f5ed56cfc960669eefa1ec8732e3e9087c3c4c3f2066759c \ - --hash=sha256:3d2720335020219197380ccfa5c895f079ac364b4c429e96952cd6509934d8eb \ - --hash=sha256:3e36a8da17134ffc29373775d88c04832f9ecfab1880470661813e6c7991ef79 \ - --hash=sha256:3e8b77b5f54d0937b26512774916041756c9eb3e66f1031971e626eea49d0bf4 \ - --hash=sha256:41064a0c07b4cc7a81355ccc305cb097d6027002209ffca51306e65ee8293630 \ - --hash=sha256:421765e8c6b18e64d21c8ead315708a56fc24f44075059702e421d164575fdda \ - --hash=sha256:4831c44b8919e75ca0dfb52052897c1ef59fdae19d3589893fbd068f1e41afbf \ - --hash=sha256:48f84830a8f8ad7918afd743fd7c4eb558728bceab7b0e38fd5a5cf78206a556 \ - --hash=sha256:4b705f85311ee76acec5ee70806990a51f0deb519ea0c29c1d1652d79127604d \ - --hash=sha256:4d3e38797eb482485b486898f89415a6ab163bc291476bd95712e42cf4383c05 \ - --hash=sha256:4eb5e06ebcc668677ed6389164f52f13f71737fc8be471101fa8b4ce77baeb0c \ - --hash=sha256:4f6e975377fbc4c9567cb33ea9ab826031b6c7ec0515bfae66a4fb110d40d6da \ - --hash=sha256:4f764b2424cb04524ff7a486b9c391e93f93dc1bd8305b2136d25e582e99aa2f \ - --hash=sha256:507e94f4bec00b2f590fbe55f48cd518a208e2474a3b90a60aa8f29136ddbada \ - --hash=sha256:56901f1eec031396f230db71c59a01d450715cbbef9856bf636726994331195d \ - --hash=sha256:5cb11061a736a9db45e3c1293cfcb1e3caf205912dfa085734ba750f2197ff9a \ - --hash=sha256:5d0f76fc73480d42285c609c0ea74d79856c160fa828ff9aceab574ea4ecfd7b \ - --hash=sha256:667e2513cf69bfd1e1ed9a00d6c736d5108714ec071192afb737987955888a25 \ - --hash=sha256:671a6152edf3b924d98a5ed5e6982ec9cb30894085482acadce0975f031d4c5c \ - --hash=sha256:693697133c3b32aa9b27f040e3691be210e9ac4d905061859a9ed519b1d5a376 \ - --hash=sha256:6a3146c63220d814c4a2c7d6a1eacc8d5c14aed0ff85115c1dfea868080cd18f \ - --hash=sha256:6b6caff69e25d80c269b1952be8493b4d94ef745f438fa619d7931066bdd26de \ - --hash=sha256:6e1af31a710e17891d9adf0dbd9a5fcd94901a3922a96499abdbf7ce658f4e01 \ - --hash=sha256:70defb797c4d5402166787a6b3c66dfb3fa7f93d118c0509ffafa35a392f4258 \ - --hash=sha256:71fc517efc14f75c2f74b1f0a5d5eb4a8e06aa135c34d18eaf3522f4a53cd62d \ - --hash=sha256:75d1a8cab20b2043f03f7aab730551e9e440adc034d776f15f6f8d582b0a5ad4 \ - --hash=sha256:789911e8fa40a2e82f41120c936b1965f3213c67f5a483fc5a41f5839a05dcbb \ - --hash=sha256:7bd68cebf3131bb920d5984f75fe302d758db33264e44b45ad139385662d7bc3 \ - --hash=sha256:7ce0a8cb67e702dcb06342b2aaaa3da9fb0ddc670417879adfa088b44cf7b3b6 \ - --hash=sha256:7f820210e21e3a8bf8fde2ae3c3d10106d4de9ead28cbfdf6d0f0f41f5b12fa1 \ - --hash=sha256:8070aa3368559de81061ef752770d03ca1f5fc9467d4d512d405bd0483bfffe6 \ - --hash=sha256:82e61cd1c563745ad495387c3b65806bfd453badb4adbc019df3389dddee1bf6 \ - --hash=sha256:82fb4602d1b3e303a58bfe6165992b5a78d823ec646445356c332cd5f5bbaa61 \ - --hash=sha256:88c6e75540f1f10f5e0fc5e87b4b6c290f0e90d1db8c6734f670840494764af8 \ - --hash=sha256:8992ca186a1678107b0af3d0c9303d8c7305981b9914989b9788319ed4d89546 \ - --hash=sha256:92249938ab744a5890580d3cb2b22042f0dce71cdaa7c1369823df62bedf7cbc \ - --hash=sha256:95a719a049f0eefaf1952673223cf00d442952273cbd20cf2ed7ec423a0ef58d \ - --hash=sha256:9646178cd794704d722306c2c920c221abbf080fede3ba539d5afdec16c46dad \ - --hash=sha256:9726305d3e53419d27fc8cdfcd3f9571f0ceae22fa6b5ea1b3662c2e538f833e \ - --hash=sha256:995d24caa6bbb34bcdd4a41df98ac6d1af637cfa8975cb0790e47d6623e70e3e \ - --hash=sha256:9ab3a3475a55b89b87ffd7e6665838e8458e0b596c22e0177e0f961434ec474a \ - --hash=sha256:9f09d4884f882baa39a7e36bbf3eae124c4ca2a223efb91e567381d1c55c6b06 \ - --hash=sha256:a512c88900bdb1d448882f5623a0b1ad27ba81a9bd75dacfe17080b72272ca1f \ - --hash=sha256:a905091a13e0884701226860836d0386b88c72ce5c2fdfba6618e14c72be9f25 \ - --hash=sha256:aaadec87f45a3612b6818d1db5fbfe93630669b7ee5d6bdb6427ae08a1aa2141 \ - --hash=sha256:b055bb3abaf69abed25743d8fc1ab691e4f51a912ee0a6f9a6c84f4bbddb283d \ - --hash=sha256:b4bb00bd71b448f16749909b08a0ff16f58b079e2261c2e1000f2bbb2a4f0a45 \ - --hash=sha256:b9aef96d7593584e31ef6ac1eb9775355b0099fee7651fae3a15bc8657b67b52 \ - --hash=sha256:ba581acad5ac8f33e2ff1746e8a57e001b47c6721873121bf8bbcf7ba8bd3aa4 \ - --hash=sha256:ba9d9e60651615bc614be5e21a82cdb7b1769a029369cf4b4d861e4f19686fb6 \ - --hash=sha256:bbebd2bba5c6ae02907df49150e55870fdd7440d727b6192c46b6f754723dde9 \ - --hash=sha256:bd32add59b58fba3439d48d6f36ac695830388e3da3e92e4fc26d2d02670d19c \ - --hash=sha256:bdab762e2c0b48bab76f1a08acb3f4c77afd2123bedac59446aeaaeed3d086cf \ - --hash=sha256:c5512aae4648152abaf4d48b59890503fcbe86e85abc12fb9b096fe948bdd816 \ - --hash=sha256:c6e4c10761ddbc0d67d2f6e2753daf99908db85d8b901729bf2bf5eaa60e0567 \ - --hash=sha256:cb4b3ad543084ed79f186741470b251b9d269cd8b03556f15a8d1a99a64b7de5 \ - --hash=sha256:cb74cdcbc0103fc988e04e5c58b0b31e8e5dd2babb9182b6f9490488eb36324b \ - --hash=sha256:cc3d107f603b5ee7a79b6aa6f166551b99b32fb4a5303c4dfcb4222fc6a0335e \ - --hash=sha256:d920789eca7ef71df7f31fd547ec0d3002e04d77f30ba6881e08a630e7b2c30e \ - --hash=sha256:daae5e955764be8fd70a93e9e5133c75297f8bce1e802e1d3683b98f77e1c5ab \ - --hash=sha256:db63cf3586a24241e89ca1ce0b56baaec9d371a328bd186c529b27c914c9a1ef \ - --hash=sha256:db953b675079884ffda33d1dca7189fb961b6d372153750beb81880384300817 \ - --hash=sha256:de076eaba208d16efb5962f99539867f8e2c73480988cb513fcf1b5dbb0c9dcf \ - --hash=sha256:e79dbc8f57de360f0ed987dc7de7be814b4803ef0e8fc6d3ff86e16798c99935 \ - --hash=sha256:e9a3a38eb4134ad33122a6d575e6324831f930a771d951a15ce232e0237412c2 \ - --hash=sha256:f04ca50e847abc486fa8f4107250566441e693779a5374ba211e96e238f298b9 \ - --hash=sha256:f1178e0de0c271231a660fbef9be6acdfa1d596803464706862bef6644cc1cae \ - --hash=sha256:f4617cef654fca552f00ce5ffdf4f4b68770f18950e4246ce94629b789b92467 \ - --hash=sha256:fa37f99bff354ff191c6bcdffbc9d7cdd4fc37faccfc9be0ef3a4fd5613977da +librt==0.8.1 \ + --hash=sha256:01170b6729a438f0dedc4a26ed342e3dc4f02d1000b4b19f980e1877f0c297e6 \ + --hash=sha256:039b9f2c506bd0ab0f8725aa5ba339c6f0cd19d3b514b50d134789809c24285d \ + --hash=sha256:05bd41cdee35b0c59c259f870f6da532a2c5ca57db95b5f23689fcb5c9e42440 \ + --hash=sha256:086a32dbb71336627e78cc1d6ee305a68d038ef7d4c39aaff41ae8c9aa46e91a \ + --hash=sha256:08eec3a1fc435f0d09c87b6bf1ec798986a3544f446b864e4099633a56fcd9ed \ + --hash=sha256:0bf69d79a23f4f40b8673a947a234baeeb133b5078b483b7297c5916539cf5d5 \ + --hash=sha256:0c3811485fccfda840861905b8c70bba5ec094e02825598bb9d4ca3936857a04 \ + --hash=sha256:0d2f82168e55ddefd27c01c654ce52379c0750ddc31ee86b4b266bcf4d65f2a3 \ + --hash=sha256:0f2ae3725904f7377e11cc37722d5d401e8b3d5851fb9273d7f4fe04f6b3d37d \ + --hash=sha256:10c42e1f6fd06733ef65ae7bebce2872bcafd8d6e6b0a08fe0a05a23b044fb14 \ + --hash=sha256:153188fe98a72f206042be10a2c6026139852805215ed9539186312d50a8e972 \ + --hash=sha256:172d57ec04346b047ca6af181e1ea4858086c80bdf455f61994c4aa6fc3f866c \ + --hash=sha256:190b109bb69592a3401fe1ffdea41a2e73370ace2ffdc4a0e8e2b39cdea81b78 \ + --hash=sha256:1d3a7da44baf692f0c6aeb5b2a09c5e6fc7a703bca9ffa337ddd2e2da53f7732 \ + --hash=sha256:228c2409c079f8c11fb2e5d7b277077f694cb93443eb760e00b3b83cb8b3176c \ + --hash=sha256:22b46eabd76c1986ee7d231b0765ad387d7673bbd996aa0d0d054b38ac65d8f6 \ + --hash=sha256:237796479f4d0637d6b9cbcb926ff424a97735e68ade6facf402df4ec93375ed \ + --hash=sha256:2c74a2da57a094bd48d03fa5d196da83d2815678385d2978657499063709abe1 \ + --hash=sha256:2cc68eeeef5e906839c7bb0815748b5b0a974ec27125beefc0f942715785b551 \ + --hash=sha256:2eb345e8b33fb748227409c9f1233d4df354d6e54091f0e8fc53acdb2ffedeb7 \ + --hash=sha256:31362dbfe297b23590530007062c32c6f6176f6099646bb2c95ab1b00a57c382 \ + --hash=sha256:3dff3d3ca8db20e783b1bc7de49c0a2ab0b8387f31236d6a026597d07fcd68ac \ + --hash=sha256:43353b943613c5d9c49a25aaffdba46f888ec354e71e3529a00cca3f04d66a7a \ + --hash=sha256:439352ba9373f11cb8e1933da194dcc6206daf779ff8df0ed69c5e39113e6a99 \ + --hash=sha256:4998009e7cb9e896569f4be7004f09d0ed70d386fa99d42b6d363f6d200501ac \ + --hash=sha256:4be2a5c926b9770c9e08e717f05737a269b9d0ebc5d2f0060f0fe3fe9ce47acb \ + --hash=sha256:4beb04b8c66c6ae62f8c1e0b2f097c1ebad9295c929a8d5286c05eae7c2fc7dc \ + --hash=sha256:4c8dfa264b9193c4ee19113c985c95f876fae5e51f731494fc4e0cf594990ba7 \ + --hash=sha256:5212a5bd7fae98dae95710032902edcd2ec4dc994e883294f75c857b83f9aba0 \ + --hash=sha256:52c224e14614b750c0a6d97368e16804a98c684657c7518752c356834fff83bb \ + --hash=sha256:56e04c14b696300d47b3bc5f1d10a00e86ae978886d0cee14e5714fafb5df5d2 \ + --hash=sha256:5bb54f1205a3a6ab41a6fd71dfcdcbd278670d3a90ca502a30d9da583105b6f7 \ + --hash=sha256:5cdc0f588ff4b663ea96c26d2a230c525c6fc62b28314edaaaca8ed5af931ad0 \ + --hash=sha256:5db05697c82b3a2ec53f6e72b2ed373132b0c2e05135f0696784e97d7f5d48e7 \ + --hash=sha256:5e4af413908f77294605e28cfd98063f54b2c790561383971d2f52d113d9c363 \ + --hash=sha256:5fc48998000cbc39ec0d5311312dda93ecf92b39aaf184c5e817d5d440b29624 \ + --hash=sha256:60a78b694c9aee2a0f1aaeaa7d101cf713e92e8423a941d2897f4fa37908dab9 \ + --hash=sha256:64548cde61b692dc0dc379f4b5f59a2f582c2ebe7890d09c1ae3b9e66fa015b7 \ + --hash=sha256:681dc2451d6d846794a828c16c22dc452d924e9f700a485b7ecb887a30aad1fd \ + --hash=sha256:6b1977c4ea97ce5eb7755a78fae68d87e4102e4aaf54985e8b56806849cc06a3 \ + --hash=sha256:6cfa7fe54fd4d1f47130017351a959fe5804bda7a0bc7e07a2cdbc3fdd28d34f \ + --hash=sha256:738f08021b3142c2918c03692608baed43bc51144c29e35807682f8070ee2a3a \ + --hash=sha256:747328be0c5b7075cde86a0e09d7a9196029800ba75a1689332348e998fb85c0 \ + --hash=sha256:758509ea3f1eba2a57558e7e98f4659d0ea7670bff49673b0dde18a3c7e6c0eb \ + --hash=sha256:785ae29c1f5c6e7c2cde2c7c0e148147f4503da3abc5d44d482068da5322fd9e \ + --hash=sha256:7aae78ab5e3206181780e56912d1b9bb9f90a7249ce12f0e8bf531d0462dd0fc \ + --hash=sha256:7b02679a0d783bdae30d443025b94465d8c3dc512f32f5b5031f93f57ac32071 \ + --hash=sha256:7e2f3edca35664499fbb36e4770650c4bd4a08abc1f4458eab9df4ec56389730 \ + --hash=sha256:7e6bad1cd94f6764e1e21950542f818a09316645337fd5ab9a7acc45d99a8f35 \ + --hash=sha256:81fd938344fecb9373ba1b155968c8a329491d2ce38e7ddb76f30ffb938f12dc \ + --hash=sha256:82210adabbc331dbb65d7868b105185464ef13f56f7f76688565ad79f648b0fe \ + --hash=sha256:89815a22daf9c51884fb5dbe4f1ef65ee6a146e0b6a8df05f753e2e4a9359bf4 \ + --hash=sha256:8f1125e6bbf2f1657d9a2f3ccc4a2c9b0c8b176965bb565dd4d86be67eddb4b6 \ + --hash=sha256:8f4bb453f408137d7581be309b2fbc6868a80e7ef60c88e689078ee3a296ae71 \ + --hash=sha256:924817ab3141aca17893386ee13261f1d100d1ef410d70afe4389f2359fea4f0 \ + --hash=sha256:93c2af9e01e0ef80d95ae3c720be101227edae5f2fe7e3dc63d8857fadfc5a1d \ + --hash=sha256:97c2b54ff6717a7a563b72627990bec60d8029df17df423f0ed37d56a17a176b \ + --hash=sha256:9be2f15e53ce4e83cc08adc29b26fb5978db62ef2a366fbdf716c8a6c8901040 \ + --hash=sha256:9e2c6f77b9ad48ce5603b83b7da9ee3e36b3ab425353f695cba13200c5d96596 \ + --hash=sha256:a28f2612ab566b17f3698b0da021ff9960610301607c9a5e8eaca62f5e1c350a \ + --hash=sha256:a355d99c4c0d8e5b770313b8b247411ed40949ca44e33e46a4789b9293a907ee \ + --hash=sha256:a3b4350b13cc0e6f5bec8fa7caf29a8fb8cdc051a3bae45cfbfd7ce64f009965 \ + --hash=sha256:aaab0e307e344cb28d800957ef3ec16605146ef0e59e059a60a176d19543d1b7 \ + --hash=sha256:ac1e7817fd0ed3d14fd7c5df91daed84c48e4c2a11ee99c0547f9f62fdae13da \ + --hash=sha256:adfab487facf03f0d0857b8710cf82d0704a309d8ffc33b03d9302b4c64e91a9 \ + --hash=sha256:b6d7ab1f01aa753188605b09a51faa44a3327400b00b8cce424c71910fc0a128 \ + --hash=sha256:bacdb58d9939d95cc557b4dbaa86527c9db2ac1ed76a18bc8d26f6dc8647d851 \ + --hash=sha256:be46a14693955b3bd96014ccbdb8339ee8c9346fbe11c1b78901b55125f14c73 \ + --hash=sha256:bf512a71a23504ed08103a13c941f763db13fb11177beb3d9244c98c29fb4a61 \ + --hash=sha256:c00e5c884f528c9932d278d5c9cbbea38a6b81eb62c02e06ae53751a83a4d52b \ + --hash=sha256:c25d9e338d5bed46c1632f851babf3d13c78f49a225462017cf5e11e845c5891 \ + --hash=sha256:c336d61d2fe74a3195edc1646d53ff1cddd3a9600b09fa6ab75e5514ba4862a7 \ + --hash=sha256:cc3656283d11540ab0ea01978378e73e10002145117055e03722417aeab30994 \ + --hash=sha256:cf450f498c30af55551ba4f66b9123b7185362ec8b625a773b3d39aa1a717583 \ + --hash=sha256:d0ee06b5b5291f609ddb37b9750985b27bc567791bc87c76a569b3feed8481ac \ + --hash=sha256:d480de377f5b687b6b1bc0c0407426da556e2a757633cc7e4d2e1a057aa688f3 \ + --hash=sha256:d56bc4011975f7460bea7b33e1ff425d2f1adf419935ff6707273c77f8a4ada6 \ + --hash=sha256:dd3c41254ee98604b08bd5b3af5bf0a89740d4ee0711de95b65166bf44091921 \ + --hash=sha256:e0d138c7ae532908cbb342162b2611dbd4d90c941cd25ab82084aaf71d2c0bd0 \ + --hash=sha256:e11769a1dbda4da7b00a76cfffa67aa47cfa66921d2724539eee4b9ede780b79 \ + --hash=sha256:e3f0a41487fd5fad7e760b9e8a90e251e27c2816fbc2cff36a22a0e6bcbbd9dd \ + --hash=sha256:e692aa2d1d604e6ca12d35e51fdc36f4cda6345e28e36374579f7ef3611b3012 \ + --hash=sha256:e70a57ecf89a0f64c24e37f38d3fe217a58169d2fe6ed6d70554964042474023 \ + --hash=sha256:e96baa6820280077a78244b2e06e416480ed859bbd8e5d641cf5742919d8beb4 \ + --hash=sha256:eb5656019db7c4deacf0c1a55a898c5bb8f989be904597fcb5232a2f4828fa05 \ + --hash=sha256:eca45e982fa074090057132e30585a7e8674e9e885d402eae85633e9f449ce6c \ + --hash=sha256:f0af2bd2bc204fa27f3d6711d0f360e6b8c684a035206257a81673ab924aa11e \ + --hash=sha256:f7cdf7f26c2286ffb02e46d7bac56c94655540b26347673bea15fa52a6af17e9 \ + --hash=sha256:fd1a720332ea335ceb544cf0a03f81df92abd4bb887679fd1e460976b0e6214b \ + --hash=sha256:ff8baf1f8d3f4b6b7257fcb75a501f2a5499d0dda57645baa09d4d0d34b19444 # via mypy locket==1.0.0 \ --hash=sha256:5c0d4c052a8bbbf750e056a8e65ccd309086f4f0f18a2eac306a8dfa4112a632 \ @@ -438,246 +454,238 @@ markupsafe==3.0.3 \ --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \ --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50 # via jinja2 -mmh3==5.2.0 \ - --hash=sha256:03e08c6ebaf666ec1e3d6ea657a2d363bb01effd1a9acfe41f9197decaef0051 \ - --hash=sha256:097e13c8b8a66c5753c6968b7640faefe85d8e38992703c1f666eda6ef4c3762 \ - --hash=sha256:0b898cecff57442724a0f52bf42c2de42de63083a91008fb452887e372f9c328 \ - --hash=sha256:10983c10f5c77683bd845751905ba535ec47409874acc759d5ce3ff7ef34398a \ - --hash=sha256:11730eeb16dfcf9674fdea9bb6b8e6dd9b40813b7eb839bc35113649eef38aeb \ - --hash=sha256:127c95336f2a98c51e7682341ab7cb0be3adb9df0819ab8505a726ed1801876d \ - --hash=sha256:12da42c0a55c9d86ab566395324213c319c73ecb0c239fad4726324212b9441c \ - --hash=sha256:132dd943451a7c7546978863d2f5a64977928410782e1a87d583cb60eb89e667 \ - --hash=sha256:1556e31e4bd0ac0c17eaf220be17a09c171d7396919c3794274cb3415a9d3646 \ - --hash=sha256:1a5f4d2e59d6bba8ef01b013c472741835ad961e7c28f50c82b27c57748744a4 \ - --hash=sha256:1ba55d6ca32eeef8b2625e1e4bfc3b3db52bc63014bd7e5df8cc11bf2b036b12 \ - --hash=sha256:1efc8fec8478e9243a78bb993422cf79f8ff85cb4cf6b79647480a31e0d950a8 \ - --hash=sha256:1f8d8b627799f4e2fcc7c034fed8f5f24dc7724ff52f69838a3d6d15f1ad4765 \ - --hash=sha256:1fae471339ae1b9c641f19cf46dfe6ffd7f64b1fba7c4333b99fa3dd7f21ae0a \ - --hash=sha256:1fdb36b940e9261aff0b5177c5b74a36936b902f473180f6c15bde26143681a9 \ - --hash=sha256:2421b9d665a0b1ad724ec7332fb5a98d075f50bc51a6ff854f3a1882bd650d49 \ - --hash=sha256:29c2b9ce61886809d0492a274a5a53047742dea0f703f9c4d5d223c3ea6377d3 \ - --hash=sha256:2c9da0d568569cc87315cb063486d761e38458b8ad513fedd3dc9263e1b81bcd \ - --hash=sha256:2ebfc46b39168ab1cd44670a32ea5489bcbc74a25795c61b6d888c5c2cf654ed \ - --hash=sha256:3193752fc05ea72366c2b63ff24b9a190f422e32d75fdeae71087c08fff26115 \ - --hash=sha256:33576136c06b46a7046b6d83a3d75fbca7d25f84cec743f1ae156362608dc6d2 \ - --hash=sha256:37a358cc881fe796e099c1db6ce07ff757f088827b4e8467ac52b7a7ffdca647 \ - --hash=sha256:382a6bb3f8c6532ea084e7acc5be6ae0c6effa529240836d59352398f002e3fc \ - --hash=sha256:384eda9361a7bf83a85e09447e1feafe081034af9dd428893701b959230d84be \ - --hash=sha256:38d899a156549da8ef6a9f1d6f7ef231228d29f8f69bce2ee12f5fba6d6fd7c5 \ - --hash=sha256:3bc244802ccab5220008cb712ca1508cb6a12f0eb64ad62997156410579a1770 \ - --hash=sha256:3c6041fd9d5fb5fcac57d5c80f521a36b74aea06b8566431c63e4ffc49aced51 \ - --hash=sha256:3ca975c51c5028947bbcfc24966517aac06a01d6c921e30f7c5383c195f87991 \ - --hash=sha256:3d6bfd9662a20c054bc216f861fa330c2dac7c81e7fb8307b5e32ab5b9b4d2e0 \ - --hash=sha256:419005f84ba1cab47a77465a2a843562dadadd6671b8758bf179d82a15ca63eb \ - --hash=sha256:45b590e31bc552c6f8e2150ff1ad0c28dd151e9f87589e7eaf508fbdd8e8e908 \ - --hash=sha256:49037d417419863b222ae47ee562b2de9c3416add0a45c8d7f4e864be8dc4f89 \ - --hash=sha256:4a5f5536b1cbfa72318ab3bfc8a8188b949260baed186b75f0abc75b95d8c051 \ - --hash=sha256:582f9dbeefe15c32a5fa528b79b088b599a1dfe290a4436351c6090f90ddebb8 \ - --hash=sha256:58477cf9ef16664d1ce2b038f87d2dc96d70fe50733a34a7f07da6c9a5e3538c \ - --hash=sha256:58981d6ea9646dbbf9e59a30890cbf9f610df0e4a57dbfe09215116fd90b0093 \ - --hash=sha256:5a5dba98e514fb26241868f6eb90a7f7ca0e039aed779342965ce24ea32ba513 \ - --hash=sha256:5b0b58215befe0f0e120b828f7645e97719bbba9f23b69e268ed0ac7adde8645 \ - --hash=sha256:61ac226af521a572700f863d6ecddc6ece97220ce7174e311948ff8c8919a363 \ - --hash=sha256:63830f846797187c5d3e2dae50f0848fdc86032f5bfdc58ae352f02f857e9025 \ - --hash=sha256:69fc339d7202bea69ef9bd7c39bfdf9fdabc8e6822a01eba62fb43233c1b3932 \ - --hash=sha256:6d541038b3fc360ec538fc116de87462627944765a6750308118f8b509a8eec7 \ - --hash=sha256:6ecb4e750d712abde046858ee6992b65c93f1f71b397fce7975c3860c07365d2 \ - --hash=sha256:72d80005b7634a3a2220f81fbeb94775ebd12794623bb2e1451701ea732b4aa3 \ - --hash=sha256:7303aab41e97adcf010a09efd8f1403e719e59b7705d5e3cfed3dd7571589290 \ - --hash=sha256:7434a27754049144539d2099a6d2da5d88b8bdeedf935180bf42ad59b3607aa3 \ - --hash=sha256:746a5ee71c6d1103d9b560fa147881b5e68fd35da56e54e03d5acefad0e7c055 \ - --hash=sha256:7733ec52296fc1ba22e9b90a245c821adbb943e98c91d8a330a2254612726106 \ - --hash=sha256:7901c893e704ee3c65f92d39b951f8f34ccf8e8566768c58103fb10e55afb8c1 \ - --hash=sha256:7aa18cdb58983ee660c9c400b46272e14fa253c675ed963d3812487f8ca42037 \ - --hash=sha256:7b986d506a8e8ea345791897ba5d8ba0d9d8820cd4fc3e52dbe6de19388de2e7 \ - --hash=sha256:7bbb0df897944b5ec830f3ad883e32c5a7375370a521565f5fe24443bfb2c4f7 \ - --hash=sha256:7c7f0b342fd06044bedd0b6e72177ddc0076f54fd89ee239447f8b271d919d9b \ - --hash=sha256:7e5634565367b6d98dc4aa2983703526ef556b3688ba3065edb4b9b90ede1c54 \ - --hash=sha256:7fddccd4113e7b736706e17a239a696332360cbaddf25ae75b57ba1acce65081 \ - --hash=sha256:81c504ad11c588c8629536b032940f2a359dda3b6cbfd4ad8f74cb24dcd1b0bc \ - --hash=sha256:81df0dae22cd0da87f1c978602750f33d17fb3d21fb0f326c89dc89834fea79b \ - --hash=sha256:86d1be5d63232e6eb93c50881aea55ff06eb86d8e08f9b5417c8c9b10db9db96 \ - --hash=sha256:8b0c53fe0994beade1ad7c0f13bd6fec980a0664bfbe5a6a7d64500b9ab76772 \ - --hash=sha256:8ebf241072cf2777a492d0e09252f8cc2b3edd07dfdb9404b9757bffeb4f2cee \ - --hash=sha256:931d47e08c9c8a67bf75d82f0ada8399eac18b03388818b62bfa42882d571d72 \ - --hash=sha256:932a6eec1d2e2c3c9e630d10f7128d80e70e2d47fe6b8c7ea5e1afbd98733e65 \ - --hash=sha256:941603bfd75a46023807511c1ac2f1b0f39cccc393c15039969806063b27e6db \ - --hash=sha256:956127e663d05edbeec54df38885d943dfa27406594c411139690485128525de \ - --hash=sha256:96f1e1ac44cbb42bcc406e509f70c9af42c594e72ccc7b1257f97554204445f0 \ - --hash=sha256:99bb6a4d809aa4e528ddfe2c85dd5239b78b9dd14be62cca0329db78505e7b50 \ - --hash=sha256:9f64bf06f4bf623325fda3a6d02d36cd69199b9ace99b04bb2d7fd9f89688504 \ - --hash=sha256:a094319ec0db52a04af9fdc391b4d39a1bc72bc8424b47c4411afb05413a44b5 \ - --hash=sha256:a367d4741ac0103f8198c82f429bccb9359f543ca542b06a51f4f0332e8de279 \ - --hash=sha256:a7c0c7845566b9686480e6a7e9044db4afb60038d5fabd19227443f0104eeee4 \ - --hash=sha256:aa6e5d31fdc5ed9e3e95f9873508615a778fe9b523d52c17fc770a3eb39ab6e4 \ - --hash=sha256:ae9d032488fcec32d22be6542d1a836f00247f40f320844dbb361393b5b22773 \ - --hash=sha256:b0271ac12415afd3171ab9a3c7cbfc71dee2c68760a7dc9d05bf8ed6ddfa3a7a \ - --hash=sha256:b0d753ad566c721faa33db7e2e0eddd74b224cdd3eaf8481d76c926603c7a00e \ - --hash=sha256:b29044e1ffdb84fe164d0a7ea05c7316afea93c00f8ed9449cf357c36fc4f814 \ - --hash=sha256:b5995088dd7023d2d9f310a0c67de5a2b2e06a570ecfd00f9ff4ab94a67cde43 \ - --hash=sha256:b5f317a727bba0e633a12e71228bc6a4acb4f471a98b1c003163b917311ea9a9 \ - --hash=sha256:b9a87025121d1c448f24f27ff53a5fe7b6ef980574b4a4f11acaabe702420d63 \ - --hash=sha256:bb0fdc451fb6d86d81ab8f23d881b8d6e37fc373a2deae1c02d27002d2ad7a05 \ - --hash=sha256:bb4fe46bdc6104fbc28db7a6bacb115ee6368ff993366bbd8a2a7f0076e6f0c0 \ - --hash=sha256:bc44fc2b886243d7c0d8daeb37864e16f232e5b56aaec27cc781d848264cfd28 \ - --hash=sha256:bdde97310d59604f2a9119322f61b31546748499a21b44f6715e8ced9308a6c5 \ - --hash=sha256:be1374df449465c9f2500e62eee73a39db62152a8bdfbe12ec5b5c1cd451344d \ - --hash=sha256:be7d3dca9358e01dab1bad881fb2b4e8730cec58d36dd44482bc068bfcd3bc65 \ - --hash=sha256:bf7bee43e17e81671c447e9c83499f53d99bf440bc6d9dc26a841e21acfbe094 \ - --hash=sha256:c3dca4cb5b946ee91b3d6bb700d137b1cd85c20827f89fdf9c16258253489044 \ - --hash=sha256:c3f563e8901960e2eaa64c8e8821895818acabeb41c96f2efbb936f65dbe486c \ - --hash=sha256:c463d7c1c4cfc9d751efeaadd936bbba07b5b0ed81a012b3a9f5a12f0872bd6e \ - --hash=sha256:c4a2f3d83879e3de2eb8cbf562e71563a8ed15ee9b9c2e77ca5d9f73072ac15c \ - --hash=sha256:c5584061fd3da584659b13587f26c6cad25a096246a481636d64375d0c1f6c07 \ - --hash=sha256:c677d78887244bf3095020b73c42b505b700f801c690f8eaa90ad12d3179612f \ - --hash=sha256:c903e71fd8debb35ad2a4184c1316b3cb22f64ce517b4e6747f25b0a34e41266 \ - --hash=sha256:c9ff37ba9f15637e424c2ab57a1a590c52897c845b768e4e0a4958084ec87f22 \ - --hash=sha256:cadc16e8ea64b5d9a47363013e2bea469e121e6e7cb416a7593aeb24f2ad122e \ - --hash=sha256:cedac4f4054b8f7859e5aed41aaa31ad03fce6851901a7fdc2af0275ac533c10 \ - --hash=sha256:d22c9dcafed659fadc605538946c041722b6d1104fe619dbf5cc73b3c8a0ded8 \ - --hash=sha256:d765058da196f68dc721116cab335e696e87e76720e6ef8ee5a24801af65e63d \ - --hash=sha256:d86651fa45799530885ba4dab3d21144486ed15285e8784181a0ab37a4552384 \ - --hash=sha256:dd966df3489ec13848d6c6303429bbace94a153f43d1ae2a55115fd36fd5ca5d \ - --hash=sha256:ddc63328889bcaee77b743309e5c7d2d52cee0d7d577837c91b6e7cc9e755e0b \ - --hash=sha256:dfbead5575f6470c17e955b94f92d62a03dfc3d07f2e6f817d9b93dc211a1515 \ - --hash=sha256:e0f3ed828d709f5b82d8bfe14f8856120718ec4bd44a5b26102c3030a1e12501 \ - --hash=sha256:e1861fb6b1d0453ed7293200139c0a9011eeb1376632e048e3766945b13313c5 \ - --hash=sha256:e5015f0bb6eb50008bed2d4b1ce0f2a294698a926111e4bb202c0987b4f89078 \ - --hash=sha256:e651e17bfde5840e9e4174b01e9e080ce49277b70d424308b36a7969d0d1af73 \ - --hash=sha256:e7884931fe5e788163e7b3c511614130c2c59feffdc21112290a194487efb2e9 \ - --hash=sha256:e79c00eba78f7258e5b354eccd4d7907d60317ced924ea4a5f2e9d83f5453065 \ - --hash=sha256:e912b19cf2378f2967d0c08e86ff4c6c360129887f678e27e4dde970d21b3f4d \ - --hash=sha256:e9a011469b47b752e7d20de296bb34591cdfcbe76c99c2e863ceaa2aa61113d2 \ - --hash=sha256:eb756caf8975882630ce4e9fbbeb9d3401242a72528230422c9ab3a0d278e60c \ - --hash=sha256:eba01ec3bd4a49b9ac5ca2bc6a73ff5f3af53374b8556fcc2966dd2af9eb7779 \ - --hash=sha256:ecbfc0437ddfdced5e7822d1ce4855c9c64f46819d0fdc4482c53f56c707b935 \ - --hash=sha256:eed4bba7ff8a0d37106ba931ab03bdd3915fbb025bcf4e1f0aa02bc8114960c5 \ - --hash=sha256:f35727c5118aba95f0397e18a1a5b8405425581bfe53e821f0fb444cbdc2bc9b \ - --hash=sha256:f698733a8a494466432d611a8f0d1e026f5286dee051beea4b3c3146817e35d5 \ - --hash=sha256:f7f9034c7cf05ddfaac8d7a2e63a3c97a840d4615d0a0e65ba8bdf6f8576e3be \ - --hash=sha256:fa0c966ee727aad5406d516375593c5f058c766b21236ab8985693934bb5085b \ - --hash=sha256:fc9c5f280438cf1c1a8f9abb87dc8ce9630a964120cfb5dd50d1e7ce79690c7a \ - --hash=sha256:fd6e6c3d90660d085f7e73710eab6f5545d4854b81b0135a3526e797009dbda3 \ - --hash=sha256:fdfd3fb739f4e22746e13ad7ba0c6eedf5f454b18d11249724a388868e308ee4 \ - --hash=sha256:ff3d50dc3fe8a98059f99b445dfb62792b5d006c5e0b8f03c6de2813b8376110 +mmh3==5.2.1 \ + --hash=sha256:022aa1a528604e6c83d0a7705fdef0b5355d897a9e0fa3a8d26709ceaa06965d \ + --hash=sha256:0634581290e6714c068f4aa24020acf7880927d1f0084fa753d9799ae9610082 \ + --hash=sha256:08043f7cb1fb9467c3fbbbaea7896986e7fbc81f4d3fd9289a73d9110ab6207a \ + --hash=sha256:0a3984146e414684a6be2862d84fcb1035f4984851cb81b26d933bab6119bf00 \ + --hash=sha256:0bbc17250b10d3466875a40a52520a6bac3c02334ca709207648abd3c223ed5c \ + --hash=sha256:0cc21533878e5586b80d74c281d7f8da7932bc8ace50b8d5f6dbf7e3935f63f1 \ + --hash=sha256:0d0b7e803191db5f714d264044e06189c8ccd3219e936cc184f07106bd17fd7b \ + --hash=sha256:113f78e7463a36dbbcea05bfe688efd7fa759d0f0c56e73c974d60dcfec3dfcc \ + --hash=sha256:169e0d178cb59314456ab30772429a802b25d13227088085b0d49b9fe1533104 \ + --hash=sha256:17fbb47f0885ace8327ce1235d0416dc86a211dcd8cc1e703f41523be32cfec8 \ + --hash=sha256:19bbd3b841174ae6ed588536ab5e1b1fe83d046e668602c20266547298d939a9 \ + --hash=sha256:1d9f9a3ce559a5267014b04b82956993270f63ec91765e13e9fd73daf2d2738e \ + --hash=sha256:1e4ecee40ba19e6975e1120829796770325841c2f153c0e9aecca927194c6a2a \ + --hash=sha256:22b0f9971ec4e07e8223f2beebe96a6cfc779d940b6f27d26604040dd74d3a44 \ + --hash=sha256:26fb5b9c3946bf7f1daed7b37e0c03898a6f062149127570f8ede346390a0825 \ + --hash=sha256:2778fed822d7db23ac5008b181441af0c869455b2e7d001f4019636ac31b6fe4 \ + --hash=sha256:28cfab66577000b9505a0d068c731aee7ca85cd26d4d63881fab17857e0fe1fb \ + --hash=sha256:29bc3973676ae334412efdd367fcd11d036b7be3efc1ce2407ef8676dabfeb82 \ + --hash=sha256:2bd9f19f7f1fcebd74e830f4af0f28adad4975d40d80620be19ffb2b2af56c9f \ + --hash=sha256:2d5d542bf2abd0fd0361e8017d03f7cb5786214ceb4a40eef1539d6585d93386 \ + --hash=sha256:30e4d2084df019880d55f6f7bea35328d9b464ebee090baa372c096dc77556fb \ + --hash=sha256:3619473a0e0d329fd4aec8075628f8f616be2da41605300696206d6f36920c3d \ + --hash=sha256:368625fb01666655985391dbad3860dc0ba7c0d6b9125819f3121ee7292b4ac8 \ + --hash=sha256:3737303ca9ea0f7cb83028781148fcda4f1dac7821db0c47672971dabcf63593 \ + --hash=sha256:3a9fed49c6ce4ed7e73f13182760c65c816da006debe67f37635580dfb0fae00 \ + --hash=sha256:3c38d142c706201db5b2345166eeef1e7740e3e2422b470b8ba5c8727a9b4c7a \ + --hash=sha256:3cb61db880ec11e984348227b333259994c2c85caa775eb7875decb3768db890 \ + --hash=sha256:3d74a03fb57757ece25aa4b3c1c60157a1cece37a020542785f942e2f827eed5 \ + --hash=sha256:3f796b535008708846044c43302719c6956f39ca2d93f2edda5319e79a29efbb \ + --hash=sha256:41105377f6282e8297f182e393a79cfffd521dde37ace52b106373bdcd9ca5cb \ + --hash=sha256:41aac7002a749f08727cb91babff1daf8deac317c0b1f317adc69be0e6c375d1 \ + --hash=sha256:44983e45310ee5b9f73397350251cdf6e63a466406a105f1d16cb5baa659270b \ + --hash=sha256:4cbbde66f1183db040daede83dd86c06d663c5bb2af6de1142b7c8c37923dd74 \ + --hash=sha256:4eda76074cfca2787c8cf1bec603eaebdddd8b061ad5502f85cddae998d54f00 \ + --hash=sha256:4fc6cd65dc4d2fdb2625e288939a3566e36127a84811a4913f02f3d5931da52d \ + --hash=sha256:50885073e2909251d4718634a191c49ae5f527e5e1736d738e365c3e8be8f22b \ + --hash=sha256:5174a697ce042fa77c407e05efe41e03aa56dae9ec67388055820fb48cf4c3ba \ + --hash=sha256:54b64fb2433bc71488e7a449603bf8bd31fbcf9cb56fbe1eb6d459e90b86c37b \ + --hash=sha256:54fe8518abe06a4c3852754bfd498b30cc58e667f376c513eac89a244ce781a4 \ + --hash=sha256:55dbbd8ffbc40d1697d5e2d0375b08599dae8746b0b08dea05eee4ce81648fac \ + --hash=sha256:57b52603e89355ff318025dd55158f6e71396c0f1f609d548e9ea9c94cc6ce0a \ + --hash=sha256:58370d05d033ee97224c81263af123dea3d931025030fd34b61227a768a8858a \ + --hash=sha256:5d87a3584093e1a89987e3d36d82c98d9621b2cb944e22a420aa1401e096758f \ + --hash=sha256:623f938f6a039536cc02b7582a07a080f13fdfd48f87e63201d92d7e34d09a18 \ + --hash=sha256:62815d2c67f2dd1be76a253d88af4e1da19aeaa1820146dec52cf8bee2958b16 \ + --hash=sha256:6290289fa5fb4c70fd7f72016e03633d60388185483ff3b162912c81205ae2cf \ + --hash=sha256:67e41a497bac88cc1de96eeba56eeb933c39d54bc227352f8455aa87c4ca4000 \ + --hash=sha256:6c85c38a279ca9295a69b9b088a2e48aa49737bb1b34e6a9dc6297c110e8d912 \ + --hash=sha256:6f01f044112d43a20be2f13a11683666d87151542ad627fe41a18b9791d2802f \ + --hash=sha256:707151644085dd0f20fe4f4b573d28e5130c4aaa5f587e95b60989c5926653b5 \ + --hash=sha256:723b2681ed4cc07d3401bbea9c201ad4f2a4ca6ba8cddaff6789f715dd2b391e \ + --hash=sha256:72d1cc63bcc91e14933f77d51b3df899d6a07d184ec515ea7f56bff659e124d7 \ + --hash=sha256:7374d6e3ef72afe49697ecd683f3da12f4fc06af2d75433d0580c6746d2fa025 \ + --hash=sha256:7501e9be34cb21e72fcfe672aafd0eee65c16ba2afa9dcb5500a587d3a0580f0 \ + --hash=sha256:76219cd1eefb9bf4af7856e3ae563d15158efa145c0aab01e9933051a1954045 \ + --hash=sha256:7aec798c2b01aaa65a55f1124f3405804184373abb318a3091325aece235f67c \ + --hash=sha256:7be6dfb49e48fd0a7d91ff758a2b51336f1cd21f9d44b20f6801f072bd080cdd \ + --hash=sha256:7e4e1f580033335c6f76d1e0d6b56baf009d1a64d6a4816347e4271ba951f46d \ + --hash=sha256:7e8ec5f606e0809426d2440e0683509fb605a8820a21ebd120dcdba61b74ef7f \ + --hash=sha256:7f196cd7910d71e9d9860da0ff7a77f64d22c1ad931f1dd18559a06e03109fc0 \ + --hash=sha256:82f3802bfc4751f420d591c5c864de538b71cea117fce67e4595c2afede08a15 \ + --hash=sha256:85ffc9920ffc39c5eee1e3ac9100c913a0973996fbad5111f939bbda49204bb7 \ + --hash=sha256:8e6c219e375f6341d0959af814296372d265a8ca1af63825f65e2e87c618f006 \ + --hash=sha256:8f767ba0911602ddef289404e33835a61168314ebd3c729833db2ed685824211 \ + --hash=sha256:8ff038d52ef6aa0f309feeba00c5095c9118d0abf787e8e8454d6048db2037fc \ + --hash=sha256:915e7a2418f10bd1151b1953df06d896db9783c9cfdb9a8ee1f9b3a4331ab503 \ + --hash=sha256:92883836caf50d5255be03d988d75bc93e3f86ba247b7ca137347c323f731deb \ + --hash=sha256:960b1b3efa39872ac8b6cc3a556edd6fb90ed74f08c9c45e028f1005b26aa55d \ + --hash=sha256:9aeaf53eaa075dd63e81512522fd180097312fb2c9f476333309184285c49ce0 \ + --hash=sha256:9d8089d853c7963a8ce87fff93e2a67075c0bc08684a08ea6ad13577c38ffc38 \ + --hash=sha256:a4130d0b9ce5fad6af07421b1aecc7e079519f70d6c05729ab871794eded8617 \ + --hash=sha256:a482ac121de6973897c92c2f31defc6bafb11c83825109275cffce54bb64933f \ + --hash=sha256:add7ac388d1e0bf57259afbcf9ed05621a3bf11ce5ee337e7536f1e1aaf056b0 \ + --hash=sha256:b1f12bd684887a0a5d55e6363ca87056f361e45451105012d329b86ec19dbe0b \ + --hash=sha256:b3f99e1756fc48ad507b95e5d86f2fb21b3d495012ff13e6592ebac14033f166 \ + --hash=sha256:b4cce60d0223074803c9dbe0721ad3fa51dafe7d462fee4b656a1aa01ee07518 \ + --hash=sha256:baeb47635cb33375dee4924cd93d7f5dcaa786c740b08423b0209b824a1ee728 \ + --hash=sha256:bbea5b775f0ac84945191fb83f845a6fd9a21a03ea7f2e187defac7e401616ad \ + --hash=sha256:bbfcb95d9a744e6e2827dfc66ad10e1020e0cac255eb7f85652832d5a264c2fc \ + --hash=sha256:bd6e7d363aa93bd3421b30b6af97064daf47bc96005bddba67c5ffbc6df426b8 \ + --hash=sha256:be77c402d5e882b6fbacfd90823f13da8e0a69658405a39a569c6b58fdb17b03 \ + --hash=sha256:c302245fd6c33d96bd169c7ccf2513c20f4c1e417c07ce9dce107c8bc3f8411f \ + --hash=sha256:c88653877aeb514c089d1b3d473451677b8b9a6d1497dbddf1ae7934518b06d2 \ + --hash=sha256:cae6383181f1e345317742d2ddd88f9e7d2682fa4c9432e3a74e47d92dce0229 \ + --hash=sha256:cd471ede0d802dd936b6fab28188302b2d497f68436025857ca72cd3810423fe \ + --hash=sha256:d106493a60dcb4aef35a0fac85105e150a11cf8bc2b0d388f5a33272d756c966 \ + --hash=sha256:d30b650595fdbe32366b94cb14f30bb2b625e512bd4e1df00611f99dc5c27fd4 \ + --hash=sha256:d51fde50a77f81330523562e3c2734ffdca9c4c9e9d355478117905e1cfe16c6 \ + --hash=sha256:d57dea657357230cc780e13920d7fa7db059d58fe721c80020f94476da4ca0a1 \ + --hash=sha256:d771f085fcdf4035786adfb1d8db026df1eb4b41dac1c3d070d1e49512843227 \ + --hash=sha256:dae0f0bd7d30c0ad61b9a504e8e272cb8391eed3f1587edf933f4f6b33437450 \ + --hash=sha256:db0562c5f71d18596dcd45e854cf2eeba27d7543e1a3acdafb7eef728f7fe85d \ + --hash=sha256:dfd51b4c56b673dfbc43d7d27ef857dd91124801e2806c69bb45585ce0fa019b \ + --hash=sha256:e080c0637aea036f35507e803a4778f119a9b436617694ae1c5c366805f1e997 \ + --hash=sha256:e48d4dbe0f88e53081da605ae68644e5182752803bbc2beb228cca7f1c4454d6 \ + --hash=sha256:e8b4b5580280b9265af3e0409974fb79c64cf7523632d03fbf11df18f8b0181e \ + --hash=sha256:e8b5378de2b139c3a830f0209c1e91f7705919a4b3e563a10955104f5097a70a \ + --hash=sha256:e904f2417f0d6f6d514f3f8b836416c360f306ddaee1f84de8eef1e722d212e5 \ + --hash=sha256:eee884572b06bbe8a2b54f424dbd996139442cf83c76478e1ec162512e0dd2c7 \ + --hash=sha256:f1fbb0a99125b1287c6d9747f937dc66621426836d1a2d50d05aecfc81911b57 \ + --hash=sha256:f40a95186a72fa0b67d15fef0f157bfcda00b4f59c8a07cbe5530d41ac35d105 \ + --hash=sha256:f6e0bfe77d238308839699944164b96a2eeccaf55f2af400f54dc20669d8d5f2 \ + --hash=sha256:f963eafc0a77a6c0562397da004f5876a9bcf7265a7bcc3205e29636bc4a1312 \ + --hash=sha256:fb9d44c25244e11c8be3f12c938ca8ba8404620ef8092245d2093c6ab3df260f \ + --hash=sha256:fc78739b5ec6e4fb02301984a3d442a91406e7700efbe305071e7fd1c78278f2 \ + --hash=sha256:fceef7fe67c81e1585198215e42ad3fdba3a25644beda8fbdaf85f4d7b93175a \ + --hash=sha256:fd96476f04db5ceba1cfa0f21228f67c1f7402296f0e73fee3513aa680ad237b # via feast (pyproject.toml) -mypy==1.19.1 \ - --hash=sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd \ - --hash=sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b \ - --hash=sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1 \ - --hash=sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba \ - --hash=sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b \ - --hash=sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045 \ - --hash=sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac \ - --hash=sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6 \ - --hash=sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a \ - --hash=sha256:409088884802d511ee52ca067707b90c883426bd95514e8cfda8281dc2effe24 \ - --hash=sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957 \ - --hash=sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042 \ - --hash=sha256:4f28f99c824ecebcdaa2e55d82953e38ff60ee5ec938476796636b86afa3956e \ - --hash=sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec \ - --hash=sha256:7bcfc336a03a1aaa26dfce9fff3e287a3ba99872a157561cbfcebe67c13308e3 \ - --hash=sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718 \ - --hash=sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f \ - --hash=sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331 \ - --hash=sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1 \ - --hash=sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1 \ - --hash=sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13 \ - --hash=sha256:b13cfdd6c87fc3efb69ea4ec18ef79c74c3f98b4e5498ca9b85ab3b2c2329a67 \ - --hash=sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2 \ - --hash=sha256:b7951a701c07ea584c4fe327834b92a30825514c868b1f69c30445093fdd9d5a \ - --hash=sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b \ - --hash=sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8 \ - --hash=sha256:c608937067d2fc5a4dd1a5ce92fd9e1398691b8c5d012d66e1ddd430e9244376 \ - --hash=sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef \ - --hash=sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288 \ - --hash=sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75 \ - --hash=sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74 \ - --hash=sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250 \ - --hash=sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab \ - --hash=sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6 \ - --hash=sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247 \ - --hash=sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925 \ - --hash=sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e \ - --hash=sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e +mypy==1.20.0 \ + --hash=sha256:002b613ae19f4ac7d18b7e168ffe1cb9013b37c57f7411984abbd3b817b0a214 \ + --hash=sha256:00e047c74d3ec6e71a2eb88e9ea551a2edb90c21f993aefa9e0d2a898e0bb732 \ + --hash=sha256:02cca0761c75b42a20a2757ae58713276605eb29a08dd8a6e092aa347c4115ca \ + --hash=sha256:0ecd63f75fdd30327e4ad8b5704bd6d91fc6c1b2e029f8ee14705e1207212489 \ + --hash=sha256:0f42dfaab7ec1baff3b383ad7af562ab0de573c5f6edb44b2dab016082b89948 \ + --hash=sha256:1973868d2adbb4584a3835780b27436f06d1dc606af5be09f187aaa25be1070f \ + --hash=sha256:26c8b52627b6552f47ff11adb4e1509605f094e29815323e487fc0053ebe93d1 \ + --hash=sha256:2721f0ce49cb74a38f00c50da67cb7d36317b5eda38877a49614dc018e91c787 \ + --hash=sha256:2fcedb16d456106e545b2bfd7ef9d24e70b38ec252d2a629823a4d07ebcdb69e \ + --hash=sha256:31b5dbb55293c1bd27c0fc813a0d2bb5ceef9d65ac5afa2e58f829dab7921fd5 \ + --hash=sha256:34506397dbf40c15dc567635d18a21d33827e9ab29014fb83d292a8f4f8953b6 \ + --hash=sha256:367e5c993ba34d5054d11937d0485ad6dfc60ba760fa326c01090fc256adf15c \ + --hash=sha256:379edf079ce44ac8d2805bcf9b3dd7340d4f97aad3a5e0ebabbf9d125b84b442 \ + --hash=sha256:39362cdb4ba5f916e7976fccecaab1ba3a83e35f60fa68b64e9a70e221bb2436 \ + --hash=sha256:4525e7010b1b38334516181c5b81e16180b8e149e6684cee5a727c78186b4e3b \ + --hash=sha256:47781555a7aa5fedcc2d16bcd72e0dc83eb272c10dd657f9fb3f9cc08e2e6abb \ + --hash=sha256:49d11c6f573a5a08f77fad13faff2139f6d0730ebed2cfa9b3d2702671dd7188 \ + --hash=sha256:555493c44a4f5a1b58d611a43333e71a9981c6dbe26270377b6f8174126a0526 \ + --hash=sha256:555658c611099455b2da507582ea20d2043dfdfe7f5ad0add472b1c6238b433f \ + --hash=sha256:697f102c5c1d526bdd761a69f17c6070f9892eebcb94b1a5963d679288c09e78 \ + --hash=sha256:76a70bf840495729be47510856b978f1b0ec7d08f257ca38c9d932720bf6b43e \ + --hash=sha256:7d3243c406773185144527f83be0e0aefc7bf4601b0b2b956665608bf7c98a83 \ + --hash=sha256:931a7630bba591593dcf6e97224a21ff80fb357e7982628d25e3c618e7f598ef \ + --hash=sha256:9804c3ad27f78e54e58b32e7cb532d128b43dbfb9f3f9f06262b821a0f6bd3f5 \ + --hash=sha256:a17c5d0bdcca61ce24a35beb828a2d0d323d3fcf387d7512206888c900193367 \ + --hash=sha256:a6e0641147cbfa7e4e94efdb95c2dab1aff8cfc159ded13e07f308ddccc8c48e \ + --hash=sha256:a79c1eba7ac4209f2d850f0edd0a2f8bba88cbfdfefe6fb76a19e9d4fe5e71a2 \ + --hash=sha256:a9336b5e6712f4adaf5afc3203a99a40b379049104349d747eb3e5a3aa23ac2e \ + --hash=sha256:b20c8b0fd5877abdf402e79a3af987053de07e6fb208c18df6659f708b535134 \ + --hash=sha256:b3a49064504be59e59da664c5e149edc1f26c67c4f8e8456f6ba6aba55033018 \ + --hash=sha256:b503ab55a836136b619b5fc21c8803d810c5b87551af8600b72eecafb0059cb0 \ + --hash=sha256:bd0212976dc57a5bfeede7c219e7cd66568a32c05c9129686dd487c059c1b88a \ + --hash=sha256:c70380fe5d64010f79fb863b9081c7004dd65225d2277333c219d93a10dad4dd \ + --hash=sha256:d99f515f95fd03a90875fdb2cca12ff074aa04490db4d190905851bdf8a549a8 \ + --hash=sha256:e80cf77847d0d3e6e3111b7b25db32a7f8762fd4b9a3a72ce53fe16a2863b281 \ + --hash=sha256:eb96c84efcc33f0b5e0e04beacf00129dd963b67226b01c00b9dfc8affb464c3 \ + --hash=sha256:ebea00201737ad4391142808ed16e875add5c17f676e0912b387739f84991e13 \ + --hash=sha256:efe8d70949c3023698c3fca1e94527e7e790a361ab8116f90d11221421cd8726 \ + --hash=sha256:f13b3e41bce9d257eded794c0f12878af3129d80aacd8a3ee0dee51f3a978651 \ + --hash=sha256:f194db59657c58593a3c47c6dfd7bad4ef4ac12dbc94d01b3a95521f78177e33 \ + --hash=sha256:f49590891d2c2f8a9de15614e32e459a794bcba84693c2394291a2038bbaaa69 \ + --hash=sha256:f75ff57defcd0f1d6e006d721ccdec6c88d4f6a7816eb92f1c4890d979d9ee62 \ + --hash=sha256:f799d9db89fc00446f03281f84a221e50018fc40113a3ba9864b132895619ebe \ + --hash=sha256:f8426d4d75d68714abc17a4292d922f6ba2cfb984b72c2278c437f6dae797865 # via sqlalchemy mypy-extensions==1.1.0 \ --hash=sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505 \ --hash=sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558 # via mypy -numpy==2.4.2 \ - --hash=sha256:00ab83c56211a1d7c07c25e3217ea6695e50a3e2f255053686b081dc0b091a82 \ - --hash=sha256:068cdb2d0d644cdb45670810894f6a0600797a69c05f1ac478e8d31670b8ee75 \ - --hash=sha256:0f01dcf33e73d80bd8dc0f20a71303abbafa26a19e23f6b68d1aa9990af90257 \ - --hash=sha256:0fece1d1f0a89c16b03442eae5c56dc0be0c7883b5d388e0c03f53019a4bfd71 \ - --hash=sha256:12e26134a0331d8dbd9351620f037ec470b7c75929cb8a1537f6bfe411152a1a \ - --hash=sha256:1ae241bbfc6ae276f94a170b14785e561cb5e7f626b6688cf076af4110887413 \ - --hash=sha256:1f92f53998a17265194018d1cc321b2e96e900ca52d54c7c77837b71b9465181 \ - --hash=sha256:209fae046e62d0ce6435fcfe3b1a10537e858249b3d9b05829e2a05218296a85 \ - --hash=sha256:20abd069b9cda45874498b245c8015b18ace6de8546bf50dfa8cea1696ed06ef \ - --hash=sha256:21982668592194c609de53ba4933a7471880ccbaadcc52352694a59ecc860b3a \ - --hash=sha256:25f2059807faea4b077a2b6837391b5d830864b3543627f381821c646f31a63c \ - --hash=sha256:2653de5c24910e49c2b106499803124dde62a5a1fe0eedeaecf4309a5f639390 \ - --hash=sha256:2b8f157c8a6f20eb657e240f8985cc135598b2b46985c5bccbde7616dc9c6b1e \ - --hash=sha256:2fb882da679409066b4603579619341c6d6898fc83a8995199d5249f986e8e8f \ - --hash=sha256:40397bda92382fcec844066efb11f13e1c9a3e2a8e8f318fb72ed8b6db9f60f1 \ - --hash=sha256:444be170853f1f9d528428eceb55f12918e4fda5d8805480f36a002f1415e09b \ - --hash=sha256:47c5a6ed21d9452b10227e5e8a0e1c22979811cad7dcc19d8e3e2fb8fa03f1a3 \ - --hash=sha256:4f069069931240b3fc703f1e23df63443dbd6390614c8c44a87d96cd0ec81eb1 \ - --hash=sha256:52b913ec40ff7ae845687b0b34d8d93b60cb66dcee06996dd5c99f2fc9328657 \ - --hash=sha256:5633c0da313330fd20c484c78cdd3f9b175b55e1a766c4a174230c6b70ad8262 \ - --hash=sha256:5daf6f3914a733336dab21a05cdec343144600e964d2fcdabaac0c0269874b2a \ - --hash=sha256:5eea80d908b2c1f91486eb95b3fb6fab187e569ec9752ab7d9333d2e66bf2d6b \ - --hash=sha256:602f65afdef699cda27ec0b9224ae5dc43e328f4c24c689deaf77133dbee74d0 \ - --hash=sha256:659a6107e31a83c4e33f763942275fd278b21d095094044eb35569e86a21ddae \ - --hash=sha256:66cb9422236317f9d44b67b4d18f44efe6e9c7f8794ac0462978513359461554 \ - --hash=sha256:6d82351358ffbcdcd7b686b90742a9b86632d6c1c051016484fa0b326a0a1548 \ - --hash=sha256:6e9f61981ace1360e42737e2bae58b27bf28a1b27e781721047d84bd754d32e7 \ - --hash=sha256:6ed0be1ee58eef41231a5c943d7d1375f093142702d5723ca2eb07db9b934b05 \ - --hash=sha256:7cdde6de52fb6664b00b056341265441192d1291c130e99183ec0d4b110ff8b1 \ - --hash=sha256:7df2de1e4fba69a51c06c28f5a3de36731eb9639feb8e1cf7e4a7b0daf4cf622 \ - --hash=sha256:7edc794af8b36ca37ef5fcb5e0d128c7e0595c7b96a2318d1badb6fcd8ee86b1 \ - --hash=sha256:7f54844851cdb630ceb623dcec4db3240d1ac13d4990532446761baede94996a \ - --hash=sha256:805cc8de9fd6e7a22da5aed858e0ab16be5a4db6c873dde1d7451c541553aa27 \ - --hash=sha256:8906e71fd8afcb76580404e2a950caef2685df3d2a57fe82a86ac8d33cc007ba \ - --hash=sha256:89f7268c009bc492f506abd6f5265defa7cb3f7487dc21d357c3d290add45082 \ - --hash=sha256:8c50dd1fc8826f5b26a5ee4d77ca55d88a895f4e4819c7ecc2a9f5905047a443 \ - --hash=sha256:8e4549f8a3c6d13d55041925e912bfd834285ef1dd64d6bc7d542583355e2e98 \ - --hash=sha256:8e9afaeb0beff068b4d9cd20d322ba0ee1cecfb0b08db145e4ab4dd44a6b5110 \ - --hash=sha256:98f16a80e917003a12c0580f97b5f875853ebc33e2eaa4bccfc8201ac6869308 \ - --hash=sha256:9e35d3e0144137d9fdae62912e869136164534d64a169f86438bc9561b6ad49f \ - --hash=sha256:9e4424677ce4b47fe73c8b5556d876571f7c6945d264201180db2dc34f676ab5 \ - --hash=sha256:adb6ed2ad29b9e15321d167d152ee909ec73395901b70936f029c3bc6d7f4460 \ - --hash=sha256:aea4f66ff44dfddf8c2cffd66ba6538c5ec67d389285292fe428cb2c738c8aef \ - --hash=sha256:b21041e8cb6a1eb5312dd1d2f80a94d91efffb7a06b70597d44f1bd2dfc315ab \ - --hash=sha256:b2f0073ed0868db1dcd86e052d37279eef185b9c8db5bf61f30f46adac63c909 \ - --hash=sha256:b3a24467af63c67829bfaa61eecf18d5432d4f11992688537be59ecd6ad32f5e \ - --hash=sha256:b9c618d56a29c9cb1c4da979e9899be7578d2e0b3c24d52079c166324c9e8695 \ - --hash=sha256:bba37bc29d4d85761deed3954a1bc62be7cf462b9510b51d367b769a8c8df325 \ - --hash=sha256:bd3a7a9f5847d2fb8c2c6d1c862fa109c31a9abeca1a3c2bd5a64572955b2979 \ - --hash=sha256:be71bf1edb48ebbbf7f6337b5bfd2f895d1902f6335a5830b20141fc126ffba0 \ - --hash=sha256:c02ef4401a506fb60b411467ad501e1429a3487abca4664871d9ae0b46c8ba32 \ - --hash=sha256:c3cd545784805de05aafe1dde61752ea49a359ccba9760c1e5d1c88a93bbf2b7 \ - --hash=sha256:c7ac672d699bf36275c035e16b65539931347d68b70667d28984c9fb34e07fa7 \ - --hash=sha256:cb7bbb88aa74908950d979eeaa24dbdf1a865e3c7e45ff0121d8f70387b55f73 \ - --hash=sha256:cd2bd2bbed13e213d6b55dc1d035a4f91748a7d3edc9480c13898b0353708920 \ - --hash=sha256:cda077c2e5b780200b6b3e09d0b42205a3d1c68f30c6dceb90401c13bff8fe74 \ - --hash=sha256:cf28c0c1d4c4bf00f509fa7eb02c58d7caf221b50b467bcb0d9bbf1584d5c821 \ - --hash=sha256:d0d9b7c93578baafcbc5f0b83eaf17b79d345c6f36917ba0c67f45226911d499 \ - --hash=sha256:d1240d50adff70c2a88217698ca844723068533f3f5c5fa6ee2e3220e3bdb000 \ - --hash=sha256:d30291931c915b2ab5717c2974bb95ee891a1cf22ebc16a8006bd59cd210d40a \ - --hash=sha256:d9f64d786b3b1dd742c946c42d15b07497ed14af1a1f3ce840cce27daa0ce913 \ - --hash=sha256:da6cad4e82cb893db4b69105c604d805e0c3ce11501a55b5e9f9083b47d2ffe8 \ - --hash=sha256:df1b10187212b198dd45fa943d8985a3c8cf854aed4923796e0e019e113a1bda \ - --hash=sha256:e04ae107ac591763a47398bb45b568fc38f02dbc4aa44c063f67a131f99346cb \ - --hash=sha256:e6dee3bb76aa4009d5a912180bf5b2de012532998d094acee25d9cb8dee3e44a \ - --hash=sha256:e7e88598032542bd49af7c4747541422884219056c268823ef6e5e89851c8825 \ - --hash=sha256:e98c97502435b53741540a5717a6749ac2ada901056c7db951d33e11c885cc7d \ - --hash=sha256:ec055f6dae239a6299cace477b479cca2fc125c5675482daf1dd886933a1076f \ - --hash=sha256:f74f0f7779cc7ae07d1810aab8ac6b1464c3eafb9e283a40da7309d5e6e48fbb \ - --hash=sha256:fbde1b0c6e81d56f5dccd95dd4a711d9b95df1ae4009a60887e56b27e8d903fa \ - --hash=sha256:fcf92bee92742edd401ba41135185866f7026c502617f422eb432cfeca4fe236 \ - --hash=sha256:fd49860271d52127d61197bb50b64f58454e9f578cb4b2c001a6de8b1f50b0b1 +numpy==2.4.4 \ + --hash=sha256:07077278157d02f65c43b1b26a3886bce886f95d20aabd11f87932750dfb14ed \ + --hash=sha256:08f2e31ed5e6f04b118e49821397f12767934cfdd12a1ce86a058f91e004ee50 \ + --hash=sha256:0aec54fd785890ecca25a6003fd9a5aed47ad607bbac5cd64f836ad8666f4959 \ + --hash=sha256:0d35aea54ad1d420c812bfa0385c71cd7cc5bcf7c65fed95fc2cd02fe8c79827 \ + --hash=sha256:0d4e437e295f18ec29bc79daf55e8a47a9113df44d66f702f02a293d93a2d6dd \ + --hash=sha256:0dfd3f9d3adbe2920b68b5cd3d51444e13a10792ec7154cd0a2f6e74d4ab3233 \ + --hash=sha256:1378871da56ca8943c2ba674530924bb8ca40cd228358a3b5f302ad60cf875fc \ + --hash=sha256:15716cfef24d3a9762e3acdf87e27f58dc823d1348f765bbea6bef8c639bfa1b \ + --hash=sha256:19710a9ca9992d7174e9c52f643d4272dcd1558c5f7af7f6f8190f633bd651a7 \ + --hash=sha256:23cbfd4c17357c81021f21540da84ee282b9c8fba38a03b7b9d09ba6b951421e \ + --hash=sha256:2483e4584a1cb3092da4470b38866634bafb223cbcd551ee047633fd2584599a \ + --hash=sha256:27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d \ + --hash=sha256:28a650663f7314afc3e6ec620f44f333c386aad9f6fc472030865dc0ebb26ee3 \ + --hash=sha256:2aa0613a5177c264ff5921051a5719d20095ea586ca88cc802c5c218d1c67d3e \ + --hash=sha256:2c194dd721e54ecad9ad387c1d35e63dce5c4450c6dc7dd5611283dda239aabb \ + --hash=sha256:2d19e6e2095506d1736b7d80595e0f252d76b89f5e715c35e06e937679ea7d7a \ + --hash=sha256:2d390634c5182175533585cc89f3608a4682ccb173cc9bb940b2881c8d6f8fa0 \ + --hash=sha256:30caa73029a225b2d40d9fae193e008e24b2026b7ee1a867b7ee8d96ca1a448e \ + --hash=sha256:42c16925aa5a02362f986765f9ebabf20de75cdefdca827d14315c568dcab113 \ + --hash=sha256:45dbed2ab436a9e826e302fcdcbe9133f9b0006e5af7168afb8963a6520da103 \ + --hash=sha256:4636de7fd195197b7535f231b5de9e4b36d2c440b6e566d2e4e4746e6af0ca93 \ + --hash=sha256:4a19d9dba1a76618dd86b164d608566f393f8ec6ac7c44f0cc879011c45e65af \ + --hash=sha256:4bbc7f303d125971f60ec0aaad5e12c62d0d2c925f0ab1273debd0e4ba37aba5 \ + --hash=sha256:4d6d57903571f86180eb98f8f0c839fa9ebbfb031356d87f1361be91e433f5b7 \ + --hash=sha256:4e874c976154687c1f71715b034739b45c7711bec81db01914770373d125e392 \ + --hash=sha256:51fc224f7ca4d92656d5a5eb315f12eb5fe2c97a66249aa7b5f562528a3be38c \ + --hash=sha256:58c8b5929fcb8287cbd6f0a3fae19c6e03a5c48402ae792962ac465224a629a4 \ + --hash=sha256:5a285b3b96f951841799528cd1f4f01cd70e7e0204b4abebac9463eecfcf2a40 \ + --hash=sha256:5c70f1cc1c4efbe316a572e2d8b9b9cc44e89b95f79ca3331553fbb63716e2bf \ + --hash=sha256:62d6b0f03b694173f9fcb1fb317f7222fd0b0b103e784c6549f5e53a27718c44 \ + --hash=sha256:6a246d5914aa1c820c9443ddcee9c02bec3e203b0c080349533fae17727dfd1b \ + --hash=sha256:6aa3236c78803afbcb255045fbef97a9e25a1f6c9888357d205ddc42f4d6eba5 \ + --hash=sha256:6bbe4eb67390b0a0265a2c25458f6b90a409d5d069f1041e6aff1e27e3d9a79e \ + --hash=sha256:715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74 \ + --hash=sha256:72944b19f2324114e9dc86a159787333b77874143efcf89a5167ef83cfee8af0 \ + --hash=sha256:81f4a14bee47aec54f883e0cad2d73986640c1590eb9bfaaba7ad17394481e6e \ + --hash=sha256:846300f379b5b12cc769334464656bc882e0735d27d9726568bc932fdc49d5ec \ + --hash=sha256:86b6f55f5a352b48d7fbfd2dbc3d5b780b2d79f4d3c121f33eb6efb22e9a2015 \ + --hash=sha256:874f200b2a981c647340f841730fc3a2b54c9d940566a3c4149099591e2c4c3d \ + --hash=sha256:8a87ec22c87be071b6bdbd27920b129b94f2fc964358ce38f3822635a3e2e03d \ + --hash=sha256:8b3b60bb7cba2c8c81837661c488637eee696f59a877788a396d33150c35d842 \ + --hash=sha256:8e3ed142f2728df44263aaf5fb1f5b0b99f4070c553a0d7f033be65338329150 \ + --hash=sha256:93e15038125dc1e5345d9b5b68aa7f996ec33b98118d18c6ca0d0b7d6198b7e8 \ + --hash=sha256:989824e9faf85f96ec9c7761cd8d29c531ad857bfa1daa930cba85baaecf1a9a \ + --hash=sha256:99d838547ace2c4aace6c4f76e879ddfe02bb58a80c1549928477862b7a6d6ed \ + --hash=sha256:9b2aec6af35c113b05695ebb5749a787acd63cafc83086a05771d1e1cd1e555f \ + --hash=sha256:9c585a1790d5436a5374bac930dad6ed244c046ed91b2b2a3634eb2971d21008 \ + --hash=sha256:a7164afb23be6e37ad90b2f10426149fd75aee07ca55653d2aa41e66c4ef697e \ + --hash=sha256:ac6b31e35612a26483e20750126d30d0941f949426974cace8e6b5c58a3657b0 \ + --hash=sha256:ad2e2ef14e0b04e544ea2fa0a36463f847f113d314aa02e5b402fdf910ef309e \ + --hash=sha256:b268594bccac7d7cf5844c7732e3f20c50921d94e36d7ec9b79e9857694b1b2f \ + --hash=sha256:b5f0362dc928a6ecd9db58868fca5e48485205e3855957bdedea308f8672ea4a \ + --hash=sha256:ba1f4fc670ed79f876f70082eff4f9583c15fb9a4b89d6188412de4d18ae2f40 \ + --hash=sha256:ba203255017337d39f89bdd58417f03c4426f12beed0440cfd933cb15f8669c7 \ + --hash=sha256:c901b15172510173f5cb310eae652908340f8dede90fff9e3bf6c0d8dfd92f83 \ + --hash=sha256:c9b39d38a9bd2ae1becd7eac1303d031c5c110ad31f2b319c6e7d98b135c934d \ + --hash=sha256:d2a8490669bfe99a233298348acc2d824d496dee0e66e31b66a6022c2ad74a5c \ + --hash=sha256:dddbbd259598d7240b18c9d87c56a9d2fb3b02fe266f49a7c101532e78c1d871 \ + --hash=sha256:df3775294accfdd75f32c74ae39fcba920c9a378a2fc18a12b6820aa8c1fb502 \ + --hash=sha256:e44319a2953c738205bf3354537979eaa3998ed673395b964c1176083dd46252 \ + --hash=sha256:e4a010c27ff6f210ff4c6ef34394cd61470d01014439b192ec22552ee867f2a8 \ + --hash=sha256:e823b8b6edc81e747526f70f71a9c0a07ac4e7ad13020aa736bb7c9d67196115 \ + --hash=sha256:e892aff75639bbef0d2a2cfd55535510df26ff92f63c92cd84ef8d4ba5a5557f \ + --hash=sha256:eea7ac5d2dce4189771cedb559c738a71512768210dc4e4753b107a2048b3d0e \ + --hash=sha256:ef4059d6e5152fa1a39f888e344c73fdc926e1b2dd58c771d67b0acfbf2aa67d \ + --hash=sha256:f169b9a863d34f5d11b8698ead99febeaa17a13ca044961aa8e2662a6c7766a0 \ + --hash=sha256:f2cf083b324a467e1ab358c105f6cad5ea950f50524668a80c486ff1db24e119 \ + --hash=sha256:f8474c4241bc18b750be2abea9d7a9ec84f46ef861dbacf86a4f6e043401f79e \ + --hash=sha256:f983334aea213c99992053ede6168500e5f086ce74fbc4acc3f2b00f5762e9db \ + --hash=sha256:f9e75681b59ddaa5e659898085ae0eaea229d054f2ac0c7e563a62205a700121 \ + --hash=sha256:fbc356aae7adf9e6336d336b9c8111d390a05df88f1805573ebb0807bd06fd1d \ + --hash=sha256:fcfe2045fd2e8f3cb0ce9d4ba6dba6333b8fa05bb8a4939c908cd43322d14c7e # via # feast (pyproject.toml) # dask @@ -759,17 +767,15 @@ prometheus-client==0.24.1 \ --hash=sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055 \ --hash=sha256:7e0ced7fbbd40f7b84962d5d2ab6f17ef88a72504dcf7c0b40737b43b2a461f9 # via feast (pyproject.toml) -protobuf==6.33.5 \ - --hash=sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c \ - --hash=sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02 \ - --hash=sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c \ - --hash=sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd \ - --hash=sha256:8f04fa32763dcdb4973d537d6b54e615cc61108c7cb38fe59310c3192d29510a \ - --hash=sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190 \ - --hash=sha256:a3157e62729aafb8df6da2c03aa5c0937c7266c626ce11a278b6eb7963c4e37c \ - --hash=sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5 \ - --hash=sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0 \ - --hash=sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b +protobuf==7.34.1 \ + --hash=sha256:34b84ce27680df7cca9f231043ada0daa55d0c44a2ddfaa58ec1d0d89d8bf60a \ + --hash=sha256:403b093a6e28a960372b44e5eb081775c9b056e816a8029c61231743d63f881a \ + --hash=sha256:5185e0e948d07abe94bb76ec9b8416b604cfe5da6f871d67aad30cbf24c3110b \ + --hash=sha256:8ff40ce8cd688f7265326b38d5a1bed9bfdf5e6723d49961432f83e21d5713e4 \ + --hash=sha256:9ce42245e704cc5027be797c1db1eb93184d44d1cdd71811fb2d9b25ad541280 \ + --hash=sha256:bb3812cd53aefea2b028ef42bd780f5b96407247f20c6ef7c679807e9d188f11 \ + --hash=sha256:d8b2cc79c4d8f62b293ad9b11ec3aebce9af481fa73e64556969f7345ebf9fc7 \ + --hash=sha256:e97b55646e6ce5cbb0954a8c28cd39a5869b59090dfaa7df4598a7fba869468c # via feast (pyproject.toml) psutil==7.2.2 \ --hash=sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372 \ @@ -977,25 +983,25 @@ pydantic-core==2.41.5 \ --hash=sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425 \ --hash=sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52 # via pydantic -pygments==2.19.2 \ - --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \ - --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b +pygments==2.20.0 \ + --hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \ + --hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176 # via feast (pyproject.toml) -pyjwt==2.11.0 \ - --hash=sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623 \ - --hash=sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469 +pyjwt==2.12.1 \ + --hash=sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c \ + --hash=sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b # via feast (pyproject.toml) python-dateutil==2.9.0.post0 \ --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 # via pandas -python-dotenv==1.2.1 \ - --hash=sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6 \ - --hash=sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61 +python-dotenv==1.2.2 \ + --hash=sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a \ + --hash=sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3 # via uvicorn -pytz==2025.2 \ - --hash=sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3 \ - --hash=sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00 +pytz==2026.1.post1 \ + --hash=sha256:3378dde6a0c3d26719182142c56e60c7f9af7e968076f31aae569d72a0358ee1 \ + --hash=sha256:f2fd16142fda348286a75e1a524be810bb05d444e5a081f37f7affc635035f7a # via pandas pyyaml==6.0.3 \ --hash=sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c \ @@ -1081,9 +1087,9 @@ referencing==0.37.0 \ # via # jsonschema # jsonschema-specifications -requests==2.32.5 \ - --hash=sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6 \ - --hash=sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf +requests==2.33.1 \ + --hash=sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517 \ + --hash=sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a # via feast (pyproject.toml) rpds-py==0.30.0 \ --hash=sha256:07ae8a593e1c3c6b82ca3292efbe73c30b61332fd612e05abee07c79359f292f \ @@ -1208,74 +1214,78 @@ six==1.17.0 \ --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \ --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81 # via python-dateutil -sqlalchemy[mypy]==2.0.46 \ - --hash=sha256:09168817d6c19954d3b7655da6ba87fcb3a62bb575fb396a81a8b6a9fadfe8b5 \ - --hash=sha256:0cc3117db526cad3e61074100bd2867b533e2c7dc1569e95c14089735d6fb4fe \ - --hash=sha256:181903fe8c1b9082995325f1b2e84ac078b1189e2819380c2303a5f90e114a62 \ - --hash=sha256:1bc3f601f0a818d27bfe139f6766487d9c88502062a2cd3a7ee6c342e81d5047 \ - --hash=sha256:1e6199143d51e3e1168bedd98cc698397404a8f7508831b81b6a29b18b051069 \ - --hash=sha256:2347c3f0efc4de367ba00218e0ae5c4ba2306e47216ef80d6e31761ac97cb0b9 \ - --hash=sha256:261c4b1f101b4a411154f1da2b76497d73abbfc42740029205d4d01fa1052684 \ - --hash=sha256:33e462154edb9493f6c3ad2125931e273bbd0be8ae53f3ecd1c161ea9a1dd366 \ - --hash=sha256:37fee2164cf21417478b6a906adc1a91d69ae9aba8f9533e67ce882f4bb1de53 \ - --hash=sha256:3a9a72b0da8387f15d5810f1facca8f879de9b85af8c645138cba61ea147968c \ - --hash=sha256:3aac08f7546179889c62b53b18ebf1148b10244b3405569c93984b0388d016a7 \ - --hash=sha256:3c32e993bc57be6d177f7d5d31edb93f30726d798ad86ff9066d75d9bf2e0b6b \ - --hash=sha256:412f26bb4ba942d52016edc8d12fb15d91d3cd46b0047ba46e424213ad407bcb \ - --hash=sha256:42a1643dc5427b69aca967dae540a90b0fbf57eaf248f13a90ea5930e0966863 \ - --hash=sha256:4396c948d8217e83e2c202fbdcc0389cf8c93d2c1c5e60fa5c5a955eae0e64be \ - --hash=sha256:4dafb537740eef640c4d6a7c254611dca2df87eaf6d14d6a5fca9d1f4c3fc0fa \ - --hash=sha256:4f52f7291a92381e9b4de9050b0a65ce5d6a763333406861e33906b8aa4906bf \ - --hash=sha256:52fe29b3817bd191cc20bad564237c808967972c97fa683c04b28ec8979ae36f \ - --hash=sha256:56bdd261bfd0895452006d5316cbf35739c53b9bb71a170a331fa0ea560b2ada \ - --hash=sha256:585af6afe518732d9ccd3aea33af2edaae4a7aa881af5d8f6f4fe3a368699597 \ - --hash=sha256:590be24e20e2424a4c3c1b0835e9405fa3d0af5823a1a9fc02e5dff56471515f \ - --hash=sha256:64901e08c33462acc9ec3bad27fc7a5c2b6491665f2aa57564e57a4f5d7c52ad \ - --hash=sha256:6ac245604295b521de49b465bab845e3afe6916bcb2147e5929c8041b4ec0545 \ - --hash=sha256:6f827fd687fa1ba7f51699e1132129eac8db8003695513fcf13fc587e1bd47a5 \ - --hash=sha256:70ed2830b169a9960193f4d4322d22be5c0925357d82cbf485b3369893350908 \ - --hash=sha256:716be5bcabf327b6d5d265dbdc6213a01199be587224eb991ad0d37e83d728fd \ - --hash=sha256:7568fe771f974abadce52669ef3a03150ff03186d8eb82613bc8adc435a03f01 \ - --hash=sha256:77f8071d8fbcbb2dd11b7fd40dedd04e8ebe2eb80497916efedba844298065ef \ - --hash=sha256:82ec52100ec1e6ec671563bbd02d7c7c8d0b9e71a0723c72f22ecf52d1755330 \ - --hash=sha256:895296687ad06dc9b11a024cf68e8d9d3943aa0b4964278d2553b86f1b267735 \ - --hash=sha256:8d3b44b3d0ab2f1319d71d9863d76eeb46766f8cf9e921ac293511804d39813f \ - --hash=sha256:8d679b5f318423eacb61f933a9a0f75535bfca7056daeadbf6bd5bcee6183aee \ - --hash=sha256:8e84b09a9b0f19accedcbeff5c2caf36e0dd537341a33aad8d680336152dc34e \ - --hash=sha256:9094c8b3197db12aa6f05c51c05daaad0a92b8c9af5388569847b03b1007fb1b \ - --hash=sha256:90bde6c6b1827565a95fde597da001212ab436f1b2e0c2dcc7246e14db26e2a3 \ - --hash=sha256:9397b381dcee8a2d6b99447ae85ea2530dcac82ca494d1db877087a13e38926d \ - --hash=sha256:93a12da97cca70cea10d4b4fc602589c4511f96c1f8f6c11817620c021d21d00 \ - --hash=sha256:93bb0aae40b52c57fd74ef9c6933c08c040ba98daf23ad33c3f9893494b8d3ce \ - --hash=sha256:94b1e5f3a5f1ff4f42d5daab047428cd45a3380e51e191360a35cef71c9a7a2a \ - --hash=sha256:965c62be8256d10c11f8907e7a8d3e18127a4c527a5919d85fa87fd9ecc2cfdc \ - --hash=sha256:96c7cca1a4babaaf3bfff3e4e606e38578856917e52f0384635a95b226c87764 \ - --hash=sha256:9bcdce05f056622a632f1d44bb47dbdb677f58cad393612280406ce37530eb6d \ - --hash=sha256:9d80ea2ac519c364a7286e8d765d6cd08648f5b21ca855a8017d9871f075542d \ - --hash=sha256:a1e8cc6cc01da346dc92d9509a63033b9b1bda4fed7a7a7807ed385c7dccdc10 \ - --hash=sha256:ab65cb2885a9f80f979b85aa4e9c9165a31381ca322cbde7c638fe6eefd1ec39 \ - --hash=sha256:af865c18752d416798dae13f83f38927c52f085c52e2f32b8ab0fef46fdd02c2 \ - --hash=sha256:b1e14b2f6965a685c7128bd315e27387205429c2e339eeec55cb75ca4ab0ea2e \ - --hash=sha256:b2a9f9aee38039cf4755891a1e50e1effcc42ea6ba053743f452c372c3152b1b \ - --hash=sha256:be6c0466b4c25b44c5d82b0426b5501de3c424d7a3220e86cd32f319ba56798e \ - --hash=sha256:c4e2cc868b7b5208aec6c960950b7bb821f82c2fe66446c92ee0a571765e91a5 \ - --hash=sha256:c805fa6e5d461329fa02f53f88c914d189ea771b6821083937e79550bf31fc19 \ - --hash=sha256:cf36851ee7219c170bb0793dbc3da3e80c582e04a5437bc601bfe8c85c9216d7 \ - --hash=sha256:db23b1bf8cfe1f7fda19018e7207b20cdb5168f83c437ff7e95d19e39289c447 \ - --hash=sha256:e0c05aff5c6b1bb5fb46a87e0f9d2f733f83ef6cbbbcd5c642b6c01678268061 \ - --hash=sha256:e8ac45e8f4eaac0f9f8043ea0e224158855c6a4329fd4ee37c45c61e3beb518e \ - --hash=sha256:ea3cd46b6713a10216323cda3333514944e510aa691c945334713fca6b5279ff \ - --hash=sha256:ebf7e1e78af38047e08836d33502c7a278915698b7c2145d045f780201679999 \ - --hash=sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e \ - --hash=sha256:ff33c6e6ad006bbc0f34f5faf941cfc62c45841c64c0a058ac38c799f15b5ede +sqlalchemy[mypy]==2.0.48 \ + --hash=sha256:01f6bbd4308b23240cf7d3ef117557c8fd097ec9549d5d8a52977544e35b40ad \ + --hash=sha256:07edba08061bc277bfdc772dd2a1a43978f5a45994dd3ede26391b405c15221e \ + --hash=sha256:10853a53a4a00417a00913d270dddda75815fcb80675874285f41051c094d7dd \ + --hash=sha256:1182437cb2d97988cfea04cf6cdc0b0bb9c74f4d56ec3d08b81e23d621a28cc6 \ + --hash=sha256:144921da96c08feb9e2b052c5c5c1d0d151a292c6135623c6b2c041f2a45f9e0 \ + --hash=sha256:1a89ce07ad2d4b8cfc30bd5889ec40613e028ed80ef47da7d9dd2ce969ad30e0 \ + --hash=sha256:1b4c575df7368b3b13e0cebf01d4679f9a28ed2ae6c1cd0b1d5beffb6b2007dc \ + --hash=sha256:1ccd42229aaac2df431562117ac7e667d702e8e44afdb6cf0e50fa3f18160f0b \ + --hash=sha256:2645b7d8a738763b664a12a1542c89c940daa55196e8d73e55b169cc5c99f65f \ + --hash=sha256:288937433bd44e3990e7da2402fabc44a3c6c25d3704da066b85b89a85474ae0 \ + --hash=sha256:34634e196f620c7a61d18d5cf7dc841ca6daa7961aed75d532b7e58b309ac894 \ + --hash=sha256:348174f228b99f33ca1f773e85510e08927620caa59ffe7803b37170df30332b \ + --hash=sha256:36ac4ddc3d33e852da9cb00ffb08cea62ca05c39711dc67062ca2bb1fae35fd8 \ + --hash=sha256:3713e21ea67bca727eecd4a24bf68bcd414c403faae4989442be60994301ded0 \ + --hash=sha256:389b984139278f97757ea9b08993e7b9d1142912e046ab7d82b3fbaeb0209131 \ + --hash=sha256:426c5ca86415d9b8945c7073597e10de9644802e2ff502b8e1f11a7a2642856b \ + --hash=sha256:4599a95f9430ae0de82b52ff0d27304fe898c17cb5f4099f7438a51b9998ac77 \ + --hash=sha256:49b7bddc1eebf011ea5ab722fdbe67a401caa34a350d278cc7733c0e88fecb1f \ + --hash=sha256:53667b5f668991e279d21f94ccfa6e45b4e3f4500e7591ae59a8012d0f010dcb \ + --hash=sha256:546572a1793cc35857a2ffa1fe0e58571af1779bcc1ffa7c9fb0839885ed69a9 \ + --hash=sha256:583849c743e0e3c9bb7446f5b5addeacedc168d657a69b418063dfdb2d90081c \ + --hash=sha256:5aee45fd2c6c0f2b9cdddf48c48535e7471e42d6fb81adfde801da0bd5b93241 \ + --hash=sha256:5b193a7e29fd9fa56e502920dca47dffe60f97c863494946bd698c6058a55658 \ + --hash=sha256:5ca74f37f3369b45e1f6b7b06afb182af1fd5dde009e4ffd831830d98cbe5fe7 \ + --hash=sha256:68549c403f79a8e25984376480959975212a670405e3913830614432b5daa07a \ + --hash=sha256:69f5bc24904d3bc3640961cddd2523e361257ef68585d6e364166dfbe8c78fae \ + --hash=sha256:6bb85c546591569558571aa1b06aba711b26ae62f111e15e56136d69920e1616 \ + --hash=sha256:6f7b7243850edd0b8b97043f04748f31de50cf426e939def5c16bedb540698f7 \ + --hash=sha256:7001dc9d5f6bb4deb756d5928eaefe1930f6f4179da3924cbd95ee0e9f4dce89 \ + --hash=sha256:7a936f1bb23d370b7c8cc079d5fce4c7d18da87a33c6744e51a93b0f9e97e9b3 \ + --hash=sha256:7c998f2ace8bf76b453b75dbcca500d4f4b9dd3908c13e89b86289b37784848b \ + --hash=sha256:7cddca31edf8b0653090cbb54562ca027c421c58ddde2c0685f49ff56a1690e0 \ + --hash=sha256:8183dc57ae7d9edc1346e007e840a9f3d6aa7b7f165203a99e16f447150140d2 \ + --hash=sha256:82745b03b4043e04600a6b665cb98697c4339b24e34d74b0a2ac0a2488b6f94d \ + --hash=sha256:841a94c66577661c1f088ac958cd767d7c9bf507698f45afffe7a4017049de76 \ + --hash=sha256:858e433f12b0e5b3ed2f8da917433b634f4937d0e8793e5cb33c54a1a01df565 \ + --hash=sha256:908a3fa6908716f803b86896a09a2c4dde5f5ce2bb07aacc71ffebb57986ce99 \ + --hash=sha256:9764014ef5e58aab76220c5664abb5d47d5bc858d9debf821e55cfdd0f128485 \ + --hash=sha256:9c7d0a77e36b5f4b01ca398482230ab792061d243d715299b44a0b55c89fe617 \ + --hash=sha256:a5b429eb84339f9f05e06083f119ad814e6d85e27ecbdf9c551dfdbb128eaf8a \ + --hash=sha256:a66fe406437dd65cacd96a72689a3aaaecaebbcd62d81c5ac1c0fdbeac835096 \ + --hash=sha256:a6b764fb312bd35e47797ad2e63f0d323792837a6ac785a4ca967019357d2bc7 \ + --hash=sha256:b19151e76620a412c2ac1c6f977ab1b9fa7ad43140178345136456d5265b32ed \ + --hash=sha256:b8438ec5594980d405251451c5b7ea9aa58dda38eb7ac35fb7e4c696712ee24f \ + --hash=sha256:b8fc3454b4f3bd0a368001d0e968852dad45a873f8b4babd41bc302ec851a099 \ + --hash=sha256:bcb8ebbf2e2c36cfe01a94f2438012c6a9d494cf80f129d9753bcdf33bfc35a6 \ + --hash=sha256:d404dc897ce10e565d647795861762aa2d06ca3f4a728c5e9a835096c7059018 \ + --hash=sha256:d612c976cbc2d17edfcc4c006874b764e85e990c29ce9bd411f926bbfb02b9a2 \ + --hash=sha256:d64177f443594c8697369c10e4bbcac70ef558e0f7921a1de7e4a3d1734bcf67 \ + --hash=sha256:d854b3970067297f3a7fbd7a4683587134aa9b3877ee15aa29eea478dc68f933 \ + --hash=sha256:d8fcccbbc0c13c13702c471da398b8cd72ba740dca5859f148ae8e0e8e0d3e7e \ + --hash=sha256:e004aa9248e8cb0a5f9b96d003ca7c1c0a5da8decd1066e7b53f59eb8ce7c62b \ + --hash=sha256:e214d546c8ecb5fc22d6e6011746082abf13a9cf46eefb45769c7b31407c97b5 \ + --hash=sha256:e2d0d88686e3d35a76f3e15a34e8c12d73fc94c1dea1cd55782e695cc14086dd \ + --hash=sha256:e2f35b4cccd9ed286ad62e0a3c3ac21e06c02abc60e20aa51a3e305a30f5fa79 \ + --hash=sha256:e3070c03701037aa418b55d36532ecb8f8446ed0135acb71c678dbdf12f5b6e4 \ + --hash=sha256:e5e088bf43f6ee6fec7dbf1ef7ff7774a616c236b5c0cb3e00662dd71a56b571 \ + --hash=sha256:e83e3f959aaa1c9df95c22c528096d94848a1bc819f5d0ebf7ee3df0ca63db6c \ + --hash=sha256:f0dcbc588cd5b725162c076eb9119342f6579c7f7f55057bb7e3c6ff27e13121 \ + --hash=sha256:f27f9da0a7d22b9f981108fd4b62f8b5743423388915a563e651c20d06c1f457 \ + --hash=sha256:f8649a14caa5f8a243628b1d61cf530ad9ae4578814ba726816adb1121fc493e \ + --hash=sha256:fac0fa4e4f55f118fd87177dacb1c6522fe39c28d498d259014020fec9164c29 \ + --hash=sha256:fd08b90d211c086181caed76931ecfa2bdfc83eea3cfccdb0f82abc6c4b876cb # via feast (pyproject.toml) -starlette==0.52.1 \ - --hash=sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74 \ - --hash=sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933 +starlette==1.0.0 \ + --hash=sha256:6a4beaf1f81bb472fd19ea9b918b50dc3a77a6f2e190a12954b25e6ed5eea149 \ + --hash=sha256:d3ec55e0bb321692d275455ddfd3df75fff145d009685eb40dc91fc66b03d38b # via fastapi -tabulate==0.9.0 \ - --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ - --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f +tabulate==0.10.0 \ + --hash=sha256:e2cfde8f79420f6deeffdeda9aaec3b6bc5abce947655d17ac662b126e48a60d \ + --hash=sha256:f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3 # via feast (pyproject.toml) tenacity==8.5.0 \ --hash=sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78 \ @@ -1295,9 +1305,9 @@ tqdm==4.67.3 \ --hash=sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb \ --hash=sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf # via feast (pyproject.toml) -typeguard==4.5.0 \ - --hash=sha256:749bea21cdb2553e12831bc29f1eae980b22c7de8331ab67ae7db9e85470b5a7 \ - --hash=sha256:cfda388fc88a9ce42a41890900d6f31ee124bea9b73bb84701a32438e92165c3 +typeguard==4.5.1 \ + --hash=sha256:44d2bf329d49a244110a090b55f5f91aa82d9a9834ebfd30bcc73651e4a8cc40 \ + --hash=sha256:f6f8ecbbc819c9bc749983cc67c02391e16a9b43b8b27f15dc70ed7c4a007274 # via feast (pyproject.toml) typing-extensions==4.15.0 \ --hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \ diff --git a/sdk/python/requirements/py3.12-ci-requirements.txt b/sdk/python/requirements/py3.12-ci-requirements.txt index e93a6c3784f..8fe44b610b6 100644 --- a/sdk/python/requirements/py3.12-ci-requirements.txt +++ b/sdk/python/requirements/py3.12-ci-requirements.txt @@ -1,8 +1,8 @@ # This file was autogenerated by uv via the following command: # uv pip compile -p 3.12 --no-strip-extras pyproject.toml --extra ci --generate-hashes --output-file sdk/python/requirements/py3.12-ci-requirements.txt -accelerate==1.12.0 \ - --hash=sha256:3e2091cd341423207e2f084a6654b1efcd250dc326f2a37d6dde446e07cabb11 \ - --hash=sha256:70988c352feb481887077d2ab845125024b2a137a5090d6d7a32b57d03a45df6 +accelerate==1.13.0 \ + --hash=sha256:cf1a3efb96c18f7b152eb0fa7490f3710b19c3f395699358f08decca2b8b62e0 \ + --hash=sha256:d631b4e0f5b3de4aff2d7e9e6857d164810dfc3237d54d017f075122d057b236 # via docling-ibm-models aiobotocore==2.23.1 \ --hash=sha256:a59f2a78629b97d52f10936b79c73de64e481a8c44a62c1871f088df6c1afc4f \ @@ -12,127 +12,127 @@ aiohappyeyeballs==2.6.1 \ --hash=sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558 \ --hash=sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8 # via aiohttp -aiohttp==3.13.3 \ - --hash=sha256:01ad2529d4b5035578f5081606a465f3b814c542882804e2e8cda61adf5c71bf \ - --hash=sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c \ - --hash=sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c \ - --hash=sha256:084911a532763e9d3dd95adf78a78f4096cd5f58cdc18e6fdbc1b58417a45423 \ - --hash=sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f \ - --hash=sha256:0db318f7a6f065d84cb1e02662c526294450b314a02bd9e2a8e67f0d8564ce40 \ - --hash=sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2 \ - --hash=sha256:1449ceddcdbcf2e0446957863af03ebaaa03f94c090f945411b61269e2cb5daf \ - --hash=sha256:147e422fd1223005c22b4fe080f5d93ced44460f5f9c105406b753612b587821 \ - --hash=sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64 \ - --hash=sha256:215a685b6fbbfcf71dfe96e3eba7a6f58f10da1dfdf4889c7dd856abe430dca7 \ - --hash=sha256:2712039939ec963c237286113c68dbad80a82a4281543f3abf766d9d73228998 \ - --hash=sha256:27234ef6d85c914f9efeb77ff616dbf4ad2380be0cda40b4db086ffc7ddd1b7d \ - --hash=sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea \ - --hash=sha256:2b8d8ddba8f95ba17582226f80e2de99c7a7948e66490ef8d947e272a93e9463 \ - --hash=sha256:2ba0eea45eb5cc3172dbfc497c066f19c41bac70963ea1a67d51fc92e4cf9a80 \ - --hash=sha256:2be0e9ccf23e8a94f6f0650ce06042cefc6ac703d0d7ab6c7a917289f2539ad4 \ - --hash=sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767 \ - --hash=sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43 \ - --hash=sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592 \ - --hash=sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a \ - --hash=sha256:31a83ea4aead760dfcb6962efb1d861db48c34379f2ff72db9ddddd4cda9ea2e \ - --hash=sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687 \ - --hash=sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8 \ - --hash=sha256:37239e9f9a7ea9ac5bf6b92b0260b01f8a22281996da609206a84df860bc1261 \ - --hash=sha256:37da61e244d1749798c151421602884db5270faf479cf0ef03af0ff68954c9dd \ - --hash=sha256:3b61b7169ababd7802f9568ed96142616a9118dd2be0d1866e920e77ec8fa92a \ - --hash=sha256:3d9908a48eb7416dc1f4524e69f1d32e5d90e3981e4e37eb0aa1cd18f9cfa2a4 \ - --hash=sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587 \ - --hash=sha256:4021b51936308aeea0367b8f006dc999ca02bc118a0cc78c303f50a2ff6afb91 \ - --hash=sha256:40c5e40ecc29ba010656c18052b877a1c28f84344825efa106705e835c28530f \ - --hash=sha256:425c126c0dc43861e22cb1c14ba4c8e45d09516d0a3ae0a3f7494b79f5f233a3 \ - --hash=sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344 \ - --hash=sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6 \ - --hash=sha256:49a03727c1bba9a97d3e93c9f93ca03a57300f484b6e935463099841261195d3 \ - --hash=sha256:4ae5b5a0e1926e504c81c5b84353e7a5516d8778fbbff00429fe7b05bb25cbce \ - --hash=sha256:4e239d501f73d6db1522599e14b9b321a7e3b1de66ce33d53a765d975e9f4808 \ - --hash=sha256:56339a36b9f1fc708260c76c87e593e2afb30d26de9ae1eb445b5e051b98a7a1 \ - --hash=sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29 \ - --hash=sha256:5b179331a481cb5529fca8b432d8d3c7001cb217513c94cd72d668d1248688a3 \ - --hash=sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b \ - --hash=sha256:5d2d94f1f5fcbe40838ac51a6ab5704a6f9ea42e72ceda48de5e6b898521da51 \ - --hash=sha256:5dff64413671b0d3e7d5918ea490bdccb97a4ad29b3f311ed423200b2203e01c \ - --hash=sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926 \ - --hash=sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64 \ - --hash=sha256:642f752c3eb117b105acbd87e2c143de710987e09860d674e068c4c2c441034f \ - --hash=sha256:65d2ccb7eabee90ce0503c17716fc77226be026dcc3e65cce859a30db715025b \ - --hash=sha256:693781c45a4033d31d4187d2436f5ac701e7bbfe5df40d917736108c1cc7436e \ - --hash=sha256:694976222c711d1d00ba131904beb60534f93966562f64440d0c9d41b8cdb440 \ - --hash=sha256:697753042d57f4bf7122cab985bf15d0cef23c770864580f5af4f52023a56bd6 \ - --hash=sha256:69c56fbc1993fa17043e24a546959c0178fe2b5782405ad4559e6c13975c15e3 \ - --hash=sha256:6de499a1a44e7de70735d0b39f67c8f25eb3d91eb3103be99ca0fa882cdd987d \ - --hash=sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415 \ - --hash=sha256:75ca857eba4e20ce9f546cd59c7007b33906a4cd48f2ff6ccf1ccfc3b646f279 \ - --hash=sha256:7a4a94eb787e606d0a09404b9c38c113d3b099d508021faa615d70a0131907ce \ - --hash=sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603 \ - --hash=sha256:7bfdc049127717581866fa4708791220970ce291c23e28ccf3922c700740fdc0 \ - --hash=sha256:7e63f210bc1b57ef699035f2b4b6d9ce096b5914414a49b0997c839b2bd2223c \ - --hash=sha256:7f9120f7093c2a32d9647abcaf21e6ad275b4fbec5b55969f978b1a97c7c86bf \ - --hash=sha256:8057c98e0c8472d8846b9c79f56766bcc57e3e8ac7bfd510482332366c56c591 \ - --hash=sha256:80dd4c21b0f6237676449c6baaa1039abae86b91636b6c91a7f8e61c87f89540 \ - --hash=sha256:81e97251d9298386c2b7dbeb490d3d1badbdc69107fb8c9299dd04eb39bddc0e \ - --hash=sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26 \ - --hash=sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a \ - --hash=sha256:859bd3f2156e81dd01432f5849fc73e2243d4a487c4fd26609b1299534ee1845 \ - --hash=sha256:87797e645d9d8e222e04160ee32aa06bc5c163e8499f24db719e7852ec23093a \ - --hash=sha256:87b9aab6d6ed88235aa2970294f496ff1a1f9adcd724d800e9b952395a80ffd9 \ - --hash=sha256:8a60e60746623925eab7d25823329941aee7242d559baa119ca2b253c88a7bd6 \ - --hash=sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba \ - --hash=sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df \ - --hash=sha256:947c26539750deeaee933b000fb6517cc770bbd064bad6033f1cff4803881e43 \ - --hash=sha256:96d604498a7c782cb15a51c406acaea70d8c027ee6b90c569baa6e7b93073679 \ - --hash=sha256:988a8c5e317544fdf0d39871559e67b6341065b87fceac641108c2096d5506b7 \ - --hash=sha256:9a9dc347e5a3dc7dfdbc1f82da0ef29e388ddb2ed281bfce9dd8248a313e62b7 \ - --hash=sha256:9ae8dd55c8e6c4257eae3a20fd2c8f41edaea5992ed67156642493b8daf3cecc \ - --hash=sha256:9af5e68ee47d6534d36791bbe9b646d2a7c7deb6fc24d7943628edfbb3581f29 \ - --hash=sha256:9b174f267b5cfb9a7dba9ee6859cecd234e9a681841eb85068059bc867fb8f02 \ - --hash=sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984 \ - --hash=sha256:9d4c940f02f49483b18b079d1c27ab948721852b281f8b015c058100e9421dd1 \ - --hash=sha256:9ebf57d09e131f5323464bd347135a88622d1c0976e88ce15b670e7ad57e4bd6 \ - --hash=sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632 \ - --hash=sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56 \ - --hash=sha256:a2212ad43c0833a873d0fb3c63fa1bacedd4cf6af2fee62bf4b739ceec3ab239 \ - --hash=sha256:a45530014d7a1e09f4a55f4f43097ba0fd155089372e105e4bff4ca76cb1b168 \ - --hash=sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88 \ - --hash=sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc \ - --hash=sha256:af71fff7bac6bb7508956696dce8f6eec2bbb045eceb40343944b1ae62b5ef11 \ - --hash=sha256:b04be762396457bef43f3597c991e192ee7da460a4953d7e647ee4b1c28e7046 \ - --hash=sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0 \ - --hash=sha256:b1a6102b4d3ebc07dad44fbf07b45bb600300f15b552ddf1851b5390202ea2e3 \ - --hash=sha256:b46020d11d23fe16551466c77823df9cc2f2c1e63cc965daf67fa5eec6ca1877 \ - --hash=sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1 \ - --hash=sha256:b903a4dfee7d347e2d87697d0713be59e0b87925be030c9178c5faa58ea58d5c \ - --hash=sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25 \ - --hash=sha256:b99281b0704c103d4e11e72a76f1b543d4946fea7dd10767e7e1b5f00d4e5704 \ - --hash=sha256:bae5c2ed2eae26cc382020edad80d01f36cb8e746da40b292e68fec40421dc6a \ - --hash=sha256:bb4f7475e359992b580559e008c598091c45b5088f28614e855e42d39c2f1033 \ - --hash=sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1 \ - --hash=sha256:bfc1cc2fe31a6026a8a88e4ecfb98d7f6b1fec150cfd708adbfd1d2f42257c29 \ - --hash=sha256:c014c7ea7fb775dd015b2d3137378b7be0249a448a1612268b5a90c2d81de04d \ - --hash=sha256:c048058117fd649334d81b4b526e94bde3ccaddb20463a815ced6ecbb7d11160 \ - --hash=sha256:c0e2d366af265797506f0283487223146af57815b388623f0357ef7eac9b209d \ - --hash=sha256:c19b90316ad3b24c69cd78d5c9b4f3aa4497643685901185b65166293d36a00f \ - --hash=sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f \ - --hash=sha256:c6b8568a3bb5819a0ad087f16d40e5a3fb6099f39ea1d5625a3edc1e923fc538 \ - --hash=sha256:d32764c6c9aafb7fb55366a224756387cd50bfa720f32b88e0e6fa45b27dcf29 \ - --hash=sha256:d5a372fd5afd301b3a89582817fdcdb6c34124787c70dbcc616f259013e7eef7 \ - --hash=sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72 \ - --hash=sha256:dca68018bf48c251ba17c72ed479f4dafe9dbd5a73707ad8d28a38d11f3d42af \ - --hash=sha256:de2c184bb1fe2cbd2cefba613e9db29a5ab559323f994b6737e370d3da0ac455 \ - --hash=sha256:e3531d63d3bdfa7e3ac5e9b27b2dd7ec9df3206a98e0b3445fa906f233264c57 \ - --hash=sha256:e50a2e1404f063427c9d027378472316201a2290959a295169bcf25992d04558 \ - --hash=sha256:e636b3c5f61da31a92bf0d91da83e58fdfa96f178ba682f11d24f31944cdd28c \ - --hash=sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808 \ - --hash=sha256:f33ed1a2bf1997a36661874b017f5c4b760f41266341af36febaf271d179f6d7 \ - --hash=sha256:f76c1e3fe7d7c8afad7ed193f89a292e1999608170dcc9751a7462a87dfd5bc0 \ - --hash=sha256:f9444f105664c4ce47a2a7171a2418bce5b7bae45fb610f4e2c36045d85911d3 \ - --hash=sha256:fc290605db2a917f6e81b0e1e0796469871f5af381ce15c604a3c5c7e51cb730 \ - --hash=sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa \ - --hash=sha256:fee0c6bc7db1de362252affec009707a17478a00ec69f797d23ca256e36d5940 +aiohttp==3.13.5 \ + --hash=sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5 \ + --hash=sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b \ + --hash=sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9 \ + --hash=sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b \ + --hash=sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8 \ + --hash=sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a \ + --hash=sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2 \ + --hash=sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1 \ + --hash=sha256:147b4f501d0292077f29d5268c16bb7c864a1f054d7001c4c1812c0421ea1ed0 \ + --hash=sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037 \ + --hash=sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416 \ + --hash=sha256:178c7b5e62b454c2bc790786e6058c3cc968613b4419251b478c153a4aec32b1 \ + --hash=sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9 \ + --hash=sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a \ + --hash=sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36 \ + --hash=sha256:206b7b3ef96e4ce211754f0cd003feb28b7d81f0ad26b8d077a5d5161436067f \ + --hash=sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b \ + --hash=sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174 \ + --hash=sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b \ + --hash=sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8 \ + --hash=sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e \ + --hash=sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6 \ + --hash=sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c \ + --hash=sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe \ + --hash=sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9 \ + --hash=sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc \ + --hash=sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800 \ + --hash=sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286 \ + --hash=sha256:347542f0ea3f95b2a955ee6656461fa1c776e401ac50ebce055a6c38454a0adf \ + --hash=sha256:39380e12bd1f2fdab4285b6e055ad48efbaed5c836433b142ed4f5b9be71036a \ + --hash=sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc \ + --hash=sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9 \ + --hash=sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665 \ + --hash=sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832 \ + --hash=sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297 \ + --hash=sha256:4e704c52438f66fdd89588346183d898bb42167cf88f8b7ff1c0f9fc957c348f \ + --hash=sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73 \ + --hash=sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b \ + --hash=sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9 \ + --hash=sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090 \ + --hash=sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49 \ + --hash=sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d \ + --hash=sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46 \ + --hash=sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83 \ + --hash=sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796 \ + --hash=sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be \ + --hash=sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d \ + --hash=sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf \ + --hash=sha256:6f497a6876aa4b1a102b04996ce4c1170c7040d83faa9387dd921c16e30d5c83 \ + --hash=sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25 \ + --hash=sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06 \ + --hash=sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3 \ + --hash=sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6 \ + --hash=sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb \ + --hash=sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88 \ + --hash=sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9 \ + --hash=sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be \ + --hash=sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14 \ + --hash=sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a \ + --hash=sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c \ + --hash=sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3 \ + --hash=sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f \ + --hash=sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d \ + --hash=sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670 \ + --hash=sha256:912d4b6af530ddb1338a66229dac3a25ff11d4448be3ec3d6340583995f56031 \ + --hash=sha256:9277145d36a01653863899c665243871434694bcc3431922c3b35c978061bdb8 \ + --hash=sha256:95d14ca7abefde230f7639ec136ade282655431fd5db03c343b19dda72dd1643 \ + --hash=sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d \ + --hash=sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8 \ + --hash=sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8 \ + --hash=sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1 \ + --hash=sha256:9efcc0f11d850cefcafdd9275b9576ad3bfb539bed96807663b32ad99c4d4b88 \ + --hash=sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb \ + --hash=sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61 \ + --hash=sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4 \ + --hash=sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7 \ + --hash=sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9 \ + --hash=sha256:a8a4d3427e8de1312ddf309cc482186466c79895b3a139fed3259fc01dfa9a5b \ + --hash=sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500 \ + --hash=sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6 \ + --hash=sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2 \ + --hash=sha256:af545c2cffdb0967a96b6249e6f5f7b0d92cdfd267f9d5238d5b9ca63e8edb10 \ + --hash=sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1 \ + --hash=sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3 \ + --hash=sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e \ + --hash=sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a \ + --hash=sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5 \ + --hash=sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95 \ + --hash=sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074 \ + --hash=sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5 \ + --hash=sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b \ + --hash=sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772 \ + --hash=sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a \ + --hash=sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274 \ + --hash=sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94 \ + --hash=sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13 \ + --hash=sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac \ + --hash=sha256:cb979826071c0986a5f08333a36104153478ce6018c58cba7f9caddaf63d5d67 \ + --hash=sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76 \ + --hash=sha256:d147004fede1b12f6013a6dbb2a26a986a671a03c6ea740ddc76500e5f1c399f \ + --hash=sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8 \ + --hash=sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7 \ + --hash=sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8 \ + --hash=sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3 \ + --hash=sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be \ + --hash=sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b \ + --hash=sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c \ + --hash=sha256:e999f0c88a458c836d5fb521814e92ed2172c649200336a6df514987c1488258 \ + --hash=sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c \ + --hash=sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6 \ + --hash=sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56 \ + --hash=sha256:ee5e86776273de1795947d17bddd6bb19e0365fd2af4289c0d2c5454b6b1d36b \ + --hash=sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d \ + --hash=sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a \ + --hash=sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162 \ + --hash=sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1 \ + --hash=sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6 \ + --hash=sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5 \ + --hash=sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540 \ + --hash=sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254 # via # aiobotocore # aiohttp-cors @@ -166,9 +166,9 @@ annotated-types==0.7.0 \ --hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \ --hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89 # via pydantic -anyio==4.12.1 \ - --hash=sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703 \ - --hash=sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c +anyio==4.13.0 \ + --hash=sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708 \ + --hash=sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc # via # elasticsearch # httpx @@ -230,9 +230,9 @@ asttokens==3.0.1 \ --hash=sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a \ --hash=sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7 # via stack-data -async-lru==2.1.0 \ - --hash=sha256:9eeb2fecd3fe42cc8a787fc32ead53a3a7158cc43d039c3c55ab3e4e5b2a80ed \ - --hash=sha256:fa12dcf99a42ac1280bc16c634bbaf06883809790f6304d85cdab3f666f33a7e +async-lru==2.3.0 \ + --hash=sha256:89bdb258a0140d7313cf8f4031d816a042202faa61d0ab310a0a538baa1c24b6 \ + --hash=sha256:eea27b01841909316f2cc739807acea1c623df2be8c5cfad7583286397bb8315 # via jupyterlab async-property==0.2.2 \ --hash=sha256:17d9bd6ca67e27915a75d92549df64b5c7174e9dc806b30a3934dc4ff0506380 \ @@ -242,24 +242,24 @@ atpublic==7.0.0 \ --hash=sha256:466ef10d0c8bbd14fd02a5fbd5a8b6af6a846373d91106d3a07c16d72d96b63e \ --hash=sha256:6702bd9e7245eb4e8220a3e222afcef7f87412154732271ee7deee4433b72b4b # via ibis-framework -attrs==25.4.0 \ - --hash=sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11 \ - --hash=sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373 +attrs==26.1.0 \ + --hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \ + --hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32 # via # aiohttp # jsonlines # jsonschema # openlineage-python # referencing -azure-core==1.38.1 \ - --hash=sha256:69f08ee3d55136071b7100de5b198994fc1c5f89d2b91f2f43156d20fcf200a4 \ - --hash=sha256:9317db1d838e39877eb94a2240ce92fa607db68adf821817b723f0d679facbf6 +azure-core==1.39.0 \ + --hash=sha256:4ac7b70fab5438c3f68770649a78daf97833caa83827f91df9c14e0e0ea7d34f \ + --hash=sha256:8a90a562998dd44ce84597590fff6249701b98c0e8797c95fcdd695b54c35d74 # via # azure-identity # azure-storage-blob -azure-identity==1.25.2 \ - --hash=sha256:030dbaa720266c796221c6cdbd1999b408c079032c919fef725fcc348a540fe9 \ - --hash=sha256:1b40060553d01a72ba0d708b9a46d0f61f56312e215d8896d836653ffdc6753d +azure-identity==1.25.3 \ + --hash=sha256:ab23c0d63015f50b630ef6c6cf395e7262f439ce06e5d07a64e874c724f8d9e6 \ + --hash=sha256:f4d0b956a8146f30333e071374171f3cfa7bdb8073adb8c3814b65567aa7447c # via feast (pyproject.toml) azure-storage-blob==12.28.0 \ --hash=sha256:00fb1db28bf6a7b7ecaa48e3b1d5c83bfadacc5a678b77826081304bd87d6461 \ @@ -342,9 +342,9 @@ beautifulsoup4==4.14.3 \ # via # docling # nbconvert -bigtree==1.3.1 \ - --hash=sha256:a22a0ecd9b0abb283f4a1515370dbf1ec93adee70746767272e2c49d7af9f407 \ - --hash=sha256:c8b766b00188c532d3499bfd9e9666b357428db507fc701f088031a0d5c614d5 +bigtree==1.4.0 \ + --hash=sha256:d0d99550ae64ce4529f132602ab875c2ab472c96c942f5704f8c72a17450d3ea \ + --hash=sha256:e5ae2e948168da671d99601c9ed87ab3b48d9d4ea8a98f111e5748e98064c31c # via feast (pyproject.toml) bleach[css]==6.3.0 \ --hash=sha256:6f3b91b1c0a02bb9a78b5a454c92506aa0fdf197e1d5e114d2e00c6f64306d22 \ @@ -355,7 +355,6 @@ boto3==1.38.27 \ --hash=sha256:95f5fe688795303a8a15e8b7e7f255cadab35eae459d00cc281a4fd77252ea80 # via # feast (pyproject.toml) - # ikvpy # moto # snowflake-connector-python botocore==1.38.46 \ @@ -367,12 +366,11 @@ botocore==1.38.46 \ # moto # s3transfer # snowflake-connector-python -build==1.4.0 \ - --hash=sha256:6a07c1b8eb6f2b311b96fcbdbce5dab5fe637ffda0fd83c9cac622e927501596 \ - --hash=sha256:f1b91b925aa322be454f8330c6fb48b465da993d1e7e7e6fa35027ec49f3c936 +build==1.4.2 \ + --hash=sha256:35b14e1ee329c186d3f08466003521ed7685ec15ecffc07e68d706090bf161d1 \ + --hash=sha256:7a4d8651ea877cb2a89458b1b198f2e69f536c95e89129dbf5d448045d60db88 # via # feast (pyproject.toml) - # openlineage-python # pip-tools # singlestoredb cassandra-driver==3.29.3 \ @@ -408,9 +406,9 @@ cassandra-driver==3.29.3 \ --hash=sha256:fcf45725ae1751cb934b9b827a7d9cd899bbd09eb1ad28e2160b4584de35ba77 \ --hash=sha256:ff6b82ee4533f6fd4474d833e693b44b984f58337173ee98ed76bce08721a636 # via feast (pyproject.toml) -certifi==2026.1.4 \ - --hash=sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c \ - --hash=sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120 +certifi==2026.2.25 \ + --hash=sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa \ + --hash=sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7 # via # clickhouse-connect # docling @@ -510,132 +508,147 @@ cffi==2.0.0 \ # feast (pyproject.toml) # argon2-cffi-bindings # cryptography - # ikvpy # pynacl cfgv==3.5.0 \ --hash=sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0 \ --hash=sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132 # via pre-commit -charset-normalizer==3.4.4 \ - --hash=sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad \ - --hash=sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93 \ - --hash=sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394 \ - --hash=sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89 \ - --hash=sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc \ - --hash=sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86 \ - --hash=sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63 \ - --hash=sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d \ - --hash=sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f \ - --hash=sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8 \ - --hash=sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0 \ - --hash=sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505 \ - --hash=sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161 \ - --hash=sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af \ - --hash=sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152 \ - --hash=sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318 \ - --hash=sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72 \ - --hash=sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4 \ - --hash=sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e \ - --hash=sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3 \ - --hash=sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576 \ - --hash=sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c \ - --hash=sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1 \ - --hash=sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8 \ - --hash=sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1 \ - --hash=sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2 \ - --hash=sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44 \ - --hash=sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26 \ - --hash=sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88 \ - --hash=sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016 \ - --hash=sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede \ - --hash=sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf \ - --hash=sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a \ - --hash=sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc \ - --hash=sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0 \ - --hash=sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84 \ - --hash=sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db \ - --hash=sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1 \ - --hash=sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7 \ - --hash=sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed \ - --hash=sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8 \ - --hash=sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133 \ - --hash=sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e \ - --hash=sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef \ - --hash=sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14 \ - --hash=sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2 \ - --hash=sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0 \ - --hash=sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d \ - --hash=sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828 \ - --hash=sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f \ - --hash=sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf \ - --hash=sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6 \ - --hash=sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328 \ - --hash=sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090 \ - --hash=sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa \ - --hash=sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381 \ - --hash=sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c \ - --hash=sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb \ - --hash=sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc \ - --hash=sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a \ - --hash=sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec \ - --hash=sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc \ - --hash=sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac \ - --hash=sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e \ - --hash=sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313 \ - --hash=sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569 \ - --hash=sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3 \ - --hash=sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d \ - --hash=sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525 \ - --hash=sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894 \ - --hash=sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3 \ - --hash=sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9 \ - --hash=sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a \ - --hash=sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9 \ - --hash=sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14 \ - --hash=sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25 \ - --hash=sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50 \ - --hash=sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf \ - --hash=sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1 \ - --hash=sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3 \ - --hash=sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac \ - --hash=sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e \ - --hash=sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815 \ - --hash=sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c \ - --hash=sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6 \ - --hash=sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6 \ - --hash=sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e \ - --hash=sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4 \ - --hash=sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84 \ - --hash=sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69 \ - --hash=sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15 \ - --hash=sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191 \ - --hash=sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0 \ - --hash=sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897 \ - --hash=sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd \ - --hash=sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2 \ - --hash=sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794 \ - --hash=sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d \ - --hash=sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074 \ - --hash=sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3 \ - --hash=sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224 \ - --hash=sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838 \ - --hash=sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a \ - --hash=sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d \ - --hash=sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d \ - --hash=sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f \ - --hash=sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8 \ - --hash=sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490 \ - --hash=sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966 \ - --hash=sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9 \ - --hash=sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3 \ - --hash=sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e \ - --hash=sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608 +charset-normalizer==3.4.7 \ + --hash=sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc \ + --hash=sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c \ + --hash=sha256:07d9e39b01743c3717745f4c530a6349eadbfa043c7577eef86c502c15df2c67 \ + --hash=sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4 \ + --hash=sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0 \ + --hash=sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c \ + --hash=sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5 \ + --hash=sha256:12a6fff75f6bc66711b73a2f0addfc4c8c15a20e805146a02d147a318962c444 \ + --hash=sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153 \ + --hash=sha256:14265bfe1f09498b9d8ec91e9ec9fa52775edf90fcbde092b25f4a33d444fea9 \ + --hash=sha256:16d971e29578a5e97d7117866d15889a4a07befe0e87e703ed63cd90cb348c01 \ + --hash=sha256:177a0ba5f0211d488e295aaf82707237e331c24788d8d76c96c5a41594723217 \ + --hash=sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b \ + --hash=sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c \ + --hash=sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a \ + --hash=sha256:1dc8b0ea451d6e69735094606991f32867807881400f808a106ee1d963c46a83 \ + --hash=sha256:1efde3cae86c8c273f1eb3b287be7d8499420cf2fe7585c41d370d3e790054a5 \ + --hash=sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7 \ + --hash=sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb \ + --hash=sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c \ + --hash=sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1 \ + --hash=sha256:2cd4a60d0e2fb04537162c62bbbb4182f53541fe0ede35cdf270a1c1e723cc42 \ + --hash=sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab \ + --hash=sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df \ + --hash=sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e \ + --hash=sha256:320ade88cfb846b8cd6b4ddf5ee9e80ee0c1f52401f2456b84ae1ae6a1a5f207 \ + --hash=sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18 \ + --hash=sha256:36836d6ff945a00b88ba1e4572d721e60b5b8c98c155d465f56ad19d68f23734 \ + --hash=sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38 \ + --hash=sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110 \ + --hash=sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18 \ + --hash=sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44 \ + --hash=sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d \ + --hash=sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48 \ + --hash=sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e \ + --hash=sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5 \ + --hash=sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d \ + --hash=sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53 \ + --hash=sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790 \ + --hash=sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c \ + --hash=sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b \ + --hash=sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116 \ + --hash=sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d \ + --hash=sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10 \ + --hash=sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6 \ + --hash=sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2 \ + --hash=sha256:6370e8686f662e6a3941ee48ed4742317cafbe5707e36406e9df792cdb535776 \ + --hash=sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a \ + --hash=sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265 \ + --hash=sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008 \ + --hash=sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943 \ + --hash=sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374 \ + --hash=sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246 \ + --hash=sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e \ + --hash=sha256:6e0d51f618228538a3e8f46bd246f87a6cd030565e015803691603f55e12afb5 \ + --hash=sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616 \ + --hash=sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15 \ + --hash=sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41 \ + --hash=sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960 \ + --hash=sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752 \ + --hash=sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e \ + --hash=sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72 \ + --hash=sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7 \ + --hash=sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8 \ + --hash=sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b \ + --hash=sha256:813c0e0132266c08eb87469a642cb30aaff57c5f426255419572aaeceeaa7bf4 \ + --hash=sha256:82b271f5137d07749f7bf32f70b17ab6eaabedd297e75dce75081a24f76eb545 \ + --hash=sha256:84c018e49c3bf790f9c2771c45e9313a08c2c2a6342b162cd650258b57817706 \ + --hash=sha256:8751d2787c9131302398b11e6c8068053dcb55d5a8964e114b6e196cf16cb366 \ + --hash=sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb \ + --hash=sha256:87fad7d9ba98c86bcb41b2dc8dbb326619be2562af1f8ff50776a39e55721c5a \ + --hash=sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e \ + --hash=sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00 \ + --hash=sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f \ + --hash=sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a \ + --hash=sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1 \ + --hash=sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66 \ + --hash=sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356 \ + --hash=sha256:a6c5863edfbe888d9eff9c8b8087354e27618d9da76425c119293f11712a6319 \ + --hash=sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4 \ + --hash=sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad \ + --hash=sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d \ + --hash=sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5 \ + --hash=sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7 \ + --hash=sha256:aef65cd602a6d0e0ff6f9930fcb1c8fec60dd2cfcb6facaf4bdb0e5873042db0 \ + --hash=sha256:af21eb4409a119e365397b2adbaca4c9ccab56543a65d5dbd9f920d6ac29f686 \ + --hash=sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34 \ + --hash=sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49 \ + --hash=sha256:bb8cc7534f51d9a017b93e3e85b260924f909601c3df002bcdb58ddb4dc41a5c \ + --hash=sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1 \ + --hash=sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e \ + --hash=sha256:bd9b23791fe793e4968dba0c447e12f78e425c59fc0e3b97f6450f4781f3ee60 \ + --hash=sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0 \ + --hash=sha256:c0f081d69a6e58272819b70288d3221a6ee64b98df852631c80f293514d3b274 \ + --hash=sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d \ + --hash=sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0 \ + --hash=sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae \ + --hash=sha256:c593052c465475e64bbfe5dbd81680f64a67fdc752c56d7a0ae205dc8aeefe0f \ + --hash=sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d \ + --hash=sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe \ + --hash=sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3 \ + --hash=sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393 \ + --hash=sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1 \ + --hash=sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af \ + --hash=sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44 \ + --hash=sha256:d61f00a0869d77422d9b2aba989e2d24afa6ffd552af442e0e58de4f35ea6d00 \ + --hash=sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c \ + --hash=sha256:dca4bbc466a95ba9c0234ef56d7dd9509f63da22274589ebd4ed7f1f4d4c54e3 \ + --hash=sha256:dd915403e231e6b1809fe9b6d9fc55cf8fb5e02765ac625d9cd623342a7905d7 \ + --hash=sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd \ + --hash=sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e \ + --hash=sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b \ + --hash=sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8 \ + --hash=sha256:e5f4d355f0a2b1a31bc3edec6795b46324349c9cb25eed068049e4f472fb4259 \ + --hash=sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859 \ + --hash=sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46 \ + --hash=sha256:e80c8378d8f3d83cd3164da1ad2df9e37a666cdde7b1cb2298ed0b558064be30 \ + --hash=sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b \ + --hash=sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46 \ + --hash=sha256:ed065083d0898c9d5b4bbec7b026fd755ff7454e6e8b73a67f8c744b13986e24 \ + --hash=sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a \ + --hash=sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24 \ + --hash=sha256:f22dec1690b584cea26fade98b2435c132c1b5f68e39f5a0b7627cd7ae31f1dc \ + --hash=sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215 \ + --hash=sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063 \ + --hash=sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832 \ + --hash=sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6 \ + --hash=sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79 \ + --hash=sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464 # via # requests # snowflake-connector-python -click==8.2.1 \ - --hash=sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202 \ - --hash=sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b +click==8.3.1 \ + --hash=sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a \ + --hash=sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6 # via # feast (pyproject.toml) # dask @@ -645,74 +658,82 @@ click==8.2.1 \ # ray # typer # uvicorn -clickhouse-connect==0.11.0 \ - --hash=sha256:00c525036aeb968c578a7e32bf3d4acbac4f91a3748b39921a654dbbf8fae482 \ - --hash=sha256:035d66337654c7d7812e43910195d0c1ab2e64512a98407a51ee5860d7f32289 \ - --hash=sha256:0e1de4b74dbfd75b4990267a6168e1181130b2a255c1250e40f6aa922a147b4d \ - --hash=sha256:0e857234d6f91ce30dd4f3f6dfd0b84c83057cf45686a86eab1912c3991ce8b1 \ - --hash=sha256:0fdd59e35164472404ddddf4407903e516dd11c929f248846dd2993e2c005774 \ - --hash=sha256:121cb63648ee812582c8691bc1c4bd3f4c5ee1220278f32fb3d2bf581cb5fe2b \ - --hash=sha256:19b60f592b9de67c366d1459a2c73ded0955a9b0ccde265a1f9aa237c1e1c89f \ - --hash=sha256:242f891559a2b0c4b9eb37cad5181b6141c521763b10c8025a105826ae0c6957 \ - --hash=sha256:2853493849e59ccf60a095915f9a8d70f539853fc4536260f21720a6c495e339 \ - --hash=sha256:2dbc742bc0c7db72ca88bb5e67bf1959c60dfe1ed3376bf4c48e35b026374a97 \ - --hash=sha256:2dd49ac4d0d59a836ceda8b2c6b7f348accf2512f81d46543fc33f3b64c55152 \ - --hash=sha256:2e8f339f7fbd1880d67e5a8d07dfaecd4cd0f5bf6c77ae3e254030b2a7e71f53 \ - --hash=sha256:3b0196d4a7f6cd76dc57cf178f4dee2e92c08daa6e77def88d95604cf715b913 \ - --hash=sha256:3e5d64a10f2938ac3e84194c6dd312a42c62f875d6f0be00bc73d337d2115570 \ - --hash=sha256:40267a3b72c3d26b5e062d1858183d1b7c2ff8142457b6962a5826f726ba8ba8 \ - --hash=sha256:4196a2caad25ea83cfbc627306daa4345c9b44ce4dd247dc462842da5f10630f \ - --hash=sha256:470d5ab8f2cd9835feb4198c6fbd80730b52257fad23a20dbc7e4ab0c0ab1c2f \ - --hash=sha256:49898f30c94dfac1d655e32f3ca829f98344384b470f29dc46532ad2285b2fad \ - --hash=sha256:4b1ab7542701f8e76742da18eaac31a5c7b49ebab4020be90d1129a222de0dd5 \ - --hash=sha256:524afd5a64fd9fd53184ec14ad1a69ea89e1fa8373c89350b53c38982232aa45 \ - --hash=sha256:55d23aa3a68617323ea23440dcdcd6d85f47ac239076aa83c568ffdf28e41348 \ - --hash=sha256:55e08de1df514dc6b40fbf6264020750fea191343ad1c645ed5e7a1da5c9e78f \ - --hash=sha256:64662538e91077de6b73991e39ab0d90b0465cd510eb23ff4b2013c81a620063 \ - --hash=sha256:66bc5ed12b7a09e4ed68053eb3150c6243b6a1d82addb243bb3c6b75f48efefa \ - --hash=sha256:68cb75f902cf0bfa150ba4ebba01a831af62d54270e74ee7349c6dd62db40300 \ - --hash=sha256:69bf8935c8b4dd6455483ae4713ee21230bf6abe84a173e5587d8b9bb862bb7c \ - --hash=sha256:75924dcefba9727c39660ac0e94585fba44877839b026de7cdbf74e6c4e05b78 \ - --hash=sha256:76ad068e7b73c27eae7e620dd0bbbb95cf8089ecb661b50a02af771f845649a8 \ - --hash=sha256:7c24ae9f88caf9cb503c4641051cb89978cb677e0db0e1ef28eb3e3615e1473f \ - --hash=sha256:7c78caf3aeeed4243843be887a3056f0b0ef5d148f2035e2bd8decd3f8760399 \ - --hash=sha256:7e6b23587c7ef5c33c22b830e9ad93d0cc90d498526aec970467cac51065cfd7 \ - --hash=sha256:83478aa71633e1bc555c8607d6716c365d2e7bfdb1296588f386e29b464983cc \ - --hash=sha256:9159ac864c0fadd785de64aabf875e8bb1a97303871dff745a5ae647cc7d449f \ - --hash=sha256:9c16c54d3ae023a85ca278609c3a1fef9ccbfaa3d96c1a7d789b3c7faaf32262 \ - --hash=sha256:9d3174b1944391777d4549c29a88dbb5214e4ef7194d3cfcd3d338706f58d6bc \ - --hash=sha256:a27bf20184c491d42501989f04fa0228e4b062dd9b09b0ff9766a7968b92dcfb \ - --hash=sha256:acc1009501b651504aa7c6c0d1e21dd0974d1c36a77b10407c31c91fef359ffe \ - --hash=sha256:ad76bf2b433836d3730052113b357cfcb62accefd145b822bbf0fd0e537047c1 \ - --hash=sha256:b4730b1ac6f4d932628f44609ac4754b642d1138eb9f0c3934e7cfe344dfc590 \ - --hash=sha256:c00e38d3d621b3e14f2566257c4b95efc7769cb0673172ae0aeeb9114169dc62 \ - --hash=sha256:c109c35964bff0b0ed8adaa47d3a07d620188b451c4f7a1cbfda7e4d2db852d6 \ - --hash=sha256:c1f3daf18324c3ac4c56ddc594bc122dd9512c55df9410ae08a4df325e63df03 \ - --hash=sha256:c522fd0ee6adc0c9bac97cd4c079993301b79919dfdacfb6310eecfb62c050e7 \ - --hash=sha256:c6f19acaf8b2de034bae55ab82e154ed9194c5c5d454fde72012e9f44e9c52fa \ - --hash=sha256:cc0dfa69da660fa2847c79c0698e0ebfb5309afae14b53fb29121475860cfacb \ - --hash=sha256:d783d69eadc8d1b5f6581e3e1d82e8ea0af8f9a2386c795d35b4a2ac845f6f5a \ - --hash=sha256:d94a8e8e66e3a97ac4e7bbfce2a8a27f8b56d87bfa32739cac209159f5c186eb \ - --hash=sha256:dc91654e353b22980d4e34ca212e1eaa063b047110f8db7d1739a7ca8fbb44e6 \ - --hash=sha256:dceb4201905993dcf7efa56678d30c12f82c195c14249292b9f381bd91940f65 \ - --hash=sha256:dd1f9d8ac9b95027a36ba66e00bf82297e041e8682e68bc1dc5a4ab08d091e28 \ - --hash=sha256:de312c2a1be01c3015e8ac1ebd742f28843d12c1352359b4070c65fbbb6e1cb0 \ - --hash=sha256:dfd2b70a91debe45b9ad5470a87e7cf904e06981bc90c0380e5bd62da27c4393 \ - --hash=sha256:e3b31bb62f538ea70d0a285c8519c86707f7030ac505001f31596baca4cacd1e \ - --hash=sha256:e47d9270b2e6fcadd691f6958ae15a365e80edfb2ea002348ea0f045dc2485c3 \ - --hash=sha256:e4f2fd9df304ada18fbd4a8ef8008cbe77d64d163102ee173d4f05b86f00a7c5 \ - --hash=sha256:e70da2df99fff309285a4f25b774e05d82d01c60ff68dc414de9f292ad2508b4 \ - --hash=sha256:e9429c5241bf1fdeb92678705857aa06ef4bb2b923e382a7e76dc83b14eff615 \ - --hash=sha256:f5db1b8032d6a252040eb4fecb6a330de4712133d0d75b0fbf7cbee1ba7ade61 \ - --hash=sha256:ffde6e5bda89af1217bd888175e5854b5e7539b1e9efc715de48c908fe072561 +clickhouse-connect==0.15.1 \ + --hash=sha256:08df7857ecd2e345abbbdfc54d80fa060732cf75c953940355140af9a73b730a \ + --hash=sha256:0bef871fb9803ae82b4dc1f797b6e784de0a4dec351591191a0c1a6008548284 \ + --hash=sha256:158325a06978f91a182967341188502a0761447d1e13ffa775cf017def1a3d9e \ + --hash=sha256:167e674dff8ac12be7796d93190b6fe9097c042940b3c41d87fe4d85970be27d \ + --hash=sha256:1ef6922c8887a8b0db49a81823ef031807c971f628a363f6d53b030abaefd589 \ + --hash=sha256:1ff5d10c6e49d36ee6941f52c4233f2bfb4198e9c726fed224f725974a667e37 \ + --hash=sha256:24cdfe9b486c8f2e66f5f51b1f322d89d9eb4df29d9ebb2fa19b553065651e85 \ + --hash=sha256:265f1660e8db5006ca32e8894e6c6cc984b343d96171ab0580b2104084b0fc08 \ + --hash=sha256:2e19c9daabe4c24027006e903d0ba3f2a6b2e0703af37b2536335ac4558d541e \ + --hash=sha256:2e52e20190004ed4578b803b1d5f2097c336fafec41b2cc0d490b5a4964c1284 \ + --hash=sha256:371a201ee128ba2b47bd05e2f184b0d20fb78171d27441a6fb1183f4fcc9316e \ + --hash=sha256:3b456d469db994b188bb0b5afa373e8f2e5e2bf41a70a736b9ed2485a976e9ae \ + --hash=sha256:3cf1b78abf7e1b97ab279a2b244357c40657d2d8504ff3f713c6577cd0550b38 \ + --hash=sha256:46bcebd00aff52ea5f7433e9cee1157b411dba9187f6677a18378c799c27c8aa \ + --hash=sha256:4bf70933ab860bd2f0a872db624603706bed400c915c7aeef382956cf8ebbdf3 \ + --hash=sha256:4f87d283399cbda676c8765605bf60dc6559df6fd38cbb9ea07048a4b34dda26 \ + --hash=sha256:5046cb96d1c344c35198fe072a21ce3f273754df3e58fd0a6222c9a1aff72e75 \ + --hash=sha256:5462bad97d97919a4ed230e2ef28d0b76bec0354a343218647830aac7744a43b \ + --hash=sha256:57ad606e878fd284242713449217a0c475fde6b9b7ab59e7ba9e9c388431f004 \ + --hash=sha256:5ab0d019c18d9d63b228ce2e45768f6c65fd27067d1127ab3e558c35c90f52ef \ + --hash=sha256:5de299ada0f7eb9090bb5a6304d8d78163d4d9cc8eb04d8f552bfb82bafb61d5 \ + --hash=sha256:60aa8c9c775d22db324260265f4c656f803fbc71de9193ef83cf8d8d0ef6ab9a \ + --hash=sha256:691cbf6d3dd16988feb75d43942bb212f50f0cbec284eb249e0cd33ebf74ad09 \ + --hash=sha256:693a03e44256886ac5dd26dc708833913157ec72e3b3a44fb89fd5fc202f85dc \ + --hash=sha256:6f9619f9e8885886039e451c2e22d3fb9bd2e95bc64bbf4ebe6c0a50875785f4 \ + --hash=sha256:7586fae639db65d6ff9f7d539aaac04ebd8604657751d78f6b45e7f971be83f3 \ + --hash=sha256:76699fb79c0de182f915d96a08c15afc19755d9d0e9c93411abb0e4b539c7166 \ + --hash=sha256:7a590116037ae56fab339b625f317d7c0a15bbede5f2f206ce1e55b1a2385e90 \ + --hash=sha256:82e60e108d78e32d58a0f21570b02d3baad67ccbad6482eeb79d74a616d8a5ad \ + --hash=sha256:83d881bf786b05489ccf96f07972b9c28638b513f3e064d39987d837749b35e3 \ + --hash=sha256:859c718cb93780dd681f75d59ceaf4415915fa9617a5ba2de6105e291d6df3ad \ + --hash=sha256:873d8f74eaec141f40ae060318c32353da94fdd4601f925bfd52426f3ddcd689 \ + --hash=sha256:8bb70307589099c67dfe9a973998491bc82c1af9040560b5ebab799721bb197d \ + --hash=sha256:9610ef6ff653f8a030f50e39cdeb1a39bea925c48f9196d787ea4b9f5eb1c8f0 \ + --hash=sha256:99d55aab64fdeb53d74c16d2c46ae5491e90aa37ba55c24884a68a869418ee8e \ + --hash=sha256:a1266a52bf61f0420630f625c5ac87bc2d095f08321820546300a699d4300ba3 \ + --hash=sha256:a326e2f5518d6a9d71f0895d50a3ccd8c4d5e3abb625f39330512ff3c45c6731 \ + --hash=sha256:a9d1e12bf86cd96626f74d21e3ac237abcda105f55cd2e78d139197d35f86209 \ + --hash=sha256:aa9890507aac52a8a5363813bb315b6867e86a97ffa08576cb934603f5bc0216 \ + --hash=sha256:ae24e4e7b10ff140c9041d9bdb2c08781145d844c7486c2661d223ededce7634 \ + --hash=sha256:aeb09a6f8585f3bd4d8c5bead38f3821c076e0bca08c474a7b9039732a6e2e9a \ + --hash=sha256:aed10f7615d0c72457d21ace9b59bfcbea0293188af2ffa3f3c2942d36974e7c \ + --hash=sha256:b2f5174fc6001a1555fc3cb565f3b727e1b786d572df0b30d14929ae13bd3542 \ + --hash=sha256:b692998e6dea344a4a2d7c34c129379767a068f234e1cb721ba27f1f023c70ee \ + --hash=sha256:b6d107b5f964af97f25a0d1bfd59fe3510f2a646c87ad4f9ab9014bb0c66aa1c \ + --hash=sha256:b8236c7dd675ed13d5e96f1f9126eeb711e8c266e4a0476ebc32be8a17decb32 \ + --hash=sha256:c12d9f2b2fc57adaf5ea267804f00e520771794641227ed5285e38fdf36557a6 \ + --hash=sha256:cd41ebe8b7f1c2579b22bbc414a800f3f8f5c843928019aca27c81592f70c5a7 \ + --hash=sha256:cdeee50fb2822e4f886d9676c5979b9e6f93ee9159b1aa1b7d62e71bcf7ae551 \ + --hash=sha256:d0dad989ae193c7261b12c9829f219fc1cb1ae9cad380c35cfe489f139c03ee9 \ + --hash=sha256:d10e8f42bafa12d43dd280d157af1ca5a1743e0ca94e61de94c1d00cb1b2da2b \ + --hash=sha256:d3fca3e0781b664556690decc788e7d25691043bf67a0d241e9c29233a2990d5 \ + --hash=sha256:d6e98c0cf53db3b24dc0ff9f522fcf13205b1d191c632567d1744fbd4671741f \ + --hash=sha256:d75324bb3a611eeb8c22b7fdda7c2cbc6ddbcc3871c65624b97f219430ded282 \ + --hash=sha256:df93fa024d6ed46dbc3182b6202180be4cf2bbe9c331dcb21f85963b1b3fd1e5 \ + --hash=sha256:e1a157205efd47884c22bfe061fc6f8c9aea844929ee755c47b446093805d21a \ + --hash=sha256:e307ea69dc2a6e6d942d2799ee8bfe20c99019ddf95121cbeaf7efbb97f79f09 \ + --hash=sha256:e702b77720ae6fd501e5a52262518dddb6c705fbc122bca4567694fb0bab401f \ + --hash=sha256:e88a31bbd9da7f4b49de39d21e8c93c8fbb5cf487071e935af0eba884681df00 \ + --hash=sha256:e911cffe6a9d9d27ccf91b8060086254c152c48ade47c1de3fc8e91d22cdd143 \ + --hash=sha256:eb595e820e46ccdffd702d23e4d1d1efadaa60db81a3da53e693ab055d8a3b1a \ + --hash=sha256:ecf244f91fc72e5dfe83652baf69a7ced414e9147288138897bc4376ebd6f8ac \ + --hash=sha256:f03814b6e6a72892ce913eaef3931e6d011068480e9c19b80e5c640fdac55109 \ + --hash=sha256:f13c34ad1ddb0d1efc92bc4039b50b534da94c51bbce25e61484bfd28b231cb5 \ + --hash=sha256:f25df0298ecea9c29768ab1267ff1186aacfff0cbd75ff3b588644043f313cd6 \ + --hash=sha256:f2aaf5fc0bb3098c24f0d8ca7e4ecbe605a26957481dfca2c8cef9d1fad7b7ca \ + --hash=sha256:fa01fdb92db6bf72cb9509eecd0a0057a4558a4f40c02eebffbc2d61b644620e # via feast (pyproject.toml) cloudpickle==3.1.2 \ --hash=sha256:7fda9eb655c9c230dab534f1983763de5835249750e85fbcef43aaa30a9a2414 \ --hash=sha256:9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a # via dask -codeflare-sdk==0.33.1 \ - --hash=sha256:6622a73edde5042455ae7d76279a5279c55db4950533ea7f12aac2fc51d49bb8 \ - --hash=sha256:ad41ec5260217fd030904fb4b9fe62e26c3f51ac7999a5d607eb4b1359edd5e5 +codeflare-sdk==0.36.0 \ + --hash=sha256:5dfba97aef0c2a83437682b960a9c323d54e459d949e24729d00d330b00b96a2 \ + --hash=sha256:cbac45169916e63198d214492ed1c17c49ee27d3e98303cff59e2170266a441d # via feast (pyproject.toml) colorama==0.4.6 \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ @@ -796,142 +817,164 @@ couchbase-columnar==1.0.0 \ --hash=sha256:fc0fad2d386c5b5df7aaaccd8751e01caa886cc640cc8c92523dd07c4e7be519 \ --hash=sha256:fc4efa3e15190c3731478006de494b046bc57785e9c8ae99ac8b375a91683e38 # via feast (pyproject.toml) -coverage[toml]==7.13.4 \ - --hash=sha256:01d4cbc3c283a17fc1e42d614a119f7f438eabb593391283adca8dc86eff1246 \ - --hash=sha256:02231499b08dabbe2b96612993e5fc34217cdae907a51b906ac7fca8027a4459 \ - --hash=sha256:0dd7ab8278f0d58a0128ba2fca25824321f05d059c1441800e934ff2efa52129 \ - --hash=sha256:0e086334e8537ddd17e5f16a344777c1ab8194986ec533711cbe6c41cde841b6 \ - --hash=sha256:0fc31c787a84f8cd6027eba44010517020e0d18487064cd3d8968941856d1415 \ - --hash=sha256:14375934243ee05f56c45393fe2ce81fe5cc503c07cee2bdf1725fb8bef3ffaf \ - --hash=sha256:1731dc33dc276dafc410a885cbf5992f1ff171393e48a21453b78727d090de80 \ - --hash=sha256:19bc3c88078789f8ef36acb014d7241961dbf883fd2533d18cb1e7a5b4e28b11 \ - --hash=sha256:1af1641e57cf7ba1bd67d677c9abdbcd6cc2ab7da3bca7fa1e2b7e50e65f2ad0 \ - --hash=sha256:1d4be36a5114c499f9f1f9195e95ebf979460dbe2d88e6816ea202010ba1c34b \ - --hash=sha256:200dea7d1e8095cc6e98cdabe3fd1d21ab17d3cee6dab00cadbb2fe35d9c15b9 \ - --hash=sha256:23e3f687cf945070d1c90f85db66d11e3025665d8dafa831301a0e0038f3db9b \ - --hash=sha256:2421d591f8ca05b308cf0092807308b2facbefe54af7c02ac22548b88b95c98f \ - --hash=sha256:245e37f664d89861cf2329c9afa2c1fe9e6d4e1a09d872c947e70718aeeac505 \ - --hash=sha256:25381386e80ae727608e662474db537d4df1ecd42379b5ba33c84633a2b36d47 \ - --hash=sha256:25a41c3104d08edb094d9db0d905ca54d0cd41c928bb6be3c4c799a54753af55 \ - --hash=sha256:296f8b0af861d3970c2a4d8c91d48eb4dd4771bcef9baedec6a9b515d7de3def \ - --hash=sha256:29e3220258d682b6226a9b0925bc563ed9a1ebcff3cad30f043eceea7eaf2689 \ - --hash=sha256:2a09cfa6a5862bc2fc6ca7c3def5b2926194a56b8ab78ffcf617d28911123012 \ - --hash=sha256:2b0f6ccf3dbe577170bebfce1318707d0e8c3650003cb4b3a9dd744575daa8b5 \ - --hash=sha256:2c048ea43875fbf8b45d476ad79f179809c590ec7b79e2035c662e7afa3192e3 \ - --hash=sha256:2cb0f1e000ebc419632bbe04366a8990b6e32c4e0b51543a6484ffe15eaeda95 \ - --hash=sha256:2fa8d5f8de70688a28240de9e139fa16b153cc3cbb01c5f16d88d6505ebdadf9 \ - --hash=sha256:300deaee342f90696ed186e3a00c71b5b3d27bffe9e827677954f4ee56969601 \ - --hash=sha256:30b8d0512f2dc8c8747557e8fb459d6176a2c9e5731e2b74d311c03b78451997 \ - --hash=sha256:33901f604424145c6e9c2398684b92e176c0b12df77d52db81c20abd48c3794c \ - --hash=sha256:3599eb3992d814d23b35c536c28df1a882caa950f8f507cef23d1cbf334995ac \ - --hash=sha256:391ee8f19bef69210978363ca930f7328081c6a0152f1166c91f0b5fdd2a773c \ - --hash=sha256:3998e5a32e62fdf410c0dbd3115df86297995d6e3429af80b8798aad894ca7aa \ - --hash=sha256:3c06f0f1337c667b971ca2f975523347e63ec5e500b9aa5882d91931cd3ef750 \ - --hash=sha256:40aa8808140e55dc022b15d8aa7f651b6b3d68b365ea0398f1441e0b04d859c3 \ - --hash=sha256:40d74da8e6c4b9ac18b15331c4b5ebc35a17069410cad462ad4f40dcd2d50c0d \ - --hash=sha256:4223b4230a376138939a9173f1bdd6521994f2aff8047fae100d6d94d50c5a12 \ - --hash=sha256:48685fee12c2eb3b27c62f2658e7ea21e9c3239cba5a8a242801a0a3f6a8c62a \ - --hash=sha256:4c7d3cc01e7350f2f0f6f7036caaf5673fb56b6998889ccfe9e1c1fe75a9c932 \ - --hash=sha256:4e83efc079eb39480e6346a15a1bcb3e9b04759c5202d157e1dd4303cd619356 \ - --hash=sha256:4fc7fa81bbaf5a02801b65346c8b3e657f1d93763e58c0abdf7c992addd81a92 \ - --hash=sha256:53d133df809c743eb8bce33b24bcababb371f4441340578cd406e084d94a6148 \ - --hash=sha256:590c0ed4bf8e85f745e6b805b2e1c457b2e33d5255dd9729743165253bc9ad39 \ - --hash=sha256:5b856a8ccf749480024ff3bd7310adaef57bf31fd17e1bfc404b7940b6986634 \ - --hash=sha256:65dfcbe305c3dfe658492df2d85259e0d79ead4177f9ae724b6fb245198f55d6 \ - --hash=sha256:6f01afcff62bf9a08fb32b2c1d6e924236c0383c02c790732b6537269e466a72 \ - --hash=sha256:6fdef321fdfbb30a197efa02d48fcd9981f0d8ad2ae8903ac318adc653f5df98 \ - --hash=sha256:71ca20079dd8f27fcf808817e281e90220475cd75115162218d0e27549f95fef \ - --hash=sha256:725d985c5ab621268b2edb8e50dfe57633dc69bda071abc470fed55a14935fd3 \ - --hash=sha256:75eab1ebe4f2f64d9509b984f9314d4aa788540368218b858dad56dc8f3e5eb9 \ - --hash=sha256:75fcd519f2a5765db3f0e391eb3b7d150cce1a771bf4c9f861aeab86c767a3c0 \ - --hash=sha256:76451d1978b95ba6507a039090ba076105c87cc76fc3efd5d35d72093964d49a \ - --hash=sha256:784fc3cf8be001197b652d51d3fd259b1e2262888693a4636e18879f613a62a9 \ - --hash=sha256:78cdf0d578b15148b009ccf18c686aa4f719d887e76e6b40c38ffb61d264a552 \ - --hash=sha256:79be69cf7f3bf9b0deeeb062eab7ac7f36cd4cc4c4dd694bd28921ba4d8596cc \ - --hash=sha256:79e73a76b854d9c6088fe5d8b2ebe745f8681c55f7397c3c0a016192d681045f \ - --hash=sha256:7b322db1284a2ed3aa28ffd8ebe3db91c929b7a333c0820abec3d838ef5b3525 \ - --hash=sha256:7d41eead3cc673cbd38a4417deb7fd0b4ca26954ff7dc6078e33f6ff97bed940 \ - --hash=sha256:7eda778067ad7ffccd23ecffce537dface96212576a07924cbf0d8799d2ded5a \ - --hash=sha256:7f57b33491e281e962021de110b451ab8a24182589be17e12a22c79047935e23 \ - --hash=sha256:8041b6c5bfdc03257666e9881d33b1abc88daccaf73f7b6340fb7946655cd10f \ - --hash=sha256:8248977c2e33aecb2ced42fef99f2d319e9904a36e55a8a68b69207fb7e43edc \ - --hash=sha256:845f352911777a8e722bfce168958214951e07e47e5d5d9744109fa5fe77f79b \ - --hash=sha256:85480adfb35ffc32d40918aad81b89c69c9cc5661a9b8a81476d3e645321a056 \ - --hash=sha256:8e264226ec98e01a8e1054314af91ee6cde0eacac4f465cc93b03dbe0bce2fd7 \ - --hash=sha256:8e798c266c378da2bd819b0677df41ab46d78065fb2a399558f3f6cae78b2fbb \ - --hash=sha256:9181a3ccead280b828fae232df12b16652702b49d41e99d657f46cc7b1f6ec7a \ - --hash=sha256:9351229c8c8407645840edcc277f4a2d44814d1bc34a2128c11c2a031d45a5dd \ - --hash=sha256:93550784d9281e374fb5a12bf1324cc8a963fd63b2d2f223503ef0fd4aa339ea \ - --hash=sha256:9401ebc7ef522f01d01d45532c68c5ac40fb27113019b6b7d8b208f6e9baa126 \ - --hash=sha256:94eb63f9b363180aff17de3e7c8760c3ba94664ea2695c52f10111244d16a299 \ - --hash=sha256:9d107aff57a83222ddbd8d9ee705ede2af2cc926608b57abed8ef96b50b7e8f9 \ - --hash=sha256:a32ebc02a1805adf637fc8dec324b5cdacd2e493515424f70ee33799573d661b \ - --hash=sha256:a3aa4e7b9e416774b21797365b358a6e827ffadaaca81b69ee02946852449f00 \ - --hash=sha256:a6f94a7d00eb18f1b6d403c91a88fd58cfc92d4b16080dfdb774afc8294469bf \ - --hash=sha256:aa3feb8db2e87ff5e6d00d7e1480ae241876286691265657b500886c98f38bda \ - --hash=sha256:ad27098a189e5838900ce4c2a99f2fe42a0bf0c2093c17c69b45a71579e8d4a2 \ - --hash=sha256:ae4578f8528569d3cf303fef2ea569c7f4c4059a38c8667ccef15c6e1f118aa5 \ - --hash=sha256:b1ec7b6b6e93255f952e27ab58fbc68dcc468844b16ecbee881aeb29b6ab4d8d \ - --hash=sha256:b507778ae8a4c915436ed5c2e05b4a6cecfa70f734e19c22a005152a11c7b6a9 \ - --hash=sha256:b66a2da594b6068b48b2692f043f35d4d3693fb639d5ea8b39533c2ad9ac3ab9 \ - --hash=sha256:b720ce6a88a2755f7c697c23268ddc47a571b88052e6b155224347389fdf6a3b \ - --hash=sha256:b7b38448866e83176e28086674fe7368ab8590e4610fb662b44e345b86d63ffa \ - --hash=sha256:b8eb931ee8e6d8243e253e5ed7336deea6904369d2fd8ae6e43f68abbf167092 \ - --hash=sha256:bb28c0f2cf2782508a40cec377935829d5fcc3ad9a3681375af4e84eb34b6b58 \ - --hash=sha256:bd60d4fe2f6fa7dff9223ca1bbc9f05d2b6697bc5961072e5d3b952d46e1b1ea \ - --hash=sha256:c35eb28c1d085eb7d8c9b3296567a1bebe03ce72962e932431b9a61f28facf26 \ - --hash=sha256:c4240e7eded42d131a2d2c4dec70374b781b043ddc79a9de4d55ca71f8e98aea \ - --hash=sha256:caa421e2684e382c5d8973ac55e4f36bed6821a9bad5c953494de960c74595c9 \ - --hash=sha256:d490ba50c3f35dd7c17953c68f3270e7ccd1c6642e2d2afe2d8e720b98f5a053 \ - --hash=sha256:d65b2d373032411e86960604dc4edac91fdfb5dca539461cf2cbe78327d1e64f \ - --hash=sha256:dae88bc0fc77edaa65c14be099bd57ee140cf507e6bfdeea7938457ab387efb0 \ - --hash=sha256:de6defc1c9badbf8b9e67ae90fd00519186d6ab64e5cc5f3d21359c2a9b2c1d3 \ - --hash=sha256:e101609bcbbfb04605ea1027b10dc3735c094d12d40826a60f897b98b1c30256 \ - --hash=sha256:e24f9156097ff9dc286f2f913df3a7f63c0e333dcafa3c196f2c18b4175ca09a \ - --hash=sha256:e2f25215f1a359ab17320b47bcdaca3e6e6356652e8256f2441e4ef972052903 \ - --hash=sha256:e5c8f6ed1e61a8b2dcdf31eb0b9bbf0130750ca79c1c49eb898e2ad86f5ccc91 \ - --hash=sha256:e6f70dec1cc557e52df5306d051ef56003f74d56e9c4dd7ddb07e07ef32a84dd \ - --hash=sha256:e856bf6616714c3a9fbc270ab54103f4e685ba236fa98c054e8f87f266c93505 \ - --hash=sha256:e87f6c587c3f34356c3759f0420693e35e7eb0e2e41e4c011cb6ec6ecbbf1db7 \ - --hash=sha256:eb30bf180de3f632cd043322dad5751390e5385108b2807368997d1a92a509d0 \ - --hash=sha256:eb88b316ec33760714a4720feb2816a3a59180fd58c1985012054fa7aebee4c2 \ - --hash=sha256:eb9078108fbf0bcdde37c3f4779303673c2fa1fe8f7956e68d447d0dd426d38a \ - --hash=sha256:ecae9737b72408d6a950f7e525f30aca12d4bd8dd95e37342e5beb3a2a8c4f71 \ - --hash=sha256:ee756f00726693e5ba94d6df2bdfd64d4852d23b09bb0bc700e3b30e6f333985 \ - --hash=sha256:f4594c67d8a7c89cf922d9df0438c7c7bb022ad506eddb0fdb2863359ff78242 \ - --hash=sha256:f53d492307962561ac7de4cd1de3e363589b000ab69617c6156a16ba7237998d \ - --hash=sha256:fb07dc5da7e849e2ad31a5d74e9bece81f30ecf5a42909d0a695f8bd1874d6af \ - --hash=sha256:fb26a934946a6afe0e326aebe0730cdff393a8bc0bbb65a2f41e30feddca399c \ - --hash=sha256:fdfc1e28e7c7cdce44985b3043bc13bbd9c747520f94a4d7164af8260b3d91f0 +coverage[toml]==7.13.5 \ + --hash=sha256:012d5319e66e9d5a218834642d6c35d265515a62f01157a45bcc036ecf947256 \ + --hash=sha256:02ca0eed225b2ff301c474aeeeae27d26e2537942aa0f87491d3e147e784a82b \ + --hash=sha256:03ccc709a17a1de074fb1d11f217342fb0d2b1582ed544f554fc9fc3f07e95f5 \ + --hash=sha256:0428cbef5783ad91fe240f673cc1f76b25e74bbfe1a13115e4aa30d3f538162d \ + --hash=sha256:04690832cbea4e4663d9149e05dba142546ca05cb1848816760e7f58285c970a \ + --hash=sha256:0590e44dd2745c696a778f7bab6aa95256de2cbc8b8cff4f7db8ff09813d6969 \ + --hash=sha256:0672854dc733c342fa3e957e0605256d2bf5934feeac328da9e0b5449634a642 \ + --hash=sha256:084b84a8c63e8d6fc7e3931b316a9bcafca1458d753c539db82d31ed20091a87 \ + --hash=sha256:0b67af5492adb31940ee418a5a655c28e48165da5afab8c7fa6fd72a142f8740 \ + --hash=sha256:0cd9ed7a8b181775459296e402ca4fb27db1279740a24e93b3b41942ebe4b215 \ + --hash=sha256:0cef0cdec915d11254a7f549c1170afecce708d30610c6abdded1f74e581666d \ + --hash=sha256:0e223ce4b4ed47f065bfb123687686512e37629be25cc63728557ae7db261422 \ + --hash=sha256:0e3c426ffc4cd952f54ee9ffbdd10345709ecc78a3ecfd796a57236bfad0b9b8 \ + --hash=sha256:0ecf12ecb326fe2c339d93fc131816f3a7367d223db37817208905c89bded911 \ + --hash=sha256:10a0c37f0b646eaff7cce1874c31d1f1ccb297688d4c747291f4f4c70741cc8b \ + --hash=sha256:145ede53ccbafb297c1c9287f788d1bc3efd6c900da23bf6931b09eafc931587 \ + --hash=sha256:1b11eef33edeae9d142f9b4358edb76273b3bfd30bc3df9a4f95d0e49caf94e8 \ + --hash=sha256:1b88c69c8ef5d4b6fe7dea66d6636056a0f6a7527c440e890cf9259011f5e606 \ + --hash=sha256:258354455f4e86e3e9d0d17571d522e13b4e1e19bf0f8596bcf9476d61e7d8a9 \ + --hash=sha256:259b69bb83ad9894c4b25be2528139eecba9a82646ebdda2d9db1ba28424a6bf \ + --hash=sha256:2aa055ae1857258f9e0045be26a6d62bdb47a72448b62d7b55f4820f361a2633 \ + --hash=sha256:2d3807015f138ffea1ed9afeeb8624fd781703f2858b62a8dd8da5a0994c57b6 \ + --hash=sha256:301e3b7dfefecaca37c9f1aa6f0049b7d4ab8dd933742b607765d757aca77d43 \ + --hash=sha256:32ca0c0114c9834a43f045a87dcebd69d108d8ffb666957ea65aa132f50332e2 \ + --hash=sha256:34b02417cf070e173989b3db962f7ed56d2f644307b2cf9d5a0f258e13084a61 \ + --hash=sha256:356e76b46783a98c2a2fe81ec79df4883a1e62895ea952968fb253c114e7f930 \ + --hash=sha256:35a31f2b1578185fbe6aa2e74cea1b1d0bbf4c552774247d9160d29b80ed56cc \ + --hash=sha256:380e8e9084d8eb38db3a9176a1a4f3c0082c3806fa0dc882d1d87abc3c789247 \ + --hash=sha256:3ad050321264c49c2fa67bb599100456fc51d004b82534f379d16445da40fb75 \ + --hash=sha256:3e1bb5f6c78feeb1be3475789b14a0f0a5b47d505bfc7267126ccbd50289999e \ + --hash=sha256:3f4818d065964db3c1c66dc0fbdac5ac692ecbc875555e13374fdbe7eedb4376 \ + --hash=sha256:460cf0114c5016fa841214ff5564aa4864f11948da9440bc97e21ad1f4ba1e01 \ + --hash=sha256:48c39bc4a04d983a54a705a6389512883d4a3b9862991b3617d547940e9f52b1 \ + --hash=sha256:4b59148601efcd2bac8c4dbf1f0ad6391693ccf7a74b8205781751637076aee3 \ + --hash=sha256:4d2afbc5cc54d286bfb54541aa50b64cdb07a718227168c87b9e2fb8f25e1743 \ + --hash=sha256:505d7083c8b0c87a8fa8c07370c285847c1f77739b22e299ad75a6af6c32c5c9 \ + --hash=sha256:52f444e86475992506b32d4e5ca55c24fc88d73bcbda0e9745095b28ef4dc0cf \ + --hash=sha256:5b13955d31d1633cf9376908089b7cebe7d15ddad7aeaabcbe969a595a97e95e \ + --hash=sha256:5ec4af212df513e399cf11610cc27063f1586419e814755ab362e50a85ea69c1 \ + --hash=sha256:60365289c3741e4db327e7baff2a4aaacf22f788e80fa4683393891b70a89fbd \ + --hash=sha256:631efb83f01569670a5e866ceb80fe483e7c159fac6f167e6571522636104a0b \ + --hash=sha256:6697e29b93707167687543480a40f0db8f356e86d9f67ddf2e37e2dfd91a9dab \ + --hash=sha256:66a80c616f80181f4d643b0f9e709d97bcea413ecd9631e1dedc7401c8e6695d \ + --hash=sha256:67e9bc5449801fad0e5dff329499fb090ba4c5800b86805c80617b4e29809b2a \ + --hash=sha256:68a4953be99b17ac3c23b6efbc8a38330d99680c9458927491d18700ef23ded0 \ + --hash=sha256:6c36ddb64ed9d7e496028d1d00dfec3e428e0aabf4006583bb1839958d280510 \ + --hash=sha256:6e3370441f4513c6252bf042b9c36d22491142385049243253c7e48398a15a9f \ + --hash=sha256:7034b5c56a58ae5e85f23949d52c14aca2cfc6848a31764995b7de88f13a1ea0 \ + --hash=sha256:704de6328e3d612a8f6c07000a878ff38181ec3263d5a11da1db294fa6a9bdf8 \ + --hash=sha256:7132bed4bd7b836200c591410ae7d97bf7ae8be6fc87d160b2bd881df929e7bf \ + --hash=sha256:7300c8a6d13335b29bb76d7651c66af6bd8658517c43499f110ddc6717bfc209 \ + --hash=sha256:750db93a81e3e5a9831b534be7b1229df848b2e125a604fe6651e48aa070e5f9 \ + --hash=sha256:777c4d1eff1b67876139d24288aaf1817f6c03d6bae9c5cc8d27b83bcfe38fe3 \ + --hash=sha256:78e696e1cc714e57e8b25760b33a8b1026b7048d270140d25dafe1b0a1ee05a3 \ + --hash=sha256:79060214983769c7ba3f0cee10b54c97609dca4d478fa1aa32b914480fd5738d \ + --hash=sha256:7c8d4bc913dd70b93488d6c496c77f3aff5ea99a07e36a18f865bca55adef8bd \ + --hash=sha256:7f2c47b36fe7709a6e83bfadf4eefb90bd25fbe4014d715224c4316f808e59a2 \ + --hash=sha256:800bc829053c80d240a687ceeb927a94fd108bbdc68dfbe505d0d75ab578a882 \ + --hash=sha256:843ea8643cf967d1ac7e8ecd4bb00c99135adf4816c0c0593fdcc47b597fcf09 \ + --hash=sha256:8769751c10f339021e2638cd354e13adeac54004d1941119b2c96fe5276d45ea \ + --hash=sha256:8dd02af98971bdb956363e4827d34425cb3df19ee550ef92855b0acb9c7ce51c \ + --hash=sha256:8fdf453a942c3e4d99bd80088141c4c6960bb232c409d9c3558e2dbaa3998562 \ + --hash=sha256:941617e518602e2d64942c88ec8499f7fbd49d3f6c4327d3a71d43a1973032f3 \ + --hash=sha256:972a9cd27894afe4bc2b1480107054e062df08e671df7c2f18c205e805ccd806 \ + --hash=sha256:9adb6688e3b53adffefd4a52d72cbd8b02602bfb8f74dcd862337182fd4d1a4e \ + --hash=sha256:9b74db26dfea4f4e50d48a4602207cd1e78be33182bc9cbf22da94f332f99878 \ + --hash=sha256:9bb2a28101a443669a423b665939381084412b81c3f8c0fcfbac57f4e30b5b8e \ + --hash=sha256:9d44d7aa963820b1b971dbecd90bfe5fe8f81cff79787eb6cca15750bd2f79b9 \ + --hash=sha256:9dacc2ad679b292709e0f5fc1ac74a6d4d5562e424058962c7bb0c658ad25e45 \ + --hash=sha256:9ddb4f4a5479f2539644be484da179b653273bca1a323947d48ab107b3ed1f29 \ + --hash=sha256:a1a6d79a14e1ec1832cabc833898636ad5f3754a678ef8bb4908515208bf84f4 \ + --hash=sha256:a698e363641b98843c517817db75373c83254781426e94ada3197cabbc2c919c \ + --hash=sha256:ad14385487393e386e2ea988b09d62dd42c397662ac2dabc3832d71253eee479 \ + --hash=sha256:ad146744ca4fd09b50c482650e3c1b1f4dfa1d4792e0a04a369c7f23336f0400 \ + --hash=sha256:b5db73ba3c41c7008037fa731ad5459fc3944cb7452fc0aa9f822ad3533c583c \ + --hash=sha256:bd3a2fbc1c6cccb3c5106140d87cc6a8715110373ef42b63cf5aea29df8c217a \ + --hash=sha256:bdba0a6b8812e8c7df002d908a9a2ea3c36e92611b5708633c50869e6d922fdf \ + --hash=sha256:be3d4bbad9d4b037791794ddeedd7d64a56f5933a2c1373e18e9e568b9141686 \ + --hash=sha256:bf69236a9a81bdca3bff53796237aab096cdbf8d78a66ad61e992d9dac7eb2de \ + --hash=sha256:bff95879c33ec8da99fc9b6fe345ddb5be6414b41d6d1ad1c8f188d26f36e028 \ + --hash=sha256:c555b48be1853fe3997c11c4bd521cdd9a9612352de01fa4508f16ec341e6fe0 \ + --hash=sha256:c81f6515c4c40141f83f502b07bbfa5c240ba25bbe73da7b33f1e5b6120ff179 \ + --hash=sha256:c9136ff29c3a91e25b1d1552b5308e53a1e0653a23e53b6366d7c2dcbbaf8a16 \ + --hash=sha256:ce1998c0483007608c8382f4ff50164bfc5bd07a2246dd272aa4043b75e61e85 \ + --hash=sha256:cec2d83125531bd153175354055cdb7a09987af08a9430bd173c937c6d0fba2a \ + --hash=sha256:cff784eef7f0b8f6cb28804fbddcfa99f89efe4cc35fb5627e3ac58f91ed3ac0 \ + --hash=sha256:d2c87e0c473a10bffe991502eac389220533024c8082ec1ce849f4218dded810 \ + --hash=sha256:d7cfad2d6d81dd298ab6b89fe72c3b7b05ec7544bdda3b707ddaecff8d25c161 \ + --hash=sha256:d8a7a2049c14f413163e2bdabd37e41179b1d1ccb10ffc6ccc4b7a718429c607 \ + --hash=sha256:da305e9937617ee95c2e39d8ff9f040e0487cbf1ac174f777ed5eddd7a7c1f26 \ + --hash=sha256:da86cdcf10d2519e10cabb8ac2de03da1bcb6e4853790b7fbd48523332e3a819 \ + --hash=sha256:dc022073d063b25a402454e5712ef9e007113e3a676b96c5f29b2bda29352f40 \ + --hash=sha256:e0723d2c96324561b9aa76fb982406e11d93cdb388a7a7da2b16e04719cf7ca5 \ + --hash=sha256:e092b9499de38ae0fbfbc603a74660eb6ff3e869e507b50d85a13b6db9863e15 \ + --hash=sha256:e0b216a19534b2427cc201a26c25da4a48633f29a487c61258643e89d28200c0 \ + --hash=sha256:e1c85e0b6c05c592ea6d8768a66a254bfb3874b53774b12d4c89c481eb78cb90 \ + --hash=sha256:e301d30dd7e95ae068671d746ba8c34e945a82682e62918e41b2679acd2051a0 \ + --hash=sha256:e808af52a0513762df4d945ea164a24b37f2f518cbe97e03deaa0ee66139b4d6 \ + --hash=sha256:eb07647a5738b89baab047f14edd18ded523de60f3b30e75c2acc826f79c839a \ + --hash=sha256:eb7fdf1ef130660e7415e0253a01a7d5a88c9c4d158bcf75cbbd922fd65a5b58 \ + --hash=sha256:ec10e2a42b41c923c2209b846126c6582db5e43a33157e9870ba9fb70dc7854b \ + --hash=sha256:ee2aa19e03161671ec964004fb74b2257805d9710bf14a5c704558b9d8dbaf17 \ + --hash=sha256:f08fd75c50a760c7eb068ae823777268daaf16a80b918fa58eea888f8e3919f5 \ + --hash=sha256:f4cd16206ad171cbc2470dbea9103cf9a7607d5fe8c242fdf1edf36174020664 \ + --hash=sha256:f70c9ab2595c56f81a89620e22899eea8b212a4041bd728ac6f4a28bf5d3ddd0 \ + --hash=sha256:fbabfaceaeb587e16f7008f7795cd80d20ec548dc7f94fbb0d4ec2e038ce563f # via pytest-cov -cryptography==43.0.3 \ - --hash=sha256:0c580952eef9bf68c4747774cde7ec1d85a6e61de97281f2dba83c7d2c806362 \ - --hash=sha256:0f996e7268af62598f2fc1204afa98a3b5712313a55c4c9d434aef49cadc91d4 \ - --hash=sha256:1ec0bcf7e17c0c5669d881b1cd38c4972fade441b27bda1051665faaa89bdcaa \ - --hash=sha256:281c945d0e28c92ca5e5930664c1cefd85efe80e5c0d2bc58dd63383fda29f83 \ - --hash=sha256:2ce6fae5bdad59577b44e4dfed356944fbf1d925269114c28be377692643b4ff \ - --hash=sha256:315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805 \ - --hash=sha256:443c4a81bb10daed9a8f334365fe52542771f25aedaf889fd323a853ce7377d6 \ - --hash=sha256:4a02ded6cd4f0a5562a8887df8b3bd14e822a90f97ac5e544c162899bc467664 \ - --hash=sha256:53a583b6637ab4c4e3591a15bc9db855b8d9dee9a669b550f311480acab6eb08 \ - --hash=sha256:63efa177ff54aec6e1c0aefaa1a241232dcd37413835a9b674b6e3f0ae2bfd3e \ - --hash=sha256:74f57f24754fe349223792466a709f8e0c093205ff0dca557af51072ff47ab18 \ - --hash=sha256:7e1ce50266f4f70bf41a2c6dc4358afadae90e2a1e5342d3c08883df1675374f \ - --hash=sha256:81ef806b1fef6b06dcebad789f988d3b37ccaee225695cf3e07648eee0fc6b73 \ - --hash=sha256:846da004a5804145a5f441b8530b4bf35afbf7da70f82409f151695b127213d5 \ - --hash=sha256:8ac43ae87929a5982f5948ceda07001ee5e83227fd69cf55b109144938d96984 \ - --hash=sha256:9762ea51a8fc2a88b70cf2995e5675b38d93bf36bd67d91721c309df184f49bd \ - --hash=sha256:a2a431ee15799d6db9fe80c82b055bae5a752bef645bba795e8e52687c69efe3 \ - --hash=sha256:bf7a1932ac4176486eab36a19ed4c0492da5d97123f1406cf15e41b05e787d2e \ - --hash=sha256:c2e6fc39c4ab499049df3bdf567f768a723a5e8464816e8f009f121a5a9f4405 \ - --hash=sha256:cbeb489927bd7af4aa98d4b261af9a5bc025bd87f0e3547e11584be9e9427be2 \ - --hash=sha256:d03b5621a135bffecad2c73e9f4deb1a0f977b9a8ffe6f8e002bf6c9d07b918c \ - --hash=sha256:d56e96520b1020449bbace2b78b603442e7e378a9b3bd68de65c782db1507995 \ - --hash=sha256:df6b6c6d742395dd77a23ea3728ab62f98379eff8fb61be2744d4679ab678f73 \ - --hash=sha256:e1be4655c7ef6e1bbe6b5d0403526601323420bcf414598955968c9ef3eb7d16 \ - --hash=sha256:f18c716be16bc1fea8e95def49edf46b82fccaa88587a45f8dc0ff6ab5d8e0a7 \ - --hash=sha256:f46304d6f0c6ab8e52770addfa2fc41e6629495548862279641972b6215451cd \ - --hash=sha256:f7b178f11ed3664fd0e995a47ed2b5ff0a12d893e41dd0494f406d1cf555cab7 +cryptography==46.0.6 \ + --hash=sha256:02fad249cb0e090b574e30b276a3da6a149e04ee2f049725b1f69e7b8351ec70 \ + --hash=sha256:063b67749f338ca9c5a0b7fe438a52c25f9526b851e24e6c9310e7195aad3b4d \ + --hash=sha256:12cae594e9473bca1a7aceb90536060643128bb274fcea0fc459ab90f7d1ae7a \ + --hash=sha256:12f0fa16cc247b13c43d56d7b35287ff1569b5b1f4c5e87e92cc4fcc00cd10c0 \ + --hash=sha256:22259338084d6ae497a19bae5d4c66b7ca1387d3264d1c2c0e72d9e9b6a77b97 \ + --hash=sha256:26031f1e5ca62fcb9d1fcb34b2b60b390d1aacaa15dc8b895a9ed00968b97b30 \ + --hash=sha256:27550628a518c5c6c903d84f637fbecf287f6cb9ced3804838a1295dc1fd0759 \ + --hash=sha256:2b417edbe8877cda9022dde3a008e2deb50be9c407eef034aeeb3a8b11d9db3c \ + --hash=sha256:2ea0f37e9a9cf0df2952893ad145fd9627d326a59daec9b0802480fa3bcd2ead \ + --hash=sha256:2ef9e69886cbb137c2aef9772c2e7138dc581fad4fcbcf13cc181eb5a3ab6275 \ + --hash=sha256:341359d6c9e68834e204ceaf25936dffeafea3829ab80e9503860dcc4f4dac58 \ + --hash=sha256:380343e0653b1c9d7e1f55b52aaa2dbb2fdf2730088d48c43ca1c7c0abb7cc2f \ + --hash=sha256:3c21d92ed15e9cfc6eb64c1f5a0326db22ca9c2566ca46d845119b45b4400361 \ + --hash=sha256:3dfa6567f2e9e4c5dceb8ccb5a708158a2a871052fa75c8b78cb0977063f1507 \ + --hash=sha256:456b3215172aeefb9284550b162801d62f5f264a081049a3e94307fe20792cfa \ + --hash=sha256:4668298aef7cddeaf5c6ecc244c2302a2b8e40f384255505c22875eebb47888b \ + --hash=sha256:50575a76e2951fe7dbd1f56d181f8c5ceeeb075e9ff88e7ad997d2f42af06e7b \ + --hash=sha256:639301950939d844a9e1c4464d7e07f902fe9a7f6b215bb0d4f28584729935d8 \ + --hash=sha256:64235194bad039a10bb6d2d930ab3323baaec67e2ce36215fd0952fad0930ca8 \ + --hash=sha256:6617f67b1606dfd9fe4dbfa354a9508d4a6d37afe30306fe6c101b7ce3274b72 \ + --hash=sha256:67177e8a9f421aa2d3a170c3e56eca4e0128883cf52a071a7cbf53297f18b175 \ + --hash=sha256:6728c49e3b2c180ef26f8e9f0a883a2c585638db64cf265b49c9ba10652d430e \ + --hash=sha256:6739d56300662c468fddb0e5e291f9b4d084bead381667b9e654c7dd81705124 \ + --hash=sha256:69cf0056d6947edc6e6760e5f17afe4bea06b56a9ac8a06de9d2bd6b532d4f3a \ + --hash=sha256:760997a4b950ff00d418398ad73fbc91aa2894b5c1db7ccb45b4f68b42a63b3c \ + --hash=sha256:79e865c642cfc5c0b3eb12af83c35c5aeff4fa5c672dc28c43721c2c9fdd2f0f \ + --hash=sha256:7e6142674f2a9291463e5e150090b95a8519b2fb6e6aaec8917dd8d094ce750d \ + --hash=sha256:7f417f034f91dcec1cb6c5c35b07cdbb2ef262557f701b4ecd803ee8cefed4f4 \ + --hash=sha256:7f6690b6c55e9c5332c0b59b9c8a3fb232ebf059094c17f9019a51e9827df91c \ + --hash=sha256:8927ccfbe967c7df312ade694f987e7e9e22b2425976ddbf28271d7e58845290 \ + --hash=sha256:8ce35b77aaf02f3b59c90b2c8a05c73bac12cea5b4e8f3fbece1f5fddea5f0ca \ + --hash=sha256:8e7304c4f4e9490e11efe56af6713983460ee0780f16c63f219984dab3af9d2d \ + --hash=sha256:90e5f0a7b3be5f40c3a0a0eafb32c681d8d2c181fc2a1bdabe9b3f611d9f6b1a \ + --hash=sha256:97c8115b27e19e592a05c45d0dd89c57f81f841cc9880e353e0d3bf25b2139ed \ + --hash=sha256:9a693028b9cbe51b5a1136232ee8f2bc242e4e19d456ded3fa7c86e43c713b4a \ + --hash=sha256:9a9c42a2723999a710445bc0d974e345c32adfd8d2fac6d8a251fa829ad31cfb \ + --hash=sha256:a3e84d5ec9ba01f8fd03802b2147ba77f0c8f2617b2aff254cedd551844209c8 \ + --hash=sha256:aad75154a7ac9039936d50cf431719a2f8d4ed3d3c277ac03f3339ded1a5e707 \ + --hash=sha256:b12c6b1e1651e42ab5de8b1e00dc3b6354fdfd778e7fa60541ddacc27cd21410 \ + --hash=sha256:b928a3ca837c77a10e81a814a693f2295200adb3352395fad024559b7be7a736 \ + --hash=sha256:bcb87663e1f7b075e48c3be3ecb5f0b46c8fc50b50a97cf264e7f60242dca3f2 \ + --hash=sha256:c797e2517cb7880f8297e2c0f43bb910e91381339336f75d2c1c2cbf811b70b4 \ + --hash=sha256:c89eb37fae9216985d8734c1afd172ba4927f5a05cfd9bf0e4863c6d5465b013 \ + --hash=sha256:cdcd3edcbc5d55757e5f5f3d330dd00007ae463a7e7aa5bf132d1f22a4b62b19 \ + --hash=sha256:d24c13369e856b94892a89ddf70b332e0b70ad4a5c43cf3e9cb71d6d7ffa1f7b \ + --hash=sha256:d4e4aadb7fc1f88687f47ca20bb7227981b03afaae69287029da08096853b738 \ + --hash=sha256:d9528b535a6c4f8ff37847144b8986a9a143585f0540fbcb1a98115b543aa463 \ + --hash=sha256:ed3775295fb91f70b4027aeba878d79b3e55c0b3e97eaa4de71f8f23a9f2eb77 \ + --hash=sha256:ed418c37d095aeddf5336898a132fba01091f0ac5844e3e8018506f014b6d2c4 # via # feast (pyproject.toml) # azure-identity @@ -942,29 +985,30 @@ cryptography==43.0.3 \ # jwcrypto # moto # msal + # oracledb # paramiko # pyjwt # pyopenssl # snowflake-connector-python # types-pyopenssl # types-redis -dask[dataframe]==2026.1.2 \ - --hash=sha256:1136683de2750d98ea792670f7434e6c1cfce90cab2cc2f2495a9e60fd25a4fc \ - --hash=sha256:46a0cf3b8d87f78a3d2e6b145aea4418a6d6d606fe6a16c79bd8ca2bb862bc91 +dask[dataframe]==2026.3.0 \ + --hash=sha256:be614b9242b0b38288060fb2d7696125946469c98a1c30e174883fd199e0428d \ + --hash=sha256:f7d96c8274e8a900d217c1ff6ea8d1bbf0b4c2c21e74a409644498d925eb8f85 # via feast (pyproject.toml) -datasets==4.5.0 \ - --hash=sha256:00c698ce1c2452e646cc5fad47fef39d3fe78dd650a8a6eb205bb45eb63cd500 \ - --hash=sha256:b5d7e08096ffa407dd69e58b1c0271c9b2506140839b8d99af07375ad31b6726 +datasets==4.8.4 \ + --hash=sha256:a1429ed853275ce7943a01c6d2e25475b4501eb758934362106a280470df3a52 \ + --hash=sha256:cdc8bee4698e549d78bf1fed6aea2eebc760b22b084f07e6fc020c6577a6ce6d # via feast (pyproject.toml) -db-dtypes==1.5.0 \ - --hash=sha256:abdbb2e4eb965800ed6f98af0c5c1cafff9063ace09114be2d26a7f046be2c8a \ - --hash=sha256:ad9e94243f53e104bc77dbf9ae44b580d83a770d3694483aba59c9767966daa5 +db-dtypes==1.5.1 \ + --hash=sha256:901099b807c9312bc61a5bddbfb07512884e6c6d5a9edacf24d50bcf303aa5f7 \ + --hash=sha256:ad71a6645e3c1f06d4d32023940576648f43119822f825f0d22587c6ef8afe15 # via # google-cloud-bigquery # pandas-gbq -dbt-artifacts-parser==0.12.0 \ - --hash=sha256:3db93df7969c3f22c6fbf75a51b0af4c21b189d8db6f3c54e8471102c775bb0d \ - --hash=sha256:9d1c0ed41926102c1c39fdd780e1a332f58c9b794e94dba0dcf5dfefc847d6ea +dbt-artifacts-parser==0.13.0 \ + --hash=sha256:304f2b857650566fed4ed8b976ed3582332eda3cedfe7167158dbbcfced3fe47 \ + --hash=sha256:55498e8bd0d9064d56617f9c714ced8607d94ccb61e70d4b49dcfd8a28a030d8 # via feast (pyproject.toml) debugpy==1.8.20 \ --hash=sha256:077a7447589ee9bc1ff0cdf443566d0ecf540ac8aa7333b775ebcb8ce9f4ecad \ @@ -1040,16 +1084,16 @@ docling==2.27.0 \ --hash=sha256:1288ed75b27e33bf94daff34faffc6d11b7d7ccc13e3df84fb24adad3991f72d \ --hash=sha256:faba35662612a2c687a3a463e501d95f645316436084af92a0442ce162429a3d # via feast (pyproject.toml) -docling-core[chunking]==2.65.1 \ - --hash=sha256:3a143adb9cc613c503380eff92f5895078fc5a00fc7264f327d0d85ff60176cd \ - --hash=sha256:fcdb30254bc5046b52b8bec5919de3b6cdbeed915399cede5351ff328cdd020d +docling-core[chunking]==2.71.0 \ + --hash=sha256:4761857816853b2b35263b5b4518e1ea6214e0565db0bbf1d929fb976665d1a0 \ + --hash=sha256:4caa9f50c68b9dd332584ae16170b36db05d773532b14d7078b580d89d8bd2a4 # via # docling # docling-ibm-models # docling-parse -docling-ibm-models==3.11.0 \ - --hash=sha256:454401563a8e79cb33b718bc559d9bacca8a0183583e48f8e616c9184c1f5eb1 \ - --hash=sha256:68f7961069d643bfdab21b1c9ef24a979db293496f4c2283d95b1025a9ac5347 +docling-ibm-models==3.13.0 \ + --hash=sha256:a11acc6034b06e0bed8dc0ca1fa700615b8246eacce411619168e1f6562b0d0d \ + --hash=sha256:f402effae8a63b0e5c3b5ce13120601baa2cd8098beef1d53ab5a056443758d3 # via docling docling-parse==4.7.3 \ --hash=sha256:1790e7e4ae202d67875c1c48fd6f8ef5c51d10b0c23157e4989b8673f2f31308 \ @@ -1084,48 +1128,42 @@ docutils==0.19 \ --hash=sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6 \ --hash=sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc # via sphinx -duckdb==1.4.4 \ - --hash=sha256:0509b39ea7af8cff0198a99d206dca753c62844adab54e545984c2e2c1381616 \ - --hash=sha256:0d636ceda422e7babd5e2f7275f6a0d1a3405e6a01873f00d38b72118d30c10b \ - --hash=sha256:1af6e76fe8bd24875dc56dd8e38300d64dc708cd2e772f67b9fbc635cc3066a3 \ - --hash=sha256:1f8d55843cc940e36261689054f7dfb6ce35b1f5b0953b0d355b6adb654b0d52 \ - --hash=sha256:25874f8b1355e96178079e37312c3ba6d61a2354f51319dae860cf21335c3a20 \ - --hash=sha256:337f8b24e89bc2e12dadcfe87b4eb1c00fd920f68ab07bc9b70960d6523b8bc3 \ - --hash=sha256:452c5b5d6c349dc5d1154eb2062ee547296fcbd0c20e9df1ed00b5e1809089da \ - --hash=sha256:453b115f4777467f35103d8081770ac2f223fb5799178db5b06186e3ab51d1f2 \ - --hash=sha256:47dd4162da6a2be59a0aef640eb08d6360df1cf83c317dcc127836daaf3b7f7c \ - --hash=sha256:49123b579e4a6323e65139210cd72dddc593a72d840211556b60f9703bda8526 \ - --hash=sha256:4c25d5b0febda02b7944e94fdae95aecf952797afc8cb920f677b46a7c251955 \ - --hash=sha256:50f2eb173c573811b44aba51176da7a4e5c487113982be6a6a1c37337ec5fa57 \ - --hash=sha256:53cd6423136ab44383ec9955aefe7599b3fb3dd1fe006161e6396d8167e0e0d4 \ - --hash=sha256:5536eb952a8aa6ae56469362e344d4e6403cc945a80bc8c5c2ebdd85d85eb64b \ - --hash=sha256:59c8d76016dde854beab844935b1ec31de358d4053e792988108e995b18c08e7 \ - --hash=sha256:5ba684f498d4e924c7e8f30dd157da8da34c8479746c5011b6c0e037e9c60ad2 \ - --hash=sha256:5cdc4126ec925edf3112bc656ac9ed23745294b854935fa7a643a216e4455af6 \ - --hash=sha256:5e1933fac5293fea5926b0ee75a55b8cfe7f516d867310a5b251831ab61fe62b \ - --hash=sha256:6703dd1bb650025b3771552333d305d62ddd7ff182de121483d4e042ea6e2e00 \ - --hash=sha256:6792ca647216bd5c4ff16396e4591cfa9b4a72e5ad7cdd312cec6d67e8431a7c \ - --hash=sha256:6cb357cfa3403910e79e2eb46c8e445bb1ee2fd62e9e9588c6b999df4256abc1 \ - --hash=sha256:6fb1225a9ea5877421481d59a6c556a9532c32c16c7ae6ca8d127e2b878c9389 \ - --hash=sha256:707530f6637e91dc4b8125260595299ec9dd157c09f5d16c4186c5988bfbd09a \ - --hash=sha256:7df7351328ffb812a4a289732f500d621e7de9942a3a2c9b6d4afcf4c0e72526 \ - --hash=sha256:7eec0bf271ac622e57b7f6554a27a6e7d1dd2f43d1871f7962c74bcbbede15ba \ - --hash=sha256:8097201bc5fd0779d7fcc2f3f4736c349197235f4cb7171622936343a1aa8dbf \ - --hash=sha256:8bba52fd2acb67668a4615ee17ee51814124223de836d9e2fdcbc4c9021b3d3c \ - --hash=sha256:8e5c2d8a0452df55e092959c0bfc8ab8897ac3ea0f754cb3b0ab3e165cd79aff \ - --hash=sha256:a3c8542db7ffb128aceb7f3b35502ebaddcd4f73f1227569306cc34bad06680c \ - --hash=sha256:b297eff642503fd435a9de5a9cb7db4eccb6f61d61a55b30d2636023f149855f \ - --hash=sha256:bf138201f56e5d6fc276a25138341b3523e2f84733613fc43f02c54465619a95 \ - --hash=sha256:c65d15c440c31e06baaebfd2c06d71ce877e132779d309f1edf0a85d23c07e92 \ - --hash=sha256:c9566a4ed834ec7999db5849f53da0a7ee83d86830c33f471bf0211a1148ca12 \ - --hash=sha256:cd1be3d48577f5b40eb9706c6b2ae10edfe18e78eb28e31a3b922dcff1183597 \ - --hash=sha256:d0440f59e0cd9936a9ebfcf7a13312eda480c79214ffed3878d75947fc3b7d6d \ - --hash=sha256:d525de5f282b03aa8be6db86b1abffdceae5f1055113a03d5b50cd2fb8cf2ef8 \ - --hash=sha256:ddcfd9c6ff234da603a1edd5fd8ae6107f4d042f74951b65f91bc5e2643856b3 \ - --hash=sha256:e041f2fbd6888da090eca96ac167a7eb62d02f778385dd9155ed859f1c6b6dc8 \ - --hash=sha256:e870a441cb1c41d556205deb665749f26347ed13b3a247b53714f5d589596977 \ - --hash=sha256:f28a18cc790217e5b347bb91b2cab27aafc557c58d3d8382e04b4fe55d0c3f66 \ - --hash=sha256:fb94de6d023de9d79b7edc1ae07ee1d0b4f5fa8a9dcec799650b5befdf7aafec +duckdb==1.5.1 \ + --hash=sha256:054ad424b051b334052afac58cb216f3b1ebb8579fc8c641e60f0182e8725ea9 \ + --hash=sha256:05fc91767d0cfc4cf2fa68966ab5b479ac07561752e42dd0ae30327bd160f64a \ + --hash=sha256:0a6acc2040bec1f05de62a2f3f68f4c12f3ec7d6012b4317d0ab1a195af26225 \ + --hash=sha256:26e56b5f0c96189e3288d83cf7b476e23615987902f801e5788dee15ee9f24a9 \ + --hash=sha256:36e8e32621a9e2a9abe75dc15a4b54a3997f2d8b1e53ad754bae48a083c91130 \ + --hash=sha256:40c5220ec93790b18ec6278da9c6ac2608d997ee6d6f7cd44c5c3992764e8e71 \ + --hash=sha256:446d500a2977c6ae2077f340c510a25956da5c77597175c316edfa87248ceda3 \ + --hash=sha256:46f92ada9023e59f27edc048167b31ac9a03911978b1296c845a34462a27f096 \ + --hash=sha256:482f8a13f2600f527e427f73c42b5aa75536f9892868068f0aaf573055a0135f \ + --hash=sha256:553c273a6a8f140adaa6da6a6135c7f95bdc8c2e5f95252fcdf9832d758e2141 \ + --hash=sha256:5ae7c0d744d64e2753149634787cc4ab60f05ef1e542b060eeab719f3cdb7723 \ + --hash=sha256:5d4147422d91ccdc2d2abf6ed24196025e020259d1d267970ae20c13c2ce84b1 \ + --hash=sha256:6af347debc8b721aa72e48671166282da979d5e5ae52dbc660ab417282b48e23 \ + --hash=sha256:6ba302115f63f6482c000ccfd62efdb6c41d9d182a5bcd4a90e7ab8cd13856eb \ + --hash=sha256:6f7361d66cc801d9eb4df734b139cd7b0e3c257a16f3573ebd550ddb255549e6 \ + --hash=sha256:715f05ea198d20d7f8b407b9b84e0023d17f2b9096c194cea702b7840e74f1f7 \ + --hash=sha256:71dddcebbc5a70e946a06c30b59b5dd7999c9833d307168f90fb4e4b672ab63e \ + --hash=sha256:8150c569b2aa4573b51ba8475e814aa41fd53a3d510c1ffb96f1139f46faf611 \ + --hash=sha256:8843bd9594e1387f1e601439e19ad73abdf57356104fd1e53a708255bb95a13d \ + --hash=sha256:8c0088765747ae5d6c9f89987bb36f9fb83564f07090d721344ce8e1abedffea \ + --hash=sha256:972d0dbf283508f9bc446ee09c3838cb7c7f114b5bdceee41753288c97fe2f7c \ + --hash=sha256:a28531cee2a5a42d89f9ba4da53bfeb15681f12acc0263476c8705380dadce07 \ + --hash=sha256:a3be2072315982e232bfe49c9d3db0a59ba67b2240a537ef42656cc772a887c7 \ + --hash=sha256:ac2804043bd1bc10b5da18f8f4c706877197263a510c41be9b4c0062f5783dcc \ + --hash=sha256:afab8b4b1f4469c3879bb049dd039f8fce402712050324e9524a43d7324c5e87 \ + --hash=sha256:b370d1620a34a4538ef66524fcee9de8171fa263c701036a92bc0b4c1f2f9c6d \ + --hash=sha256:b8b0808dba0c63b7633bdaefb34e08fe0612622224f9feb0e7518904b1615101 \ + --hash=sha256:bc7ca6a1a40e7e4c933017e6c09ef18032add793df4e42624c6c0c87e0bebdad \ + --hash=sha256:caa65e1f5bf007430bf657c37cab7ab81a4ddf8d337e3062bcc5085d17ef038b \ + --hash=sha256:d68c5a01a283cb13b79eafe016fe5869aa11bff8c46e7141c70aa0aac808010f \ + --hash=sha256:da137802688190835b4c863cafa77fd7e29dff662ee6d905a9ffc14f00299c91 \ + --hash=sha256:e56a20ab6cdb90a95b0c99652e28de3504ce77129087319c03c9098266183ae5 \ + --hash=sha256:e878ccb7d20872065e1597935fdb5e65efa43220c8edd0d9c4a1a7ff1f3eb277 \ + --hash=sha256:eba81e0b3011c1f23df7ea47ef4ffaa8239817959ae291515b6efd068bde2161 \ + --hash=sha256:ed6d23a3f806898e69c77430ebd8da0c79c219f97b9acbc9a29a653e09740c59 # via ibis-framework durationpy==0.10 \ --hash=sha256:1fa6893409a6e739c9c72334fc65cca1f355dbdd93405d30f726deb5bde42fba \ @@ -1154,9 +1192,9 @@ execnet==2.1.2 \ --hash=sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd \ --hash=sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec # via pytest-xdist -executing==1.2.0 \ - --hash=sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc \ - --hash=sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107 +executing==2.2.1 \ + --hash=sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4 \ + --hash=sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017 # via # codeflare-sdk # stack-data @@ -1187,9 +1225,9 @@ faiss-cpu==1.10.0 \ --hash=sha256:e71f7e24d5b02d3a51df47b77bd10f394a1b48a8331d5c817e71e9e27a8a75ac \ --hash=sha256:f71c5860c860df2320299f9e4f2ca1725beb559c04acb1cf961ed24e6218277a # via feast (pyproject.toml) -fastapi==0.129.0 \ - --hash=sha256:61315cebd2e65df5f97ec298c888f9de30430dd0612d59d6480beafbc10655af \ - --hash=sha256:b4946880e48f462692b31c083be0432275cbfb6e2274566b1be91479cc1a84ec +fastapi==0.135.3 \ + --hash=sha256:9b0f590c813acd13d0ab43dd8494138eb58e484bfac405db1f3187cfc5810d98 \ + --hash=sha256:bd6d7caf1a2bdd8d676843cdcd2287729572a1ef524fc4d65c17ae002a1be654 # via # feast (pyproject.toml) # fastapi-mcp @@ -1201,9 +1239,9 @@ fastjsonschema==2.21.2 \ --hash=sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463 \ --hash=sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de # via nbformat -filelock==3.24.2 \ - --hash=sha256:667d7dc0b7d1e1064dd5f8f8e80bdac157a6482e8d2e02cd16fd3b6b33bd6556 \ - --hash=sha256:c22803117490f156e59fafce621f0550a7a853e2bbf4f87f112b11d469b6c81b +filelock==3.25.2 \ + --hash=sha256:b64ece2b38f4ca29dd3e810287aa8c48182bbecd1ae6e9ae126c9b35f1382694 \ + --hash=sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70 # via # datasets # huggingface-hub @@ -1368,9 +1406,9 @@ geomet==1.1.0 \ --hash=sha256:4372fe4e286a34acc6f2e9308284850bd8c4aa5bc12065e2abbd4995900db12f \ --hash=sha256:51e92231a0ef6aaa63ac20c443377ba78a303fd2ecd179dc3567de79f3c11605 # via cassandra-driver -google-api-core[grpc]==2.29.0 \ - --hash=sha256:84181be0f8e6b04006df75ddfe728f24489f0af57c96a529ff7cf45bc28797f7 \ - --hash=sha256:d30bc60980daa36e314b5d5a3e5958b0200cb44ca8fa1be2b614e932b75a3ea9 +google-api-core[grpc]==2.30.2 \ + --hash=sha256:9a8113e1a88bdc09a7ff629707f2214d98d61c7f6ceb0ea38c42a095d02dc0f9 \ + --hash=sha256:a4c226766d6af2580577db1f1a51bf53cd262f722b49731ce7414c43068a9594 # via # feast (pyproject.toml) # google-cloud-bigquery @@ -1381,9 +1419,9 @@ google-api-core[grpc]==2.29.0 \ # google-cloud-storage # opencensus # pandas-gbq -google-auth==2.48.0 \ - --hash=sha256:2e2a537873d449434252a9632c28bfc268b0adb1e53f9fb62afc5333a975903f \ - --hash=sha256:4f7e706b0cd3208a3d940a19a822c37a476ddba5450156c3e6624a71f7c841ce +google-auth==2.49.1 \ + --hash=sha256:16d40da1c3c5a0533f57d268fe72e0ebb0ae1cc3b567024122651c045d879b64 \ + --hash=sha256:195ebe3dca18eddd1b3db5edc5189b76c13e96f29e73043b923ebcf3f1a860f7 # via # google-api-core # google-auth-oauthlib @@ -1395,37 +1433,37 @@ google-auth==2.48.0 \ # google-cloud-storage # pandas-gbq # pydata-google-auth -google-auth-oauthlib==1.2.4 \ - --hash=sha256:0e922eea5f2baacaf8867febb782e46e7b153236c21592ed76ab3ddb77ffd772 \ - --hash=sha256:3ca93859c6cc9003c8e12b2a0868915209d7953f05a70f4880ab57d57e56ee3e +google-auth-oauthlib==1.3.1 \ + --hash=sha256:14c22c7b3dd3d06dbe44264144409039465effdd1eef94f7ce3710e486cc4bfa \ + --hash=sha256:1a139ef23f1318756805b0e95f655c238bffd29655329a2978218248da4ee7f8 # via # pandas-gbq # pydata-google-auth -google-cloud-bigquery[pandas]==3.40.1 \ - --hash=sha256:75afcfb6e007238fe1deefb2182105249321145ff921784fe7b1de2b4ba24506 \ - --hash=sha256:9082a6b8193aba87bed6a2c79cf1152b524c99bb7e7ac33a785e333c09eac868 +google-cloud-bigquery[pandas]==3.41.0 \ + --hash=sha256:2217e488b47ed576360c9b2cc07d59d883a54b83167c0ef37f915c26b01a06fe \ + --hash=sha256:2a5b5a737b401cbd824a6e5eac7554100b878668d908e6548836b5d8aaa4dcaa # via # feast (pyproject.toml) # pandas-gbq -google-cloud-bigquery-storage==2.36.1 \ - --hash=sha256:99ad6b8810d028f0cf368ea0cc54b3cda20e856f05eb4cda51f1db2a70692286 \ - --hash=sha256:fd3917584a41f7a9d9c633b31ff43103869b108224e8a4b765537eb1ea83148c +google-cloud-bigquery-storage==2.37.0 \ + --hash=sha256:1e319c27ef60fc31030f6e0b52e5e891e1cdd50551effe8c6f673a4c3c56fcb6 \ + --hash=sha256:f88ee7f1e49db1e639da3d9a8b79835ca4bc47afbb514fb2adfc0ccb41a7fd97 # via feast (pyproject.toml) -google-cloud-bigtable==2.35.0 \ - --hash=sha256:f355bfce1f239453ec2bb3839b0f4f9937cf34ef06ef29e1ca63d58fd38d0c50 \ - --hash=sha256:f5699012c5fea4bd4bdf7e80e5e3a812a847eb8f41bf8dc2f43095d6d876b83b +google-cloud-bigtable==2.36.0 \ + --hash=sha256:21b2f41231b7368a550b44d5b493b811b3507fcb23eb26d00005cd3f205f2207 \ + --hash=sha256:d5987733c2f60c739f93f259d2037858411cc994ac37cdfbccb6bb159f3ca43e # via feast (pyproject.toml) -google-cloud-core==2.5.0 \ - --hash=sha256:67d977b41ae6c7211ee830c7912e41003ea8194bff15ae7d72fd6f51e57acabc \ - --hash=sha256:7c1b7ef5c92311717bd05301aa1a91ffbc565673d3b0b4163a52d8413a186963 +google-cloud-core==2.5.1 \ + --hash=sha256:3dc94bdec9d05a31d9f355045ed0f369fbc0d8c665076c734f065d729800f811 \ + --hash=sha256:ea62cdf502c20e3e14be8a32c05ed02113d7bef454e40ff3fab6fe1ec9f1f4e7 # via # google-cloud-bigquery # google-cloud-bigtable # google-cloud-datastore # google-cloud-storage -google-cloud-datastore==2.23.0 \ - --hash=sha256:24a1b1d29b902148fe41b109699f76fd3aa60591e9d547c0f8b87d7bf9ff213f \ - --hash=sha256:80049883a4ae928fdcc661ba6803ec267665dc0e6f3ce2da91441079a6bb6387 +google-cloud-datastore==2.24.0 \ + --hash=sha256:81f1d1c12c2906f59507f72742545ab04c38f62ed70b0542057e3cf04a53aa65 \ + --hash=sha256:f087c02a6aa4ac68bbf17f0c048ae3ee355856bf09c51439bfba193741387792 # via feast (pyproject.toml) google-cloud-storage==2.19.0 \ --hash=sha256:aeb971b5c29cf8ab98445082cbfe7b161a1f48ed275822f59ed3f1524ea54fba \ @@ -1469,15 +1507,15 @@ google-crc32c==1.8.0 \ # google-cloud-bigtable # google-cloud-storage # google-resumable-media -google-resumable-media==2.8.0 \ - --hash=sha256:dd14a116af303845a8d932ddae161a26e86cc229645bc98b39f026f9b1717582 \ - --hash=sha256:f1157ed8b46994d60a1bc432544db62352043113684d4e030ee02e77ebe9a1ae +google-resumable-media==2.8.2 \ + --hash=sha256:82b6d8ccd11765268cdd2a2123f417ec806b8eef3000a9a38dfe3033da5fb220 \ + --hash=sha256:f3354a182ebd193ae3f42e3ef95e6c9b10f128320de23ac7637236713b1acd70 # via # google-cloud-bigquery # google-cloud-storage -googleapis-common-protos[grpc]==1.72.0 \ - --hash=sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038 \ - --hash=sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5 +googleapis-common-protos[grpc]==1.74.0 \ + --hash=sha256:57971e4eeeba6aad1163c1f0fc88543f965bb49129b8bb55b2b7b26ecab084f1 \ + --hash=sha256:702216f78610bb510e3f12ac3cafd281b7ac45cc5d86e90ad87e4d301a3426b5 # via # feast (pyproject.toml) # google-api-core @@ -1487,9 +1525,9 @@ great-expectations==0.18.8 \ --hash=sha256:ab41cfa3de829a4f77bdcd4a23244684cbb67fdacc734d38910164cd02ec95b6 \ --hash=sha256:c1205bede593f679e22e0b3826d6ae1623c439cafd553f9f0bc2b0fd441f6ed9 # via feast (pyproject.toml) -grpc-google-iam-v1==0.14.3 \ - --hash=sha256:7a7f697e017a067206a3dfef44e4c634a34d3dee135fe7d7a4613fe3e59217e6 \ - --hash=sha256:879ac4ef33136c5491a6300e27575a9ec760f6cdf9a2518798c1b8977a5dc389 +grpc-google-iam-v1==0.14.4 \ + --hash=sha256:392b3796947ed6334e61171d9ab06bf7eb357f554e5fc7556ad7aab6d0e17038 \ + --hash=sha256:412facc320fcbd94034b4df3d557662051d4d8adfa86e0ddb4dca70a3f739964 # via google-cloud-bigtable grpcio==1.62.3 \ --hash=sha256:059444f0ed5dba73ab7dd0ee7e8e6b606df4130d2b0a9f010f84da4ab9f6c2d8 \ @@ -1559,7 +1597,6 @@ grpcio==1.62.3 \ # grpcio-status # grpcio-testing # grpcio-tools - # ikvpy # pymilvus # qdrant-client # ray @@ -1574,9 +1611,7 @@ grpcio-reflection==1.62.3 \ grpcio-status==1.62.3 \ --hash=sha256:289bdd7b2459794a12cf95dc0cb727bd4a1742c37bd823f760236c937e53a485 \ --hash=sha256:f9049b762ba8de6b1086789d8315846e094edac2c50beaf462338b301a8fd4b8 - # via - # google-api-core - # ikvpy + # via google-api-core grpcio-testing==1.62.3 \ --hash=sha256:06a4d7eb30d22f91368aa7f48bfc33563da13b9d951314455ca8c9c987fb75bb \ --hash=sha256:f63577f28aaa95ea525124a0fd63c3429d71f769f4179b13f5e6cbc54979bfab @@ -1631,9 +1666,9 @@ grpcio-tools==1.62.3 \ --hash=sha256:f4b1615adf67bd8bb71f3464146a6f9949972d06d21a4f5e87e73f6464d97f57 \ --hash=sha256:f6831fdec2b853c9daa3358535c55eed3694325889aa714070528cf8f92d7d6d # via feast (pyproject.toml) -gunicorn==25.1.0 \ - --hash=sha256:1426611d959fa77e7de89f8c0f32eed6aa03ee735f98c01efba3e281b1c47616 \ - --hash=sha256:d0b1236ccf27f72cfe14bce7caadf467186f19e865094ca84221424e839b8b8b +gunicorn==25.3.0 \ + --hash=sha256:cacea387dab08cd6776501621c295a904fe8e3b7aae9a1a3cbb26f4e7ed54660 \ + --hash=sha256:f74e1b2f9f76f6cd1ca01198968bd2dd65830edc24b6e8e4d78de8320e2fe889 # via # feast (pyproject.toml) # uvicorn-worker @@ -1655,29 +1690,32 @@ hazelcast-python-client==5.6.0 \ --hash=sha256:834b87076a47c781ef80bdcb522b86abc75ff28992dfe384e47f669f06cabb18 \ --hash=sha256:e2cec409068990ca9b4381fe97160cc2375412334782bef45ab4c8fe4d10536c # via feast (pyproject.toml) -hf-xet==1.2.0 \ - --hash=sha256:10bfab528b968c70e062607f663e21e34e2bba349e8038db546646875495179e \ - --hash=sha256:210d577732b519ac6ede149d2f2f34049d44e8622bf14eb3d63bbcd2d4b332dc \ - --hash=sha256:27df617a076420d8845bea087f59303da8be17ed7ec0cd7ee3b9b9f579dff0e4 \ - --hash=sha256:293a7a3787e5c95d7be1857358a9130694a9c6021de3f27fa233f37267174382 \ - --hash=sha256:29c8fc913a529ec0a91867ce3d119ac1aac966e098cf49501800c870328cc090 \ - --hash=sha256:2a212e842647b02eb6a911187dc878e79c4aa0aa397e88dd3b26761676e8c1f8 \ - --hash=sha256:30e06daccb3a7d4c065f34fc26c14c74f4653069bb2b194e7f18f17cbe9939c0 \ - --hash=sha256:3651fd5bfe0281951b988c0facbe726aa5e347b103a675f49a3fa8144c7968fd \ - --hash=sha256:46740d4ac024a7ca9b22bebf77460ff43332868b661186a8e46c227fdae01848 \ - --hash=sha256:4c1428c9ae73ec0939410ec73023c4f842927f39db09b063b9482dac5a3bb737 \ - --hash=sha256:66e159cbfcfbb29f920db2c09ed8b660eb894640d284f102ada929b6e3dc410a \ - --hash=sha256:6de1fc44f58f6dd937956c8d304d8c2dea264c80680bcfa61ca4a15e7b76780f \ - --hash=sha256:7d40b18769bb9a8bc82a9ede575ce1a44c75eb80e7375a01d76259089529b5dc \ - --hash=sha256:9c91d5ae931510107f148874e9e2de8a16052b6f1b3ca3c1b12f15ccb491390f \ - --hash=sha256:a55558084c16b09b5ed32ab9ed38421e2d87cf3f1f89815764d1177081b99865 \ - --hash=sha256:a8c27070ca547293b6890c4bf389f713f80e8c478631432962bb7f4bc0bd7d7f \ - --hash=sha256:b70218dd548e9840224df5638fdc94bd033552963cfa97f9170829381179c813 \ - --hash=sha256:cd3a6027d59cfb60177c12d6424e31f4b5ff13d8e3a1247b3a584bf8977e6df5 \ - --hash=sha256:ceeefcd1b7aed4956ae8499e2199607765fbd1c60510752003b6cc0b8413b649 \ - --hash=sha256:d06fa97c8562fb3ee7a378dd9b51e343bc5bc8190254202c9771029152f5e08c \ - --hash=sha256:e6584a52253f72c9f52f9e549d5895ca7a471608495c4ecaa6cc73dba2b24d69 \ - --hash=sha256:f182f264ed2acd566c514e45da9f2119110e48a87a327ca271027904c70c5832 +hf-xet==1.4.3 \ + --hash=sha256:0392c79b7cf48418cd61478c1a925246cf10639f4cd9d94368d8ca1e8df9ea07 \ + --hash=sha256:1feb0f3abeacee143367c326a128a2e2b60868ec12a36c225afb1d6c5a05e6d2 \ + --hash=sha256:21644b404bb0100fe3857892f752c4d09642586fd988e61501c95bbf44b393a3 \ + --hash=sha256:22bdc1f5fb8b15bf2831440b91d1c9bbceeb7e10c81a12e8d75889996a5c9da8 \ + --hash=sha256:27c976ba60079fb8217f485b9c5c7fcd21c90b0367753805f87cb9f3cdc4418a \ + --hash=sha256:2815a49a7a59f3e2edf0cf113ae88e8cb2ca2a221bf353fb60c609584f4884d4 \ + --hash=sha256:39f2d2e9654cd9b4319885733993807aab6de9dfbd34c42f0b78338d6617421f \ + --hash=sha256:42ee323265f1e6a81b0e11094564fb7f7e0ec75b5105ffd91ae63f403a11931b \ + --hash=sha256:49ad8a8cead2b56051aa84d7fce3e1335efe68df3cf6c058f22a65513885baac \ + --hash=sha256:5251d5ece3a81815bae9abab41cf7ddb7bcb8f56411bce0827f4a3071c92fdc6 \ + --hash=sha256:60cf7fc43a99da0a853345cf86d23738c03983ee5249613a6305d3e57a5dca74 \ + --hash=sha256:681c92a07796325778a79d76c67011764ecc9042a8c3579332b61b63ae512075 \ + --hash=sha256:6b591fcad34e272a5b02607485e4f2a1334aebf1bc6d16ce8eb1eb8978ac2021 \ + --hash=sha256:7551659ba4f1e1074e9623996f28c3873682530aee0a846b7f2f066239228144 \ + --hash=sha256:7716d62015477a70ea272d2d68cd7cad140f61c52ee452e133e139abfe2c17ba \ + --hash=sha256:7c2c7e20bcfcc946dc67187c203463f5e932e395845d098cc2a93f5b67ca0b47 \ + --hash=sha256:8b301fc150290ca90b4fccd079829b84bb4786747584ae08b94b4577d82fb791 \ + --hash=sha256:8ddedb73c8c08928c793df2f3401ec26f95be7f7e516a7bee2fbb546f6676113 \ + --hash=sha256:987f09cfe418237812896a6736b81b1af02a3a6dcb4b4944425c4c4fca7a7cf8 \ + --hash=sha256:bee693ada985e7045997f05f081d0e12c4c08bd7626dc397f8a7c487e6c04f7f \ + --hash=sha256:c5b48db1ee344a805a1b9bd2cda9b6b65fe77ed3787bd6e87ad5521141d317cd \ + --hash=sha256:d0da85329eaf196e03e90b84c2d0aca53bd4573d097a75f99609e80775f98025 \ + --hash=sha256:d972fbe95ddc0d3c0fc49b31a8a69f47db35c1e3699bf316421705741aab6653 \ + --hash=sha256:e23717ce4186b265f69afa66e6f0069fe7efbf331546f5c313d00e123dc84583 \ + --hash=sha256:fc360b70c815bf340ed56c7b8c63aacf11762a4b099b2fe2c9bd6d6068668c08 # via huggingface-hub hiredis==2.4.0 \ --hash=sha256:06815c3b9bf7225c4dcc9dd9dfb5a9fa91b4f680104443ef3fcd78410d7eb027 \ @@ -1852,6 +1890,7 @@ huggingface-hub==0.36.2 \ # datasets # docling # docling-ibm-models + # sentence-transformers # timm # tokenizers # transformers @@ -1859,13 +1898,13 @@ hyperframe==6.1.0 \ --hash=sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5 \ --hash=sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08 # via h2 -ibis-framework[duckdb, mssql]==12.0.0 \ +ibis-framework[duckdb, mssql, oracle]==12.0.0 \ --hash=sha256:0bbd790f268da9cb87926d5eaad2b827a573927113c4ed3be5095efa89b9e512 \ --hash=sha256:238624f2c14fdab8382ca2f4f667c3cdb81e29844cd5f8db8a325d0743767c61 # via feast (pyproject.toml) -identify==2.6.16 \ - --hash=sha256:391ee4d77741d994189522896270b787aed8670389bfd60f326d677d64a6dfb0 \ - --hash=sha256:846857203b5511bbe94d5a352a48ef2359532bc8f6727b5544077a0dcfb24980 +identify==2.6.18 \ + --hash=sha256:873ac56a5e3fd63e7438a7ecbc4d91aca692eb3fefa4534db2b7913f3fc352fd \ + --hash=sha256:8db9d3c8ea9079db92cafb0ebf97abdc09d52e97f4dcf773a2e694048b7cd737 # via pre-commit idna==3.11 \ --hash=sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea \ @@ -1877,17 +1916,13 @@ idna==3.11 \ # requests # snowflake-connector-python # yarl -ikvpy==0.0.36 \ - --hash=sha256:b0edf6fb6482877940f6c2b5d59a7fabe30cb554b13b88ca52805f043cfda5b3 \ - --hash=sha256:c0ce7dfb61456c283c9ba2cdeb68b3647f245c3905bca652ca2a1068804939d1 - # via feast (pyproject.toml) -imageio==2.37.2 \ - --hash=sha256:0212ef2727ac9caa5ca4b2c75ae89454312f440a756fcfc8ef1993e718f50f8a \ - --hash=sha256:ad9adfb20335d718c03de457358ed69f141021a333c40a53e57273d8a5bd0b9b +imageio==2.37.3 \ + --hash=sha256:46f5bb8522cd421c0f5ae104d8268f569d856b29eb1a13b92829d1970f32c9f0 \ + --hash=sha256:bbb37efbfc4c400fcd534b367b91fcd66d5da639aaa138034431a1c5e0a41451 # via scikit-image -imagesize==1.4.1 \ - --hash=sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b \ - --hash=sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a +imagesize==2.0.0 \ + --hash=sha256:5667c5bbb57ab3f1fa4bc366f4fbc971db3d5ed011fd2715fd8001f782718d96 \ + --hash=sha256:8e8358c4a05c304f1fccf7ff96f036e7243a189e9e42e90851993c558cfe9ee3 # via sphinx importlib-metadata==8.7.1 \ --hash=sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb \ @@ -1909,9 +1944,9 @@ ipykernel==7.2.0 \ --hash=sha256:18ed160b6dee2cbb16e5f3575858bc19d8f1fe6046a9a680c708494ce31d909e \ --hash=sha256:3bbd4420d2b3cc105cbdf3756bfc04500b1e52f090a90716851f3916c62e1661 # via jupyterlab -ipython==9.10.0 \ - --hash=sha256:c6ab68cc23bba8c7e18e9b932797014cc61ea7fd6f19de180ab9ba73e65ee58d \ - --hash=sha256:cd9e656be97618a0676d058134cd44e6dc7012c0e5cb36a9ce96a8c904adaf77 +ipython==9.12.0 \ + --hash=sha256:01daa83f504b693ba523b5a407246cabde4eb4513285a3c6acaff11a66735ee4 \ + --hash=sha256:0f2701e8ee86e117e37f50563205d36feaa259d2e08d4a6bc6b6d74b18ce128d # via # great-expectations # ipykernel @@ -1963,9 +1998,9 @@ joblib==1.5.3 \ --hash=sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713 \ --hash=sha256:8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3 # via scikit-learn -json5==0.13.0 \ - --hash=sha256:9a08e1dd65f6a4d4c6fa82d216cf2477349ec2346a38fd70cc11d2557499fbcc \ - --hash=sha256:b1edf8d487721c0bf64d83c28e91280781f6e21f4a797d3261c7c828d4c165bf +json5==0.14.0 \ + --hash=sha256:56cf861bab076b1178eb8c92e1311d273a9b9acea2ccc82c276abf839ebaef3a \ + --hash=sha256:b3f492fad9f6cdbced8b7d40b28b9b1c9701c5f561bef0d33b81c2ff433fefcb # via jupyterlab-server jsonlines==4.0.0 \ --hash=sha256:0c6d2c09117550c089995247f605ae4cf77dd1533041d366351f6f298822ea74 \ @@ -1975,9 +2010,9 @@ jsonpatch==1.33 \ --hash=sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade \ --hash=sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c # via great-expectations -jsonpointer==3.0.0 \ - --hash=sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942 \ - --hash=sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef +jsonpointer==3.1.1 \ + --hash=sha256:0b801c7db33a904024f6004d526dcc53bbb8a4a0f4e32bfd10beadf60adf1900 \ + --hash=sha256:8ff8b95779d071ba472cf5bc913028df06031797532f08a7d5b602d8b2a488ca # via # jsonpatch # jsonschema @@ -2024,9 +2059,9 @@ jupyter-events==0.12.0 \ --hash=sha256:6464b2fa5ad10451c3d35fabc75eab39556ae1e2853ad0c0cc31b656731a97fb \ --hash=sha256:fc3fce98865f6784c9cd0a56a20644fc6098f21c8c33834a8d9fe383c17e554b # via jupyter-server -jupyter-lsp==2.3.0 \ - --hash=sha256:458aa59339dc868fb784d73364f17dbce8836e906cd75fd471a325cba02e0245 \ - --hash=sha256:e914a3cb2addf48b1c7710914771aaf1819d46b2e5a79b0f917b5478ec93f34f +jupyter-lsp==2.3.1 \ + --hash=sha256:71b954d834e85ff3096400554f2eefaf7fe37053036f9a782b0f7c5e42dadb81 \ + --hash=sha256:fdf8a4aa7d85813976d6e29e95e6a2c8f752701f926f2715305249a3829805a6 # via jupyterlab jupyter-server==2.17.0 \ --hash=sha256:c38ea898566964c888b4772ae1ed58eca84592e88251d2cfc4d171f81f7e99d5 \ @@ -2041,9 +2076,9 @@ jupyter-server-terminals==0.5.4 \ --hash=sha256:55be353fc74a80bc7f3b20e6be50a55a61cd525626f578dcb66a5708e2007d14 \ --hash=sha256:bbda128ed41d0be9020349f9f1f2a4ab9952a73ed5f5ac9f1419794761fb87f5 # via jupyter-server -jupyterlab==4.5.4 \ - --hash=sha256:c215f48d8e4582bd2920ad61cc6a40d8ebfef7e5a517ae56b8a9413c9789fdfb \ - --hash=sha256:cc233f70539728534669fb0015331f2a3a87656207b3bb2d07916e9289192f12 +jupyterlab==4.5.6 \ + --hash=sha256:642fe2cfe7f0f5922a8a558ba7a0d246c7bc133b708dfe43f7b3a826d163cf42 \ + --hash=sha256:d6b3dac883aa4d9993348e0f8e95b24624f75099aed64eab6a4351a9cdd1e580 # via notebook jupyterlab-pygments==0.3.0 \ --hash=sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d \ @@ -2063,23 +2098,28 @@ jwcrypto==1.5.6 \ --hash=sha256:150d2b0ebbdb8f40b77f543fb44ffd2baeff48788be71f67f03566692fd55789 \ --hash=sha256:771a87762a0c081ae6166958a954f80848820b2ab066937dc8b8379d65b1b039 # via python-keycloak +kube-authkit==0.4.0 \ + --hash=sha256:1df61ac392fca96c8f5ae8c3d6e9918f1e1655d212434b3c3da5f92cc23b660d \ + --hash=sha256:3bf5fc6ddc882498040118c907628ea68789f9a947454c241972008be59601a3 + # via codeflare-sdk kubernetes==35.0.0 \ --hash=sha256:39e2b33b46e5834ef6c3985ebfe2047ab39135d41de51ce7641a7ca5b372a13d \ --hash=sha256:3d00d344944239821458b9efd484d6df9f011da367ecb155dadf9513f05f09ee # via # feast (pyproject.toml) # codeflare-sdk + # kube-authkit lark==1.3.1 \ --hash=sha256:b426a7a6d6d53189d318f2b6236ab5d6429eaf09259f1ca33eb716eed10d2905 \ --hash=sha256:c629b661023a014c37da873b4ff58a817398d12635d3bbb2c5a03be7fe5d1e12 # via rfc3987-syntax -latex2mathml==3.78.1 \ - --hash=sha256:f089b6d75e85b937f99693c93e8c16c0804008672c3dd2a3d25affd36f238100 \ - --hash=sha256:f941db80bf41db33f31df87b304e8b588f8166b813b0257c11c98f7a9d0aac71 +latex2mathml==3.79.0 \ + --hash=sha256:11bde318c2d2d6fcdd105a07509d867cee2208f653278eb80243dec7ea77a0ce \ + --hash=sha256:9f10720d4fcf6b22d1b81f6628237832419a7a29783c13aa92fa8d680165e63d # via docling-core -lazy-loader==0.4 \ - --hash=sha256:342aa8e14d543a154047afb4ba8ef17f5563baad3fc610d7b15b213b0f119efc \ - --hash=sha256:47c75182589b91a4e1a85a136c074285a5ad4d9f39c63e0d7fb76391c4574cd1 +lazy-loader==0.5 \ + --hash=sha256:717f9179a0dbed357012ddad50a5ad3d5e4d9a0b8712680d4e687f5e6e6ed9b3 \ + --hash=sha256:ab0ea149e9c554d4ffeeb21105ac60bed7f3b4fd69b1d2360a4add51b170b005 # via scikit-image locket==1.0.0 \ --hash=sha256:5c0d4c052a8bbbf750e056a8e65ccd309086f4f0f18a2eac306a8dfa4112a632 \ @@ -2399,9 +2439,9 @@ matplotlib-inline==0.2.1 \ # via # ipykernel # ipython -mcp==1.26.0 \ - --hash=sha256:904a21c33c25aa98ddbeb47273033c435e595bbacfdb177f4bd87f6dceebe1ca \ - --hash=sha256:db6e2ef491eecc1a0d93711a76f28dec2e05999f93afd48795da1c1137142c66 +mcp==1.27.0 \ + --hash=sha256:5ce1fa81614958e267b21fb2aa34e0aea8e2c6ede60d52aba45fd47246b4d741 \ + --hash=sha256:d3dc35a7eec0d458c1da4976a48f982097ddaab87e278c5511d5a4a56e852b83 # via fastapi-mcp mdurl==0.1.2 \ --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ @@ -2425,128 +2465,114 @@ mistune==3.2.0 \ # via # great-expectations # nbconvert -mmh3==5.2.0 \ - --hash=sha256:03e08c6ebaf666ec1e3d6ea657a2d363bb01effd1a9acfe41f9197decaef0051 \ - --hash=sha256:097e13c8b8a66c5753c6968b7640faefe85d8e38992703c1f666eda6ef4c3762 \ - --hash=sha256:0b898cecff57442724a0f52bf42c2de42de63083a91008fb452887e372f9c328 \ - --hash=sha256:10983c10f5c77683bd845751905ba535ec47409874acc759d5ce3ff7ef34398a \ - --hash=sha256:11730eeb16dfcf9674fdea9bb6b8e6dd9b40813b7eb839bc35113649eef38aeb \ - --hash=sha256:127c95336f2a98c51e7682341ab7cb0be3adb9df0819ab8505a726ed1801876d \ - --hash=sha256:12da42c0a55c9d86ab566395324213c319c73ecb0c239fad4726324212b9441c \ - --hash=sha256:132dd943451a7c7546978863d2f5a64977928410782e1a87d583cb60eb89e667 \ - --hash=sha256:1556e31e4bd0ac0c17eaf220be17a09c171d7396919c3794274cb3415a9d3646 \ - --hash=sha256:1a5f4d2e59d6bba8ef01b013c472741835ad961e7c28f50c82b27c57748744a4 \ - --hash=sha256:1ba55d6ca32eeef8b2625e1e4bfc3b3db52bc63014bd7e5df8cc11bf2b036b12 \ - --hash=sha256:1efc8fec8478e9243a78bb993422cf79f8ff85cb4cf6b79647480a31e0d950a8 \ - --hash=sha256:1f8d8b627799f4e2fcc7c034fed8f5f24dc7724ff52f69838a3d6d15f1ad4765 \ - --hash=sha256:1fae471339ae1b9c641f19cf46dfe6ffd7f64b1fba7c4333b99fa3dd7f21ae0a \ - --hash=sha256:1fdb36b940e9261aff0b5177c5b74a36936b902f473180f6c15bde26143681a9 \ - --hash=sha256:2421b9d665a0b1ad724ec7332fb5a98d075f50bc51a6ff854f3a1882bd650d49 \ - --hash=sha256:29c2b9ce61886809d0492a274a5a53047742dea0f703f9c4d5d223c3ea6377d3 \ - --hash=sha256:2c9da0d568569cc87315cb063486d761e38458b8ad513fedd3dc9263e1b81bcd \ - --hash=sha256:2ebfc46b39168ab1cd44670a32ea5489bcbc74a25795c61b6d888c5c2cf654ed \ - --hash=sha256:3193752fc05ea72366c2b63ff24b9a190f422e32d75fdeae71087c08fff26115 \ - --hash=sha256:33576136c06b46a7046b6d83a3d75fbca7d25f84cec743f1ae156362608dc6d2 \ - --hash=sha256:37a358cc881fe796e099c1db6ce07ff757f088827b4e8467ac52b7a7ffdca647 \ - --hash=sha256:382a6bb3f8c6532ea084e7acc5be6ae0c6effa529240836d59352398f002e3fc \ - --hash=sha256:384eda9361a7bf83a85e09447e1feafe081034af9dd428893701b959230d84be \ - --hash=sha256:38d899a156549da8ef6a9f1d6f7ef231228d29f8f69bce2ee12f5fba6d6fd7c5 \ - --hash=sha256:3bc244802ccab5220008cb712ca1508cb6a12f0eb64ad62997156410579a1770 \ - --hash=sha256:3c6041fd9d5fb5fcac57d5c80f521a36b74aea06b8566431c63e4ffc49aced51 \ - --hash=sha256:3ca975c51c5028947bbcfc24966517aac06a01d6c921e30f7c5383c195f87991 \ - --hash=sha256:3d6bfd9662a20c054bc216f861fa330c2dac7c81e7fb8307b5e32ab5b9b4d2e0 \ - --hash=sha256:419005f84ba1cab47a77465a2a843562dadadd6671b8758bf179d82a15ca63eb \ - --hash=sha256:45b590e31bc552c6f8e2150ff1ad0c28dd151e9f87589e7eaf508fbdd8e8e908 \ - --hash=sha256:49037d417419863b222ae47ee562b2de9c3416add0a45c8d7f4e864be8dc4f89 \ - --hash=sha256:4a5f5536b1cbfa72318ab3bfc8a8188b949260baed186b75f0abc75b95d8c051 \ - --hash=sha256:582f9dbeefe15c32a5fa528b79b088b599a1dfe290a4436351c6090f90ddebb8 \ - --hash=sha256:58477cf9ef16664d1ce2b038f87d2dc96d70fe50733a34a7f07da6c9a5e3538c \ - --hash=sha256:58981d6ea9646dbbf9e59a30890cbf9f610df0e4a57dbfe09215116fd90b0093 \ - --hash=sha256:5a5dba98e514fb26241868f6eb90a7f7ca0e039aed779342965ce24ea32ba513 \ - --hash=sha256:5b0b58215befe0f0e120b828f7645e97719bbba9f23b69e268ed0ac7adde8645 \ - --hash=sha256:61ac226af521a572700f863d6ecddc6ece97220ce7174e311948ff8c8919a363 \ - --hash=sha256:63830f846797187c5d3e2dae50f0848fdc86032f5bfdc58ae352f02f857e9025 \ - --hash=sha256:69fc339d7202bea69ef9bd7c39bfdf9fdabc8e6822a01eba62fb43233c1b3932 \ - --hash=sha256:6d541038b3fc360ec538fc116de87462627944765a6750308118f8b509a8eec7 \ - --hash=sha256:6ecb4e750d712abde046858ee6992b65c93f1f71b397fce7975c3860c07365d2 \ - --hash=sha256:72d80005b7634a3a2220f81fbeb94775ebd12794623bb2e1451701ea732b4aa3 \ - --hash=sha256:7303aab41e97adcf010a09efd8f1403e719e59b7705d5e3cfed3dd7571589290 \ - --hash=sha256:7434a27754049144539d2099a6d2da5d88b8bdeedf935180bf42ad59b3607aa3 \ - --hash=sha256:746a5ee71c6d1103d9b560fa147881b5e68fd35da56e54e03d5acefad0e7c055 \ - --hash=sha256:7733ec52296fc1ba22e9b90a245c821adbb943e98c91d8a330a2254612726106 \ - --hash=sha256:7901c893e704ee3c65f92d39b951f8f34ccf8e8566768c58103fb10e55afb8c1 \ - --hash=sha256:7aa18cdb58983ee660c9c400b46272e14fa253c675ed963d3812487f8ca42037 \ - --hash=sha256:7b986d506a8e8ea345791897ba5d8ba0d9d8820cd4fc3e52dbe6de19388de2e7 \ - --hash=sha256:7bbb0df897944b5ec830f3ad883e32c5a7375370a521565f5fe24443bfb2c4f7 \ - --hash=sha256:7c7f0b342fd06044bedd0b6e72177ddc0076f54fd89ee239447f8b271d919d9b \ - --hash=sha256:7e5634565367b6d98dc4aa2983703526ef556b3688ba3065edb4b9b90ede1c54 \ - --hash=sha256:7fddccd4113e7b736706e17a239a696332360cbaddf25ae75b57ba1acce65081 \ - --hash=sha256:81c504ad11c588c8629536b032940f2a359dda3b6cbfd4ad8f74cb24dcd1b0bc \ - --hash=sha256:81df0dae22cd0da87f1c978602750f33d17fb3d21fb0f326c89dc89834fea79b \ - --hash=sha256:86d1be5d63232e6eb93c50881aea55ff06eb86d8e08f9b5417c8c9b10db9db96 \ - --hash=sha256:8b0c53fe0994beade1ad7c0f13bd6fec980a0664bfbe5a6a7d64500b9ab76772 \ - --hash=sha256:8ebf241072cf2777a492d0e09252f8cc2b3edd07dfdb9404b9757bffeb4f2cee \ - --hash=sha256:931d47e08c9c8a67bf75d82f0ada8399eac18b03388818b62bfa42882d571d72 \ - --hash=sha256:932a6eec1d2e2c3c9e630d10f7128d80e70e2d47fe6b8c7ea5e1afbd98733e65 \ - --hash=sha256:941603bfd75a46023807511c1ac2f1b0f39cccc393c15039969806063b27e6db \ - --hash=sha256:956127e663d05edbeec54df38885d943dfa27406594c411139690485128525de \ - --hash=sha256:96f1e1ac44cbb42bcc406e509f70c9af42c594e72ccc7b1257f97554204445f0 \ - --hash=sha256:99bb6a4d809aa4e528ddfe2c85dd5239b78b9dd14be62cca0329db78505e7b50 \ - --hash=sha256:9f64bf06f4bf623325fda3a6d02d36cd69199b9ace99b04bb2d7fd9f89688504 \ - --hash=sha256:a094319ec0db52a04af9fdc391b4d39a1bc72bc8424b47c4411afb05413a44b5 \ - --hash=sha256:a367d4741ac0103f8198c82f429bccb9359f543ca542b06a51f4f0332e8de279 \ - --hash=sha256:a7c0c7845566b9686480e6a7e9044db4afb60038d5fabd19227443f0104eeee4 \ - --hash=sha256:aa6e5d31fdc5ed9e3e95f9873508615a778fe9b523d52c17fc770a3eb39ab6e4 \ - --hash=sha256:ae9d032488fcec32d22be6542d1a836f00247f40f320844dbb361393b5b22773 \ - --hash=sha256:b0271ac12415afd3171ab9a3c7cbfc71dee2c68760a7dc9d05bf8ed6ddfa3a7a \ - --hash=sha256:b0d753ad566c721faa33db7e2e0eddd74b224cdd3eaf8481d76c926603c7a00e \ - --hash=sha256:b29044e1ffdb84fe164d0a7ea05c7316afea93c00f8ed9449cf357c36fc4f814 \ - --hash=sha256:b5995088dd7023d2d9f310a0c67de5a2b2e06a570ecfd00f9ff4ab94a67cde43 \ - --hash=sha256:b5f317a727bba0e633a12e71228bc6a4acb4f471a98b1c003163b917311ea9a9 \ - --hash=sha256:b9a87025121d1c448f24f27ff53a5fe7b6ef980574b4a4f11acaabe702420d63 \ - --hash=sha256:bb0fdc451fb6d86d81ab8f23d881b8d6e37fc373a2deae1c02d27002d2ad7a05 \ - --hash=sha256:bb4fe46bdc6104fbc28db7a6bacb115ee6368ff993366bbd8a2a7f0076e6f0c0 \ - --hash=sha256:bc44fc2b886243d7c0d8daeb37864e16f232e5b56aaec27cc781d848264cfd28 \ - --hash=sha256:bdde97310d59604f2a9119322f61b31546748499a21b44f6715e8ced9308a6c5 \ - --hash=sha256:be1374df449465c9f2500e62eee73a39db62152a8bdfbe12ec5b5c1cd451344d \ - --hash=sha256:be7d3dca9358e01dab1bad881fb2b4e8730cec58d36dd44482bc068bfcd3bc65 \ - --hash=sha256:bf7bee43e17e81671c447e9c83499f53d99bf440bc6d9dc26a841e21acfbe094 \ - --hash=sha256:c3dca4cb5b946ee91b3d6bb700d137b1cd85c20827f89fdf9c16258253489044 \ - --hash=sha256:c3f563e8901960e2eaa64c8e8821895818acabeb41c96f2efbb936f65dbe486c \ - --hash=sha256:c463d7c1c4cfc9d751efeaadd936bbba07b5b0ed81a012b3a9f5a12f0872bd6e \ - --hash=sha256:c4a2f3d83879e3de2eb8cbf562e71563a8ed15ee9b9c2e77ca5d9f73072ac15c \ - --hash=sha256:c5584061fd3da584659b13587f26c6cad25a096246a481636d64375d0c1f6c07 \ - --hash=sha256:c677d78887244bf3095020b73c42b505b700f801c690f8eaa90ad12d3179612f \ - --hash=sha256:c903e71fd8debb35ad2a4184c1316b3cb22f64ce517b4e6747f25b0a34e41266 \ - --hash=sha256:c9ff37ba9f15637e424c2ab57a1a590c52897c845b768e4e0a4958084ec87f22 \ - --hash=sha256:cadc16e8ea64b5d9a47363013e2bea469e121e6e7cb416a7593aeb24f2ad122e \ - --hash=sha256:cedac4f4054b8f7859e5aed41aaa31ad03fce6851901a7fdc2af0275ac533c10 \ - --hash=sha256:d22c9dcafed659fadc605538946c041722b6d1104fe619dbf5cc73b3c8a0ded8 \ - --hash=sha256:d765058da196f68dc721116cab335e696e87e76720e6ef8ee5a24801af65e63d \ - --hash=sha256:d86651fa45799530885ba4dab3d21144486ed15285e8784181a0ab37a4552384 \ - --hash=sha256:dd966df3489ec13848d6c6303429bbace94a153f43d1ae2a55115fd36fd5ca5d \ - --hash=sha256:ddc63328889bcaee77b743309e5c7d2d52cee0d7d577837c91b6e7cc9e755e0b \ - --hash=sha256:dfbead5575f6470c17e955b94f92d62a03dfc3d07f2e6f817d9b93dc211a1515 \ - --hash=sha256:e0f3ed828d709f5b82d8bfe14f8856120718ec4bd44a5b26102c3030a1e12501 \ - --hash=sha256:e1861fb6b1d0453ed7293200139c0a9011eeb1376632e048e3766945b13313c5 \ - --hash=sha256:e5015f0bb6eb50008bed2d4b1ce0f2a294698a926111e4bb202c0987b4f89078 \ - --hash=sha256:e651e17bfde5840e9e4174b01e9e080ce49277b70d424308b36a7969d0d1af73 \ - --hash=sha256:e7884931fe5e788163e7b3c511614130c2c59feffdc21112290a194487efb2e9 \ - --hash=sha256:e79c00eba78f7258e5b354eccd4d7907d60317ced924ea4a5f2e9d83f5453065 \ - --hash=sha256:e912b19cf2378f2967d0c08e86ff4c6c360129887f678e27e4dde970d21b3f4d \ - --hash=sha256:e9a011469b47b752e7d20de296bb34591cdfcbe76c99c2e863ceaa2aa61113d2 \ - --hash=sha256:eb756caf8975882630ce4e9fbbeb9d3401242a72528230422c9ab3a0d278e60c \ - --hash=sha256:eba01ec3bd4a49b9ac5ca2bc6a73ff5f3af53374b8556fcc2966dd2af9eb7779 \ - --hash=sha256:ecbfc0437ddfdced5e7822d1ce4855c9c64f46819d0fdc4482c53f56c707b935 \ - --hash=sha256:eed4bba7ff8a0d37106ba931ab03bdd3915fbb025bcf4e1f0aa02bc8114960c5 \ - --hash=sha256:f35727c5118aba95f0397e18a1a5b8405425581bfe53e821f0fb444cbdc2bc9b \ - --hash=sha256:f698733a8a494466432d611a8f0d1e026f5286dee051beea4b3c3146817e35d5 \ - --hash=sha256:f7f9034c7cf05ddfaac8d7a2e63a3c97a840d4615d0a0e65ba8bdf6f8576e3be \ - --hash=sha256:fa0c966ee727aad5406d516375593c5f058c766b21236ab8985693934bb5085b \ - --hash=sha256:fc9c5f280438cf1c1a8f9abb87dc8ce9630a964120cfb5dd50d1e7ce79690c7a \ - --hash=sha256:fd6e6c3d90660d085f7e73710eab6f5545d4854b81b0135a3526e797009dbda3 \ - --hash=sha256:fdfd3fb739f4e22746e13ad7ba0c6eedf5f454b18d11249724a388868e308ee4 \ - --hash=sha256:ff3d50dc3fe8a98059f99b445dfb62792b5d006c5e0b8f03c6de2813b8376110 +mmh3==5.2.1 \ + --hash=sha256:022aa1a528604e6c83d0a7705fdef0b5355d897a9e0fa3a8d26709ceaa06965d \ + --hash=sha256:0634581290e6714c068f4aa24020acf7880927d1f0084fa753d9799ae9610082 \ + --hash=sha256:08043f7cb1fb9467c3fbbbaea7896986e7fbc81f4d3fd9289a73d9110ab6207a \ + --hash=sha256:0a3984146e414684a6be2862d84fcb1035f4984851cb81b26d933bab6119bf00 \ + --hash=sha256:0bbc17250b10d3466875a40a52520a6bac3c02334ca709207648abd3c223ed5c \ + --hash=sha256:0cc21533878e5586b80d74c281d7f8da7932bc8ace50b8d5f6dbf7e3935f63f1 \ + --hash=sha256:0d0b7e803191db5f714d264044e06189c8ccd3219e936cc184f07106bd17fd7b \ + --hash=sha256:113f78e7463a36dbbcea05bfe688efd7fa759d0f0c56e73c974d60dcfec3dfcc \ + --hash=sha256:169e0d178cb59314456ab30772429a802b25d13227088085b0d49b9fe1533104 \ + --hash=sha256:17fbb47f0885ace8327ce1235d0416dc86a211dcd8cc1e703f41523be32cfec8 \ + --hash=sha256:19bbd3b841174ae6ed588536ab5e1b1fe83d046e668602c20266547298d939a9 \ + --hash=sha256:1d9f9a3ce559a5267014b04b82956993270f63ec91765e13e9fd73daf2d2738e \ + --hash=sha256:1e4ecee40ba19e6975e1120829796770325841c2f153c0e9aecca927194c6a2a \ + --hash=sha256:22b0f9971ec4e07e8223f2beebe96a6cfc779d940b6f27d26604040dd74d3a44 \ + --hash=sha256:26fb5b9c3946bf7f1daed7b37e0c03898a6f062149127570f8ede346390a0825 \ + --hash=sha256:2778fed822d7db23ac5008b181441af0c869455b2e7d001f4019636ac31b6fe4 \ + --hash=sha256:28cfab66577000b9505a0d068c731aee7ca85cd26d4d63881fab17857e0fe1fb \ + --hash=sha256:29bc3973676ae334412efdd367fcd11d036b7be3efc1ce2407ef8676dabfeb82 \ + --hash=sha256:2bd9f19f7f1fcebd74e830f4af0f28adad4975d40d80620be19ffb2b2af56c9f \ + --hash=sha256:2d5d542bf2abd0fd0361e8017d03f7cb5786214ceb4a40eef1539d6585d93386 \ + --hash=sha256:30e4d2084df019880d55f6f7bea35328d9b464ebee090baa372c096dc77556fb \ + --hash=sha256:3619473a0e0d329fd4aec8075628f8f616be2da41605300696206d6f36920c3d \ + --hash=sha256:368625fb01666655985391dbad3860dc0ba7c0d6b9125819f3121ee7292b4ac8 \ + --hash=sha256:3737303ca9ea0f7cb83028781148fcda4f1dac7821db0c47672971dabcf63593 \ + --hash=sha256:3a9fed49c6ce4ed7e73f13182760c65c816da006debe67f37635580dfb0fae00 \ + --hash=sha256:3c38d142c706201db5b2345166eeef1e7740e3e2422b470b8ba5c8727a9b4c7a \ + --hash=sha256:3cb61db880ec11e984348227b333259994c2c85caa775eb7875decb3768db890 \ + --hash=sha256:3d74a03fb57757ece25aa4b3c1c60157a1cece37a020542785f942e2f827eed5 \ + --hash=sha256:3f796b535008708846044c43302719c6956f39ca2d93f2edda5319e79a29efbb \ + --hash=sha256:41105377f6282e8297f182e393a79cfffd521dde37ace52b106373bdcd9ca5cb \ + --hash=sha256:41aac7002a749f08727cb91babff1daf8deac317c0b1f317adc69be0e6c375d1 \ + --hash=sha256:44983e45310ee5b9f73397350251cdf6e63a466406a105f1d16cb5baa659270b \ + --hash=sha256:4cbbde66f1183db040daede83dd86c06d663c5bb2af6de1142b7c8c37923dd74 \ + --hash=sha256:4eda76074cfca2787c8cf1bec603eaebdddd8b061ad5502f85cddae998d54f00 \ + --hash=sha256:4fc6cd65dc4d2fdb2625e288939a3566e36127a84811a4913f02f3d5931da52d \ + --hash=sha256:50885073e2909251d4718634a191c49ae5f527e5e1736d738e365c3e8be8f22b \ + --hash=sha256:5174a697ce042fa77c407e05efe41e03aa56dae9ec67388055820fb48cf4c3ba \ + --hash=sha256:54b64fb2433bc71488e7a449603bf8bd31fbcf9cb56fbe1eb6d459e90b86c37b \ + --hash=sha256:54fe8518abe06a4c3852754bfd498b30cc58e667f376c513eac89a244ce781a4 \ + --hash=sha256:55dbbd8ffbc40d1697d5e2d0375b08599dae8746b0b08dea05eee4ce81648fac \ + --hash=sha256:57b52603e89355ff318025dd55158f6e71396c0f1f609d548e9ea9c94cc6ce0a \ + --hash=sha256:58370d05d033ee97224c81263af123dea3d931025030fd34b61227a768a8858a \ + --hash=sha256:5d87a3584093e1a89987e3d36d82c98d9621b2cb944e22a420aa1401e096758f \ + --hash=sha256:623f938f6a039536cc02b7582a07a080f13fdfd48f87e63201d92d7e34d09a18 \ + --hash=sha256:62815d2c67f2dd1be76a253d88af4e1da19aeaa1820146dec52cf8bee2958b16 \ + --hash=sha256:6290289fa5fb4c70fd7f72016e03633d60388185483ff3b162912c81205ae2cf \ + --hash=sha256:67e41a497bac88cc1de96eeba56eeb933c39d54bc227352f8455aa87c4ca4000 \ + --hash=sha256:6c85c38a279ca9295a69b9b088a2e48aa49737bb1b34e6a9dc6297c110e8d912 \ + --hash=sha256:6f01f044112d43a20be2f13a11683666d87151542ad627fe41a18b9791d2802f \ + --hash=sha256:707151644085dd0f20fe4f4b573d28e5130c4aaa5f587e95b60989c5926653b5 \ + --hash=sha256:723b2681ed4cc07d3401bbea9c201ad4f2a4ca6ba8cddaff6789f715dd2b391e \ + --hash=sha256:72d1cc63bcc91e14933f77d51b3df899d6a07d184ec515ea7f56bff659e124d7 \ + --hash=sha256:7374d6e3ef72afe49697ecd683f3da12f4fc06af2d75433d0580c6746d2fa025 \ + --hash=sha256:7501e9be34cb21e72fcfe672aafd0eee65c16ba2afa9dcb5500a587d3a0580f0 \ + --hash=sha256:76219cd1eefb9bf4af7856e3ae563d15158efa145c0aab01e9933051a1954045 \ + --hash=sha256:7aec798c2b01aaa65a55f1124f3405804184373abb318a3091325aece235f67c \ + --hash=sha256:7be6dfb49e48fd0a7d91ff758a2b51336f1cd21f9d44b20f6801f072bd080cdd \ + --hash=sha256:7e4e1f580033335c6f76d1e0d6b56baf009d1a64d6a4816347e4271ba951f46d \ + --hash=sha256:7e8ec5f606e0809426d2440e0683509fb605a8820a21ebd120dcdba61b74ef7f \ + --hash=sha256:7f196cd7910d71e9d9860da0ff7a77f64d22c1ad931f1dd18559a06e03109fc0 \ + --hash=sha256:82f3802bfc4751f420d591c5c864de538b71cea117fce67e4595c2afede08a15 \ + --hash=sha256:85ffc9920ffc39c5eee1e3ac9100c913a0973996fbad5111f939bbda49204bb7 \ + --hash=sha256:8e6c219e375f6341d0959af814296372d265a8ca1af63825f65e2e87c618f006 \ + --hash=sha256:8f767ba0911602ddef289404e33835a61168314ebd3c729833db2ed685824211 \ + --hash=sha256:8ff038d52ef6aa0f309feeba00c5095c9118d0abf787e8e8454d6048db2037fc \ + --hash=sha256:915e7a2418f10bd1151b1953df06d896db9783c9cfdb9a8ee1f9b3a4331ab503 \ + --hash=sha256:92883836caf50d5255be03d988d75bc93e3f86ba247b7ca137347c323f731deb \ + --hash=sha256:960b1b3efa39872ac8b6cc3a556edd6fb90ed74f08c9c45e028f1005b26aa55d \ + --hash=sha256:9aeaf53eaa075dd63e81512522fd180097312fb2c9f476333309184285c49ce0 \ + --hash=sha256:9d8089d853c7963a8ce87fff93e2a67075c0bc08684a08ea6ad13577c38ffc38 \ + --hash=sha256:a4130d0b9ce5fad6af07421b1aecc7e079519f70d6c05729ab871794eded8617 \ + --hash=sha256:a482ac121de6973897c92c2f31defc6bafb11c83825109275cffce54bb64933f \ + --hash=sha256:add7ac388d1e0bf57259afbcf9ed05621a3bf11ce5ee337e7536f1e1aaf056b0 \ + --hash=sha256:b1f12bd684887a0a5d55e6363ca87056f361e45451105012d329b86ec19dbe0b \ + --hash=sha256:b3f99e1756fc48ad507b95e5d86f2fb21b3d495012ff13e6592ebac14033f166 \ + --hash=sha256:b4cce60d0223074803c9dbe0721ad3fa51dafe7d462fee4b656a1aa01ee07518 \ + --hash=sha256:baeb47635cb33375dee4924cd93d7f5dcaa786c740b08423b0209b824a1ee728 \ + --hash=sha256:bbea5b775f0ac84945191fb83f845a6fd9a21a03ea7f2e187defac7e401616ad \ + --hash=sha256:bbfcb95d9a744e6e2827dfc66ad10e1020e0cac255eb7f85652832d5a264c2fc \ + --hash=sha256:bd6e7d363aa93bd3421b30b6af97064daf47bc96005bddba67c5ffbc6df426b8 \ + --hash=sha256:be77c402d5e882b6fbacfd90823f13da8e0a69658405a39a569c6b58fdb17b03 \ + --hash=sha256:c302245fd6c33d96bd169c7ccf2513c20f4c1e417c07ce9dce107c8bc3f8411f \ + --hash=sha256:c88653877aeb514c089d1b3d473451677b8b9a6d1497dbddf1ae7934518b06d2 \ + --hash=sha256:cae6383181f1e345317742d2ddd88f9e7d2682fa4c9432e3a74e47d92dce0229 \ + --hash=sha256:cd471ede0d802dd936b6fab28188302b2d497f68436025857ca72cd3810423fe \ + --hash=sha256:d106493a60dcb4aef35a0fac85105e150a11cf8bc2b0d388f5a33272d756c966 \ + --hash=sha256:d30b650595fdbe32366b94cb14f30bb2b625e512bd4e1df00611f99dc5c27fd4 \ + --hash=sha256:d51fde50a77f81330523562e3c2734ffdca9c4c9e9d355478117905e1cfe16c6 \ + --hash=sha256:d57dea657357230cc780e13920d7fa7db059d58fe721c80020f94476da4ca0a1 \ + --hash=sha256:d771f085fcdf4035786adfb1d8db026df1eb4b41dac1c3d070d1e49512843227 \ + --hash=sha256:dae0f0bd7d30c0ad61b9a504e8e272cb8391eed3f1587edf933f4f6b33437450 \ + --hash=sha256:db0562c5f71d18596dcd45e854cf2eeba27d7543e1a3acdafb7eef728f7fe85d \ + --hash=sha256:dfd51b4c56b673dfbc43d7d27ef857dd91124801e2806c69bb45585ce0fa019b \ + --hash=sha256:e080c0637aea036f35507e803a4778f119a9b436617694ae1c5c366805f1e997 \ + --hash=sha256:e48d4dbe0f88e53081da605ae68644e5182752803bbc2beb228cca7f1c4454d6 \ + --hash=sha256:e8b4b5580280b9265af3e0409974fb79c64cf7523632d03fbf11df18f8b0181e \ + --hash=sha256:e8b5378de2b139c3a830f0209c1e91f7705919a4b3e563a10955104f5097a70a \ + --hash=sha256:e904f2417f0d6f6d514f3f8b836416c360f306ddaee1f84de8eef1e722d212e5 \ + --hash=sha256:eee884572b06bbe8a2b54f424dbd996139442cf83c76478e1ec162512e0dd2c7 \ + --hash=sha256:f1fbb0a99125b1287c6d9747f937dc66621426836d1a2d50d05aecfc81911b57 \ + --hash=sha256:f40a95186a72fa0b67d15fef0f157bfcda00b4f59c8a07cbe5530d41ac35d105 \ + --hash=sha256:f6e0bfe77d238308839699944164b96a2eeccaf55f2af400f54dc20669d8d5f2 \ + --hash=sha256:f963eafc0a77a6c0562397da004f5876a9bcf7265a7bcc3205e29636bc4a1312 \ + --hash=sha256:fb9d44c25244e11c8be3f12c938ca8ba8404620ef8092245d2093c6ab3df260f \ + --hash=sha256:fc78739b5ec6e4fb02301984a3d442a91406e7700efbe305071e7fd1c78278f2 \ + --hash=sha256:fceef7fe67c81e1585198215e42ad3fdba3a25644beda8fbdaf85f4d7b93175a \ + --hash=sha256:fd96476f04db5ceba1cfa0f21228f67c1f7402296f0e73fee3513aa680ad237b # via feast (pyproject.toml) mock==2.0.0 \ --hash=sha256:5ce3c71c5545b472da17b72268978914d0252980348636840bd34a00b5cc96c1 \ @@ -2564,9 +2590,9 @@ mpmath==1.3.0 \ --hash=sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f \ --hash=sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c # via sympy -msal==1.34.0 \ - --hash=sha256:76ba83b716ea5a6d75b0279c0ac353a0e05b820ca1f6682c0eb7f45190c43c2f \ - --hash=sha256:f669b1644e4950115da7a176441b0e13ec2975c29528d8b9e81316023676d6e1 +msal==1.35.1 \ + --hash=sha256:70cac18ab80a053bff86219ba64cfe3da1f307c74b009e2da57ef040eb1b5656 \ + --hash=sha256:8f4e82f34b10c19e326ec69f44dc6b30171f2f7098f3720ea8a9f0c11832caa3 # via # azure-identity # msal-extensions @@ -2899,9 +2925,9 @@ nodeenv==1.10.0 \ --hash=sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827 \ --hash=sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb # via pre-commit -notebook==7.5.3 \ - --hash=sha256:393ceb269cf9fdb02a3be607a57d7bd5c2c14604f1818a17dbeb38e04f98cbfa \ - --hash=sha256:c997bfa1a2a9eb58c9bbb7e77d50428befb1033dd6f02c482922e96851d67354 +notebook==7.5.5 \ + --hash=sha256:a7c14dbeefa6592e87f72290ca982e0c10f5bbf3786be2a600fda9da2764a2b8 \ + --hash=sha256:dc0bfab0f2372c8278c457423d3256c34154ac2cc76bf20e9925260c461013c3 # via great-expectations notebook-shim==0.2.4 \ --hash=sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef \ @@ -2909,79 +2935,79 @@ notebook-shim==0.2.4 \ # via # jupyterlab # notebook -numpy==2.4.2 \ - --hash=sha256:00ab83c56211a1d7c07c25e3217ea6695e50a3e2f255053686b081dc0b091a82 \ - --hash=sha256:068cdb2d0d644cdb45670810894f6a0600797a69c05f1ac478e8d31670b8ee75 \ - --hash=sha256:0f01dcf33e73d80bd8dc0f20a71303abbafa26a19e23f6b68d1aa9990af90257 \ - --hash=sha256:0fece1d1f0a89c16b03442eae5c56dc0be0c7883b5d388e0c03f53019a4bfd71 \ - --hash=sha256:12e26134a0331d8dbd9351620f037ec470b7c75929cb8a1537f6bfe411152a1a \ - --hash=sha256:1ae241bbfc6ae276f94a170b14785e561cb5e7f626b6688cf076af4110887413 \ - --hash=sha256:1f92f53998a17265194018d1cc321b2e96e900ca52d54c7c77837b71b9465181 \ - --hash=sha256:209fae046e62d0ce6435fcfe3b1a10537e858249b3d9b05829e2a05218296a85 \ - --hash=sha256:20abd069b9cda45874498b245c8015b18ace6de8546bf50dfa8cea1696ed06ef \ - --hash=sha256:21982668592194c609de53ba4933a7471880ccbaadcc52352694a59ecc860b3a \ - --hash=sha256:25f2059807faea4b077a2b6837391b5d830864b3543627f381821c646f31a63c \ - --hash=sha256:2653de5c24910e49c2b106499803124dde62a5a1fe0eedeaecf4309a5f639390 \ - --hash=sha256:2b8f157c8a6f20eb657e240f8985cc135598b2b46985c5bccbde7616dc9c6b1e \ - --hash=sha256:2fb882da679409066b4603579619341c6d6898fc83a8995199d5249f986e8e8f \ - --hash=sha256:40397bda92382fcec844066efb11f13e1c9a3e2a8e8f318fb72ed8b6db9f60f1 \ - --hash=sha256:444be170853f1f9d528428eceb55f12918e4fda5d8805480f36a002f1415e09b \ - --hash=sha256:47c5a6ed21d9452b10227e5e8a0e1c22979811cad7dcc19d8e3e2fb8fa03f1a3 \ - --hash=sha256:4f069069931240b3fc703f1e23df63443dbd6390614c8c44a87d96cd0ec81eb1 \ - --hash=sha256:52b913ec40ff7ae845687b0b34d8d93b60cb66dcee06996dd5c99f2fc9328657 \ - --hash=sha256:5633c0da313330fd20c484c78cdd3f9b175b55e1a766c4a174230c6b70ad8262 \ - --hash=sha256:5daf6f3914a733336dab21a05cdec343144600e964d2fcdabaac0c0269874b2a \ - --hash=sha256:5eea80d908b2c1f91486eb95b3fb6fab187e569ec9752ab7d9333d2e66bf2d6b \ - --hash=sha256:602f65afdef699cda27ec0b9224ae5dc43e328f4c24c689deaf77133dbee74d0 \ - --hash=sha256:659a6107e31a83c4e33f763942275fd278b21d095094044eb35569e86a21ddae \ - --hash=sha256:66cb9422236317f9d44b67b4d18f44efe6e9c7f8794ac0462978513359461554 \ - --hash=sha256:6d82351358ffbcdcd7b686b90742a9b86632d6c1c051016484fa0b326a0a1548 \ - --hash=sha256:6e9f61981ace1360e42737e2bae58b27bf28a1b27e781721047d84bd754d32e7 \ - --hash=sha256:6ed0be1ee58eef41231a5c943d7d1375f093142702d5723ca2eb07db9b934b05 \ - --hash=sha256:7cdde6de52fb6664b00b056341265441192d1291c130e99183ec0d4b110ff8b1 \ - --hash=sha256:7df2de1e4fba69a51c06c28f5a3de36731eb9639feb8e1cf7e4a7b0daf4cf622 \ - --hash=sha256:7edc794af8b36ca37ef5fcb5e0d128c7e0595c7b96a2318d1badb6fcd8ee86b1 \ - --hash=sha256:7f54844851cdb630ceb623dcec4db3240d1ac13d4990532446761baede94996a \ - --hash=sha256:805cc8de9fd6e7a22da5aed858e0ab16be5a4db6c873dde1d7451c541553aa27 \ - --hash=sha256:8906e71fd8afcb76580404e2a950caef2685df3d2a57fe82a86ac8d33cc007ba \ - --hash=sha256:89f7268c009bc492f506abd6f5265defa7cb3f7487dc21d357c3d290add45082 \ - --hash=sha256:8c50dd1fc8826f5b26a5ee4d77ca55d88a895f4e4819c7ecc2a9f5905047a443 \ - --hash=sha256:8e4549f8a3c6d13d55041925e912bfd834285ef1dd64d6bc7d542583355e2e98 \ - --hash=sha256:8e9afaeb0beff068b4d9cd20d322ba0ee1cecfb0b08db145e4ab4dd44a6b5110 \ - --hash=sha256:98f16a80e917003a12c0580f97b5f875853ebc33e2eaa4bccfc8201ac6869308 \ - --hash=sha256:9e35d3e0144137d9fdae62912e869136164534d64a169f86438bc9561b6ad49f \ - --hash=sha256:9e4424677ce4b47fe73c8b5556d876571f7c6945d264201180db2dc34f676ab5 \ - --hash=sha256:adb6ed2ad29b9e15321d167d152ee909ec73395901b70936f029c3bc6d7f4460 \ - --hash=sha256:aea4f66ff44dfddf8c2cffd66ba6538c5ec67d389285292fe428cb2c738c8aef \ - --hash=sha256:b21041e8cb6a1eb5312dd1d2f80a94d91efffb7a06b70597d44f1bd2dfc315ab \ - --hash=sha256:b2f0073ed0868db1dcd86e052d37279eef185b9c8db5bf61f30f46adac63c909 \ - --hash=sha256:b3a24467af63c67829bfaa61eecf18d5432d4f11992688537be59ecd6ad32f5e \ - --hash=sha256:b9c618d56a29c9cb1c4da979e9899be7578d2e0b3c24d52079c166324c9e8695 \ - --hash=sha256:bba37bc29d4d85761deed3954a1bc62be7cf462b9510b51d367b769a8c8df325 \ - --hash=sha256:bd3a7a9f5847d2fb8c2c6d1c862fa109c31a9abeca1a3c2bd5a64572955b2979 \ - --hash=sha256:be71bf1edb48ebbbf7f6337b5bfd2f895d1902f6335a5830b20141fc126ffba0 \ - --hash=sha256:c02ef4401a506fb60b411467ad501e1429a3487abca4664871d9ae0b46c8ba32 \ - --hash=sha256:c3cd545784805de05aafe1dde61752ea49a359ccba9760c1e5d1c88a93bbf2b7 \ - --hash=sha256:c7ac672d699bf36275c035e16b65539931347d68b70667d28984c9fb34e07fa7 \ - --hash=sha256:cb7bbb88aa74908950d979eeaa24dbdf1a865e3c7e45ff0121d8f70387b55f73 \ - --hash=sha256:cd2bd2bbed13e213d6b55dc1d035a4f91748a7d3edc9480c13898b0353708920 \ - --hash=sha256:cda077c2e5b780200b6b3e09d0b42205a3d1c68f30c6dceb90401c13bff8fe74 \ - --hash=sha256:cf28c0c1d4c4bf00f509fa7eb02c58d7caf221b50b467bcb0d9bbf1584d5c821 \ - --hash=sha256:d0d9b7c93578baafcbc5f0b83eaf17b79d345c6f36917ba0c67f45226911d499 \ - --hash=sha256:d1240d50adff70c2a88217698ca844723068533f3f5c5fa6ee2e3220e3bdb000 \ - --hash=sha256:d30291931c915b2ab5717c2974bb95ee891a1cf22ebc16a8006bd59cd210d40a \ - --hash=sha256:d9f64d786b3b1dd742c946c42d15b07497ed14af1a1f3ce840cce27daa0ce913 \ - --hash=sha256:da6cad4e82cb893db4b69105c604d805e0c3ce11501a55b5e9f9083b47d2ffe8 \ - --hash=sha256:df1b10187212b198dd45fa943d8985a3c8cf854aed4923796e0e019e113a1bda \ - --hash=sha256:e04ae107ac591763a47398bb45b568fc38f02dbc4aa44c063f67a131f99346cb \ - --hash=sha256:e6dee3bb76aa4009d5a912180bf5b2de012532998d094acee25d9cb8dee3e44a \ - --hash=sha256:e7e88598032542bd49af7c4747541422884219056c268823ef6e5e89851c8825 \ - --hash=sha256:e98c97502435b53741540a5717a6749ac2ada901056c7db951d33e11c885cc7d \ - --hash=sha256:ec055f6dae239a6299cace477b479cca2fc125c5675482daf1dd886933a1076f \ - --hash=sha256:f74f0f7779cc7ae07d1810aab8ac6b1464c3eafb9e283a40da7309d5e6e48fbb \ - --hash=sha256:fbde1b0c6e81d56f5dccd95dd4a711d9b95df1ae4009a60887e56b27e8d903fa \ - --hash=sha256:fcf92bee92742edd401ba41135185866f7026c502617f422eb432cfeca4fe236 \ - --hash=sha256:fd49860271d52127d61197bb50b64f58454e9f578cb4b2c001a6de8b1f50b0b1 +numpy==2.4.4 \ + --hash=sha256:07077278157d02f65c43b1b26a3886bce886f95d20aabd11f87932750dfb14ed \ + --hash=sha256:08f2e31ed5e6f04b118e49821397f12767934cfdd12a1ce86a058f91e004ee50 \ + --hash=sha256:0aec54fd785890ecca25a6003fd9a5aed47ad607bbac5cd64f836ad8666f4959 \ + --hash=sha256:0d35aea54ad1d420c812bfa0385c71cd7cc5bcf7c65fed95fc2cd02fe8c79827 \ + --hash=sha256:0d4e437e295f18ec29bc79daf55e8a47a9113df44d66f702f02a293d93a2d6dd \ + --hash=sha256:0dfd3f9d3adbe2920b68b5cd3d51444e13a10792ec7154cd0a2f6e74d4ab3233 \ + --hash=sha256:1378871da56ca8943c2ba674530924bb8ca40cd228358a3b5f302ad60cf875fc \ + --hash=sha256:15716cfef24d3a9762e3acdf87e27f58dc823d1348f765bbea6bef8c639bfa1b \ + --hash=sha256:19710a9ca9992d7174e9c52f643d4272dcd1558c5f7af7f6f8190f633bd651a7 \ + --hash=sha256:23cbfd4c17357c81021f21540da84ee282b9c8fba38a03b7b9d09ba6b951421e \ + --hash=sha256:2483e4584a1cb3092da4470b38866634bafb223cbcd551ee047633fd2584599a \ + --hash=sha256:27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d \ + --hash=sha256:28a650663f7314afc3e6ec620f44f333c386aad9f6fc472030865dc0ebb26ee3 \ + --hash=sha256:2aa0613a5177c264ff5921051a5719d20095ea586ca88cc802c5c218d1c67d3e \ + --hash=sha256:2c194dd721e54ecad9ad387c1d35e63dce5c4450c6dc7dd5611283dda239aabb \ + --hash=sha256:2d19e6e2095506d1736b7d80595e0f252d76b89f5e715c35e06e937679ea7d7a \ + --hash=sha256:2d390634c5182175533585cc89f3608a4682ccb173cc9bb940b2881c8d6f8fa0 \ + --hash=sha256:30caa73029a225b2d40d9fae193e008e24b2026b7ee1a867b7ee8d96ca1a448e \ + --hash=sha256:42c16925aa5a02362f986765f9ebabf20de75cdefdca827d14315c568dcab113 \ + --hash=sha256:45dbed2ab436a9e826e302fcdcbe9133f9b0006e5af7168afb8963a6520da103 \ + --hash=sha256:4636de7fd195197b7535f231b5de9e4b36d2c440b6e566d2e4e4746e6af0ca93 \ + --hash=sha256:4a19d9dba1a76618dd86b164d608566f393f8ec6ac7c44f0cc879011c45e65af \ + --hash=sha256:4bbc7f303d125971f60ec0aaad5e12c62d0d2c925f0ab1273debd0e4ba37aba5 \ + --hash=sha256:4d6d57903571f86180eb98f8f0c839fa9ebbfb031356d87f1361be91e433f5b7 \ + --hash=sha256:4e874c976154687c1f71715b034739b45c7711bec81db01914770373d125e392 \ + --hash=sha256:51fc224f7ca4d92656d5a5eb315f12eb5fe2c97a66249aa7b5f562528a3be38c \ + --hash=sha256:58c8b5929fcb8287cbd6f0a3fae19c6e03a5c48402ae792962ac465224a629a4 \ + --hash=sha256:5a285b3b96f951841799528cd1f4f01cd70e7e0204b4abebac9463eecfcf2a40 \ + --hash=sha256:5c70f1cc1c4efbe316a572e2d8b9b9cc44e89b95f79ca3331553fbb63716e2bf \ + --hash=sha256:62d6b0f03b694173f9fcb1fb317f7222fd0b0b103e784c6549f5e53a27718c44 \ + --hash=sha256:6a246d5914aa1c820c9443ddcee9c02bec3e203b0c080349533fae17727dfd1b \ + --hash=sha256:6aa3236c78803afbcb255045fbef97a9e25a1f6c9888357d205ddc42f4d6eba5 \ + --hash=sha256:6bbe4eb67390b0a0265a2c25458f6b90a409d5d069f1041e6aff1e27e3d9a79e \ + --hash=sha256:715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74 \ + --hash=sha256:72944b19f2324114e9dc86a159787333b77874143efcf89a5167ef83cfee8af0 \ + --hash=sha256:81f4a14bee47aec54f883e0cad2d73986640c1590eb9bfaaba7ad17394481e6e \ + --hash=sha256:846300f379b5b12cc769334464656bc882e0735d27d9726568bc932fdc49d5ec \ + --hash=sha256:86b6f55f5a352b48d7fbfd2dbc3d5b780b2d79f4d3c121f33eb6efb22e9a2015 \ + --hash=sha256:874f200b2a981c647340f841730fc3a2b54c9d940566a3c4149099591e2c4c3d \ + --hash=sha256:8a87ec22c87be071b6bdbd27920b129b94f2fc964358ce38f3822635a3e2e03d \ + --hash=sha256:8b3b60bb7cba2c8c81837661c488637eee696f59a877788a396d33150c35d842 \ + --hash=sha256:8e3ed142f2728df44263aaf5fb1f5b0b99f4070c553a0d7f033be65338329150 \ + --hash=sha256:93e15038125dc1e5345d9b5b68aa7f996ec33b98118d18c6ca0d0b7d6198b7e8 \ + --hash=sha256:989824e9faf85f96ec9c7761cd8d29c531ad857bfa1daa930cba85baaecf1a9a \ + --hash=sha256:99d838547ace2c4aace6c4f76e879ddfe02bb58a80c1549928477862b7a6d6ed \ + --hash=sha256:9b2aec6af35c113b05695ebb5749a787acd63cafc83086a05771d1e1cd1e555f \ + --hash=sha256:9c585a1790d5436a5374bac930dad6ed244c046ed91b2b2a3634eb2971d21008 \ + --hash=sha256:a7164afb23be6e37ad90b2f10426149fd75aee07ca55653d2aa41e66c4ef697e \ + --hash=sha256:ac6b31e35612a26483e20750126d30d0941f949426974cace8e6b5c58a3657b0 \ + --hash=sha256:ad2e2ef14e0b04e544ea2fa0a36463f847f113d314aa02e5b402fdf910ef309e \ + --hash=sha256:b268594bccac7d7cf5844c7732e3f20c50921d94e36d7ec9b79e9857694b1b2f \ + --hash=sha256:b5f0362dc928a6ecd9db58868fca5e48485205e3855957bdedea308f8672ea4a \ + --hash=sha256:ba1f4fc670ed79f876f70082eff4f9583c15fb9a4b89d6188412de4d18ae2f40 \ + --hash=sha256:ba203255017337d39f89bdd58417f03c4426f12beed0440cfd933cb15f8669c7 \ + --hash=sha256:c901b15172510173f5cb310eae652908340f8dede90fff9e3bf6c0d8dfd92f83 \ + --hash=sha256:c9b39d38a9bd2ae1becd7eac1303d031c5c110ad31f2b319c6e7d98b135c934d \ + --hash=sha256:d2a8490669bfe99a233298348acc2d824d496dee0e66e31b66a6022c2ad74a5c \ + --hash=sha256:dddbbd259598d7240b18c9d87c56a9d2fb3b02fe266f49a7c101532e78c1d871 \ + --hash=sha256:df3775294accfdd75f32c74ae39fcba920c9a378a2fc18a12b6820aa8c1fb502 \ + --hash=sha256:e44319a2953c738205bf3354537979eaa3998ed673395b964c1176083dd46252 \ + --hash=sha256:e4a010c27ff6f210ff4c6ef34394cd61470d01014439b192ec22552ee867f2a8 \ + --hash=sha256:e823b8b6edc81e747526f70f71a9c0a07ac4e7ad13020aa736bb7c9d67196115 \ + --hash=sha256:e892aff75639bbef0d2a2cfd55535510df26ff92f63c92cd84ef8d4ba5a5557f \ + --hash=sha256:eea7ac5d2dce4189771cedb559c738a71512768210dc4e4753b107a2048b3d0e \ + --hash=sha256:ef4059d6e5152fa1a39f888e344c73fdc926e1b2dd58c771d67b0acfbf2aa67d \ + --hash=sha256:f169b9a863d34f5d11b8698ead99febeaa17a13ca044961aa8e2662a6c7766a0 \ + --hash=sha256:f2cf083b324a467e1ab358c105f6cad5ea950f50524668a80c486ff1db24e119 \ + --hash=sha256:f8474c4241bc18b750be2abea9d7a9ec84f46ef861dbacf86a4f6e043401f79e \ + --hash=sha256:f983334aea213c99992053ede6168500e5f086ce74fbc4acc3f2b00f5762e9db \ + --hash=sha256:f9e75681b59ddaa5e659898085ae0eaea229d054f2ac0c7e563a62205a700121 \ + --hash=sha256:fbc356aae7adf9e6336d336b9c8111d390a05df88f1805573ebb0807bd06fd1d \ + --hash=sha256:fcfe2045fd2e8f3cb0ce9d4ba6dba6333b8fa05bb8a4939c908cd43322d14c7e # via # feast (pyproject.toml) # accelerate @@ -3004,6 +3030,7 @@ numpy==2.4.2 \ # scikit-image # scikit-learn # scipy + # sentence-transformers # shapely # tifffile # torchvision @@ -3030,8 +3057,8 @@ opencv-python-headless==4.13.0.92 \ --hash=sha256:a7cf08e5b191f4ebb530791acc0825a7986e0d0dee2a3c491184bd8599848a4b \ --hash=sha256:eb60e36b237b1ebd40a912da5384b348df8ed534f6f644d8e0b4f103e272ba7d # via easyocr -openlineage-python==1.43.0 \ - --hash=sha256:595dc641f696d0a1c021440a9ff8155f4e2776452cf118112a09b12cf4038827 +openlineage-python==1.45.0 \ + --hash=sha256:cf66e7d517d3c8b510b39ad646d8fd0ca2f0cc92d7d6d601d93b2a859783f380 # via feast (pyproject.toml) openpyxl==3.1.5 \ --hash=sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2 \ @@ -3041,106 +3068,139 @@ openshift-client==1.0.18 \ --hash=sha256:be3979440cfd96788146a3a1650dabe939d4d516eea0b39f87e66d2ab39495b1 \ --hash=sha256:d8a84080307ccd9556f6c62a3707a3e6507baedee36fa425754f67db9ded528b # via codeflare-sdk -opentelemetry-api==1.39.1 \ - --hash=sha256:2edd8463432a7f8443edce90972169b195e7d6a05500cd29e6d13898187c9950 \ - --hash=sha256:fbde8c80e1b937a2c61f20347e91c0c18a1940cecf012d62e65a7caf08967c9c +opentelemetry-api==1.40.0 \ + --hash=sha256:159be641c0b04d11e9ecd576906462773eb97ae1b657730f0ecf64d32071569f \ + --hash=sha256:82dd69331ae74b06f6a874704be0cfaa49a1650e1537d4a813b86ecef7d0ecf9 # via # opentelemetry-exporter-prometheus # opentelemetry-sdk # opentelemetry-semantic-conventions -opentelemetry-exporter-prometheus==0.60b1 \ - --hash=sha256:49f59178de4f4590e3cef0b8b95cf6e071aae70e1f060566df5546fad773b8fd \ - --hash=sha256:a4011b46906323f71724649d301b4dc188aaa068852e814f4df38cc76eac616b +opentelemetry-exporter-prometheus==0.61b0 \ + --hash=sha256:3013b41f4370143d48d219a2351473761423e5882fa4c213811eaefacba39cb7 \ + --hash=sha256:7c4919bd8e79abd62b610767e80f42c9c3a06c5183f4dd9141eedeb57aea284b # via ray opentelemetry-proto==1.27.0 \ --hash=sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6 \ --hash=sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace # via ray -opentelemetry-sdk==1.39.1 \ - --hash=sha256:4d5482c478513ecb0a5d938dcc61394e647066e0cc2676bee9f3af3f3f45f01c \ - --hash=sha256:cf4d4563caf7bff906c9f7967e2be22d0d6b349b908be0d90fb21c8e9c995cc6 +opentelemetry-sdk==1.40.0 \ + --hash=sha256:18e9f5ec20d859d268c7cb3c5198c8d105d073714db3de50b593b8c1345a48f2 \ + --hash=sha256:787d2154a71f4b3d81f20524a8ce061b7db667d24e46753f32a7bc48f1c1f3f1 # via # opentelemetry-exporter-prometheus # ray -opentelemetry-semantic-conventions==0.60b1 \ - --hash=sha256:87c228b5a0669b748c76d76df6c364c369c28f1c465e50f661e39737e84bc953 \ - --hash=sha256:9fa8c8b0c110da289809292b0591220d3a7b53c1526a23021e977d68597893fb +opentelemetry-semantic-conventions==0.61b0 \ + --hash=sha256:072f65473c5d7c6dc0355b27d6c9d1a679d63b6d4b4b16a9773062cb7e31192a \ + --hash=sha256:fa530a96be229795f8cef353739b618148b0fe2b4b3f005e60e262926c4d38e2 # via opentelemetry-sdk -orjson==3.11.7 \ - --hash=sha256:043d3006b7d32c7e233b8cfb1f01c651013ea079e08dcef7189a29abd8befe11 \ - --hash=sha256:0527a4510c300e3b406591b0ba69b5dc50031895b0a93743526a3fc45f59d26e \ - --hash=sha256:0724e265bc548af1dedebd9cb3d24b4e1c1e685a343be43e87ba922a5c5fff2f \ - --hash=sha256:136dcd6a2e796dfd9ffca9fc027d778567b0b7c9968d092842d3c323cef88aa8 \ - --hash=sha256:14f440c7268c8f8633d1b3d443a434bd70cb15686117ea6beff8fdc8f5917a1e \ - --hash=sha256:1d98b30cc1313d52d4af17d9c3d307b08389752ec5f2e5febdfada70b0f8c733 \ - --hash=sha256:1eb80451a9c351a71dfaf5b7ccc13ad065405217726b59fdbeadbcc544f9d223 \ - --hash=sha256:1ee5cc7160a821dfe14f130bc8e63e7611051f964b463d9e2a3a573204446a4d \ - --hash=sha256:23d6c20517a97a9daf1d48b580fcdc6f0516c6f4b5038823426033690b4d2650 \ - --hash=sha256:26c3b9132f783b7d7903bf1efb095fed8d4a3a85ec0d334ee8beff3d7a4749d5 \ - --hash=sha256:31c80ce534ac4ea3739c5ee751270646cbc46e45aea7576a38ffec040b4029a1 \ - --hash=sha256:3726be79e36e526e3d9c1aceaadbfb4a04ee80a72ab47b3f3c17fefb9812e7b8 \ - --hash=sha256:390a1dce0c055ddf8adb6aa94a73b45a4a7d7177b5c584b8d1c1947f2ba60fb3 \ - --hash=sha256:3a2479753bbb95b0ebcf7969f562cdb9668e6d12416a35b0dda79febf89cdea2 \ - --hash=sha256:3c4bc6c6ac52cdaa267552544c73e486fecbd710b7ac09bc024d5a78555a22f6 \ - --hash=sha256:411ebaf34d735e25e358a6d9e7978954a9c9d58cfb47bc6683cdc3964cd2f910 \ - --hash=sha256:4682d1db3bcebd2b64757e0ddf9e87ae5f00d29d16c5cdf3a62f561d08cc3dd2 \ - --hash=sha256:4a2e9c5be347b937a2e0203866f12bba36082e89b402ddb9e927d5822e43088d \ - --hash=sha256:57036b27ac8a25d81112eb0cc9835cd4833c5b16e1467816adc0015f59e870dc \ - --hash=sha256:5ede977b5fe5ac91b1dffc0a517ca4542d2ec8a6a4ff7b2652d94f640796342a \ - --hash=sha256:5fdfad2093bdd08245f2e204d977facd5f871c88c4a71230d5bcbd0e43bf6222 \ - --hash=sha256:623ad1b9548ef63886319c16fa317848e465a21513b31a6ad7b57443c3e0dcf5 \ - --hash=sha256:652c6c3af76716f4a9c290371ba2e390ede06f6603edb277b481daf37f6f464e \ - --hash=sha256:6543001328aa857187f905308a028935864aefe9968af3848401b6fe80dbb471 \ - --hash=sha256:6e776b998ac37c0396093d10290e60283f59cfe0fc3fccbd0ccc4bd04dd19892 \ - --hash=sha256:71924496986275a737f38e3f22b4e0878882b3f7a310d2ff4dc96e812789120c \ - --hash=sha256:733ae23ada68b804b222c44affed76b39e30806d38660bf1eb200520d259cc16 \ - --hash=sha256:7477aa6a6ec6139c5cb1cc7b214643592169a5494d200397c7fc95d740d5fcf3 \ - --hash=sha256:79cacb0b52f6004caf92405a7e1f11e6e2de8bdf9019e4f76b44ba045125cd6b \ - --hash=sha256:7ba61079379b0ae29e117db13bda5f28d939766e410d321ec1624afc6a0b0504 \ - --hash=sha256:800988273a014a0541483dc81021247d7eacb0c845a9d1a34a422bc718f41539 \ - --hash=sha256:814be4b49b228cfc0b3c565acf642dd7d13538f966e3ccde61f4f55be3e20785 \ - --hash=sha256:845c3e0d8ded9c9271cd79596b9b552448b885b97110f628fb687aee2eed11c1 \ - --hash=sha256:849e38203e5be40b776ed2718e587faf204d184fc9a008ae441f9442320c0cab \ - --hash=sha256:89e13dd3f89f1c38a9c9eba5fbf7cdc2d1feca82f5f290864b4b7a6aac704576 \ - --hash=sha256:89e440ebc74ce8ab5c7bc4ce6757b4a6b1041becb127df818f6997b5c71aa60b \ - --hash=sha256:8ff206156006da5b847c9304b6308a01e8cdbc8cce824e2779a5ba71c3def141 \ - --hash=sha256:91c81ef070c8f3220054115e1ef468b1c9ce8497b4e526cb9f68ab4dc0a7ac62 \ - --hash=sha256:9487abc2c2086e7c8eb9a211d2ce8855bae0e92586279d0d27b341d5ad76c85c \ - --hash=sha256:962d046ee1765f74a1da723f4b33e3b228fe3a48bd307acce5021dfefe0e29b2 \ - --hash=sha256:996b65230271f1a97026fd0e6a753f51fbc0c335d2ad0c6201f711b0da32693b \ - --hash=sha256:9b1a67243945819ce55d24a30b59d6a168e86220452d2c96f4d1f093e71c0c49 \ - --hash=sha256:9c0b51672e466fd7e56230ffbae7f1639e18d0ce023351fb75da21b71bc2c960 \ - --hash=sha256:9e54f3808e2b6b945078c41aa8d9b5834b28c50843846e97807e5adb75fa9705 \ - --hash=sha256:a02c833f38f36546ba65a452127633afce4cf0dd7296b753d3bb54e55e5c0174 \ - --hash=sha256:a12b80df61aab7b98b490fe9e4879925ba666fccdfcd175252ce4d9035865ace \ - --hash=sha256:a16bcd08ab0bcdfc7e8801d9c4a9cc17e58418e4d48ddc6ded4e9e4b1a94062b \ - --hash=sha256:a56df3239294ea5964adf074c54bcc4f0ccd21636049a2cf3ca9cf03b5d03cf1 \ - --hash=sha256:a709e881723c9b18acddcfb8ba357322491ad553e277cf467e1e7e20e2d90561 \ - --hash=sha256:ab49d4b2a6a1d415ddb9f37a21e02e0d5dbfe10b7870b21bf779fc21e9156157 \ - --hash=sha256:ae9e0b37a834cef7ce8f99de6498f8fad4a2c0bf6bfc3d02abd8ed56aa15b2de \ - --hash=sha256:b4a9eefdc70bf8bf9857f0290f973dec534ac84c35cd6a7f4083be43e7170a8f \ - --hash=sha256:b63c6e6738d7c3470ad01601e23376aa511e50e1f3931395b9f9c722406d1a67 \ - --hash=sha256:b7b1dae39230a393df353827c855a5f176271c23434cfd2db74e0e424e693e10 \ - --hash=sha256:b8d14b71c0b12963fe8a62aac87119f1afdf4cb88a400f61ca5ae581449efcb5 \ - --hash=sha256:b9f95dcdea9d4f805daa9ddf02617a89e484c6985fa03055459f90e87d7a0757 \ - --hash=sha256:b9fc4d0f81f394689e0814617aadc4f2ea0e8025f38c226cbf22d3b5ddbf025d \ - --hash=sha256:bd03ea7606833655048dab1a00734a2875e3e86c276e1d772b2a02556f0d895f \ - --hash=sha256:bd0d68edd7dfca1b2eca9361a44ac9f24b078de3481003159929a0573f21a6bf \ - --hash=sha256:bda117c4148e81f746655d5a3239ae9bd00cb7bc3ca178b5fc5a5997e9744183 \ - --hash=sha256:bf742e149121dc5648ba0a08ea0871e87b660467ef168a3a5e53bc1fbd64bb74 \ - --hash=sha256:c2428d358d85e8da9d37cba18b8c4047c55222007a84f97156a5b22028dfbfc0 \ - --hash=sha256:c2e85fe4698b6a56d5e2ebf7ae87544d668eb6bde1ad1226c13f44663f20ec9e \ - --hash=sha256:c43b8b5bab288b6b90dac410cca7e986a4fa747a2e8f94615aea407da706980d \ - --hash=sha256:cededd6738e1c153530793998e31c05086582b08315db48ab66649768f326baa \ - --hash=sha256:d06e5c5fed5caedd2e540d62e5b1c25e8c82431b9e577c33537e5fa4aa909539 \ - --hash=sha256:d772afdb22555f0c58cfc741bdae44180122b3616faa1ecadb595cd526e4c993 \ - --hash=sha256:d897e81f8d0cbd2abb82226d1860ad2e1ab3ff16d7b08c96ca00df9d45409ef4 \ - --hash=sha256:de0a37f21d0d364954ad5de1970491d7fbd0fb1ef7417d4d56a36dc01ba0c0a0 \ - --hash=sha256:e7745312efa9e11c17fbd3cb3097262d079da26930ae9ae7ba28fb738367cbad \ - --hash=sha256:ed46f17096e28fb28d2975834836a639af7278aa87c84f68ab08fbe5b8bd75fa \ - --hash=sha256:f4f7c956b5215d949a1f65334cf9d7612dde38f20a95f2315deef167def91a6f \ - --hash=sha256:f50979824bde13d32b4320eedd513431c921102796d86be3eee0b58e58a3ecd1 \ - --hash=sha256:f904c24bdeabd4298f7a977ef14ca2a022ca921ed670b92ecd16ab6f3d01f867 +oracledb==3.4.2 \ + --hash=sha256:00c79448017f367bb7ab6900efe0706658a53768abea2b4519a4c9b2d5743890 \ + --hash=sha256:0e16fe3d057e0c41a23ad2ae95bfa002401690773376d476be608f79ac74bf05 \ + --hash=sha256:0f04a2d62073407672f114d02529921de0677c6883ed7c64d8d1a3c04caa3238 \ + --hash=sha256:1617a1db020346883455af005efbefd51be2c4d797e43b1b38455a19f8526b48 \ + --hash=sha256:19fa80ef84f85ad74077aa626067bbe697e527bd39604b4209f9d86cb2876b89 \ + --hash=sha256:1e4930d7f6584832dcc15b8ca415a7957b0c45f5aa7c4f88702e070e5c53bf93 \ + --hash=sha256:23aa07c1eaca17ae74c6fdc86b218f58484d56452958aead1aa460c0596a76c1 \ + --hash=sha256:31b7ee83c23d0439778303de8a675717f805f7e8edb5556d48c4d8343bcf14f5 \ + --hash=sha256:3df8eee1410d25360599968b1625b000f10c5ae0e47274031a7842a9dc418890 \ + --hash=sha256:404ec1451d0448653ee074213b87d6c5bd65eaa74b50083ddf2c9c3e11c71c71 \ + --hash=sha256:46e0f2278ff1fe83fbc33a3b93c72d429323ec7eed47bc9484e217776cd437e5 \ + --hash=sha256:55397e7eb43bb7017c03a981c736c25724182f5210951181dfe3fab0e5d457fb \ + --hash=sha256:574c8280d49cbbe21dbe03fc28356d9b9a5b9e300ebcde6c6d106e51453a7e65 \ + --hash=sha256:59ad6438f56a25e8e1a4a3dd1b42235a5d09ab9ba417ff2ad14eae6596f3d06f \ + --hash=sha256:5d7befb014174c5ae11c3a08f5ed6668a25ab2335d8e7104dca70d54d54a5b3a \ + --hash=sha256:5ed78d7e7079a778062744ccf42141ce4806818c3f4dd6463e4a7edd561c9f86 \ + --hash=sha256:643c25d301a289a371e37fcedb59e5fa5e54fb321708e5c12821c4b55bdd8a4d \ + --hash=sha256:6d85622664cc88d5a82bbd7beccb62cd53bd272c550a5e15e7d5f8ae6b86f1f1 \ + --hash=sha256:9f434a739405557bd57cb39b62238142bb27855a524a70dc6d397a2a8c576c9d \ + --hash=sha256:a7396664e592881225ba66385ee83ce339d864f39003d6e4ca31a894a7e7c552 \ + --hash=sha256:ac25a0448fc830fb7029ad50cd136cdbfcd06975d53967e269772cc5cb8c203a \ + --hash=sha256:b1095d95d0c8b37e4d0e17cf1928919cb59222b6344362a1cf6a2f3ca205a28a \ + --hash=sha256:b26a10f9c790bd141ffc8af68520803ed4a44a9258bf7d1eea9bfdd36bd6df7f \ + --hash=sha256:b8e4b8a852251cef09038b75f30fce1227010835f4e19cfbd436027acba2697c \ + --hash=sha256:b974caec2c330c22bbe765705a5ac7d98ec3022811dec2042d561a3c65cb991b \ + --hash=sha256:d7ce75c498bff758548ec6e4424ab4271aa257e5887cc436a54bc947fd46199a \ + --hash=sha256:d8d75e4f879b908be66cce05ba6c05791a5dbb4a15e39abc01aa25c8a2492bd9 \ + --hash=sha256:e068ef844a327877bfefbef1bc6fb7284c727bb87af80095f08d95bcaf7b8bb2 \ + --hash=sha256:f8ea989965a4f636a309444bd696ab877bba373d5d67bf744785f9bd8c560865 \ + --hash=sha256:f93cae08e8ed20f2d5b777a8602a71f9418389c661d2c937e84d94863e7e7011 \ + --hash=sha256:ff3c89cecea62af8ca02aa33cab0f2edc0214c747eac7d3364ed6b2640cb55e4 + # via ibis-framework +orjson==3.11.8 \ + --hash=sha256:0022bb50f90da04b009ce32c512dc1885910daa7cb10b7b0cba4505b16db82a8 \ + --hash=sha256:003646067cc48b7fcab2ae0c562491c9b5d2cbd43f1e5f16d98fd118c5522d34 \ + --hash=sha256:01928d0476b216ad2201823b0a74000440360cef4fed1912d297b8d84718f277 \ + --hash=sha256:01c4e5a6695dc09098f2e6468a251bc4671c50922d4d745aff1a0a33a0cf5b8d \ + --hash=sha256:093d489fa039ddade2db541097dbb484999fcc65fc2b0ff9819141e2ab364f25 \ + --hash=sha256:0b57f67710a8cd459e4e54eb96d5f77f3624eba0c661ba19a525807e42eccade \ + --hash=sha256:0e32f7154299f42ae66f13488963269e5eccb8d588a65bc839ed986919fc9fac \ + --hash=sha256:14439063aebcb92401c11afc68ee4e407258d2752e62d748b6942dad20d2a70d \ + --hash=sha256:14778ffd0f6896aa613951a7fbf4690229aa7a543cb2bfbe9f358e08aafa9546 \ + --hash=sha256:14f7b8fcb35ef403b42fa5ecfa4ed032332a91f3dc7368fbce4184d59e1eae0d \ + --hash=sha256:1ab359aff0436d80bfe8a23b46b5fea69f1e18aaf1760a709b4787f1318b317f \ + --hash=sha256:1cd0b77e77c95758f8e1100139844e99f3ccc87e71e6fc8e1c027e55807c549f \ + --hash=sha256:25e0c672a2e32348d2eb33057b41e754091f2835f87222e4675b796b92264f06 \ + --hash=sha256:29c009e7a2ca9ad0ed1376ce20dd692146a5d9fe4310848904b6b4fee5c5c137 \ + --hash=sha256:3222adff1e1ff0dce93c16146b93063a7793de6c43d52309ae321234cdaf0f4d \ + --hash=sha256:3223665349bbfb68da234acd9846955b1a0808cbe5520ff634bf253a4407009b \ + --hash=sha256:3cf17c141617b88ced4536b2135c552490f07799f6ad565948ea07bef0dcb9a6 \ + --hash=sha256:3f23426851d98478c8970da5991f84784a76682213cd50eb73a1da56b95239dc \ + --hash=sha256:3f262401086a3960586af06c054609365e98407151f5ea24a62893a40d80dbbb \ + --hash=sha256:436c4922968a619fb7fef1ccd4b8b3a76c13b67d607073914d675026e911a65c \ + --hash=sha256:469ac2125611b7c5741a0b3798cd9e5786cbad6345f9f400c77212be89563bec \ + --hash=sha256:4861bde57f4d253ab041e374f44023460e60e71efaa121f3c5f0ed457c3a701e \ + --hash=sha256:48854463b0572cc87dac7d981aa72ed8bf6deedc0511853dc76b8bbd5482d36d \ + --hash=sha256:53a0f57e59a530d18a142f4d4ba6dfc708dc5fdedce45e98ff06b44930a2a48f \ + --hash=sha256:54153d21520a71a4c82a0dbb4523e468941d549d221dc173de0f019678cf3813 \ + --hash=sha256:55120759e61309af7fcf9e961c6f6af3dde5921cdb3ee863ef63fd9db126cae6 \ + --hash=sha256:5774c1fdcc98b2259800b683b19599c133baeb11d60033e2095fd9d4667b82db \ + --hash=sha256:58a4a208a6fbfdb7a7327b8f201c6014f189f721fd55d047cafc4157af1bc62a \ + --hash=sha256:58fb9b17b4472c7b1dcf1a54583629e62e23779b2331052f09a9249edf81675b \ + --hash=sha256:5d8b5231de76c528a46b57010bbd83fb51e056aa0220a372fd5065e978406f1c \ + --hash=sha256:5f8952d6d2505c003e8f0224ff7858d341fa4e33fef82b91c4ff0ef070f2393c \ + --hash=sha256:61c9d357a59465736022d5d9ba06687afb7611dfb581a9d2129b77a6fcf78e59 \ + --hash=sha256:6a3d159d5ffa0e3961f353c4b036540996bf8b9697ccc38261c0eac1fd3347a6 \ + --hash=sha256:6a4a639049c44d36a6d1ae0f4a94b271605c745aee5647fa8ffaabcdc01b69a6 \ + --hash=sha256:6ccdea2c213cf9f3d9490cbd5d427693c870753df41e6cb375bd79bcbafc8817 \ + --hash=sha256:6dbe9a97bdb4d8d9d5367b52a7c32549bba70b2739c58ef74a6964a6d05ae054 \ + --hash=sha256:6eda5b8b6be91d3f26efb7dc6e5e68ee805bc5617f65a328587b35255f138bf4 \ + --hash=sha256:705b895b781b3e395c067129d8551655642dfe9437273211d5404e87ac752b53 \ + --hash=sha256:708c95f925a43ab9f34625e45dcdadf09ec8a6e7b664a938f2f8d5650f6c090b \ + --hash=sha256:735e2262363dcbe05c35e3a8869898022af78f89dde9e256924dc02e99fe69ca \ + --hash=sha256:76070a76e9c5ae661e2d9848f216980d8d533e0f8143e6ed462807b242e3c5e8 \ + --hash=sha256:7679bc2f01bb0d219758f1a5f87bb7c8a81c0a186824a393b366876b4948e14f \ + --hash=sha256:88006eda83858a9fdf73985ce3804e885c2befb2f506c9a3723cdeb5a2880e3e \ + --hash=sha256:883206d55b1bd5f5679ad5e6ddd3d1a5e3cac5190482927fdb8c78fb699193b5 \ + --hash=sha256:8ac7381c83dd3d4a6347e6635950aa448f54e7b8406a27c7ecb4a37e9f1ae08b \ + --hash=sha256:8e8c6218b614badf8e229b697865df4301afa74b791b6c9ade01d19a9953a942 \ + --hash=sha256:9185589c1f2a944c17e26c9925dcdbc2df061cc4a145395c57f0c51f9b5dbfcd \ + --hash=sha256:93de06bc920854552493c81f1f729fab7213b7db4b8195355db5fda02c7d1363 \ + --hash=sha256:96163d9cdc5a202703e9ad1b9ae757d5f0ca62f4fa0cc93d1f27b0e180cc404e \ + --hash=sha256:97c8f5d3b62380b70c36ffacb2a356b7c6becec86099b177f73851ba095ef623 \ + --hash=sha256:97d823831105c01f6c8029faf297633dbeb30271892bd430e9c24ceae3734744 \ + --hash=sha256:98bdc6cb889d19bed01de46e67574a2eab61f5cc6b768ed50e8ac68e9d6ffab6 \ + --hash=sha256:9b48e274f8824567d74e2158199e269597edf00823a1b12b63d48462bbf5123e \ + --hash=sha256:a5c370674ebabe16c6ccac33ff80c62bf8a6e59439f5e9d40c1f5ab8fd2215b7 \ + --hash=sha256:b43dc2a391981d36c42fa57747a49dae793ef1d2e43898b197925b5534abd10a \ + --hash=sha256:c154a35dd1330707450bb4d4e7dd1f17fa6f42267a40c1e8a1daa5e13719b4b8 \ + --hash=sha256:c2bdf7b2facc80b5e34f48a2d557727d5c5c57a8a450de122ae81fa26a81c1bc \ + --hash=sha256:c492a0e011c0f9066e9ceaa896fbc5b068c54d365fea5f3444b697ee01bc8625 \ + --hash=sha256:c60c0423f15abb6cf78f56dff00168a1b582f7a1c23f114036e2bfc697814d5f \ + --hash=sha256:c98121237fea2f679480765abd566f7713185897f35c9e6c2add7e3a9900eb61 \ + --hash=sha256:ccd7ba1b0605813a0715171d39ec4c314cb97a9c85893c2c5c0c3a3729df38bf \ + --hash=sha256:cdbc8c9c02463fef4d3c53a9ba3336d05496ec8e1f1c53326a1e4acc11f5c600 \ + --hash=sha256:e0950ed1bcb9893f4293fd5c5a7ee10934fbf82c4101c70be360db23ce24b7d2 \ + --hash=sha256:e6693ff90018600c72fd18d3d22fa438be26076cd3c823da5f63f7bab28c11cb \ + --hash=sha256:ea56a955056a6d6c550cf18b3348656a9d9a4f02e2d0c02cabf3c73f1055d506 \ + --hash=sha256:ebaed4cef74a045b83e23537b52ef19a367c7e3f536751e355a2a394f8648559 \ + --hash=sha256:ec795530a73c269a55130498842aaa762e4a939f6ce481a7e986eeaa790e9da4 \ + --hash=sha256:ed193ce51d77a3830cad399a529cd4ef029968761f43ddc549e1bc62b40d88f8 \ + --hash=sha256:ee8db7bfb6fe03581bbab54d7c4124a6dd6a7f4273a38f7267197890f094675f \ + --hash=sha256:f30491bc4f862aa15744b9738517454f1e46e56c972a2be87d70d727d5b2a8f8 \ + --hash=sha256:f89b6d0b3a8d81e1929d3ab3d92bbc225688bd80a770c49432543928fe09ac55 \ + --hash=sha256:fa72e71977bff96567b0f500fc5bfd2fdf915f34052c782a4c6ebbdaa97aa858 \ + --hash=sha256:fe0b8c83e0f36247fc9431ce5425a5d95f9b3a689133d494831bdbd6f0bceb13 \ + --hash=sha256:ff51f9d657d1afb6f410cb435792ce4e1fe427aab23d2fcd727a2876e21d4cb6 # via trino packaging==26.0 \ --hash=sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4 \ @@ -3573,26 +3633,26 @@ propcache==0.4.1 \ # via # aiohttp # yarl -proto-plus==1.27.1 \ - --hash=sha256:912a7460446625b792f6448bade9e55cd4e41e6ac10e27009ef71a7f317fa147 \ - --hash=sha256:e4643061f3a4d0de092d62aa4ad09fa4756b2cbb89d4627f3985018216f9fefc +proto-plus==1.27.2 \ + --hash=sha256:6432f75893d3b9e70b9c412f1d2f03f65b11fb164b793d14ae2ca01821d22718 \ + --hash=sha256:b2adde53adadf75737c44d3dcb0104fde65250dfc83ad59168b4aa3e574b6a24 # via # google-api-core # google-cloud-bigquery-storage # google-cloud-bigtable # google-cloud-datastore -protobuf==4.25.8 \ - --hash=sha256:077ff8badf2acf8bc474406706ad890466274191a48d0abd3bd6987107c9cde5 \ - --hash=sha256:15a0af558aa3b13efef102ae6e4f3efac06f1eea11afb3a57db2901447d9fb59 \ - --hash=sha256:27d498ffd1f21fb81d987a041c32d07857d1d107909f5134ba3350e1ce80a4af \ - --hash=sha256:504435d831565f7cfac9f0714440028907f1975e4bed228e58e72ecfff58a1e0 \ - --hash=sha256:6135cf8affe1fc6f76cced2641e4ea8d3e59518d1f24ae41ba97bcad82d397cd \ - --hash=sha256:83e6e54e93d2b696a92cad6e6efc924f3850f82b52e1563778dfab8b355101b0 \ - --hash=sha256:9ad7ef62d92baf5a8654fbb88dac7fa5594cfa70fd3440488a5ca3bfc6d795a7 \ - --hash=sha256:bd551eb1fe1d7e92c1af1d75bdfa572eff1ab0e5bf1736716814cdccdb2360f9 \ - --hash=sha256:ca809b42f4444f144f2115c4c1a747b9a404d590f18f37e9402422033e464e0f \ - --hash=sha256:d552c53d0415449c8d17ced5c341caba0d89dbf433698e1436c8fa0aae7808a3 \ - --hash=sha256:f4510b93a3bec6eba8fd8f1093e9d7fb0d4a24d1a81377c10c0e5bbfe9e4ed24 +protobuf==4.25.9 \ + --hash=sha256:3683c05154252206f7cb2d371626514b3708199d9bcf683b503dabf3a2e38e06 \ + --hash=sha256:438c636de8fb706a0de94a12a268ef1ae8f5ba5ae655a7671fcda5968ba3c9be \ + --hash=sha256:79faf4e5a80b231d94dcf3a0a2917ccbacf0f586f12c9b9c91794b41b913a853 \ + --hash=sha256:7f7c1abcea3fc215918fba67a2d2a80fbcccc0f84159610eb187e9bbe6f939ee \ + --hash=sha256:9481e80e8cffb1c492c68e7c4e6726f4ad02eebc4fa97ead7beebeaa3639511d \ + --hash=sha256:9560813560e6ee72c11ca8873878bdb7ee003c96a57ebb013245fe84e2540904 \ + --hash=sha256:999146ef02e7fa6a692477badd1528bcd7268df211852a3df2d834ba2b480791 \ + --hash=sha256:b0dc7e7c68de8b1ce831dacb12fb407e838edbb8b6cc0dc3a2a6b4cbf6de9cff \ + --hash=sha256:b1d467352de666dc1b6d5740b6319d9c08cab7b21b452501e4ee5b0ac5156780 \ + --hash=sha256:bde396f568b0b46fc8fbfe9f02facf25b6755b2578a3b8ac61e74b9d69499e03 \ + --hash=sha256:d49b615e7c935194ac161f0965699ac84df6112c378e05ec53da65d2e4cbb6d4 # via # feast (pyproject.toml) # google-api-core @@ -3606,7 +3666,6 @@ protobuf==4.25.8 \ # grpcio-status # grpcio-testing # grpcio-tools - # ikvpy # mypy-protobuf # opentelemetry-proto # proto-plus @@ -3823,12 +3882,10 @@ pyarrow-hotfix==0.7 \ --hash=sha256:3236f3b5f1260f0e2ac070a55c1a7b339c4bb7267839bd2015e283234e758100 \ --hash=sha256:59399cd58bdd978b2e42816a4183a55c6472d4e33d183351b6069f11ed42661d # via ibis-framework -pyasn1==0.6.2 \ - --hash=sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf \ - --hash=sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b - # via - # pyasn1-modules - # rsa +pyasn1==0.6.3 \ + --hash=sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf \ + --hash=sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde + # via pyasn1-modules pyasn1-modules==0.4.2 \ --hash=sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a \ --hash=sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6 @@ -4063,9 +4120,9 @@ pydantic-core==2.41.5 \ --hash=sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425 \ --hash=sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52 # via pydantic -pydantic-settings==2.13.0 \ - --hash=sha256:95d875514610e8595672800a5c40b073e99e4aae467fa7c8f9c263061ea2e1fe \ - --hash=sha256:d67b576fff39cd086b595441bf9c75d4193ca9c0ed643b90360694d0f1240246 +pydantic-settings==2.13.1 \ + --hash=sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025 \ + --hash=sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237 # via # docling # fastapi-mcp @@ -4074,9 +4131,9 @@ pydata-google-auth==1.9.1 \ --hash=sha256:0a51ce41c601ca0bc69b8795bf58bedff74b4a6a007c9106c7cbcdec00eaced2 \ --hash=sha256:75ffce5d106e34b717b31844c1639ea505b7d9550dc23b96fb6c20d086b53fa3 # via pandas-gbq -pygments==2.19.2 \ - --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \ - --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b +pygments==2.20.0 \ + --hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \ + --hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176 # via # feast (pyproject.toml) # ipython @@ -4085,11 +4142,12 @@ pygments==2.19.2 \ # nbconvert # rich # sphinx -pyjwt[crypto]==2.11.0 \ - --hash=sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623 \ - --hash=sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469 +pyjwt[crypto]==2.12.1 \ + --hash=sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c \ + --hash=sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b # via # feast (pyproject.toml) + # kube-authkit # mcp # msal # singlestoredb @@ -4260,9 +4318,9 @@ pyodbc==5.3.0 \ # via # feast (pyproject.toml) # ibis-framework -pyopenssl==25.1.0 \ - --hash=sha256:2b11f239acc47ac2e5aca04fd7fa829800aeee22a2eb30d744572a157bd8a1ab \ - --hash=sha256:8d031884482e0c67ee92bf9a4d8cceb08d92aba7136432ffb0703c5280fc205b +pyopenssl==26.0.0 \ + --hash=sha256:df94d28498848b98cc1c0ffb8ef1e71e40210d3b0a8064c9d29571ed2904bf81 \ + --hash=sha256:f293934e52936f2e3413b89c6ce36df66a0b34ae1ea3a053b8c5020ff2f513fc # via snowflake-connector-python pyparsing==3.3.2 \ --hash=sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d \ @@ -4314,9 +4372,9 @@ pytest-benchmark==3.4.1 \ --hash=sha256:36d2b08c4882f6f997fd3126a3d6dfd70f3249cde178ed8bbc0b73db7c20f809 \ --hash=sha256:40e263f912de5a81d891619032983557d62a3d85843f9a9f30b98baea0cd7b47 # via feast (pyproject.toml) -pytest-cov==7.0.0 \ - --hash=sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1 \ - --hash=sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861 +pytest-cov==7.1.0 \ + --hash=sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2 \ + --hash=sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678 # via feast (pyproject.toml) pytest-env==1.1.3 \ --hash=sha256:aada77e6d09fcfb04540a6e462c58533c37df35fa853da78707b17ec04d17dfc \ @@ -4472,17 +4530,17 @@ python-docx==1.2.0 \ --hash=sha256:3fd478f3250fbbbfd3b94fe1e985955737c145627498896a8a6bf81f4baf66c7 \ --hash=sha256:7bc9d7b7d8a69c9c02ca09216118c86552704edc23bac179283f2e38f86220ce # via docling -python-dotenv==1.2.1 \ - --hash=sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6 \ - --hash=sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61 +python-dotenv==1.2.2 \ + --hash=sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a \ + --hash=sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3 # via # pydantic-settings # pymilvus # testcontainers # uvicorn -python-json-logger==4.0.0 \ - --hash=sha256:af09c9daf6a813aa4cc7180395f50f2a9e5fa056034c9953aec92e381c5ba1e2 \ - --hash=sha256:f58e68eb46e1faed27e0f574a55a0455eecd7b8a5b88b85a784519ba3cff047f +python-json-logger==4.1.0 \ + --hash=sha256:132994765cf75bf44554be9aa49b06ef2345d23661a96720262716438141b6b2 \ + --hash=sha256:b396b9e3ed782b09ff9d6e4f1683d46c83ad0d35d2e407c09a9ebbf038f88195 # via jupyter-events python-keycloak==4.2.2 \ --hash=sha256:1d43a1accd4a038ed39317fcb3eb78211df6c75bbcbc4c482c99ee76327136f2 \ @@ -4496,9 +4554,9 @@ python-pptx==1.0.2 \ --hash=sha256:160838e0b8565a8b1f67947675886e9fea18aa5e795db7ae531606d68e785cba \ --hash=sha256:479a8af0eaf0f0d76b6f00b0887732874ad2e3188230315290cd1f9dd9cc7095 # via docling -pytz==2025.2 \ - --hash=sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3 \ - --hash=sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00 +pytz==2026.1.post1 \ + --hash=sha256:3378dde6a0c3d26719182142c56e60c7f9af7e968076f31aae569d72a0358ee1 \ + --hash=sha256:f2fd16142fda348286a75e1a524be810bb05d444e5a081f37f7affc635035f7a # via # clickhouse-connect # great-expectations @@ -4694,26 +4752,26 @@ pyzmq==27.1.0 \ # ipykernel # jupyter-client # jupyter-server -qdrant-client==1.16.2 \ - --hash=sha256:442c7ef32ae0f005e88b5d3c0783c63d4912b97ae756eb5e052523be682f17d3 \ - --hash=sha256:ca4ef5f9be7b5eadeec89a085d96d5c723585a391eb8b2be8192919ab63185f0 +qdrant-client==1.17.1 \ + --hash=sha256:22f990bbd63485ed97ba551a4c498181fcb723f71dcab5d6e4e43fe1050a2bc0 \ + --hash=sha256:6cda4064adfeaf211c751f3fbc00edbbdb499850918c7aff4855a9a759d56cbd # via feast (pyproject.toml) -ray[data, default]==2.52.1 \ - --hash=sha256:08eb8f5fd55292ba6bee363a32491136a5e54af54e007f81e0603986fbea41a4 \ - --hash=sha256:24694e60cdc7770b90f123cc578cabb9d1a231c1fe673b5da0027b118de45846 \ - --hash=sha256:2b57ef272a2a0a0dbae6d18d70aa541eab620b4fe3b44d50466d3a533c16f9d9 \ - --hash=sha256:4e8478544fef69a17d865431c0bebdcfeff7c0f76a306f29b73c3bc3cbb0bdb9 \ - --hash=sha256:65bf461fdfe4ffa667c46f9455f8740b2ad6c1fa471b461d5f5cf6b7baf177b5 \ - --hash=sha256:6831592fedf0a122016f5dab4b67d85fa3d4db3b21f588d18834b5c031396d1c \ - --hash=sha256:8045172ad3fcff62b9dab9a4cd2e0991ad0e27fc814fe625a8d3a120306651d6 \ - --hash=sha256:843c0108ad72bb7fc6c23a22e29e6099546a5eaad3ad675c78a146d9080f6ec6 \ - --hash=sha256:993194a8be70540e0f819862031bbf19a64401fbe6c31b42065fd313ba466d34 \ - --hash=sha256:a5a3c268d45060c50cd029979ecc5f1eaaec040b19fa88dd4fe9e927d19ff13e \ - --hash=sha256:b3f9e61b799fb3cc8fd7077a3d2eb676ddfef7db644f6b6a2b657c5c3214cf19 \ - --hash=sha256:b5bc29548abb0a0a7ae9e6ff3b0ccca2824edaf011a4336e15a32793d574fbfd \ - --hash=sha256:bbe492c780a39a64bd3d0766cad10d54cf12222df88d287ec2d8f2d52de37c79 \ - --hash=sha256:e3826aeb4e4399de0c6885bd8be7ce2f629fa0010f0013f1183e0726b3d25e40 \ - --hash=sha256:f59e3b2d1a1466ac0778f2c6fac9ccb5f30107d77e3dddd1d60167248d268474 +ray[data, default]==2.53.0 \ + --hash=sha256:14f46363e9b4cf0c1c8b4d8623ec337c5bd408377831b5e5b50067930137bbca \ + --hash=sha256:4108280d8a1cb90d7d68e5c954c35e63b8bb9a4ba15f88c5e7da0e2025647712 \ + --hash=sha256:4a1bb3fe09ab4cd0d16ddc96b9f60c9ed83b3f93b87aa8506e0d3b746fd4e825 \ + --hash=sha256:4db914a0a6dd608fa49c066929a1282745a2dbd73caee67d7b80fe684ca65bdd \ + --hash=sha256:4dbb5fce1364763f29741055f50abe33cf726397141f9cc0e845dd3cc963e455 \ + --hash=sha256:65e2ce58d3dc6baa3cf45824d889c1968ebde565ee54dfd80a98af8f31af8e4a \ + --hash=sha256:7196e5358dfcc8211be864f45e6dfe4827202df294af3c7a76ff8fbc080e0522 \ + --hash=sha256:73dbbaa7962a7f5e38aa8cf9483e0e9817205e989aa3dc859c738c2af1ae01df \ + --hash=sha256:85b472ab6fb8f1189f8cef81913fd91b24dd69b3fa7dcca7e144827bd924f6c0 \ + --hash=sha256:90faf630d20b6abf3135997fb3edb5842134aff92e04ee709865db04816d97ef \ + --hash=sha256:a0bbb98b0b0f25a3ee075ca10171e1260e70b6bc690cd509ecd7ce1228af854d \ + --hash=sha256:b828c147f9ff2f277b1d254e4fe9a746fdfaee7e313a93a97c7edf4dae9b81a4 \ + --hash=sha256:bd3ec4c342776ddac23ae2b108c64f5939f417ccc4875900d586c7c978463269 \ + --hash=sha256:d8b95d047d947493803fb8417aea31225dcacdab15afdc75b8a238901949d457 \ + --hash=sha256:eb000c17f7301071fdd15c44c4cd3ac0f7953bb4c7c227e61719fe7048195bcd # via codeflare-sdk redis==4.6.0 \ --hash=sha256:585dc516b9eb042a619ef0a39c3d7d55fe81bdb4df09a52c9cdde0d07bf1aa7d \ @@ -4726,145 +4784,128 @@ referencing==0.37.0 \ # jsonschema # jsonschema-specifications # jupyter-events -regex==2026.1.15 \ - --hash=sha256:0057de9eaef45783ff69fa94ae9f0fd906d629d0bd4c3217048f46d1daa32e9b \ - --hash=sha256:008b185f235acd1e53787333e5690082e4f156c44c87d894f880056089e9bc7c \ - --hash=sha256:05d75a668e9ea16f832390d22131fe1e8acc8389a694c8febc3e340b0f810b93 \ - --hash=sha256:069f56a7bf71d286a6ff932a9e6fb878f151c998ebb2519a9f6d1cee4bffdba3 \ - --hash=sha256:0751a26ad39d4f2ade8fe16c59b2bf5cb19eb3d2cd543e709e583d559bd9efde \ - --hash=sha256:08df9722d9b87834a3d701f3fca570b2be115654dbfd30179f30ab2f39d606d3 \ - --hash=sha256:0bda75ebcac38d884240914c6c43d8ab5fb82e74cde6da94b43b17c411aa4c2b \ - --hash=sha256:0bf065240704cb8951cc04972cf107063917022511273e0969bdb34fc173456c \ - --hash=sha256:0bf650f26087363434c4e560011f8e4e738f6f3e029b85d4904c50135b86cfa5 \ - --hash=sha256:0dcd31594264029b57bf16f37fd7248a70b3b764ed9e0839a8f271b2d22c0785 \ - --hash=sha256:0f0c7684c7f9ca241344ff95a1de964f257a5251968484270e91c25a755532c5 \ - --hash=sha256:124dc36c85d34ef2d9164da41a53c1c8c122cfb1f6e1ec377a1f27ee81deb794 \ - --hash=sha256:164759aa25575cbc0651bef59a0b18353e54300d79ace8084c818ad8ac72b7d5 \ - --hash=sha256:166551807ec20d47ceaeec380081f843e88c8949780cd42c40f18d16168bed10 \ - --hash=sha256:1704d204bd42b6bb80167df0e4554f35c255b579ba99616def38f69e14a5ccb9 \ - --hash=sha256:18388a62989c72ac24de75f1449d0fb0b04dfccd0a1a7c1c43af5eb503d890f6 \ - --hash=sha256:194312a14819d3e44628a44ed6fea6898fdbecb0550089d84c403475138d0a09 \ - --hash=sha256:1ae6020fb311f68d753b7efa9d4b9a5d47a5d6466ea0d5e3b5a471a960ea6e4a \ - --hash=sha256:1cb740d044aff31898804e7bf1181cc72c03d11dfd19932b9911ffc19a79070a \ - --hash=sha256:1e1808471fbe44c1a63e5f577a1d5f02fe5d66031dcbdf12f093ffc1305a858e \ - --hash=sha256:1e8cd52557603f5c66a548f69421310886b28b7066853089e1a71ee710e1cdc1 \ - --hash=sha256:21ca32c28c30d5d65fc9886ff576fc9b59bbca08933e844fa2363e530f4c8218 \ - --hash=sha256:2748c1ec0663580b4510bd89941a31560b4b439a0b428b49472a3d9944d11cd8 \ - --hash=sha256:27618391db7bdaf87ac6c92b31e8f0dfb83a9de0075855152b720140bda177a2 \ - --hash=sha256:2a8d7b50c34578d0d3bf7ad58cde9652b7d683691876f83aedc002862a35dc5e \ - --hash=sha256:2b091aefc05c78d286657cd4db95f2e6313375ff65dcf085e42e4c04d9c8d410 \ - --hash=sha256:2c2b80399a422348ce5de4fe40c418d6299a0fa2803dd61dc0b1a2f28e280fcf \ - --hash=sha256:2f2775843ca49360508d080eaa87f94fa248e2c946bbcd963bb3aae14f333413 \ - --hash=sha256:3038a62fc7d6e5547b8915a3d927a0fbeef84cdbe0b1deb8c99bbd4a8961b52a \ - --hash=sha256:32655d17905e7ff8ba5c764c43cb124e34a9245e45b83c22e81041e1071aee10 \ - --hash=sha256:343db82cb3712c31ddf720f097ef17c11dab2f67f7a3e7be976c4f82eba4e6df \ - --hash=sha256:3601ffb5375de85a16f407854d11cca8fe3f5febbe3ac78fb2866bb220c74d10 \ - --hash=sha256:3d6ce5ae80066b319ae3bc62fd55a557c9491baa5efd0d355f0de08c4ba54e79 \ - --hash=sha256:3d7d92495f47567a9b1669c51fc8d6d809821849063d168121ef801bbc213846 \ - --hash=sha256:40c86d8046915bb9aeb15d3f3f15b6fd500b8ea4485b30e1bbc799dab3fe29f8 \ - --hash=sha256:4161d87f85fa831e31469bfd82c186923070fc970b9de75339b68f0c75b51903 \ - --hash=sha256:41aef6f953283291c4e4e6850607bd71502be67779586a61472beacb315c97ec \ - --hash=sha256:453078802f1b9e2b7303fb79222c054cb18e76f7bdc220f7530fdc85d319f99e \ - --hash=sha256:492534a0ab925d1db998defc3c302dae3616a2fc3fe2e08db1472348f096ddf2 \ - --hash=sha256:4c5ef43b5c2d4114eb8ea424bb8c9cec01d5d17f242af88b2448f5ee81caadbc \ - --hash=sha256:4c8fcc5793dde01641a35905d6731ee1548f02b956815f8f1cab89e515a5bdf1 \ - --hash=sha256:4def140aa6156bc64ee9912383d4038f3fdd18fee03a6f222abd4de6357ce42a \ - --hash=sha256:4e3dd93c8f9abe8aa4b6c652016da9a3afa190df5ad822907efe6b206c09896e \ - --hash=sha256:505831646c945e3e63552cc1b1b9b514f0e93232972a2d5bedbcc32f15bc82e3 \ - --hash=sha256:5170907244b14303edc5978f522f16c974f32d3aa92109fabc2af52411c9433b \ - --hash=sha256:55b4ea996a8e4458dd7b584a2f89863b1655dd3d17b88b46cbb9becc495a0ec5 \ - --hash=sha256:55e9d0118d97794367309635df398bdfd7c33b93e2fdfa0b239661cd74b4c14e \ - --hash=sha256:56a5595d0f892f214609c9f76b41b7428bed439d98dc961efafdd1354d42baae \ - --hash=sha256:57e7d17f59f9ebfa9667e6e5a1c0127b96b87cb9cede8335482451ed00788ba4 \ - --hash=sha256:5ef19071f4ac9f0834793af85bd04a920b4407715624e40cb7a0631a11137cdf \ - --hash=sha256:5ff818702440a5878a81886f127b80127f5d50563753a28211482867f8318106 \ - --hash=sha256:619843841e220adca114118533a574a9cd183ed8a28b85627d2844c500a2b0db \ - --hash=sha256:621f73a07595d83f28952d7bd1e91e9d1ed7625fb7af0064d3516674ec93a2a2 \ - --hash=sha256:693b465171707bbe882a7a05de5e866f33c76aa449750bee94a8d90463533cc9 \ - --hash=sha256:6bfc31a37fd1592f0c4fc4bfc674b5c42e52efe45b4b7a6a14f334cca4bcebe4 \ - --hash=sha256:6d220a2517f5893f55daac983bfa9fe998a7dbcaee4f5d27a88500f8b7873788 \ - --hash=sha256:6e42844ad64194fa08d5ccb75fe6a459b9b08e6d7296bd704460168d58a388f3 \ - --hash=sha256:726ea4e727aba21643205edad8f2187ec682d3305d790f73b7a51c7587b64bdd \ - --hash=sha256:74f45d170a21df41508cb67165456538425185baaf686281fa210d7e729abc34 \ - --hash=sha256:7dcc02368585334f5bc81fc73a2a6a0bbade60e7d83da21cead622faf408f32c \ - --hash=sha256:7e1e28be779884189cdd57735e997f282b64fd7ccf6e2eef3e16e57d7a34a815 \ - --hash=sha256:7ef7d5d4bd49ec7364315167a4134a015f61e8266c6d446fc116a9ac4456e10d \ - --hash=sha256:8050ba2e3ea1d8731a549e83c18d2f0999fbc99a5f6bd06b4c91449f55291804 \ - --hash=sha256:82345326b1d8d56afbe41d881fdf62f1926d7264b2fc1537f99ae5da9aad7913 \ - --hash=sha256:8355ad842a7c7e9e5e55653eade3b7d1885ba86f124dd8ab1f722f9be6627434 \ - --hash=sha256:86c1077a3cc60d453d4084d5b9649065f3bf1184e22992bd322e1f081d3117fb \ - --hash=sha256:87adf5bd6d72e3e17c9cb59ac4096b1faaf84b7eb3037a5ffa61c4b4370f0f13 \ - --hash=sha256:8db052bbd981e1666f09e957f3790ed74080c2229007c1dd67afdbf0b469c48b \ - --hash=sha256:8dd16fba2758db7a3780a051f245539c4451ca20910f5a5e6ea1c08d06d4a76b \ - --hash=sha256:8e32f7896f83774f91499d239e24cebfadbc07639c1494bb7213983842348337 \ - --hash=sha256:91c5036ebb62663a6b3999bdd2e559fd8456d17e2b485bf509784cd31a8b1705 \ - --hash=sha256:9250d087bc92b7d4899ccd5539a1b2334e44eee85d848c4c1aef8e221d3f8c8f \ - --hash=sha256:9479cae874c81bf610d72b85bb681a94c95722c127b55445285fb0e2c82db8e1 \ - --hash=sha256:968c14d4f03e10b2fd960f1d5168c1f0ac969381d3c1fcc973bc45fb06346599 \ - --hash=sha256:97499ff7862e868b1977107873dd1a06e151467129159a6ffd07b66706ba3a9f \ - --hash=sha256:99ad739c3686085e614bf77a508e26954ff1b8f14da0e3765ff7abbf7799f952 \ - --hash=sha256:9d787e3310c6a6425eb346be4ff2ccf6eece63017916fd77fe8328c57be83521 \ - --hash=sha256:a1774cd1981cd212506a23a14dba7fdeaee259f5deba2df6229966d9911e767a \ - --hash=sha256:a30a68e89e5a218b8b23a52292924c1f4b245cb0c68d1cce9aec9bbda6e2c160 \ - --hash=sha256:adc97a9077c2696501443d8ad3fa1b4fc6d131fc8fd7dfefd1a723f89071cf0a \ - --hash=sha256:b0d190e6f013ea938623a58706d1469a62103fb2a241ce2873a9906e0386582c \ - --hash=sha256:b10e42a6de0e32559a92f2f8dc908478cc0fa02838d7dbe764c44dca3fa13569 \ - --hash=sha256:b2a13dd6a95e95a489ca242319d18fc02e07ceb28fa9ad146385194d95b3c829 \ - --hash=sha256:b30bcbd1e1221783c721483953d9e4f3ab9c5d165aa709693d3f3946747b1aea \ - --hash=sha256:b325d4714c3c48277bfea1accd94e193ad6ed42b4bad79ad64f3b8f8a31260a5 \ - --hash=sha256:b5a28980a926fa810dbbed059547b02783952e2efd9c636412345232ddb87ff6 \ - --hash=sha256:b5f7d8d2867152cdb625e72a530d2ccb48a3d199159144cbdd63870882fb6f80 \ - --hash=sha256:bfb0d6be01fbae8d6655c8ca21b3b72458606c4aec9bbc932db758d47aba6db1 \ - --hash=sha256:bfd876041a956e6a90ad7cdb3f6a630c07d491280bfeed4544053cd434901681 \ - --hash=sha256:c08c1f3e34338256732bd6938747daa3c0d5b251e04b6e43b5813e94d503076e \ - --hash=sha256:c243da3436354f4af6c3058a3f81a97d47ea52c9bd874b52fd30274853a1d5df \ - --hash=sha256:c32bef3e7aeee75746748643667668ef941d28b003bfc89994ecf09a10f7a1b5 \ - --hash=sha256:c661fc820cfb33e166bf2450d3dadbda47c8d8981898adb9b6fe24e5e582ba60 \ - --hash=sha256:c6c4dcdfff2c08509faa15d36ba7e5ef5fcfab25f1e8f85a0c8f45bc3a30725d \ - --hash=sha256:c6c565d9a6e1a8d783c1948937ffc377dd5771e83bd56de8317c450a954d2056 \ - --hash=sha256:c8a154cf6537ebbc110e24dabe53095e714245c272da9c1be05734bdad4a61aa \ - --hash=sha256:c9c08c2fbc6120e70abff5d7f28ffb4d969e14294fb2143b4b5c7d20e46d1714 \ - --hash=sha256:ca89c5e596fc05b015f27561b3793dc2fa0917ea0d7507eebb448efd35274a70 \ - --hash=sha256:cc7cd0b2be0f0269283a45c0d8b2c35e149d1319dcb4a43c9c3689fa935c1ee6 \ - --hash=sha256:cda1ed70d2b264952e88adaa52eea653a33a1b98ac907ae2f86508eb44f65cdc \ - --hash=sha256:cf8ff04c642716a7f2048713ddc6278c5fd41faa3b9cab12607c7abecd012c22 \ - --hash=sha256:cfecdaa4b19f9ca534746eb3b55a5195d5c95b88cac32a205e981ec0a22b7d31 \ - --hash=sha256:d426616dae0967ca225ab12c22274eb816558f2f99ccb4a1d52ca92e8baf180f \ - --hash=sha256:d5eaa4a4c5b1906bd0d2508d68927f15b81821f85092e06f1a34a4254b0e1af3 \ - --hash=sha256:d639a750223132afbfb8f429c60d9d318aeba03281a5f1ab49f877456448dcf1 \ - --hash=sha256:d920392a6b1f353f4aa54328c867fec3320fa50657e25f64abf17af054fc97ac \ - --hash=sha256:d991483606f3dbec93287b9f35596f41aa2e92b7c2ebbb935b63f409e243c9af \ - --hash=sha256:d9ea2604370efc9a174c1b5dcc81784fb040044232150f7f33756049edfc9026 \ - --hash=sha256:dbaf3c3c37ef190439981648ccbf0c02ed99ae066087dd117fcb616d80b010a4 \ - --hash=sha256:dca3582bca82596609959ac39e12b7dad98385b4fefccb1151b937383cec547d \ - --hash=sha256:e3174a5ed4171570dc8318afada56373aa9289eb6dc0d96cceb48e7358b0e220 \ - --hash=sha256:e43a55f378df1e7a4fa3547c88d9a5a9b7113f653a66821bcea4718fe6c58763 \ - --hash=sha256:e69d0deeb977ffe7ed3d2e4439360089f9c3f217ada608f0f88ebd67afb6385e \ - --hash=sha256:e85dc94595f4d766bd7d872a9de5ede1ca8d3063f3bdf1e2c725f5eb411159e3 \ - --hash=sha256:e90b8db97f6f2c97eb045b51a6b2c5ed69cedd8392459e0642d4199b94fabd7e \ - --hash=sha256:e9bf3f0bbdb56633c07d7116ae60a576f846efdd86a8848f8d62b749e1209ca7 \ - --hash=sha256:ea4e6b3566127fda5e007e90a8fd5a4169f0cf0619506ed426db647f19c8454a \ - --hash=sha256:ec94c04149b6a7b8120f9f44565722c7ae31b7a6d2275569d2eefa76b83da3be \ - --hash=sha256:eddf73f41225942c1f994914742afa53dc0d01a6e20fe14b878a1b1edc74151f \ - --hash=sha256:ee6854c9000a10938c79238de2379bea30c82e4925a371711af45387df35cab8 \ - --hash=sha256:ef71d476caa6692eea743ae5ea23cde3260677f70122c4d258ca952e5c2d4e84 \ - --hash=sha256:f052d1be37ef35a54e394de66136e30fa1191fab64f71fc06ac7bc98c9a84618 \ - --hash=sha256:f1862739a1ffb50615c0fde6bae6569b5efbe08d98e59ce009f68a336f64da75 \ - --hash=sha256:f192a831d9575271a22d804ff1a5355355723f94f31d9eef25f0d45a152fdc1a \ - --hash=sha256:f42e68301ff4afee63e365a5fc302b81bb8ba31af625a671d7acb19d10168a8c \ - --hash=sha256:f7792f27d3ee6e0244ea4697d92b825f9a329ab5230a78c1a68bd274e64b5077 \ - --hash=sha256:f82110ab962a541737bd0ce87978d4c658f06e7591ba899192e2712a517badbb \ - --hash=sha256:f9ca1cbdc0fbfe5e6e6f8221ef2309988db5bcede52443aeaee9a4ad555e0dac \ - --hash=sha256:fd65af65e2aaf9474e468f9e571bd7b189e1df3a61caa59dcbabd0000e4ea839 \ - --hash=sha256:fe2fda4110a3d0bc163c2e0664be44657431440722c5c5315c65155cab92f9e5 \ - --hash=sha256:febd38857b09867d3ed3f4f1af7d241c5c50362e25ef43034995b77a50df494e +regex==2026.3.32 \ + --hash=sha256:03c2ebd15ff51e7b13bb3dc28dd5ac18cd39e59ebb40430b14ae1a19e833cff1 \ + --hash=sha256:09e26cad1544d856da85881ad292797289e4406338afe98163f3db9f7fac816c \ + --hash=sha256:0cec365d44835b043d7b3266487797639d07d621bec9dc0ea224b00775797cc1 \ + --hash=sha256:0d7855f5e59fcf91d0c9f4a51dc5d8847813832a2230c3e8e35912ccf20baaa2 \ + --hash=sha256:0f21ae18dfd15752cdd98d03cbd7a3640be826bfd58482a93f730dbd24d7b9fb \ + --hash=sha256:10fb2aaae1aaadf7d43c9f3c2450404253697bf8b9ce360bd5418d1d16292298 \ + --hash=sha256:110ba4920721374d16c4c8ea7ce27b09546d43e16aea1d7f43681b5b8f80ba61 \ + --hash=sha256:12917c6c6813ffcdfb11680a04e4d63c5532b88cf089f844721c5f41f41a63ad \ + --hash=sha256:18eb45f711e942c27dbed4109830bd070d8d618e008d0db39705f3f57070a4c6 \ + --hash=sha256:1a6ac1ed758902e664e0d95c1ee5991aa6fb355423f378ed184c6ec47a1ec0e9 \ + --hash=sha256:1ca02ff0ef33e9d8276a1fcd6d90ff6ea055a32c9149c0050b5b67e26c6d2c51 \ + --hash=sha256:1cb22fa9ee6a0acb22fc9aecce5f9995fe4d2426ed849357d499d62608fbd7f9 \ + --hash=sha256:1e0f6648fd48f4c73d801c55ab976cd602e2da87de99c07bff005b131f269c6a \ + --hash=sha256:245667ad430745bae6a1e41081872d25819d86fbd9e0eec485ba00d9f78ad43d \ + --hash=sha256:2820d2231885e97aff0fcf230a19ebd5d2b5b8a1ba338c20deb34f16db1c7897 \ + --hash=sha256:2c8d402ea3dfe674288fe3962016affd33b5b27213d2b5db1823ffa4de524c57 \ + --hash=sha256:2dcca2bceb823c9cc610e57b86a265d7ffc30e9fe98548c609eba8bd3c0c2488 \ + --hash=sha256:2ffbadc647325dd4e3118269bda93ded1eb5f5b0c3b7ba79a3da9fbd04f248e9 \ + --hash=sha256:34c905a721ddee0f84c99e3e3b59dd4a5564a6fe338222bc89dd4d4df166115c \ + --hash=sha256:3c054e39a9f85a3d76c62a1d50c626c5e9306964eaa675c53f61ff7ec1204bbb \ + --hash=sha256:3c0bbfbd38506e1ea96a85da6782577f06239cb9fcf9696f1ea537c980c0680b \ + --hash=sha256:3e221b615f83b15887636fcb90ed21f1a19541366f8b7ba14ba1ad8304f4ded4 \ + --hash=sha256:3ea568832eca219c2be1721afa073c1c9eb8f98a9733fdedd0a9747639fc22a5 \ + --hash=sha256:3f5747501b69299c6b0b047853771e4ed390510bada68cb16da9c9c2078343f7 \ + --hash=sha256:462a041d2160090553572f6bb0be417ab9bb912a08de54cb692829c871ee88c1 \ + --hash=sha256:4bc32b4dbdb4f9f300cf9f38f8ea2ce9511a068ffaa45ac1373ee7a943f1d810 \ + --hash=sha256:4d082be64e51671dd5ee1c208c92da2ddda0f2f20d8ef387e57634f7e97b6aae \ + --hash=sha256:4f9ae4755fa90f1dc2d0d393d572ebc134c0fe30fcfc0ab7e67c1db15f192041 \ + --hash=sha256:51a93452034d671b0e21b883d48ea66c5d6a05620ee16a9d3f229e828568f3f0 \ + --hash=sha256:51fb7e26f91f9091fd8ec6a946f99b15d3bc3667cb5ddc73dd6cb2222dd4a1cc \ + --hash=sha256:5336b1506142eb0f23c96fb4a34b37c4fefd4fed2a7042069f3c8058efe17855 \ + --hash=sha256:567b57eb987547a23306444e4f6f85d4314f83e65c71d320d898aa7550550443 \ + --hash=sha256:5aa78c857c1731bdd9863923ffadc816d823edf475c7db6d230c28b53b7bdb5e \ + --hash=sha256:5bf2f3c2c5bd8360d335c7dcd4a9006cf1dabae063ee2558ee1b07bbc8a20d88 \ + --hash=sha256:5c35d097f509cf7e40d20d5bee548d35d6049b36eb9965e8d43e4659923405b9 \ + --hash=sha256:5d86e3fb08c94f084a625c8dc2132a79a3a111c8bf6e2bc59351fa61753c2f6e \ + --hash=sha256:6062c4ef581a3e9e503dccf4e1b7f2d33fdc1c13ad510b287741ac73bc4c6b27 \ + --hash=sha256:6128dd0793a87287ea1d8bf16b4250dd96316c464ee15953d5b98875a284d41e \ + --hash=sha256:631f7d95c83f42bccfe18946a38ad27ff6b6717fb4807e60cf24860b5eb277fc \ + --hash=sha256:66a5083c3ffe5a5a95f8281ea47a88072d4f24001d562d1d9d28d4cdc005fec5 \ + --hash=sha256:66d3126afe7eac41759cd5f0b3b246598086e88e70527c0d68c9e615b81771c4 \ + --hash=sha256:67015a8162d413af9e3309d9a24e385816666fbf09e48e3ec43342c8536f7df6 \ + --hash=sha256:6980ceb5c1049d4878632f08ba0bf7234c30e741b0dc9081da0f86eca13189d3 \ + --hash=sha256:69a847a6ffaa86e8af7b9e7037606e05a6f663deec516ad851e8e05d9908d16a \ + --hash=sha256:6ada7bd5bb6511d12177a7b00416ce55caee49fbf8c268f26b909497b534cacb \ + --hash=sha256:70c634e39c5cda0da05c93d6747fdc957599f7743543662b6dbabdd8d3ba8a96 \ + --hash=sha256:7cdd508664430dd51b8888deb6c5b416d8de046b2e11837254378d31febe4a98 \ + --hash=sha256:844d88509c968dd44b30daeefac72b038b1bf31ac372d5106358ab01d393c48b \ + --hash=sha256:847087abe98b3c1ebf1eb49d6ef320dbba75a83ee4f83c94704580f1df007dd4 \ + --hash=sha256:85c9b0c131427470a6423baa0a9330be6fd8c3630cc3ee6fdee03360724cbec5 \ + --hash=sha256:879ae91f2928a13f01a55cfa168acedd2b02b11b4cd8b5bb9223e8cde777ca52 \ + --hash=sha256:887a9fa74418d74d645281ee0edcf60694053bd1bc2ebc49eb5e66bfffc6d107 \ + --hash=sha256:88ebc0783907468f17fca3d7821b30f9c21865a721144eb498cb0ff99a67bcac \ + --hash=sha256:89e50667e7e8c0e7903e4d644a2764fffe9a3a5d6578f72ab7a7b4205bf204b7 \ + --hash=sha256:8a4a3189a99ecdd1c13f42513ab3fc7fa8311b38ba7596dd98537acb8cd9acc3 \ + --hash=sha256:8aaf8ee8f34b677f90742ca089b9c83d64bdc410528767273c816a863ed57327 \ + --hash=sha256:8e4c8fa46aad1a11ae2f8fcd1c90b9d55e18925829ac0d98c5bb107f93351745 \ + --hash=sha256:8fc918cd003ba0d066bf0003deb05a259baaaab4dc9bd4f1207bbbe64224857a \ + --hash=sha256:8fe14e24124ef41220e5992a0f09432f890037df6f93fd3d6b7a0feff2db16b2 \ + --hash=sha256:918db4e34a7ef3d0beee913fa54b34231cc3424676f1c19bdb85f01828d3cd37 \ + --hash=sha256:987cdfcfb97a249abc3601ad53c7de5c370529f1981e4c8c46793e4a1e1bfe8e \ + --hash=sha256:9b9118a78e031a2e4709cd2fcc3028432e89b718db70073a8da574c249b5b249 \ + --hash=sha256:9cf7036dfa2370ccc8651521fcbb40391974841119e9982fa312b552929e6c85 \ + --hash=sha256:a094e9dcafedfb9d333db5cf880304946683f43a6582bb86688f123335122929 \ + --hash=sha256:a416ee898ecbc5d8b283223b4cf4d560f93244f6f7615c1bd67359744b00c166 \ + --hash=sha256:a5d88fa37ba5e8a80ca8d956b9ea03805cfa460223ac94b7d4854ee5e30f3173 \ + --hash=sha256:ace48c5e157c1e58b7de633c5e257285ce85e567ac500c833349c363b3df69d4 \ + --hash=sha256:ad5c53f2e8fcae9144009435ebe3d9832003508cf8935c04542a1b3b8deefa15 \ + --hash=sha256:ad8d372587e659940568afd009afeb72be939c769c552c9b28773d0337251391 \ + --hash=sha256:b193ed199848aa96618cd5959c1582a0bf23cd698b0b900cb0ffe81b02c8659c \ + --hash=sha256:b2e9c2ea2e93223579308263f359eab8837dc340530b860cb59b713651889f14 \ + --hash=sha256:b3aa21bad31db904e0b9055e12c8282df62d43169c4a9d2929407060066ebc74 \ + --hash=sha256:b565f25171e04d4fad950d1fa837133e3af6ea6f509d96166eed745eb0cf63bc \ + --hash=sha256:b56993a7aeb4140c4770f4f7965c9e5af4f024457d06e23c01b0d47501cb18ed \ + --hash=sha256:b6acb765e7c1f2fa08ac9057a33595e26104d7d67046becae184a8f100932dd9 \ + --hash=sha256:b6f366a5ef66a2df4d9e68035cfe9f0eb8473cdfb922c37fac1d169b468607b0 \ + --hash=sha256:b7836aa13721dbdef658aebd11f60d00de633a95726521860fe1f6be75fa225a \ + --hash=sha256:b8fca73e16c49dd972ce3a88278dfa5b93bf91ddef332a46e9443abe21ca2f7c \ + --hash=sha256:b953d9d496d19786f4d46e6ba4b386c6e493e81e40f9c5392332458183b0599d \ + --hash=sha256:bbc458a292aee57d572075f22c035fa32969cdb7987d454e3e34d45a40a0a8b4 \ + --hash=sha256:c1cecea3e477af105f32ef2119b8d895f297492e41d317e60d474bc4bffd62ff \ + --hash=sha256:c1d7fa44aece1fa02b8927441614c96520253a5cad6a96994e3a81e060feed55 \ + --hash=sha256:c1ed17104d1be7f807fdec35ec99777168dd793a09510d753f8710590ba54cdd \ + --hash=sha256:c3c6f6b027d10f84bfe65049028892b5740878edd9eae5fea0d1710b09b1d257 \ + --hash=sha256:c5e0fdb5744caf1036dec5510f543164f2144cb64932251f6dfd42fa872b7f9c \ + --hash=sha256:c60f1de066eb5a0fd8ee5974de4194bb1c2e7692941458807162ffbc39887303 \ + --hash=sha256:c6d9c6e783b348f719b6118bb3f187b2e138e3112576c9679eb458cc8b2e164b \ + --hash=sha256:c940e00e8d3d10932c929d4b8657c2ea47d2560f31874c3e174c0d3488e8b865 \ + --hash=sha256:c9f261ad3cd97257dc1d9355bfbaa7dd703e06574bffa0fa8fe1e31da915ee38 \ + --hash=sha256:d21a07edddb3e0ca12a8b8712abc8452481c3d3db19ae87fc94e9842d005964b \ + --hash=sha256:d363660f9ef8c734495598d2f3e527fb41f745c73159dc0d743402f049fb6836 \ + --hash=sha256:d478a2ca902b6ef28ffc9521e5f0f728d036abe35c0b250ee8ae78cfe7c5e44e \ + --hash=sha256:d571f0b2eec3513734ea31a16ce0f7840c0b85a98e7edfa0e328ed144f9ef78f \ + --hash=sha256:d6b39a2cc5625bbc4fda18919a891eab9aab934eecf83660a90ce20c53621a9a \ + --hash=sha256:d76d62909bfb14521c3f7cfd5b94c0c75ec94b0a11f647d2f604998962ec7b6c \ + --hash=sha256:dab4178a0bc1ef13178832b12db7bc7f562e8f028b2b5be186e370090dc50652 \ + --hash=sha256:db976be51375bca900e008941639448d148c655c9545071965d0571ecc04f5d0 \ + --hash=sha256:ded4fc0edf3de792850cb8b04bbf3c5bd725eeaf9df4c27aad510f6eed9c4e19 \ + --hash=sha256:e006ea703d5c0f3d112b51ba18af73b58209b954acfe3d8da42eacc9a00e4be6 \ + --hash=sha256:e3e5d1802cba785210a4a800e63fcee7a228649a880f3bf7f2aadccb151a834b \ + --hash=sha256:e480d3dac06c89bc2e0fd87524cc38c546ac8b4a38177650745e64acbbcfdeba \ + --hash=sha256:e50af656c15e2723eeb7279c0837e07accc594b95ec18b86821a4d44b51b24bf \ + --hash=sha256:e83ce8008b48762be296f1401f19afd9ea29f3d035d1974e0cecb74e9afbd1df \ + --hash=sha256:ed3b8281c5d0944d939c82db4ec2300409dd69ee087f7a75a94f2e301e855fb4 \ + --hash=sha256:ef250a3f5e93182193f5c927c5e9575b2cb14b80d03e258bc0b89cc5de076b60 \ + --hash=sha256:f1574566457161678297a116fa5d1556c5a4159d64c5ff7c760e7c564bf66f16 \ + --hash=sha256:f26262900edd16272b6360014495e8d68379c6c6e95983f9b7b322dc928a1194 \ + --hash=sha256:f28eac18a8733a124444643a66ac96fef2c0ad65f50034e0a043b90333dc677f \ + --hash=sha256:f54840bea73541652f1170dc63402a5b776fc851ad36a842da9e5163c1f504a0 \ + --hash=sha256:f785f44a44702dea89b28bce5bc82552490694ce4e144e21a4f0545e364d2150 \ + --hash=sha256:f7cc00089b4c21847852c0ad76fb3680f9833b855a0d30bcec94211c435bff6b \ + --hash=sha256:f95bd07f301135771559101c060f558e2cf896c7df00bec050ca7f93bf11585a \ + --hash=sha256:fc8ced733d6cd9af5e412f256a32f7c61cd2d7371280a65c689939ac4572499f \ + --hash=sha256:fd03e38068faeef937cc6761a250a4aaa015564bd0d61481fefcf15586d31825 # via # feast (pyproject.toml) # parsimonious # transformers -requests==2.32.5 \ - --hash=sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6 \ - --hash=sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf +requests==2.33.1 \ + --hash=sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517 \ + --hash=sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a # via # feast (pyproject.toml) # azure-core @@ -4878,6 +4919,7 @@ requests==2.32.5 \ # great-expectations # huggingface-hub # jupyterlab-server + # kube-authkit # kubernetes # moto # msal @@ -4902,9 +4944,9 @@ requests-toolbelt==1.0.0 \ --hash=sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6 \ --hash=sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06 # via python-keycloak -responses==0.25.8 \ - --hash=sha256:0c710af92def29c8352ceadff0c3fe340ace27cf5af1bbe46fb71275bcd2831c \ - --hash=sha256:9374d047a575c8f781b94454db5cab590b6029505f488d12899ddb10a4af1cf4 +responses==0.26.0 \ + --hash=sha256:03ec4409088cd5c66b71ecbbbd27fe2c58ddfad801c66203457b3e6a04868c37 \ + --hash=sha256:c7f6923e6343ef3682816ba421c006626777893cb0d5e1434f674b649bac9eb4 # via moto rfc3339-validator==0.1.4 \ --hash=sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b \ @@ -4922,9 +4964,9 @@ rfc3987-syntax==1.1.0 \ --hash=sha256:6c3d97604e4c5ce9f714898e05401a0445a641cfa276432b0a648c80856f6a3f \ --hash=sha256:717a62cbf33cffdd16dfa3a497d81ce48a660ea691b1ddd7be710c22f00b4a0d # via jsonschema -rich==13.9.4 \ - --hash=sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098 \ - --hash=sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90 +rich==14.3.3 \ + --hash=sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d \ + --hash=sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b # via # codeflare-sdk # fastapi-mcp @@ -5049,10 +5091,6 @@ rpds-py==0.30.0 \ # via # jsonschema # referencing -rsa==4.9.1 \ - --hash=sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762 \ - --hash=sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75 - # via google-auth rtree==1.4.1 \ --hash=sha256:12de4578f1b3381a93a655846900be4e3d5f4cd5e306b8b00aa77c1121dc7e8c \ --hash=sha256:3d46f55729b28138e897ffef32f7ce93ac335cb67f9120125ad3742a220800f0 \ @@ -5070,25 +5108,25 @@ ruamel-yaml==0.17.17 \ --hash=sha256:9751de4cbb57d4bfbf8fc394e125ed4a2f170fbff3dc3d78abf50be85924f8be \ --hash=sha256:9af3ec5d7f8065582f3aa841305465025d0afd26c5fb54e15b964e11838fc74f # via great-expectations -ruff==0.15.1 \ - --hash=sha256:1d83466455fdefe60b8d9c8df81d3c1bbb2115cede53549d3b522ce2bc703899 \ - --hash=sha256:1fe5c41ab43e3a06778844c586251eb5a510f67125427625f9eb2b9526535779 \ - --hash=sha256:3dd86dccb83cd7d4dcfac303ffc277e6048600dfc22e38158afa208e8bf94a1f \ - --hash=sha256:4ab064052c31dddada35079901592dfba2e05f5b1e43af3954aafcbc1096a5b2 \ - --hash=sha256:518f9af03bfc33c03bdb4cb63fabc935341bb7f54af500f92ac309ecfbba6330 \ - --hash=sha256:5631c940fe9fe91f817a4c2ea4e81f47bee3ca4aa646134a24374f3c19ad9454 \ - --hash=sha256:5ff7d5f0f88567850f45081fac8f4ec212be8d0b963e385c3f7d0d2eb4899416 \ - --hash=sha256:660975d9cb49b5d5278b12b03bb9951d554543a90b74ed5d366b20e2c57c2098 \ - --hash=sha256:66a6dd6df4d80dc382c6484f8ce1bcceb55c32e9f27a8b94c32f6c7331bf14fb \ - --hash=sha256:68138a4ba184b4691ccdc39f7795c66b3c68160c586519e7e8444cf5a53e1b4c \ - --hash=sha256:6a4a42cbb8af0bda9bcd7606b064d7c0bc311a88d141d02f78920be6acb5aa83 \ - --hash=sha256:92c92b003e9d4f7fbd33b1867bb15a1b785b1735069108dfc23821ba045b29bc \ - --hash=sha256:939c995e9277e63ea632cc8d3fae17aa758526f49a9a850d2e7e758bfef46602 \ - --hash=sha256:a9457e3c3291024866222b96108ab2d8265b477e5b1534c7ddb1810904858d16 \ - --hash=sha256:b101ed7cf4615bda6ffe65bdb59f964e9f4a0d3f85cbf0e54f0ab76d7b90228a \ - --hash=sha256:c590fe13fb57c97141ae975c03a1aedb3d3156030cabd740d6ff0b0d601e203f \ - --hash=sha256:c820fef9dd5d4172a6570e5721704a96c6679b80cf7be41659ed439653f62336 \ - --hash=sha256:da79f4d6a826caaea95de0237a67e33b81e6ec2e25fc7e1993a4015dffca7c61 +ruff==0.15.9 \ + --hash=sha256:058d8e99e1bfe79d8a0def0b481c56059ee6716214f7e425d8e737e412d69677 \ + --hash=sha256:0694e601c028fd97dc5c6ee244675bc241aeefced7ef80cd9c6935a871078f53 \ + --hash=sha256:29cbb1255a9797903f6dde5ba0188c707907ff44a9006eb273b5a17bfa0739a2 \ + --hash=sha256:2b0c7c341f68adb01c488c3b7d4b49aa8ea97409eae6462d860a79cf55f431b6 \ + --hash=sha256:45a70921b80e1c10cf0b734ef09421f71b5aa11d27404edc89d7e8a69505e43d \ + --hash=sha256:4965bac6ac9ea86772f4e23587746f0b7a395eccabb823eb8bfacc3fa06069f7 \ + --hash=sha256:55cc15eee27dc0eebdfcb0d185a6153420efbedc15eb1d38fe5e685657b0f840 \ + --hash=sha256:6d3fcbca7388b066139c523bda744c822258ebdcfbba7d24410c3f454cc9af71 \ + --hash=sha256:6efbe303983441c51975c243e26dff328aca11f94b70992f35b093c2e71801e1 \ + --hash=sha256:7b34a9766aeec27a222373d0b055722900fbc0582b24f39661aa96f3fe6ad901 \ + --hash=sha256:89dd695bc72ae76ff484ae54b7e8b0f6b50f49046e198355e44ea656e521fef9 \ + --hash=sha256:8e1ddb11dbd61d5983fa2d7d6370ef3eb210951e443cace19594c01c72abab4c \ + --hash=sha256:9439a342adb8725f32f92732e2bafb6d5246bd7a5021101166b223d312e8fc59 \ + --hash=sha256:9c5e6faf9d97c8edc43877c3f406f47446fc48c40e1442d58cfcdaba2acea745 \ + --hash=sha256:a6537f6eed5cda688c81073d46ffdfb962a5f29ecb6f7e770b2dc920598997ed \ + --hash=sha256:bde6ff36eaf72b700f32b7196088970bf8fdb2b917b7accd8c371bfc0fd573ec \ + --hash=sha256:ce187224ef1de1bd225bc9a152ac7102a6171107f026e81f317e4257052916d5 \ + --hash=sha256:eaf05aad70ca5b5a0a4b0e080df3a6b699803916d88f006efd1f5b46302daab8 # via feast (pyproject.toml) s3transfer==0.13.1 \ --hash=sha256:a981aa7429be23fe6dfc13e80e4020057cbab622b08c0315288758d67cabc724 \ @@ -5212,83 +5250,90 @@ scikit-learn==1.8.0 \ --hash=sha256:f984ca4b14914e6b4094c5d52a32ea16b49832c03bd17a110f004db3c223e8e1 \ --hash=sha256:fb65db5d7531bccf3a4f6bec3462223bea71384e2cda41da0f10b7c292b9e7c4 \ --hash=sha256:fe1c011a640a9f0791146011dfd3c7d9669785f9fed2b2a5f9e207536cf5c2fd - # via feast (pyproject.toml) -scipy==1.17.0 \ - --hash=sha256:00fb5f8ec8398ad90215008d8b6009c9db9fa924fd4c7d6be307c6f945f9cd73 \ - --hash=sha256:031121914e295d9791319a1875444d55079885bbae5bdc9c5e0f2ee5f09d34ff \ - --hash=sha256:0937a0b0d8d593a198cededd4c439a0ea216a3f36653901ea1f3e4be949056f8 \ - --hash=sha256:0cf46c8013fec9d3694dc572f0b54100c28405d55d3e2cb15e2895b25057996e \ - --hash=sha256:0d5018a57c24cb1dd828bcf51d7b10e65986d549f52ef5adb6b4d1ded3e32a57 \ - --hash=sha256:130d12926ae34399d157de777472bf82e9061c60cc081372b3118edacafe1d00 \ - --hash=sha256:13c4096ac6bc31d706018f06a49abe0485f96499deb82066b94d19b02f664209 \ - --hash=sha256:13e861634a2c480bd237deb69333ac79ea1941b94568d4b0efa5db5e263d4fd1 \ - --hash=sha256:1f9586a58039d7229ce77b52f8472c972448cded5736eaf102d5658bbac4c269 \ - --hash=sha256:1ff269abf702f6c7e67a4b7aad981d42871a11b9dd83c58d2d2ea624efbd1088 \ - --hash=sha256:255c0da161bd7b32a6c898e7891509e8a9289f0b1c6c7d96142ee0d2b114c2ea \ - --hash=sha256:2591060c8e648d8b96439e111ac41fd8342fdeff1876be2e19dea3fe8930454e \ - --hash=sha256:272a9f16d6bb4667e8b50d25d71eddcc2158a214df1b566319298de0939d2ab7 \ - --hash=sha256:2abd71643797bd8a106dff97894ff7869eeeb0af0f7a5ce02e4227c6a2e9d6fd \ - --hash=sha256:2b531f57e09c946f56ad0b4a3b2abee778789097871fc541e267d2eca081cff1 \ - --hash=sha256:30509da9dbec1c2ed8f168b8d8aa853bc6723fede1dbc23c7d43a56f5ab72a67 \ - --hash=sha256:33af70d040e8af9d5e7a38b5ed3b772adddd281e3062ff23fec49e49681c38cf \ - --hash=sha256:357ca001c6e37601066092e7c89cca2f1ce74e2a520ca78d063a6d2201101df2 \ - --hash=sha256:3625c631a7acd7cfd929e4e31d2582cf00f42fcf06011f59281271746d77e061 \ - --hash=sha256:363ad4ae2853d88ebcde3ae6ec46ccca903ea9835ee8ba543f12f575e7b07e4e \ - --hash=sha256:40052543f7bbe921df4408f46003d6f01c6af109b9e2c8a66dd1cf6cf57f7d5d \ - --hash=sha256:423ca1f6584fc03936972b5f7c06961670dbba9f234e71676a7c7ccf938a0d61 \ - --hash=sha256:474da16199f6af66601a01546144922ce402cb17362e07d82f5a6cf8f963e449 \ - --hash=sha256:4e00562e519c09da34c31685f6acc3aa384d4d50604db0f245c14e1b4488bfa2 \ - --hash=sha256:5194c445d0a1c7a6c1a4a4681b6b7c71baad98ff66d96b949097e7513c9d6742 \ - --hash=sha256:5fb10d17e649e1446410895639f3385fd2bf4c3c7dfc9bea937bddcbc3d7b9ba \ - --hash=sha256:65ec32f3d32dfc48c72df4291345dae4f048749bc8d5203ee0a3f347f96c5ce6 \ - --hash=sha256:6680f2dfd4f6182e7d6db161344537da644d1cf85cf293f015c60a17ecf08752 \ - --hash=sha256:6e886000eb4919eae3a44f035e63f0fd8b651234117e8f6f29bad1cd26e7bc45 \ - --hash=sha256:7204fddcbec2fe6598f1c5fdf027e9f259106d05202a959a9f1aecf036adc9f6 \ - --hash=sha256:819fc26862b4b3c73a60d486dbb919202f3d6d98c87cf20c223511429f2d1a97 \ - --hash=sha256:8547e7c57f932e7354a2319fab613981cde910631979f74c9b542bb167a8b9db \ - --hash=sha256:85b0ac3ad17fa3be50abd7e69d583d98792d7edc08367e01445a1e2076005379 \ - --hash=sha256:87b411e42b425b84777718cc41516b8a7e0795abfa8e8e1d573bf0ef014f0812 \ - --hash=sha256:88c22af9e5d5a4f9e027e26772cc7b5922fab8bcc839edb3ae33de404feebd9e \ - --hash=sha256:9244608d27eafe02b20558523ba57f15c689357c85bdcfe920b1828750aa26eb \ - --hash=sha256:979c3a0ff8e5ba254d45d59ebd38cde48fce4f10b5125c680c7a4bfe177aab07 \ - --hash=sha256:9eeb9b5f5997f75507814ed9d298ab23f62cf79f5a3ef90031b1ee2506abdb5b \ - --hash=sha256:9fad7d3578c877d606b1150135c2639e9de9cecd3705caa37b66862977cc3e72 \ - --hash=sha256:a38c3337e00be6fd8a95b4ed66b5d988bac4ec888fd922c2ea9fe5fb1603dd67 \ - --hash=sha256:aabf057c632798832f071a8dde013c2e26284043934f53b00489f1773b33527e \ - --hash=sha256:c17514d11b78be8f7e6331b983a65a7f5ca1fd037b95e27b280921fe5606286a \ - --hash=sha256:c5e8647f60679790c2f5c76be17e2e9247dc6b98ad0d3b065861e082c56e078d \ - --hash=sha256:cacbaddd91fcffde703934897c5cd2c7cb0371fac195d383f4e1f1c5d3f3bd04 \ - --hash=sha256:d7425fcafbc09a03731e1bc05581f5fad988e48c6a861f441b7ab729a49a55ea \ - --hash=sha256:dac97a27520d66c12a34fd90a4fe65f43766c18c0d6e1c0a80f114d2260080e4 \ - --hash=sha256:dbf133ced83889583156566d2bdf7a07ff89228fe0c0cb727f777de92092ec6b \ - --hash=sha256:e8c0b331c2c1f531eb51f1b4fc9ba709521a712cce58f1aa627bc007421a5306 \ - --hash=sha256:eb2651271135154aa24f6481cbae5cc8af1f0dd46e6533fb7b56aa9727b6a232 \ - --hash=sha256:ebb7446a39b3ae0fe8f416a9a3fdc6fba3f11c634f680f16a239c5187bc487c0 \ - --hash=sha256:ec0827aa4d36cb79ff1b81de898e948a51ac0b9b1c43e4a372c0508c38c0f9a3 \ - --hash=sha256:edce1a1cf66298cccdc48a1bdf8fb10a3bf58e8b58d6c3883dd1530e103f87c0 \ - --hash=sha256:eec3842ec9ac9de5917899b277428886042a93db0b227ebbe3a333b64ec7643d \ - --hash=sha256:ef28d815f4d2686503e5f4f00edc387ae58dfd7a2f42e348bb53359538f01558 \ - --hash=sha256:f2a4942b0f5f7c23c7cd641a0ca1955e2ae83dedcff537e3a0259096635e186b \ - --hash=sha256:f3cd947f20fe17013d401b64e857c6b2da83cae567adbb75b9dcba865abc66d8 \ - --hash=sha256:f603d8a5518c7426414d1d8f82e253e454471de682ce5e39c29adb0df1efb86b \ - --hash=sha256:f7df7941d71314e60a481e02d5ebcb3f0185b8d799c70d03d8258f6c80f3d467 \ - --hash=sha256:f9eb55bb97d00f8b7ab95cb64f873eb0bf54d9446264d9f3609130381233483f \ - --hash=sha256:fc02c37a5639ee67d8fb646ffded6d793c06c5622d36b35cfa8fe5ececb8f042 \ - --hash=sha256:fe508b5690e9eaaa9467fc047f833af58f1152ae51a0d0aed67aa5801f4dd7d6 + # via + # feast (pyproject.toml) + # sentence-transformers +scipy==1.17.1 \ + --hash=sha256:010f4333c96c9bb1a4516269e33cb5917b08ef2166d5556ca2fd9f082a9e6ea0 \ + --hash=sha256:02ae3b274fde71c5e92ac4d54bc06c42d80e399fec704383dcd99b301df37458 \ + --hash=sha256:08b900519463543aa604a06bec02461558a6e1cef8fdbb8098f77a48a83c8118 \ + --hash=sha256:131f5aaea57602008f9822e2115029b55d4b5f7c070287699fe45c661d051e39 \ + --hash=sha256:158dd96d2207e21c966063e1635b1063cd7787b627b6f07305315dd73d9c679e \ + --hash=sha256:1cc682cea2ae55524432f3cdff9e9a3be743d52a7443d0cba9017c23c87ae2f6 \ + --hash=sha256:1f95b894f13729334fb990162e911c9e5dc1ab390c58aa6cbecb389c5b5e28ec \ + --hash=sha256:200e1050faffacc162be6a486a984a0497866ec54149a01270adc8a59b7c7d21 \ + --hash=sha256:2040ad4d1795a0ae89bfc7e8429677f365d45aa9fd5e4587cf1ea737f927b4a1 \ + --hash=sha256:2b64ca7d4aee0102a97f3ba22124052b4bd2152522355073580bf4845e2550b6 \ + --hash=sha256:2ceb2d3e01c5f1d83c4189737a42d9cb2fc38a6eeed225e7515eef71ad301dce \ + --hash=sha256:35c3a56d2ef83efc372eaec584314bd0ef2e2f0d2adb21c55e6ad5b344c0dcb8 \ + --hash=sha256:37425bc9175607b0268f493d79a292c39f9d001a357bebb6b88fdfaff13f6448 \ + --hash=sha256:3877ac408e14da24a6196de0ddcace62092bfc12a83823e92e49e40747e52c19 \ + --hash=sha256:3fd1fcdab3ea951b610dc4cef356d416d5802991e7e32b5254828d342f7b7e0b \ + --hash=sha256:41b71f4a3a4cab9d366cd9065b288efc4d4f3c0b37a91a8e0947fb5bd7f31d87 \ + --hash=sha256:43af8d1f3bea642559019edfe64e9b11192a8978efbd1539d7bc2aaa23d92de4 \ + --hash=sha256:45abad819184f07240d8a696117a7aacd39787af9e0b719d00285549ed19a1e9 \ + --hash=sha256:4b400bdc6f79fa02a4d86640310dde87a21fba0c979efff5248908c6f15fad1b \ + --hash=sha256:4eb6c25dd62ee8d5edf68a8e1c171dd71c292fdae95d8aeb3dd7d7de4c364082 \ + --hash=sha256:581b2264fc0aa555f3f435a5944da7504ea3a065d7029ad60e7c3d1ae09c5464 \ + --hash=sha256:5cf36e801231b6a2059bf354720274b7558746f3b1a4efb43fcf557ccd484a87 \ + --hash=sha256:5e3c5c011904115f88a39308379c17f91546f77c1667cea98739fe0fccea804c \ + --hash=sha256:6609bc224e9568f65064cfa72edc0f24ee6655b47575954ec6339534b2798369 \ + --hash=sha256:6e3dcd57ab780c741fde8dc68619de988b966db759a3c3152e8e9142c26295ad \ + --hash=sha256:6fac755ca3d2c3edcb22f479fceaa241704111414831ddd3bc6056e18516892f \ + --hash=sha256:744b2bf3640d907b79f3fd7874efe432d1cf171ee721243e350f55234b4cec4c \ + --hash=sha256:74cbb80d93260fe2ffa334efa24cb8f2f0f622a9b9febf8b483c0b865bfb3475 \ + --hash=sha256:766e0dc5a616d026a3a1cffa379af959671729083882f50307e18175797b3dfd \ + --hash=sha256:7bdf2da170b67fdf10bca777614b1c7d96ae3ca5794fd9587dce41eb2966e866 \ + --hash=sha256:7ff200bf9d24f2e4d5dc6ee8c3ac64d739d3a89e2326ba68aaf6c4a2b838fd7d \ + --hash=sha256:844e165636711ef41f80b4103ed234181646b98a53c8f05da12ca5ca289134f6 \ + --hash=sha256:8a604bae87c6195d8b1045eddece0514d041604b14f2727bbc2b3020172045eb \ + --hash=sha256:94055a11dfebe37c656e70317e1996dc197e1a15bbcc351bcdd4610e128fe1ca \ + --hash=sha256:95d8e012d8cb8816c226aef832200b1d45109ed4464303e997c5b13122b297c0 \ + --hash=sha256:9cdc1a2fcfd5c52cfb3045feb399f7b3ce822abdde3a193a6b9a60b3cb5854ca \ + --hash=sha256:9ecb4efb1cd6e8c4afea0daa91a87fbddbce1b99d2895d151596716c0b2e859d \ + --hash=sha256:a3472cfbca0a54177d0faa68f697d8ba4c80bbdc19908c3465556d9f7efce9ee \ + --hash=sha256:a4328d245944d09fd639771de275701ccadf5f781ba0ff092ad141e017eccda4 \ + --hash=sha256:a48a72c77a310327f6a3a920092fa2b8fd03d7deaa60f093038f22d98e096717 \ + --hash=sha256:a720477885a9d2411f94a93d16f9d89bad0f28ca23c3f8daa521e2dcc3f44d49 \ + --hash=sha256:a77cbd07b940d326d39a1d1b37817e2ee4d79cb30e7338f3d0cddffae70fcaa2 \ + --hash=sha256:a9956e4d4f4a301ebf6cde39850333a6b6110799d470dbbb1e25326ac447f52a \ + --hash=sha256:adb2642e060a6549c343603a3851ba76ef0b74cc8c079a9a58121c7ec9fe2350 \ + --hash=sha256:beeda3d4ae615106d7094f7e7cef6218392e4465cc95d25f900bebabfded0950 \ + --hash=sha256:c80be5ede8f3f8eded4eff73cc99a25c388ce98e555b17d31da05287015ffa5b \ + --hash=sha256:cc90d2e9c7e5c7f1a482c9875007c095c3194b1cfedca3c2f3291cdc2bc7c086 \ + --hash=sha256:cd96a1898c0a47be4520327e01f874acfd61fb48a9420f8aa9f6483412ffa444 \ + --hash=sha256:d2650c1fb97e184d12d8ba010493ee7b322864f7d3d00d3f9bb97d9c21de4068 \ + --hash=sha256:d30e57c72013c2a4fe441c2fcb8e77b14e152ad48b5464858e07e2ad9fbfceff \ + --hash=sha256:d59c30000a16d8edc7e64152e30220bfbd724c9bbb08368c054e24c651314f0a \ + --hash=sha256:dbc12c9f3d185f5c737d801da555fb74b3dcfa1a50b66a1a93e09190f41fab50 \ + --hash=sha256:e18f12c6b0bc5a592ed23d3f7b891f68fd7f8241d69b7883769eb5d5dfb52696 \ + --hash=sha256:e19ebea31758fac5893a2ac360fedd00116cbb7628e650842a6691ba7ca28a21 \ + --hash=sha256:e30bdeaa5deed6bc27b4cc490823cd0347d7dae09119b8803ae576ea0ce52e4c \ + --hash=sha256:eb092099205ef62cd1782b006658db09e2fed75bffcae7cc0d44052d8aa0f484 \ + --hash=sha256:eee2cfda04c00a857206a4330f0c5e3e56535494e30ca445eb19ec624ae75118 \ + --hash=sha256:f4115102802df98b2b0db3cce5cb9b92572633a1197c77b7553e5203f284a5b3 \ + --hash=sha256:f590cd684941912d10becc07325a3eeb77886fe981415660d9265c4c418d0bea \ + --hash=sha256:f8885db0bc2bffa59d5c1b72fad7a6a92d3e80e7257f967dd81abb553a90d293 \ + --hash=sha256:fcb310ddb270a06114bb64bbe53c94926b943f5b7f0842194d585c65eb4edd76 # via # docling # easyocr # great-expectations # scikit-image # scikit-learn -semchunk==2.2.2 \ - --hash=sha256:940e89896e64eeb01de97ba60f51c8c7b96c6a3951dfcf574f25ce2146752f52 \ - --hash=sha256:94ca19020c013c073abdfd06d79a7c13637b91738335f3b8cdb5655ee7cc94d2 + # sentence-transformers +semchunk==3.2.5 \ + --hash=sha256:ee15e9a06a69a411937dd8fcf0a25d7ef389c5195863140436872a02c95b0218 \ + --hash=sha256:fd09cc5f380bd010b8ca773bd81893f7eaf11d37dd8362a83d46cedaf5dae076 # via docling-core send2trash==2.1.0 \ --hash=sha256:0da2f112e6d6bb22de6aa6daa7e144831a4febf2a87261451c4ad849fe9a873c \ --hash=sha256:1c72b39f09457db3c05ce1d19158c2cbef4c32b8bedd02c155e49282b7ea7459 # via jupyter-server +sentence-transformers==5.3.0 \ + --hash=sha256:414a0a881f53a4df0e6cbace75f823bfcb6b94d674c42a384b498959b7c065e2 \ + --hash=sha256:dca6b98db790274a68185d27a65801b58b4caf653a4e556b5f62827509347c7d + # via feast (pyproject.toml) setuptools==80.10.2 \ --hash=sha256:8b0e9d10c784bf7d262c4e5ec5d4ec94127ce206e8738f29a437945fbc219b70 \ --hash=sha256:95b30ddfb717250edb492926c92b5221f7ef3fbcc2b07579bcd4a27da21d0173 @@ -5387,9 +5432,9 @@ six==1.17.0 \ # python-dateutil # rfc3339-validator # thriftpy2 -smart-open==7.5.0 \ - --hash=sha256:87e695c5148bbb988f15cec00971602765874163be85acb1c9fb8abc012e6599 \ - --hash=sha256:f394b143851d8091011832ac8113ea4aba6b92e6c35f6e677ddaaccb169d7cb9 +smart-open==7.5.1 \ + --hash=sha256:3e07cbbd9c8a908bcb8e25d48becf1a5cbb4886fa975e9f34c672ed171df2318 \ + --hash=sha256:3f08e16827c4733699e6b2cc40328a3568f900cb12ad9a3ad233ba6c872d9fe7 # via ray sniffio==1.3.1 \ --hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \ @@ -5402,33 +5447,32 @@ snowballstemmer==3.0.1 \ --hash=sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064 \ --hash=sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895 # via sphinx -snowflake-connector-python[pandas]==4.0.0 \ - --hash=sha256:0c0204f639fddc58452b0362ba8821cd5153bd7aaa89434d59104bc39f4fa176 \ - --hash=sha256:1ca2503f705627f7e045da6254d97c37210a3b0a18b43d0f1b29616d0c7aaa01 \ - --hash=sha256:1fea301e3d1e8022b9f2ff87dc3be139d5ed7be5e85fab8a6c59d400a02e6d58 \ - --hash=sha256:2c3e0f6d103fe67c975550ed424f579d3e7ae503d56467e5549f3a1a1e0e8f24 \ - --hash=sha256:4106a66e770e564b3037457b7b01b15ca28aee61afb88560b664aa8af439b533 \ - --hash=sha256:4b10a865c4a5e1fa60c365c7fe41e0433605e6e5edc824e8730a9038f330b3a6 \ - --hash=sha256:4e8c3d2ea4055dd4aecc93514030341e300f557f2e86ca21eb47568c461a6f56 \ - --hash=sha256:54e648bbd506a0f2f8076f9eafe231b2d4284b1a884528c3a0690391ab2bb54e \ - --hash=sha256:5ad5d0f1ebcb2c6b7a7859ee3d4e02203087e40faae539a336bbcb45a3660777 \ - --hash=sha256:65e4e36dd1b0c7235d84cddef8a3c97c5ea0dc8fea85e31e45fc485000b77a83 \ - --hash=sha256:7789df78f7c7abfb351f2709258d05a94652cfe3c2c617fb15f15a11fc1b7b25 \ - --hash=sha256:79b4e7a58e600419f083a63f99e5da89d438faddae1d344e9f9b003754fa231b \ - --hash=sha256:835161dd46ef8f5fc9d2f135ca654c2f3fbdf57b035d3e1980506aa8eac671dc \ - --hash=sha256:985cd2f8b6b2e663ef30dc59f1ba8c1becff7683ebc51bd7f14b962407a9fa88 \ - --hash=sha256:a790f06808e4481c23cfed1396d2c9a786060ddd62408b1fda1a63e1e6bc4b07 \ - --hash=sha256:af89a9e1355ea4dac7927d2f9bc15b2c81e381ad8bcdf8954ba3dd457a4d51d6 \ - --hash=sha256:b95b29589293ad14d0367428518141995524cfc7dc47d8f3d0c47010f5d974da \ - --hash=sha256:bfd3b8523d7adc830f99c5c4c635689ceca61700a05368d5bbb34c6811f2ec54 \ - --hash=sha256:cd23bff2abc74e34c6123a181c004ead9e6cc8ef2661250892afd64bad24533c \ - --hash=sha256:e376bad497c7932448cc29058e75737f02b3f0e25569de9e4ff0616944b4ceba \ - --hash=sha256:e6132986d6965e4005b0167270612fbc7fa4bc4ef42726a40b85a8f57475a78d \ - --hash=sha256:e8d5b66f283967c700fff2303ac5e52d1a3cf41990a634f121ac8b1f1cd9af10 \ - --hash=sha256:eb1bb9729fd3bfaae22364491cec4816dda380376ac3be4559a6f6949c6d2833 \ - --hash=sha256:ebbdeec0d65c2e3f648c8b05839001c062984959417902717f7fc6eed983211d \ - --hash=sha256:f67d844241a6fed764a8f04d32c0273aedf9159d5162b764748526277c7f8831 \ - --hash=sha256:fd0d2d2c5cfd15f041e8522f5f8bdad0be4de7d805dd1646377fccd6bd404fa8 +snowflake-connector-python[pandas]==4.4.0 \ + --hash=sha256:16fdca775f7ca5ce4a973c07c434f5ab72bef5284e81a5e4ae2fb4d54d28965c \ + --hash=sha256:19d0c1ed033abae715a71b74c53010b180a5247c6924f851e4f7d0b0d58066c4 \ + --hash=sha256:2a6f6a514a10c3bb2d4554132f0b639f43d7e9fbb73fa1fae1c8a75333102686 \ + --hash=sha256:307f41326c702f6976746d2001dacf35adaf567f3f12afb3a5778fbb063c7241 \ + --hash=sha256:43e1a2f3ac51d24406d4eb0c23a8ceb9d6f5cb4854c941e5e1375d8c481e2844 \ + --hash=sha256:52efe2d6543a09807283748dd50a36ec01d52b4f342868132f8f9856b9c95a42 \ + --hash=sha256:56ff04dd9e17edc82128f412aa3776687dc94088f3d6b9144971e169952623cb \ + --hash=sha256:648f49029d699591af0f253e81c5bf60efc4411c7b0149ef074a59a038210a3b \ + --hash=sha256:693a1bef97509f09b7e6f42ea6f743d27819413c04fb3dc543b060d029871c56 \ + --hash=sha256:70d4051e2d9c87258b02672e17e21f5873e0cb49ff9705f6194ccfa25ac0d5fd \ + --hash=sha256:7c2984663a733d06c979aa6c8c1d7691621ec0d3521ef345d57c869ff2f1c4b2 \ + --hash=sha256:8304b4818d3e9de552dcfbdd0bca61bae1583e1c9794e242e58fe44bce701604 \ + --hash=sha256:85a01338d282423611f357cd5392dca2219bbda9a66b44761b11d6ae8ebf1e50 \ + --hash=sha256:96fdca994c4d9f7780e82fc7b4bd3398d856b43de3bae57d44e242ff435a2431 \ + --hash=sha256:9b1a28f843c1c0b582db7854789525d0c8aac4ea5c56e31113684e38220d0af9 \ + --hash=sha256:9fa43d330389df27024757c4f97dabddafbedc74b8bcc189b6a86e8b4d036014 \ + --hash=sha256:a088f108da4653ad1396ddb63a1c757ad614d0862c38f6f69cc77344bdcfeccb \ + --hash=sha256:b9f0ac0c00075321e1720d3876e936ee0256f54832e7463c5193a8dfa54913d5 \ + --hash=sha256:c828248214a49f77b903e05acf887d3ccb9d958b5a979f2ed3663bba1bd0f2b3 \ + --hash=sha256:d6fd334e4d8df7fcb30e6746e5ade845e82de2942268862aa8bce974ae2b86a2 \ + --hash=sha256:d8ac1659c8e588b9502f8d3d03c1ded2f274de0da9c09e62fe007cba5b46d6a5 \ + --hash=sha256:e8e7ce0e8b33aec8b1fc6741eb51dbeb54e2c3a6d282a0d459c355a85f089b08 \ + --hash=sha256:ea6e4083ebea0a814b46f029d64a2fb0ba6e7732952cd8af4406041708ce0e21 \ + --hash=sha256:f5d0e90e68a899c13fda5ca842ff77b5759b1674adf2c72702d3c2b53ca9d27b \ + --hash=sha256:fb628d5ea1999e23bfbaabce4125eb44d56605ca5634b8b1d6092ab22d555598 # via feast (pyproject.toml) sortedcontainers==2.4.0 \ --hash=sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88 \ @@ -5466,135 +5510,107 @@ sphinxcontrib-serializinghtml==2.0.0 \ --hash=sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331 \ --hash=sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d # via sphinx -sqlalchemy[mypy]==2.0.46 \ - --hash=sha256:09168817d6c19954d3b7655da6ba87fcb3a62bb575fb396a81a8b6a9fadfe8b5 \ - --hash=sha256:0cc3117db526cad3e61074100bd2867b533e2c7dc1569e95c14089735d6fb4fe \ - --hash=sha256:181903fe8c1b9082995325f1b2e84ac078b1189e2819380c2303a5f90e114a62 \ - --hash=sha256:1bc3f601f0a818d27bfe139f6766487d9c88502062a2cd3a7ee6c342e81d5047 \ - --hash=sha256:1e6199143d51e3e1168bedd98cc698397404a8f7508831b81b6a29b18b051069 \ - --hash=sha256:2347c3f0efc4de367ba00218e0ae5c4ba2306e47216ef80d6e31761ac97cb0b9 \ - --hash=sha256:261c4b1f101b4a411154f1da2b76497d73abbfc42740029205d4d01fa1052684 \ - --hash=sha256:33e462154edb9493f6c3ad2125931e273bbd0be8ae53f3ecd1c161ea9a1dd366 \ - --hash=sha256:37fee2164cf21417478b6a906adc1a91d69ae9aba8f9533e67ce882f4bb1de53 \ - --hash=sha256:3a9a72b0da8387f15d5810f1facca8f879de9b85af8c645138cba61ea147968c \ - --hash=sha256:3aac08f7546179889c62b53b18ebf1148b10244b3405569c93984b0388d016a7 \ - --hash=sha256:3c32e993bc57be6d177f7d5d31edb93f30726d798ad86ff9066d75d9bf2e0b6b \ - --hash=sha256:412f26bb4ba942d52016edc8d12fb15d91d3cd46b0047ba46e424213ad407bcb \ - --hash=sha256:42a1643dc5427b69aca967dae540a90b0fbf57eaf248f13a90ea5930e0966863 \ - --hash=sha256:4396c948d8217e83e2c202fbdcc0389cf8c93d2c1c5e60fa5c5a955eae0e64be \ - --hash=sha256:4dafb537740eef640c4d6a7c254611dca2df87eaf6d14d6a5fca9d1f4c3fc0fa \ - --hash=sha256:4f52f7291a92381e9b4de9050b0a65ce5d6a763333406861e33906b8aa4906bf \ - --hash=sha256:52fe29b3817bd191cc20bad564237c808967972c97fa683c04b28ec8979ae36f \ - --hash=sha256:56bdd261bfd0895452006d5316cbf35739c53b9bb71a170a331fa0ea560b2ada \ - --hash=sha256:585af6afe518732d9ccd3aea33af2edaae4a7aa881af5d8f6f4fe3a368699597 \ - --hash=sha256:590be24e20e2424a4c3c1b0835e9405fa3d0af5823a1a9fc02e5dff56471515f \ - --hash=sha256:64901e08c33462acc9ec3bad27fc7a5c2b6491665f2aa57564e57a4f5d7c52ad \ - --hash=sha256:6ac245604295b521de49b465bab845e3afe6916bcb2147e5929c8041b4ec0545 \ - --hash=sha256:6f827fd687fa1ba7f51699e1132129eac8db8003695513fcf13fc587e1bd47a5 \ - --hash=sha256:70ed2830b169a9960193f4d4322d22be5c0925357d82cbf485b3369893350908 \ - --hash=sha256:716be5bcabf327b6d5d265dbdc6213a01199be587224eb991ad0d37e83d728fd \ - --hash=sha256:7568fe771f974abadce52669ef3a03150ff03186d8eb82613bc8adc435a03f01 \ - --hash=sha256:77f8071d8fbcbb2dd11b7fd40dedd04e8ebe2eb80497916efedba844298065ef \ - --hash=sha256:82ec52100ec1e6ec671563bbd02d7c7c8d0b9e71a0723c72f22ecf52d1755330 \ - --hash=sha256:895296687ad06dc9b11a024cf68e8d9d3943aa0b4964278d2553b86f1b267735 \ - --hash=sha256:8d3b44b3d0ab2f1319d71d9863d76eeb46766f8cf9e921ac293511804d39813f \ - --hash=sha256:8d679b5f318423eacb61f933a9a0f75535bfca7056daeadbf6bd5bcee6183aee \ - --hash=sha256:8e84b09a9b0f19accedcbeff5c2caf36e0dd537341a33aad8d680336152dc34e \ - --hash=sha256:9094c8b3197db12aa6f05c51c05daaad0a92b8c9af5388569847b03b1007fb1b \ - --hash=sha256:90bde6c6b1827565a95fde597da001212ab436f1b2e0c2dcc7246e14db26e2a3 \ - --hash=sha256:9397b381dcee8a2d6b99447ae85ea2530dcac82ca494d1db877087a13e38926d \ - --hash=sha256:93a12da97cca70cea10d4b4fc602589c4511f96c1f8f6c11817620c021d21d00 \ - --hash=sha256:93bb0aae40b52c57fd74ef9c6933c08c040ba98daf23ad33c3f9893494b8d3ce \ - --hash=sha256:94b1e5f3a5f1ff4f42d5daab047428cd45a3380e51e191360a35cef71c9a7a2a \ - --hash=sha256:965c62be8256d10c11f8907e7a8d3e18127a4c527a5919d85fa87fd9ecc2cfdc \ - --hash=sha256:96c7cca1a4babaaf3bfff3e4e606e38578856917e52f0384635a95b226c87764 \ - --hash=sha256:9bcdce05f056622a632f1d44bb47dbdb677f58cad393612280406ce37530eb6d \ - --hash=sha256:9d80ea2ac519c364a7286e8d765d6cd08648f5b21ca855a8017d9871f075542d \ - --hash=sha256:a1e8cc6cc01da346dc92d9509a63033b9b1bda4fed7a7a7807ed385c7dccdc10 \ - --hash=sha256:ab65cb2885a9f80f979b85aa4e9c9165a31381ca322cbde7c638fe6eefd1ec39 \ - --hash=sha256:af865c18752d416798dae13f83f38927c52f085c52e2f32b8ab0fef46fdd02c2 \ - --hash=sha256:b1e14b2f6965a685c7128bd315e27387205429c2e339eeec55cb75ca4ab0ea2e \ - --hash=sha256:b2a9f9aee38039cf4755891a1e50e1effcc42ea6ba053743f452c372c3152b1b \ - --hash=sha256:be6c0466b4c25b44c5d82b0426b5501de3c424d7a3220e86cd32f319ba56798e \ - --hash=sha256:c4e2cc868b7b5208aec6c960950b7bb821f82c2fe66446c92ee0a571765e91a5 \ - --hash=sha256:c805fa6e5d461329fa02f53f88c914d189ea771b6821083937e79550bf31fc19 \ - --hash=sha256:cf36851ee7219c170bb0793dbc3da3e80c582e04a5437bc601bfe8c85c9216d7 \ - --hash=sha256:db23b1bf8cfe1f7fda19018e7207b20cdb5168f83c437ff7e95d19e39289c447 \ - --hash=sha256:e0c05aff5c6b1bb5fb46a87e0f9d2f733f83ef6cbbbcd5c642b6c01678268061 \ - --hash=sha256:e8ac45e8f4eaac0f9f8043ea0e224158855c6a4329fd4ee37c45c61e3beb518e \ - --hash=sha256:ea3cd46b6713a10216323cda3333514944e510aa691c945334713fca6b5279ff \ - --hash=sha256:ebf7e1e78af38047e08836d33502c7a278915698b7c2145d045f780201679999 \ - --hash=sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e \ - --hash=sha256:ff33c6e6ad006bbc0f34f5faf941cfc62c45841c64c0a058ac38c799f15b5ede +sqlalchemy[mypy]==2.0.48 \ + --hash=sha256:01f6bbd4308b23240cf7d3ef117557c8fd097ec9549d5d8a52977544e35b40ad \ + --hash=sha256:07edba08061bc277bfdc772dd2a1a43978f5a45994dd3ede26391b405c15221e \ + --hash=sha256:10853a53a4a00417a00913d270dddda75815fcb80675874285f41051c094d7dd \ + --hash=sha256:1182437cb2d97988cfea04cf6cdc0b0bb9c74f4d56ec3d08b81e23d621a28cc6 \ + --hash=sha256:144921da96c08feb9e2b052c5c5c1d0d151a292c6135623c6b2c041f2a45f9e0 \ + --hash=sha256:1a89ce07ad2d4b8cfc30bd5889ec40613e028ed80ef47da7d9dd2ce969ad30e0 \ + --hash=sha256:1b4c575df7368b3b13e0cebf01d4679f9a28ed2ae6c1cd0b1d5beffb6b2007dc \ + --hash=sha256:1ccd42229aaac2df431562117ac7e667d702e8e44afdb6cf0e50fa3f18160f0b \ + --hash=sha256:2645b7d8a738763b664a12a1542c89c940daa55196e8d73e55b169cc5c99f65f \ + --hash=sha256:288937433bd44e3990e7da2402fabc44a3c6c25d3704da066b85b89a85474ae0 \ + --hash=sha256:34634e196f620c7a61d18d5cf7dc841ca6daa7961aed75d532b7e58b309ac894 \ + --hash=sha256:348174f228b99f33ca1f773e85510e08927620caa59ffe7803b37170df30332b \ + --hash=sha256:36ac4ddc3d33e852da9cb00ffb08cea62ca05c39711dc67062ca2bb1fae35fd8 \ + --hash=sha256:3713e21ea67bca727eecd4a24bf68bcd414c403faae4989442be60994301ded0 \ + --hash=sha256:389b984139278f97757ea9b08993e7b9d1142912e046ab7d82b3fbaeb0209131 \ + --hash=sha256:426c5ca86415d9b8945c7073597e10de9644802e2ff502b8e1f11a7a2642856b \ + --hash=sha256:4599a95f9430ae0de82b52ff0d27304fe898c17cb5f4099f7438a51b9998ac77 \ + --hash=sha256:49b7bddc1eebf011ea5ab722fdbe67a401caa34a350d278cc7733c0e88fecb1f \ + --hash=sha256:53667b5f668991e279d21f94ccfa6e45b4e3f4500e7591ae59a8012d0f010dcb \ + --hash=sha256:546572a1793cc35857a2ffa1fe0e58571af1779bcc1ffa7c9fb0839885ed69a9 \ + --hash=sha256:583849c743e0e3c9bb7446f5b5addeacedc168d657a69b418063dfdb2d90081c \ + --hash=sha256:5aee45fd2c6c0f2b9cdddf48c48535e7471e42d6fb81adfde801da0bd5b93241 \ + --hash=sha256:5b193a7e29fd9fa56e502920dca47dffe60f97c863494946bd698c6058a55658 \ + --hash=sha256:5ca74f37f3369b45e1f6b7b06afb182af1fd5dde009e4ffd831830d98cbe5fe7 \ + --hash=sha256:68549c403f79a8e25984376480959975212a670405e3913830614432b5daa07a \ + --hash=sha256:69f5bc24904d3bc3640961cddd2523e361257ef68585d6e364166dfbe8c78fae \ + --hash=sha256:6bb85c546591569558571aa1b06aba711b26ae62f111e15e56136d69920e1616 \ + --hash=sha256:6f7b7243850edd0b8b97043f04748f31de50cf426e939def5c16bedb540698f7 \ + --hash=sha256:7001dc9d5f6bb4deb756d5928eaefe1930f6f4179da3924cbd95ee0e9f4dce89 \ + --hash=sha256:7a936f1bb23d370b7c8cc079d5fce4c7d18da87a33c6744e51a93b0f9e97e9b3 \ + --hash=sha256:7c998f2ace8bf76b453b75dbcca500d4f4b9dd3908c13e89b86289b37784848b \ + --hash=sha256:7cddca31edf8b0653090cbb54562ca027c421c58ddde2c0685f49ff56a1690e0 \ + --hash=sha256:8183dc57ae7d9edc1346e007e840a9f3d6aa7b7f165203a99e16f447150140d2 \ + --hash=sha256:82745b03b4043e04600a6b665cb98697c4339b24e34d74b0a2ac0a2488b6f94d \ + --hash=sha256:841a94c66577661c1f088ac958cd767d7c9bf507698f45afffe7a4017049de76 \ + --hash=sha256:858e433f12b0e5b3ed2f8da917433b634f4937d0e8793e5cb33c54a1a01df565 \ + --hash=sha256:908a3fa6908716f803b86896a09a2c4dde5f5ce2bb07aacc71ffebb57986ce99 \ + --hash=sha256:9764014ef5e58aab76220c5664abb5d47d5bc858d9debf821e55cfdd0f128485 \ + --hash=sha256:9c7d0a77e36b5f4b01ca398482230ab792061d243d715299b44a0b55c89fe617 \ + --hash=sha256:a5b429eb84339f9f05e06083f119ad814e6d85e27ecbdf9c551dfdbb128eaf8a \ + --hash=sha256:a66fe406437dd65cacd96a72689a3aaaecaebbcd62d81c5ac1c0fdbeac835096 \ + --hash=sha256:a6b764fb312bd35e47797ad2e63f0d323792837a6ac785a4ca967019357d2bc7 \ + --hash=sha256:b19151e76620a412c2ac1c6f977ab1b9fa7ad43140178345136456d5265b32ed \ + --hash=sha256:b8438ec5594980d405251451c5b7ea9aa58dda38eb7ac35fb7e4c696712ee24f \ + --hash=sha256:b8fc3454b4f3bd0a368001d0e968852dad45a873f8b4babd41bc302ec851a099 \ + --hash=sha256:bcb8ebbf2e2c36cfe01a94f2438012c6a9d494cf80f129d9753bcdf33bfc35a6 \ + --hash=sha256:d404dc897ce10e565d647795861762aa2d06ca3f4a728c5e9a835096c7059018 \ + --hash=sha256:d612c976cbc2d17edfcc4c006874b764e85e990c29ce9bd411f926bbfb02b9a2 \ + --hash=sha256:d64177f443594c8697369c10e4bbcac70ef558e0f7921a1de7e4a3d1734bcf67 \ + --hash=sha256:d854b3970067297f3a7fbd7a4683587134aa9b3877ee15aa29eea478dc68f933 \ + --hash=sha256:d8fcccbbc0c13c13702c471da398b8cd72ba740dca5859f148ae8e0e8e0d3e7e \ + --hash=sha256:e004aa9248e8cb0a5f9b96d003ca7c1c0a5da8decd1066e7b53f59eb8ce7c62b \ + --hash=sha256:e214d546c8ecb5fc22d6e6011746082abf13a9cf46eefb45769c7b31407c97b5 \ + --hash=sha256:e2d0d88686e3d35a76f3e15a34e8c12d73fc94c1dea1cd55782e695cc14086dd \ + --hash=sha256:e2f35b4cccd9ed286ad62e0a3c3ac21e06c02abc60e20aa51a3e305a30f5fa79 \ + --hash=sha256:e3070c03701037aa418b55d36532ecb8f8446ed0135acb71c678dbdf12f5b6e4 \ + --hash=sha256:e5e088bf43f6ee6fec7dbf1ef7ff7774a616c236b5c0cb3e00662dd71a56b571 \ + --hash=sha256:e83e3f959aaa1c9df95c22c528096d94848a1bc819f5d0ebf7ee3df0ca63db6c \ + --hash=sha256:f0dcbc588cd5b725162c076eb9119342f6579c7f7f55057bb7e3c6ff27e13121 \ + --hash=sha256:f27f9da0a7d22b9f981108fd4b62f8b5743423388915a563e651c20d06c1f457 \ + --hash=sha256:f8649a14caa5f8a243628b1d61cf530ad9ae4578814ba726816adb1121fc493e \ + --hash=sha256:fac0fa4e4f55f118fd87177dacb1c6522fe39c28d498d259014020fec9164c29 \ + --hash=sha256:fd08b90d211c086181caed76931ecfa2bdfc83eea3cfccdb0f82abc6c4b876cb # via feast (pyproject.toml) -sqlglot[rs]==28.10.1 \ - --hash=sha256:214aef51fd4ce16407022f81cfc80c173409dab6d0f6ae18c52b43f43b31d4dd \ - --hash=sha256:66e0dae43b4bce23314b80e9aef41b8c88fea0e17ada62de095b45262084a8c5 +sqlglot[rs]==30.2.1 \ + --hash=sha256:ef4a67cc6f66a8043085eb8ea95fa9541c1625dffa9145ad4e9815a7ba60a199 \ + --hash=sha256:f23d9ee9427ef9d20df15f9b0ffa57d9eb45e52b012219a349d1e6b50ed926d1 # via # feast (pyproject.toml) # ibis-framework -sqlglotrs==0.12.0 \ - --hash=sha256:011e9c1c1465de06198cc6b3220e64c833a0ebe3565db8bea1ddda70a6515e8d \ - --hash=sha256:033160f03e6a6aa14e8a07a680eb0706e3ed1ad997ba9fb89c7fc8149e83899c \ - --hash=sha256:0c27d654a7dc0d0a06e3fb94798542e3e748a3f2fc41444565d18ba95021b806 \ - --hash=sha256:10a67825f654a599cbac58c8d129b0c7f49acf4e3ca05e471df301ca00b819e7 \ - --hash=sha256:16d581b25d0731aa25681640450f5d305a0aa04c3257a8e0d3a7ecd15e6e1c7f \ - --hash=sha256:1a5147585d909d5640aa2589a470986a7c9cfb3c90e92970942b9ccc512bacad \ - --hash=sha256:1ca61b15c2fd37d21770a02cf7b48e406e887ae597d158f67e8d868ddc79f4d6 \ - --hash=sha256:21d4c25cee14f758f8ca095fc9e61aa239cd93c438eaffc36462d85e94e7d395 \ - --hash=sha256:28d1ecc8afc6323a537d74df8c5f4545641742cf9b965813de1fb72ddc1bfe5c \ - --hash=sha256:2a097e56cbaed9b97901c2a149381e547627aaeb1dc388a0b691543558dad1ab \ - --hash=sha256:2a58221be2d771b6d65a7b3721a0c3020eeff17cd825905a35a47558acad8257 \ - --hash=sha256:2faa9dc5d11b19122189a8635a269efaee6f7bb609ae653d43f7b71be2ff54d0 \ - --hash=sha256:466451fed87ca90a4a2ec1b3e026ac9d4f8a57e4ed9c51583290ef11fc4c1631 \ - --hash=sha256:47b56e8bd5ed85055ae0409c53cdf4d8dbc5f7c3170f238b472173fcb16ddfe0 \ - --hash=sha256:4e5f477522a76fee1d1907b0196510f002f4c339a286de9cd63f8d51265b0f68 \ - --hash=sha256:4f0dac396c68ea9612cc89bb170c0366a7d686d012142a4365ed222401d6b645 \ - --hash=sha256:5312f17e3e2b5c18fac8269d8d5a2c26a0aed79a22854787153d7ff5bff7be66 \ - --hash=sha256:533cbefb35128de669efa7e1e86fec61383121ebd5514e0a1e70aa33bf875987 \ - --hash=sha256:5443e10a41894719778d40fb854192efd569eb99b26ef37e87a4730cc2ee899b \ - --hash=sha256:558720d901a0be3ee69660c0b72fe3dfdf23f557d7911d13f4d3555fdd44ae75 \ - --hash=sha256:6156f621c1c4ea4a46efbaf977f4df52a29f2f414bfb62de8ea878f50d4fd506 \ - --hash=sha256:61751c7f2ca0a1f83e2df041295fe71a88ce0b025bb4e578164657822bead0e1 \ - --hash=sha256:6364c8bfc8c5678e13562bf705a111124afbfaaa1762ce00384dc514e31c6a4a \ - --hash=sha256:656b03b7eae2fd03f0a89770e08a6b815f462d5eef8abf6942442c769bda8ca2 \ - --hash=sha256:672cdcbed0dfa45fa6f3922c8c9d893092dd47e0600f25b8076559e3aeeb1921 \ - --hash=sha256:69470afeaef3a48e1bb87f25c83d2061bc4bd870665e6a2c2e0c0c2b82ab0480 \ - --hash=sha256:6be5fac1f7a01c1b3e40c2478a3db5a125201d39e4601f6075660804a7b40e18 \ - --hash=sha256:6e0be4ceffe2aec98e308df9e872084c47c8f178fa0269d4bf1f1b99eb1c877b \ - --hash=sha256:72b9829ab9dfce9997740d6949a981f619f813d664524314386fa80b72ede7b1 \ - --hash=sha256:7a9f6ffb06b3d617556819f9e14703a0f5a65b8d87613969141be08cdd06b620 \ - --hash=sha256:7fcbc0004986510f4c5c625d053ee8febf836116db1dab3bd407292a69dee375 \ - --hash=sha256:850c408ae94f85f9d8c35a4511d1f67c560c077467c41a6ea66f5046b4b731f9 \ - --hash=sha256:8641bfbcc9b92167aff99d589e0fd2f4d902759e415b13e59352314bf5348770 \ - --hash=sha256:900f9023f8eca065e81665507722a4563e76bab19cc1322837d9248186e1ea90 \ - --hash=sha256:90bee58c15c9144f571e79e4e57b645452d0142cfee35cf2e11ec6124c4e5f07 \ - --hash=sha256:94b02d14c044d3eb22b4c494813f587f47e65d0343a4dc341c9b542a01cfca16 \ - --hash=sha256:a0b78f58b5ea14fef29d03636666e3a749b2aed88a3603df1dadc16215fb5b78 \ - --hash=sha256:a27d106b870d2a28f6caf100af8976054fdea649e6da733c31bcf7730ad928dd \ - --hash=sha256:a6c419d8ae6c234d151a71f1becabc13d0c44d67a76376d8d934aaf350f08858 \ - --hash=sha256:a880b4d4133591e90d40bdd802404e960e396dd24c2eda6a2a04cbba6effc4d5 \ - --hash=sha256:ae6d7e877bf6890fdb35ed00819783e1a1ddce8c8ed7009dc1604323bf24d0ed \ - --hash=sha256:b0e0193d3e13d37ede7969f3b52d3feaeb56d7e3ba78bafb1d75a2c789bf0373 \ - --hash=sha256:ba15622063c60b17bdce8575d53b1c81ad5d31fc77d00e20378c0051d6ffa4cf \ - --hash=sha256:bb7d8e05fe19b5bd157c20289a66a9b218c9eb3314ae78ec6bae2e9525900b30 \ - --hash=sha256:bd6c108d6b64950060570aba6181fa03366e2e458793706cef379d86ebde5670 \ - --hash=sha256:bdc5bb2c4ba35fa76baeb6eb31ee7c5bb349af1bc7c4b51ce5804e1370442e30 \ - --hash=sha256:c08e633850082cc1353fe2c24ec3c6bd229f8b5925662a8d5526cc94073349b4 \ - --hash=sha256:c26f1ff7eca636a55eb79bc2b622422561b9801201a4c2a62512902d818671e8 \ - --hash=sha256:c37796704edaa1ad73ba9e43f308f8e93d2392ade33fa8a51e1d55d8b6136b0f \ - --hash=sha256:c876cd551d3d724daac533b833e11d359f95037b5757487492caf8e600326848 \ - --hash=sha256:ce31216150be347a045ef35358c6c640a87c389482745cef5d481242cbac8f8e \ - --hash=sha256:d08c63e1bebe4963a5efe56e4ed278a441c2e552f9d1d6a768721b52b29cbb4a \ - --hash=sha256:d0bf559389c38aecdaefba14a7e4d59570ef491dbfaa41b8493614c97c1268c5 \ - --hash=sha256:e0f8c959e44f330e9b7000bc9a6926e18bf9d44b6cba2dd81807a6a2d552c597 \ - --hash=sha256:e55cb36ec074fd0abafd6698d2f7cd1d91e01c102384bdc945b977a86d2199a6 \ - --hash=sha256:f36716d090f373eda020b5e130a48da0139f3eede7f5e5b684c58263b83bd7d1 \ - --hash=sha256:f3c937c9ae8fb4ec3bc3bc0bea215dec290dfa0ce033048d25c87f7b632a3d3a \ - --hash=sha256:f4fc40bae51f36818acd8f98a4246eebd8c283081906dc22db353ab1e141f529 \ - --hash=sha256:f7426f61a2596a6f681dde5d8e4d0386aa2bdddee3af8902c6c3266d6249480e \ - --hash=sha256:fa2c04c40af5b209631feea812103a079f8a016e1ddb60eb74e9460d72050bfe \ - --hash=sha256:fb402884d234c0a500c42bb2a5f500604891ef83e58c984ec2b4af8fa76bd72d +sqlglotc==30.2.1 \ + --hash=sha256:052cd7bb41fc9b841eb268d4dd601eb6b5954b7c6d5656795d4350a0f8020d53 \ + --hash=sha256:058f0e9aed2b8dff87dc893b8793e514204c8dfef699b7d3d1704dfbdd949f2b \ + --hash=sha256:0e6be524252894c0fa98d25d4e60dfae6485ba66ca1abd40bf05f16a9cf26baf \ + --hash=sha256:13f8f68808777ba7d845bc908bf09f72a0c9899a19811483dc52f0fa48b38d5a \ + --hash=sha256:1a004086ab871be0cc97766f7b6fb8866729f09dd7272254fd31c05107f3fdc8 \ + --hash=sha256:25c6f62f31cd3a051285635c3f6a01d2f3c73ca2baaa26970815166928042ace \ + --hash=sha256:2b5fe8adc1a1e2fb819e014e94974a274f30dbf9684ceed9f171fb0889f80f0b \ + --hash=sha256:2ffe527bc8664b03cc936bae7ebf965f482beb4acee7a815c2ec2d9aea720b4e \ + --hash=sha256:4aa90e08f53409b1857572836e57a31835ed20e32521c6fafdc6af96199baff7 \ + --hash=sha256:507935a971e0a9e5d4ac7ca14df479f8e270502b44904f71d95c0aaed066006f \ + --hash=sha256:515e092ab8fb522b256fa8a34f471e9b187bb8a50a7c0226a65b036a07d6d188 \ + --hash=sha256:585bb610fde3e3dd1d7e5ff3cce14f70fbd53ced6769cd104679adf8b5c4ab5b \ + --hash=sha256:850e7517dd4739cad9af65bcb9699825f9202e5971407bf955e3248fe4814f96 \ + --hash=sha256:8f063af733cbcc51686380470e7f3f80b589b8c58084baa138efb3b8ca821597 \ + --hash=sha256:b17e3002ed10747388367621b2ecf39c06d5fdc6b3c31a8c32be2f5ef546fc0b \ + --hash=sha256:d577e1635e127febb7012bc42fa1c3b958076e59a1a116ade20048c572a1be42 \ + --hash=sha256:dc292cd73e0c447253877c27f00454a2d09b71324a130ad4c58c145ab753889e \ + --hash=sha256:de168df756a21a028cf1f917f92da2f77bb135f3b6cdd960914460942a5eca10 \ + --hash=sha256:de884dd224220002c3e940ca5bdceb27ef9638e5f02493db133ffb8ae88b5610 \ + --hash=sha256:f33c7d1646ff6531cb9b07f0740b2939f3ecaa31efebfbec8adb6b275f1a45f2 \ + --hash=sha256:f9a1fc7b1ff3b51d0d03a391768a79964f68541b4c2f294a25a6f14e6670ffab \ + --hash=sha256:fae4edad0b7c5f9f963bd63452f722f0d7f77a436c2d334b555b31722f9573ad \ + --hash=sha256:fdc19623a1c7659918c3cee18ea8849fc4af9eaeb87247acf37e0393295d32b7 \ + --hash=sha256:feefc0ab7606d1fe284d23bef09ea4829ce4fad679936959c29324310f23e081 \ + --hash=sha256:ff19b7ecb931aef6c7c6168af5530c07e67915102b701d45ae80446f0695ba54 + # via sqlglot +sqlglotrs==0.13.0 \ + --hash=sha256:6b934a244b16f26fca50974328a2ebc7689583c59f06203cebb46e2e6e8d93a7 \ + --hash=sha256:ad1ad158234af0f8ba5054ca51bd17a7c1e3f81b4798c7970ebf7953fe08ddcb # via sqlglot sqlite-vec==0.1.6 \ --hash=sha256:77491bcaa6d496f2acb5cc0d0ff0b8964434f141523c121e313f9a7d8088dee3 \ @@ -5607,17 +5623,17 @@ sqlparams==6.2.0 \ --hash=sha256:3744a2ad16f71293db6505b21fd5229b4757489a9b09f3553656a1ae97ba7ca5 \ --hash=sha256:63b32ed9051bdc52e7e8b38bc4f78aed51796cdd9135e730f4c6a7db1048dedf # via singlestoredb -sse-starlette==3.2.0 \ - --hash=sha256:5876954bd51920fc2cd51baee47a080eb88a37b5b784e615abb0b283f801cdbf \ - --hash=sha256:8127594edfb51abe44eac9c49e59b0b01f1039d0c7461c6fd91d4e03b70da422 +sse-starlette==3.3.4 \ + --hash=sha256:84bb06e58939a8b38d8341f1bc9792f06c2b53f48c608dd207582b664fc8f3c1 \ + --hash=sha256:aaf92fc067af8a5427192895ac028e947b484ac01edbc3caf00e7e7137c7bef1 # via mcp stack-data==0.6.3 \ --hash=sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9 \ --hash=sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695 # via ipython -starlette==0.52.1 \ - --hash=sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74 \ - --hash=sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933 +starlette==1.0.0 \ + --hash=sha256:6a4beaf1f81bb472fd19ea9b918b50dc3a77a6f2e190a12954b25e6ed5eea149 \ + --hash=sha256:d3ec55e0bb321692d275455ddfd3df75fff145d009685eb40dc91fc66b03d38b # via # fastapi # mcp @@ -5626,9 +5642,9 @@ sympy==1.14.0 \ --hash=sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517 \ --hash=sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5 # via torch -tabulate==0.9.0 \ - --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ - --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f +tabulate==0.10.0 \ + --hash=sha256:e2cfde8f79420f6deeffdeda9aaec3b6bc5abce947655d17ac662b126e48a60d \ + --hash=sha256:f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3 # via # feast (pyproject.toml) # docling-core @@ -5660,14 +5676,18 @@ thriftpy2==0.6.0 \ --hash=sha256:1245c36b82f34aa26f049e6529f40ad34d9be8d12bd0131559847c8476b98ce0 \ --hash=sha256:151d299e8e3694a6cc0f2f2cda01d5744080742649de958c5cdcbebb4306205f \ --hash=sha256:16eecfd34bd541b75172ba0d69ea90b874611a7361d18906fb6d95955089cc30 \ + --hash=sha256:182f54a7248c8ecf1320cf26d1fc9115765df6b1f2589c1d2d0df7049a5b27d4 \ --hash=sha256:210345281d41b3a76d263b555d3e3cc482103738441bdb92a73033a4e9a042e1 \ --hash=sha256:265588b8cdb3fe1097db43bf35fb208edc69d9350a2bec3a737d6357d0a5650d \ --hash=sha256:28fd55960a6d42207060536109928a4615fbbd6874c0ddd8a705b47075f1d2d0 \ --hash=sha256:29ff125e40c8016b4d3bf48e6d727bd93d2892451b47bfe57ba896944ecbdb0c \ --hash=sha256:2ae866adf9b112c7ab30c1a90d878a5d6f2d40244fbc46ec8477425d802f4ac5 \ --hash=sha256:2bf891c2d441b1edddfc62f16ab3031ac7506cba5b77680654179dbe93d8b7ec \ + --hash=sha256:2c88b0d356ea18ce026a52aa7c2110693db77fd52d5ac7553616635a7f165bbd \ --hash=sha256:3090d9cabc2c31c92ae943f36d539a20adfd82697f50e996ce94f0b279e9e1e4 \ + --hash=sha256:3359a7c4eb4c281bf54bd760dcc03c43299f0d529dd2a5018be2f1fbebf0cbbd \ --hash=sha256:375cca06f36f54339838c7f8251b64a777d5ff1277f8b91999487fad1a8e2d73 \ + --hash=sha256:386d8c4a5677fd94fd16c1af2adf39f59698af1e4ef0c3c026083f278540e352 \ --hash=sha256:44365bb5098d0a91c44382e7df0ad44d5b9a588d29d9071aca4a2867f704aaf1 \ --hash=sha256:443e502b428d325c57aec0947991857e8dc0589d0464181f35bd48f870cd5d18 \ --hash=sha256:4550cbb6629c9f6186ab22cb497f262408e1a90ae10b8653599f2717f518f0df \ @@ -5684,6 +5704,7 @@ thriftpy2==0.6.0 \ --hash=sha256:851981ded8bb42da66213cf95d1dd5eaf06c5d6b3a95725a18eddd58ec992b6b \ --hash=sha256:852e538b4866ed776126349161d9fdc37387b1e15ab46805f98dcdee25fee4b5 \ --hash=sha256:8b19d19661fc9a71f19b7c432c413ab65025e5dd11fbd192bd9169afb13b9ce0 \ + --hash=sha256:8e62d9c36bcfe6b85bec7b754accb97e2fa7b6a7c9a0c37f824d85eba699e7b8 \ --hash=sha256:8eb0566b4501c27ea51f2e593531122703946969564fe526a5ff1b18be0ad49a \ --hash=sha256:8f393607d54091e8976e297f8fd7399606d12cd8c2b8852353f07ad5ddac4224 \ --hash=sha256:91df1fa70a99ac08dc449d6fda24a14992a1836d571928f217c40c66fd63fcc8 \ @@ -5698,25 +5719,28 @@ thriftpy2==0.6.0 \ --hash=sha256:b361152c24fd5c791220de9966b00696578c9884a2bb67e4759d4dfe05fd7049 \ --hash=sha256:b51b5259dc344482ab21b768dfc7f54d51d9133665e72890831725068f69f24a \ --hash=sha256:b57f367d7b0e1bc9e5c9b0ff34febdb3fe440f1fe8d75903ae71301bc06072c0 \ + --hash=sha256:b8dc65d2e7951b7e81c17b92857db7c19d6b3dd442d2d8600b5bd5040aa43ce6 \ --hash=sha256:bc320e960347e5f9d27e8b4a9fc7044b2b26bfe4522bb4957e741fc1d1ebd2f0 \ --hash=sha256:bdf77ba7a8987a239eb57cf840d62669741f8b92b61a617e63898caed31da898 \ --hash=sha256:bf96b64400da2f411b43c4c81c2e20b09e3300d86766a52f42393696c8962f11 \ --hash=sha256:c37f5dbfe95579549485c33167854784358f559feda703ccc058719ca0efd8aa \ --hash=sha256:c41312c6edad5e875613719236f1ca6bba9310df40b1adc9308248e1bdb7a1ea \ + --hash=sha256:cafa1d43bcc69129a4855fd3973ab7983bb2274c407e5ff572af5dc196e00313 \ --hash=sha256:cb98556e919be3e6ba9bca629dbddccfaa33b95a0fe7503052849b124e4f88cd \ --hash=sha256:cd2e2c4dcc30c373e317d39b044afa6d9a090bec11d186f25841f70bc520bbb5 \ --hash=sha256:e6c4fb1e7f51f8858f348ed9c31bb408b61274942d18b549ec163bb480c987a0 \ + --hash=sha256:eccab0281667caab0c055882b3bbb8e346bb0181e55f37477e3e5e3f5b7a96dd \ --hash=sha256:f59f74c3779aa47223ba0a9e23ef10d2af5a873ed3624c78303f62a679d1b63e \ --hash=sha256:f6b86112cca7bd04151ce248d781763ea5f74cc18d148476c6d16cee32db81ac \ --hash=sha256:f837ab85ae93b118766b8b28a1cec47a1daddee303e1f986a595c56379062a5c # via happybase -tifffile==2026.2.15 \ - --hash=sha256:28fe145c615fe3d33d40c2d4c9cc848f7631fd30af852583c4186069458895b2 \ - --hash=sha256:d9b427d269a708c58400e8ce5a702b26b2502087537beb88b8e29ba7ba825a90 +tifffile==2026.3.3 \ + --hash=sha256:d9a1266bed6f2ee1dd0abde2018a38b4f8b2935cb843df381d70ac4eac5458b7 \ + --hash=sha256:e8be15c94273113d31ecb7aa3a39822189dd11c4967e3cc88c178f1ad2fd1170 # via scikit-image -timm==1.0.24 \ - --hash=sha256:8301ac783410c6ad72c73c49326af6d71a9e4d1558238552796e825c2464913f \ - --hash=sha256:c7b909f43fe2ef8fe62c505e270cd4f1af230dfbc37f2ee93e3608492b9d9a40 +timm==1.0.26 \ + --hash=sha256:985c330de5ccc3a2aa0224eb7272e6a336084702390bb7e3801f3c91603d3683 \ + --hash=sha256:f66f082f2f381cf68431c22714c8b70f723837fa2a185b155961eab90f2d5b10 # via feast (pyproject.toml) tinycss2==1.4.0 \ --hash=sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7 \ @@ -5752,54 +5776,54 @@ toml==0.10.2 \ --hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \ --hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f # via feast (pyproject.toml) -tomli==2.4.0 \ - --hash=sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729 \ - --hash=sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b \ - --hash=sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d \ - --hash=sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df \ - --hash=sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576 \ - --hash=sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d \ - --hash=sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1 \ - --hash=sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a \ - --hash=sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e \ - --hash=sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc \ - --hash=sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702 \ - --hash=sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6 \ - --hash=sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd \ - --hash=sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4 \ - --hash=sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776 \ - --hash=sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a \ - --hash=sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66 \ - --hash=sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87 \ - --hash=sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2 \ - --hash=sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f \ - --hash=sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475 \ - --hash=sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f \ - --hash=sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95 \ - --hash=sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9 \ - --hash=sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3 \ - --hash=sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9 \ - --hash=sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76 \ - --hash=sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da \ - --hash=sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8 \ - --hash=sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51 \ - --hash=sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86 \ - --hash=sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8 \ - --hash=sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0 \ - --hash=sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b \ - --hash=sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1 \ - --hash=sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e \ - --hash=sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d \ - --hash=sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c \ - --hash=sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867 \ - --hash=sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a \ - --hash=sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c \ - --hash=sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0 \ - --hash=sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4 \ - --hash=sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614 \ - --hash=sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132 \ - --hash=sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa \ - --hash=sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087 +tomli==2.4.1 \ + --hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \ + --hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \ + --hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \ + --hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \ + --hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \ + --hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \ + --hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \ + --hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \ + --hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \ + --hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \ + --hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \ + --hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \ + --hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \ + --hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \ + --hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \ + --hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \ + --hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \ + --hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \ + --hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \ + --hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \ + --hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \ + --hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \ + --hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \ + --hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \ + --hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \ + --hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \ + --hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \ + --hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \ + --hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \ + --hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \ + --hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \ + --hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \ + --hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \ + --hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \ + --hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \ + --hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \ + --hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \ + --hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \ + --hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \ + --hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \ + --hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \ + --hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \ + --hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \ + --hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \ + --hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \ + --hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \ + --hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049 # via fastapi-mcp tomlkit==0.14.0 \ --hash=sha256:592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680 \ @@ -5813,94 +5837,89 @@ toolz==1.1.0 \ # dask # ibis-framework # partd -torch==2.10.0 \ - --hash=sha256:13ec4add8c3faaed8d13e0574f5cd4a323c11655546f91fbe6afa77b57423574 \ - --hash=sha256:233aed0659a2503b831d8a67e9da66a62c996204c0bba4f4c442ccc0c68a3f60 \ - --hash=sha256:29b7009dba4b7a1c960260fc8ac85022c784250af43af9fb0ebafc9883782ebd \ - --hash=sha256:2b980edd8d7c0a68c4e951ee1856334a43193f98730d97408fbd148c1a933313 \ - --hash=sha256:2c66c61f44c5f903046cc696d088e21062644cbe541c7f1c4eaae88b2ad23547 \ - --hash=sha256:3202429f58309b9fa96a614885eace4b7995729f44beb54d3e4a47773649d382 \ - --hash=sha256:3282d9febd1e4e476630a099692b44fdc214ee9bf8ee5377732d9d9dfe5712e4 \ - --hash=sha256:35e407430795c8d3edb07a1d711c41cc1f9eaddc8b2f1cc0a165a6767a8fb73d \ - --hash=sha256:418997cb02d0a0f1497cf6a09f63166f9f5df9f3e16c8a716ab76a72127c714f \ - --hash=sha256:5276fa790a666ee8becaffff8acb711922252521b28fbce5db7db5cf9cb2026d \ - --hash=sha256:5c4d217b14741e40776dd7074d9006fd28b8a97ef5654db959d8635b2fe5f29b \ - --hash=sha256:5fd4117d89ffd47e3dcc71e71a22efac24828ad781c7e46aaaf56bf7f2796acf \ - --hash=sha256:6021db85958db2f07ec94e1bc77212721ba4920c12a18dc552d2ae36a3eb163f \ - --hash=sha256:6528f13d2a8593a1a412ea07a99812495bec07e9224c28b2a25c0a30c7da025c \ - --hash=sha256:682497e16bdfa6efeec8cde66531bc8d1fbbbb4d8788ec6173c089ed3cc2bfe5 \ - --hash=sha256:6b71486353fce0f9714ca0c9ef1c850a2ae766b409808acd58e9678a3edb7738 \ - --hash=sha256:6d3707a61863d1c4d6ebba7be4ca320f42b869ee657e9b2c21c736bf17000294 \ - --hash=sha256:71283a373f0ee2c89e0f0d5f446039bdabe8dbc3c9ccf35f0f784908b0acd185 \ - --hash=sha256:716b01a176c2a5659c98f6b01bf868244abdd896526f1c692712ab36dbaf9b63 \ - --hash=sha256:787124e7db3b379d4f1ed54dd12ae7c741c16a4d29b49c0226a89bea50923ffb \ - --hash=sha256:a2f9edd8dbc99f62bc4dfb78af7bf89499bca3d753423ac1b4e06592e467b763 \ - --hash=sha256:a4be6a2a190b32ff5c8002a0977a25ea60e64f7ba46b1be37093c141d9c49aeb \ - --hash=sha256:aae1b29cd68e50a9397f5ee897b9c24742e9e306f88a807a27d617f07adb3bd8 \ - --hash=sha256:aaf663927bcd490ae971469a624c322202a2a1e68936eb952535ca4cd3b90444 \ - --hash=sha256:b7bd80f3477b830dd166c707c5b0b82a898e7b16f59a7d9d42778dd058272e8b \ - --hash=sha256:bf0d9ff448b0218e0433aeb198805192346c4fd659c852370d5cc245f602a06a \ - --hash=sha256:c2ee399c644dc92ef7bc0d4f7e74b5360c37cdbe7c5ba11318dda49ffac2bc57 \ - --hash=sha256:cdf2a523d699b70d613243211ecaac14fe9c5df8a0b0a9c02add60fb2a413e0f \ - --hash=sha256:d8f5912ba938233f86361e891789595ff35ca4b4e2ac8fe3670895e5976731d6 \ - --hash=sha256:e521c9f030a3774ed770a9c011751fb47c4d12029a3d6522116e48431f2ff89e \ - --hash=sha256:f5ab4ba32383061be0fb74bda772d470140a12c1c3b58a0cfbf3dae94d164c28 \ - --hash=sha256:ff43db38af76fda183156153983c9a096fc4c78d0cd1e07b14a2314c7f01c2c8 +torch==2.11.0 \ + --hash=sha256:01018087326984a33b64e04c8cb5c2795f9120e0d775ada1f6638840227b04d7 \ + --hash=sha256:0f68f4ac6d95d12e896c3b7a912b5871619542ec54d3649cf48cc1edd4dd2756 \ + --hash=sha256:1b32ceda909818a03b112006709b02be1877240c31750a8d9c6b7bf5f2d8a6e5 \ + --hash=sha256:1e6debd97ccd3205bbb37eb806a9d8219e1139d15419982c09e23ef7d4369d18 \ + --hash=sha256:2658f34ce7e2dabf4ec73b45e2ca68aedad7a5be87ea756ad656eaf32bf1e1ea \ + --hash=sha256:2b4e811728bd0cc58fb2b0948fe939a1ee2bf1422f6025be2fca4c7bd9d79718 \ + --hash=sha256:2bb3cc54bd0dea126b0060bb1ec9de0f9c7f7342d93d436646516b0330cd5be7 \ + --hash=sha256:2c0d7fcfbc0c4e8bb5ebc3907cbc0c6a0da1b8f82b1fc6e14e914fa0b9baf74e \ + --hash=sha256:4b5866312ee6e52ea625cd211dcb97d6a2cdc1131a5f15cc0d87eec948f6dd34 \ + --hash=sha256:4cf8687f4aec3900f748d553483ef40e0ac38411c3c48d0a86a438f6d7a99b18 \ + --hash=sha256:4dc8b3809469b6c30b411bb8c4cad3828efd26236153d9beb6a3ec500f211a60 \ + --hash=sha256:4dda3b3f52d121063a731ddb835f010dc137b920d7fec2778e52f60d8e4bf0cd \ + --hash=sha256:563ed3d25542d7e7bbc5b235ccfacfeb97fb470c7fee257eae599adb8005c8a2 \ + --hash=sha256:63a68fa59de8f87acc7e85a5478bb2dddbb3392b7593ec3e78827c793c4b73fd \ + --hash=sha256:73e24aaf8f36ab90d95cd1761208b2eb70841c2a9ca1a3f9061b39fc5331b708 \ + --hash=sha256:7aa2f9bbc6d4595ba72138026b2074be1233186150e9292865e04b7a63b8c67a \ + --hash=sha256:7b6a60d48062809f58595509c524b88e6ddec3ebe25833d6462eeab81e5f2ce4 \ + --hash=sha256:8245477871c3700d4370352ffec94b103cfcb737229445cf9946cddb7b2ca7cd \ + --hash=sha256:8b394322f49af4362d4f80e424bcaca7efcd049619af03a4cf4501520bdf0fb4 \ + --hash=sha256:98bb213c3084cfe176302949bdc360074b18a9da7ab59ef2edc9d9f742504778 \ + --hash=sha256:a97b94bbf62992949b4730c6cd2cc9aee7b335921ee8dc207d930f2ed09ae2db \ + --hash=sha256:ab9a8482f475f9ba20e12db84b0e55e2f58784bdca43a854a6ccd3fd4b9f75e6 \ + --hash=sha256:b2a43985ff5ef6ddd923bbcf99943e5f58059805787c5c9a2622bf05ca2965b0 \ + --hash=sha256:b3c712ae6fb8e7a949051a953fc412fe0a6940337336c3b6f905e905dac5157f \ + --hash=sha256:cc89b9b173d9adfab59fd227f0ab5e5516d9a52b658ae41d64e59d2e55a418db \ + --hash=sha256:d91aac77f24082809d2c5a93f52a5f085032740a1ebc9252a7b052ef5a4fddc6 \ + --hash=sha256:f99924682ef0aa6a4ab3b1b76f40dc6e273fca09f367d15a524266db100a723f \ + --hash=sha256:fbf39280699d1b869f55eac536deceaa1b60bd6788ba74f399cc67e60a5fab10 # via # feast (pyproject.toml) # accelerate # docling-ibm-models # easyocr # safetensors + # sentence-transformers # timm # torchvision -torchvision==0.25.0 \ - --hash=sha256:0b5e7f50002a8145a98c5694a018e738c50e2972608310c7e88e1bd4c058f6ce \ - --hash=sha256:0d9a3f925a081dd2ebb0b791249b687c2ef2c2717d027946654607494b9b64b6 \ - --hash=sha256:146d02c9876858420adf41f3189fe90e3d6a409cbfa65454c09f25fb33bf7266 \ - --hash=sha256:153c0d2cbc34b7cf2da19d73450f24ba36d2b75ec9211b9962b5022fb9e4ecee \ - --hash=sha256:24e11199e4d84ba9c5ee7825ebdf1cd37ce8deec225117f10243cae984ced3ec \ - --hash=sha256:40a122c3cf4d14b651f095e0f672b688dde78632783fc5cd3d4d5e4f6a828563 \ - --hash=sha256:5e6b449e9fa7d642142c0e27c41e5a43b508d57ed8e79b7c0a0c28652da8678c \ - --hash=sha256:5f271136d2d2c0b7a24c5671795c6e4fd8da4e0ea98aeb1041f62bc04c4370ef \ - --hash=sha256:620a236288d594dcec7634c754484542dc0a5c1b0e0b83a34bda5e91e9b7c3a1 \ - --hash=sha256:632db02300e83793812eee4f61ae6a2686dab10b4cfd628b620dc47747aa9d03 \ - --hash=sha256:846890161b825b38aa85fc37fb3ba5eea74e7091ff28bab378287111483b6443 \ - --hash=sha256:855c0dc6d37f462482da7531c6788518baedca1e0847f3df42a911713acdfe52 \ - --hash=sha256:a8f8061284395ce31bcd460f2169013382ccf411148ceb2ee38e718e9860f5a7 \ - --hash=sha256:a95c47abb817d4e90ea1a8e57bd0d728e3e6b533b3495ae77d84d883c4d11f56 \ - --hash=sha256:acc339aba4a858192998c2b91f635827e40d9c469d9cf1455bafdda6e4c28ea4 \ - --hash=sha256:ad9a8a5877782944d99186e4502a614770fe906626d76e9cd32446a0ac3075f2 \ - --hash=sha256:b57430fbe9e9b697418a395041bb615124d9c007710a2712fda6e35fb310f264 \ - --hash=sha256:b75deafa2dfea3e2c2a525559b04783515e3463f6e830cb71de0fb7ea36fe233 \ - --hash=sha256:c2abe430c90b1d5e552680037d68da4eb80a5852ebb1c811b2b89d299b10573b \ - --hash=sha256:c4d395cb2c4a2712f6eb93a34476cdf7aae74bb6ea2ea1917f858e96344b00aa \ - --hash=sha256:cef0196be31be421f6f462d1e9da1101be7332d91984caa6f8022e6c78a5877f \ - --hash=sha256:d1abd5ed030c708f5dbf4812ad5f6fbe9384b63c40d6bd79f8df41a4a759a917 \ - --hash=sha256:db74a551946b75d19f9996c419a799ffdf6a223ecf17c656f90da011f1d75b20 \ - --hash=sha256:ea580ffd6094cc01914ad32f8c8118174f18974629af905cea08cb6d5d48c7b7 \ - --hash=sha256:f07f01d27375ad89d72aa2b3f2180f07da95dd9d2e4c758e015c0acb2da72977 \ - --hash=sha256:f25aa9e380865b11ea6e9d99d84df86b9cc959f1a007cd966fc6f1ab2ed0e248 \ - --hash=sha256:f49964f96644dbac2506dffe1a0a7ec0f2bf8cf7a588c3319fed26e6329ffdf3 \ - --hash=sha256:f9c55ae8d673ab493325d1267cbd285bb94d56f99626c00ac4644de32a59ede3 +torchvision==0.26.0 \ + --hash=sha256:0f3e572efe62ad645017ea847e0b5e4f2f638d4e39f05bc011d1eb9ac68d4806 \ + --hash=sha256:114bec0c0e98aa4ba446f63e2fe7a2cbca37b39ac933987ee4804f65de121800 \ + --hash=sha256:1c55dc8affbcc0eb2060fbabbe996ae9e5839b24bb6419777f17848945a411b1 \ + --hash=sha256:2adfbe438473236191ff077a4a9a0c767436879c89628aa97137e959b0c11a94 \ + --hash=sha256:358fc4726d0c08615b6d83b3149854f11efb2a564ed1acb6fce882e151412d23 \ + --hash=sha256:3daf9cc149cf3cdcbd4df9c59dae69ffca86c6823250442c3bbfd63fc2e26c61 \ + --hash=sha256:406557718e62fdf10f5706e88d8a5ec000f872da913bf629aab9297622585547 \ + --hash=sha256:4280c35ec8cba1fcc8294fb87e136924708726864c379e4c54494797d86bc474 \ + --hash=sha256:55bd6ad4ae77be01ba67a410b05b51f53b0d0ee45f146eb6a0dfb9007e70ab3c \ + --hash=sha256:5d63dd43162691258b1b3529b9041bac7d54caa37eae0925f997108268cbf7c4 \ + --hash=sha256:7058c5878262937e876f20c25867b33724586aa4499e2853b2d52b99a5e51953 \ + --hash=sha256:7993c01648e7c61d191b018e84d38fe0825c8fcb2720cd0f37caf7ba14404aa1 \ + --hash=sha256:8008474855623c6ba52876589dc52df0aa66e518c25eca841445348e5f79844c \ + --hash=sha256:82c3965eca27e86a316e31e4c3e5a16d353e0bcbe0ef8efa2e66502c54493c4b \ + --hash=sha256:9a904f2131cbfadab4df828088a9f66291ad33f49ff853872aed1f86848ef776 \ + --hash=sha256:a06d4772a8e13e772906ed736cc53ec6639e5e60554f8e5fa6ca165aabebc464 \ + --hash=sha256:a39c7a26538c41fda453f9a9692b5ff9b35a5437db1d94f3027f6f509c160eac \ + --hash=sha256:b6f9ad1ecc0eab52647298b379ee9426845f8903703e6127973f8f3d049a798b \ + --hash=sha256:b7d3e295624a28b3b1769228ce1345d94cf4d390dd31136766f76f2d20f718da \ + --hash=sha256:b7e6213620bbf97742e5f79832f9e9d769e6cf0f744c5b53dad80b76db633691 \ + --hash=sha256:c409e1c3fdebec7a3834465086dbda8bf7680eff79abf7fd2f10c6b59520a7a4 \ + --hash=sha256:d61a5abb6b42a0c0c311996c2ac4b83a94418a97182c83b055a2a4ae985e05aa \ + --hash=sha256:de6424b12887ad884f39a0ee446994ae3cd3b6a00a9cafe1bead85a031132af0 \ + --hash=sha256:e9d0e022c19a78552fb055d0414d47fecb4a649309b9968573daea160ba6869c \ + --hash=sha256:eb61804eb9dbe88c5a2a6c4da8dec1d80d2d0a6f18c999c524e32266cb1ebcd3 \ + --hash=sha256:ebc043cc5a4f0bf22e7680806dbba37ffb19e70f6953bbb44ed1a90aeb5c9bea \ + --hash=sha256:f13f12b3791a266de2d599cb8162925261622a037d87fc03132848343cf68f75 \ + --hash=sha256:fd10b5f994c210f4f6d6761cf686f82d748554adf486cb0979770c3252868c8f # via # feast (pyproject.toml) # docling-ibm-models # easyocr # timm -tornado==6.5.4 \ - --hash=sha256:053e6e16701eb6cbe641f308f4c1a9541f91b6261991160391bfc342e8a551a1 \ - --hash=sha256:1768110f2411d5cd281bac0a090f707223ce77fd110424361092859e089b38d1 \ - --hash=sha256:2d50f63dda1d2cac3ae1fa23d254e16b5e38153758470e9956cbc3d813d40843 \ - --hash=sha256:50ff0a58b0dc97939d29da29cd624da010e7f804746621c78d14b80238669335 \ - --hash=sha256:6076d5dda368c9328ff41ab5d9dd3608e695e8225d1cd0fd1e006f05da3635a8 \ - --hash=sha256:6eb82872335a53dd063a4f10917b3efd28270b56a33db69009606a0312660a6f \ - --hash=sha256:9c86b1643b33a4cd415f8d0fe53045f913bf07b4a3ef646b735a6a86047dda84 \ - --hash=sha256:a22fa9047405d03260b483980635f0b041989d8bcc9a313f8fe18b411d84b1d7 \ - --hash=sha256:d1cf66105dc6acb5af613c054955b8137e34a03698aa53272dbda4afe252be17 \ - --hash=sha256:d6241c1a16b1c9e4cc28148b1cda97dd1c6cb4fb7068ac1bedc610768dff0ba9 \ - --hash=sha256:e5fb5e04efa54cf0baabdd10061eb4148e0be137166146fff835745f59ab9f7f \ - --hash=sha256:fa07d31e0cd85c60713f2b995da613588aa03e1303d75705dca6af8babc18ddc +tornado==6.5.5 \ + --hash=sha256:192b8f3ea91bd7f1f50c06955416ed76c6b72f96779b962f07f911b91e8d30e9 \ + --hash=sha256:2c9a876e094109333f888539ddb2de4361743e5d21eece20688e3e351e4990a6 \ + --hash=sha256:36abed1754faeb80fbd6e64db2758091e1320f6bba74a4cf8c09cd18ccce8aca \ + --hash=sha256:3f54aa540bdbfee7b9eb268ead60e7d199de5021facd276819c193c0fb28ea4e \ + --hash=sha256:435319e9e340276428bbdb4e7fa732c2d399386d1de5686cb331ec8eee754f07 \ + --hash=sha256:487dc9cc380e29f58c7ab88f9e27cdeef04b2140862e5076a66fb6bb68bb1bfa \ + --hash=sha256:6443a794ba961a9f619b1ae926a2e900ac20c34483eea67be4ed8f1e58d3ef7b \ + --hash=sha256:65a7f1d46d4bb41df1ac99f5fcb685fb25c7e61613742d5108b010975a9a6521 \ + --hash=sha256:dd3eafaaeec1c7f2f8fdcd5f964e8907ad788fe8a5a32c4426fbbdda621223b7 \ + --hash=sha256:e74c92e8e65086b338fd56333fb9a68b9f6f2fe7ad532645a290a464bcf46be5 # via # ipykernel # jupyter-client @@ -5921,6 +5940,7 @@ tqdm==4.67.3 \ # milvus-lite # mpire # semchunk + # sentence-transformers # transformers traitlets==5.14.3 \ --hash=sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7 \ @@ -5945,6 +5965,7 @@ transformers==4.57.6 \ # feast (pyproject.toml) # docling-core # docling-ibm-models + # sentence-transformers tree-sitter==0.25.2 \ --hash=sha256:0628671f0de69bb279558ef6b640bcfc97864fe0026d840f872728a86cd6b6cd \ --hash=sha256:0c8b6682cac77e37cfe5cf7ec388844957f48b7bd8d6321d0ca2d852994e10d5 \ @@ -6025,13 +6046,13 @@ tree-sitter-typescript==0.23.2 \ --hash=sha256:c7cc1b0ff5d91bac863b0e38b1578d5505e718156c9db577c8baea2557f66de8 \ --hash=sha256:e96d36b85bcacdeb8ff5c2618d75593ef12ebaf1b4eace3477e2bdb2abb1752c # via docling-core -trino==0.336.0 \ - --hash=sha256:389150841446949119c3c2c13c1a51bb4be1a27818e40ae40dd3701f36c02550 \ - --hash=sha256:e82339e9fffe5c6c51de3bfdf28f083e3ae5945a4502739ab2094a0d08d68070 +trino==0.337.0 \ + --hash=sha256:3a0bd03a09b7ea5dccd41ca6e58abfb127c6303f3a48a258ff794d411dd83a3c \ + --hash=sha256:868f2b8137d4d1baa84c9bc341f2cdf29039462aa69d7c089a0b821b5a91f29c # via feast (pyproject.toml) -typeguard==4.5.0 \ - --hash=sha256:749bea21cdb2553e12831bc29f1eae980b22c7de8331ab67ae7db9e85470b5a7 \ - --hash=sha256:cfda388fc88a9ce42a41890900d6f31ee124bea9b73bb84701a32438e92165c3 +typeguard==4.5.1 \ + --hash=sha256:44d2bf329d49a244110a090b55f5f91aa82d9a9834ebfd30bcc73651e4a8cc40 \ + --hash=sha256:f6f8ecbbc819c9bc749983cc67c02391e16a9b43b8b27f15dc70ed7c4a007274 # via feast (pyproject.toml) typer==0.12.5 \ --hash=sha256:62fe4e471711b147e3365034133904df3e235698399bc4de2b36c8579298d52b \ @@ -6040,9 +6061,9 @@ typer==0.12.5 \ # docling # docling-core # fastapi-mcp -types-cffi==1.17.0.20250915 \ - --hash=sha256:4362e20368f78dabd5c56bca8004752cc890e07a71605d9e0d9e069dbaac8c06 \ - --hash=sha256:cef4af1116c83359c11bb4269283c50f0688e9fc1d7f0eeb390f3661546da52c +types-cffi==2.0.0.20260402 \ + --hash=sha256:47e1320c009f630c59c55c8e3d2b8c501e280babf52e92f6109cbfb0864ba367 \ + --hash=sha256:f647a400fba0a31d603479169d82ee5359db79bd1136e41dc7e6489296e3a2b2 # via types-pyopenssl types-protobuf==3.19.22 \ --hash=sha256:d291388678af91bb045fafa864f142dc4ac22f5d4cdca097c7d8d8a32fa9b3ab \ @@ -6058,13 +6079,13 @@ types-pyopenssl==24.1.0.20240722 \ --hash=sha256:47913b4678a01d879f503a12044468221ed8576263c1540dcb0484ca21b08c39 \ --hash=sha256:6a7a5d2ec042537934cfb4c9d4deb0e16c4c6250b09358df1f083682fe6fda54 # via types-redis -types-python-dateutil==2.9.0.20260124 \ - --hash=sha256:7d2db9f860820c30e5b8152bfe78dbdf795f7d1c6176057424e8b3fdd1f581af \ - --hash=sha256:f802977ae08bf2260142e7ca1ab9d4403772a254409f7bbdf652229997124951 +types-python-dateutil==2.9.0.20260402 \ + --hash=sha256:7827e6a9c93587cc18e766944254d1351a2396262e4abe1510cbbd7601c5e01f \ + --hash=sha256:a980142b9966713acb382c467e35c5cc4208a2f91b10b8d785a0ae6765df6c0b # via feast (pyproject.toml) -types-pytz==2025.2.0.20251108 \ - --hash=sha256:0f1c9792cab4eb0e46c52f8845c8f77cf1e313cb3d68bf826aa867fe4717d91c \ - --hash=sha256:fca87917836ae843f07129567b74c1929f1870610681b4c92cb86a3df5817bdb +types-pytz==2026.1.1.20260402 \ + --hash=sha256:0d9a60ed1c6ad4fce7c6395b5bd2d9827db41d4b83de7c0322cf85869c2bfda3 \ + --hash=sha256:79209aa51dc003a4a6a764234d92b14e5c09a1b7f24e0f00c493929fd33618e8 # via feast (pyproject.toml) types-pyyaml==6.0.12.20250915 \ --hash=sha256:0f8b54a528c303f0e6f7165687dd33fafa81c807fcac23f632b63aa624ced1d3 \ @@ -6078,15 +6099,15 @@ types-requests==2.30.0.0 \ --hash=sha256:c6cf08e120ca9f0dc4fa4e32c3f953c3fba222bcc1db6b97695bce8da1ba9864 \ --hash=sha256:dec781054324a70ba64430ae9e62e7e9c8e4618c185a5cb3f87a6738251b5a31 # via feast (pyproject.toml) -types-setuptools==82.0.0.20260210 \ - --hash=sha256:5124a7daf67f195c6054e0f00f1d97c69caad12fdcf9113eba33eff0bce8cd2b \ - --hash=sha256:d9719fbbeb185254480ade1f25327c4654f8c00efda3fec36823379cebcdee58 +types-setuptools==82.0.0.20260402 \ + --hash=sha256:4b9a9f6c3c4c65107a3956ad6a6acbccec38e398ff6d5f78d5df7f103dadb8d6 \ + --hash=sha256:63d2b10ba7958396ad79bbc24d2f6311484e452daad4637ffd40407983a27069 # via # feast (pyproject.toml) # types-cffi -types-tabulate==0.9.0.20241207 \ - --hash=sha256:ac1ac174750c0a385dfd248edc6279fa328aaf4ea317915ab879a2ec47833230 \ - --hash=sha256:b8dad1343c2a8ba5861c5441370c3e35908edd234ff036d4298708a1d4cf8a85 +types-tabulate==0.10.0.20260308 \ + --hash=sha256:724dcb1330ffba5f46d3cf6e29f45089fccb8e85801e6e7ac9efb1195bf7bea1 \ + --hash=sha256:94a9795965bc6290f844d61e8680a1270040664b88fd12014624090fd847e13c # via feast (pyproject.toml) types-urllib3==1.26.25.14 \ --hash=sha256:229b7f577c951b8c1b92c1bc2b2fdb0b49847bd2af6d1cc2a2e3dd340f3bda8f \ @@ -6115,6 +6136,7 @@ typing-extensions==4.15.0 \ # opentelemetry-api # opentelemetry-sdk # opentelemetry-semantic-conventions + # oracledb # psycopg # psycopg-pool # pydantic @@ -6123,6 +6145,7 @@ typing-extensions==4.15.0 \ # python-docx # python-pptx # referencing + # sentence-transformers # snowflake-connector-python # sqlalchemy # starlette @@ -6152,91 +6175,85 @@ tzlocal==5.3.1 \ # via # great-expectations # trino -ujson==5.11.0 \ - --hash=sha256:0180a480a7d099082501cad1fe85252e4d4bf926b40960fb3d9e87a3a6fbbc80 \ - --hash=sha256:04c41afc195fd477a59db3a84d5b83a871bd648ef371cf8c6f43072d89144eef \ - --hash=sha256:0654a2691fc252c3c525e3d034bb27b8a7546c9d3eb33cd29ce6c9feda361a6a \ - --hash=sha256:090b4d11b380ae25453100b722d0609d5051ffe98f80ec52853ccf8249dfd840 \ - --hash=sha256:109f59885041b14ee9569bf0bb3f98579c3fa0652317b355669939e5fc5ede53 \ - --hash=sha256:10f29e71ecf4ecd93a6610bd8efa8e7b6467454a363c3d6416db65de883eb076 \ - --hash=sha256:1194b943e951092db611011cb8dbdb6cf94a3b816ed07906e14d3bc6ce0e90ab \ - --hash=sha256:12b5e7e22a1fe01058000d1b317d3b65cc3daf61bd2ea7a2b76721fe160fa74d \ - --hash=sha256:16ccb973b7ada0455201808ff11d48fe9c3f034a6ab5bd93b944443c88299f89 \ - --hash=sha256:181fb5b15703a8b9370b25345d2a1fd1359f0f18776b3643d24e13ed9c036d4c \ - --hash=sha256:185f93ebccffebc8baf8302c869fac70dd5dd78694f3b875d03a31b03b062cdb \ - --hash=sha256:1a0a9b76a89827a592656fe12e000cf4f12da9692f51a841a4a07aa4c7ecc41c \ - --hash=sha256:1a325fd2c3a056cf6c8e023f74a0c478dd282a93141356ae7f16d5309f5ff823 \ - --hash=sha256:1aa8a2ab482f09f6c10fba37112af5f957689a79ea598399c85009f2f29898b5 \ - --hash=sha256:1d663b96eb34c93392e9caae19c099ec4133ba21654b081956613327f0e973ac \ - --hash=sha256:29113c003ca33ab71b1b480bde952fbab2a0b6b03a4ee4c3d71687cdcbd1a29d \ - --hash=sha256:30f607c70091483550fbd669a0b37471e5165b317d6c16e75dba2aa967608723 \ - --hash=sha256:3134b783ab314d2298d58cda7e47e7a0f7f71fc6ade6ac86d5dbeaf4b9770fa6 \ - --hash=sha256:34032aeca4510a7c7102bd5933f59a37f63891f30a0706fb46487ab6f0edf8f0 \ - --hash=sha256:3772e4fe6b0c1e025ba3c50841a0ca4786825a4894c8411bf8d3afe3a8061328 \ - --hash=sha256:3d2720e9785f84312b8e2cb0c2b87f1a0b1c53aaab3b2af3ab817d54409012e0 \ - --hash=sha256:416389ec19ef5f2013592f791486bef712ebce0cd59299bf9df1ba40bb2f6e04 \ - --hash=sha256:446e8c11c06048611c9d29ef1237065de0af07cabdd97e6b5b527b957692ec25 \ - --hash=sha256:4598bf3965fc1a936bd84034312bcbe00ba87880ef1ee33e33c1e88f2c398b49 \ - --hash=sha256:48055e1061c1bb1f79e75b4ac39e821f3f35a9b82de17fce92c3140149009bec \ - --hash=sha256:4843f3ab4fe1cc596bb7e02228ef4c25d35b4bb0809d6a260852a4bfcab37ba3 \ - --hash=sha256:49e56ef8066f11b80d620985ae36869a3ff7e4b74c3b6129182ec5d1df0255f3 \ - --hash=sha256:4b42c115c7c6012506e8168315150d1e3f76e7ba0f4f95616f4ee599a1372bbc \ - --hash=sha256:4c9f5d6a27d035dd90a146f7761c2272cf7103de5127c9ab9c4cd39ea61e878a \ - --hash=sha256:5600202a731af24a25e2d7b6eb3f648e4ecd4bb67c4d5cf12f8fab31677469c9 \ - --hash=sha256:65724738c73645db88f70ba1f2e6fb678f913281804d5da2fd02c8c5839af302 \ - --hash=sha256:65f3c279f4ed4bf9131b11972040200c66ae040368abdbb21596bf1564899694 \ - --hash=sha256:674f306e3e6089f92b126eb2fe41bcb65e42a15432c143365c729fdb50518547 \ - --hash=sha256:683f57f0dd3acdd7d9aff1de0528d603aafcb0e6d126e3dc7ce8b020a28f5d01 \ - --hash=sha256:6b6ec7e7321d7fc19abdda3ad809baef935f49673951a8bab486aea975007e02 \ - --hash=sha256:6cd2df62f24c506a0ba322d5e4fe4466d47a9467b57e881ee15a31f7ecf68ff6 \ - --hash=sha256:6dd703c3e86dc6f7044c5ac0b3ae079ed96bf297974598116aa5fb7f655c3a60 \ - --hash=sha256:6eff24e1abd79e0ec6d7eae651dd675ddbc41f9e43e29ef81e16b421da896915 \ - --hash=sha256:7855ccea3f8dad5e66d8445d754fc1cf80265a4272b5f8059ebc7ec29b8d0835 \ - --hash=sha256:787aff4a84da301b7f3bac09bc696e2e5670df829c6f8ecf39916b4e7e24e701 \ - --hash=sha256:7895f0d2d53bd6aea11743bd56e3cb82d729980636cd0ed9b89418bf66591702 \ - --hash=sha256:78c684fb21255b9b90320ba7e199780f653e03f6c2528663768965f4126a5b50 \ - --hash=sha256:7e0ec1646db172beb8d3df4c32a9d78015e671d2000af548252769e33079d9a6 \ - --hash=sha256:7e3cff632c1d78023b15f7e3a81c3745cd3f94c044d1e8fa8efbd6b161997bbc \ - --hash=sha256:7f1a27ab91083b4770e160d17f61b407f587548f2c2b5fbf19f94794c495594a \ - --hash=sha256:80017e870d882d5517d28995b62e4e518a894f932f1e242cbc802a2fd64d365c \ - --hash=sha256:8254e858437c00f17cb72e7a644fc42dad0ebb21ea981b71df6e84b1072aaa7c \ - --hash=sha256:837da4d27fed5fdc1b630bd18f519744b23a0b5ada1bbde1a36ba463f2900c03 \ - --hash=sha256:849e65b696f0d242833f1df4182096cedc50d414215d1371fca85c541fbff629 \ - --hash=sha256:85e6796631165f719084a9af00c79195d3ebf108151452fefdcb1c8bb50f0105 \ - --hash=sha256:86baf341d90b566d61a394869ce77188cc8668f76d7bb2c311d77a00f4bdf844 \ - --hash=sha256:8fa2af7c1459204b7a42e98263b069bd535ea0cd978b4d6982f35af5a04a4241 \ - --hash=sha256:94fcae844f1e302f6f8095c5d1c45a2f0bfb928cccf9f1b99e3ace634b980a2a \ - --hash=sha256:952c0be400229940248c0f5356514123d428cba1946af6fa2bbd7503395fef26 \ - --hash=sha256:99c49400572cd77050894e16864a335225191fd72a818ea6423ae1a06467beac \ - --hash=sha256:9aacbeb23fdbc4b256a7d12e0beb9063a1ba5d9e0dbb2cfe16357c98b4334596 \ - --hash=sha256:a0af6574fc1d9d53f4ff371f58c96673e6d988ed2b5bf666a6143c782fa007e9 \ - --hash=sha256:a31c6b8004438e8c20fc55ac1c0e07dad42941db24176fe9acf2815971f8e752 \ - --hash=sha256:a4df61a6df0a4a8eb5b9b1ffd673429811f50b235539dac586bb7e9e91994138 \ - --hash=sha256:a638425d3c6eed0318df663df44480f4a40dc87cc7c6da44d221418312f6413b \ - --hash=sha256:aa6b3d4f1c0d3f82930f4cbd7fe46d905a4a9205a7c13279789c1263faf06dba \ - --hash=sha256:aa6d7a5e09217ff93234e050e3e380da62b084e26b9f2e277d2606406a2fc2e5 \ - --hash=sha256:ab2cb8351d976e788669c8281465d44d4e94413718af497b4e7342d7b2f78018 \ - --hash=sha256:abae0fb58cc820092a0e9e8ba0051ac4583958495bfa5262a12f628249e3b362 \ - --hash=sha256:b16930f6a0753cdc7d637b33b4e8f10d5e351e1fb83872ba6375f1e87be39746 \ - --hash=sha256:b7b136cc6abc7619124fd897ef75f8e63105298b5ca9bdf43ebd0e1fa0ee105f \ - --hash=sha256:be6b0eaf92cae8cdee4d4c9e074bde43ef1c590ed5ba037ea26c9632fb479c88 \ - --hash=sha256:c44c703842024d796b4c78542a6fcd5c3cb948b9fc2a73ee65b9c86a22ee3638 \ - --hash=sha256:c6618f480f7c9ded05e78a1938873fde68baf96cdd74e6d23c7e0a8441175c4b \ - --hash=sha256:ce076f2df2e1aa62b685086fbad67f2b1d3048369664b4cdccc50707325401f9 \ - --hash=sha256:d06e87eded62ff0e5f5178c916337d2262fdbc03b31688142a3433eabb6511db \ - --hash=sha256:d7c46cb0fe5e7056b9acb748a4c35aa1b428025853032540bb7e41f46767321f \ - --hash=sha256:d8951bb7a505ab2a700e26f691bdfacf395bc7e3111e3416d325b513eea03a58 \ - --hash=sha256:da473b23e3a54448b008d33f742bcd6d5fb2a897e42d1fc6e7bf306ea5d18b1b \ - --hash=sha256:de6e88f62796372fba1de973c11138f197d3e0e1d80bcb2b8aae1e826096d433 \ - --hash=sha256:e204ae6f909f099ba6b6b942131cee359ddda2b6e4ea39c12eb8b991fe2010e0 \ - --hash=sha256:e73df8648c9470af2b6a6bf5250d4744ad2cf3d774dcf8c6e31f018bdd04d764 \ - --hash=sha256:e750c436fb90edf85585f5c62a35b35082502383840962c6983403d1bd96a02c \ - --hash=sha256:e979fbc469a7f77f04ec2f4e853ba00c441bf2b06720aa259f0f720561335e34 \ - --hash=sha256:ecd6ff8a3b5a90c292c2396c2d63c687fd0ecdf17de390d852524393cd9ed052 \ - --hash=sha256:f278b31a7c52eb0947b2db55a5133fbc46b6f0ef49972cd1a80843b72e135aba \ - --hash=sha256:f62b9976fabbcde3ab6e413f4ec2ff017749819a0786d84d7510171109f2d53c \ - --hash=sha256:fa79fdb47701942c2132a9dd2297a1a85941d966d8c87bfd9e29b0cf423f26cc \ - --hash=sha256:fac6c0649d6b7c3682a0a6e18d3de6857977378dce8d419f57a0b20e3d775b39 +ujson==5.12.0 \ + --hash=sha256:006428d3813b87477d72d306c40c09f898a41b968e57b15a7d88454ecc42a3fb \ + --hash=sha256:02f93da7a4115e24f886b04fd56df1ee8741c2ce4ea491b7ab3152f744ad8f8e \ + --hash=sha256:0727363b05ab05ee737a28f6200dc4078bce6b0508e10bd8aab507995a15df61 \ + --hash=sha256:085b6ce182cdd6657481c7c4003a417e0655c4f6e58b76f26ee18f0ae21db827 \ + --hash=sha256:09b4beff9cc91d445d5818632907b85fb06943b61cb346919ce202668bf6794a \ + --hash=sha256:0a3ae28f0b209be5af50b54ca3e2123a3de3a57d87b75f1e5aa3d7961e041983 \ + --hash=sha256:0d2e8db5ade3736a163906154ca686203acc7d1d30736cbf577c730d13653d84 \ + --hash=sha256:0e00cec383eab2406c9e006bd4edb55d284e94bb943fda558326048178d26961 \ + --hash=sha256:0fe6b8b8968e11dd9b2348bd508f0f57cf49ab3512064b36bc4117328218718e \ + --hash=sha256:0fe9128e75c6aa6e9ae06c1408d6edd9179a2fef0fe6d9cda3166b887eba521d \ + --hash=sha256:14b2e1eb528d77bc0f4c5bd1a7ebc05e02b5b41beefb7e8567c9675b8b13bcf4 \ + --hash=sha256:15d416440148f3e56b9b244fdaf8a09fcf5a72e4944b8e119f5bf60417a2bfc8 \ + --hash=sha256:15e555c4caca42411270b2ed2b2ebc7b3a42bb04138cef6c956e1f1d49709fe2 \ + --hash=sha256:16b4fe9c97dc605f5e1887a9e1224287291e35c56cbc379f8aa44b6b7bcfe2bb \ + --hash=sha256:1b5c6ceb65fecd28a1d20d1eba9dbfa992612b86594e4b6d47bb580d2dd6bcb3 \ + --hash=sha256:1d072a403d82aef8090c6d4f728e3a727dfdba1ad3b7fa3a052c3ecbd37e73cb \ + --hash=sha256:2324d9a0502317ffc35d38e153c1b2fa9610ae03775c9d0f8d0cca7b8572b04e \ + --hash=sha256:2a248750abce1c76fbd11b2e1d88b95401e72819295c3b851ec73399d6849b3d \ + --hash=sha256:2ea6206043385343aff0b7da65cf73677f6f5e50de8f1c879e557f4298cac36a \ + --hash=sha256:31348a0ffbfc815ce78daac569d893349d85a0b57e1cd2cdbba50b7f333784da \ + --hash=sha256:38051f36423f084b909aaadb3b41c9c6a2958e86956ba21a8489636911e87504 \ + --hash=sha256:3c2f947e55d3c7cfe124dd4521ee481516f3007d13c6ad4bf6aeb722e190eb1b \ + --hash=sha256:3ed5cb149892141b1e77ef312924a327f2cc718b34247dae346ed66329e1b8be \ + --hash=sha256:3ff4ede90ed771140caa7e1890de17431763a483c54b3c1f88bd30f0cc1affc0 \ + --hash=sha256:40aa43a7a3a8d2f05e79900858053d697a88a605e3887be178b43acbcd781161 \ + --hash=sha256:42d875388fbd091c7ea01edfff260f839ba303038ffb23475ef392012e4d63dd \ + --hash=sha256:457fabc2700a8e6ddb85bc5a1d30d3345fe0d3ec3ee8161a4e032ec585801dfa \ + --hash=sha256:460e76a4daff214ae33ab959494962c93918cb44714ea3e3f748b14aa37f8a87 \ + --hash=sha256:50524f4f6a1c839714dbaff5386a1afb245d2d5ec8213a01fbc99cea7307811e \ + --hash=sha256:51acc750ec7a2df786cdc868fb16fa04abd6269a01d58cf59bafc57978773d8e \ + --hash=sha256:55ede2a7a051b3b7e71a394978a098d71b3783e6b904702ff45483fad434ae2d \ + --hash=sha256:561f89cc82deeae82e37d4a4764184926fb432f740a9691563a391b13f7339a4 \ + --hash=sha256:56ba3f7abbd6b0bb282a544dc38406d1a188d8bb9164f49fdb9c2fee62cb29da \ + --hash=sha256:57930ac9519099b852e190d2c04b1fb5d97ea128db33bce77ed874eccb4c7f09 \ + --hash=sha256:58a11cb49482f1a095a2bd9a1d81dd7c8fb5d2357f959ece85db4e46a825fd00 \ + --hash=sha256:64df53eef4ac857eb5816a56e2885ccf0d7dff6333c94065c93b39c51063e01d \ + --hash=sha256:6879aed770557f0961b252648d36f6fdaab41079d37a2296b5649fd1b35608e0 \ + --hash=sha256:6ad57654570464eb1b040b5c353dee442608e06cff9102b8fcb105565a44c9ed \ + --hash=sha256:6c0aed6a4439994c9666fb8a5b6c4eac94d4ef6ddc95f9b806a599ef83547e3b \ + --hash=sha256:76bf3e7406cf23a3e1ca6a23fb1fb9ea82f4f6bd226fe226e09146b0194f85dc \ + --hash=sha256:7bbf05c38debc90d1a195b11340cc85cb43ab3e753dc47558a3a84a38cbc72da \ + --hash=sha256:7ddb08b3c2f9213df1f2e3eb2fbea4963d80ec0f8de21f0b59898e34f3b3d96d \ + --hash=sha256:7e07f6f644d2c44d53b7a320a084eef98063651912c1b9449b5f45fcbdc6ccd2 \ + --hash=sha256:85833bca01aa5cae326ac759276dc175c5fa3f7b3733b7d543cf27f2df12d1ef \ + --hash=sha256:8712b61eb1b74a4478cfd1c54f576056199e9f093659334aeb5c4a6b385338e5 \ + --hash=sha256:871c0e5102e47995b0e37e8df7819a894a6c3da0d097545cd1f9f1f7d7079927 \ + --hash=sha256:89e302abd3749f6d6699691747969a5d85f7c73081d5ed7e2624c7bd9721a2ab \ + --hash=sha256:937794042342006f707837f38d721426b11b0774d327a2a45c0bd389eb750a87 \ + --hash=sha256:93bc91fdadcf046da37a214eaa714574e7e9b1913568e93bb09527b2ceb7f759 \ + --hash=sha256:94c5f1621cbcab83c03be46441f090b68b9f307b6c7ec44d4e3f6d5997383df4 \ + --hash=sha256:973b7d7145b1ac553a7466a64afa8b31ec2693d7c7fff6a755059e0a2885dfd2 \ + --hash=sha256:99cc80facad240b0c2fb5a633044420878aac87a8e7c348b9486450cba93f27c \ + --hash=sha256:9a5fcbe7b949f2e95c47ea8a80b410fcdf2da61c98553b45a4ee875580418b68 \ + --hash=sha256:9b3b86ec3e818f3dd3e13a9de628e88a9990f4af68ecb0b12dd3de81227f0a26 \ + --hash=sha256:9b3cf13facf6f77c283af0e1713e5e8c47a0fe295af81326cb3cb4380212e797 \ + --hash=sha256:9c5a52987a990eb1bae55f9000994f1afdb0326c154fb089992f839ab3c30688 \ + --hash=sha256:a2d79c6635ccffcbfc1d5c045874ba36b594589be81d50d43472570bb8de9c57 \ + --hash=sha256:a6ec5bf6bc361f2f0f9644907a36ce527715b488988a8df534120e5c34eeda94 \ + --hash=sha256:a7bf9cc97f05048ac8f3e02cd58f0fe62b901453c24345bfde287f4305dcc31c \ + --hash=sha256:ab9056d94e5db513d9313b34394f3a3b83e6301a581c28ad67773434f3faccab \ + --hash=sha256:adf28d13a33f9d750fe7a78fb481cac298fa257d8863d8727b2ea4455ea41235 \ + --hash=sha256:b62cb9a7501e1f5c9ffe190485501349c33e8862dde4377df774e40b8166871f \ + --hash=sha256:bacbd3c69862478cbe1c7ed4325caedec580d8acf31b8ee1b9a1e02a56295cad \ + --hash=sha256:bb349dbba57c76eec25e5917e07f35aabaf0a33b9e67fc13d188002500106487 \ + --hash=sha256:bd03472c36fa3a386a6deb887113b9e3fa40efba8203eb4fe786d3c0ccc724f6 \ + --hash=sha256:bf85a00ac3b56a1e7a19c5be7b02b5180a0895ac4d3c234d717a55e86960691c \ + --hash=sha256:ca0c7ce828bb76ab78b3991904b477c2fd0f711d7815c252d1ef28ff9450b052 \ + --hash=sha256:ccbfd94e59aad4a2566c71912b55f0547ac1680bfac25eb138e6703eb3dd434e \ + --hash=sha256:d1831c07bd4dce53c4b666fa846c7eba4b7c414f2e641a4585b7f50b72f502dc \ + --hash=sha256:d22cad98c2a10bbf6aa083a8980db6ed90d4285a841c4de892890c2b28286ef9 \ + --hash=sha256:d30ad4359413c8821cc7b3707f7ca38aa8bc852ba3b9c5a759ee2d7740157315 \ + --hash=sha256:e0dd3676ea0837cd70ea1879765e9e9f6be063be0436de9b3ea4b775caf83654 \ + --hash=sha256:e584d0cdd37cac355aca52ed788d1a2d939d6837e2870d3b70e585db24025a50 \ + --hash=sha256:e6369ac293d2cc40d52577e4fa3d75a70c1aae2d01fa3580a34a4e6eff9286b9 \ + --hash=sha256:efae5df7a8cc8bdb1037b0f786b044ce281081441df5418c3a0f0e1f86fe7bb3 \ + --hash=sha256:f19b3af31d02a2e79c5f9a6deaab0fb3c116456aeb9277d11720ad433de6dfc6 \ + --hash=sha256:f7a0430d765f9bda043e6aefaba5944d5f21ec43ff4774417d7e296f61917382 \ + --hash=sha256:fb94245a715b4d6e24689de12772b85329a1f9946cbf6187923a64ecdea39e65 # via pymilvus uri-template==1.3.0 \ --hash=sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7 \ @@ -6252,6 +6269,7 @@ urllib3==2.6.3 \ # docker # elastic-transport # great-expectations + # kube-authkit # kubernetes # minio # qdrant-client @@ -6522,9 +6540,9 @@ websockets==16.0 \ --hash=sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da \ --hash=sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4 # via uvicorn -werkzeug==3.1.5 \ - --hash=sha256:5111e36e91086ece91f93268bb39b4a35c1e6f1feac762c9c822ded0a4e322dc \ - --hash=sha256:6a548b0e88955dd07ccb25539d7d0cc97417ee9e179677d22c7041c8f078ce67 +werkzeug==3.1.8 \ + --hash=sha256:63a77fb8892bf28ebc3178683445222aa500e48ebad5ec77b0ad80f8726b1f50 \ + --hash=sha256:9bad61a4268dac112f1c5cd4630a56ede601b6ed420300677a869083d70a4c44 # via moto wheel==0.46.3 \ --hash=sha256:4b399d56c9d9338230118d705d9737a2a468ccca63d5e813e2a4fc7815d8bc4d \ @@ -6626,9 +6644,9 @@ xlsxwriter==3.2.9 \ --hash=sha256:254b1c37a368c444eac6e2f867405cc9e461b0ed97a3233b2ac1e574efb4140c \ --hash=sha256:9a5db42bc5dff014806c58a20b9eae7322a134abb6fce3c92c181bfb275ec5b3 # via python-pptx -xmltodict==1.0.3 \ - --hash=sha256:35d65d5c08f2a1121df338a0c4e49ca638480fa7c1b899ded45e0759bf32e40e \ - --hash=sha256:3bf1f49c7836df34cf6d9cc7e690c4351f7dfff2ab0b8a1988bba4a9b9474909 +xmltodict==1.0.4 \ + --hash=sha256:6d94c9f834dd9e44514162799d344d815a3a4faec913717a9ecbfa5be1bb8e61 \ + --hash=sha256:a4a00d300b0e1c59fc2bfccb53d7b2e88c32f200df138a0dd2229f842497026a # via moto xxhash==3.6.0 \ --hash=sha256:01262da8798422d0685f7cef03b2bd3f4f46511b02830861df548d7def4402ad \ @@ -6772,137 +6790,135 @@ xxhash==3.6.0 \ --hash=sha256:fba27a198363a7ef87f8c0f6b171ec36b674fe9053742c58dd7e3201c1ab30ee \ --hash=sha256:ffc578717a347baf25be8397cb10d2528802d24f94cfc005c0e44fef44b5cdd6 # via datasets -yarl==1.22.0 \ - --hash=sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a \ - --hash=sha256:029866bde8d7b0878b9c160e72305bbf0a7342bcd20b9999381704ae03308dc8 \ - --hash=sha256:078278b9b0b11568937d9509b589ee83ef98ed6d561dfe2020e24a9fd08eaa2b \ - --hash=sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da \ - --hash=sha256:07a524d84df0c10f41e3ee918846e1974aba4ec017f990dc735aad487a0bdfdf \ - --hash=sha256:088e4e08f033db4be2ccd1f34cf29fe994772fb54cfe004bbf54db320af56890 \ - --hash=sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093 \ - --hash=sha256:0cf71bf877efeac18b38d3930594c0948c82b64547c1cf420ba48722fe5509f6 \ - --hash=sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79 \ - --hash=sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683 \ - --hash=sha256:10619d9fdee46d20edc49d3479e2f8269d0779f1b031e6f7c2aa1c76be04b7ed \ - --hash=sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2 \ - --hash=sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff \ - --hash=sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02 \ - --hash=sha256:14291620375b1060613f4aab9ebf21850058b6b1b438f386cc814813d901c60b \ - --hash=sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03 \ - --hash=sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511 \ - --hash=sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c \ - --hash=sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124 \ - --hash=sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c \ - --hash=sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da \ - --hash=sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2 \ - --hash=sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0 \ - --hash=sha256:2e4e1f6f0b4da23e61188676e3ed027ef0baa833a2e633c29ff8530800edccba \ - --hash=sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d \ - --hash=sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53 \ - --hash=sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138 \ - --hash=sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4 \ - --hash=sha256:3aa27acb6de7a23785d81557577491f6c38a5209a254d1191519d07d8fe51748 \ - --hash=sha256:3b06bcadaac49c70f4c88af4ffcfbe3dc155aab3163e75777818092478bcbbe7 \ - --hash=sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d \ - --hash=sha256:3e2daa88dc91870215961e96a039ec73e4937da13cf77ce17f9cad0c18df3503 \ - --hash=sha256:3ea66b1c11c9150f1372f69afb6b8116f2dd7286f38e14ea71a44eee9ec51b9d \ - --hash=sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2 \ - --hash=sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa \ - --hash=sha256:437840083abe022c978470b942ff832c3940b2ad3734d424b7eaffcd07f76737 \ - --hash=sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f \ - --hash=sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1 \ - --hash=sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d \ - --hash=sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694 \ - --hash=sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3 \ - --hash=sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a \ - --hash=sha256:4c52a6e78aef5cf47a98ef8e934755abf53953379b7d53e68b15ff4420e6683d \ - --hash=sha256:4dcc74149ccc8bba31ce1944acee24813e93cfdee2acda3c172df844948ddf7b \ - --hash=sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a \ - --hash=sha256:51af598701f5299012b8416486b40fceef8c26fc87dc6d7d1f6fc30609ea0aa6 \ - --hash=sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b \ - --hash=sha256:595697f68bd1f0c1c159fcb97b661fc9c3f5db46498043555d04805430e79bea \ - --hash=sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5 \ - --hash=sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f \ - --hash=sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df \ - --hash=sha256:5cdac20da754f3a723cceea5b3448e1a2074866406adeb4ef35b469d089adb8f \ - --hash=sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b \ - --hash=sha256:5dbeefd6ca588b33576a01b0ad58aa934bc1b41ef89dee505bf2932b22ddffba \ - --hash=sha256:62441e55958977b8167b2709c164c91a6363e25da322d87ae6dd9c6019ceecf9 \ - --hash=sha256:663e1cadaddae26be034a6ab6072449a8426ddb03d500f43daf952b74553bba0 \ - --hash=sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6 \ - --hash=sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b \ - --hash=sha256:6944b2dc72c4d7f7052683487e3677456050ff77fcf5e6204e98caf785ad1967 \ - --hash=sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2 \ - --hash=sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708 \ - --hash=sha256:6dcbb0829c671f305be48a7227918cfcd11276c2d637a8033a99a02b67bf9eda \ - --hash=sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8 \ - --hash=sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10 \ - --hash=sha256:75976c6945d85dbb9ee6308cd7ff7b1fb9409380c82d6119bd778d8fcfe2931c \ - --hash=sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b \ - --hash=sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028 \ - --hash=sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e \ - --hash=sha256:80ddf7a5f8c86cb3eb4bc9028b07bbbf1f08a96c5c0bc1244be5e8fefcb94147 \ - --hash=sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33 \ - --hash=sha256:84fc3ec96fce86ce5aa305eb4aa9358279d1aa644b71fab7b8ed33fe3ba1a7ca \ - --hash=sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590 \ - --hash=sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c \ - --hash=sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53 \ - --hash=sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74 \ - --hash=sha256:99b6fc1d55782461b78221e95fc357b47ad98b041e8e20f47c1411d0aacddc60 \ - --hash=sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f \ - --hash=sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1 \ - --hash=sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27 \ - --hash=sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520 \ - --hash=sha256:a4fcfc8eb2c34148c118dfa02e6427ca278bfd0f3df7c5f99e33d2c0e81eae3e \ - --hash=sha256:a899cbd98dce6f5d8de1aad31cb712ec0a530abc0a86bd6edaa47c1090138467 \ - --hash=sha256:a9b1ba5610a4e20f655258d5a1fdc7ebe3d837bb0e45b581398b99eb98b1f5ca \ - --hash=sha256:af74f05666a5e531289cb1cc9c883d1de2088b8e5b4de48004e5ca8a830ac859 \ - --hash=sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273 \ - --hash=sha256:b266bd01fedeffeeac01a79ae181719ff848a5a13ce10075adbefc8f1daee70e \ - --hash=sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601 \ - --hash=sha256:b580e71cac3f8113d3135888770903eaf2f507e9421e5697d6ee6d8cd1c7f054 \ - --hash=sha256:b6a6f620cfe13ccec221fa312139135166e47ae169f8253f72a0abc0dae94376 \ - --hash=sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7 \ - --hash=sha256:b85b982afde6df99ecc996990d4ad7ccbdbb70e2a4ba4de0aecde5922ba98a0b \ - --hash=sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb \ - --hash=sha256:ba440ae430c00eee41509353628600212112cd5018d5def7e9b05ea7ac34eb65 \ - --hash=sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784 \ - --hash=sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71 \ - --hash=sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b \ - --hash=sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a \ - --hash=sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c \ - --hash=sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face \ - --hash=sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d \ - --hash=sha256:c7bd6683587567e5a49ee6e336e0612bec8329be1b7d4c8af5687dcdeb67ee1e \ - --hash=sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e \ - --hash=sha256:cb95a9b1adaa48e41815a55ae740cfda005758104049a640a398120bf02515ca \ - --hash=sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9 \ - --hash=sha256:d332fc2e3c94dad927f2112395772a4e4fedbcf8f80efc21ed7cdfae4d574fdb \ - --hash=sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95 \ - --hash=sha256:d5372ca1df0f91a86b047d1277c2aaf1edb32d78bbcefffc81b40ffd18f027ed \ - --hash=sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf \ - --hash=sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca \ - --hash=sha256:dd7afd3f8b0bfb4e0d9fc3c31bfe8a4ec7debe124cfd90619305def3c8ca8cd2 \ - --hash=sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62 \ - --hash=sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df \ - --hash=sha256:e1b329cb8146d7b736677a2440e422eadd775d1806a81db2d4cded80a48efc1a \ - --hash=sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67 \ - --hash=sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f \ - --hash=sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529 \ - --hash=sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486 \ - --hash=sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a \ - --hash=sha256:e6438cc8f23a9c1478633d216b16104a586b9761db62bfacb6425bac0a36679e \ - --hash=sha256:e81fda2fb4a07eda1a2252b216aa0df23ebcd4d584894e9612e80999a78fd95b \ - --hash=sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74 \ - --hash=sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d \ - --hash=sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b \ - --hash=sha256:f0d97c18dfd9a9af4490631905a3f131a8e4c9e80a39353919e2cfed8f00aedc \ - --hash=sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2 \ - --hash=sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e \ - --hash=sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8 \ - --hash=sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82 \ - --hash=sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd \ - --hash=sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249 +yarl==1.23.0 \ + --hash=sha256:03214408cfa590df47728b84c679ae4ef00be2428e11630277be0727eba2d7cc \ + --hash=sha256:041b1a4cefacf65840b4e295c6985f334ba83c30607441ae3cf206a0eed1a2e4 \ + --hash=sha256:0793e2bd0cf14234983bbb371591e6bea9e876ddf6896cdcc93450996b0b5c85 \ + --hash=sha256:0e1fdaa14ef51366d7757b45bde294e95f6c8c049194e793eedb8387c86d5993 \ + --hash=sha256:0e40111274f340d32ebcc0a5668d54d2b552a6cca84c9475859d364b380e3222 \ + --hash=sha256:115136c4a426f9da976187d238e84139ff6b51a20839aa6e3720cd1026d768de \ + --hash=sha256:13a563739ae600a631c36ce096615fe307f131344588b0bc0daec108cdb47b25 \ + --hash=sha256:16c6994ac35c3e74fb0ae93323bf8b9c2a9088d55946109489667c510a7d010e \ + --hash=sha256:170e26584b060879e29fac213e4228ef063f39128723807a312e5c7fec28eff2 \ + --hash=sha256:17235362f580149742739cc3828b80e24029d08cbb9c4bda0242c7b5bc610a8e \ + --hash=sha256:1932b6b8bba8d0160a9d1078aae5838a66039e8832d41d2992daa9a3a08f7860 \ + --hash=sha256:1b6b572edd95b4fa8df75de10b04bc81acc87c1c7d16bcdd2035b09d30acc957 \ + --hash=sha256:1c3a3598a832590c5a3ce56ab5576361b5688c12cb1d39429cf5dba30b510760 \ + --hash=sha256:1c57676bdedc94cd3bc37724cf6f8cd2779f02f6aba48de45feca073e714fe52 \ + --hash=sha256:1dc702e42d0684f42d6519c8d581e49c96cefaaab16691f03566d30658ee8788 \ + --hash=sha256:21d1b7305a71a15b4794b5ff22e8eef96ff4a6d7f9657155e5aa419444b28912 \ + --hash=sha256:23f371bd662cf44a7630d4d113101eafc0cfa7518a2760d20760b26021454719 \ + --hash=sha256:2569b67d616eab450d262ca7cb9f9e19d2f718c70a8b88712859359d0ab17035 \ + --hash=sha256:263cd4f47159c09b8b685890af949195b51d1aa82ba451c5847ca9bc6413c220 \ + --hash=sha256:2803ed8b21ca47a43da80a6fd1ed3019d30061f7061daa35ac54f63933409412 \ + --hash=sha256:2a6940a074fb3c48356ed0158a3ca5699c955ee4185b4d7d619be3c327143e05 \ + --hash=sha256:2e27c8841126e017dd2a054a95771569e6070b9ee1b133366d8b31beb5018a41 \ + --hash=sha256:31c9921eb8bd12633b41ad27686bbb0b1a2a9b8452bfdf221e34f311e9942ed4 \ + --hash=sha256:34b6cf500e61c90f305094911f9acc9c86da1a05a7a3f5be9f68817043f486e4 \ + --hash=sha256:3650dc2480f94f7116c364096bc84b1d602f44224ef7d5c7208425915c0475dd \ + --hash=sha256:389871e65468400d6283c0308e791a640b5ab5c83bcee02a2f51295f95e09748 \ + --hash=sha256:39004f0ad156da43e86aa71f44e033de68a44e5a31fc53507b36dd253970054a \ + --hash=sha256:394906945aa8b19fc14a61cf69743a868bb8c465efe85eee687109cc540b98f4 \ + --hash=sha256:3ceb13c5c858d01321b5d9bb65e4cf37a92169ea470b70fec6f236b2c9dd7e34 \ + --hash=sha256:411225bae281f114067578891bc75534cfb3d92a3b4dfef7a6ca78ba354e6069 \ + --hash=sha256:44bb7bef4ea409384e3f8bc36c063d77ea1b8d4a5b2706956c0d6695f07dcc25 \ + --hash=sha256:4503053d296bc6e4cbd1fad61cf3b6e33b939886c4f249ba7c78b602214fabe2 \ + --hash=sha256:4764a6a7588561a9aef92f65bda2c4fb58fe7c675c0883862e6df97559de0bfb \ + --hash=sha256:4966242ec68afc74c122f8459abd597afd7d8a60dc93d695c1334c5fd25f762f \ + --hash=sha256:4a42e651629dafb64fd5b0286a3580613702b5809ad3f24934ea87595804f2c5 \ + --hash=sha256:4a59ba56f340334766f3a4442e0efd0af895fae9e2b204741ef885c446b3a1a8 \ + --hash=sha256:4c41e021bc6d7affb3364dc1e1e5fa9582b470f283748784bd6ea0558f87f42c \ + --hash=sha256:5023346c4ee7992febc0068e7593de5fa2bf611848c08404b35ebbb76b1b0512 \ + --hash=sha256:50f9d8d531dfb767c565f348f33dd5139a6c43f5cbdf3f67da40d54241df93f6 \ + --hash=sha256:51430653db848d258336cfa0244427b17d12db63d42603a55f0d4546f50f25b5 \ + --hash=sha256:531ef597132086b6cf96faa7c6c1dcd0361dd5f1694e5cc30375907b9b7d3ea9 \ + --hash=sha256:53ad387048f6f09a8969631e4de3f1bf70c50e93545d64af4f751b2498755072 \ + --hash=sha256:53b1ea6ca88ebd4420379c330aea57e258408dd0df9af0992e5de2078dc9f5d5 \ + --hash=sha256:575aa4405a656e61a540f4a80eaa5260f2a38fff7bfdc4b5f611840d76e9e277 \ + --hash=sha256:578110dd426f0d209d1509244e6d4a3f1a3e9077655d98c5f22583d63252a08a \ + --hash=sha256:5ec2f42d41ccbd5df0270d7df31618a8ee267bfa50997f5d720ddba86c4a83a6 \ + --hash=sha256:5ee586fb17ff8f90c91cf73c6108a434b02d69925f44f5f8e0d7f2f260607eae \ + --hash=sha256:5f10fd85e4b75967468af655228fbfd212bdf66db1c0d135065ce288982eda26 \ + --hash=sha256:609d3614d78d74ebe35f54953c5bbd2ac647a7ddb9c30a5d877580f5e86b22f2 \ + --hash=sha256:62694e275c93d54f7ccedcfef57d42761b2aad5234b6be1f3e3026cae4001cd4 \ + --hash=sha256:63e92247f383c85ab00dd0091e8c3fa331a96e865459f5ee80353c70a4a42d70 \ + --hash=sha256:682bae25f0a0dd23a056739f23a134db9f52a63e2afd6bfb37ddc76292bbd723 \ + --hash=sha256:6b41389c19b07c760c7e427a3462e8ab83c4bb087d127f0e854c706ce1b9215c \ + --hash=sha256:6e87a6e8735b44816e7db0b2fbc9686932df473c826b0d9743148432e10bb9b9 \ + --hash=sha256:6f0fd84de0c957b2d280143522c4f91a73aada1923caee763e24a2b3fda9f8a5 \ + --hash=sha256:70efd20be968c76ece7baa8dafe04c5be06abc57f754d6f36f3741f7aa7a208e \ + --hash=sha256:71d006bee8397a4a89f469b8deb22469fe7508132d3c17fa6ed871e79832691c \ + --hash=sha256:73309162a6a571d4cbd3b6a1dcc703c7311843ae0d1578df6f09be4e98df38d4 \ + --hash=sha256:75e3026ab649bf48f9a10c0134512638725b521340293f202a69b567518d94e0 \ + --hash=sha256:76855800ac56f878847a09ce6dba727c93ca2d89c9e9d63002d26b916810b0a2 \ + --hash=sha256:7c6b9461a2a8b47c65eef63bb1c76a4f1c119618ffa99ea79bc5bb1e46c5821b \ + --hash=sha256:803a3c3ce4acc62eaf01eaca1208dcf0783025ef27572c3336502b9c232005e7 \ + --hash=sha256:80e6d33a3d42a7549b409f199857b4fb54e2103fc44fb87605b6663b7a7ff750 \ + --hash=sha256:8419ebd326430d1cbb7efb5292330a2cf39114e82df5cc3d83c9a0d5ebeaf2f2 \ + --hash=sha256:85610b4f27f69984932a7abbe52703688de3724d9f72bceb1cca667deff27474 \ + --hash=sha256:85e9beda1f591bc73e77ea1c51965c68e98dafd0fec72cdd745f77d727466716 \ + --hash=sha256:877b0738624280e34c55680d6054a307aa94f7d52fa0e3034a9cc6e790871da7 \ + --hash=sha256:88f9fb0116fbfcefcab70f85cf4b74a2b6ce5d199c41345296f49d974ddb4123 \ + --hash=sha256:8c4fe09e0780c6c3bf2b7d4af02ee2394439d11a523bbcf095cf4747c2932007 \ + --hash=sha256:93a784271881035ab4406a172edb0faecb6e7d00f4b53dc2f55919d6c9688595 \ + --hash=sha256:94f8575fbdf81749008d980c17796097e645574a3b8c28ee313931068dad14fe \ + --hash=sha256:95451e6ce06c3e104556d73b559f5da6c34a069b6b62946d3ad66afcd51642ea \ + --hash=sha256:99c8a9ed30f4164bc4c14b37a90208836cbf50d4ce2a57c71d0f52c7fb4f7598 \ + --hash=sha256:9a18d6f9359e45722c064c97464ec883eb0e0366d33eda61cb19a244bf222679 \ + --hash=sha256:9cbf44c5cb4a7633d078788e1b56387e3d3cf2b8139a3be38040b22d6c3221c8 \ + --hash=sha256:9ee33b875f0b390564c1fb7bc528abf18c8ee6073b201c6ae8524aca778e2d83 \ + --hash=sha256:a0e317df055958a0c1e79e5d2aa5a5eaa4a6d05a20d4b0c9c3f48918139c9fc6 \ + --hash=sha256:a2df6afe50dea8ae15fa34c9f824a3ee958d785fd5d089063d960bae1daa0a3f \ + --hash=sha256:a31de1613658308efdb21ada98cbc86a97c181aa050ba22a808120bb5be3ab94 \ + --hash=sha256:a3d2bff8f37f8d0f96c7ec554d16945050d54462d6e95414babaa18bfafc7f51 \ + --hash=sha256:a41bcf68efd19073376eb8cf948b8d9be0af26256403e512bb18f3966f1f9120 \ + --hash=sha256:a82836cab5f197a0514235aaf7ffccdc886ccdaa2324bc0aafdd4ae898103039 \ + --hash=sha256:a8d00f29b42f534cc8aa3931cfe773b13b23e561e10d2b26f27a8d309b0e82a1 \ + --hash=sha256:aafe5dcfda86c8af00386d7781d4c2181b5011b7be3f2add5e99899ea925df05 \ + --hash=sha256:ab5f043cb8a2d71c981c09c510da013bc79fd661f5c60139f00dd3c3cc4f2ffb \ + --hash=sha256:ac09d42f48f80c9ee1635b2fcaa819496a44502737660d3c0f2ade7526d29144 \ + --hash=sha256:aecfed0b41aa72b7881712c65cf764e39ce2ec352324f5e0837c7048d9e6daaa \ + --hash=sha256:b2c6b50c7b0464165472b56b42d4c76a7b864597007d9c085e8b63e185cf4a7a \ + --hash=sha256:b35d13d549077713e4414f927cdc388d62e543987c572baee613bf82f11a4b99 \ + --hash=sha256:b39cb32a6582750b6cc77bfb3c49c0f8760dc18dc96ec9fb55fbb0f04e08b928 \ + --hash=sha256:b5405bb8f0e783a988172993cfc627e4d9d00432d6bbac65a923041edacf997d \ + --hash=sha256:baaf55442359053c7d62f6f8413a62adba3205119bcb6f49594894d8be47e5e3 \ + --hash=sha256:bd654fad46d8d9e823afbb4f87c79160b5a374ed1ff5bde24e542e6ba8f41434 \ + --hash=sha256:be61f6fff406ca40e3b1d84716fde398fc08bc63dd96d15f3a14230a0973ed86 \ + --hash=sha256:bf49a3ae946a87083ef3a34c8f677ae4243f5b824bfc4c69672e72b3d6719d46 \ + --hash=sha256:c4a80f77dc1acaaa61f0934176fccca7096d9b1ff08c8ba9cddf5ae034a24319 \ + --hash=sha256:c75eb09e8d55bceb4367e83496ff8ef2bc7ea6960efb38e978e8073ea59ecb67 \ + --hash=sha256:c7f8dc16c498ff06497c015642333219871effba93e4a2e8604a06264aca5c5c \ + --hash=sha256:c8aa34a5c864db1087d911a0b902d60d203ea3607d91f615acd3f3108ac32169 \ + --hash=sha256:cbb0fef01f0c6b38cb0f39b1f78fc90b807e0e3c86a7ff3ce74ad77ce5c7880c \ + --hash=sha256:cde9a2ecd91668bcb7f077c4966d8ceddb60af01b52e6e3e2680e4cf00ad1a59 \ + --hash=sha256:cff6d44cb13d39db2663a22b22305d10855efa0fa8015ddeacc40bc59b9d8107 \ + --hash=sha256:d1009abedb49ae95b136a8904a3f71b342f849ffeced2d3747bf29caeda218c4 \ + --hash=sha256:d38c1e8231722c4ce40d7593f28d92b5fc72f3e9774fe73d7e800ec32299f63a \ + --hash=sha256:d53834e23c015ee83a99377db6e5e37d8484f333edb03bd15b4bc312cc7254fb \ + --hash=sha256:d7504f2b476d21653e4d143f44a175f7f751cd41233525312696c76aa3dbb23f \ + --hash=sha256:dbf507e9ef5688bada447a24d68b4b58dd389ba93b7afc065a2ba892bea54769 \ + --hash=sha256:dc52310451fc7c629e13c4e061cbe2dd01684d91f2f8ee2821b083c58bd72432 \ + --hash=sha256:dd00607bffbf30250fe108065f07453ec124dbf223420f57f5e749b04295e090 \ + --hash=sha256:dda608c88cf709b1d406bdfcd84d8d63cff7c9e577a403c6108ce8ce9dcc8764 \ + --hash=sha256:debe9c4f41c32990771be5c22b56f810659f9ddf3d63f67abfdcaa2c6c9c5c1d \ + --hash=sha256:e09fd068c2e169a7070d83d3bde728a4d48de0549f975290be3c108c02e499b4 \ + --hash=sha256:e0fd068364a6759bc794459f0a735ab151d11304346332489c7972bacbe9e72b \ + --hash=sha256:e4c53f8347cd4200f0d70a48ad059cabaf24f5adc6ba08622a23423bc7efa10d \ + --hash=sha256:e5723c01a56c5028c807c701aa66722916d2747ad737a046853f6c46f4875543 \ + --hash=sha256:e7b0460976dc75cb87ad9cc1f9899a4b97751e7d4e77ab840fc9b6d377b8fd24 \ + --hash=sha256:e9d9a4d06d3481eab79803beb4d9bd6f6a8e781ec078ac70d7ef2dcc29d1bea5 \ + --hash=sha256:ead11956716a940c1abc816b7df3fa2b84d06eaed8832ca32f5c5e058c65506b \ + --hash=sha256:ed5f69ce7be7902e5c70ea19eb72d20abf7d725ab5d49777d696e32d4fc1811d \ + --hash=sha256:f2af5c81a1f124609d5f33507082fc3f739959d4719b56877ab1ee7e7b3d602b \ + --hash=sha256:f40e782d49630ad384db66d4d8b73ff4f1b8955dc12e26b09a3e3af064b3b9d6 \ + --hash=sha256:f514f6474e04179d3d33175ed3f3e31434d3130d42ec153540d5b157deefd735 \ + --hash=sha256:f69f57305656a4852f2a7203efc661d8c042e6cc67f7acd97d8667fb448a426e \ + --hash=sha256:fb1e8b8d66c278b21d13b0a7ca22c41dd757a7c209c6b12c313e445c31dd3b28 \ + --hash=sha256:fb4948814a2a98e3912505f09c9e7493b1506226afb1f881825368d6fb776ee3 \ + --hash=sha256:fda207c815b253e34f7e1909840fd14299567b1c0eb4908f8c2ce01a41265401 \ + --hash=sha256:fe8f8f5e70e6dbdfca9882cd9deaac058729bcf323cf7a58660901e55c9c94f6 \ + --hash=sha256:fffc45637bcd6538de8b85f51e3df3223e4ad89bccbfca0481c08c7fc8b7ed7d # via aiohttp zipp==3.23.0 \ --hash=sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e \ diff --git a/sdk/python/requirements/py3.12-minimal-requirements.txt b/sdk/python/requirements/py3.12-minimal-requirements.txt index ca3934a0e20..71c61613cb2 100644 --- a/sdk/python/requirements/py3.12-minimal-requirements.txt +++ b/sdk/python/requirements/py3.12-minimal-requirements.txt @@ -8,127 +8,127 @@ aiohappyeyeballs==2.6.1 \ --hash=sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558 \ --hash=sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8 # via aiohttp -aiohttp==3.13.3 \ - --hash=sha256:01ad2529d4b5035578f5081606a465f3b814c542882804e2e8cda61adf5c71bf \ - --hash=sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c \ - --hash=sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c \ - --hash=sha256:084911a532763e9d3dd95adf78a78f4096cd5f58cdc18e6fdbc1b58417a45423 \ - --hash=sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f \ - --hash=sha256:0db318f7a6f065d84cb1e02662c526294450b314a02bd9e2a8e67f0d8564ce40 \ - --hash=sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2 \ - --hash=sha256:1449ceddcdbcf2e0446957863af03ebaaa03f94c090f945411b61269e2cb5daf \ - --hash=sha256:147e422fd1223005c22b4fe080f5d93ced44460f5f9c105406b753612b587821 \ - --hash=sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64 \ - --hash=sha256:215a685b6fbbfcf71dfe96e3eba7a6f58f10da1dfdf4889c7dd856abe430dca7 \ - --hash=sha256:2712039939ec963c237286113c68dbad80a82a4281543f3abf766d9d73228998 \ - --hash=sha256:27234ef6d85c914f9efeb77ff616dbf4ad2380be0cda40b4db086ffc7ddd1b7d \ - --hash=sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea \ - --hash=sha256:2b8d8ddba8f95ba17582226f80e2de99c7a7948e66490ef8d947e272a93e9463 \ - --hash=sha256:2ba0eea45eb5cc3172dbfc497c066f19c41bac70963ea1a67d51fc92e4cf9a80 \ - --hash=sha256:2be0e9ccf23e8a94f6f0650ce06042cefc6ac703d0d7ab6c7a917289f2539ad4 \ - --hash=sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767 \ - --hash=sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43 \ - --hash=sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592 \ - --hash=sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a \ - --hash=sha256:31a83ea4aead760dfcb6962efb1d861db48c34379f2ff72db9ddddd4cda9ea2e \ - --hash=sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687 \ - --hash=sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8 \ - --hash=sha256:37239e9f9a7ea9ac5bf6b92b0260b01f8a22281996da609206a84df860bc1261 \ - --hash=sha256:37da61e244d1749798c151421602884db5270faf479cf0ef03af0ff68954c9dd \ - --hash=sha256:3b61b7169ababd7802f9568ed96142616a9118dd2be0d1866e920e77ec8fa92a \ - --hash=sha256:3d9908a48eb7416dc1f4524e69f1d32e5d90e3981e4e37eb0aa1cd18f9cfa2a4 \ - --hash=sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587 \ - --hash=sha256:4021b51936308aeea0367b8f006dc999ca02bc118a0cc78c303f50a2ff6afb91 \ - --hash=sha256:40c5e40ecc29ba010656c18052b877a1c28f84344825efa106705e835c28530f \ - --hash=sha256:425c126c0dc43861e22cb1c14ba4c8e45d09516d0a3ae0a3f7494b79f5f233a3 \ - --hash=sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344 \ - --hash=sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6 \ - --hash=sha256:49a03727c1bba9a97d3e93c9f93ca03a57300f484b6e935463099841261195d3 \ - --hash=sha256:4ae5b5a0e1926e504c81c5b84353e7a5516d8778fbbff00429fe7b05bb25cbce \ - --hash=sha256:4e239d501f73d6db1522599e14b9b321a7e3b1de66ce33d53a765d975e9f4808 \ - --hash=sha256:56339a36b9f1fc708260c76c87e593e2afb30d26de9ae1eb445b5e051b98a7a1 \ - --hash=sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29 \ - --hash=sha256:5b179331a481cb5529fca8b432d8d3c7001cb217513c94cd72d668d1248688a3 \ - --hash=sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b \ - --hash=sha256:5d2d94f1f5fcbe40838ac51a6ab5704a6f9ea42e72ceda48de5e6b898521da51 \ - --hash=sha256:5dff64413671b0d3e7d5918ea490bdccb97a4ad29b3f311ed423200b2203e01c \ - --hash=sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926 \ - --hash=sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64 \ - --hash=sha256:642f752c3eb117b105acbd87e2c143de710987e09860d674e068c4c2c441034f \ - --hash=sha256:65d2ccb7eabee90ce0503c17716fc77226be026dcc3e65cce859a30db715025b \ - --hash=sha256:693781c45a4033d31d4187d2436f5ac701e7bbfe5df40d917736108c1cc7436e \ - --hash=sha256:694976222c711d1d00ba131904beb60534f93966562f64440d0c9d41b8cdb440 \ - --hash=sha256:697753042d57f4bf7122cab985bf15d0cef23c770864580f5af4f52023a56bd6 \ - --hash=sha256:69c56fbc1993fa17043e24a546959c0178fe2b5782405ad4559e6c13975c15e3 \ - --hash=sha256:6de499a1a44e7de70735d0b39f67c8f25eb3d91eb3103be99ca0fa882cdd987d \ - --hash=sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415 \ - --hash=sha256:75ca857eba4e20ce9f546cd59c7007b33906a4cd48f2ff6ccf1ccfc3b646f279 \ - --hash=sha256:7a4a94eb787e606d0a09404b9c38c113d3b099d508021faa615d70a0131907ce \ - --hash=sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603 \ - --hash=sha256:7bfdc049127717581866fa4708791220970ce291c23e28ccf3922c700740fdc0 \ - --hash=sha256:7e63f210bc1b57ef699035f2b4b6d9ce096b5914414a49b0997c839b2bd2223c \ - --hash=sha256:7f9120f7093c2a32d9647abcaf21e6ad275b4fbec5b55969f978b1a97c7c86bf \ - --hash=sha256:8057c98e0c8472d8846b9c79f56766bcc57e3e8ac7bfd510482332366c56c591 \ - --hash=sha256:80dd4c21b0f6237676449c6baaa1039abae86b91636b6c91a7f8e61c87f89540 \ - --hash=sha256:81e97251d9298386c2b7dbeb490d3d1badbdc69107fb8c9299dd04eb39bddc0e \ - --hash=sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26 \ - --hash=sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a \ - --hash=sha256:859bd3f2156e81dd01432f5849fc73e2243d4a487c4fd26609b1299534ee1845 \ - --hash=sha256:87797e645d9d8e222e04160ee32aa06bc5c163e8499f24db719e7852ec23093a \ - --hash=sha256:87b9aab6d6ed88235aa2970294f496ff1a1f9adcd724d800e9b952395a80ffd9 \ - --hash=sha256:8a60e60746623925eab7d25823329941aee7242d559baa119ca2b253c88a7bd6 \ - --hash=sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba \ - --hash=sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df \ - --hash=sha256:947c26539750deeaee933b000fb6517cc770bbd064bad6033f1cff4803881e43 \ - --hash=sha256:96d604498a7c782cb15a51c406acaea70d8c027ee6b90c569baa6e7b93073679 \ - --hash=sha256:988a8c5e317544fdf0d39871559e67b6341065b87fceac641108c2096d5506b7 \ - --hash=sha256:9a9dc347e5a3dc7dfdbc1f82da0ef29e388ddb2ed281bfce9dd8248a313e62b7 \ - --hash=sha256:9ae8dd55c8e6c4257eae3a20fd2c8f41edaea5992ed67156642493b8daf3cecc \ - --hash=sha256:9af5e68ee47d6534d36791bbe9b646d2a7c7deb6fc24d7943628edfbb3581f29 \ - --hash=sha256:9b174f267b5cfb9a7dba9ee6859cecd234e9a681841eb85068059bc867fb8f02 \ - --hash=sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984 \ - --hash=sha256:9d4c940f02f49483b18b079d1c27ab948721852b281f8b015c058100e9421dd1 \ - --hash=sha256:9ebf57d09e131f5323464bd347135a88622d1c0976e88ce15b670e7ad57e4bd6 \ - --hash=sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632 \ - --hash=sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56 \ - --hash=sha256:a2212ad43c0833a873d0fb3c63fa1bacedd4cf6af2fee62bf4b739ceec3ab239 \ - --hash=sha256:a45530014d7a1e09f4a55f4f43097ba0fd155089372e105e4bff4ca76cb1b168 \ - --hash=sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88 \ - --hash=sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc \ - --hash=sha256:af71fff7bac6bb7508956696dce8f6eec2bbb045eceb40343944b1ae62b5ef11 \ - --hash=sha256:b04be762396457bef43f3597c991e192ee7da460a4953d7e647ee4b1c28e7046 \ - --hash=sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0 \ - --hash=sha256:b1a6102b4d3ebc07dad44fbf07b45bb600300f15b552ddf1851b5390202ea2e3 \ - --hash=sha256:b46020d11d23fe16551466c77823df9cc2f2c1e63cc965daf67fa5eec6ca1877 \ - --hash=sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1 \ - --hash=sha256:b903a4dfee7d347e2d87697d0713be59e0b87925be030c9178c5faa58ea58d5c \ - --hash=sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25 \ - --hash=sha256:b99281b0704c103d4e11e72a76f1b543d4946fea7dd10767e7e1b5f00d4e5704 \ - --hash=sha256:bae5c2ed2eae26cc382020edad80d01f36cb8e746da40b292e68fec40421dc6a \ - --hash=sha256:bb4f7475e359992b580559e008c598091c45b5088f28614e855e42d39c2f1033 \ - --hash=sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1 \ - --hash=sha256:bfc1cc2fe31a6026a8a88e4ecfb98d7f6b1fec150cfd708adbfd1d2f42257c29 \ - --hash=sha256:c014c7ea7fb775dd015b2d3137378b7be0249a448a1612268b5a90c2d81de04d \ - --hash=sha256:c048058117fd649334d81b4b526e94bde3ccaddb20463a815ced6ecbb7d11160 \ - --hash=sha256:c0e2d366af265797506f0283487223146af57815b388623f0357ef7eac9b209d \ - --hash=sha256:c19b90316ad3b24c69cd78d5c9b4f3aa4497643685901185b65166293d36a00f \ - --hash=sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f \ - --hash=sha256:c6b8568a3bb5819a0ad087f16d40e5a3fb6099f39ea1d5625a3edc1e923fc538 \ - --hash=sha256:d32764c6c9aafb7fb55366a224756387cd50bfa720f32b88e0e6fa45b27dcf29 \ - --hash=sha256:d5a372fd5afd301b3a89582817fdcdb6c34124787c70dbcc616f259013e7eef7 \ - --hash=sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72 \ - --hash=sha256:dca68018bf48c251ba17c72ed479f4dafe9dbd5a73707ad8d28a38d11f3d42af \ - --hash=sha256:de2c184bb1fe2cbd2cefba613e9db29a5ab559323f994b6737e370d3da0ac455 \ - --hash=sha256:e3531d63d3bdfa7e3ac5e9b27b2dd7ec9df3206a98e0b3445fa906f233264c57 \ - --hash=sha256:e50a2e1404f063427c9d027378472316201a2290959a295169bcf25992d04558 \ - --hash=sha256:e636b3c5f61da31a92bf0d91da83e58fdfa96f178ba682f11d24f31944cdd28c \ - --hash=sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808 \ - --hash=sha256:f33ed1a2bf1997a36661874b017f5c4b760f41266341af36febaf271d179f6d7 \ - --hash=sha256:f76c1e3fe7d7c8afad7ed193f89a292e1999608170dcc9751a7462a87dfd5bc0 \ - --hash=sha256:f9444f105664c4ce47a2a7171a2418bce5b7bae45fb610f4e2c36045d85911d3 \ - --hash=sha256:fc290605db2a917f6e81b0e1e0796469871f5af381ce15c604a3c5c7e51cb730 \ - --hash=sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa \ - --hash=sha256:fee0c6bc7db1de362252affec009707a17478a00ec69f797d23ca256e36d5940 +aiohttp==3.13.5 \ + --hash=sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5 \ + --hash=sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b \ + --hash=sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9 \ + --hash=sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b \ + --hash=sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8 \ + --hash=sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a \ + --hash=sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2 \ + --hash=sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1 \ + --hash=sha256:147b4f501d0292077f29d5268c16bb7c864a1f054d7001c4c1812c0421ea1ed0 \ + --hash=sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037 \ + --hash=sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416 \ + --hash=sha256:178c7b5e62b454c2bc790786e6058c3cc968613b4419251b478c153a4aec32b1 \ + --hash=sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9 \ + --hash=sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a \ + --hash=sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36 \ + --hash=sha256:206b7b3ef96e4ce211754f0cd003feb28b7d81f0ad26b8d077a5d5161436067f \ + --hash=sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b \ + --hash=sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174 \ + --hash=sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b \ + --hash=sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8 \ + --hash=sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e \ + --hash=sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6 \ + --hash=sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c \ + --hash=sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe \ + --hash=sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9 \ + --hash=sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc \ + --hash=sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800 \ + --hash=sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286 \ + --hash=sha256:347542f0ea3f95b2a955ee6656461fa1c776e401ac50ebce055a6c38454a0adf \ + --hash=sha256:39380e12bd1f2fdab4285b6e055ad48efbaed5c836433b142ed4f5b9be71036a \ + --hash=sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc \ + --hash=sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9 \ + --hash=sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665 \ + --hash=sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832 \ + --hash=sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297 \ + --hash=sha256:4e704c52438f66fdd89588346183d898bb42167cf88f8b7ff1c0f9fc957c348f \ + --hash=sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73 \ + --hash=sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b \ + --hash=sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9 \ + --hash=sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090 \ + --hash=sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49 \ + --hash=sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d \ + --hash=sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46 \ + --hash=sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83 \ + --hash=sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796 \ + --hash=sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be \ + --hash=sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d \ + --hash=sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf \ + --hash=sha256:6f497a6876aa4b1a102b04996ce4c1170c7040d83faa9387dd921c16e30d5c83 \ + --hash=sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25 \ + --hash=sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06 \ + --hash=sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3 \ + --hash=sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6 \ + --hash=sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb \ + --hash=sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88 \ + --hash=sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9 \ + --hash=sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be \ + --hash=sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14 \ + --hash=sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a \ + --hash=sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c \ + --hash=sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3 \ + --hash=sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f \ + --hash=sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d \ + --hash=sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670 \ + --hash=sha256:912d4b6af530ddb1338a66229dac3a25ff11d4448be3ec3d6340583995f56031 \ + --hash=sha256:9277145d36a01653863899c665243871434694bcc3431922c3b35c978061bdb8 \ + --hash=sha256:95d14ca7abefde230f7639ec136ade282655431fd5db03c343b19dda72dd1643 \ + --hash=sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d \ + --hash=sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8 \ + --hash=sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8 \ + --hash=sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1 \ + --hash=sha256:9efcc0f11d850cefcafdd9275b9576ad3bfb539bed96807663b32ad99c4d4b88 \ + --hash=sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb \ + --hash=sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61 \ + --hash=sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4 \ + --hash=sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7 \ + --hash=sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9 \ + --hash=sha256:a8a4d3427e8de1312ddf309cc482186466c79895b3a139fed3259fc01dfa9a5b \ + --hash=sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500 \ + --hash=sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6 \ + --hash=sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2 \ + --hash=sha256:af545c2cffdb0967a96b6249e6f5f7b0d92cdfd267f9d5238d5b9ca63e8edb10 \ + --hash=sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1 \ + --hash=sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3 \ + --hash=sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e \ + --hash=sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a \ + --hash=sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5 \ + --hash=sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95 \ + --hash=sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074 \ + --hash=sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5 \ + --hash=sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b \ + --hash=sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772 \ + --hash=sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a \ + --hash=sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274 \ + --hash=sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94 \ + --hash=sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13 \ + --hash=sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac \ + --hash=sha256:cb979826071c0986a5f08333a36104153478ce6018c58cba7f9caddaf63d5d67 \ + --hash=sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76 \ + --hash=sha256:d147004fede1b12f6013a6dbb2a26a986a671a03c6ea740ddc76500e5f1c399f \ + --hash=sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8 \ + --hash=sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7 \ + --hash=sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8 \ + --hash=sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3 \ + --hash=sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be \ + --hash=sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b \ + --hash=sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c \ + --hash=sha256:e999f0c88a458c836d5fb521814e92ed2172c649200336a6df514987c1488258 \ + --hash=sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c \ + --hash=sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6 \ + --hash=sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56 \ + --hash=sha256:ee5e86776273de1795947d17bddd6bb19e0365fd2af4289c0d2c5454b6b1d36b \ + --hash=sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d \ + --hash=sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a \ + --hash=sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162 \ + --hash=sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1 \ + --hash=sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6 \ + --hash=sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5 \ + --hash=sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540 \ + --hash=sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254 # via aiobotocore aioitertools==0.13.0 \ --hash=sha256:0be0292b856f08dfac90e31f4739432f4cb6d7520ab9eb73e143f4f2fa5259be \ @@ -148,9 +148,9 @@ annotated-types==0.7.0 \ --hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \ --hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89 # via pydantic -anyio==4.12.1 \ - --hash=sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703 \ - --hash=sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c +anyio==4.13.0 \ + --hash=sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708 \ + --hash=sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc # via # httpx # mcp @@ -165,16 +165,16 @@ atpublic==7.0.0 \ --hash=sha256:466ef10d0c8bbd14fd02a5fbd5a8b6af6a846373d91106d3a07c16d72d96b63e \ --hash=sha256:6702bd9e7245eb4e8220a3e222afcef7f87412154732271ee7deee4433b72b4b # via ibis-framework -attrs==25.4.0 \ - --hash=sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11 \ - --hash=sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373 +attrs==26.1.0 \ + --hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \ + --hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32 # via # aiohttp # jsonschema # referencing -bigtree==1.3.1 \ - --hash=sha256:a22a0ecd9b0abb283f4a1515370dbf1ec93adee70746767272e2c49d7af9f407 \ - --hash=sha256:c8b766b00188c532d3499bfd9e9666b357428db507fc701f088031a0d5c614d5 +bigtree==1.4.0 \ + --hash=sha256:d0d99550ae64ce4529f132602ab875c2ab472c96c942f5704f8c72a17450d3ea \ + --hash=sha256:e5ae2e948168da671d99601c9ed87ab3b48d9d4ea8a98f111e5748e98064c31c # via feast (pyproject.toml) boto3==1.38.27 \ --hash=sha256:94bd7fdd92d5701b362d4df100d21e28f8307a67ff56b6a8b0398119cf22f859 \ @@ -190,9 +190,9 @@ botocore==1.38.46 \ # boto3 # s3transfer # snowflake-connector-python -certifi==2026.1.4 \ - --hash=sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c \ - --hash=sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120 +certifi==2026.2.25 \ + --hash=sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa \ + --hash=sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7 # via # httpcore # httpx @@ -287,120 +287,136 @@ cffi==2.0.0 \ # via # feast (pyproject.toml) # cryptography -charset-normalizer==3.4.4 \ - --hash=sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad \ - --hash=sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93 \ - --hash=sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394 \ - --hash=sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89 \ - --hash=sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc \ - --hash=sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86 \ - --hash=sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63 \ - --hash=sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d \ - --hash=sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f \ - --hash=sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8 \ - --hash=sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0 \ - --hash=sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505 \ - --hash=sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161 \ - --hash=sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af \ - --hash=sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152 \ - --hash=sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318 \ - --hash=sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72 \ - --hash=sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4 \ - --hash=sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e \ - --hash=sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3 \ - --hash=sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576 \ - --hash=sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c \ - --hash=sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1 \ - --hash=sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8 \ - --hash=sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1 \ - --hash=sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2 \ - --hash=sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44 \ - --hash=sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26 \ - --hash=sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88 \ - --hash=sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016 \ - --hash=sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede \ - --hash=sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf \ - --hash=sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a \ - --hash=sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc \ - --hash=sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0 \ - --hash=sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84 \ - --hash=sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db \ - --hash=sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1 \ - --hash=sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7 \ - --hash=sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed \ - --hash=sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8 \ - --hash=sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133 \ - --hash=sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e \ - --hash=sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef \ - --hash=sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14 \ - --hash=sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2 \ - --hash=sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0 \ - --hash=sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d \ - --hash=sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828 \ - --hash=sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f \ - --hash=sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf \ - --hash=sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6 \ - --hash=sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328 \ - --hash=sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090 \ - --hash=sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa \ - --hash=sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381 \ - --hash=sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c \ - --hash=sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb \ - --hash=sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc \ - --hash=sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a \ - --hash=sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec \ - --hash=sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc \ - --hash=sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac \ - --hash=sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e \ - --hash=sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313 \ - --hash=sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569 \ - --hash=sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3 \ - --hash=sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d \ - --hash=sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525 \ - --hash=sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894 \ - --hash=sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3 \ - --hash=sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9 \ - --hash=sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a \ - --hash=sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9 \ - --hash=sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14 \ - --hash=sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25 \ - --hash=sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50 \ - --hash=sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf \ - --hash=sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1 \ - --hash=sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3 \ - --hash=sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac \ - --hash=sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e \ - --hash=sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815 \ - --hash=sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c \ - --hash=sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6 \ - --hash=sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6 \ - --hash=sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e \ - --hash=sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4 \ - --hash=sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84 \ - --hash=sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69 \ - --hash=sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15 \ - --hash=sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191 \ - --hash=sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0 \ - --hash=sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897 \ - --hash=sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd \ - --hash=sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2 \ - --hash=sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794 \ - --hash=sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d \ - --hash=sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074 \ - --hash=sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3 \ - --hash=sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224 \ - --hash=sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838 \ - --hash=sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a \ - --hash=sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d \ - --hash=sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d \ - --hash=sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f \ - --hash=sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8 \ - --hash=sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490 \ - --hash=sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966 \ - --hash=sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9 \ - --hash=sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3 \ - --hash=sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e \ - --hash=sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608 +charset-normalizer==3.4.7 \ + --hash=sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc \ + --hash=sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c \ + --hash=sha256:07d9e39b01743c3717745f4c530a6349eadbfa043c7577eef86c502c15df2c67 \ + --hash=sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4 \ + --hash=sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0 \ + --hash=sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c \ + --hash=sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5 \ + --hash=sha256:12a6fff75f6bc66711b73a2f0addfc4c8c15a20e805146a02d147a318962c444 \ + --hash=sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153 \ + --hash=sha256:14265bfe1f09498b9d8ec91e9ec9fa52775edf90fcbde092b25f4a33d444fea9 \ + --hash=sha256:16d971e29578a5e97d7117866d15889a4a07befe0e87e703ed63cd90cb348c01 \ + --hash=sha256:177a0ba5f0211d488e295aaf82707237e331c24788d8d76c96c5a41594723217 \ + --hash=sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b \ + --hash=sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c \ + --hash=sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a \ + --hash=sha256:1dc8b0ea451d6e69735094606991f32867807881400f808a106ee1d963c46a83 \ + --hash=sha256:1efde3cae86c8c273f1eb3b287be7d8499420cf2fe7585c41d370d3e790054a5 \ + --hash=sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7 \ + --hash=sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb \ + --hash=sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c \ + --hash=sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1 \ + --hash=sha256:2cd4a60d0e2fb04537162c62bbbb4182f53541fe0ede35cdf270a1c1e723cc42 \ + --hash=sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab \ + --hash=sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df \ + --hash=sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e \ + --hash=sha256:320ade88cfb846b8cd6b4ddf5ee9e80ee0c1f52401f2456b84ae1ae6a1a5f207 \ + --hash=sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18 \ + --hash=sha256:36836d6ff945a00b88ba1e4572d721e60b5b8c98c155d465f56ad19d68f23734 \ + --hash=sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38 \ + --hash=sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110 \ + --hash=sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18 \ + --hash=sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44 \ + --hash=sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d \ + --hash=sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48 \ + --hash=sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e \ + --hash=sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5 \ + --hash=sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d \ + --hash=sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53 \ + --hash=sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790 \ + --hash=sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c \ + --hash=sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b \ + --hash=sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116 \ + --hash=sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d \ + --hash=sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10 \ + --hash=sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6 \ + --hash=sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2 \ + --hash=sha256:6370e8686f662e6a3941ee48ed4742317cafbe5707e36406e9df792cdb535776 \ + --hash=sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a \ + --hash=sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265 \ + --hash=sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008 \ + --hash=sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943 \ + --hash=sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374 \ + --hash=sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246 \ + --hash=sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e \ + --hash=sha256:6e0d51f618228538a3e8f46bd246f87a6cd030565e015803691603f55e12afb5 \ + --hash=sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616 \ + --hash=sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15 \ + --hash=sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41 \ + --hash=sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960 \ + --hash=sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752 \ + --hash=sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e \ + --hash=sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72 \ + --hash=sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7 \ + --hash=sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8 \ + --hash=sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b \ + --hash=sha256:813c0e0132266c08eb87469a642cb30aaff57c5f426255419572aaeceeaa7bf4 \ + --hash=sha256:82b271f5137d07749f7bf32f70b17ab6eaabedd297e75dce75081a24f76eb545 \ + --hash=sha256:84c018e49c3bf790f9c2771c45e9313a08c2c2a6342b162cd650258b57817706 \ + --hash=sha256:8751d2787c9131302398b11e6c8068053dcb55d5a8964e114b6e196cf16cb366 \ + --hash=sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb \ + --hash=sha256:87fad7d9ba98c86bcb41b2dc8dbb326619be2562af1f8ff50776a39e55721c5a \ + --hash=sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e \ + --hash=sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00 \ + --hash=sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f \ + --hash=sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a \ + --hash=sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1 \ + --hash=sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66 \ + --hash=sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356 \ + --hash=sha256:a6c5863edfbe888d9eff9c8b8087354e27618d9da76425c119293f11712a6319 \ + --hash=sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4 \ + --hash=sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad \ + --hash=sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d \ + --hash=sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5 \ + --hash=sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7 \ + --hash=sha256:aef65cd602a6d0e0ff6f9930fcb1c8fec60dd2cfcb6facaf4bdb0e5873042db0 \ + --hash=sha256:af21eb4409a119e365397b2adbaca4c9ccab56543a65d5dbd9f920d6ac29f686 \ + --hash=sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34 \ + --hash=sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49 \ + --hash=sha256:bb8cc7534f51d9a017b93e3e85b260924f909601c3df002bcdb58ddb4dc41a5c \ + --hash=sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1 \ + --hash=sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e \ + --hash=sha256:bd9b23791fe793e4968dba0c447e12f78e425c59fc0e3b97f6450f4781f3ee60 \ + --hash=sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0 \ + --hash=sha256:c0f081d69a6e58272819b70288d3221a6ee64b98df852631c80f293514d3b274 \ + --hash=sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d \ + --hash=sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0 \ + --hash=sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae \ + --hash=sha256:c593052c465475e64bbfe5dbd81680f64a67fdc752c56d7a0ae205dc8aeefe0f \ + --hash=sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d \ + --hash=sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe \ + --hash=sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3 \ + --hash=sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393 \ + --hash=sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1 \ + --hash=sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af \ + --hash=sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44 \ + --hash=sha256:d61f00a0869d77422d9b2aba989e2d24afa6ffd552af442e0e58de4f35ea6d00 \ + --hash=sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c \ + --hash=sha256:dca4bbc466a95ba9c0234ef56d7dd9509f63da22274589ebd4ed7f1f4d4c54e3 \ + --hash=sha256:dd915403e231e6b1809fe9b6d9fc55cf8fb5e02765ac625d9cd623342a7905d7 \ + --hash=sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd \ + --hash=sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e \ + --hash=sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b \ + --hash=sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8 \ + --hash=sha256:e5f4d355f0a2b1a31bc3edec6795b46324349c9cb25eed068049e4f472fb4259 \ + --hash=sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859 \ + --hash=sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46 \ + --hash=sha256:e80c8378d8f3d83cd3164da1ad2df9e37a666cdde7b1cb2298ed0b558064be30 \ + --hash=sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b \ + --hash=sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46 \ + --hash=sha256:ed065083d0898c9d5b4bbec7b026fd755ff7454e6e8b73a67f8c744b13986e24 \ + --hash=sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a \ + --hash=sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24 \ + --hash=sha256:f22dec1690b584cea26fade98b2435c132c1b5f68e39f5a0b7627cd7ae31f1dc \ + --hash=sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215 \ + --hash=sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063 \ + --hash=sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832 \ + --hash=sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6 \ + --hash=sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79 \ + --hash=sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464 # via # requests # snowflake-connector-python @@ -420,68 +436,68 @@ colorama==0.4.6 \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 # via feast (pyproject.toml) -cryptography==46.0.5 \ - --hash=sha256:02f547fce831f5096c9a567fd41bc12ca8f11df260959ecc7c3202555cc47a72 \ - --hash=sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235 \ - --hash=sha256:1abfdb89b41c3be0365328a410baa9df3ff8a9110fb75e7b52e66803ddabc9a9 \ - --hash=sha256:2ae6971afd6246710480e3f15824ed3029a60fc16991db250034efd0b9fb4356 \ - --hash=sha256:2b7a67c9cd56372f3249b39699f2ad479f6991e62ea15800973b956f4b73e257 \ - --hash=sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad \ - --hash=sha256:38946c54b16c885c72c4f59846be9743d699eee2b69b6988e0a00a01f46a61a4 \ - --hash=sha256:3b4995dc971c9fb83c25aa44cf45f02ba86f71ee600d81091c2f0cbae116b06c \ - --hash=sha256:3ce58ba46e1bc2aac4f7d9290223cead56743fa6ab94a5d53292ffaac6a91614 \ - --hash=sha256:3ee190460e2fbe447175cda91b88b84ae8322a104fc27766ad09428754a618ed \ - --hash=sha256:4108d4c09fbbf2789d0c926eb4152ae1760d5a2d97612b92d508d96c861e4d31 \ - --hash=sha256:420d0e909050490d04359e7fdb5ed7e667ca5c3c402b809ae2563d7e66a92229 \ - --hash=sha256:47fb8a66058b80e509c47118ef8a75d14c455e81ac369050f20ba0d23e77fee0 \ - --hash=sha256:4c3341037c136030cb46e4b1e17b7418ea4cbd9dd207e4a6f3b2b24e0d4ac731 \ - --hash=sha256:4d7e3d356b8cd4ea5aff04f129d5f66ebdc7b6f8eae802b93739ed520c47c79b \ - --hash=sha256:4d8ae8659ab18c65ced284993c2265910f6c9e650189d4e3f68445ef82a810e4 \ - --hash=sha256:4e817a8920bfbcff8940ecfd60f23d01836408242b30f1a708d93198393a80b4 \ - --hash=sha256:50bfb6925eff619c9c023b967d5b77a54e04256c4281b0e21336a130cd7fc263 \ - --hash=sha256:556e106ee01aa13484ce9b0239bca667be5004efb0aabbed28d353df86445595 \ - --hash=sha256:582f5fcd2afa31622f317f80426a027f30dc792e9c80ffee87b993200ea115f1 \ - --hash=sha256:5be7bf2fb40769e05739dd0046e7b26f9d4670badc7b032d6ce4db64dddc0678 \ - --hash=sha256:60ee7e19e95104d4c03871d7d7dfb3d22ef8a9b9c6778c94e1c8fcc8365afd48 \ - --hash=sha256:61aa400dce22cb001a98014f647dc21cda08f7915ceb95df0c9eaf84b4b6af76 \ - --hash=sha256:68f68d13f2e1cb95163fa3b4db4bf9a159a418f5f6e7242564fc75fcae667fd0 \ - --hash=sha256:7d1f30a86d2757199cb2d56e48cce14deddf1f9c95f1ef1b64ee91ea43fe2e18 \ - --hash=sha256:7d731d4b107030987fd61a7f8ab512b25b53cef8f233a97379ede116f30eb67d \ - --hash=sha256:803812e111e75d1aa73690d2facc295eaefd4439be1023fefc4995eaea2af90d \ - --hash=sha256:80a8d7bfdf38f87ca30a5391c0c9ce4ed2926918e017c29ddf643d0ed2778ea1 \ - --hash=sha256:8293f3dea7fc929ef7240796ba231413afa7b68ce38fd21da2995549f5961981 \ - --hash=sha256:8456928655f856c6e1533ff59d5be76578a7157224dbd9ce6872f25055ab9ab7 \ - --hash=sha256:890bcb4abd5a2d3f852196437129eb3667d62630333aacc13dfd470fad3aaa82 \ - --hash=sha256:94a76daa32eb78d61339aff7952ea819b1734b46f73646a07decb40e5b3448e2 \ - --hash=sha256:9f16fbdf4da055efb21c22d81b89f155f02ba420558db21288b3d0035bafd5f4 \ - --hash=sha256:a3d1fae9863299076f05cb8a778c467578262fae09f9dc0ee9b12eb4268ce663 \ - --hash=sha256:a3d507bb6a513ca96ba84443226af944b0f7f47dcc9a399d110cd6146481d24c \ - --hash=sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d \ - --hash=sha256:ba2a27ff02f48193fc4daeadf8ad2590516fa3d0adeeb34336b96f7fa64c1e3a \ - --hash=sha256:bc84e875994c3b445871ea7181d424588171efec3e185dced958dad9e001950a \ - --hash=sha256:bfd56bb4b37ed4f330b82402f6f435845a5f5648edf1ad497da51a8452d5d62d \ - --hash=sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b \ - --hash=sha256:c3bcce8521d785d510b2aad26ae2c966092b7daa8f45dd8f44734a104dc0bc1a \ - --hash=sha256:c4143987a42a2397f2fc3b4d7e3a7d313fbe684f67ff443999e803dd75a76826 \ - --hash=sha256:c69fd885df7d089548a42d5ec05be26050ebcd2283d89b3d30676eb32ff87dee \ - --hash=sha256:ced80795227d70549a411a4ab66e8ce307899fad2220ce5ab2f296e687eacde9 \ - --hash=sha256:d66e421495fdb797610a08f43b05269e0a5ea7f5e652a89bfd5a7d3c1dee3648 \ - --hash=sha256:d861ee9e76ace6cf36a6a89b959ec08e7bc2493ee39d07ffe5acb23ef46d27da \ - --hash=sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2 \ - --hash=sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2 \ - --hash=sha256:fe346b143ff9685e40192a4960938545c699054ba11d4f9029f94751e3f71d87 +cryptography==46.0.6 \ + --hash=sha256:02fad249cb0e090b574e30b276a3da6a149e04ee2f049725b1f69e7b8351ec70 \ + --hash=sha256:063b67749f338ca9c5a0b7fe438a52c25f9526b851e24e6c9310e7195aad3b4d \ + --hash=sha256:12cae594e9473bca1a7aceb90536060643128bb274fcea0fc459ab90f7d1ae7a \ + --hash=sha256:12f0fa16cc247b13c43d56d7b35287ff1569b5b1f4c5e87e92cc4fcc00cd10c0 \ + --hash=sha256:22259338084d6ae497a19bae5d4c66b7ca1387d3264d1c2c0e72d9e9b6a77b97 \ + --hash=sha256:26031f1e5ca62fcb9d1fcb34b2b60b390d1aacaa15dc8b895a9ed00968b97b30 \ + --hash=sha256:27550628a518c5c6c903d84f637fbecf287f6cb9ced3804838a1295dc1fd0759 \ + --hash=sha256:2b417edbe8877cda9022dde3a008e2deb50be9c407eef034aeeb3a8b11d9db3c \ + --hash=sha256:2ea0f37e9a9cf0df2952893ad145fd9627d326a59daec9b0802480fa3bcd2ead \ + --hash=sha256:2ef9e69886cbb137c2aef9772c2e7138dc581fad4fcbcf13cc181eb5a3ab6275 \ + --hash=sha256:341359d6c9e68834e204ceaf25936dffeafea3829ab80e9503860dcc4f4dac58 \ + --hash=sha256:380343e0653b1c9d7e1f55b52aaa2dbb2fdf2730088d48c43ca1c7c0abb7cc2f \ + --hash=sha256:3c21d92ed15e9cfc6eb64c1f5a0326db22ca9c2566ca46d845119b45b4400361 \ + --hash=sha256:3dfa6567f2e9e4c5dceb8ccb5a708158a2a871052fa75c8b78cb0977063f1507 \ + --hash=sha256:456b3215172aeefb9284550b162801d62f5f264a081049a3e94307fe20792cfa \ + --hash=sha256:4668298aef7cddeaf5c6ecc244c2302a2b8e40f384255505c22875eebb47888b \ + --hash=sha256:50575a76e2951fe7dbd1f56d181f8c5ceeeb075e9ff88e7ad997d2f42af06e7b \ + --hash=sha256:639301950939d844a9e1c4464d7e07f902fe9a7f6b215bb0d4f28584729935d8 \ + --hash=sha256:64235194bad039a10bb6d2d930ab3323baaec67e2ce36215fd0952fad0930ca8 \ + --hash=sha256:6617f67b1606dfd9fe4dbfa354a9508d4a6d37afe30306fe6c101b7ce3274b72 \ + --hash=sha256:67177e8a9f421aa2d3a170c3e56eca4e0128883cf52a071a7cbf53297f18b175 \ + --hash=sha256:6728c49e3b2c180ef26f8e9f0a883a2c585638db64cf265b49c9ba10652d430e \ + --hash=sha256:6739d56300662c468fddb0e5e291f9b4d084bead381667b9e654c7dd81705124 \ + --hash=sha256:69cf0056d6947edc6e6760e5f17afe4bea06b56a9ac8a06de9d2bd6b532d4f3a \ + --hash=sha256:760997a4b950ff00d418398ad73fbc91aa2894b5c1db7ccb45b4f68b42a63b3c \ + --hash=sha256:79e865c642cfc5c0b3eb12af83c35c5aeff4fa5c672dc28c43721c2c9fdd2f0f \ + --hash=sha256:7e6142674f2a9291463e5e150090b95a8519b2fb6e6aaec8917dd8d094ce750d \ + --hash=sha256:7f417f034f91dcec1cb6c5c35b07cdbb2ef262557f701b4ecd803ee8cefed4f4 \ + --hash=sha256:7f6690b6c55e9c5332c0b59b9c8a3fb232ebf059094c17f9019a51e9827df91c \ + --hash=sha256:8927ccfbe967c7df312ade694f987e7e9e22b2425976ddbf28271d7e58845290 \ + --hash=sha256:8ce35b77aaf02f3b59c90b2c8a05c73bac12cea5b4e8f3fbece1f5fddea5f0ca \ + --hash=sha256:8e7304c4f4e9490e11efe56af6713983460ee0780f16c63f219984dab3af9d2d \ + --hash=sha256:90e5f0a7b3be5f40c3a0a0eafb32c681d8d2c181fc2a1bdabe9b3f611d9f6b1a \ + --hash=sha256:97c8115b27e19e592a05c45d0dd89c57f81f841cc9880e353e0d3bf25b2139ed \ + --hash=sha256:9a693028b9cbe51b5a1136232ee8f2bc242e4e19d456ded3fa7c86e43c713b4a \ + --hash=sha256:9a9c42a2723999a710445bc0d974e345c32adfd8d2fac6d8a251fa829ad31cfb \ + --hash=sha256:a3e84d5ec9ba01f8fd03802b2147ba77f0c8f2617b2aff254cedd551844209c8 \ + --hash=sha256:aad75154a7ac9039936d50cf431719a2f8d4ed3d3c277ac03f3339ded1a5e707 \ + --hash=sha256:b12c6b1e1651e42ab5de8b1e00dc3b6354fdfd778e7fa60541ddacc27cd21410 \ + --hash=sha256:b928a3ca837c77a10e81a814a693f2295200adb3352395fad024559b7be7a736 \ + --hash=sha256:bcb87663e1f7b075e48c3be3ecb5f0b46c8fc50b50a97cf264e7f60242dca3f2 \ + --hash=sha256:c797e2517cb7880f8297e2c0f43bb910e91381339336f75d2c1c2cbf811b70b4 \ + --hash=sha256:c89eb37fae9216985d8734c1afd172ba4927f5a05cfd9bf0e4863c6d5465b013 \ + --hash=sha256:cdcd3edcbc5d55757e5f5f3d330dd00007ae463a7e7aa5bf132d1f22a4b62b19 \ + --hash=sha256:d24c13369e856b94892a89ddf70b332e0b70ad4a5c43cf3e9cb71d6d7ffa1f7b \ + --hash=sha256:d4e4aadb7fc1f88687f47ca20bb7227981b03afaae69287029da08096853b738 \ + --hash=sha256:d9528b535a6c4f8ff37847144b8986a9a143585f0540fbcb1a98115b543aa463 \ + --hash=sha256:ed3775295fb91f70b4027aeba878d79b3e55c0b3e97eaa4de71f8f23a9f2eb77 \ + --hash=sha256:ed418c37d095aeddf5336898a132fba01091f0ac5844e3e8018506f014b6d2c4 # via # google-auth # pyjwt # pyopenssl # snowflake-connector-python -dask[dataframe]==2026.1.2 \ - --hash=sha256:1136683de2750d98ea792670f7434e6c1cfce90cab2cc2f2495a9e60fd25a4fc \ - --hash=sha256:46a0cf3b8d87f78a3d2e6b145aea4418a6d6d606fe6a16c79bd8ca2bb862bc91 +dask[dataframe]==2026.3.0 \ + --hash=sha256:be614b9242b0b38288060fb2d7696125946469c98a1c30e174883fd199e0428d \ + --hash=sha256:f7d96c8274e8a900d217c1ff6ea8d1bbf0b4c2c21e74a409644498d925eb8f85 # via feast (pyproject.toml) -db-dtypes==1.5.0 \ - --hash=sha256:abdbb2e4eb965800ed6f98af0c5c1cafff9063ace09114be2d26a7f046be2c8a \ - --hash=sha256:ad9e94243f53e104bc77dbf9ae44b580d83a770d3694483aba59c9767966daa5 +db-dtypes==1.5.1 \ + --hash=sha256:901099b807c9312bc61a5bddbfb07512884e6c6d5a9edacf24d50bcf303aa5f7 \ + --hash=sha256:ad71a6645e3c1f06d4d32023940576648f43119822f825f0d22587c6ef8afe15 # via # google-cloud-bigquery # pandas-gbq @@ -489,56 +505,50 @@ dill==0.3.9 \ --hash=sha256:468dff3b89520b474c0397703366b7b95eebe6303f108adf9b19da1f702be87a \ --hash=sha256:81aa267dddf68cbfe8029c42ca9ec6a4ab3b22371d1c450abc54422577b4512c # via feast (pyproject.toml) -duckdb==1.4.4 \ - --hash=sha256:0509b39ea7af8cff0198a99d206dca753c62844adab54e545984c2e2c1381616 \ - --hash=sha256:0d636ceda422e7babd5e2f7275f6a0d1a3405e6a01873f00d38b72118d30c10b \ - --hash=sha256:1af6e76fe8bd24875dc56dd8e38300d64dc708cd2e772f67b9fbc635cc3066a3 \ - --hash=sha256:1f8d55843cc940e36261689054f7dfb6ce35b1f5b0953b0d355b6adb654b0d52 \ - --hash=sha256:25874f8b1355e96178079e37312c3ba6d61a2354f51319dae860cf21335c3a20 \ - --hash=sha256:337f8b24e89bc2e12dadcfe87b4eb1c00fd920f68ab07bc9b70960d6523b8bc3 \ - --hash=sha256:452c5b5d6c349dc5d1154eb2062ee547296fcbd0c20e9df1ed00b5e1809089da \ - --hash=sha256:453b115f4777467f35103d8081770ac2f223fb5799178db5b06186e3ab51d1f2 \ - --hash=sha256:47dd4162da6a2be59a0aef640eb08d6360df1cf83c317dcc127836daaf3b7f7c \ - --hash=sha256:49123b579e4a6323e65139210cd72dddc593a72d840211556b60f9703bda8526 \ - --hash=sha256:4c25d5b0febda02b7944e94fdae95aecf952797afc8cb920f677b46a7c251955 \ - --hash=sha256:50f2eb173c573811b44aba51176da7a4e5c487113982be6a6a1c37337ec5fa57 \ - --hash=sha256:53cd6423136ab44383ec9955aefe7599b3fb3dd1fe006161e6396d8167e0e0d4 \ - --hash=sha256:5536eb952a8aa6ae56469362e344d4e6403cc945a80bc8c5c2ebdd85d85eb64b \ - --hash=sha256:59c8d76016dde854beab844935b1ec31de358d4053e792988108e995b18c08e7 \ - --hash=sha256:5ba684f498d4e924c7e8f30dd157da8da34c8479746c5011b6c0e037e9c60ad2 \ - --hash=sha256:5cdc4126ec925edf3112bc656ac9ed23745294b854935fa7a643a216e4455af6 \ - --hash=sha256:5e1933fac5293fea5926b0ee75a55b8cfe7f516d867310a5b251831ab61fe62b \ - --hash=sha256:6703dd1bb650025b3771552333d305d62ddd7ff182de121483d4e042ea6e2e00 \ - --hash=sha256:6792ca647216bd5c4ff16396e4591cfa9b4a72e5ad7cdd312cec6d67e8431a7c \ - --hash=sha256:6cb357cfa3403910e79e2eb46c8e445bb1ee2fd62e9e9588c6b999df4256abc1 \ - --hash=sha256:6fb1225a9ea5877421481d59a6c556a9532c32c16c7ae6ca8d127e2b878c9389 \ - --hash=sha256:707530f6637e91dc4b8125260595299ec9dd157c09f5d16c4186c5988bfbd09a \ - --hash=sha256:7df7351328ffb812a4a289732f500d621e7de9942a3a2c9b6d4afcf4c0e72526 \ - --hash=sha256:7eec0bf271ac622e57b7f6554a27a6e7d1dd2f43d1871f7962c74bcbbede15ba \ - --hash=sha256:8097201bc5fd0779d7fcc2f3f4736c349197235f4cb7171622936343a1aa8dbf \ - --hash=sha256:8bba52fd2acb67668a4615ee17ee51814124223de836d9e2fdcbc4c9021b3d3c \ - --hash=sha256:8e5c2d8a0452df55e092959c0bfc8ab8897ac3ea0f754cb3b0ab3e165cd79aff \ - --hash=sha256:a3c8542db7ffb128aceb7f3b35502ebaddcd4f73f1227569306cc34bad06680c \ - --hash=sha256:b297eff642503fd435a9de5a9cb7db4eccb6f61d61a55b30d2636023f149855f \ - --hash=sha256:bf138201f56e5d6fc276a25138341b3523e2f84733613fc43f02c54465619a95 \ - --hash=sha256:c65d15c440c31e06baaebfd2c06d71ce877e132779d309f1edf0a85d23c07e92 \ - --hash=sha256:c9566a4ed834ec7999db5849f53da0a7ee83d86830c33f471bf0211a1148ca12 \ - --hash=sha256:cd1be3d48577f5b40eb9706c6b2ae10edfe18e78eb28e31a3b922dcff1183597 \ - --hash=sha256:d0440f59e0cd9936a9ebfcf7a13312eda480c79214ffed3878d75947fc3b7d6d \ - --hash=sha256:d525de5f282b03aa8be6db86b1abffdceae5f1055113a03d5b50cd2fb8cf2ef8 \ - --hash=sha256:ddcfd9c6ff234da603a1edd5fd8ae6107f4d042f74951b65f91bc5e2643856b3 \ - --hash=sha256:e041f2fbd6888da090eca96ac167a7eb62d02f778385dd9155ed859f1c6b6dc8 \ - --hash=sha256:e870a441cb1c41d556205deb665749f26347ed13b3a247b53714f5d589596977 \ - --hash=sha256:f28a18cc790217e5b347bb91b2cab27aafc557c58d3d8382e04b4fe55d0c3f66 \ - --hash=sha256:fb94de6d023de9d79b7edc1ae07ee1d0b4f5fa8a9dcec799650b5befdf7aafec +duckdb==1.5.1 \ + --hash=sha256:054ad424b051b334052afac58cb216f3b1ebb8579fc8c641e60f0182e8725ea9 \ + --hash=sha256:05fc91767d0cfc4cf2fa68966ab5b479ac07561752e42dd0ae30327bd160f64a \ + --hash=sha256:0a6acc2040bec1f05de62a2f3f68f4c12f3ec7d6012b4317d0ab1a195af26225 \ + --hash=sha256:26e56b5f0c96189e3288d83cf7b476e23615987902f801e5788dee15ee9f24a9 \ + --hash=sha256:36e8e32621a9e2a9abe75dc15a4b54a3997f2d8b1e53ad754bae48a083c91130 \ + --hash=sha256:40c5220ec93790b18ec6278da9c6ac2608d997ee6d6f7cd44c5c3992764e8e71 \ + --hash=sha256:446d500a2977c6ae2077f340c510a25956da5c77597175c316edfa87248ceda3 \ + --hash=sha256:46f92ada9023e59f27edc048167b31ac9a03911978b1296c845a34462a27f096 \ + --hash=sha256:482f8a13f2600f527e427f73c42b5aa75536f9892868068f0aaf573055a0135f \ + --hash=sha256:553c273a6a8f140adaa6da6a6135c7f95bdc8c2e5f95252fcdf9832d758e2141 \ + --hash=sha256:5ae7c0d744d64e2753149634787cc4ab60f05ef1e542b060eeab719f3cdb7723 \ + --hash=sha256:5d4147422d91ccdc2d2abf6ed24196025e020259d1d267970ae20c13c2ce84b1 \ + --hash=sha256:6af347debc8b721aa72e48671166282da979d5e5ae52dbc660ab417282b48e23 \ + --hash=sha256:6ba302115f63f6482c000ccfd62efdb6c41d9d182a5bcd4a90e7ab8cd13856eb \ + --hash=sha256:6f7361d66cc801d9eb4df734b139cd7b0e3c257a16f3573ebd550ddb255549e6 \ + --hash=sha256:715f05ea198d20d7f8b407b9b84e0023d17f2b9096c194cea702b7840e74f1f7 \ + --hash=sha256:71dddcebbc5a70e946a06c30b59b5dd7999c9833d307168f90fb4e4b672ab63e \ + --hash=sha256:8150c569b2aa4573b51ba8475e814aa41fd53a3d510c1ffb96f1139f46faf611 \ + --hash=sha256:8843bd9594e1387f1e601439e19ad73abdf57356104fd1e53a708255bb95a13d \ + --hash=sha256:8c0088765747ae5d6c9f89987bb36f9fb83564f07090d721344ce8e1abedffea \ + --hash=sha256:972d0dbf283508f9bc446ee09c3838cb7c7f114b5bdceee41753288c97fe2f7c \ + --hash=sha256:a28531cee2a5a42d89f9ba4da53bfeb15681f12acc0263476c8705380dadce07 \ + --hash=sha256:a3be2072315982e232bfe49c9d3db0a59ba67b2240a537ef42656cc772a887c7 \ + --hash=sha256:ac2804043bd1bc10b5da18f8f4c706877197263a510c41be9b4c0062f5783dcc \ + --hash=sha256:afab8b4b1f4469c3879bb049dd039f8fce402712050324e9524a43d7324c5e87 \ + --hash=sha256:b370d1620a34a4538ef66524fcee9de8171fa263c701036a92bc0b4c1f2f9c6d \ + --hash=sha256:b8b0808dba0c63b7633bdaefb34e08fe0612622224f9feb0e7518904b1615101 \ + --hash=sha256:bc7ca6a1a40e7e4c933017e6c09ef18032add793df4e42624c6c0c87e0bebdad \ + --hash=sha256:caa65e1f5bf007430bf657c37cab7ab81a4ddf8d337e3062bcc5085d17ef038b \ + --hash=sha256:d68c5a01a283cb13b79eafe016fe5869aa11bff8c46e7141c70aa0aac808010f \ + --hash=sha256:da137802688190835b4c863cafa77fd7e29dff662ee6d905a9ffc14f00299c91 \ + --hash=sha256:e56a20ab6cdb90a95b0c99652e28de3504ce77129087319c03c9098266183ae5 \ + --hash=sha256:e878ccb7d20872065e1597935fdb5e65efa43220c8edd0d9c4a1a7ff1f3eb277 \ + --hash=sha256:eba81e0b3011c1f23df7ea47ef4ffaa8239817959ae291515b6efd068bde2161 \ + --hash=sha256:ed6d23a3f806898e69c77430ebd8da0c79c219f97b9acbc9a29a653e09740c59 # via ibis-framework durationpy==0.10 \ --hash=sha256:1fa6893409a6e739c9c72334fc65cca1f355dbdd93405d30f726deb5bde42fba \ --hash=sha256:3b41e1b601234296b4fb368338fdcd3e13e0b4fb5b67345948f4f2bf9868b286 # via kubernetes -fastapi==0.129.0 \ - --hash=sha256:61315cebd2e65df5f97ec298c888f9de30430dd0612d59d6480beafbc10655af \ - --hash=sha256:b4946880e48f462692b31c083be0432275cbfb6e2274566b1be91479cc1a84ec +fastapi==0.135.3 \ + --hash=sha256:9b0f590c813acd13d0ab43dd8494138eb58e484bfac405db1f3187cfc5810d98 \ + --hash=sha256:bd6d7caf1a2bdd8d676843cdcd2287729572a1ef524fc4d65c17ae002a1be654 # via # feast (pyproject.toml) # fastapi-mcp @@ -546,9 +556,9 @@ fastapi-mcp==0.4.0 \ --hash=sha256:d4a3fe7966af24d44e4b412720561c95eb12bed999a4443a88221834b3b15aec \ --hash=sha256:d4ca9410996f4c7b8ea0d7b20fdf79878dc359ebf89cbf3b222e0b675a55097d # via feast (pyproject.toml) -filelock==3.24.2 \ - --hash=sha256:667d7dc0b7d1e1064dd5f8f8e80bdac157a6482e8d2e02cd16fd3b6b33bd6556 \ - --hash=sha256:c22803117490f156e59fafce621f0550a7a853e2bbf4f87f112b11d469b6c81b +filelock==3.25.2 \ + --hash=sha256:b64ece2b38f4ca29dd3e810287aa8c48182bbecd1ae6e9ae126c9b35f1382694 \ + --hash=sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70 # via snowflake-connector-python frozenlist==1.8.0 \ --hash=sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686 \ @@ -690,9 +700,9 @@ fsspec==2024.9.0 \ # via # feast (pyproject.toml) # dask -google-api-core[grpc]==2.29.0 \ - --hash=sha256:84181be0f8e6b04006df75ddfe728f24489f0af57c96a529ff7cf45bc28797f7 \ - --hash=sha256:d30bc60980daa36e314b5d5a3e5958b0200cb44ca8fa1be2b614e932b75a3ea9 +google-api-core[grpc]==2.30.2 \ + --hash=sha256:9a8113e1a88bdc09a7ff629707f2214d98d61c7f6ceb0ea38c42a095d02dc0f9 \ + --hash=sha256:a4c226766d6af2580577db1f1a51bf53cd262f722b49731ce7414c43068a9594 # via # feast (pyproject.toml) # google-cloud-bigquery @@ -702,9 +712,9 @@ google-api-core[grpc]==2.29.0 \ # google-cloud-datastore # google-cloud-storage # pandas-gbq -google-auth==2.48.0 \ - --hash=sha256:2e2a537873d449434252a9632c28bfc268b0adb1e53f9fb62afc5333a975903f \ - --hash=sha256:4f7e706b0cd3208a3d940a19a822c37a476ddba5450156c3e6624a71f7c841ce +google-auth==2.49.1 \ + --hash=sha256:16d40da1c3c5a0533f57d268fe72e0ebb0ae1cc3b567024122651c045d879b64 \ + --hash=sha256:195ebe3dca18eddd1b3db5edc5189b76c13e96f29e73043b923ebcf3f1a860f7 # via # google-api-core # google-auth-oauthlib @@ -716,37 +726,37 @@ google-auth==2.48.0 \ # google-cloud-storage # pandas-gbq # pydata-google-auth -google-auth-oauthlib==1.2.4 \ - --hash=sha256:0e922eea5f2baacaf8867febb782e46e7b153236c21592ed76ab3ddb77ffd772 \ - --hash=sha256:3ca93859c6cc9003c8e12b2a0868915209d7953f05a70f4880ab57d57e56ee3e +google-auth-oauthlib==1.3.1 \ + --hash=sha256:14c22c7b3dd3d06dbe44264144409039465effdd1eef94f7ce3710e486cc4bfa \ + --hash=sha256:1a139ef23f1318756805b0e95f655c238bffd29655329a2978218248da4ee7f8 # via # pandas-gbq # pydata-google-auth -google-cloud-bigquery[pandas]==3.40.1 \ - --hash=sha256:75afcfb6e007238fe1deefb2182105249321145ff921784fe7b1de2b4ba24506 \ - --hash=sha256:9082a6b8193aba87bed6a2c79cf1152b524c99bb7e7ac33a785e333c09eac868 +google-cloud-bigquery[pandas]==3.41.0 \ + --hash=sha256:2217e488b47ed576360c9b2cc07d59d883a54b83167c0ef37f915c26b01a06fe \ + --hash=sha256:2a5b5a737b401cbd824a6e5eac7554100b878668d908e6548836b5d8aaa4dcaa # via # feast (pyproject.toml) # pandas-gbq -google-cloud-bigquery-storage==2.36.1 \ - --hash=sha256:99ad6b8810d028f0cf368ea0cc54b3cda20e856f05eb4cda51f1db2a70692286 \ - --hash=sha256:fd3917584a41f7a9d9c633b31ff43103869b108224e8a4b765537eb1ea83148c +google-cloud-bigquery-storage==2.37.0 \ + --hash=sha256:1e319c27ef60fc31030f6e0b52e5e891e1cdd50551effe8c6f673a4c3c56fcb6 \ + --hash=sha256:f88ee7f1e49db1e639da3d9a8b79835ca4bc47afbb514fb2adfc0ccb41a7fd97 # via feast (pyproject.toml) -google-cloud-bigtable==2.35.0 \ - --hash=sha256:f355bfce1f239453ec2bb3839b0f4f9937cf34ef06ef29e1ca63d58fd38d0c50 \ - --hash=sha256:f5699012c5fea4bd4bdf7e80e5e3a812a847eb8f41bf8dc2f43095d6d876b83b +google-cloud-bigtable==2.36.0 \ + --hash=sha256:21b2f41231b7368a550b44d5b493b811b3507fcb23eb26d00005cd3f205f2207 \ + --hash=sha256:d5987733c2f60c739f93f259d2037858411cc994ac37cdfbccb6bb159f3ca43e # via feast (pyproject.toml) -google-cloud-core==2.5.0 \ - --hash=sha256:67d977b41ae6c7211ee830c7912e41003ea8194bff15ae7d72fd6f51e57acabc \ - --hash=sha256:7c1b7ef5c92311717bd05301aa1a91ffbc565673d3b0b4163a52d8413a186963 +google-cloud-core==2.5.1 \ + --hash=sha256:3dc94bdec9d05a31d9f355045ed0f369fbc0d8c665076c734f065d729800f811 \ + --hash=sha256:ea62cdf502c20e3e14be8a32c05ed02113d7bef454e40ff3fab6fe1ec9f1f4e7 # via # google-cloud-bigquery # google-cloud-bigtable # google-cloud-datastore # google-cloud-storage -google-cloud-datastore==2.23.0 \ - --hash=sha256:24a1b1d29b902148fe41b109699f76fd3aa60591e9d547c0f8b87d7bf9ff213f \ - --hash=sha256:80049883a4ae928fdcc661ba6803ec267665dc0e6f3ce2da91441079a6bb6387 +google-cloud-datastore==2.24.0 \ + --hash=sha256:81f1d1c12c2906f59507f72742545ab04c38f62ed70b0542057e3cf04a53aa65 \ + --hash=sha256:f087c02a6aa4ac68bbf17f0c048ae3ee355856bf09c51439bfba193741387792 # via feast (pyproject.toml) google-cloud-storage==2.19.0 \ --hash=sha256:aeb971b5c29cf8ab98445082cbfe7b161a1f48ed275822f59ed3f1524ea54fba \ @@ -790,23 +800,23 @@ google-crc32c==1.8.0 \ # google-cloud-bigtable # google-cloud-storage # google-resumable-media -google-resumable-media==2.8.0 \ - --hash=sha256:dd14a116af303845a8d932ddae161a26e86cc229645bc98b39f026f9b1717582 \ - --hash=sha256:f1157ed8b46994d60a1bc432544db62352043113684d4e030ee02e77ebe9a1ae +google-resumable-media==2.8.2 \ + --hash=sha256:82b6d8ccd11765268cdd2a2123f417ec806b8eef3000a9a38dfe3033da5fb220 \ + --hash=sha256:f3354a182ebd193ae3f42e3ef95e6c9b10f128320de23ac7637236713b1acd70 # via # google-cloud-bigquery # google-cloud-storage -googleapis-common-protos[grpc]==1.72.0 \ - --hash=sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038 \ - --hash=sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5 +googleapis-common-protos[grpc]==1.74.0 \ + --hash=sha256:57971e4eeeba6aad1163c1f0fc88543f965bb49129b8bb55b2b7b26ecab084f1 \ + --hash=sha256:702216f78610bb510e3f12ac3cafd281b7ac45cc5d86e90ad87e4d301a3426b5 # via # feast (pyproject.toml) # google-api-core # grpc-google-iam-v1 # grpcio-status -grpc-google-iam-v1==0.14.3 \ - --hash=sha256:7a7f697e017a067206a3dfef44e4c634a34d3dee135fe7d7a4613fe3e59217e6 \ - --hash=sha256:879ac4ef33136c5491a6300e27575a9ec760f6cdf9a2518798c1b8977a5dc389 +grpc-google-iam-v1==0.14.4 \ + --hash=sha256:392b3796947ed6334e61171d9ab06bf7eb357f554e5fc7556ad7aab6d0e17038 \ + --hash=sha256:412facc320fcbd94034b4df3d557662051d4d8adfa86e0ddb4dca70a3f739964 # via google-cloud-bigtable grpcio==1.62.3 \ --hash=sha256:059444f0ed5dba73ab7dd0ee7e8e6b606df4130d2b0a9f010f84da4ab9f6c2d8 \ @@ -887,9 +897,9 @@ grpcio-status==1.62.3 \ --hash=sha256:289bdd7b2459794a12cf95dc0cb727bd4a1742c37bd823f760236c937e53a485 \ --hash=sha256:f9049b762ba8de6b1086789d8315846e094edac2c50beaf462338b301a8fd4b8 # via google-api-core -gunicorn==25.1.0 \ - --hash=sha256:1426611d959fa77e7de89f8c0f32eed6aa03ee735f98c01efba3e281b1c47616 \ - --hash=sha256:d0b1236ccf27f72cfe14bce7caadf467186f19e865094ca84221424e839b8b8b +gunicorn==25.3.0 \ + --hash=sha256:cacea387dab08cd6776501621c295a904fe8e3b7aae9a1a3cbb26f4e7ed54660 \ + --hash=sha256:f74e1b2f9f76f6cd1ca01198968bd2dd65830edc24b6e8e4d78de8320e2fe889 # via # feast (pyproject.toml) # uvicorn-worker @@ -1092,97 +1102,97 @@ kubernetes==35.0.0 \ --hash=sha256:39e2b33b46e5834ef6c3985ebfe2047ab39135d41de51ce7641a7ca5b372a13d \ --hash=sha256:3d00d344944239821458b9efd484d6df9f011da367ecb155dadf9513f05f09ee # via feast (pyproject.toml) -librt==0.8.0 \ - --hash=sha256:001e5330093d887b8b9165823eca6c5c4db183fe4edea4fdc0680bbac5f46944 \ - --hash=sha256:015e2dde6e096d27c10238bf9f6492ba6c65822dfb69d2bf74c41a8e88b7ddef \ - --hash=sha256:02a9fe85410cc9bef045e7cb7fd26fdde6669e6d173f99df659aa7f6335961e9 \ - --hash=sha256:0583aef7e9a720dd40f26a2ad5a1bf2ccbb90059dac2b32ac516df232c701db3 \ - --hash=sha256:05a3dd3f116747f7e1a2b475ccdc6fb637fd4987126d109e03013a79d40bf9e6 \ - --hash=sha256:0a33335eb59921e77c9acc05d0e654e4e32e45b014a4d61517897c11591094f8 \ - --hash=sha256:0ce33a9778e294507f3a0e3468eccb6a698b5166df7db85661543eca1cfc5369 \ - --hash=sha256:1566dbb9d1eb0987264c9b9460d212e809ba908d2f4a3999383a84d765f2f3f1 \ - --hash=sha256:17269dd2745dbe8e42475acb28e419ad92dfa38214224b1b01020b8cac70b645 \ - --hash=sha256:178707cda89d910c3b28bf5aa5f69d3d4734e0f6ae102f753ad79edef83a83c7 \ - --hash=sha256:1c25a131013eadd3c600686a0c0333eb2896483cbc7f65baa6a7ee761017aef9 \ - --hash=sha256:1e6811cac1dcb27ca4c74e0ca4a5917a8e06db0d8408d30daee3a41724bfde7a \ - --hash=sha256:1ef3bd856373cf8e7382402731f43bfe978a8613b4039e49e166e1e0dc590216 \ - --hash=sha256:20f73d4fecba969efc15cdefd030e382502d56bb6f1fc66b580cce582836c9fa \ - --hash=sha256:21b14464bee0b604d80a638cf1ee3148d84ca4cc163dcdcecb46060c1b3605e4 \ - --hash=sha256:24a01c13a2a9bdad20997a4443ebe6e329df063d1978bbe2ebbf637878a46d1e \ - --hash=sha256:25b3e667cbfc9000c4740b282df599ebd91dbdcc1aa6785050e4c1d6be5329ab \ - --hash=sha256:25e82d920d4d62ad741592fcf8d0f3bda0e3fc388a184cb7d2f566c681c5f7b9 \ - --hash=sha256:2b37437e7e4ef5e15a297b36ba9e577f73e29564131d86dd75875705e97402b5 \ - --hash=sha256:2ccdd20d9a72c562ffb73098ac411de351b53a6fbb3390903b2d33078ef90447 \ - --hash=sha256:2e0ffe88ebb5962f8fb0ddcbaaff30f1ea06a79501069310e1e030eafb1ad787 \ - --hash=sha256:375eda7acfce1f15f5ed56cfc960669eefa1ec8732e3e9087c3c4c3f2066759c \ - --hash=sha256:3d2720335020219197380ccfa5c895f079ac364b4c429e96952cd6509934d8eb \ - --hash=sha256:3e36a8da17134ffc29373775d88c04832f9ecfab1880470661813e6c7991ef79 \ - --hash=sha256:3e8b77b5f54d0937b26512774916041756c9eb3e66f1031971e626eea49d0bf4 \ - --hash=sha256:41064a0c07b4cc7a81355ccc305cb097d6027002209ffca51306e65ee8293630 \ - --hash=sha256:421765e8c6b18e64d21c8ead315708a56fc24f44075059702e421d164575fdda \ - --hash=sha256:4831c44b8919e75ca0dfb52052897c1ef59fdae19d3589893fbd068f1e41afbf \ - --hash=sha256:48f84830a8f8ad7918afd743fd7c4eb558728bceab7b0e38fd5a5cf78206a556 \ - --hash=sha256:4b705f85311ee76acec5ee70806990a51f0deb519ea0c29c1d1652d79127604d \ - --hash=sha256:4d3e38797eb482485b486898f89415a6ab163bc291476bd95712e42cf4383c05 \ - --hash=sha256:4eb5e06ebcc668677ed6389164f52f13f71737fc8be471101fa8b4ce77baeb0c \ - --hash=sha256:4f6e975377fbc4c9567cb33ea9ab826031b6c7ec0515bfae66a4fb110d40d6da \ - --hash=sha256:4f764b2424cb04524ff7a486b9c391e93f93dc1bd8305b2136d25e582e99aa2f \ - --hash=sha256:507e94f4bec00b2f590fbe55f48cd518a208e2474a3b90a60aa8f29136ddbada \ - --hash=sha256:56901f1eec031396f230db71c59a01d450715cbbef9856bf636726994331195d \ - --hash=sha256:5cb11061a736a9db45e3c1293cfcb1e3caf205912dfa085734ba750f2197ff9a \ - --hash=sha256:5d0f76fc73480d42285c609c0ea74d79856c160fa828ff9aceab574ea4ecfd7b \ - --hash=sha256:667e2513cf69bfd1e1ed9a00d6c736d5108714ec071192afb737987955888a25 \ - --hash=sha256:671a6152edf3b924d98a5ed5e6982ec9cb30894085482acadce0975f031d4c5c \ - --hash=sha256:693697133c3b32aa9b27f040e3691be210e9ac4d905061859a9ed519b1d5a376 \ - --hash=sha256:6a3146c63220d814c4a2c7d6a1eacc8d5c14aed0ff85115c1dfea868080cd18f \ - --hash=sha256:6b6caff69e25d80c269b1952be8493b4d94ef745f438fa619d7931066bdd26de \ - --hash=sha256:6e1af31a710e17891d9adf0dbd9a5fcd94901a3922a96499abdbf7ce658f4e01 \ - --hash=sha256:70defb797c4d5402166787a6b3c66dfb3fa7f93d118c0509ffafa35a392f4258 \ - --hash=sha256:71fc517efc14f75c2f74b1f0a5d5eb4a8e06aa135c34d18eaf3522f4a53cd62d \ - --hash=sha256:75d1a8cab20b2043f03f7aab730551e9e440adc034d776f15f6f8d582b0a5ad4 \ - --hash=sha256:789911e8fa40a2e82f41120c936b1965f3213c67f5a483fc5a41f5839a05dcbb \ - --hash=sha256:7bd68cebf3131bb920d5984f75fe302d758db33264e44b45ad139385662d7bc3 \ - --hash=sha256:7ce0a8cb67e702dcb06342b2aaaa3da9fb0ddc670417879adfa088b44cf7b3b6 \ - --hash=sha256:7f820210e21e3a8bf8fde2ae3c3d10106d4de9ead28cbfdf6d0f0f41f5b12fa1 \ - --hash=sha256:8070aa3368559de81061ef752770d03ca1f5fc9467d4d512d405bd0483bfffe6 \ - --hash=sha256:82e61cd1c563745ad495387c3b65806bfd453badb4adbc019df3389dddee1bf6 \ - --hash=sha256:82fb4602d1b3e303a58bfe6165992b5a78d823ec646445356c332cd5f5bbaa61 \ - --hash=sha256:88c6e75540f1f10f5e0fc5e87b4b6c290f0e90d1db8c6734f670840494764af8 \ - --hash=sha256:8992ca186a1678107b0af3d0c9303d8c7305981b9914989b9788319ed4d89546 \ - --hash=sha256:92249938ab744a5890580d3cb2b22042f0dce71cdaa7c1369823df62bedf7cbc \ - --hash=sha256:95a719a049f0eefaf1952673223cf00d442952273cbd20cf2ed7ec423a0ef58d \ - --hash=sha256:9646178cd794704d722306c2c920c221abbf080fede3ba539d5afdec16c46dad \ - --hash=sha256:9726305d3e53419d27fc8cdfcd3f9571f0ceae22fa6b5ea1b3662c2e538f833e \ - --hash=sha256:995d24caa6bbb34bcdd4a41df98ac6d1af637cfa8975cb0790e47d6623e70e3e \ - --hash=sha256:9ab3a3475a55b89b87ffd7e6665838e8458e0b596c22e0177e0f961434ec474a \ - --hash=sha256:9f09d4884f882baa39a7e36bbf3eae124c4ca2a223efb91e567381d1c55c6b06 \ - --hash=sha256:a512c88900bdb1d448882f5623a0b1ad27ba81a9bd75dacfe17080b72272ca1f \ - --hash=sha256:a905091a13e0884701226860836d0386b88c72ce5c2fdfba6618e14c72be9f25 \ - --hash=sha256:aaadec87f45a3612b6818d1db5fbfe93630669b7ee5d6bdb6427ae08a1aa2141 \ - --hash=sha256:b055bb3abaf69abed25743d8fc1ab691e4f51a912ee0a6f9a6c84f4bbddb283d \ - --hash=sha256:b4bb00bd71b448f16749909b08a0ff16f58b079e2261c2e1000f2bbb2a4f0a45 \ - --hash=sha256:b9aef96d7593584e31ef6ac1eb9775355b0099fee7651fae3a15bc8657b67b52 \ - --hash=sha256:ba581acad5ac8f33e2ff1746e8a57e001b47c6721873121bf8bbcf7ba8bd3aa4 \ - --hash=sha256:ba9d9e60651615bc614be5e21a82cdb7b1769a029369cf4b4d861e4f19686fb6 \ - --hash=sha256:bbebd2bba5c6ae02907df49150e55870fdd7440d727b6192c46b6f754723dde9 \ - --hash=sha256:bd32add59b58fba3439d48d6f36ac695830388e3da3e92e4fc26d2d02670d19c \ - --hash=sha256:bdab762e2c0b48bab76f1a08acb3f4c77afd2123bedac59446aeaaeed3d086cf \ - --hash=sha256:c5512aae4648152abaf4d48b59890503fcbe86e85abc12fb9b096fe948bdd816 \ - --hash=sha256:c6e4c10761ddbc0d67d2f6e2753daf99908db85d8b901729bf2bf5eaa60e0567 \ - --hash=sha256:cb4b3ad543084ed79f186741470b251b9d269cd8b03556f15a8d1a99a64b7de5 \ - --hash=sha256:cb74cdcbc0103fc988e04e5c58b0b31e8e5dd2babb9182b6f9490488eb36324b \ - --hash=sha256:cc3d107f603b5ee7a79b6aa6f166551b99b32fb4a5303c4dfcb4222fc6a0335e \ - --hash=sha256:d920789eca7ef71df7f31fd547ec0d3002e04d77f30ba6881e08a630e7b2c30e \ - --hash=sha256:daae5e955764be8fd70a93e9e5133c75297f8bce1e802e1d3683b98f77e1c5ab \ - --hash=sha256:db63cf3586a24241e89ca1ce0b56baaec9d371a328bd186c529b27c914c9a1ef \ - --hash=sha256:db953b675079884ffda33d1dca7189fb961b6d372153750beb81880384300817 \ - --hash=sha256:de076eaba208d16efb5962f99539867f8e2c73480988cb513fcf1b5dbb0c9dcf \ - --hash=sha256:e79dbc8f57de360f0ed987dc7de7be814b4803ef0e8fc6d3ff86e16798c99935 \ - --hash=sha256:e9a3a38eb4134ad33122a6d575e6324831f930a771d951a15ce232e0237412c2 \ - --hash=sha256:f04ca50e847abc486fa8f4107250566441e693779a5374ba211e96e238f298b9 \ - --hash=sha256:f1178e0de0c271231a660fbef9be6acdfa1d596803464706862bef6644cc1cae \ - --hash=sha256:f4617cef654fca552f00ce5ffdf4f4b68770f18950e4246ce94629b789b92467 \ - --hash=sha256:fa37f99bff354ff191c6bcdffbc9d7cdd4fc37faccfc9be0ef3a4fd5613977da +librt==0.8.1 \ + --hash=sha256:01170b6729a438f0dedc4a26ed342e3dc4f02d1000b4b19f980e1877f0c297e6 \ + --hash=sha256:039b9f2c506bd0ab0f8725aa5ba339c6f0cd19d3b514b50d134789809c24285d \ + --hash=sha256:05bd41cdee35b0c59c259f870f6da532a2c5ca57db95b5f23689fcb5c9e42440 \ + --hash=sha256:086a32dbb71336627e78cc1d6ee305a68d038ef7d4c39aaff41ae8c9aa46e91a \ + --hash=sha256:08eec3a1fc435f0d09c87b6bf1ec798986a3544f446b864e4099633a56fcd9ed \ + --hash=sha256:0bf69d79a23f4f40b8673a947a234baeeb133b5078b483b7297c5916539cf5d5 \ + --hash=sha256:0c3811485fccfda840861905b8c70bba5ec094e02825598bb9d4ca3936857a04 \ + --hash=sha256:0d2f82168e55ddefd27c01c654ce52379c0750ddc31ee86b4b266bcf4d65f2a3 \ + --hash=sha256:0f2ae3725904f7377e11cc37722d5d401e8b3d5851fb9273d7f4fe04f6b3d37d \ + --hash=sha256:10c42e1f6fd06733ef65ae7bebce2872bcafd8d6e6b0a08fe0a05a23b044fb14 \ + --hash=sha256:153188fe98a72f206042be10a2c6026139852805215ed9539186312d50a8e972 \ + --hash=sha256:172d57ec04346b047ca6af181e1ea4858086c80bdf455f61994c4aa6fc3f866c \ + --hash=sha256:190b109bb69592a3401fe1ffdea41a2e73370ace2ffdc4a0e8e2b39cdea81b78 \ + --hash=sha256:1d3a7da44baf692f0c6aeb5b2a09c5e6fc7a703bca9ffa337ddd2e2da53f7732 \ + --hash=sha256:228c2409c079f8c11fb2e5d7b277077f694cb93443eb760e00b3b83cb8b3176c \ + --hash=sha256:22b46eabd76c1986ee7d231b0765ad387d7673bbd996aa0d0d054b38ac65d8f6 \ + --hash=sha256:237796479f4d0637d6b9cbcb926ff424a97735e68ade6facf402df4ec93375ed \ + --hash=sha256:2c74a2da57a094bd48d03fa5d196da83d2815678385d2978657499063709abe1 \ + --hash=sha256:2cc68eeeef5e906839c7bb0815748b5b0a974ec27125beefc0f942715785b551 \ + --hash=sha256:2eb345e8b33fb748227409c9f1233d4df354d6e54091f0e8fc53acdb2ffedeb7 \ + --hash=sha256:31362dbfe297b23590530007062c32c6f6176f6099646bb2c95ab1b00a57c382 \ + --hash=sha256:3dff3d3ca8db20e783b1bc7de49c0a2ab0b8387f31236d6a026597d07fcd68ac \ + --hash=sha256:43353b943613c5d9c49a25aaffdba46f888ec354e71e3529a00cca3f04d66a7a \ + --hash=sha256:439352ba9373f11cb8e1933da194dcc6206daf779ff8df0ed69c5e39113e6a99 \ + --hash=sha256:4998009e7cb9e896569f4be7004f09d0ed70d386fa99d42b6d363f6d200501ac \ + --hash=sha256:4be2a5c926b9770c9e08e717f05737a269b9d0ebc5d2f0060f0fe3fe9ce47acb \ + --hash=sha256:4beb04b8c66c6ae62f8c1e0b2f097c1ebad9295c929a8d5286c05eae7c2fc7dc \ + --hash=sha256:4c8dfa264b9193c4ee19113c985c95f876fae5e51f731494fc4e0cf594990ba7 \ + --hash=sha256:5212a5bd7fae98dae95710032902edcd2ec4dc994e883294f75c857b83f9aba0 \ + --hash=sha256:52c224e14614b750c0a6d97368e16804a98c684657c7518752c356834fff83bb \ + --hash=sha256:56e04c14b696300d47b3bc5f1d10a00e86ae978886d0cee14e5714fafb5df5d2 \ + --hash=sha256:5bb54f1205a3a6ab41a6fd71dfcdcbd278670d3a90ca502a30d9da583105b6f7 \ + --hash=sha256:5cdc0f588ff4b663ea96c26d2a230c525c6fc62b28314edaaaca8ed5af931ad0 \ + --hash=sha256:5db05697c82b3a2ec53f6e72b2ed373132b0c2e05135f0696784e97d7f5d48e7 \ + --hash=sha256:5e4af413908f77294605e28cfd98063f54b2c790561383971d2f52d113d9c363 \ + --hash=sha256:5fc48998000cbc39ec0d5311312dda93ecf92b39aaf184c5e817d5d440b29624 \ + --hash=sha256:60a78b694c9aee2a0f1aaeaa7d101cf713e92e8423a941d2897f4fa37908dab9 \ + --hash=sha256:64548cde61b692dc0dc379f4b5f59a2f582c2ebe7890d09c1ae3b9e66fa015b7 \ + --hash=sha256:681dc2451d6d846794a828c16c22dc452d924e9f700a485b7ecb887a30aad1fd \ + --hash=sha256:6b1977c4ea97ce5eb7755a78fae68d87e4102e4aaf54985e8b56806849cc06a3 \ + --hash=sha256:6cfa7fe54fd4d1f47130017351a959fe5804bda7a0bc7e07a2cdbc3fdd28d34f \ + --hash=sha256:738f08021b3142c2918c03692608baed43bc51144c29e35807682f8070ee2a3a \ + --hash=sha256:747328be0c5b7075cde86a0e09d7a9196029800ba75a1689332348e998fb85c0 \ + --hash=sha256:758509ea3f1eba2a57558e7e98f4659d0ea7670bff49673b0dde18a3c7e6c0eb \ + --hash=sha256:785ae29c1f5c6e7c2cde2c7c0e148147f4503da3abc5d44d482068da5322fd9e \ + --hash=sha256:7aae78ab5e3206181780e56912d1b9bb9f90a7249ce12f0e8bf531d0462dd0fc \ + --hash=sha256:7b02679a0d783bdae30d443025b94465d8c3dc512f32f5b5031f93f57ac32071 \ + --hash=sha256:7e2f3edca35664499fbb36e4770650c4bd4a08abc1f4458eab9df4ec56389730 \ + --hash=sha256:7e6bad1cd94f6764e1e21950542f818a09316645337fd5ab9a7acc45d99a8f35 \ + --hash=sha256:81fd938344fecb9373ba1b155968c8a329491d2ce38e7ddb76f30ffb938f12dc \ + --hash=sha256:82210adabbc331dbb65d7868b105185464ef13f56f7f76688565ad79f648b0fe \ + --hash=sha256:89815a22daf9c51884fb5dbe4f1ef65ee6a146e0b6a8df05f753e2e4a9359bf4 \ + --hash=sha256:8f1125e6bbf2f1657d9a2f3ccc4a2c9b0c8b176965bb565dd4d86be67eddb4b6 \ + --hash=sha256:8f4bb453f408137d7581be309b2fbc6868a80e7ef60c88e689078ee3a296ae71 \ + --hash=sha256:924817ab3141aca17893386ee13261f1d100d1ef410d70afe4389f2359fea4f0 \ + --hash=sha256:93c2af9e01e0ef80d95ae3c720be101227edae5f2fe7e3dc63d8857fadfc5a1d \ + --hash=sha256:97c2b54ff6717a7a563b72627990bec60d8029df17df423f0ed37d56a17a176b \ + --hash=sha256:9be2f15e53ce4e83cc08adc29b26fb5978db62ef2a366fbdf716c8a6c8901040 \ + --hash=sha256:9e2c6f77b9ad48ce5603b83b7da9ee3e36b3ab425353f695cba13200c5d96596 \ + --hash=sha256:a28f2612ab566b17f3698b0da021ff9960610301607c9a5e8eaca62f5e1c350a \ + --hash=sha256:a355d99c4c0d8e5b770313b8b247411ed40949ca44e33e46a4789b9293a907ee \ + --hash=sha256:a3b4350b13cc0e6f5bec8fa7caf29a8fb8cdc051a3bae45cfbfd7ce64f009965 \ + --hash=sha256:aaab0e307e344cb28d800957ef3ec16605146ef0e59e059a60a176d19543d1b7 \ + --hash=sha256:ac1e7817fd0ed3d14fd7c5df91daed84c48e4c2a11ee99c0547f9f62fdae13da \ + --hash=sha256:adfab487facf03f0d0857b8710cf82d0704a309d8ffc33b03d9302b4c64e91a9 \ + --hash=sha256:b6d7ab1f01aa753188605b09a51faa44a3327400b00b8cce424c71910fc0a128 \ + --hash=sha256:bacdb58d9939d95cc557b4dbaa86527c9db2ac1ed76a18bc8d26f6dc8647d851 \ + --hash=sha256:be46a14693955b3bd96014ccbdb8339ee8c9346fbe11c1b78901b55125f14c73 \ + --hash=sha256:bf512a71a23504ed08103a13c941f763db13fb11177beb3d9244c98c29fb4a61 \ + --hash=sha256:c00e5c884f528c9932d278d5c9cbbea38a6b81eb62c02e06ae53751a83a4d52b \ + --hash=sha256:c25d9e338d5bed46c1632f851babf3d13c78f49a225462017cf5e11e845c5891 \ + --hash=sha256:c336d61d2fe74a3195edc1646d53ff1cddd3a9600b09fa6ab75e5514ba4862a7 \ + --hash=sha256:cc3656283d11540ab0ea01978378e73e10002145117055e03722417aeab30994 \ + --hash=sha256:cf450f498c30af55551ba4f66b9123b7185362ec8b625a773b3d39aa1a717583 \ + --hash=sha256:d0ee06b5b5291f609ddb37b9750985b27bc567791bc87c76a569b3feed8481ac \ + --hash=sha256:d480de377f5b687b6b1bc0c0407426da556e2a757633cc7e4d2e1a057aa688f3 \ + --hash=sha256:d56bc4011975f7460bea7b33e1ff425d2f1adf419935ff6707273c77f8a4ada6 \ + --hash=sha256:dd3c41254ee98604b08bd5b3af5bf0a89740d4ee0711de95b65166bf44091921 \ + --hash=sha256:e0d138c7ae532908cbb342162b2611dbd4d90c941cd25ab82084aaf71d2c0bd0 \ + --hash=sha256:e11769a1dbda4da7b00a76cfffa67aa47cfa66921d2724539eee4b9ede780b79 \ + --hash=sha256:e3f0a41487fd5fad7e760b9e8a90e251e27c2816fbc2cff36a22a0e6bcbbd9dd \ + --hash=sha256:e692aa2d1d604e6ca12d35e51fdc36f4cda6345e28e36374579f7ef3611b3012 \ + --hash=sha256:e70a57ecf89a0f64c24e37f38d3fe217a58169d2fe6ed6d70554964042474023 \ + --hash=sha256:e96baa6820280077a78244b2e06e416480ed859bbd8e5d641cf5742919d8beb4 \ + --hash=sha256:eb5656019db7c4deacf0c1a55a898c5bb8f989be904597fcb5232a2f4828fa05 \ + --hash=sha256:eca45e982fa074090057132e30585a7e8674e9e885d402eae85633e9f449ce6c \ + --hash=sha256:f0af2bd2bc204fa27f3d6711d0f360e6b8c684a035206257a81673ab924aa11e \ + --hash=sha256:f7cdf7f26c2286ffb02e46d7bac56c94655540b26347673bea15fa52a6af17e9 \ + --hash=sha256:fd1a720332ea335ceb544cf0a03f81df92abd4bb887679fd1e460976b0e6214b \ + --hash=sha256:ff8baf1f8d3f4b6b7257fcb75a501f2a5499d0dda57645baa09d4d0d34b19444 # via mypy locket==1.0.0 \ --hash=sha256:5c0d4c052a8bbbf750e056a8e65ccd309086f4f0f18a2eac306a8dfa4112a632 \ @@ -1283,9 +1293,9 @@ markupsafe==3.0.3 \ --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \ --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50 # via jinja2 -mcp==1.26.0 \ - --hash=sha256:904a21c33c25aa98ddbeb47273033c435e595bbacfdb177f4bd87f6dceebe1ca \ - --hash=sha256:db6e2ef491eecc1a0d93711a76f28dec2e05999f93afd48795da1c1137142c66 +mcp==1.27.0 \ + --hash=sha256:5ce1fa81614958e267b21fb2aa34e0aea8e2c6ede60d52aba45fd47246b4d741 \ + --hash=sha256:d3dc35a7eec0d458c1da4976a48f982097ddaab87e278c5511d5a4a56e852b83 # via fastapi-mcp mdurl==0.1.2 \ --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ @@ -1299,128 +1309,114 @@ milvus-lite==2.4.12 \ # via # feast (pyproject.toml) # pymilvus -mmh3==5.2.0 \ - --hash=sha256:03e08c6ebaf666ec1e3d6ea657a2d363bb01effd1a9acfe41f9197decaef0051 \ - --hash=sha256:097e13c8b8a66c5753c6968b7640faefe85d8e38992703c1f666eda6ef4c3762 \ - --hash=sha256:0b898cecff57442724a0f52bf42c2de42de63083a91008fb452887e372f9c328 \ - --hash=sha256:10983c10f5c77683bd845751905ba535ec47409874acc759d5ce3ff7ef34398a \ - --hash=sha256:11730eeb16dfcf9674fdea9bb6b8e6dd9b40813b7eb839bc35113649eef38aeb \ - --hash=sha256:127c95336f2a98c51e7682341ab7cb0be3adb9df0819ab8505a726ed1801876d \ - --hash=sha256:12da42c0a55c9d86ab566395324213c319c73ecb0c239fad4726324212b9441c \ - --hash=sha256:132dd943451a7c7546978863d2f5a64977928410782e1a87d583cb60eb89e667 \ - --hash=sha256:1556e31e4bd0ac0c17eaf220be17a09c171d7396919c3794274cb3415a9d3646 \ - --hash=sha256:1a5f4d2e59d6bba8ef01b013c472741835ad961e7c28f50c82b27c57748744a4 \ - --hash=sha256:1ba55d6ca32eeef8b2625e1e4bfc3b3db52bc63014bd7e5df8cc11bf2b036b12 \ - --hash=sha256:1efc8fec8478e9243a78bb993422cf79f8ff85cb4cf6b79647480a31e0d950a8 \ - --hash=sha256:1f8d8b627799f4e2fcc7c034fed8f5f24dc7724ff52f69838a3d6d15f1ad4765 \ - --hash=sha256:1fae471339ae1b9c641f19cf46dfe6ffd7f64b1fba7c4333b99fa3dd7f21ae0a \ - --hash=sha256:1fdb36b940e9261aff0b5177c5b74a36936b902f473180f6c15bde26143681a9 \ - --hash=sha256:2421b9d665a0b1ad724ec7332fb5a98d075f50bc51a6ff854f3a1882bd650d49 \ - --hash=sha256:29c2b9ce61886809d0492a274a5a53047742dea0f703f9c4d5d223c3ea6377d3 \ - --hash=sha256:2c9da0d568569cc87315cb063486d761e38458b8ad513fedd3dc9263e1b81bcd \ - --hash=sha256:2ebfc46b39168ab1cd44670a32ea5489bcbc74a25795c61b6d888c5c2cf654ed \ - --hash=sha256:3193752fc05ea72366c2b63ff24b9a190f422e32d75fdeae71087c08fff26115 \ - --hash=sha256:33576136c06b46a7046b6d83a3d75fbca7d25f84cec743f1ae156362608dc6d2 \ - --hash=sha256:37a358cc881fe796e099c1db6ce07ff757f088827b4e8467ac52b7a7ffdca647 \ - --hash=sha256:382a6bb3f8c6532ea084e7acc5be6ae0c6effa529240836d59352398f002e3fc \ - --hash=sha256:384eda9361a7bf83a85e09447e1feafe081034af9dd428893701b959230d84be \ - --hash=sha256:38d899a156549da8ef6a9f1d6f7ef231228d29f8f69bce2ee12f5fba6d6fd7c5 \ - --hash=sha256:3bc244802ccab5220008cb712ca1508cb6a12f0eb64ad62997156410579a1770 \ - --hash=sha256:3c6041fd9d5fb5fcac57d5c80f521a36b74aea06b8566431c63e4ffc49aced51 \ - --hash=sha256:3ca975c51c5028947bbcfc24966517aac06a01d6c921e30f7c5383c195f87991 \ - --hash=sha256:3d6bfd9662a20c054bc216f861fa330c2dac7c81e7fb8307b5e32ab5b9b4d2e0 \ - --hash=sha256:419005f84ba1cab47a77465a2a843562dadadd6671b8758bf179d82a15ca63eb \ - --hash=sha256:45b590e31bc552c6f8e2150ff1ad0c28dd151e9f87589e7eaf508fbdd8e8e908 \ - --hash=sha256:49037d417419863b222ae47ee562b2de9c3416add0a45c8d7f4e864be8dc4f89 \ - --hash=sha256:4a5f5536b1cbfa72318ab3bfc8a8188b949260baed186b75f0abc75b95d8c051 \ - --hash=sha256:582f9dbeefe15c32a5fa528b79b088b599a1dfe290a4436351c6090f90ddebb8 \ - --hash=sha256:58477cf9ef16664d1ce2b038f87d2dc96d70fe50733a34a7f07da6c9a5e3538c \ - --hash=sha256:58981d6ea9646dbbf9e59a30890cbf9f610df0e4a57dbfe09215116fd90b0093 \ - --hash=sha256:5a5dba98e514fb26241868f6eb90a7f7ca0e039aed779342965ce24ea32ba513 \ - --hash=sha256:5b0b58215befe0f0e120b828f7645e97719bbba9f23b69e268ed0ac7adde8645 \ - --hash=sha256:61ac226af521a572700f863d6ecddc6ece97220ce7174e311948ff8c8919a363 \ - --hash=sha256:63830f846797187c5d3e2dae50f0848fdc86032f5bfdc58ae352f02f857e9025 \ - --hash=sha256:69fc339d7202bea69ef9bd7c39bfdf9fdabc8e6822a01eba62fb43233c1b3932 \ - --hash=sha256:6d541038b3fc360ec538fc116de87462627944765a6750308118f8b509a8eec7 \ - --hash=sha256:6ecb4e750d712abde046858ee6992b65c93f1f71b397fce7975c3860c07365d2 \ - --hash=sha256:72d80005b7634a3a2220f81fbeb94775ebd12794623bb2e1451701ea732b4aa3 \ - --hash=sha256:7303aab41e97adcf010a09efd8f1403e719e59b7705d5e3cfed3dd7571589290 \ - --hash=sha256:7434a27754049144539d2099a6d2da5d88b8bdeedf935180bf42ad59b3607aa3 \ - --hash=sha256:746a5ee71c6d1103d9b560fa147881b5e68fd35da56e54e03d5acefad0e7c055 \ - --hash=sha256:7733ec52296fc1ba22e9b90a245c821adbb943e98c91d8a330a2254612726106 \ - --hash=sha256:7901c893e704ee3c65f92d39b951f8f34ccf8e8566768c58103fb10e55afb8c1 \ - --hash=sha256:7aa18cdb58983ee660c9c400b46272e14fa253c675ed963d3812487f8ca42037 \ - --hash=sha256:7b986d506a8e8ea345791897ba5d8ba0d9d8820cd4fc3e52dbe6de19388de2e7 \ - --hash=sha256:7bbb0df897944b5ec830f3ad883e32c5a7375370a521565f5fe24443bfb2c4f7 \ - --hash=sha256:7c7f0b342fd06044bedd0b6e72177ddc0076f54fd89ee239447f8b271d919d9b \ - --hash=sha256:7e5634565367b6d98dc4aa2983703526ef556b3688ba3065edb4b9b90ede1c54 \ - --hash=sha256:7fddccd4113e7b736706e17a239a696332360cbaddf25ae75b57ba1acce65081 \ - --hash=sha256:81c504ad11c588c8629536b032940f2a359dda3b6cbfd4ad8f74cb24dcd1b0bc \ - --hash=sha256:81df0dae22cd0da87f1c978602750f33d17fb3d21fb0f326c89dc89834fea79b \ - --hash=sha256:86d1be5d63232e6eb93c50881aea55ff06eb86d8e08f9b5417c8c9b10db9db96 \ - --hash=sha256:8b0c53fe0994beade1ad7c0f13bd6fec980a0664bfbe5a6a7d64500b9ab76772 \ - --hash=sha256:8ebf241072cf2777a492d0e09252f8cc2b3edd07dfdb9404b9757bffeb4f2cee \ - --hash=sha256:931d47e08c9c8a67bf75d82f0ada8399eac18b03388818b62bfa42882d571d72 \ - --hash=sha256:932a6eec1d2e2c3c9e630d10f7128d80e70e2d47fe6b8c7ea5e1afbd98733e65 \ - --hash=sha256:941603bfd75a46023807511c1ac2f1b0f39cccc393c15039969806063b27e6db \ - --hash=sha256:956127e663d05edbeec54df38885d943dfa27406594c411139690485128525de \ - --hash=sha256:96f1e1ac44cbb42bcc406e509f70c9af42c594e72ccc7b1257f97554204445f0 \ - --hash=sha256:99bb6a4d809aa4e528ddfe2c85dd5239b78b9dd14be62cca0329db78505e7b50 \ - --hash=sha256:9f64bf06f4bf623325fda3a6d02d36cd69199b9ace99b04bb2d7fd9f89688504 \ - --hash=sha256:a094319ec0db52a04af9fdc391b4d39a1bc72bc8424b47c4411afb05413a44b5 \ - --hash=sha256:a367d4741ac0103f8198c82f429bccb9359f543ca542b06a51f4f0332e8de279 \ - --hash=sha256:a7c0c7845566b9686480e6a7e9044db4afb60038d5fabd19227443f0104eeee4 \ - --hash=sha256:aa6e5d31fdc5ed9e3e95f9873508615a778fe9b523d52c17fc770a3eb39ab6e4 \ - --hash=sha256:ae9d032488fcec32d22be6542d1a836f00247f40f320844dbb361393b5b22773 \ - --hash=sha256:b0271ac12415afd3171ab9a3c7cbfc71dee2c68760a7dc9d05bf8ed6ddfa3a7a \ - --hash=sha256:b0d753ad566c721faa33db7e2e0eddd74b224cdd3eaf8481d76c926603c7a00e \ - --hash=sha256:b29044e1ffdb84fe164d0a7ea05c7316afea93c00f8ed9449cf357c36fc4f814 \ - --hash=sha256:b5995088dd7023d2d9f310a0c67de5a2b2e06a570ecfd00f9ff4ab94a67cde43 \ - --hash=sha256:b5f317a727bba0e633a12e71228bc6a4acb4f471a98b1c003163b917311ea9a9 \ - --hash=sha256:b9a87025121d1c448f24f27ff53a5fe7b6ef980574b4a4f11acaabe702420d63 \ - --hash=sha256:bb0fdc451fb6d86d81ab8f23d881b8d6e37fc373a2deae1c02d27002d2ad7a05 \ - --hash=sha256:bb4fe46bdc6104fbc28db7a6bacb115ee6368ff993366bbd8a2a7f0076e6f0c0 \ - --hash=sha256:bc44fc2b886243d7c0d8daeb37864e16f232e5b56aaec27cc781d848264cfd28 \ - --hash=sha256:bdde97310d59604f2a9119322f61b31546748499a21b44f6715e8ced9308a6c5 \ - --hash=sha256:be1374df449465c9f2500e62eee73a39db62152a8bdfbe12ec5b5c1cd451344d \ - --hash=sha256:be7d3dca9358e01dab1bad881fb2b4e8730cec58d36dd44482bc068bfcd3bc65 \ - --hash=sha256:bf7bee43e17e81671c447e9c83499f53d99bf440bc6d9dc26a841e21acfbe094 \ - --hash=sha256:c3dca4cb5b946ee91b3d6bb700d137b1cd85c20827f89fdf9c16258253489044 \ - --hash=sha256:c3f563e8901960e2eaa64c8e8821895818acabeb41c96f2efbb936f65dbe486c \ - --hash=sha256:c463d7c1c4cfc9d751efeaadd936bbba07b5b0ed81a012b3a9f5a12f0872bd6e \ - --hash=sha256:c4a2f3d83879e3de2eb8cbf562e71563a8ed15ee9b9c2e77ca5d9f73072ac15c \ - --hash=sha256:c5584061fd3da584659b13587f26c6cad25a096246a481636d64375d0c1f6c07 \ - --hash=sha256:c677d78887244bf3095020b73c42b505b700f801c690f8eaa90ad12d3179612f \ - --hash=sha256:c903e71fd8debb35ad2a4184c1316b3cb22f64ce517b4e6747f25b0a34e41266 \ - --hash=sha256:c9ff37ba9f15637e424c2ab57a1a590c52897c845b768e4e0a4958084ec87f22 \ - --hash=sha256:cadc16e8ea64b5d9a47363013e2bea469e121e6e7cb416a7593aeb24f2ad122e \ - --hash=sha256:cedac4f4054b8f7859e5aed41aaa31ad03fce6851901a7fdc2af0275ac533c10 \ - --hash=sha256:d22c9dcafed659fadc605538946c041722b6d1104fe619dbf5cc73b3c8a0ded8 \ - --hash=sha256:d765058da196f68dc721116cab335e696e87e76720e6ef8ee5a24801af65e63d \ - --hash=sha256:d86651fa45799530885ba4dab3d21144486ed15285e8784181a0ab37a4552384 \ - --hash=sha256:dd966df3489ec13848d6c6303429bbace94a153f43d1ae2a55115fd36fd5ca5d \ - --hash=sha256:ddc63328889bcaee77b743309e5c7d2d52cee0d7d577837c91b6e7cc9e755e0b \ - --hash=sha256:dfbead5575f6470c17e955b94f92d62a03dfc3d07f2e6f817d9b93dc211a1515 \ - --hash=sha256:e0f3ed828d709f5b82d8bfe14f8856120718ec4bd44a5b26102c3030a1e12501 \ - --hash=sha256:e1861fb6b1d0453ed7293200139c0a9011eeb1376632e048e3766945b13313c5 \ - --hash=sha256:e5015f0bb6eb50008bed2d4b1ce0f2a294698a926111e4bb202c0987b4f89078 \ - --hash=sha256:e651e17bfde5840e9e4174b01e9e080ce49277b70d424308b36a7969d0d1af73 \ - --hash=sha256:e7884931fe5e788163e7b3c511614130c2c59feffdc21112290a194487efb2e9 \ - --hash=sha256:e79c00eba78f7258e5b354eccd4d7907d60317ced924ea4a5f2e9d83f5453065 \ - --hash=sha256:e912b19cf2378f2967d0c08e86ff4c6c360129887f678e27e4dde970d21b3f4d \ - --hash=sha256:e9a011469b47b752e7d20de296bb34591cdfcbe76c99c2e863ceaa2aa61113d2 \ - --hash=sha256:eb756caf8975882630ce4e9fbbeb9d3401242a72528230422c9ab3a0d278e60c \ - --hash=sha256:eba01ec3bd4a49b9ac5ca2bc6a73ff5f3af53374b8556fcc2966dd2af9eb7779 \ - --hash=sha256:ecbfc0437ddfdced5e7822d1ce4855c9c64f46819d0fdc4482c53f56c707b935 \ - --hash=sha256:eed4bba7ff8a0d37106ba931ab03bdd3915fbb025bcf4e1f0aa02bc8114960c5 \ - --hash=sha256:f35727c5118aba95f0397e18a1a5b8405425581bfe53e821f0fb444cbdc2bc9b \ - --hash=sha256:f698733a8a494466432d611a8f0d1e026f5286dee051beea4b3c3146817e35d5 \ - --hash=sha256:f7f9034c7cf05ddfaac8d7a2e63a3c97a840d4615d0a0e65ba8bdf6f8576e3be \ - --hash=sha256:fa0c966ee727aad5406d516375593c5f058c766b21236ab8985693934bb5085b \ - --hash=sha256:fc9c5f280438cf1c1a8f9abb87dc8ce9630a964120cfb5dd50d1e7ce79690c7a \ - --hash=sha256:fd6e6c3d90660d085f7e73710eab6f5545d4854b81b0135a3526e797009dbda3 \ - --hash=sha256:fdfd3fb739f4e22746e13ad7ba0c6eedf5f454b18d11249724a388868e308ee4 \ - --hash=sha256:ff3d50dc3fe8a98059f99b445dfb62792b5d006c5e0b8f03c6de2813b8376110 +mmh3==5.2.1 \ + --hash=sha256:022aa1a528604e6c83d0a7705fdef0b5355d897a9e0fa3a8d26709ceaa06965d \ + --hash=sha256:0634581290e6714c068f4aa24020acf7880927d1f0084fa753d9799ae9610082 \ + --hash=sha256:08043f7cb1fb9467c3fbbbaea7896986e7fbc81f4d3fd9289a73d9110ab6207a \ + --hash=sha256:0a3984146e414684a6be2862d84fcb1035f4984851cb81b26d933bab6119bf00 \ + --hash=sha256:0bbc17250b10d3466875a40a52520a6bac3c02334ca709207648abd3c223ed5c \ + --hash=sha256:0cc21533878e5586b80d74c281d7f8da7932bc8ace50b8d5f6dbf7e3935f63f1 \ + --hash=sha256:0d0b7e803191db5f714d264044e06189c8ccd3219e936cc184f07106bd17fd7b \ + --hash=sha256:113f78e7463a36dbbcea05bfe688efd7fa759d0f0c56e73c974d60dcfec3dfcc \ + --hash=sha256:169e0d178cb59314456ab30772429a802b25d13227088085b0d49b9fe1533104 \ + --hash=sha256:17fbb47f0885ace8327ce1235d0416dc86a211dcd8cc1e703f41523be32cfec8 \ + --hash=sha256:19bbd3b841174ae6ed588536ab5e1b1fe83d046e668602c20266547298d939a9 \ + --hash=sha256:1d9f9a3ce559a5267014b04b82956993270f63ec91765e13e9fd73daf2d2738e \ + --hash=sha256:1e4ecee40ba19e6975e1120829796770325841c2f153c0e9aecca927194c6a2a \ + --hash=sha256:22b0f9971ec4e07e8223f2beebe96a6cfc779d940b6f27d26604040dd74d3a44 \ + --hash=sha256:26fb5b9c3946bf7f1daed7b37e0c03898a6f062149127570f8ede346390a0825 \ + --hash=sha256:2778fed822d7db23ac5008b181441af0c869455b2e7d001f4019636ac31b6fe4 \ + --hash=sha256:28cfab66577000b9505a0d068c731aee7ca85cd26d4d63881fab17857e0fe1fb \ + --hash=sha256:29bc3973676ae334412efdd367fcd11d036b7be3efc1ce2407ef8676dabfeb82 \ + --hash=sha256:2bd9f19f7f1fcebd74e830f4af0f28adad4975d40d80620be19ffb2b2af56c9f \ + --hash=sha256:2d5d542bf2abd0fd0361e8017d03f7cb5786214ceb4a40eef1539d6585d93386 \ + --hash=sha256:30e4d2084df019880d55f6f7bea35328d9b464ebee090baa372c096dc77556fb \ + --hash=sha256:3619473a0e0d329fd4aec8075628f8f616be2da41605300696206d6f36920c3d \ + --hash=sha256:368625fb01666655985391dbad3860dc0ba7c0d6b9125819f3121ee7292b4ac8 \ + --hash=sha256:3737303ca9ea0f7cb83028781148fcda4f1dac7821db0c47672971dabcf63593 \ + --hash=sha256:3a9fed49c6ce4ed7e73f13182760c65c816da006debe67f37635580dfb0fae00 \ + --hash=sha256:3c38d142c706201db5b2345166eeef1e7740e3e2422b470b8ba5c8727a9b4c7a \ + --hash=sha256:3cb61db880ec11e984348227b333259994c2c85caa775eb7875decb3768db890 \ + --hash=sha256:3d74a03fb57757ece25aa4b3c1c60157a1cece37a020542785f942e2f827eed5 \ + --hash=sha256:3f796b535008708846044c43302719c6956f39ca2d93f2edda5319e79a29efbb \ + --hash=sha256:41105377f6282e8297f182e393a79cfffd521dde37ace52b106373bdcd9ca5cb \ + --hash=sha256:41aac7002a749f08727cb91babff1daf8deac317c0b1f317adc69be0e6c375d1 \ + --hash=sha256:44983e45310ee5b9f73397350251cdf6e63a466406a105f1d16cb5baa659270b \ + --hash=sha256:4cbbde66f1183db040daede83dd86c06d663c5bb2af6de1142b7c8c37923dd74 \ + --hash=sha256:4eda76074cfca2787c8cf1bec603eaebdddd8b061ad5502f85cddae998d54f00 \ + --hash=sha256:4fc6cd65dc4d2fdb2625e288939a3566e36127a84811a4913f02f3d5931da52d \ + --hash=sha256:50885073e2909251d4718634a191c49ae5f527e5e1736d738e365c3e8be8f22b \ + --hash=sha256:5174a697ce042fa77c407e05efe41e03aa56dae9ec67388055820fb48cf4c3ba \ + --hash=sha256:54b64fb2433bc71488e7a449603bf8bd31fbcf9cb56fbe1eb6d459e90b86c37b \ + --hash=sha256:54fe8518abe06a4c3852754bfd498b30cc58e667f376c513eac89a244ce781a4 \ + --hash=sha256:55dbbd8ffbc40d1697d5e2d0375b08599dae8746b0b08dea05eee4ce81648fac \ + --hash=sha256:57b52603e89355ff318025dd55158f6e71396c0f1f609d548e9ea9c94cc6ce0a \ + --hash=sha256:58370d05d033ee97224c81263af123dea3d931025030fd34b61227a768a8858a \ + --hash=sha256:5d87a3584093e1a89987e3d36d82c98d9621b2cb944e22a420aa1401e096758f \ + --hash=sha256:623f938f6a039536cc02b7582a07a080f13fdfd48f87e63201d92d7e34d09a18 \ + --hash=sha256:62815d2c67f2dd1be76a253d88af4e1da19aeaa1820146dec52cf8bee2958b16 \ + --hash=sha256:6290289fa5fb4c70fd7f72016e03633d60388185483ff3b162912c81205ae2cf \ + --hash=sha256:67e41a497bac88cc1de96eeba56eeb933c39d54bc227352f8455aa87c4ca4000 \ + --hash=sha256:6c85c38a279ca9295a69b9b088a2e48aa49737bb1b34e6a9dc6297c110e8d912 \ + --hash=sha256:6f01f044112d43a20be2f13a11683666d87151542ad627fe41a18b9791d2802f \ + --hash=sha256:707151644085dd0f20fe4f4b573d28e5130c4aaa5f587e95b60989c5926653b5 \ + --hash=sha256:723b2681ed4cc07d3401bbea9c201ad4f2a4ca6ba8cddaff6789f715dd2b391e \ + --hash=sha256:72d1cc63bcc91e14933f77d51b3df899d6a07d184ec515ea7f56bff659e124d7 \ + --hash=sha256:7374d6e3ef72afe49697ecd683f3da12f4fc06af2d75433d0580c6746d2fa025 \ + --hash=sha256:7501e9be34cb21e72fcfe672aafd0eee65c16ba2afa9dcb5500a587d3a0580f0 \ + --hash=sha256:76219cd1eefb9bf4af7856e3ae563d15158efa145c0aab01e9933051a1954045 \ + --hash=sha256:7aec798c2b01aaa65a55f1124f3405804184373abb318a3091325aece235f67c \ + --hash=sha256:7be6dfb49e48fd0a7d91ff758a2b51336f1cd21f9d44b20f6801f072bd080cdd \ + --hash=sha256:7e4e1f580033335c6f76d1e0d6b56baf009d1a64d6a4816347e4271ba951f46d \ + --hash=sha256:7e8ec5f606e0809426d2440e0683509fb605a8820a21ebd120dcdba61b74ef7f \ + --hash=sha256:7f196cd7910d71e9d9860da0ff7a77f64d22c1ad931f1dd18559a06e03109fc0 \ + --hash=sha256:82f3802bfc4751f420d591c5c864de538b71cea117fce67e4595c2afede08a15 \ + --hash=sha256:85ffc9920ffc39c5eee1e3ac9100c913a0973996fbad5111f939bbda49204bb7 \ + --hash=sha256:8e6c219e375f6341d0959af814296372d265a8ca1af63825f65e2e87c618f006 \ + --hash=sha256:8f767ba0911602ddef289404e33835a61168314ebd3c729833db2ed685824211 \ + --hash=sha256:8ff038d52ef6aa0f309feeba00c5095c9118d0abf787e8e8454d6048db2037fc \ + --hash=sha256:915e7a2418f10bd1151b1953df06d896db9783c9cfdb9a8ee1f9b3a4331ab503 \ + --hash=sha256:92883836caf50d5255be03d988d75bc93e3f86ba247b7ca137347c323f731deb \ + --hash=sha256:960b1b3efa39872ac8b6cc3a556edd6fb90ed74f08c9c45e028f1005b26aa55d \ + --hash=sha256:9aeaf53eaa075dd63e81512522fd180097312fb2c9f476333309184285c49ce0 \ + --hash=sha256:9d8089d853c7963a8ce87fff93e2a67075c0bc08684a08ea6ad13577c38ffc38 \ + --hash=sha256:a4130d0b9ce5fad6af07421b1aecc7e079519f70d6c05729ab871794eded8617 \ + --hash=sha256:a482ac121de6973897c92c2f31defc6bafb11c83825109275cffce54bb64933f \ + --hash=sha256:add7ac388d1e0bf57259afbcf9ed05621a3bf11ce5ee337e7536f1e1aaf056b0 \ + --hash=sha256:b1f12bd684887a0a5d55e6363ca87056f361e45451105012d329b86ec19dbe0b \ + --hash=sha256:b3f99e1756fc48ad507b95e5d86f2fb21b3d495012ff13e6592ebac14033f166 \ + --hash=sha256:b4cce60d0223074803c9dbe0721ad3fa51dafe7d462fee4b656a1aa01ee07518 \ + --hash=sha256:baeb47635cb33375dee4924cd93d7f5dcaa786c740b08423b0209b824a1ee728 \ + --hash=sha256:bbea5b775f0ac84945191fb83f845a6fd9a21a03ea7f2e187defac7e401616ad \ + --hash=sha256:bbfcb95d9a744e6e2827dfc66ad10e1020e0cac255eb7f85652832d5a264c2fc \ + --hash=sha256:bd6e7d363aa93bd3421b30b6af97064daf47bc96005bddba67c5ffbc6df426b8 \ + --hash=sha256:be77c402d5e882b6fbacfd90823f13da8e0a69658405a39a569c6b58fdb17b03 \ + --hash=sha256:c302245fd6c33d96bd169c7ccf2513c20f4c1e417c07ce9dce107c8bc3f8411f \ + --hash=sha256:c88653877aeb514c089d1b3d473451677b8b9a6d1497dbddf1ae7934518b06d2 \ + --hash=sha256:cae6383181f1e345317742d2ddd88f9e7d2682fa4c9432e3a74e47d92dce0229 \ + --hash=sha256:cd471ede0d802dd936b6fab28188302b2d497f68436025857ca72cd3810423fe \ + --hash=sha256:d106493a60dcb4aef35a0fac85105e150a11cf8bc2b0d388f5a33272d756c966 \ + --hash=sha256:d30b650595fdbe32366b94cb14f30bb2b625e512bd4e1df00611f99dc5c27fd4 \ + --hash=sha256:d51fde50a77f81330523562e3c2734ffdca9c4c9e9d355478117905e1cfe16c6 \ + --hash=sha256:d57dea657357230cc780e13920d7fa7db059d58fe721c80020f94476da4ca0a1 \ + --hash=sha256:d771f085fcdf4035786adfb1d8db026df1eb4b41dac1c3d070d1e49512843227 \ + --hash=sha256:dae0f0bd7d30c0ad61b9a504e8e272cb8391eed3f1587edf933f4f6b33437450 \ + --hash=sha256:db0562c5f71d18596dcd45e854cf2eeba27d7543e1a3acdafb7eef728f7fe85d \ + --hash=sha256:dfd51b4c56b673dfbc43d7d27ef857dd91124801e2806c69bb45585ce0fa019b \ + --hash=sha256:e080c0637aea036f35507e803a4778f119a9b436617694ae1c5c366805f1e997 \ + --hash=sha256:e48d4dbe0f88e53081da605ae68644e5182752803bbc2beb228cca7f1c4454d6 \ + --hash=sha256:e8b4b5580280b9265af3e0409974fb79c64cf7523632d03fbf11df18f8b0181e \ + --hash=sha256:e8b5378de2b139c3a830f0209c1e91f7705919a4b3e563a10955104f5097a70a \ + --hash=sha256:e904f2417f0d6f6d514f3f8b836416c360f306ddaee1f84de8eef1e722d212e5 \ + --hash=sha256:eee884572b06bbe8a2b54f424dbd996139442cf83c76478e1ec162512e0dd2c7 \ + --hash=sha256:f1fbb0a99125b1287c6d9747f937dc66621426836d1a2d50d05aecfc81911b57 \ + --hash=sha256:f40a95186a72fa0b67d15fef0f157bfcda00b4f59c8a07cbe5530d41ac35d105 \ + --hash=sha256:f6e0bfe77d238308839699944164b96a2eeccaf55f2af400f54dc20669d8d5f2 \ + --hash=sha256:f963eafc0a77a6c0562397da004f5876a9bcf7265a7bcc3205e29636bc4a1312 \ + --hash=sha256:fb9d44c25244e11c8be3f12c938ca8ba8404620ef8092245d2093c6ab3df260f \ + --hash=sha256:fc78739b5ec6e4fb02301984a3d442a91406e7700efbe305071e7fd1c78278f2 \ + --hash=sha256:fceef7fe67c81e1585198215e42ad3fdba3a25644beda8fbdaf85f4d7b93175a \ + --hash=sha256:fd96476f04db5ceba1cfa0f21228f67c1f7402296f0e73fee3513aa680ad237b # via feast (pyproject.toml) multidict==6.7.1 \ --hash=sha256:026d264228bcd637d4e060844e39cdc60f86c479e463d49075dedc21b18fbbe0 \ @@ -1573,123 +1569,129 @@ multidict==6.7.1 \ # aiobotocore # aiohttp # yarl -mypy==1.19.1 \ - --hash=sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd \ - --hash=sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b \ - --hash=sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1 \ - --hash=sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba \ - --hash=sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b \ - --hash=sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045 \ - --hash=sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac \ - --hash=sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6 \ - --hash=sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a \ - --hash=sha256:409088884802d511ee52ca067707b90c883426bd95514e8cfda8281dc2effe24 \ - --hash=sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957 \ - --hash=sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042 \ - --hash=sha256:4f28f99c824ecebcdaa2e55d82953e38ff60ee5ec938476796636b86afa3956e \ - --hash=sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec \ - --hash=sha256:7bcfc336a03a1aaa26dfce9fff3e287a3ba99872a157561cbfcebe67c13308e3 \ - --hash=sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718 \ - --hash=sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f \ - --hash=sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331 \ - --hash=sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1 \ - --hash=sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1 \ - --hash=sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13 \ - --hash=sha256:b13cfdd6c87fc3efb69ea4ec18ef79c74c3f98b4e5498ca9b85ab3b2c2329a67 \ - --hash=sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2 \ - --hash=sha256:b7951a701c07ea584c4fe327834b92a30825514c868b1f69c30445093fdd9d5a \ - --hash=sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b \ - --hash=sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8 \ - --hash=sha256:c608937067d2fc5a4dd1a5ce92fd9e1398691b8c5d012d66e1ddd430e9244376 \ - --hash=sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef \ - --hash=sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288 \ - --hash=sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75 \ - --hash=sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74 \ - --hash=sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250 \ - --hash=sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab \ - --hash=sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6 \ - --hash=sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247 \ - --hash=sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925 \ - --hash=sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e \ - --hash=sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e +mypy==1.20.0 \ + --hash=sha256:002b613ae19f4ac7d18b7e168ffe1cb9013b37c57f7411984abbd3b817b0a214 \ + --hash=sha256:00e047c74d3ec6e71a2eb88e9ea551a2edb90c21f993aefa9e0d2a898e0bb732 \ + --hash=sha256:02cca0761c75b42a20a2757ae58713276605eb29a08dd8a6e092aa347c4115ca \ + --hash=sha256:0ecd63f75fdd30327e4ad8b5704bd6d91fc6c1b2e029f8ee14705e1207212489 \ + --hash=sha256:0f42dfaab7ec1baff3b383ad7af562ab0de573c5f6edb44b2dab016082b89948 \ + --hash=sha256:1973868d2adbb4584a3835780b27436f06d1dc606af5be09f187aaa25be1070f \ + --hash=sha256:26c8b52627b6552f47ff11adb4e1509605f094e29815323e487fc0053ebe93d1 \ + --hash=sha256:2721f0ce49cb74a38f00c50da67cb7d36317b5eda38877a49614dc018e91c787 \ + --hash=sha256:2fcedb16d456106e545b2bfd7ef9d24e70b38ec252d2a629823a4d07ebcdb69e \ + --hash=sha256:31b5dbb55293c1bd27c0fc813a0d2bb5ceef9d65ac5afa2e58f829dab7921fd5 \ + --hash=sha256:34506397dbf40c15dc567635d18a21d33827e9ab29014fb83d292a8f4f8953b6 \ + --hash=sha256:367e5c993ba34d5054d11937d0485ad6dfc60ba760fa326c01090fc256adf15c \ + --hash=sha256:379edf079ce44ac8d2805bcf9b3dd7340d4f97aad3a5e0ebabbf9d125b84b442 \ + --hash=sha256:39362cdb4ba5f916e7976fccecaab1ba3a83e35f60fa68b64e9a70e221bb2436 \ + --hash=sha256:4525e7010b1b38334516181c5b81e16180b8e149e6684cee5a727c78186b4e3b \ + --hash=sha256:47781555a7aa5fedcc2d16bcd72e0dc83eb272c10dd657f9fb3f9cc08e2e6abb \ + --hash=sha256:49d11c6f573a5a08f77fad13faff2139f6d0730ebed2cfa9b3d2702671dd7188 \ + --hash=sha256:555493c44a4f5a1b58d611a43333e71a9981c6dbe26270377b6f8174126a0526 \ + --hash=sha256:555658c611099455b2da507582ea20d2043dfdfe7f5ad0add472b1c6238b433f \ + --hash=sha256:697f102c5c1d526bdd761a69f17c6070f9892eebcb94b1a5963d679288c09e78 \ + --hash=sha256:76a70bf840495729be47510856b978f1b0ec7d08f257ca38c9d932720bf6b43e \ + --hash=sha256:7d3243c406773185144527f83be0e0aefc7bf4601b0b2b956665608bf7c98a83 \ + --hash=sha256:931a7630bba591593dcf6e97224a21ff80fb357e7982628d25e3c618e7f598ef \ + --hash=sha256:9804c3ad27f78e54e58b32e7cb532d128b43dbfb9f3f9f06262b821a0f6bd3f5 \ + --hash=sha256:a17c5d0bdcca61ce24a35beb828a2d0d323d3fcf387d7512206888c900193367 \ + --hash=sha256:a6e0641147cbfa7e4e94efdb95c2dab1aff8cfc159ded13e07f308ddccc8c48e \ + --hash=sha256:a79c1eba7ac4209f2d850f0edd0a2f8bba88cbfdfefe6fb76a19e9d4fe5e71a2 \ + --hash=sha256:a9336b5e6712f4adaf5afc3203a99a40b379049104349d747eb3e5a3aa23ac2e \ + --hash=sha256:b20c8b0fd5877abdf402e79a3af987053de07e6fb208c18df6659f708b535134 \ + --hash=sha256:b3a49064504be59e59da664c5e149edc1f26c67c4f8e8456f6ba6aba55033018 \ + --hash=sha256:b503ab55a836136b619b5fc21c8803d810c5b87551af8600b72eecafb0059cb0 \ + --hash=sha256:bd0212976dc57a5bfeede7c219e7cd66568a32c05c9129686dd487c059c1b88a \ + --hash=sha256:c70380fe5d64010f79fb863b9081c7004dd65225d2277333c219d93a10dad4dd \ + --hash=sha256:d99f515f95fd03a90875fdb2cca12ff074aa04490db4d190905851bdf8a549a8 \ + --hash=sha256:e80cf77847d0d3e6e3111b7b25db32a7f8762fd4b9a3a72ce53fe16a2863b281 \ + --hash=sha256:eb96c84efcc33f0b5e0e04beacf00129dd963b67226b01c00b9dfc8affb464c3 \ + --hash=sha256:ebea00201737ad4391142808ed16e875add5c17f676e0912b387739f84991e13 \ + --hash=sha256:efe8d70949c3023698c3fca1e94527e7e790a361ab8116f90d11221421cd8726 \ + --hash=sha256:f13b3e41bce9d257eded794c0f12878af3129d80aacd8a3ee0dee51f3a978651 \ + --hash=sha256:f194db59657c58593a3c47c6dfd7bad4ef4ac12dbc94d01b3a95521f78177e33 \ + --hash=sha256:f49590891d2c2f8a9de15614e32e459a794bcba84693c2394291a2038bbaaa69 \ + --hash=sha256:f75ff57defcd0f1d6e006d721ccdec6c88d4f6a7816eb92f1c4890d979d9ee62 \ + --hash=sha256:f799d9db89fc00446f03281f84a221e50018fc40113a3ba9864b132895619ebe \ + --hash=sha256:f8426d4d75d68714abc17a4292d922f6ba2cfb984b72c2278c437f6dae797865 # via sqlalchemy mypy-extensions==1.1.0 \ --hash=sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505 \ --hash=sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558 # via mypy -numpy==2.4.2 \ - --hash=sha256:00ab83c56211a1d7c07c25e3217ea6695e50a3e2f255053686b081dc0b091a82 \ - --hash=sha256:068cdb2d0d644cdb45670810894f6a0600797a69c05f1ac478e8d31670b8ee75 \ - --hash=sha256:0f01dcf33e73d80bd8dc0f20a71303abbafa26a19e23f6b68d1aa9990af90257 \ - --hash=sha256:0fece1d1f0a89c16b03442eae5c56dc0be0c7883b5d388e0c03f53019a4bfd71 \ - --hash=sha256:12e26134a0331d8dbd9351620f037ec470b7c75929cb8a1537f6bfe411152a1a \ - --hash=sha256:1ae241bbfc6ae276f94a170b14785e561cb5e7f626b6688cf076af4110887413 \ - --hash=sha256:1f92f53998a17265194018d1cc321b2e96e900ca52d54c7c77837b71b9465181 \ - --hash=sha256:209fae046e62d0ce6435fcfe3b1a10537e858249b3d9b05829e2a05218296a85 \ - --hash=sha256:20abd069b9cda45874498b245c8015b18ace6de8546bf50dfa8cea1696ed06ef \ - --hash=sha256:21982668592194c609de53ba4933a7471880ccbaadcc52352694a59ecc860b3a \ - --hash=sha256:25f2059807faea4b077a2b6837391b5d830864b3543627f381821c646f31a63c \ - --hash=sha256:2653de5c24910e49c2b106499803124dde62a5a1fe0eedeaecf4309a5f639390 \ - --hash=sha256:2b8f157c8a6f20eb657e240f8985cc135598b2b46985c5bccbde7616dc9c6b1e \ - --hash=sha256:2fb882da679409066b4603579619341c6d6898fc83a8995199d5249f986e8e8f \ - --hash=sha256:40397bda92382fcec844066efb11f13e1c9a3e2a8e8f318fb72ed8b6db9f60f1 \ - --hash=sha256:444be170853f1f9d528428eceb55f12918e4fda5d8805480f36a002f1415e09b \ - --hash=sha256:47c5a6ed21d9452b10227e5e8a0e1c22979811cad7dcc19d8e3e2fb8fa03f1a3 \ - --hash=sha256:4f069069931240b3fc703f1e23df63443dbd6390614c8c44a87d96cd0ec81eb1 \ - --hash=sha256:52b913ec40ff7ae845687b0b34d8d93b60cb66dcee06996dd5c99f2fc9328657 \ - --hash=sha256:5633c0da313330fd20c484c78cdd3f9b175b55e1a766c4a174230c6b70ad8262 \ - --hash=sha256:5daf6f3914a733336dab21a05cdec343144600e964d2fcdabaac0c0269874b2a \ - --hash=sha256:5eea80d908b2c1f91486eb95b3fb6fab187e569ec9752ab7d9333d2e66bf2d6b \ - --hash=sha256:602f65afdef699cda27ec0b9224ae5dc43e328f4c24c689deaf77133dbee74d0 \ - --hash=sha256:659a6107e31a83c4e33f763942275fd278b21d095094044eb35569e86a21ddae \ - --hash=sha256:66cb9422236317f9d44b67b4d18f44efe6e9c7f8794ac0462978513359461554 \ - --hash=sha256:6d82351358ffbcdcd7b686b90742a9b86632d6c1c051016484fa0b326a0a1548 \ - --hash=sha256:6e9f61981ace1360e42737e2bae58b27bf28a1b27e781721047d84bd754d32e7 \ - --hash=sha256:6ed0be1ee58eef41231a5c943d7d1375f093142702d5723ca2eb07db9b934b05 \ - --hash=sha256:7cdde6de52fb6664b00b056341265441192d1291c130e99183ec0d4b110ff8b1 \ - --hash=sha256:7df2de1e4fba69a51c06c28f5a3de36731eb9639feb8e1cf7e4a7b0daf4cf622 \ - --hash=sha256:7edc794af8b36ca37ef5fcb5e0d128c7e0595c7b96a2318d1badb6fcd8ee86b1 \ - --hash=sha256:7f54844851cdb630ceb623dcec4db3240d1ac13d4990532446761baede94996a \ - --hash=sha256:805cc8de9fd6e7a22da5aed858e0ab16be5a4db6c873dde1d7451c541553aa27 \ - --hash=sha256:8906e71fd8afcb76580404e2a950caef2685df3d2a57fe82a86ac8d33cc007ba \ - --hash=sha256:89f7268c009bc492f506abd6f5265defa7cb3f7487dc21d357c3d290add45082 \ - --hash=sha256:8c50dd1fc8826f5b26a5ee4d77ca55d88a895f4e4819c7ecc2a9f5905047a443 \ - --hash=sha256:8e4549f8a3c6d13d55041925e912bfd834285ef1dd64d6bc7d542583355e2e98 \ - --hash=sha256:8e9afaeb0beff068b4d9cd20d322ba0ee1cecfb0b08db145e4ab4dd44a6b5110 \ - --hash=sha256:98f16a80e917003a12c0580f97b5f875853ebc33e2eaa4bccfc8201ac6869308 \ - --hash=sha256:9e35d3e0144137d9fdae62912e869136164534d64a169f86438bc9561b6ad49f \ - --hash=sha256:9e4424677ce4b47fe73c8b5556d876571f7c6945d264201180db2dc34f676ab5 \ - --hash=sha256:adb6ed2ad29b9e15321d167d152ee909ec73395901b70936f029c3bc6d7f4460 \ - --hash=sha256:aea4f66ff44dfddf8c2cffd66ba6538c5ec67d389285292fe428cb2c738c8aef \ - --hash=sha256:b21041e8cb6a1eb5312dd1d2f80a94d91efffb7a06b70597d44f1bd2dfc315ab \ - --hash=sha256:b2f0073ed0868db1dcd86e052d37279eef185b9c8db5bf61f30f46adac63c909 \ - --hash=sha256:b3a24467af63c67829bfaa61eecf18d5432d4f11992688537be59ecd6ad32f5e \ - --hash=sha256:b9c618d56a29c9cb1c4da979e9899be7578d2e0b3c24d52079c166324c9e8695 \ - --hash=sha256:bba37bc29d4d85761deed3954a1bc62be7cf462b9510b51d367b769a8c8df325 \ - --hash=sha256:bd3a7a9f5847d2fb8c2c6d1c862fa109c31a9abeca1a3c2bd5a64572955b2979 \ - --hash=sha256:be71bf1edb48ebbbf7f6337b5bfd2f895d1902f6335a5830b20141fc126ffba0 \ - --hash=sha256:c02ef4401a506fb60b411467ad501e1429a3487abca4664871d9ae0b46c8ba32 \ - --hash=sha256:c3cd545784805de05aafe1dde61752ea49a359ccba9760c1e5d1c88a93bbf2b7 \ - --hash=sha256:c7ac672d699bf36275c035e16b65539931347d68b70667d28984c9fb34e07fa7 \ - --hash=sha256:cb7bbb88aa74908950d979eeaa24dbdf1a865e3c7e45ff0121d8f70387b55f73 \ - --hash=sha256:cd2bd2bbed13e213d6b55dc1d035a4f91748a7d3edc9480c13898b0353708920 \ - --hash=sha256:cda077c2e5b780200b6b3e09d0b42205a3d1c68f30c6dceb90401c13bff8fe74 \ - --hash=sha256:cf28c0c1d4c4bf00f509fa7eb02c58d7caf221b50b467bcb0d9bbf1584d5c821 \ - --hash=sha256:d0d9b7c93578baafcbc5f0b83eaf17b79d345c6f36917ba0c67f45226911d499 \ - --hash=sha256:d1240d50adff70c2a88217698ca844723068533f3f5c5fa6ee2e3220e3bdb000 \ - --hash=sha256:d30291931c915b2ab5717c2974bb95ee891a1cf22ebc16a8006bd59cd210d40a \ - --hash=sha256:d9f64d786b3b1dd742c946c42d15b07497ed14af1a1f3ce840cce27daa0ce913 \ - --hash=sha256:da6cad4e82cb893db4b69105c604d805e0c3ce11501a55b5e9f9083b47d2ffe8 \ - --hash=sha256:df1b10187212b198dd45fa943d8985a3c8cf854aed4923796e0e019e113a1bda \ - --hash=sha256:e04ae107ac591763a47398bb45b568fc38f02dbc4aa44c063f67a131f99346cb \ - --hash=sha256:e6dee3bb76aa4009d5a912180bf5b2de012532998d094acee25d9cb8dee3e44a \ - --hash=sha256:e7e88598032542bd49af7c4747541422884219056c268823ef6e5e89851c8825 \ - --hash=sha256:e98c97502435b53741540a5717a6749ac2ada901056c7db951d33e11c885cc7d \ - --hash=sha256:ec055f6dae239a6299cace477b479cca2fc125c5675482daf1dd886933a1076f \ - --hash=sha256:f74f0f7779cc7ae07d1810aab8ac6b1464c3eafb9e283a40da7309d5e6e48fbb \ - --hash=sha256:fbde1b0c6e81d56f5dccd95dd4a711d9b95df1ae4009a60887e56b27e8d903fa \ - --hash=sha256:fcf92bee92742edd401ba41135185866f7026c502617f422eb432cfeca4fe236 \ - --hash=sha256:fd49860271d52127d61197bb50b64f58454e9f578cb4b2c001a6de8b1f50b0b1 +numpy==2.4.4 \ + --hash=sha256:07077278157d02f65c43b1b26a3886bce886f95d20aabd11f87932750dfb14ed \ + --hash=sha256:08f2e31ed5e6f04b118e49821397f12767934cfdd12a1ce86a058f91e004ee50 \ + --hash=sha256:0aec54fd785890ecca25a6003fd9a5aed47ad607bbac5cd64f836ad8666f4959 \ + --hash=sha256:0d35aea54ad1d420c812bfa0385c71cd7cc5bcf7c65fed95fc2cd02fe8c79827 \ + --hash=sha256:0d4e437e295f18ec29bc79daf55e8a47a9113df44d66f702f02a293d93a2d6dd \ + --hash=sha256:0dfd3f9d3adbe2920b68b5cd3d51444e13a10792ec7154cd0a2f6e74d4ab3233 \ + --hash=sha256:1378871da56ca8943c2ba674530924bb8ca40cd228358a3b5f302ad60cf875fc \ + --hash=sha256:15716cfef24d3a9762e3acdf87e27f58dc823d1348f765bbea6bef8c639bfa1b \ + --hash=sha256:19710a9ca9992d7174e9c52f643d4272dcd1558c5f7af7f6f8190f633bd651a7 \ + --hash=sha256:23cbfd4c17357c81021f21540da84ee282b9c8fba38a03b7b9d09ba6b951421e \ + --hash=sha256:2483e4584a1cb3092da4470b38866634bafb223cbcd551ee047633fd2584599a \ + --hash=sha256:27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d \ + --hash=sha256:28a650663f7314afc3e6ec620f44f333c386aad9f6fc472030865dc0ebb26ee3 \ + --hash=sha256:2aa0613a5177c264ff5921051a5719d20095ea586ca88cc802c5c218d1c67d3e \ + --hash=sha256:2c194dd721e54ecad9ad387c1d35e63dce5c4450c6dc7dd5611283dda239aabb \ + --hash=sha256:2d19e6e2095506d1736b7d80595e0f252d76b89f5e715c35e06e937679ea7d7a \ + --hash=sha256:2d390634c5182175533585cc89f3608a4682ccb173cc9bb940b2881c8d6f8fa0 \ + --hash=sha256:30caa73029a225b2d40d9fae193e008e24b2026b7ee1a867b7ee8d96ca1a448e \ + --hash=sha256:42c16925aa5a02362f986765f9ebabf20de75cdefdca827d14315c568dcab113 \ + --hash=sha256:45dbed2ab436a9e826e302fcdcbe9133f9b0006e5af7168afb8963a6520da103 \ + --hash=sha256:4636de7fd195197b7535f231b5de9e4b36d2c440b6e566d2e4e4746e6af0ca93 \ + --hash=sha256:4a19d9dba1a76618dd86b164d608566f393f8ec6ac7c44f0cc879011c45e65af \ + --hash=sha256:4bbc7f303d125971f60ec0aaad5e12c62d0d2c925f0ab1273debd0e4ba37aba5 \ + --hash=sha256:4d6d57903571f86180eb98f8f0c839fa9ebbfb031356d87f1361be91e433f5b7 \ + --hash=sha256:4e874c976154687c1f71715b034739b45c7711bec81db01914770373d125e392 \ + --hash=sha256:51fc224f7ca4d92656d5a5eb315f12eb5fe2c97a66249aa7b5f562528a3be38c \ + --hash=sha256:58c8b5929fcb8287cbd6f0a3fae19c6e03a5c48402ae792962ac465224a629a4 \ + --hash=sha256:5a285b3b96f951841799528cd1f4f01cd70e7e0204b4abebac9463eecfcf2a40 \ + --hash=sha256:5c70f1cc1c4efbe316a572e2d8b9b9cc44e89b95f79ca3331553fbb63716e2bf \ + --hash=sha256:62d6b0f03b694173f9fcb1fb317f7222fd0b0b103e784c6549f5e53a27718c44 \ + --hash=sha256:6a246d5914aa1c820c9443ddcee9c02bec3e203b0c080349533fae17727dfd1b \ + --hash=sha256:6aa3236c78803afbcb255045fbef97a9e25a1f6c9888357d205ddc42f4d6eba5 \ + --hash=sha256:6bbe4eb67390b0a0265a2c25458f6b90a409d5d069f1041e6aff1e27e3d9a79e \ + --hash=sha256:715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74 \ + --hash=sha256:72944b19f2324114e9dc86a159787333b77874143efcf89a5167ef83cfee8af0 \ + --hash=sha256:81f4a14bee47aec54f883e0cad2d73986640c1590eb9bfaaba7ad17394481e6e \ + --hash=sha256:846300f379b5b12cc769334464656bc882e0735d27d9726568bc932fdc49d5ec \ + --hash=sha256:86b6f55f5a352b48d7fbfd2dbc3d5b780b2d79f4d3c121f33eb6efb22e9a2015 \ + --hash=sha256:874f200b2a981c647340f841730fc3a2b54c9d940566a3c4149099591e2c4c3d \ + --hash=sha256:8a87ec22c87be071b6bdbd27920b129b94f2fc964358ce38f3822635a3e2e03d \ + --hash=sha256:8b3b60bb7cba2c8c81837661c488637eee696f59a877788a396d33150c35d842 \ + --hash=sha256:8e3ed142f2728df44263aaf5fb1f5b0b99f4070c553a0d7f033be65338329150 \ + --hash=sha256:93e15038125dc1e5345d9b5b68aa7f996ec33b98118d18c6ca0d0b7d6198b7e8 \ + --hash=sha256:989824e9faf85f96ec9c7761cd8d29c531ad857bfa1daa930cba85baaecf1a9a \ + --hash=sha256:99d838547ace2c4aace6c4f76e879ddfe02bb58a80c1549928477862b7a6d6ed \ + --hash=sha256:9b2aec6af35c113b05695ebb5749a787acd63cafc83086a05771d1e1cd1e555f \ + --hash=sha256:9c585a1790d5436a5374bac930dad6ed244c046ed91b2b2a3634eb2971d21008 \ + --hash=sha256:a7164afb23be6e37ad90b2f10426149fd75aee07ca55653d2aa41e66c4ef697e \ + --hash=sha256:ac6b31e35612a26483e20750126d30d0941f949426974cace8e6b5c58a3657b0 \ + --hash=sha256:ad2e2ef14e0b04e544ea2fa0a36463f847f113d314aa02e5b402fdf910ef309e \ + --hash=sha256:b268594bccac7d7cf5844c7732e3f20c50921d94e36d7ec9b79e9857694b1b2f \ + --hash=sha256:b5f0362dc928a6ecd9db58868fca5e48485205e3855957bdedea308f8672ea4a \ + --hash=sha256:ba1f4fc670ed79f876f70082eff4f9583c15fb9a4b89d6188412de4d18ae2f40 \ + --hash=sha256:ba203255017337d39f89bdd58417f03c4426f12beed0440cfd933cb15f8669c7 \ + --hash=sha256:c901b15172510173f5cb310eae652908340f8dede90fff9e3bf6c0d8dfd92f83 \ + --hash=sha256:c9b39d38a9bd2ae1becd7eac1303d031c5c110ad31f2b319c6e7d98b135c934d \ + --hash=sha256:d2a8490669bfe99a233298348acc2d824d496dee0e66e31b66a6022c2ad74a5c \ + --hash=sha256:dddbbd259598d7240b18c9d87c56a9d2fb3b02fe266f49a7c101532e78c1d871 \ + --hash=sha256:df3775294accfdd75f32c74ae39fcba920c9a378a2fc18a12b6820aa8c1fb502 \ + --hash=sha256:e44319a2953c738205bf3354537979eaa3998ed673395b964c1176083dd46252 \ + --hash=sha256:e4a010c27ff6f210ff4c6ef34394cd61470d01014439b192ec22552ee867f2a8 \ + --hash=sha256:e823b8b6edc81e747526f70f71a9c0a07ac4e7ad13020aa736bb7c9d67196115 \ + --hash=sha256:e892aff75639bbef0d2a2cfd55535510df26ff92f63c92cd84ef8d4ba5a5557f \ + --hash=sha256:eea7ac5d2dce4189771cedb559c738a71512768210dc4e4753b107a2048b3d0e \ + --hash=sha256:ef4059d6e5152fa1a39f888e344c73fdc926e1b2dd58c771d67b0acfbf2aa67d \ + --hash=sha256:f169b9a863d34f5d11b8698ead99febeaa17a13ca044961aa8e2662a6c7766a0 \ + --hash=sha256:f2cf083b324a467e1ab358c105f6cad5ea950f50524668a80c486ff1db24e119 \ + --hash=sha256:f8474c4241bc18b750be2abea9d7a9ec84f46ef861dbacf86a4f6e043401f79e \ + --hash=sha256:f983334aea213c99992053ede6168500e5f086ce74fbc4acc3f2b00f5762e9db \ + --hash=sha256:f9e75681b59ddaa5e659898085ae0eaea229d054f2ac0c7e563a62205a700121 \ + --hash=sha256:fbc356aae7adf9e6336d336b9c8111d390a05df88f1805573ebb0807bd06fd1d \ + --hash=sha256:fcfe2045fd2e8f3cb0ce9d4ba6dba6333b8fa05bb8a4939c908cd43322d14c7e # via # feast (pyproject.toml) # dask @@ -1777,9 +1779,9 @@ pandas==2.3.3 \ # pandas-gbq # pymilvus # snowflake-connector-python -pandas-gbq==0.33.0 \ - --hash=sha256:499ad18a7b1917e2cc04bbd763ec37c11ecc49030348c45cebb9cbbdb7f909af \ - --hash=sha256:61357e11d73e0ae57cbff31e71fc3ed83da3d16b58b653f715b32ad760527e34 +pandas-gbq==0.34.1 \ + --hash=sha256:6bea5b85937251b976cf9db38151ea59abbff98771179183488d4614694bff67 \ + --hash=sha256:b74932c6ee35dfc81582f39c792e3a68c9ef9bee8c85f25667d9d05dfadd0daf # via google-cloud-bigquery parsy==2.2 \ --hash=sha256:5e981613d9d2d8b68012d1dd0afe928967bea2e4eefdb76c2f545af0dd02a9e7 \ @@ -1793,9 +1795,9 @@ pathspec==1.0.4 \ --hash=sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645 \ --hash=sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723 # via mypy -platformdirs==4.9.2 \ - --hash=sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd \ - --hash=sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291 +platformdirs==4.9.4 \ + --hash=sha256:1ec356301b7dc906d83f371c8f487070e99d3ccf9e501686456394622a01a934 \ + --hash=sha256:68a9a4619a666ea6439f2ff250c12a853cd1cbd5158d258bd824a7df6be2f868 # via snowflake-connector-python prometheus-client==0.24.1 \ --hash=sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055 \ @@ -1927,25 +1929,25 @@ propcache==0.4.1 \ # via # aiohttp # yarl -proto-plus==1.27.1 \ - --hash=sha256:912a7460446625b792f6448bade9e55cd4e41e6ac10e27009ef71a7f317fa147 \ - --hash=sha256:e4643061f3a4d0de092d62aa4ad09fa4756b2cbb89d4627f3985018216f9fefc +proto-plus==1.27.2 \ + --hash=sha256:6432f75893d3b9e70b9c412f1d2f03f65b11fb164b793d14ae2ca01821d22718 \ + --hash=sha256:b2adde53adadf75737c44d3dcb0104fde65250dfc83ad59168b4aa3e574b6a24 # via # google-api-core # google-cloud-bigquery-storage # google-cloud-bigtable # google-cloud-datastore -protobuf==6.33.5 \ - --hash=sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c \ - --hash=sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02 \ - --hash=sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c \ - --hash=sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd \ - --hash=sha256:8f04fa32763dcdb4973d537d6b54e615cc61108c7cb38fe59310c3192d29510a \ - --hash=sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190 \ - --hash=sha256:a3157e62729aafb8df6da2c03aa5c0937c7266c626ce11a278b6eb7963c4e37c \ - --hash=sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5 \ - --hash=sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0 \ - --hash=sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b +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) # google-api-core @@ -2058,12 +2060,10 @@ pyarrow-hotfix==0.7 \ --hash=sha256:3236f3b5f1260f0e2ac070a55c1a7b339c4bb7267839bd2015e283234e758100 \ --hash=sha256:59399cd58bdd978b2e42816a4183a55c6472d4e33d183351b6069f11ed42661d # via ibis-framework -pyasn1==0.6.2 \ - --hash=sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf \ - --hash=sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b - # via - # pyasn1-modules - # rsa +pyasn1==0.6.3 \ + --hash=sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf \ + --hash=sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde + # via pyasn1-modules pyasn1-modules==0.4.2 \ --hash=sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a \ --hash=sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6 @@ -2204,9 +2204,9 @@ pydantic-core==2.41.5 \ --hash=sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425 \ --hash=sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52 # via pydantic -pydantic-settings==2.13.0 \ - --hash=sha256:95d875514610e8595672800a5c40b073e99e4aae467fa7c8f9c263061ea2e1fe \ - --hash=sha256:d67b576fff39cd086b595441bf9c75d4193ca9c0ed643b90360694d0f1240246 +pydantic-settings==2.13.1 \ + --hash=sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025 \ + --hash=sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237 # via # fastapi-mcp # mcp @@ -2214,15 +2214,15 @@ pydata-google-auth==1.9.1 \ --hash=sha256:0a51ce41c601ca0bc69b8795bf58bedff74b4a6a007c9106c7cbcdec00eaced2 \ --hash=sha256:75ffce5d106e34b717b31844c1639ea505b7d9550dc23b96fb6c20d086b53fa3 # via pandas-gbq -pygments==2.19.2 \ - --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \ - --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b +pygments==2.20.0 \ + --hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \ + --hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176 # via # feast (pyproject.toml) # rich -pyjwt[crypto]==2.11.0 \ - --hash=sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623 \ - --hash=sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469 +pyjwt[crypto]==2.12.1 \ + --hash=sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c \ + --hash=sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b # via # feast (pyproject.toml) # mcp @@ -2235,9 +2235,9 @@ pymysql==1.1.2 \ --hash=sha256:4961d3e165614ae65014e361811a724e2044ad3ea3739de9903ae7c21f539f03 \ --hash=sha256:e6b1d89711dd51f8f74b1631fe08f039e7d76cf67a42a323d3178f0f25762ed9 # via feast (pyproject.toml) -pyopenssl==25.3.0 \ - --hash=sha256:1fda6fc034d5e3d179d39e59c1895c9faeaf40a79de5fc4cbbfbe0d36f4a77b6 \ - --hash=sha256:c981cb0a3fd84e8602d7afc209522773b94c1c2446a3c710a75b06fe1beae329 +pyopenssl==26.0.0 \ + --hash=sha256:df94d28498848b98cc1c0ffb8ef1e71e40210d3b0a8064c9d29571ed2904bf81 \ + --hash=sha256:f293934e52936f2e3413b89c6ce36df66a0b34ae1ea3a053b8c5020ff2f513fc # via snowflake-connector-python python-dateutil==2.9.0.post0 \ --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ @@ -2249,9 +2249,9 @@ python-dateutil==2.9.0.post0 \ # ibis-framework # kubernetes # pandas -python-dotenv==1.2.1 \ - --hash=sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6 \ - --hash=sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61 +python-dotenv==1.2.2 \ + --hash=sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a \ + --hash=sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3 # via # pydantic-settings # pymilvus @@ -2260,9 +2260,9 @@ python-multipart==0.0.22 \ --hash=sha256:2b2cd894c83d21bf49d702499531c7bafd057d730c201782048f7945d82de155 \ --hash=sha256:7340bef99a7e0032613f56dc36027b959fd3b30a787ed62d310e951f7c3a3a58 # via mcp -pytz==2025.2 \ - --hash=sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3 \ - --hash=sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00 +pytz==2026.1.post1 \ + --hash=sha256:3378dde6a0c3d26719182142c56e60c7f9af7e968076f31aae569d72a0358ee1 \ + --hash=sha256:f2fd16142fda348286a75e1a524be810bb05d444e5a081f37f7affc635035f7a # via # pandas # snowflake-connector-python @@ -2355,9 +2355,9 @@ referencing==0.37.0 \ # via # jsonschema # jsonschema-specifications -requests==2.32.5 \ - --hash=sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6 \ - --hash=sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf +requests==2.33.1 \ + --hash=sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517 \ + --hash=sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a # via # feast (pyproject.toml) # fastapi-mcp @@ -2373,9 +2373,9 @@ requests-oauthlib==2.0.0 \ # via # google-auth-oauthlib # kubernetes -rich==14.3.2 \ - --hash=sha256:08e67c3e90884651da3239ea668222d19bea7b589149d8014a21c633420dbb69 \ - --hash=sha256:e712f11c1a562a11843306f5ed999475f09ac31ffb64281f73ab29ffdda8b3b8 +rich==14.3.3 \ + --hash=sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d \ + --hash=sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b # via # fastapi-mcp # ibis-framework @@ -2499,10 +2499,6 @@ rpds-py==0.30.0 \ # via # jsonschema # referencing -rsa==4.9.1 \ - --hash=sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762 \ - --hash=sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75 - # via google-auth s3transfer==0.13.1 \ --hash=sha256:a981aa7429be23fe6dfc13e80e4020057cbab622b08c0315288758d67cabc724 \ --hash=sha256:c3fdba22ba1bd367922f27ec8032d6a1cf5f10c934fb5d68cf60fd5a23d936cf @@ -2525,117 +2521,120 @@ six==1.17.0 \ # via # kubernetes # python-dateutil -snowflake-connector-python[pandas]==4.3.0 \ - --hash=sha256:08f5167a10d380fe66330d5b19d19bd8b4f4af27e9648e3b254e61da025646bf \ - --hash=sha256:120463ca391d9deda3bdb185104ba847e12f73c86ef411cfcf827ce49b64d1af \ - --hash=sha256:26a65c5c93d14c4d221b780fdb2f07b4dd83e848f39eabd4832778bf0e2694d4 \ - --hash=sha256:2e0f66acee330388815fb842f91a46c9cacdefdf02c816354e6adeca8c2c3f86 \ - --hash=sha256:3e2ce47485862fa14ffbf2732f0fd02aa69a7c68a50d5f6286f34ed17527cf87 \ - --hash=sha256:486d17332b9228d2e5975755b434e6a282756a447e0c6605d4e797944fa919da \ - --hash=sha256:55163c5d9b93e10d7217aabd56f776b16c0fe13774f8d5db9188824731da9586 \ - --hash=sha256:676b56eedcc268b7e25a447e736eb8bf8bcacfbc71196c94d6f45746672ee6d5 \ - --hash=sha256:726435b2769135b6282601efb2cd8fd53f7deb1ff2fb7da93d28141fa3c8b17e \ - --hash=sha256:762ffa9673465ccc630aba438d648e0b1a2452ba49669a54a60d1625f36898f3 \ - --hash=sha256:7763c0d5f8e6326ec31f8972cc806fb6d3e07b06ca59f67dfcdf02a34219bcbc \ - --hash=sha256:79cbf5e359cfc33b4c4307df1fe8f78cd5aee56f5c50b98a647fa0cd9ba82cfc \ - --hash=sha256:79f150297b39cfd2481b732554fc4d68b43c83c82eb01e670cc4051cffc089d6 \ - --hash=sha256:7c18b5021ffa6de8313f2c7f0ae6050c36bcee7cb33bb23d40a7fdf3e0a751f2 \ - --hash=sha256:9faa9280e41258fb479ec5395b6a17d3dbb316146832e436aed582b300de655e \ - --hash=sha256:ac18b37e03a29014a9c91aac10c7dbdfa11134c620c6f93dd16f4b99b6a38c2a \ - --hash=sha256:b5a8d91c3e0127360bc3de605df9d02ea4d87e4524a50bf2e7c5c4200f9abf78 \ - --hash=sha256:c1356a2c615e120f913e5235fe87ff8aadbb479ad5a5ac5c0a84881d5fbe981d \ - --hash=sha256:c6fa80373b82125552e691f47b603766ed783f3d90a5782564854aa224aee9d1 \ - --hash=sha256:ca9d22c61f4e3d171b0adad3e9211747917c3a978dfb99564307c1ceadb0f0cd \ - --hash=sha256:ce55b93120f8b429010bf39cc02e739610b6da2ccdd34fcfc0df04849d0fd9d4 \ - --hash=sha256:e3044e6a237b35f750394f199f5e3800dfeb3227c4c8562584877e814d2dc89a \ - --hash=sha256:e42dd9af46fa3ad0e61c1aa6a227357cace481916797ecb92dbb14adb61931e1 \ - --hash=sha256:e5d360d65d42dd97cf82e688a1a7f235b9bc048b4949c9c5c7052ff2783c444e \ - --hash=sha256:e96aaf23f2b021e0d2aac8ac1b541975cd1f6896d9115eefe0938114e694a562 \ - --hash=sha256:f5291c00f610b266ab8c79b1e008b3d0cb29bb5b86a0007529320921b4a3fc3c +snowflake-connector-python[pandas]==4.4.0 \ + --hash=sha256:16fdca775f7ca5ce4a973c07c434f5ab72bef5284e81a5e4ae2fb4d54d28965c \ + --hash=sha256:19d0c1ed033abae715a71b74c53010b180a5247c6924f851e4f7d0b0d58066c4 \ + --hash=sha256:2a6f6a514a10c3bb2d4554132f0b639f43d7e9fbb73fa1fae1c8a75333102686 \ + --hash=sha256:307f41326c702f6976746d2001dacf35adaf567f3f12afb3a5778fbb063c7241 \ + --hash=sha256:43e1a2f3ac51d24406d4eb0c23a8ceb9d6f5cb4854c941e5e1375d8c481e2844 \ + --hash=sha256:52efe2d6543a09807283748dd50a36ec01d52b4f342868132f8f9856b9c95a42 \ + --hash=sha256:56ff04dd9e17edc82128f412aa3776687dc94088f3d6b9144971e169952623cb \ + --hash=sha256:648f49029d699591af0f253e81c5bf60efc4411c7b0149ef074a59a038210a3b \ + --hash=sha256:693a1bef97509f09b7e6f42ea6f743d27819413c04fb3dc543b060d029871c56 \ + --hash=sha256:70d4051e2d9c87258b02672e17e21f5873e0cb49ff9705f6194ccfa25ac0d5fd \ + --hash=sha256:7c2984663a733d06c979aa6c8c1d7691621ec0d3521ef345d57c869ff2f1c4b2 \ + --hash=sha256:8304b4818d3e9de552dcfbdd0bca61bae1583e1c9794e242e58fe44bce701604 \ + --hash=sha256:85a01338d282423611f357cd5392dca2219bbda9a66b44761b11d6ae8ebf1e50 \ + --hash=sha256:96fdca994c4d9f7780e82fc7b4bd3398d856b43de3bae57d44e242ff435a2431 \ + --hash=sha256:9b1a28f843c1c0b582db7854789525d0c8aac4ea5c56e31113684e38220d0af9 \ + --hash=sha256:9fa43d330389df27024757c4f97dabddafbedc74b8bcc189b6a86e8b4d036014 \ + --hash=sha256:a088f108da4653ad1396ddb63a1c757ad614d0862c38f6f69cc77344bdcfeccb \ + --hash=sha256:b9f0ac0c00075321e1720d3876e936ee0256f54832e7463c5193a8dfa54913d5 \ + --hash=sha256:c828248214a49f77b903e05acf887d3ccb9d958b5a979f2ed3663bba1bd0f2b3 \ + --hash=sha256:d6fd334e4d8df7fcb30e6746e5ade845e82de2942268862aa8bce974ae2b86a2 \ + --hash=sha256:d8ac1659c8e588b9502f8d3d03c1ded2f274de0da9c09e62fe007cba5b46d6a5 \ + --hash=sha256:e8e7ce0e8b33aec8b1fc6741eb51dbeb54e2c3a6d282a0d459c355a85f089b08 \ + --hash=sha256:ea6e4083ebea0a814b46f029d64a2fb0ba6e7732952cd8af4406041708ce0e21 \ + --hash=sha256:f5d0e90e68a899c13fda5ca842ff77b5759b1674adf2c72702d3c2b53ca9d27b \ + --hash=sha256:fb628d5ea1999e23bfbaabce4125eb44d56605ca5634b8b1d6092ab22d555598 # via feast (pyproject.toml) sortedcontainers==2.4.0 \ --hash=sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88 \ --hash=sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0 # via snowflake-connector-python -sqlalchemy[mypy]==2.0.46 \ - --hash=sha256:09168817d6c19954d3b7655da6ba87fcb3a62bb575fb396a81a8b6a9fadfe8b5 \ - --hash=sha256:0cc3117db526cad3e61074100bd2867b533e2c7dc1569e95c14089735d6fb4fe \ - --hash=sha256:181903fe8c1b9082995325f1b2e84ac078b1189e2819380c2303a5f90e114a62 \ - --hash=sha256:1bc3f601f0a818d27bfe139f6766487d9c88502062a2cd3a7ee6c342e81d5047 \ - --hash=sha256:1e6199143d51e3e1168bedd98cc698397404a8f7508831b81b6a29b18b051069 \ - --hash=sha256:2347c3f0efc4de367ba00218e0ae5c4ba2306e47216ef80d6e31761ac97cb0b9 \ - --hash=sha256:261c4b1f101b4a411154f1da2b76497d73abbfc42740029205d4d01fa1052684 \ - --hash=sha256:33e462154edb9493f6c3ad2125931e273bbd0be8ae53f3ecd1c161ea9a1dd366 \ - --hash=sha256:37fee2164cf21417478b6a906adc1a91d69ae9aba8f9533e67ce882f4bb1de53 \ - --hash=sha256:3a9a72b0da8387f15d5810f1facca8f879de9b85af8c645138cba61ea147968c \ - --hash=sha256:3aac08f7546179889c62b53b18ebf1148b10244b3405569c93984b0388d016a7 \ - --hash=sha256:3c32e993bc57be6d177f7d5d31edb93f30726d798ad86ff9066d75d9bf2e0b6b \ - --hash=sha256:412f26bb4ba942d52016edc8d12fb15d91d3cd46b0047ba46e424213ad407bcb \ - --hash=sha256:42a1643dc5427b69aca967dae540a90b0fbf57eaf248f13a90ea5930e0966863 \ - --hash=sha256:4396c948d8217e83e2c202fbdcc0389cf8c93d2c1c5e60fa5c5a955eae0e64be \ - --hash=sha256:4dafb537740eef640c4d6a7c254611dca2df87eaf6d14d6a5fca9d1f4c3fc0fa \ - --hash=sha256:4f52f7291a92381e9b4de9050b0a65ce5d6a763333406861e33906b8aa4906bf \ - --hash=sha256:52fe29b3817bd191cc20bad564237c808967972c97fa683c04b28ec8979ae36f \ - --hash=sha256:56bdd261bfd0895452006d5316cbf35739c53b9bb71a170a331fa0ea560b2ada \ - --hash=sha256:585af6afe518732d9ccd3aea33af2edaae4a7aa881af5d8f6f4fe3a368699597 \ - --hash=sha256:590be24e20e2424a4c3c1b0835e9405fa3d0af5823a1a9fc02e5dff56471515f \ - --hash=sha256:64901e08c33462acc9ec3bad27fc7a5c2b6491665f2aa57564e57a4f5d7c52ad \ - --hash=sha256:6ac245604295b521de49b465bab845e3afe6916bcb2147e5929c8041b4ec0545 \ - --hash=sha256:6f827fd687fa1ba7f51699e1132129eac8db8003695513fcf13fc587e1bd47a5 \ - --hash=sha256:70ed2830b169a9960193f4d4322d22be5c0925357d82cbf485b3369893350908 \ - --hash=sha256:716be5bcabf327b6d5d265dbdc6213a01199be587224eb991ad0d37e83d728fd \ - --hash=sha256:7568fe771f974abadce52669ef3a03150ff03186d8eb82613bc8adc435a03f01 \ - --hash=sha256:77f8071d8fbcbb2dd11b7fd40dedd04e8ebe2eb80497916efedba844298065ef \ - --hash=sha256:82ec52100ec1e6ec671563bbd02d7c7c8d0b9e71a0723c72f22ecf52d1755330 \ - --hash=sha256:895296687ad06dc9b11a024cf68e8d9d3943aa0b4964278d2553b86f1b267735 \ - --hash=sha256:8d3b44b3d0ab2f1319d71d9863d76eeb46766f8cf9e921ac293511804d39813f \ - --hash=sha256:8d679b5f318423eacb61f933a9a0f75535bfca7056daeadbf6bd5bcee6183aee \ - --hash=sha256:8e84b09a9b0f19accedcbeff5c2caf36e0dd537341a33aad8d680336152dc34e \ - --hash=sha256:9094c8b3197db12aa6f05c51c05daaad0a92b8c9af5388569847b03b1007fb1b \ - --hash=sha256:90bde6c6b1827565a95fde597da001212ab436f1b2e0c2dcc7246e14db26e2a3 \ - --hash=sha256:9397b381dcee8a2d6b99447ae85ea2530dcac82ca494d1db877087a13e38926d \ - --hash=sha256:93a12da97cca70cea10d4b4fc602589c4511f96c1f8f6c11817620c021d21d00 \ - --hash=sha256:93bb0aae40b52c57fd74ef9c6933c08c040ba98daf23ad33c3f9893494b8d3ce \ - --hash=sha256:94b1e5f3a5f1ff4f42d5daab047428cd45a3380e51e191360a35cef71c9a7a2a \ - --hash=sha256:965c62be8256d10c11f8907e7a8d3e18127a4c527a5919d85fa87fd9ecc2cfdc \ - --hash=sha256:96c7cca1a4babaaf3bfff3e4e606e38578856917e52f0384635a95b226c87764 \ - --hash=sha256:9bcdce05f056622a632f1d44bb47dbdb677f58cad393612280406ce37530eb6d \ - --hash=sha256:9d80ea2ac519c364a7286e8d765d6cd08648f5b21ca855a8017d9871f075542d \ - --hash=sha256:a1e8cc6cc01da346dc92d9509a63033b9b1bda4fed7a7a7807ed385c7dccdc10 \ - --hash=sha256:ab65cb2885a9f80f979b85aa4e9c9165a31381ca322cbde7c638fe6eefd1ec39 \ - --hash=sha256:af865c18752d416798dae13f83f38927c52f085c52e2f32b8ab0fef46fdd02c2 \ - --hash=sha256:b1e14b2f6965a685c7128bd315e27387205429c2e339eeec55cb75ca4ab0ea2e \ - --hash=sha256:b2a9f9aee38039cf4755891a1e50e1effcc42ea6ba053743f452c372c3152b1b \ - --hash=sha256:be6c0466b4c25b44c5d82b0426b5501de3c424d7a3220e86cd32f319ba56798e \ - --hash=sha256:c4e2cc868b7b5208aec6c960950b7bb821f82c2fe66446c92ee0a571765e91a5 \ - --hash=sha256:c805fa6e5d461329fa02f53f88c914d189ea771b6821083937e79550bf31fc19 \ - --hash=sha256:cf36851ee7219c170bb0793dbc3da3e80c582e04a5437bc601bfe8c85c9216d7 \ - --hash=sha256:db23b1bf8cfe1f7fda19018e7207b20cdb5168f83c437ff7e95d19e39289c447 \ - --hash=sha256:e0c05aff5c6b1bb5fb46a87e0f9d2f733f83ef6cbbbcd5c642b6c01678268061 \ - --hash=sha256:e8ac45e8f4eaac0f9f8043ea0e224158855c6a4329fd4ee37c45c61e3beb518e \ - --hash=sha256:ea3cd46b6713a10216323cda3333514944e510aa691c945334713fca6b5279ff \ - --hash=sha256:ebf7e1e78af38047e08836d33502c7a278915698b7c2145d045f780201679999 \ - --hash=sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e \ - --hash=sha256:ff33c6e6ad006bbc0f34f5faf941cfc62c45841c64c0a058ac38c799f15b5ede +sqlalchemy[mypy]==2.0.48 \ + --hash=sha256:01f6bbd4308b23240cf7d3ef117557c8fd097ec9549d5d8a52977544e35b40ad \ + --hash=sha256:07edba08061bc277bfdc772dd2a1a43978f5a45994dd3ede26391b405c15221e \ + --hash=sha256:10853a53a4a00417a00913d270dddda75815fcb80675874285f41051c094d7dd \ + --hash=sha256:1182437cb2d97988cfea04cf6cdc0b0bb9c74f4d56ec3d08b81e23d621a28cc6 \ + --hash=sha256:144921da96c08feb9e2b052c5c5c1d0d151a292c6135623c6b2c041f2a45f9e0 \ + --hash=sha256:1a89ce07ad2d4b8cfc30bd5889ec40613e028ed80ef47da7d9dd2ce969ad30e0 \ + --hash=sha256:1b4c575df7368b3b13e0cebf01d4679f9a28ed2ae6c1cd0b1d5beffb6b2007dc \ + --hash=sha256:1ccd42229aaac2df431562117ac7e667d702e8e44afdb6cf0e50fa3f18160f0b \ + --hash=sha256:2645b7d8a738763b664a12a1542c89c940daa55196e8d73e55b169cc5c99f65f \ + --hash=sha256:288937433bd44e3990e7da2402fabc44a3c6c25d3704da066b85b89a85474ae0 \ + --hash=sha256:34634e196f620c7a61d18d5cf7dc841ca6daa7961aed75d532b7e58b309ac894 \ + --hash=sha256:348174f228b99f33ca1f773e85510e08927620caa59ffe7803b37170df30332b \ + --hash=sha256:36ac4ddc3d33e852da9cb00ffb08cea62ca05c39711dc67062ca2bb1fae35fd8 \ + --hash=sha256:3713e21ea67bca727eecd4a24bf68bcd414c403faae4989442be60994301ded0 \ + --hash=sha256:389b984139278f97757ea9b08993e7b9d1142912e046ab7d82b3fbaeb0209131 \ + --hash=sha256:426c5ca86415d9b8945c7073597e10de9644802e2ff502b8e1f11a7a2642856b \ + --hash=sha256:4599a95f9430ae0de82b52ff0d27304fe898c17cb5f4099f7438a51b9998ac77 \ + --hash=sha256:49b7bddc1eebf011ea5ab722fdbe67a401caa34a350d278cc7733c0e88fecb1f \ + --hash=sha256:53667b5f668991e279d21f94ccfa6e45b4e3f4500e7591ae59a8012d0f010dcb \ + --hash=sha256:546572a1793cc35857a2ffa1fe0e58571af1779bcc1ffa7c9fb0839885ed69a9 \ + --hash=sha256:583849c743e0e3c9bb7446f5b5addeacedc168d657a69b418063dfdb2d90081c \ + --hash=sha256:5aee45fd2c6c0f2b9cdddf48c48535e7471e42d6fb81adfde801da0bd5b93241 \ + --hash=sha256:5b193a7e29fd9fa56e502920dca47dffe60f97c863494946bd698c6058a55658 \ + --hash=sha256:5ca74f37f3369b45e1f6b7b06afb182af1fd5dde009e4ffd831830d98cbe5fe7 \ + --hash=sha256:68549c403f79a8e25984376480959975212a670405e3913830614432b5daa07a \ + --hash=sha256:69f5bc24904d3bc3640961cddd2523e361257ef68585d6e364166dfbe8c78fae \ + --hash=sha256:6bb85c546591569558571aa1b06aba711b26ae62f111e15e56136d69920e1616 \ + --hash=sha256:6f7b7243850edd0b8b97043f04748f31de50cf426e939def5c16bedb540698f7 \ + --hash=sha256:7001dc9d5f6bb4deb756d5928eaefe1930f6f4179da3924cbd95ee0e9f4dce89 \ + --hash=sha256:7a936f1bb23d370b7c8cc079d5fce4c7d18da87a33c6744e51a93b0f9e97e9b3 \ + --hash=sha256:7c998f2ace8bf76b453b75dbcca500d4f4b9dd3908c13e89b86289b37784848b \ + --hash=sha256:7cddca31edf8b0653090cbb54562ca027c421c58ddde2c0685f49ff56a1690e0 \ + --hash=sha256:8183dc57ae7d9edc1346e007e840a9f3d6aa7b7f165203a99e16f447150140d2 \ + --hash=sha256:82745b03b4043e04600a6b665cb98697c4339b24e34d74b0a2ac0a2488b6f94d \ + --hash=sha256:841a94c66577661c1f088ac958cd767d7c9bf507698f45afffe7a4017049de76 \ + --hash=sha256:858e433f12b0e5b3ed2f8da917433b634f4937d0e8793e5cb33c54a1a01df565 \ + --hash=sha256:908a3fa6908716f803b86896a09a2c4dde5f5ce2bb07aacc71ffebb57986ce99 \ + --hash=sha256:9764014ef5e58aab76220c5664abb5d47d5bc858d9debf821e55cfdd0f128485 \ + --hash=sha256:9c7d0a77e36b5f4b01ca398482230ab792061d243d715299b44a0b55c89fe617 \ + --hash=sha256:a5b429eb84339f9f05e06083f119ad814e6d85e27ecbdf9c551dfdbb128eaf8a \ + --hash=sha256:a66fe406437dd65cacd96a72689a3aaaecaebbcd62d81c5ac1c0fdbeac835096 \ + --hash=sha256:a6b764fb312bd35e47797ad2e63f0d323792837a6ac785a4ca967019357d2bc7 \ + --hash=sha256:b19151e76620a412c2ac1c6f977ab1b9fa7ad43140178345136456d5265b32ed \ + --hash=sha256:b8438ec5594980d405251451c5b7ea9aa58dda38eb7ac35fb7e4c696712ee24f \ + --hash=sha256:b8fc3454b4f3bd0a368001d0e968852dad45a873f8b4babd41bc302ec851a099 \ + --hash=sha256:bcb8ebbf2e2c36cfe01a94f2438012c6a9d494cf80f129d9753bcdf33bfc35a6 \ + --hash=sha256:d404dc897ce10e565d647795861762aa2d06ca3f4a728c5e9a835096c7059018 \ + --hash=sha256:d612c976cbc2d17edfcc4c006874b764e85e990c29ce9bd411f926bbfb02b9a2 \ + --hash=sha256:d64177f443594c8697369c10e4bbcac70ef558e0f7921a1de7e4a3d1734bcf67 \ + --hash=sha256:d854b3970067297f3a7fbd7a4683587134aa9b3877ee15aa29eea478dc68f933 \ + --hash=sha256:d8fcccbbc0c13c13702c471da398b8cd72ba740dca5859f148ae8e0e8e0d3e7e \ + --hash=sha256:e004aa9248e8cb0a5f9b96d003ca7c1c0a5da8decd1066e7b53f59eb8ce7c62b \ + --hash=sha256:e214d546c8ecb5fc22d6e6011746082abf13a9cf46eefb45769c7b31407c97b5 \ + --hash=sha256:e2d0d88686e3d35a76f3e15a34e8c12d73fc94c1dea1cd55782e695cc14086dd \ + --hash=sha256:e2f35b4cccd9ed286ad62e0a3c3ac21e06c02abc60e20aa51a3e305a30f5fa79 \ + --hash=sha256:e3070c03701037aa418b55d36532ecb8f8446ed0135acb71c678dbdf12f5b6e4 \ + --hash=sha256:e5e088bf43f6ee6fec7dbf1ef7ff7774a616c236b5c0cb3e00662dd71a56b571 \ + --hash=sha256:e83e3f959aaa1c9df95c22c528096d94848a1bc819f5d0ebf7ee3df0ca63db6c \ + --hash=sha256:f0dcbc588cd5b725162c076eb9119342f6579c7f7f55057bb7e3c6ff27e13121 \ + --hash=sha256:f27f9da0a7d22b9f981108fd4b62f8b5743423388915a563e651c20d06c1f457 \ + --hash=sha256:f8649a14caa5f8a243628b1d61cf530ad9ae4578814ba726816adb1121fc493e \ + --hash=sha256:fac0fa4e4f55f118fd87177dacb1c6522fe39c28d498d259014020fec9164c29 \ + --hash=sha256:fd08b90d211c086181caed76931ecfa2bdfc83eea3cfccdb0f82abc6c4b876cb # via feast (pyproject.toml) -sqlglot==28.10.1 \ - --hash=sha256:214aef51fd4ce16407022f81cfc80c173409dab6d0f6ae18c52b43f43b31d4dd \ - --hash=sha256:66e0dae43b4bce23314b80e9aef41b8c88fea0e17ada62de095b45262084a8c5 +sqlglot==30.2.1 \ + --hash=sha256:ef4a67cc6f66a8043085eb8ea95fa9541c1625dffa9145ad4e9815a7ba60a199 \ + --hash=sha256:f23d9ee9427ef9d20df15f9b0ffa57d9eb45e52b012219a349d1e6b50ed926d1 # via ibis-framework -sse-starlette==3.2.0 \ - --hash=sha256:5876954bd51920fc2cd51baee47a080eb88a37b5b784e615abb0b283f801cdbf \ - --hash=sha256:8127594edfb51abe44eac9c49e59b0b01f1039d0c7461c6fd91d4e03b70da422 +sse-starlette==3.3.4 \ + --hash=sha256:84bb06e58939a8b38d8341f1bc9792f06c2b53f48c608dd207582b664fc8f3c1 \ + --hash=sha256:aaf92fc067af8a5427192895ac028e947b484ac01edbc3caf00e7e7137c7bef1 # via mcp -starlette==0.52.1 \ - --hash=sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74 \ - --hash=sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933 +starlette==1.0.0 \ + --hash=sha256:6a4beaf1f81bb472fd19ea9b918b50dc3a77a6f2e190a12954b25e6ed5eea149 \ + --hash=sha256:d3ec55e0bb321692d275455ddfd3df75fff145d009685eb40dc91fc66b03d38b # via # fastapi # mcp # sse-starlette -tabulate==0.9.0 \ - --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ - --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f +tabulate==0.10.0 \ + --hash=sha256:e2cfde8f79420f6deeffdeda9aaec3b6bc5abce947655d17ac662b126e48a60d \ + --hash=sha256:f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3 # via feast (pyproject.toml) tenacity==8.5.0 \ --hash=sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78 \ @@ -2645,54 +2644,54 @@ toml==0.10.2 \ --hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \ --hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f # via feast (pyproject.toml) -tomli==2.4.0 \ - --hash=sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729 \ - --hash=sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b \ - --hash=sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d \ - --hash=sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df \ - --hash=sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576 \ - --hash=sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d \ - --hash=sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1 \ - --hash=sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a \ - --hash=sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e \ - --hash=sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc \ - --hash=sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702 \ - --hash=sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6 \ - --hash=sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd \ - --hash=sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4 \ - --hash=sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776 \ - --hash=sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a \ - --hash=sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66 \ - --hash=sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87 \ - --hash=sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2 \ - --hash=sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f \ - --hash=sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475 \ - --hash=sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f \ - --hash=sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95 \ - --hash=sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9 \ - --hash=sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3 \ - --hash=sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9 \ - --hash=sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76 \ - --hash=sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da \ - --hash=sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8 \ - --hash=sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51 \ - --hash=sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86 \ - --hash=sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8 \ - --hash=sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0 \ - --hash=sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b \ - --hash=sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1 \ - --hash=sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e \ - --hash=sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d \ - --hash=sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c \ - --hash=sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867 \ - --hash=sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a \ - --hash=sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c \ - --hash=sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0 \ - --hash=sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4 \ - --hash=sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614 \ - --hash=sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132 \ - --hash=sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa \ - --hash=sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087 +tomli==2.4.1 \ + --hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \ + --hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \ + --hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \ + --hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \ + --hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \ + --hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \ + --hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \ + --hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \ + --hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \ + --hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \ + --hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \ + --hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \ + --hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \ + --hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \ + --hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \ + --hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \ + --hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \ + --hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \ + --hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \ + --hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \ + --hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \ + --hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \ + --hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \ + --hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \ + --hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \ + --hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \ + --hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \ + --hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \ + --hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \ + --hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \ + --hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \ + --hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \ + --hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \ + --hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \ + --hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \ + --hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \ + --hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \ + --hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \ + --hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \ + --hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \ + --hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \ + --hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \ + --hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \ + --hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \ + --hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \ + --hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \ + --hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049 # via fastapi-mcp tomlkit==0.14.0 \ --hash=sha256:592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680 \ @@ -2711,13 +2710,13 @@ tqdm==4.67.3 \ # via # feast (pyproject.toml) # milvus-lite -typeguard==4.5.0 \ - --hash=sha256:749bea21cdb2553e12831bc29f1eae980b22c7de8331ab67ae7db9e85470b5a7 \ - --hash=sha256:cfda388fc88a9ce42a41890900d6f31ee124bea9b73bb84701a32438e92165c3 +typeguard==4.5.1 \ + --hash=sha256:44d2bf329d49a244110a090b55f5f91aa82d9a9834ebfd30bcc73651e4a8cc40 \ + --hash=sha256:f6f8ecbbc819c9bc749983cc67c02391e16a9b43b8b27f15dc70ed7c4a007274 # via feast (pyproject.toml) -typer==0.23.1 \ - --hash=sha256:2070374e4d31c83e7b61362fd859aa683576432fd5b026b060ad6b4cd3b86134 \ - --hash=sha256:3291ad0d3c701cbf522012faccfbb29352ff16ad262db2139e6b01f15781f14e +typer==0.24.1 \ + --hash=sha256:112c1f0ce578bfb4cab9ffdabc68f031416ebcc216536611ba21f04e9aa84c9e \ + --hash=sha256:e39b4732d65fbdcde189ae76cf7cd48aeae72919dea1fdfc16593be016256b45 # via fastapi-mcp types-pymysql==1.1.0.20251220 \ --hash=sha256:ae1c3df32a777489431e2e9963880a0df48f6591e0aa2fd3a6fabd9dee6eca54 \ @@ -2758,91 +2757,85 @@ tzdata==2025.3 \ # via # ibis-framework # pandas -ujson==5.11.0 \ - --hash=sha256:0180a480a7d099082501cad1fe85252e4d4bf926b40960fb3d9e87a3a6fbbc80 \ - --hash=sha256:04c41afc195fd477a59db3a84d5b83a871bd648ef371cf8c6f43072d89144eef \ - --hash=sha256:0654a2691fc252c3c525e3d034bb27b8a7546c9d3eb33cd29ce6c9feda361a6a \ - --hash=sha256:090b4d11b380ae25453100b722d0609d5051ffe98f80ec52853ccf8249dfd840 \ - --hash=sha256:109f59885041b14ee9569bf0bb3f98579c3fa0652317b355669939e5fc5ede53 \ - --hash=sha256:10f29e71ecf4ecd93a6610bd8efa8e7b6467454a363c3d6416db65de883eb076 \ - --hash=sha256:1194b943e951092db611011cb8dbdb6cf94a3b816ed07906e14d3bc6ce0e90ab \ - --hash=sha256:12b5e7e22a1fe01058000d1b317d3b65cc3daf61bd2ea7a2b76721fe160fa74d \ - --hash=sha256:16ccb973b7ada0455201808ff11d48fe9c3f034a6ab5bd93b944443c88299f89 \ - --hash=sha256:181fb5b15703a8b9370b25345d2a1fd1359f0f18776b3643d24e13ed9c036d4c \ - --hash=sha256:185f93ebccffebc8baf8302c869fac70dd5dd78694f3b875d03a31b03b062cdb \ - --hash=sha256:1a0a9b76a89827a592656fe12e000cf4f12da9692f51a841a4a07aa4c7ecc41c \ - --hash=sha256:1a325fd2c3a056cf6c8e023f74a0c478dd282a93141356ae7f16d5309f5ff823 \ - --hash=sha256:1aa8a2ab482f09f6c10fba37112af5f957689a79ea598399c85009f2f29898b5 \ - --hash=sha256:1d663b96eb34c93392e9caae19c099ec4133ba21654b081956613327f0e973ac \ - --hash=sha256:29113c003ca33ab71b1b480bde952fbab2a0b6b03a4ee4c3d71687cdcbd1a29d \ - --hash=sha256:30f607c70091483550fbd669a0b37471e5165b317d6c16e75dba2aa967608723 \ - --hash=sha256:3134b783ab314d2298d58cda7e47e7a0f7f71fc6ade6ac86d5dbeaf4b9770fa6 \ - --hash=sha256:34032aeca4510a7c7102bd5933f59a37f63891f30a0706fb46487ab6f0edf8f0 \ - --hash=sha256:3772e4fe6b0c1e025ba3c50841a0ca4786825a4894c8411bf8d3afe3a8061328 \ - --hash=sha256:3d2720e9785f84312b8e2cb0c2b87f1a0b1c53aaab3b2af3ab817d54409012e0 \ - --hash=sha256:416389ec19ef5f2013592f791486bef712ebce0cd59299bf9df1ba40bb2f6e04 \ - --hash=sha256:446e8c11c06048611c9d29ef1237065de0af07cabdd97e6b5b527b957692ec25 \ - --hash=sha256:4598bf3965fc1a936bd84034312bcbe00ba87880ef1ee33e33c1e88f2c398b49 \ - --hash=sha256:48055e1061c1bb1f79e75b4ac39e821f3f35a9b82de17fce92c3140149009bec \ - --hash=sha256:4843f3ab4fe1cc596bb7e02228ef4c25d35b4bb0809d6a260852a4bfcab37ba3 \ - --hash=sha256:49e56ef8066f11b80d620985ae36869a3ff7e4b74c3b6129182ec5d1df0255f3 \ - --hash=sha256:4b42c115c7c6012506e8168315150d1e3f76e7ba0f4f95616f4ee599a1372bbc \ - --hash=sha256:4c9f5d6a27d035dd90a146f7761c2272cf7103de5127c9ab9c4cd39ea61e878a \ - --hash=sha256:5600202a731af24a25e2d7b6eb3f648e4ecd4bb67c4d5cf12f8fab31677469c9 \ - --hash=sha256:65724738c73645db88f70ba1f2e6fb678f913281804d5da2fd02c8c5839af302 \ - --hash=sha256:65f3c279f4ed4bf9131b11972040200c66ae040368abdbb21596bf1564899694 \ - --hash=sha256:674f306e3e6089f92b126eb2fe41bcb65e42a15432c143365c729fdb50518547 \ - --hash=sha256:683f57f0dd3acdd7d9aff1de0528d603aafcb0e6d126e3dc7ce8b020a28f5d01 \ - --hash=sha256:6b6ec7e7321d7fc19abdda3ad809baef935f49673951a8bab486aea975007e02 \ - --hash=sha256:6cd2df62f24c506a0ba322d5e4fe4466d47a9467b57e881ee15a31f7ecf68ff6 \ - --hash=sha256:6dd703c3e86dc6f7044c5ac0b3ae079ed96bf297974598116aa5fb7f655c3a60 \ - --hash=sha256:6eff24e1abd79e0ec6d7eae651dd675ddbc41f9e43e29ef81e16b421da896915 \ - --hash=sha256:7855ccea3f8dad5e66d8445d754fc1cf80265a4272b5f8059ebc7ec29b8d0835 \ - --hash=sha256:787aff4a84da301b7f3bac09bc696e2e5670df829c6f8ecf39916b4e7e24e701 \ - --hash=sha256:7895f0d2d53bd6aea11743bd56e3cb82d729980636cd0ed9b89418bf66591702 \ - --hash=sha256:78c684fb21255b9b90320ba7e199780f653e03f6c2528663768965f4126a5b50 \ - --hash=sha256:7e0ec1646db172beb8d3df4c32a9d78015e671d2000af548252769e33079d9a6 \ - --hash=sha256:7e3cff632c1d78023b15f7e3a81c3745cd3f94c044d1e8fa8efbd6b161997bbc \ - --hash=sha256:7f1a27ab91083b4770e160d17f61b407f587548f2c2b5fbf19f94794c495594a \ - --hash=sha256:80017e870d882d5517d28995b62e4e518a894f932f1e242cbc802a2fd64d365c \ - --hash=sha256:8254e858437c00f17cb72e7a644fc42dad0ebb21ea981b71df6e84b1072aaa7c \ - --hash=sha256:837da4d27fed5fdc1b630bd18f519744b23a0b5ada1bbde1a36ba463f2900c03 \ - --hash=sha256:849e65b696f0d242833f1df4182096cedc50d414215d1371fca85c541fbff629 \ - --hash=sha256:85e6796631165f719084a9af00c79195d3ebf108151452fefdcb1c8bb50f0105 \ - --hash=sha256:86baf341d90b566d61a394869ce77188cc8668f76d7bb2c311d77a00f4bdf844 \ - --hash=sha256:8fa2af7c1459204b7a42e98263b069bd535ea0cd978b4d6982f35af5a04a4241 \ - --hash=sha256:94fcae844f1e302f6f8095c5d1c45a2f0bfb928cccf9f1b99e3ace634b980a2a \ - --hash=sha256:952c0be400229940248c0f5356514123d428cba1946af6fa2bbd7503395fef26 \ - --hash=sha256:99c49400572cd77050894e16864a335225191fd72a818ea6423ae1a06467beac \ - --hash=sha256:9aacbeb23fdbc4b256a7d12e0beb9063a1ba5d9e0dbb2cfe16357c98b4334596 \ - --hash=sha256:a0af6574fc1d9d53f4ff371f58c96673e6d988ed2b5bf666a6143c782fa007e9 \ - --hash=sha256:a31c6b8004438e8c20fc55ac1c0e07dad42941db24176fe9acf2815971f8e752 \ - --hash=sha256:a4df61a6df0a4a8eb5b9b1ffd673429811f50b235539dac586bb7e9e91994138 \ - --hash=sha256:a638425d3c6eed0318df663df44480f4a40dc87cc7c6da44d221418312f6413b \ - --hash=sha256:aa6b3d4f1c0d3f82930f4cbd7fe46d905a4a9205a7c13279789c1263faf06dba \ - --hash=sha256:aa6d7a5e09217ff93234e050e3e380da62b084e26b9f2e277d2606406a2fc2e5 \ - --hash=sha256:ab2cb8351d976e788669c8281465d44d4e94413718af497b4e7342d7b2f78018 \ - --hash=sha256:abae0fb58cc820092a0e9e8ba0051ac4583958495bfa5262a12f628249e3b362 \ - --hash=sha256:b16930f6a0753cdc7d637b33b4e8f10d5e351e1fb83872ba6375f1e87be39746 \ - --hash=sha256:b7b136cc6abc7619124fd897ef75f8e63105298b5ca9bdf43ebd0e1fa0ee105f \ - --hash=sha256:be6b0eaf92cae8cdee4d4c9e074bde43ef1c590ed5ba037ea26c9632fb479c88 \ - --hash=sha256:c44c703842024d796b4c78542a6fcd5c3cb948b9fc2a73ee65b9c86a22ee3638 \ - --hash=sha256:c6618f480f7c9ded05e78a1938873fde68baf96cdd74e6d23c7e0a8441175c4b \ - --hash=sha256:ce076f2df2e1aa62b685086fbad67f2b1d3048369664b4cdccc50707325401f9 \ - --hash=sha256:d06e87eded62ff0e5f5178c916337d2262fdbc03b31688142a3433eabb6511db \ - --hash=sha256:d7c46cb0fe5e7056b9acb748a4c35aa1b428025853032540bb7e41f46767321f \ - --hash=sha256:d8951bb7a505ab2a700e26f691bdfacf395bc7e3111e3416d325b513eea03a58 \ - --hash=sha256:da473b23e3a54448b008d33f742bcd6d5fb2a897e42d1fc6e7bf306ea5d18b1b \ - --hash=sha256:de6e88f62796372fba1de973c11138f197d3e0e1d80bcb2b8aae1e826096d433 \ - --hash=sha256:e204ae6f909f099ba6b6b942131cee359ddda2b6e4ea39c12eb8b991fe2010e0 \ - --hash=sha256:e73df8648c9470af2b6a6bf5250d4744ad2cf3d774dcf8c6e31f018bdd04d764 \ - --hash=sha256:e750c436fb90edf85585f5c62a35b35082502383840962c6983403d1bd96a02c \ - --hash=sha256:e979fbc469a7f77f04ec2f4e853ba00c441bf2b06720aa259f0f720561335e34 \ - --hash=sha256:ecd6ff8a3b5a90c292c2396c2d63c687fd0ecdf17de390d852524393cd9ed052 \ - --hash=sha256:f278b31a7c52eb0947b2db55a5133fbc46b6f0ef49972cd1a80843b72e135aba \ - --hash=sha256:f62b9976fabbcde3ab6e413f4ec2ff017749819a0786d84d7510171109f2d53c \ - --hash=sha256:fa79fdb47701942c2132a9dd2297a1a85941d966d8c87bfd9e29b0cf423f26cc \ - --hash=sha256:fac6c0649d6b7c3682a0a6e18d3de6857977378dce8d419f57a0b20e3d775b39 +ujson==5.12.0 \ + --hash=sha256:006428d3813b87477d72d306c40c09f898a41b968e57b15a7d88454ecc42a3fb \ + --hash=sha256:02f93da7a4115e24f886b04fd56df1ee8741c2ce4ea491b7ab3152f744ad8f8e \ + --hash=sha256:0727363b05ab05ee737a28f6200dc4078bce6b0508e10bd8aab507995a15df61 \ + --hash=sha256:085b6ce182cdd6657481c7c4003a417e0655c4f6e58b76f26ee18f0ae21db827 \ + --hash=sha256:09b4beff9cc91d445d5818632907b85fb06943b61cb346919ce202668bf6794a \ + --hash=sha256:0a3ae28f0b209be5af50b54ca3e2123a3de3a57d87b75f1e5aa3d7961e041983 \ + --hash=sha256:0d2e8db5ade3736a163906154ca686203acc7d1d30736cbf577c730d13653d84 \ + --hash=sha256:0e00cec383eab2406c9e006bd4edb55d284e94bb943fda558326048178d26961 \ + --hash=sha256:0fe6b8b8968e11dd9b2348bd508f0f57cf49ab3512064b36bc4117328218718e \ + --hash=sha256:0fe9128e75c6aa6e9ae06c1408d6edd9179a2fef0fe6d9cda3166b887eba521d \ + --hash=sha256:14b2e1eb528d77bc0f4c5bd1a7ebc05e02b5b41beefb7e8567c9675b8b13bcf4 \ + --hash=sha256:15d416440148f3e56b9b244fdaf8a09fcf5a72e4944b8e119f5bf60417a2bfc8 \ + --hash=sha256:15e555c4caca42411270b2ed2b2ebc7b3a42bb04138cef6c956e1f1d49709fe2 \ + --hash=sha256:16b4fe9c97dc605f5e1887a9e1224287291e35c56cbc379f8aa44b6b7bcfe2bb \ + --hash=sha256:1b5c6ceb65fecd28a1d20d1eba9dbfa992612b86594e4b6d47bb580d2dd6bcb3 \ + --hash=sha256:1d072a403d82aef8090c6d4f728e3a727dfdba1ad3b7fa3a052c3ecbd37e73cb \ + --hash=sha256:2324d9a0502317ffc35d38e153c1b2fa9610ae03775c9d0f8d0cca7b8572b04e \ + --hash=sha256:2a248750abce1c76fbd11b2e1d88b95401e72819295c3b851ec73399d6849b3d \ + --hash=sha256:2ea6206043385343aff0b7da65cf73677f6f5e50de8f1c879e557f4298cac36a \ + --hash=sha256:31348a0ffbfc815ce78daac569d893349d85a0b57e1cd2cdbba50b7f333784da \ + --hash=sha256:38051f36423f084b909aaadb3b41c9c6a2958e86956ba21a8489636911e87504 \ + --hash=sha256:3c2f947e55d3c7cfe124dd4521ee481516f3007d13c6ad4bf6aeb722e190eb1b \ + --hash=sha256:3ed5cb149892141b1e77ef312924a327f2cc718b34247dae346ed66329e1b8be \ + --hash=sha256:3ff4ede90ed771140caa7e1890de17431763a483c54b3c1f88bd30f0cc1affc0 \ + --hash=sha256:40aa43a7a3a8d2f05e79900858053d697a88a605e3887be178b43acbcd781161 \ + --hash=sha256:42d875388fbd091c7ea01edfff260f839ba303038ffb23475ef392012e4d63dd \ + --hash=sha256:457fabc2700a8e6ddb85bc5a1d30d3345fe0d3ec3ee8161a4e032ec585801dfa \ + --hash=sha256:460e76a4daff214ae33ab959494962c93918cb44714ea3e3f748b14aa37f8a87 \ + --hash=sha256:50524f4f6a1c839714dbaff5386a1afb245d2d5ec8213a01fbc99cea7307811e \ + --hash=sha256:51acc750ec7a2df786cdc868fb16fa04abd6269a01d58cf59bafc57978773d8e \ + --hash=sha256:55ede2a7a051b3b7e71a394978a098d71b3783e6b904702ff45483fad434ae2d \ + --hash=sha256:561f89cc82deeae82e37d4a4764184926fb432f740a9691563a391b13f7339a4 \ + --hash=sha256:56ba3f7abbd6b0bb282a544dc38406d1a188d8bb9164f49fdb9c2fee62cb29da \ + --hash=sha256:57930ac9519099b852e190d2c04b1fb5d97ea128db33bce77ed874eccb4c7f09 \ + --hash=sha256:58a11cb49482f1a095a2bd9a1d81dd7c8fb5d2357f959ece85db4e46a825fd00 \ + --hash=sha256:64df53eef4ac857eb5816a56e2885ccf0d7dff6333c94065c93b39c51063e01d \ + --hash=sha256:6879aed770557f0961b252648d36f6fdaab41079d37a2296b5649fd1b35608e0 \ + --hash=sha256:6ad57654570464eb1b040b5c353dee442608e06cff9102b8fcb105565a44c9ed \ + --hash=sha256:6c0aed6a4439994c9666fb8a5b6c4eac94d4ef6ddc95f9b806a599ef83547e3b \ + --hash=sha256:76bf3e7406cf23a3e1ca6a23fb1fb9ea82f4f6bd226fe226e09146b0194f85dc \ + --hash=sha256:7bbf05c38debc90d1a195b11340cc85cb43ab3e753dc47558a3a84a38cbc72da \ + --hash=sha256:7ddb08b3c2f9213df1f2e3eb2fbea4963d80ec0f8de21f0b59898e34f3b3d96d \ + --hash=sha256:7e07f6f644d2c44d53b7a320a084eef98063651912c1b9449b5f45fcbdc6ccd2 \ + --hash=sha256:85833bca01aa5cae326ac759276dc175c5fa3f7b3733b7d543cf27f2df12d1ef \ + --hash=sha256:8712b61eb1b74a4478cfd1c54f576056199e9f093659334aeb5c4a6b385338e5 \ + --hash=sha256:871c0e5102e47995b0e37e8df7819a894a6c3da0d097545cd1f9f1f7d7079927 \ + --hash=sha256:89e302abd3749f6d6699691747969a5d85f7c73081d5ed7e2624c7bd9721a2ab \ + --hash=sha256:937794042342006f707837f38d721426b11b0774d327a2a45c0bd389eb750a87 \ + --hash=sha256:93bc91fdadcf046da37a214eaa714574e7e9b1913568e93bb09527b2ceb7f759 \ + --hash=sha256:94c5f1621cbcab83c03be46441f090b68b9f307b6c7ec44d4e3f6d5997383df4 \ + --hash=sha256:973b7d7145b1ac553a7466a64afa8b31ec2693d7c7fff6a755059e0a2885dfd2 \ + --hash=sha256:99cc80facad240b0c2fb5a633044420878aac87a8e7c348b9486450cba93f27c \ + --hash=sha256:9a5fcbe7b949f2e95c47ea8a80b410fcdf2da61c98553b45a4ee875580418b68 \ + --hash=sha256:9b3b86ec3e818f3dd3e13a9de628e88a9990f4af68ecb0b12dd3de81227f0a26 \ + --hash=sha256:9b3cf13facf6f77c283af0e1713e5e8c47a0fe295af81326cb3cb4380212e797 \ + --hash=sha256:9c5a52987a990eb1bae55f9000994f1afdb0326c154fb089992f839ab3c30688 \ + --hash=sha256:a2d79c6635ccffcbfc1d5c045874ba36b594589be81d50d43472570bb8de9c57 \ + --hash=sha256:a6ec5bf6bc361f2f0f9644907a36ce527715b488988a8df534120e5c34eeda94 \ + --hash=sha256:a7bf9cc97f05048ac8f3e02cd58f0fe62b901453c24345bfde287f4305dcc31c \ + --hash=sha256:ab9056d94e5db513d9313b34394f3a3b83e6301a581c28ad67773434f3faccab \ + --hash=sha256:adf28d13a33f9d750fe7a78fb481cac298fa257d8863d8727b2ea4455ea41235 \ + --hash=sha256:b62cb9a7501e1f5c9ffe190485501349c33e8862dde4377df774e40b8166871f \ + --hash=sha256:bacbd3c69862478cbe1c7ed4325caedec580d8acf31b8ee1b9a1e02a56295cad \ + --hash=sha256:bb349dbba57c76eec25e5917e07f35aabaf0a33b9e67fc13d188002500106487 \ + --hash=sha256:bd03472c36fa3a386a6deb887113b9e3fa40efba8203eb4fe786d3c0ccc724f6 \ + --hash=sha256:bf85a00ac3b56a1e7a19c5be7b02b5180a0895ac4d3c234d717a55e86960691c \ + --hash=sha256:ca0c7ce828bb76ab78b3991904b477c2fd0f711d7815c252d1ef28ff9450b052 \ + --hash=sha256:ccbfd94e59aad4a2566c71912b55f0547ac1680bfac25eb138e6703eb3dd434e \ + --hash=sha256:d1831c07bd4dce53c4b666fa846c7eba4b7c414f2e641a4585b7f50b72f502dc \ + --hash=sha256:d22cad98c2a10bbf6aa083a8980db6ed90d4285a841c4de892890c2b28286ef9 \ + --hash=sha256:d30ad4359413c8821cc7b3707f7ca38aa8bc852ba3b9c5a759ee2d7740157315 \ + --hash=sha256:e0dd3676ea0837cd70ea1879765e9e9f6be063be0436de9b3ea4b775caf83654 \ + --hash=sha256:e584d0cdd37cac355aca52ed788d1a2d939d6837e2870d3b70e585db24025a50 \ + --hash=sha256:e6369ac293d2cc40d52577e4fa3d75a70c1aae2d01fa3580a34a4e6eff9286b9 \ + --hash=sha256:efae5df7a8cc8bdb1037b0f786b044ce281081441df5418c3a0f0e1f86fe7bb3 \ + --hash=sha256:f19b3af31d02a2e79c5f9a6deaab0fb3c116456aeb9277d11720ad433de6dfc6 \ + --hash=sha256:f7a0430d765f9bda043e6aefaba5944d5f21ec43ff4774417d7e296f61917382 \ + --hash=sha256:fb94245a715b4d6e24689de12772b85329a1f9946cbf6187923a64ecdea39e65 # via pymilvus urllib3==2.6.3 \ --hash=sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed \ @@ -3175,135 +3168,133 @@ wrapt==1.17.3 \ --hash=sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10 \ --hash=sha256:fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c # via aiobotocore -yarl==1.22.0 \ - --hash=sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a \ - --hash=sha256:029866bde8d7b0878b9c160e72305bbf0a7342bcd20b9999381704ae03308dc8 \ - --hash=sha256:078278b9b0b11568937d9509b589ee83ef98ed6d561dfe2020e24a9fd08eaa2b \ - --hash=sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da \ - --hash=sha256:07a524d84df0c10f41e3ee918846e1974aba4ec017f990dc735aad487a0bdfdf \ - --hash=sha256:088e4e08f033db4be2ccd1f34cf29fe994772fb54cfe004bbf54db320af56890 \ - --hash=sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093 \ - --hash=sha256:0cf71bf877efeac18b38d3930594c0948c82b64547c1cf420ba48722fe5509f6 \ - --hash=sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79 \ - --hash=sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683 \ - --hash=sha256:10619d9fdee46d20edc49d3479e2f8269d0779f1b031e6f7c2aa1c76be04b7ed \ - --hash=sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2 \ - --hash=sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff \ - --hash=sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02 \ - --hash=sha256:14291620375b1060613f4aab9ebf21850058b6b1b438f386cc814813d901c60b \ - --hash=sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03 \ - --hash=sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511 \ - --hash=sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c \ - --hash=sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124 \ - --hash=sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c \ - --hash=sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da \ - --hash=sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2 \ - --hash=sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0 \ - --hash=sha256:2e4e1f6f0b4da23e61188676e3ed027ef0baa833a2e633c29ff8530800edccba \ - --hash=sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d \ - --hash=sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53 \ - --hash=sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138 \ - --hash=sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4 \ - --hash=sha256:3aa27acb6de7a23785d81557577491f6c38a5209a254d1191519d07d8fe51748 \ - --hash=sha256:3b06bcadaac49c70f4c88af4ffcfbe3dc155aab3163e75777818092478bcbbe7 \ - --hash=sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d \ - --hash=sha256:3e2daa88dc91870215961e96a039ec73e4937da13cf77ce17f9cad0c18df3503 \ - --hash=sha256:3ea66b1c11c9150f1372f69afb6b8116f2dd7286f38e14ea71a44eee9ec51b9d \ - --hash=sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2 \ - --hash=sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa \ - --hash=sha256:437840083abe022c978470b942ff832c3940b2ad3734d424b7eaffcd07f76737 \ - --hash=sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f \ - --hash=sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1 \ - --hash=sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d \ - --hash=sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694 \ - --hash=sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3 \ - --hash=sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a \ - --hash=sha256:4c52a6e78aef5cf47a98ef8e934755abf53953379b7d53e68b15ff4420e6683d \ - --hash=sha256:4dcc74149ccc8bba31ce1944acee24813e93cfdee2acda3c172df844948ddf7b \ - --hash=sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a \ - --hash=sha256:51af598701f5299012b8416486b40fceef8c26fc87dc6d7d1f6fc30609ea0aa6 \ - --hash=sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b \ - --hash=sha256:595697f68bd1f0c1c159fcb97b661fc9c3f5db46498043555d04805430e79bea \ - --hash=sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5 \ - --hash=sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f \ - --hash=sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df \ - --hash=sha256:5cdac20da754f3a723cceea5b3448e1a2074866406adeb4ef35b469d089adb8f \ - --hash=sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b \ - --hash=sha256:5dbeefd6ca588b33576a01b0ad58aa934bc1b41ef89dee505bf2932b22ddffba \ - --hash=sha256:62441e55958977b8167b2709c164c91a6363e25da322d87ae6dd9c6019ceecf9 \ - --hash=sha256:663e1cadaddae26be034a6ab6072449a8426ddb03d500f43daf952b74553bba0 \ - --hash=sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6 \ - --hash=sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b \ - --hash=sha256:6944b2dc72c4d7f7052683487e3677456050ff77fcf5e6204e98caf785ad1967 \ - --hash=sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2 \ - --hash=sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708 \ - --hash=sha256:6dcbb0829c671f305be48a7227918cfcd11276c2d637a8033a99a02b67bf9eda \ - --hash=sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8 \ - --hash=sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10 \ - --hash=sha256:75976c6945d85dbb9ee6308cd7ff7b1fb9409380c82d6119bd778d8fcfe2931c \ - --hash=sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b \ - --hash=sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028 \ - --hash=sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e \ - --hash=sha256:80ddf7a5f8c86cb3eb4bc9028b07bbbf1f08a96c5c0bc1244be5e8fefcb94147 \ - --hash=sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33 \ - --hash=sha256:84fc3ec96fce86ce5aa305eb4aa9358279d1aa644b71fab7b8ed33fe3ba1a7ca \ - --hash=sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590 \ - --hash=sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c \ - --hash=sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53 \ - --hash=sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74 \ - --hash=sha256:99b6fc1d55782461b78221e95fc357b47ad98b041e8e20f47c1411d0aacddc60 \ - --hash=sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f \ - --hash=sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1 \ - --hash=sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27 \ - --hash=sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520 \ - --hash=sha256:a4fcfc8eb2c34148c118dfa02e6427ca278bfd0f3df7c5f99e33d2c0e81eae3e \ - --hash=sha256:a899cbd98dce6f5d8de1aad31cb712ec0a530abc0a86bd6edaa47c1090138467 \ - --hash=sha256:a9b1ba5610a4e20f655258d5a1fdc7ebe3d837bb0e45b581398b99eb98b1f5ca \ - --hash=sha256:af74f05666a5e531289cb1cc9c883d1de2088b8e5b4de48004e5ca8a830ac859 \ - --hash=sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273 \ - --hash=sha256:b266bd01fedeffeeac01a79ae181719ff848a5a13ce10075adbefc8f1daee70e \ - --hash=sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601 \ - --hash=sha256:b580e71cac3f8113d3135888770903eaf2f507e9421e5697d6ee6d8cd1c7f054 \ - --hash=sha256:b6a6f620cfe13ccec221fa312139135166e47ae169f8253f72a0abc0dae94376 \ - --hash=sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7 \ - --hash=sha256:b85b982afde6df99ecc996990d4ad7ccbdbb70e2a4ba4de0aecde5922ba98a0b \ - --hash=sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb \ - --hash=sha256:ba440ae430c00eee41509353628600212112cd5018d5def7e9b05ea7ac34eb65 \ - --hash=sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784 \ - --hash=sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71 \ - --hash=sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b \ - --hash=sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a \ - --hash=sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c \ - --hash=sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face \ - --hash=sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d \ - --hash=sha256:c7bd6683587567e5a49ee6e336e0612bec8329be1b7d4c8af5687dcdeb67ee1e \ - --hash=sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e \ - --hash=sha256:cb95a9b1adaa48e41815a55ae740cfda005758104049a640a398120bf02515ca \ - --hash=sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9 \ - --hash=sha256:d332fc2e3c94dad927f2112395772a4e4fedbcf8f80efc21ed7cdfae4d574fdb \ - --hash=sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95 \ - --hash=sha256:d5372ca1df0f91a86b047d1277c2aaf1edb32d78bbcefffc81b40ffd18f027ed \ - --hash=sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf \ - --hash=sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca \ - --hash=sha256:dd7afd3f8b0bfb4e0d9fc3c31bfe8a4ec7debe124cfd90619305def3c8ca8cd2 \ - --hash=sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62 \ - --hash=sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df \ - --hash=sha256:e1b329cb8146d7b736677a2440e422eadd775d1806a81db2d4cded80a48efc1a \ - --hash=sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67 \ - --hash=sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f \ - --hash=sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529 \ - --hash=sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486 \ - --hash=sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a \ - --hash=sha256:e6438cc8f23a9c1478633d216b16104a586b9761db62bfacb6425bac0a36679e \ - --hash=sha256:e81fda2fb4a07eda1a2252b216aa0df23ebcd4d584894e9612e80999a78fd95b \ - --hash=sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74 \ - --hash=sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d \ - --hash=sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b \ - --hash=sha256:f0d97c18dfd9a9af4490631905a3f131a8e4c9e80a39353919e2cfed8f00aedc \ - --hash=sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2 \ - --hash=sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e \ - --hash=sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8 \ - --hash=sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82 \ - --hash=sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd \ - --hash=sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249 +yarl==1.23.0 \ + --hash=sha256:03214408cfa590df47728b84c679ae4ef00be2428e11630277be0727eba2d7cc \ + --hash=sha256:041b1a4cefacf65840b4e295c6985f334ba83c30607441ae3cf206a0eed1a2e4 \ + --hash=sha256:0793e2bd0cf14234983bbb371591e6bea9e876ddf6896cdcc93450996b0b5c85 \ + --hash=sha256:0e1fdaa14ef51366d7757b45bde294e95f6c8c049194e793eedb8387c86d5993 \ + --hash=sha256:0e40111274f340d32ebcc0a5668d54d2b552a6cca84c9475859d364b380e3222 \ + --hash=sha256:115136c4a426f9da976187d238e84139ff6b51a20839aa6e3720cd1026d768de \ + --hash=sha256:13a563739ae600a631c36ce096615fe307f131344588b0bc0daec108cdb47b25 \ + --hash=sha256:16c6994ac35c3e74fb0ae93323bf8b9c2a9088d55946109489667c510a7d010e \ + --hash=sha256:170e26584b060879e29fac213e4228ef063f39128723807a312e5c7fec28eff2 \ + --hash=sha256:17235362f580149742739cc3828b80e24029d08cbb9c4bda0242c7b5bc610a8e \ + --hash=sha256:1932b6b8bba8d0160a9d1078aae5838a66039e8832d41d2992daa9a3a08f7860 \ + --hash=sha256:1b6b572edd95b4fa8df75de10b04bc81acc87c1c7d16bcdd2035b09d30acc957 \ + --hash=sha256:1c3a3598a832590c5a3ce56ab5576361b5688c12cb1d39429cf5dba30b510760 \ + --hash=sha256:1c57676bdedc94cd3bc37724cf6f8cd2779f02f6aba48de45feca073e714fe52 \ + --hash=sha256:1dc702e42d0684f42d6519c8d581e49c96cefaaab16691f03566d30658ee8788 \ + --hash=sha256:21d1b7305a71a15b4794b5ff22e8eef96ff4a6d7f9657155e5aa419444b28912 \ + --hash=sha256:23f371bd662cf44a7630d4d113101eafc0cfa7518a2760d20760b26021454719 \ + --hash=sha256:2569b67d616eab450d262ca7cb9f9e19d2f718c70a8b88712859359d0ab17035 \ + --hash=sha256:263cd4f47159c09b8b685890af949195b51d1aa82ba451c5847ca9bc6413c220 \ + --hash=sha256:2803ed8b21ca47a43da80a6fd1ed3019d30061f7061daa35ac54f63933409412 \ + --hash=sha256:2a6940a074fb3c48356ed0158a3ca5699c955ee4185b4d7d619be3c327143e05 \ + --hash=sha256:2e27c8841126e017dd2a054a95771569e6070b9ee1b133366d8b31beb5018a41 \ + --hash=sha256:31c9921eb8bd12633b41ad27686bbb0b1a2a9b8452bfdf221e34f311e9942ed4 \ + --hash=sha256:34b6cf500e61c90f305094911f9acc9c86da1a05a7a3f5be9f68817043f486e4 \ + --hash=sha256:3650dc2480f94f7116c364096bc84b1d602f44224ef7d5c7208425915c0475dd \ + --hash=sha256:389871e65468400d6283c0308e791a640b5ab5c83bcee02a2f51295f95e09748 \ + --hash=sha256:39004f0ad156da43e86aa71f44e033de68a44e5a31fc53507b36dd253970054a \ + --hash=sha256:394906945aa8b19fc14a61cf69743a868bb8c465efe85eee687109cc540b98f4 \ + --hash=sha256:3ceb13c5c858d01321b5d9bb65e4cf37a92169ea470b70fec6f236b2c9dd7e34 \ + --hash=sha256:411225bae281f114067578891bc75534cfb3d92a3b4dfef7a6ca78ba354e6069 \ + --hash=sha256:44bb7bef4ea409384e3f8bc36c063d77ea1b8d4a5b2706956c0d6695f07dcc25 \ + --hash=sha256:4503053d296bc6e4cbd1fad61cf3b6e33b939886c4f249ba7c78b602214fabe2 \ + --hash=sha256:4764a6a7588561a9aef92f65bda2c4fb58fe7c675c0883862e6df97559de0bfb \ + --hash=sha256:4966242ec68afc74c122f8459abd597afd7d8a60dc93d695c1334c5fd25f762f \ + --hash=sha256:4a42e651629dafb64fd5b0286a3580613702b5809ad3f24934ea87595804f2c5 \ + --hash=sha256:4a59ba56f340334766f3a4442e0efd0af895fae9e2b204741ef885c446b3a1a8 \ + --hash=sha256:4c41e021bc6d7affb3364dc1e1e5fa9582b470f283748784bd6ea0558f87f42c \ + --hash=sha256:5023346c4ee7992febc0068e7593de5fa2bf611848c08404b35ebbb76b1b0512 \ + --hash=sha256:50f9d8d531dfb767c565f348f33dd5139a6c43f5cbdf3f67da40d54241df93f6 \ + --hash=sha256:51430653db848d258336cfa0244427b17d12db63d42603a55f0d4546f50f25b5 \ + --hash=sha256:531ef597132086b6cf96faa7c6c1dcd0361dd5f1694e5cc30375907b9b7d3ea9 \ + --hash=sha256:53ad387048f6f09a8969631e4de3f1bf70c50e93545d64af4f751b2498755072 \ + --hash=sha256:53b1ea6ca88ebd4420379c330aea57e258408dd0df9af0992e5de2078dc9f5d5 \ + --hash=sha256:575aa4405a656e61a540f4a80eaa5260f2a38fff7bfdc4b5f611840d76e9e277 \ + --hash=sha256:578110dd426f0d209d1509244e6d4a3f1a3e9077655d98c5f22583d63252a08a \ + --hash=sha256:5ec2f42d41ccbd5df0270d7df31618a8ee267bfa50997f5d720ddba86c4a83a6 \ + --hash=sha256:5ee586fb17ff8f90c91cf73c6108a434b02d69925f44f5f8e0d7f2f260607eae \ + --hash=sha256:5f10fd85e4b75967468af655228fbfd212bdf66db1c0d135065ce288982eda26 \ + --hash=sha256:609d3614d78d74ebe35f54953c5bbd2ac647a7ddb9c30a5d877580f5e86b22f2 \ + --hash=sha256:62694e275c93d54f7ccedcfef57d42761b2aad5234b6be1f3e3026cae4001cd4 \ + --hash=sha256:63e92247f383c85ab00dd0091e8c3fa331a96e865459f5ee80353c70a4a42d70 \ + --hash=sha256:682bae25f0a0dd23a056739f23a134db9f52a63e2afd6bfb37ddc76292bbd723 \ + --hash=sha256:6b41389c19b07c760c7e427a3462e8ab83c4bb087d127f0e854c706ce1b9215c \ + --hash=sha256:6e87a6e8735b44816e7db0b2fbc9686932df473c826b0d9743148432e10bb9b9 \ + --hash=sha256:6f0fd84de0c957b2d280143522c4f91a73aada1923caee763e24a2b3fda9f8a5 \ + --hash=sha256:70efd20be968c76ece7baa8dafe04c5be06abc57f754d6f36f3741f7aa7a208e \ + --hash=sha256:71d006bee8397a4a89f469b8deb22469fe7508132d3c17fa6ed871e79832691c \ + --hash=sha256:73309162a6a571d4cbd3b6a1dcc703c7311843ae0d1578df6f09be4e98df38d4 \ + --hash=sha256:75e3026ab649bf48f9a10c0134512638725b521340293f202a69b567518d94e0 \ + --hash=sha256:76855800ac56f878847a09ce6dba727c93ca2d89c9e9d63002d26b916810b0a2 \ + --hash=sha256:7c6b9461a2a8b47c65eef63bb1c76a4f1c119618ffa99ea79bc5bb1e46c5821b \ + --hash=sha256:803a3c3ce4acc62eaf01eaca1208dcf0783025ef27572c3336502b9c232005e7 \ + --hash=sha256:80e6d33a3d42a7549b409f199857b4fb54e2103fc44fb87605b6663b7a7ff750 \ + --hash=sha256:8419ebd326430d1cbb7efb5292330a2cf39114e82df5cc3d83c9a0d5ebeaf2f2 \ + --hash=sha256:85610b4f27f69984932a7abbe52703688de3724d9f72bceb1cca667deff27474 \ + --hash=sha256:85e9beda1f591bc73e77ea1c51965c68e98dafd0fec72cdd745f77d727466716 \ + --hash=sha256:877b0738624280e34c55680d6054a307aa94f7d52fa0e3034a9cc6e790871da7 \ + --hash=sha256:88f9fb0116fbfcefcab70f85cf4b74a2b6ce5d199c41345296f49d974ddb4123 \ + --hash=sha256:8c4fe09e0780c6c3bf2b7d4af02ee2394439d11a523bbcf095cf4747c2932007 \ + --hash=sha256:93a784271881035ab4406a172edb0faecb6e7d00f4b53dc2f55919d6c9688595 \ + --hash=sha256:94f8575fbdf81749008d980c17796097e645574a3b8c28ee313931068dad14fe \ + --hash=sha256:95451e6ce06c3e104556d73b559f5da6c34a069b6b62946d3ad66afcd51642ea \ + --hash=sha256:99c8a9ed30f4164bc4c14b37a90208836cbf50d4ce2a57c71d0f52c7fb4f7598 \ + --hash=sha256:9a18d6f9359e45722c064c97464ec883eb0e0366d33eda61cb19a244bf222679 \ + --hash=sha256:9cbf44c5cb4a7633d078788e1b56387e3d3cf2b8139a3be38040b22d6c3221c8 \ + --hash=sha256:9ee33b875f0b390564c1fb7bc528abf18c8ee6073b201c6ae8524aca778e2d83 \ + --hash=sha256:a0e317df055958a0c1e79e5d2aa5a5eaa4a6d05a20d4b0c9c3f48918139c9fc6 \ + --hash=sha256:a2df6afe50dea8ae15fa34c9f824a3ee958d785fd5d089063d960bae1daa0a3f \ + --hash=sha256:a31de1613658308efdb21ada98cbc86a97c181aa050ba22a808120bb5be3ab94 \ + --hash=sha256:a3d2bff8f37f8d0f96c7ec554d16945050d54462d6e95414babaa18bfafc7f51 \ + --hash=sha256:a41bcf68efd19073376eb8cf948b8d9be0af26256403e512bb18f3966f1f9120 \ + --hash=sha256:a82836cab5f197a0514235aaf7ffccdc886ccdaa2324bc0aafdd4ae898103039 \ + --hash=sha256:a8d00f29b42f534cc8aa3931cfe773b13b23e561e10d2b26f27a8d309b0e82a1 \ + --hash=sha256:aafe5dcfda86c8af00386d7781d4c2181b5011b7be3f2add5e99899ea925df05 \ + --hash=sha256:ab5f043cb8a2d71c981c09c510da013bc79fd661f5c60139f00dd3c3cc4f2ffb \ + --hash=sha256:ac09d42f48f80c9ee1635b2fcaa819496a44502737660d3c0f2ade7526d29144 \ + --hash=sha256:aecfed0b41aa72b7881712c65cf764e39ce2ec352324f5e0837c7048d9e6daaa \ + --hash=sha256:b2c6b50c7b0464165472b56b42d4c76a7b864597007d9c085e8b63e185cf4a7a \ + --hash=sha256:b35d13d549077713e4414f927cdc388d62e543987c572baee613bf82f11a4b99 \ + --hash=sha256:b39cb32a6582750b6cc77bfb3c49c0f8760dc18dc96ec9fb55fbb0f04e08b928 \ + --hash=sha256:b5405bb8f0e783a988172993cfc627e4d9d00432d6bbac65a923041edacf997d \ + --hash=sha256:baaf55442359053c7d62f6f8413a62adba3205119bcb6f49594894d8be47e5e3 \ + --hash=sha256:bd654fad46d8d9e823afbb4f87c79160b5a374ed1ff5bde24e542e6ba8f41434 \ + --hash=sha256:be61f6fff406ca40e3b1d84716fde398fc08bc63dd96d15f3a14230a0973ed86 \ + --hash=sha256:bf49a3ae946a87083ef3a34c8f677ae4243f5b824bfc4c69672e72b3d6719d46 \ + --hash=sha256:c4a80f77dc1acaaa61f0934176fccca7096d9b1ff08c8ba9cddf5ae034a24319 \ + --hash=sha256:c75eb09e8d55bceb4367e83496ff8ef2bc7ea6960efb38e978e8073ea59ecb67 \ + --hash=sha256:c7f8dc16c498ff06497c015642333219871effba93e4a2e8604a06264aca5c5c \ + --hash=sha256:c8aa34a5c864db1087d911a0b902d60d203ea3607d91f615acd3f3108ac32169 \ + --hash=sha256:cbb0fef01f0c6b38cb0f39b1f78fc90b807e0e3c86a7ff3ce74ad77ce5c7880c \ + --hash=sha256:cde9a2ecd91668bcb7f077c4966d8ceddb60af01b52e6e3e2680e4cf00ad1a59 \ + --hash=sha256:cff6d44cb13d39db2663a22b22305d10855efa0fa8015ddeacc40bc59b9d8107 \ + --hash=sha256:d1009abedb49ae95b136a8904a3f71b342f849ffeced2d3747bf29caeda218c4 \ + --hash=sha256:d38c1e8231722c4ce40d7593f28d92b5fc72f3e9774fe73d7e800ec32299f63a \ + --hash=sha256:d53834e23c015ee83a99377db6e5e37d8484f333edb03bd15b4bc312cc7254fb \ + --hash=sha256:d7504f2b476d21653e4d143f44a175f7f751cd41233525312696c76aa3dbb23f \ + --hash=sha256:dbf507e9ef5688bada447a24d68b4b58dd389ba93b7afc065a2ba892bea54769 \ + --hash=sha256:dc52310451fc7c629e13c4e061cbe2dd01684d91f2f8ee2821b083c58bd72432 \ + --hash=sha256:dd00607bffbf30250fe108065f07453ec124dbf223420f57f5e749b04295e090 \ + --hash=sha256:dda608c88cf709b1d406bdfcd84d8d63cff7c9e577a403c6108ce8ce9dcc8764 \ + --hash=sha256:debe9c4f41c32990771be5c22b56f810659f9ddf3d63f67abfdcaa2c6c9c5c1d \ + --hash=sha256:e09fd068c2e169a7070d83d3bde728a4d48de0549f975290be3c108c02e499b4 \ + --hash=sha256:e0fd068364a6759bc794459f0a735ab151d11304346332489c7972bacbe9e72b \ + --hash=sha256:e4c53f8347cd4200f0d70a48ad059cabaf24f5adc6ba08622a23423bc7efa10d \ + --hash=sha256:e5723c01a56c5028c807c701aa66722916d2747ad737a046853f6c46f4875543 \ + --hash=sha256:e7b0460976dc75cb87ad9cc1f9899a4b97751e7d4e77ab840fc9b6d377b8fd24 \ + --hash=sha256:e9d9a4d06d3481eab79803beb4d9bd6f6a8e781ec078ac70d7ef2dcc29d1bea5 \ + --hash=sha256:ead11956716a940c1abc816b7df3fa2b84d06eaed8832ca32f5c5e058c65506b \ + --hash=sha256:ed5f69ce7be7902e5c70ea19eb72d20abf7d725ab5d49777d696e32d4fc1811d \ + --hash=sha256:f2af5c81a1f124609d5f33507082fc3f739959d4719b56877ab1ee7e7b3d602b \ + --hash=sha256:f40e782d49630ad384db66d4d8b73ff4f1b8955dc12e26b09a3e3af064b3b9d6 \ + --hash=sha256:f514f6474e04179d3d33175ed3f3e31434d3130d42ec153540d5b157deefd735 \ + --hash=sha256:f69f57305656a4852f2a7203efc661d8c042e6cc67f7acd97d8667fb448a426e \ + --hash=sha256:fb1e8b8d66c278b21d13b0a7ca22c41dd757a7c209c6b12c313e445c31dd3b28 \ + --hash=sha256:fb4948814a2a98e3912505f09c9e7493b1506226afb1f881825368d6fb776ee3 \ + --hash=sha256:fda207c815b253e34f7e1909840fd14299567b1c0eb4908f8c2ce01a41265401 \ + --hash=sha256:fe8f8f5e70e6dbdfca9882cd9deaac058729bcf323cf7a58660901e55c9c94f6 \ + --hash=sha256:fffc45637bcd6538de8b85f51e3df3223e4ad89bccbfca0481c08c7fc8b7ed7d # via aiohttp diff --git a/sdk/python/requirements/py3.12-minimal-sdist-requirements-build.txt b/sdk/python/requirements/py3.12-minimal-sdist-requirements-build.txt index f90866aad88..15c53b6ba7e 100644 --- a/sdk/python/requirements/py3.12-minimal-sdist-requirements-build.txt +++ b/sdk/python/requirements/py3.12-minimal-sdist-requirements-build.txt @@ -280,9 +280,9 @@ hatch-vcs==0.5.0 \ # via # filelock # platformdirs -hatchling==1.28.0 \ - --hash=sha256:4d50b02aece6892b8cd0b3ce6c82cb218594d3ec5836dbde75bf41a21ab004c8 \ - --hash=sha256:dc48722b68b3f4bbfa3ff618ca07cdea6750e7d03481289ffa8be1521d18a961 +hatchling==1.29.0 \ + --hash=sha256:50af9343281f34785fab12da82e445ed987a6efb34fd8c2fc0f6e6630dbcc1b0 \ + --hash=sha256:793c31816d952cee405b83488ce001c719f325d9cda69f1fc4cd750527640ea6 # via # annotated-types # atpublic @@ -319,97 +319,97 @@ jinja2==3.1.6 \ --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 # via uv-dynamic-versioning -librt==0.8.0 \ - --hash=sha256:001e5330093d887b8b9165823eca6c5c4db183fe4edea4fdc0680bbac5f46944 \ - --hash=sha256:015e2dde6e096d27c10238bf9f6492ba6c65822dfb69d2bf74c41a8e88b7ddef \ - --hash=sha256:02a9fe85410cc9bef045e7cb7fd26fdde6669e6d173f99df659aa7f6335961e9 \ - --hash=sha256:0583aef7e9a720dd40f26a2ad5a1bf2ccbb90059dac2b32ac516df232c701db3 \ - --hash=sha256:05a3dd3f116747f7e1a2b475ccdc6fb637fd4987126d109e03013a79d40bf9e6 \ - --hash=sha256:0a33335eb59921e77c9acc05d0e654e4e32e45b014a4d61517897c11591094f8 \ - --hash=sha256:0ce33a9778e294507f3a0e3468eccb6a698b5166df7db85661543eca1cfc5369 \ - --hash=sha256:1566dbb9d1eb0987264c9b9460d212e809ba908d2f4a3999383a84d765f2f3f1 \ - --hash=sha256:17269dd2745dbe8e42475acb28e419ad92dfa38214224b1b01020b8cac70b645 \ - --hash=sha256:178707cda89d910c3b28bf5aa5f69d3d4734e0f6ae102f753ad79edef83a83c7 \ - --hash=sha256:1c25a131013eadd3c600686a0c0333eb2896483cbc7f65baa6a7ee761017aef9 \ - --hash=sha256:1e6811cac1dcb27ca4c74e0ca4a5917a8e06db0d8408d30daee3a41724bfde7a \ - --hash=sha256:1ef3bd856373cf8e7382402731f43bfe978a8613b4039e49e166e1e0dc590216 \ - --hash=sha256:20f73d4fecba969efc15cdefd030e382502d56bb6f1fc66b580cce582836c9fa \ - --hash=sha256:21b14464bee0b604d80a638cf1ee3148d84ca4cc163dcdcecb46060c1b3605e4 \ - --hash=sha256:24a01c13a2a9bdad20997a4443ebe6e329df063d1978bbe2ebbf637878a46d1e \ - --hash=sha256:25b3e667cbfc9000c4740b282df599ebd91dbdcc1aa6785050e4c1d6be5329ab \ - --hash=sha256:25e82d920d4d62ad741592fcf8d0f3bda0e3fc388a184cb7d2f566c681c5f7b9 \ - --hash=sha256:2b37437e7e4ef5e15a297b36ba9e577f73e29564131d86dd75875705e97402b5 \ - --hash=sha256:2ccdd20d9a72c562ffb73098ac411de351b53a6fbb3390903b2d33078ef90447 \ - --hash=sha256:2e0ffe88ebb5962f8fb0ddcbaaff30f1ea06a79501069310e1e030eafb1ad787 \ - --hash=sha256:375eda7acfce1f15f5ed56cfc960669eefa1ec8732e3e9087c3c4c3f2066759c \ - --hash=sha256:3d2720335020219197380ccfa5c895f079ac364b4c429e96952cd6509934d8eb \ - --hash=sha256:3e36a8da17134ffc29373775d88c04832f9ecfab1880470661813e6c7991ef79 \ - --hash=sha256:3e8b77b5f54d0937b26512774916041756c9eb3e66f1031971e626eea49d0bf4 \ - --hash=sha256:41064a0c07b4cc7a81355ccc305cb097d6027002209ffca51306e65ee8293630 \ - --hash=sha256:421765e8c6b18e64d21c8ead315708a56fc24f44075059702e421d164575fdda \ - --hash=sha256:4831c44b8919e75ca0dfb52052897c1ef59fdae19d3589893fbd068f1e41afbf \ - --hash=sha256:48f84830a8f8ad7918afd743fd7c4eb558728bceab7b0e38fd5a5cf78206a556 \ - --hash=sha256:4b705f85311ee76acec5ee70806990a51f0deb519ea0c29c1d1652d79127604d \ - --hash=sha256:4d3e38797eb482485b486898f89415a6ab163bc291476bd95712e42cf4383c05 \ - --hash=sha256:4eb5e06ebcc668677ed6389164f52f13f71737fc8be471101fa8b4ce77baeb0c \ - --hash=sha256:4f6e975377fbc4c9567cb33ea9ab826031b6c7ec0515bfae66a4fb110d40d6da \ - --hash=sha256:4f764b2424cb04524ff7a486b9c391e93f93dc1bd8305b2136d25e582e99aa2f \ - --hash=sha256:507e94f4bec00b2f590fbe55f48cd518a208e2474a3b90a60aa8f29136ddbada \ - --hash=sha256:56901f1eec031396f230db71c59a01d450715cbbef9856bf636726994331195d \ - --hash=sha256:5cb11061a736a9db45e3c1293cfcb1e3caf205912dfa085734ba750f2197ff9a \ - --hash=sha256:5d0f76fc73480d42285c609c0ea74d79856c160fa828ff9aceab574ea4ecfd7b \ - --hash=sha256:667e2513cf69bfd1e1ed9a00d6c736d5108714ec071192afb737987955888a25 \ - --hash=sha256:671a6152edf3b924d98a5ed5e6982ec9cb30894085482acadce0975f031d4c5c \ - --hash=sha256:693697133c3b32aa9b27f040e3691be210e9ac4d905061859a9ed519b1d5a376 \ - --hash=sha256:6a3146c63220d814c4a2c7d6a1eacc8d5c14aed0ff85115c1dfea868080cd18f \ - --hash=sha256:6b6caff69e25d80c269b1952be8493b4d94ef745f438fa619d7931066bdd26de \ - --hash=sha256:6e1af31a710e17891d9adf0dbd9a5fcd94901a3922a96499abdbf7ce658f4e01 \ - --hash=sha256:70defb797c4d5402166787a6b3c66dfb3fa7f93d118c0509ffafa35a392f4258 \ - --hash=sha256:71fc517efc14f75c2f74b1f0a5d5eb4a8e06aa135c34d18eaf3522f4a53cd62d \ - --hash=sha256:75d1a8cab20b2043f03f7aab730551e9e440adc034d776f15f6f8d582b0a5ad4 \ - --hash=sha256:789911e8fa40a2e82f41120c936b1965f3213c67f5a483fc5a41f5839a05dcbb \ - --hash=sha256:7bd68cebf3131bb920d5984f75fe302d758db33264e44b45ad139385662d7bc3 \ - --hash=sha256:7ce0a8cb67e702dcb06342b2aaaa3da9fb0ddc670417879adfa088b44cf7b3b6 \ - --hash=sha256:7f820210e21e3a8bf8fde2ae3c3d10106d4de9ead28cbfdf6d0f0f41f5b12fa1 \ - --hash=sha256:8070aa3368559de81061ef752770d03ca1f5fc9467d4d512d405bd0483bfffe6 \ - --hash=sha256:82e61cd1c563745ad495387c3b65806bfd453badb4adbc019df3389dddee1bf6 \ - --hash=sha256:82fb4602d1b3e303a58bfe6165992b5a78d823ec646445356c332cd5f5bbaa61 \ - --hash=sha256:88c6e75540f1f10f5e0fc5e87b4b6c290f0e90d1db8c6734f670840494764af8 \ - --hash=sha256:8992ca186a1678107b0af3d0c9303d8c7305981b9914989b9788319ed4d89546 \ - --hash=sha256:92249938ab744a5890580d3cb2b22042f0dce71cdaa7c1369823df62bedf7cbc \ - --hash=sha256:95a719a049f0eefaf1952673223cf00d442952273cbd20cf2ed7ec423a0ef58d \ - --hash=sha256:9646178cd794704d722306c2c920c221abbf080fede3ba539d5afdec16c46dad \ - --hash=sha256:9726305d3e53419d27fc8cdfcd3f9571f0ceae22fa6b5ea1b3662c2e538f833e \ - --hash=sha256:995d24caa6bbb34bcdd4a41df98ac6d1af637cfa8975cb0790e47d6623e70e3e \ - --hash=sha256:9ab3a3475a55b89b87ffd7e6665838e8458e0b596c22e0177e0f961434ec474a \ - --hash=sha256:9f09d4884f882baa39a7e36bbf3eae124c4ca2a223efb91e567381d1c55c6b06 \ - --hash=sha256:a512c88900bdb1d448882f5623a0b1ad27ba81a9bd75dacfe17080b72272ca1f \ - --hash=sha256:a905091a13e0884701226860836d0386b88c72ce5c2fdfba6618e14c72be9f25 \ - --hash=sha256:aaadec87f45a3612b6818d1db5fbfe93630669b7ee5d6bdb6427ae08a1aa2141 \ - --hash=sha256:b055bb3abaf69abed25743d8fc1ab691e4f51a912ee0a6f9a6c84f4bbddb283d \ - --hash=sha256:b4bb00bd71b448f16749909b08a0ff16f58b079e2261c2e1000f2bbb2a4f0a45 \ - --hash=sha256:b9aef96d7593584e31ef6ac1eb9775355b0099fee7651fae3a15bc8657b67b52 \ - --hash=sha256:ba581acad5ac8f33e2ff1746e8a57e001b47c6721873121bf8bbcf7ba8bd3aa4 \ - --hash=sha256:ba9d9e60651615bc614be5e21a82cdb7b1769a029369cf4b4d861e4f19686fb6 \ - --hash=sha256:bbebd2bba5c6ae02907df49150e55870fdd7440d727b6192c46b6f754723dde9 \ - --hash=sha256:bd32add59b58fba3439d48d6f36ac695830388e3da3e92e4fc26d2d02670d19c \ - --hash=sha256:bdab762e2c0b48bab76f1a08acb3f4c77afd2123bedac59446aeaaeed3d086cf \ - --hash=sha256:c5512aae4648152abaf4d48b59890503fcbe86e85abc12fb9b096fe948bdd816 \ - --hash=sha256:c6e4c10761ddbc0d67d2f6e2753daf99908db85d8b901729bf2bf5eaa60e0567 \ - --hash=sha256:cb4b3ad543084ed79f186741470b251b9d269cd8b03556f15a8d1a99a64b7de5 \ - --hash=sha256:cb74cdcbc0103fc988e04e5c58b0b31e8e5dd2babb9182b6f9490488eb36324b \ - --hash=sha256:cc3d107f603b5ee7a79b6aa6f166551b99b32fb4a5303c4dfcb4222fc6a0335e \ - --hash=sha256:d920789eca7ef71df7f31fd547ec0d3002e04d77f30ba6881e08a630e7b2c30e \ - --hash=sha256:daae5e955764be8fd70a93e9e5133c75297f8bce1e802e1d3683b98f77e1c5ab \ - --hash=sha256:db63cf3586a24241e89ca1ce0b56baaec9d371a328bd186c529b27c914c9a1ef \ - --hash=sha256:db953b675079884ffda33d1dca7189fb961b6d372153750beb81880384300817 \ - --hash=sha256:de076eaba208d16efb5962f99539867f8e2c73480988cb513fcf1b5dbb0c9dcf \ - --hash=sha256:e79dbc8f57de360f0ed987dc7de7be814b4803ef0e8fc6d3ff86e16798c99935 \ - --hash=sha256:e9a3a38eb4134ad33122a6d575e6324831f930a771d951a15ce232e0237412c2 \ - --hash=sha256:f04ca50e847abc486fa8f4107250566441e693779a5374ba211e96e238f298b9 \ - --hash=sha256:f1178e0de0c271231a660fbef9be6acdfa1d596803464706862bef6644cc1cae \ - --hash=sha256:f4617cef654fca552f00ce5ffdf4f4b68770f18950e4246ce94629b789b92467 \ - --hash=sha256:fa37f99bff354ff191c6bcdffbc9d7cdd4fc37faccfc9be0ef3a4fd5613977da +librt==0.8.1 \ + --hash=sha256:01170b6729a438f0dedc4a26ed342e3dc4f02d1000b4b19f980e1877f0c297e6 \ + --hash=sha256:039b9f2c506bd0ab0f8725aa5ba339c6f0cd19d3b514b50d134789809c24285d \ + --hash=sha256:05bd41cdee35b0c59c259f870f6da532a2c5ca57db95b5f23689fcb5c9e42440 \ + --hash=sha256:086a32dbb71336627e78cc1d6ee305a68d038ef7d4c39aaff41ae8c9aa46e91a \ + --hash=sha256:08eec3a1fc435f0d09c87b6bf1ec798986a3544f446b864e4099633a56fcd9ed \ + --hash=sha256:0bf69d79a23f4f40b8673a947a234baeeb133b5078b483b7297c5916539cf5d5 \ + --hash=sha256:0c3811485fccfda840861905b8c70bba5ec094e02825598bb9d4ca3936857a04 \ + --hash=sha256:0d2f82168e55ddefd27c01c654ce52379c0750ddc31ee86b4b266bcf4d65f2a3 \ + --hash=sha256:0f2ae3725904f7377e11cc37722d5d401e8b3d5851fb9273d7f4fe04f6b3d37d \ + --hash=sha256:10c42e1f6fd06733ef65ae7bebce2872bcafd8d6e6b0a08fe0a05a23b044fb14 \ + --hash=sha256:153188fe98a72f206042be10a2c6026139852805215ed9539186312d50a8e972 \ + --hash=sha256:172d57ec04346b047ca6af181e1ea4858086c80bdf455f61994c4aa6fc3f866c \ + --hash=sha256:190b109bb69592a3401fe1ffdea41a2e73370ace2ffdc4a0e8e2b39cdea81b78 \ + --hash=sha256:1d3a7da44baf692f0c6aeb5b2a09c5e6fc7a703bca9ffa337ddd2e2da53f7732 \ + --hash=sha256:228c2409c079f8c11fb2e5d7b277077f694cb93443eb760e00b3b83cb8b3176c \ + --hash=sha256:22b46eabd76c1986ee7d231b0765ad387d7673bbd996aa0d0d054b38ac65d8f6 \ + --hash=sha256:237796479f4d0637d6b9cbcb926ff424a97735e68ade6facf402df4ec93375ed \ + --hash=sha256:2c74a2da57a094bd48d03fa5d196da83d2815678385d2978657499063709abe1 \ + --hash=sha256:2cc68eeeef5e906839c7bb0815748b5b0a974ec27125beefc0f942715785b551 \ + --hash=sha256:2eb345e8b33fb748227409c9f1233d4df354d6e54091f0e8fc53acdb2ffedeb7 \ + --hash=sha256:31362dbfe297b23590530007062c32c6f6176f6099646bb2c95ab1b00a57c382 \ + --hash=sha256:3dff3d3ca8db20e783b1bc7de49c0a2ab0b8387f31236d6a026597d07fcd68ac \ + --hash=sha256:43353b943613c5d9c49a25aaffdba46f888ec354e71e3529a00cca3f04d66a7a \ + --hash=sha256:439352ba9373f11cb8e1933da194dcc6206daf779ff8df0ed69c5e39113e6a99 \ + --hash=sha256:4998009e7cb9e896569f4be7004f09d0ed70d386fa99d42b6d363f6d200501ac \ + --hash=sha256:4be2a5c926b9770c9e08e717f05737a269b9d0ebc5d2f0060f0fe3fe9ce47acb \ + --hash=sha256:4beb04b8c66c6ae62f8c1e0b2f097c1ebad9295c929a8d5286c05eae7c2fc7dc \ + --hash=sha256:4c8dfa264b9193c4ee19113c985c95f876fae5e51f731494fc4e0cf594990ba7 \ + --hash=sha256:5212a5bd7fae98dae95710032902edcd2ec4dc994e883294f75c857b83f9aba0 \ + --hash=sha256:52c224e14614b750c0a6d97368e16804a98c684657c7518752c356834fff83bb \ + --hash=sha256:56e04c14b696300d47b3bc5f1d10a00e86ae978886d0cee14e5714fafb5df5d2 \ + --hash=sha256:5bb54f1205a3a6ab41a6fd71dfcdcbd278670d3a90ca502a30d9da583105b6f7 \ + --hash=sha256:5cdc0f588ff4b663ea96c26d2a230c525c6fc62b28314edaaaca8ed5af931ad0 \ + --hash=sha256:5db05697c82b3a2ec53f6e72b2ed373132b0c2e05135f0696784e97d7f5d48e7 \ + --hash=sha256:5e4af413908f77294605e28cfd98063f54b2c790561383971d2f52d113d9c363 \ + --hash=sha256:5fc48998000cbc39ec0d5311312dda93ecf92b39aaf184c5e817d5d440b29624 \ + --hash=sha256:60a78b694c9aee2a0f1aaeaa7d101cf713e92e8423a941d2897f4fa37908dab9 \ + --hash=sha256:64548cde61b692dc0dc379f4b5f59a2f582c2ebe7890d09c1ae3b9e66fa015b7 \ + --hash=sha256:681dc2451d6d846794a828c16c22dc452d924e9f700a485b7ecb887a30aad1fd \ + --hash=sha256:6b1977c4ea97ce5eb7755a78fae68d87e4102e4aaf54985e8b56806849cc06a3 \ + --hash=sha256:6cfa7fe54fd4d1f47130017351a959fe5804bda7a0bc7e07a2cdbc3fdd28d34f \ + --hash=sha256:738f08021b3142c2918c03692608baed43bc51144c29e35807682f8070ee2a3a \ + --hash=sha256:747328be0c5b7075cde86a0e09d7a9196029800ba75a1689332348e998fb85c0 \ + --hash=sha256:758509ea3f1eba2a57558e7e98f4659d0ea7670bff49673b0dde18a3c7e6c0eb \ + --hash=sha256:785ae29c1f5c6e7c2cde2c7c0e148147f4503da3abc5d44d482068da5322fd9e \ + --hash=sha256:7aae78ab5e3206181780e56912d1b9bb9f90a7249ce12f0e8bf531d0462dd0fc \ + --hash=sha256:7b02679a0d783bdae30d443025b94465d8c3dc512f32f5b5031f93f57ac32071 \ + --hash=sha256:7e2f3edca35664499fbb36e4770650c4bd4a08abc1f4458eab9df4ec56389730 \ + --hash=sha256:7e6bad1cd94f6764e1e21950542f818a09316645337fd5ab9a7acc45d99a8f35 \ + --hash=sha256:81fd938344fecb9373ba1b155968c8a329491d2ce38e7ddb76f30ffb938f12dc \ + --hash=sha256:82210adabbc331dbb65d7868b105185464ef13f56f7f76688565ad79f648b0fe \ + --hash=sha256:89815a22daf9c51884fb5dbe4f1ef65ee6a146e0b6a8df05f753e2e4a9359bf4 \ + --hash=sha256:8f1125e6bbf2f1657d9a2f3ccc4a2c9b0c8b176965bb565dd4d86be67eddb4b6 \ + --hash=sha256:8f4bb453f408137d7581be309b2fbc6868a80e7ef60c88e689078ee3a296ae71 \ + --hash=sha256:924817ab3141aca17893386ee13261f1d100d1ef410d70afe4389f2359fea4f0 \ + --hash=sha256:93c2af9e01e0ef80d95ae3c720be101227edae5f2fe7e3dc63d8857fadfc5a1d \ + --hash=sha256:97c2b54ff6717a7a563b72627990bec60d8029df17df423f0ed37d56a17a176b \ + --hash=sha256:9be2f15e53ce4e83cc08adc29b26fb5978db62ef2a366fbdf716c8a6c8901040 \ + --hash=sha256:9e2c6f77b9ad48ce5603b83b7da9ee3e36b3ab425353f695cba13200c5d96596 \ + --hash=sha256:a28f2612ab566b17f3698b0da021ff9960610301607c9a5e8eaca62f5e1c350a \ + --hash=sha256:a355d99c4c0d8e5b770313b8b247411ed40949ca44e33e46a4789b9293a907ee \ + --hash=sha256:a3b4350b13cc0e6f5bec8fa7caf29a8fb8cdc051a3bae45cfbfd7ce64f009965 \ + --hash=sha256:aaab0e307e344cb28d800957ef3ec16605146ef0e59e059a60a176d19543d1b7 \ + --hash=sha256:ac1e7817fd0ed3d14fd7c5df91daed84c48e4c2a11ee99c0547f9f62fdae13da \ + --hash=sha256:adfab487facf03f0d0857b8710cf82d0704a309d8ffc33b03d9302b4c64e91a9 \ + --hash=sha256:b6d7ab1f01aa753188605b09a51faa44a3327400b00b8cce424c71910fc0a128 \ + --hash=sha256:bacdb58d9939d95cc557b4dbaa86527c9db2ac1ed76a18bc8d26f6dc8647d851 \ + --hash=sha256:be46a14693955b3bd96014ccbdb8339ee8c9346fbe11c1b78901b55125f14c73 \ + --hash=sha256:bf512a71a23504ed08103a13c941f763db13fb11177beb3d9244c98c29fb4a61 \ + --hash=sha256:c00e5c884f528c9932d278d5c9cbbea38a6b81eb62c02e06ae53751a83a4d52b \ + --hash=sha256:c25d9e338d5bed46c1632f851babf3d13c78f49a225462017cf5e11e845c5891 \ + --hash=sha256:c336d61d2fe74a3195edc1646d53ff1cddd3a9600b09fa6ab75e5514ba4862a7 \ + --hash=sha256:cc3656283d11540ab0ea01978378e73e10002145117055e03722417aeab30994 \ + --hash=sha256:cf450f498c30af55551ba4f66b9123b7185362ec8b625a773b3d39aa1a717583 \ + --hash=sha256:d0ee06b5b5291f609ddb37b9750985b27bc567791bc87c76a569b3feed8481ac \ + --hash=sha256:d480de377f5b687b6b1bc0c0407426da556e2a757633cc7e4d2e1a057aa688f3 \ + --hash=sha256:d56bc4011975f7460bea7b33e1ff425d2f1adf419935ff6707273c77f8a4ada6 \ + --hash=sha256:dd3c41254ee98604b08bd5b3af5bf0a89740d4ee0711de95b65166bf44091921 \ + --hash=sha256:e0d138c7ae532908cbb342162b2611dbd4d90c941cd25ab82084aaf71d2c0bd0 \ + --hash=sha256:e11769a1dbda4da7b00a76cfffa67aa47cfa66921d2724539eee4b9ede780b79 \ + --hash=sha256:e3f0a41487fd5fad7e760b9e8a90e251e27c2816fbc2cff36a22a0e6bcbbd9dd \ + --hash=sha256:e692aa2d1d604e6ca12d35e51fdc36f4cda6345e28e36374579f7ef3611b3012 \ + --hash=sha256:e70a57ecf89a0f64c24e37f38d3fe217a58169d2fe6ed6d70554964042474023 \ + --hash=sha256:e96baa6820280077a78244b2e06e416480ed859bbd8e5d641cf5742919d8beb4 \ + --hash=sha256:eb5656019db7c4deacf0c1a55a898c5bb8f989be904597fcb5232a2f4828fa05 \ + --hash=sha256:eca45e982fa074090057132e30585a7e8674e9e885d402eae85633e9f449ce6c \ + --hash=sha256:f0af2bd2bc204fa27f3d6711d0f360e6b8c684a035206257a81673ab924aa11e \ + --hash=sha256:f7cdf7f26c2286ffb02e46d7bac56c94655540b26347673bea15fa52a6af17e9 \ + --hash=sha256:fd1a720332ea335ceb544cf0a03f81df92abd4bb887679fd1e460976b0e6214b \ + --hash=sha256:ff8baf1f8d3f4b6b7257fcb75a501f2a5499d0dda57645baa09d4d0d34b19444 # via mypy markupsafe==3.0.3 \ --hash=sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f \ @@ -502,21 +502,21 @@ markupsafe==3.0.3 \ --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \ --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50 # via jinja2 -maturin==1.12.2 \ - --hash=sha256:04c9c4f9c9f904f007cbfcd4640c406e53f19d04c220f5940d1537edb914d325 \ - --hash=sha256:0ed31b6a392928ad23645a470edc4f3814b952a416e41f8e5daac42d7bfbabc6 \ - --hash=sha256:134e895578258a693ba1d55b166c2ba96e9f51067e106b8a74d422432653d45b \ - --hash=sha256:39665d622dcc950ab17b9569e8cab84a4d64eea6a18b540a8b49e00c0f7dda02 \ - --hash=sha256:4bdc486b9ab80d8b50143ecc9a1924b890866fe95be150dd9a59fa22a6b37238 \ - --hash=sha256:6af778e7ee048612e55a1255488db7678741bea2ba881e66a19712f59f2534cb \ - --hash=sha256:72aad9efe09a6392de9930f2bea80bfcc36fd98e18caa621f512571179c02d41 \ - --hash=sha256:9763d277e143409cf0ce309eb1a493fc4e1e75777364d67ccac39a161b51b5b0 \ - --hash=sha256:a882cc80c241b1e2c27bd1acd713b09e9ac9266a3159cc1e34e8c7b77f049bba \ - --hash=sha256:c06d218931985035d7ab4d0211ba96027e1bc7e4b01a87c8c4e30a57790403ec \ - --hash=sha256:ca3b20bcc3aff115c9eaf97340e78bff58829ea1efa16764940dd0d858dcf6af \ - --hash=sha256:d1617989b4a5dc543fea6d23c28b2f07fadb2c726ff00fe959538ee71a301384 \ - --hash=sha256:d6253079f53dbb692395a13abddc0f2d3d96af32f8c0b32e2912849713c55794 \ - --hash=sha256:f1c2e4ee43bf286b052091a3b2356a157978985837c7aed42354deb2947a4006 +maturin==1.12.6 \ + --hash=sha256:06fc8d089f98623ce924c669b70911dfed30f9a29956c362945f727f9abc546b \ + --hash=sha256:2cb41139295eed6411d3cdafc7430738094c2721f34b7eeb44f33cac516115dc \ + --hash=sha256:351f3af1488a7cbdcff3b6d8482c17164273ac981378a13a4a9937a49aec7d71 \ + --hash=sha256:3f32e0a3720b81423c9d35c14e728cb1f954678124749776dc72d533ea1115e8 \ + --hash=sha256:6892b4176992fcc143f9d1c1c874a816e9a041248eef46433db87b0f0aff4278 \ + --hash=sha256:6dbddfe4dc7ddee60bbac854870bd7cfec660acb54d015d24597d59a1c828f61 \ + --hash=sha256:75133e56274d43b9227fd49dca9a86e32f1fd56a7b55544910c4ce978c2bb5aa \ + --hash=sha256:8fdb0f63e77ee3df0f027a120e9af78dbc31edf0eb0f263d55783c250c33b728 \ + --hash=sha256:977290159d252db946054a0555263c59b3d0c7957135c69e690f4b1558ee9983 \ + --hash=sha256:bae91976cdc8148038e13c881e1e844e5c63e58e026e8b9945aa2d19b3b4ae89 \ + --hash=sha256:c0c742beeeef7fb93b6a81bd53e75507887e396fd1003c45117658d063812dad \ + --hash=sha256:d37be3a811a7f2ee28a0fa0964187efa50e90f21da0c6135c27787fa0b6a89db \ + --hash=sha256:e90dc12bc6a38e9495692a36c9e231c4d7e0c9bfde60719468ab7d8673db3c45 \ + --hash=sha256:fa84b7493a2e80759cacc2e668fa5b444d55b9994e90707c42904f55d6322c1e # via # cryptography # pydantic-core @@ -540,79 +540,79 @@ mypy-extensions==1.1.0 \ --hash=sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505 \ --hash=sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558 # via mypy -numpy==2.4.2 \ - --hash=sha256:00ab83c56211a1d7c07c25e3217ea6695e50a3e2f255053686b081dc0b091a82 \ - --hash=sha256:068cdb2d0d644cdb45670810894f6a0600797a69c05f1ac478e8d31670b8ee75 \ - --hash=sha256:0f01dcf33e73d80bd8dc0f20a71303abbafa26a19e23f6b68d1aa9990af90257 \ - --hash=sha256:0fece1d1f0a89c16b03442eae5c56dc0be0c7883b5d388e0c03f53019a4bfd71 \ - --hash=sha256:12e26134a0331d8dbd9351620f037ec470b7c75929cb8a1537f6bfe411152a1a \ - --hash=sha256:1ae241bbfc6ae276f94a170b14785e561cb5e7f626b6688cf076af4110887413 \ - --hash=sha256:1f92f53998a17265194018d1cc321b2e96e900ca52d54c7c77837b71b9465181 \ - --hash=sha256:209fae046e62d0ce6435fcfe3b1a10537e858249b3d9b05829e2a05218296a85 \ - --hash=sha256:20abd069b9cda45874498b245c8015b18ace6de8546bf50dfa8cea1696ed06ef \ - --hash=sha256:21982668592194c609de53ba4933a7471880ccbaadcc52352694a59ecc860b3a \ - --hash=sha256:25f2059807faea4b077a2b6837391b5d830864b3543627f381821c646f31a63c \ - --hash=sha256:2653de5c24910e49c2b106499803124dde62a5a1fe0eedeaecf4309a5f639390 \ - --hash=sha256:2b8f157c8a6f20eb657e240f8985cc135598b2b46985c5bccbde7616dc9c6b1e \ - --hash=sha256:2fb882da679409066b4603579619341c6d6898fc83a8995199d5249f986e8e8f \ - --hash=sha256:40397bda92382fcec844066efb11f13e1c9a3e2a8e8f318fb72ed8b6db9f60f1 \ - --hash=sha256:444be170853f1f9d528428eceb55f12918e4fda5d8805480f36a002f1415e09b \ - --hash=sha256:47c5a6ed21d9452b10227e5e8a0e1c22979811cad7dcc19d8e3e2fb8fa03f1a3 \ - --hash=sha256:4f069069931240b3fc703f1e23df63443dbd6390614c8c44a87d96cd0ec81eb1 \ - --hash=sha256:52b913ec40ff7ae845687b0b34d8d93b60cb66dcee06996dd5c99f2fc9328657 \ - --hash=sha256:5633c0da313330fd20c484c78cdd3f9b175b55e1a766c4a174230c6b70ad8262 \ - --hash=sha256:5daf6f3914a733336dab21a05cdec343144600e964d2fcdabaac0c0269874b2a \ - --hash=sha256:5eea80d908b2c1f91486eb95b3fb6fab187e569ec9752ab7d9333d2e66bf2d6b \ - --hash=sha256:602f65afdef699cda27ec0b9224ae5dc43e328f4c24c689deaf77133dbee74d0 \ - --hash=sha256:659a6107e31a83c4e33f763942275fd278b21d095094044eb35569e86a21ddae \ - --hash=sha256:66cb9422236317f9d44b67b4d18f44efe6e9c7f8794ac0462978513359461554 \ - --hash=sha256:6d82351358ffbcdcd7b686b90742a9b86632d6c1c051016484fa0b326a0a1548 \ - --hash=sha256:6e9f61981ace1360e42737e2bae58b27bf28a1b27e781721047d84bd754d32e7 \ - --hash=sha256:6ed0be1ee58eef41231a5c943d7d1375f093142702d5723ca2eb07db9b934b05 \ - --hash=sha256:7cdde6de52fb6664b00b056341265441192d1291c130e99183ec0d4b110ff8b1 \ - --hash=sha256:7df2de1e4fba69a51c06c28f5a3de36731eb9639feb8e1cf7e4a7b0daf4cf622 \ - --hash=sha256:7edc794af8b36ca37ef5fcb5e0d128c7e0595c7b96a2318d1badb6fcd8ee86b1 \ - --hash=sha256:7f54844851cdb630ceb623dcec4db3240d1ac13d4990532446761baede94996a \ - --hash=sha256:805cc8de9fd6e7a22da5aed858e0ab16be5a4db6c873dde1d7451c541553aa27 \ - --hash=sha256:8906e71fd8afcb76580404e2a950caef2685df3d2a57fe82a86ac8d33cc007ba \ - --hash=sha256:89f7268c009bc492f506abd6f5265defa7cb3f7487dc21d357c3d290add45082 \ - --hash=sha256:8c50dd1fc8826f5b26a5ee4d77ca55d88a895f4e4819c7ecc2a9f5905047a443 \ - --hash=sha256:8e4549f8a3c6d13d55041925e912bfd834285ef1dd64d6bc7d542583355e2e98 \ - --hash=sha256:8e9afaeb0beff068b4d9cd20d322ba0ee1cecfb0b08db145e4ab4dd44a6b5110 \ - --hash=sha256:98f16a80e917003a12c0580f97b5f875853ebc33e2eaa4bccfc8201ac6869308 \ - --hash=sha256:9e35d3e0144137d9fdae62912e869136164534d64a169f86438bc9561b6ad49f \ - --hash=sha256:9e4424677ce4b47fe73c8b5556d876571f7c6945d264201180db2dc34f676ab5 \ - --hash=sha256:adb6ed2ad29b9e15321d167d152ee909ec73395901b70936f029c3bc6d7f4460 \ - --hash=sha256:aea4f66ff44dfddf8c2cffd66ba6538c5ec67d389285292fe428cb2c738c8aef \ - --hash=sha256:b21041e8cb6a1eb5312dd1d2f80a94d91efffb7a06b70597d44f1bd2dfc315ab \ - --hash=sha256:b2f0073ed0868db1dcd86e052d37279eef185b9c8db5bf61f30f46adac63c909 \ - --hash=sha256:b3a24467af63c67829bfaa61eecf18d5432d4f11992688537be59ecd6ad32f5e \ - --hash=sha256:b9c618d56a29c9cb1c4da979e9899be7578d2e0b3c24d52079c166324c9e8695 \ - --hash=sha256:bba37bc29d4d85761deed3954a1bc62be7cf462b9510b51d367b769a8c8df325 \ - --hash=sha256:bd3a7a9f5847d2fb8c2c6d1c862fa109c31a9abeca1a3c2bd5a64572955b2979 \ - --hash=sha256:be71bf1edb48ebbbf7f6337b5bfd2f895d1902f6335a5830b20141fc126ffba0 \ - --hash=sha256:c02ef4401a506fb60b411467ad501e1429a3487abca4664871d9ae0b46c8ba32 \ - --hash=sha256:c3cd545784805de05aafe1dde61752ea49a359ccba9760c1e5d1c88a93bbf2b7 \ - --hash=sha256:c7ac672d699bf36275c035e16b65539931347d68b70667d28984c9fb34e07fa7 \ - --hash=sha256:cb7bbb88aa74908950d979eeaa24dbdf1a865e3c7e45ff0121d8f70387b55f73 \ - --hash=sha256:cd2bd2bbed13e213d6b55dc1d035a4f91748a7d3edc9480c13898b0353708920 \ - --hash=sha256:cda077c2e5b780200b6b3e09d0b42205a3d1c68f30c6dceb90401c13bff8fe74 \ - --hash=sha256:cf28c0c1d4c4bf00f509fa7eb02c58d7caf221b50b467bcb0d9bbf1584d5c821 \ - --hash=sha256:d0d9b7c93578baafcbc5f0b83eaf17b79d345c6f36917ba0c67f45226911d499 \ - --hash=sha256:d1240d50adff70c2a88217698ca844723068533f3f5c5fa6ee2e3220e3bdb000 \ - --hash=sha256:d30291931c915b2ab5717c2974bb95ee891a1cf22ebc16a8006bd59cd210d40a \ - --hash=sha256:d9f64d786b3b1dd742c946c42d15b07497ed14af1a1f3ce840cce27daa0ce913 \ - --hash=sha256:da6cad4e82cb893db4b69105c604d805e0c3ce11501a55b5e9f9083b47d2ffe8 \ - --hash=sha256:df1b10187212b198dd45fa943d8985a3c8cf854aed4923796e0e019e113a1bda \ - --hash=sha256:e04ae107ac591763a47398bb45b568fc38f02dbc4aa44c063f67a131f99346cb \ - --hash=sha256:e6dee3bb76aa4009d5a912180bf5b2de012532998d094acee25d9cb8dee3e44a \ - --hash=sha256:e7e88598032542bd49af7c4747541422884219056c268823ef6e5e89851c8825 \ - --hash=sha256:e98c97502435b53741540a5717a6749ac2ada901056c7db951d33e11c885cc7d \ - --hash=sha256:ec055f6dae239a6299cace477b479cca2fc125c5675482daf1dd886933a1076f \ - --hash=sha256:f74f0f7779cc7ae07d1810aab8ac6b1464c3eafb9e283a40da7309d5e6e48fbb \ - --hash=sha256:fbde1b0c6e81d56f5dccd95dd4a711d9b95df1ae4009a60887e56b27e8d903fa \ - --hash=sha256:fcf92bee92742edd401ba41135185866f7026c502617f422eb432cfeca4fe236 \ - --hash=sha256:fd49860271d52127d61197bb50b64f58454e9f578cb4b2c001a6de8b1f50b0b1 +numpy==2.4.4 \ + --hash=sha256:07077278157d02f65c43b1b26a3886bce886f95d20aabd11f87932750dfb14ed \ + --hash=sha256:08f2e31ed5e6f04b118e49821397f12767934cfdd12a1ce86a058f91e004ee50 \ + --hash=sha256:0aec54fd785890ecca25a6003fd9a5aed47ad607bbac5cd64f836ad8666f4959 \ + --hash=sha256:0d35aea54ad1d420c812bfa0385c71cd7cc5bcf7c65fed95fc2cd02fe8c79827 \ + --hash=sha256:0d4e437e295f18ec29bc79daf55e8a47a9113df44d66f702f02a293d93a2d6dd \ + --hash=sha256:0dfd3f9d3adbe2920b68b5cd3d51444e13a10792ec7154cd0a2f6e74d4ab3233 \ + --hash=sha256:1378871da56ca8943c2ba674530924bb8ca40cd228358a3b5f302ad60cf875fc \ + --hash=sha256:15716cfef24d3a9762e3acdf87e27f58dc823d1348f765bbea6bef8c639bfa1b \ + --hash=sha256:19710a9ca9992d7174e9c52f643d4272dcd1558c5f7af7f6f8190f633bd651a7 \ + --hash=sha256:23cbfd4c17357c81021f21540da84ee282b9c8fba38a03b7b9d09ba6b951421e \ + --hash=sha256:2483e4584a1cb3092da4470b38866634bafb223cbcd551ee047633fd2584599a \ + --hash=sha256:27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d \ + --hash=sha256:28a650663f7314afc3e6ec620f44f333c386aad9f6fc472030865dc0ebb26ee3 \ + --hash=sha256:2aa0613a5177c264ff5921051a5719d20095ea586ca88cc802c5c218d1c67d3e \ + --hash=sha256:2c194dd721e54ecad9ad387c1d35e63dce5c4450c6dc7dd5611283dda239aabb \ + --hash=sha256:2d19e6e2095506d1736b7d80595e0f252d76b89f5e715c35e06e937679ea7d7a \ + --hash=sha256:2d390634c5182175533585cc89f3608a4682ccb173cc9bb940b2881c8d6f8fa0 \ + --hash=sha256:30caa73029a225b2d40d9fae193e008e24b2026b7ee1a867b7ee8d96ca1a448e \ + --hash=sha256:42c16925aa5a02362f986765f9ebabf20de75cdefdca827d14315c568dcab113 \ + --hash=sha256:45dbed2ab436a9e826e302fcdcbe9133f9b0006e5af7168afb8963a6520da103 \ + --hash=sha256:4636de7fd195197b7535f231b5de9e4b36d2c440b6e566d2e4e4746e6af0ca93 \ + --hash=sha256:4a19d9dba1a76618dd86b164d608566f393f8ec6ac7c44f0cc879011c45e65af \ + --hash=sha256:4bbc7f303d125971f60ec0aaad5e12c62d0d2c925f0ab1273debd0e4ba37aba5 \ + --hash=sha256:4d6d57903571f86180eb98f8f0c839fa9ebbfb031356d87f1361be91e433f5b7 \ + --hash=sha256:4e874c976154687c1f71715b034739b45c7711bec81db01914770373d125e392 \ + --hash=sha256:51fc224f7ca4d92656d5a5eb315f12eb5fe2c97a66249aa7b5f562528a3be38c \ + --hash=sha256:58c8b5929fcb8287cbd6f0a3fae19c6e03a5c48402ae792962ac465224a629a4 \ + --hash=sha256:5a285b3b96f951841799528cd1f4f01cd70e7e0204b4abebac9463eecfcf2a40 \ + --hash=sha256:5c70f1cc1c4efbe316a572e2d8b9b9cc44e89b95f79ca3331553fbb63716e2bf \ + --hash=sha256:62d6b0f03b694173f9fcb1fb317f7222fd0b0b103e784c6549f5e53a27718c44 \ + --hash=sha256:6a246d5914aa1c820c9443ddcee9c02bec3e203b0c080349533fae17727dfd1b \ + --hash=sha256:6aa3236c78803afbcb255045fbef97a9e25a1f6c9888357d205ddc42f4d6eba5 \ + --hash=sha256:6bbe4eb67390b0a0265a2c25458f6b90a409d5d069f1041e6aff1e27e3d9a79e \ + --hash=sha256:715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74 \ + --hash=sha256:72944b19f2324114e9dc86a159787333b77874143efcf89a5167ef83cfee8af0 \ + --hash=sha256:81f4a14bee47aec54f883e0cad2d73986640c1590eb9bfaaba7ad17394481e6e \ + --hash=sha256:846300f379b5b12cc769334464656bc882e0735d27d9726568bc932fdc49d5ec \ + --hash=sha256:86b6f55f5a352b48d7fbfd2dbc3d5b780b2d79f4d3c121f33eb6efb22e9a2015 \ + --hash=sha256:874f200b2a981c647340f841730fc3a2b54c9d940566a3c4149099591e2c4c3d \ + --hash=sha256:8a87ec22c87be071b6bdbd27920b129b94f2fc964358ce38f3822635a3e2e03d \ + --hash=sha256:8b3b60bb7cba2c8c81837661c488637eee696f59a877788a396d33150c35d842 \ + --hash=sha256:8e3ed142f2728df44263aaf5fb1f5b0b99f4070c553a0d7f033be65338329150 \ + --hash=sha256:93e15038125dc1e5345d9b5b68aa7f996ec33b98118d18c6ca0d0b7d6198b7e8 \ + --hash=sha256:989824e9faf85f96ec9c7761cd8d29c531ad857bfa1daa930cba85baaecf1a9a \ + --hash=sha256:99d838547ace2c4aace6c4f76e879ddfe02bb58a80c1549928477862b7a6d6ed \ + --hash=sha256:9b2aec6af35c113b05695ebb5749a787acd63cafc83086a05771d1e1cd1e555f \ + --hash=sha256:9c585a1790d5436a5374bac930dad6ed244c046ed91b2b2a3634eb2971d21008 \ + --hash=sha256:a7164afb23be6e37ad90b2f10426149fd75aee07ca55653d2aa41e66c4ef697e \ + --hash=sha256:ac6b31e35612a26483e20750126d30d0941f949426974cace8e6b5c58a3657b0 \ + --hash=sha256:ad2e2ef14e0b04e544ea2fa0a36463f847f113d314aa02e5b402fdf910ef309e \ + --hash=sha256:b268594bccac7d7cf5844c7732e3f20c50921d94e36d7ec9b79e9857694b1b2f \ + --hash=sha256:b5f0362dc928a6ecd9db58868fca5e48485205e3855957bdedea308f8672ea4a \ + --hash=sha256:ba1f4fc670ed79f876f70082eff4f9583c15fb9a4b89d6188412de4d18ae2f40 \ + --hash=sha256:ba203255017337d39f89bdd58417f03c4426f12beed0440cfd933cb15f8669c7 \ + --hash=sha256:c901b15172510173f5cb310eae652908340f8dede90fff9e3bf6c0d8dfd92f83 \ + --hash=sha256:c9b39d38a9bd2ae1becd7eac1303d031c5c110ad31f2b319c6e7d98b135c934d \ + --hash=sha256:d2a8490669bfe99a233298348acc2d824d496dee0e66e31b66a6022c2ad74a5c \ + --hash=sha256:dddbbd259598d7240b18c9d87c56a9d2fb3b02fe266f49a7c101532e78c1d871 \ + --hash=sha256:df3775294accfdd75f32c74ae39fcba920c9a378a2fc18a12b6820aa8c1fb502 \ + --hash=sha256:e44319a2953c738205bf3354537979eaa3998ed673395b964c1176083dd46252 \ + --hash=sha256:e4a010c27ff6f210ff4c6ef34394cd61470d01014439b192ec22552ee867f2a8 \ + --hash=sha256:e823b8b6edc81e747526f70f71a9c0a07ac4e7ad13020aa736bb7c9d67196115 \ + --hash=sha256:e892aff75639bbef0d2a2cfd55535510df26ff92f63c92cd84ef8d4ba5a5557f \ + --hash=sha256:eea7ac5d2dce4189771cedb559c738a71512768210dc4e4753b107a2048b3d0e \ + --hash=sha256:ef4059d6e5152fa1a39f888e344c73fdc926e1b2dd58c771d67b0acfbf2aa67d \ + --hash=sha256:f169b9a863d34f5d11b8698ead99febeaa17a13ca044961aa8e2662a6c7766a0 \ + --hash=sha256:f2cf083b324a467e1ab358c105f6cad5ea950f50524668a80c486ff1db24e119 \ + --hash=sha256:f8474c4241bc18b750be2abea9d7a9ec84f46ef861dbacf86a4f6e043401f79e \ + --hash=sha256:f983334aea213c99992053ede6168500e5f086ce74fbc4acc3f2b00f5762e9db \ + --hash=sha256:f9e75681b59ddaa5e659898085ae0eaea229d054f2ac0c7e563a62205a700121 \ + --hash=sha256:fbc356aae7adf9e6336d336b9c8111d390a05df88f1805573ebb0807bd06fd1d \ + --hash=sha256:fcfe2045fd2e8f3cb0ce9d4ba6dba6333b8fa05bb8a4939c908cd43322d14c7e # via # pandas # pyarrow @@ -626,6 +626,7 @@ packaging==26.0 \ # scikit-build-core # setuptools-git-versioning # setuptools-scm + # vcs-versioning # wheel pathspec==1.0.4 \ --hash=sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645 \ @@ -634,38 +635,37 @@ pathspec==1.0.4 \ # hatchling # mypy # scikit-build-core -pdm-backend==2.4.7 \ - --hash=sha256:1599e3afa6f229b30cb4d3bd9caeca42229c42eb5730abd13e0b5256ec93c9f7 \ - --hash=sha256:a509d083850378ce919d41e7a2faddfc57a1764d376913c66731125d6b14110f +pdm-backend==2.4.8 \ + --hash=sha256:502a395859587b4f47ba36aded330aeda410da8d33751a56cb97c8c679276f8f \ + --hash=sha256:d8ef85d2c4306ee67195412d701fae9983e84ec6574598e26798ae26b7b3c7e0 # via # annotated-doc # fastapi # typer -pkgconfig==1.5.5 \ - --hash=sha256:d20023bbeb42ee6d428a0fac6e0904631f545985a10cdd71a20aa58bc47a4209 \ - --hash=sha256:deb4163ef11f75b520d822d9505c1f462761b4309b1bb713d08689759ea8b899 +pkgconfig==1.6.0 \ + --hash=sha256:4a5a6631ce937fafac457104a40d558785a658bbdca5c49b6295bc3fd651907f \ + --hash=sha256:98e71754855e9563838d952a160eb577edabb57782e49853edb5381927e6bea1 # via aiohttp pluggy==1.6.0 \ --hash=sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3 \ --hash=sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746 # via hatchling -poetry-core==2.3.1 \ - --hash=sha256:96f791d5d7d4e040f3983d76779425cf9532690e2756a24fd5ca0f86af19ef82 \ - --hash=sha256:db1cf63b782570deb38bfba61e2304a553eef0740dc17959a50cc0f5115ee634 +poetry-core==2.3.2 \ + --hash=sha256:20cb71be27b774628da9f384effd9183dfceb53bcef84063248a8672aa47031f \ + --hash=sha256:23df641b64f87fbb4ce1873c1915a4d4bb1b7d808c596e4307edc073e68d7234 # via # aiohappyeyeballs # dunamai # pkgconfig # rich - # rsa # tomlkit -pybind11-global==3.0.1 \ - --hash=sha256:0e8d5a68d084c50bf145ce5efdbdd00704dbe6315035d0b7a255708ddeb9faca \ - --hash=sha256:eb6ef4e8f5a60f4c0b6a9396cb7806f78d42f8d081e42a93c0bb62288f6cf403 +pybind11-global==3.0.3 \ + --hash=sha256:141adb150fdb84f6eba3e27241da886f4582574a3d1c30568bf33c1ed3ec8b82 \ + --hash=sha256:7a75ee81e903ea15bdf05db1342c37400751a72316b6620c800b66d70be45632 # via pybind11 -pybind11==3.0.1 \ - --hash=sha256:9c0f40056a016da59bab516efb523089139fcc6f2ba7e4930854c61efb932051 \ - --hash=sha256:aa8f0aa6e0a94d3b64adfc38f560f33f15e589be2175e103c0a33c6bce55ee89 +pybind11==3.0.3 \ + --hash=sha256:00471cdb816882c484708bc5dde80815c8c11cea540ab2cc6410f5ddea434755 \ + --hash=sha256:fb5f8e4a64946b4dcc0451c83a8c384f803bc0a62dd1ba02f199e97dbc9aad4c # via duckdb pycparser==3.0 \ --hash=sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29 \ @@ -675,9 +675,9 @@ pyproject-metadata==0.11.0 \ --hash=sha256:85bbecca8694e2c00f63b492c96921d6c228454057c88e7c352b2077fcaa4096 \ --hash=sha256:c72fa49418bb7c5a10f25e050c418009898d1c051721d19f98a6fb6da59a66cf # via meson-python -scikit-build-core==0.11.6 \ - --hash=sha256:5982ccd839735be99cfd3b92a8847c6c196692f476c215da84b79d2ad12f9f1b \ - --hash=sha256:ce6d8fe64e6b4c759ea0fb95d2f8a68f60d2df31c2989838633b8ec930736360 +scikit-build-core==0.12.2 \ + --hash=sha256:562e0bbc9de1a354c87825ccf732080268d6582a0200f648e8c4a2dcb1e3736d \ + --hash=sha256:6ea4730da400f9a998ec3287bd3ebc1d751fe45ad0a93451bead8618adbc02b1 # via # duckdb # patchelf @@ -691,17 +691,13 @@ setuptools-git-versioning==3.0.1 \ --hash=sha256:737c4d17e848edd46e28764a19dc424d8537fcb2257022e5f4f5c0c8e9b64c80 \ --hash=sha256:c8a599bacf163b5d215552b5701faf5480ffc4d65426a5711a010b802e1590eb # via toolz -setuptools-rust==1.12.0 \ - --hash=sha256:7e7db90547f224a835b45f5ad90c983340828a345554a9a660bdb2de8605dcdd \ - --hash=sha256:d94a93f0c97751c17014565f07bdc324bee45d396cd1bba83d8e7af92b945f0c +setuptools-rust==1.12.1 \ + --hash=sha256:85ae70989d96c9cfeb5ef79cf3bac2d5200bc5564f720a06edceedbdf6664640 \ + --hash=sha256:b7ebd6a182e7aefa97a072e880530c9b0ec8fcca8617e0bb8ff299c1a064f693 # via maturin -setuptools-scm==7.1.0 \ - --hash=sha256:6c508345a771aad7d56ebff0e70628bf2b0ec7573762be9960214730de278f27 \ - --hash=sha256:73988b6d848709e2af142aa48c986ea29592bbcfca5375678064708205253d8e - # via python-dateutil -setuptools-scm==9.2.2 \ - --hash=sha256:1c674ab4665686a0887d7e24c03ab25f24201c213e82ea689d2f3e169ef7ef57 \ - --hash=sha256:30e8f84d2ab1ba7cb0e653429b179395d0c33775d54807fc5f1dd6671801aef7 +setuptools-scm==10.0.5 \ + --hash=sha256:bbba8fe754516cdefd017f4456721775e6ef9662bd7887fb52ae26813d4838c3 \ + --hash=sha256:f611037d8aae618221503b8fa89319f073438252ae3420e01c9ceec249131a0a # via # anyio # dask @@ -719,59 +715,68 @@ setuptools-scm==9.2.2 \ # tqdm # typeguard # ujson +setuptools-scm==7.1.0 \ + --hash=sha256:6c508345a771aad7d56ebff0e70628bf2b0ec7573762be9960214730de278f27 \ + --hash=sha256:73988b6d848709e2af142aa48c986ea29592bbcfca5375678064708205253d8e + # via python-dateutil +setuptools-scm==9.2.2 \ + --hash=sha256:1c674ab4665686a0887d7e24c03ab25f24201c213e82ea689d2f3e169ef7ef57 \ + --hash=sha256:30e8f84d2ab1ba7cb0e653429b179395d0c33775d54807fc5f1dd6671801aef7 + # via + # hatch-vcs # urllib3 -smmap==5.0.2 \ - --hash=sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5 \ - --hash=sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e +smmap==5.0.3 \ + --hash=sha256:4d9debb8b99007ae47165abc08670bd74cb74b5227dda7f643eccc4e9eb5642c \ + --hash=sha256:c106e05d5a61449cf6ba9a1e650227ecfb141590d2a98412103ff35d89fc7b2f # via gitdb -tomli==2.4.0 \ - --hash=sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729 \ - --hash=sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b \ - --hash=sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d \ - --hash=sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df \ - --hash=sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576 \ - --hash=sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d \ - --hash=sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1 \ - --hash=sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a \ - --hash=sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e \ - --hash=sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc \ - --hash=sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702 \ - --hash=sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6 \ - --hash=sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd \ - --hash=sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4 \ - --hash=sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776 \ - --hash=sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a \ - --hash=sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66 \ - --hash=sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87 \ - --hash=sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2 \ - --hash=sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f \ - --hash=sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475 \ - --hash=sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f \ - --hash=sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95 \ - --hash=sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9 \ - --hash=sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3 \ - --hash=sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9 \ - --hash=sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76 \ - --hash=sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da \ - --hash=sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8 \ - --hash=sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51 \ - --hash=sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86 \ - --hash=sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8 \ - --hash=sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0 \ - --hash=sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b \ - --hash=sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1 \ - --hash=sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e \ - --hash=sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d \ - --hash=sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c \ - --hash=sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867 \ - --hash=sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a \ - --hash=sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c \ - --hash=sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0 \ - --hash=sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4 \ - --hash=sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614 \ - --hash=sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132 \ - --hash=sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa \ - --hash=sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087 +tomli==2.4.1 \ + --hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \ + --hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \ + --hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \ + --hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \ + --hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \ + --hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \ + --hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \ + --hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \ + --hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \ + --hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \ + --hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \ + --hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \ + --hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \ + --hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \ + --hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \ + --hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \ + --hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \ + --hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \ + --hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \ + --hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \ + --hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \ + --hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \ + --hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \ + --hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \ + --hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \ + --hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \ + --hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \ + --hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \ + --hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \ + --hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \ + --hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \ + --hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \ + --hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \ + --hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \ + --hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \ + --hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \ + --hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \ + --hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \ + --hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \ + --hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \ + --hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \ + --hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \ + --hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \ + --hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \ + --hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \ + --hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \ + --hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049 # via fastapi-mcp tomlkit==0.14.0 \ --hash=sha256:592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680 \ @@ -785,9 +790,9 @@ types-psutil==7.0.0.20250218 \ --hash=sha256:1447a30c282aafefcf8941ece854e1100eee7b0296a9d9be9977292f0269b121 \ --hash=sha256:1e642cdafe837b240295b23b1cbd4691d80b08a07d29932143cbbae30eb0db9c # via mypy -types-setuptools==82.0.0.20260210 \ - --hash=sha256:5124a7daf67f195c6054e0f00f1d97c69caad12fdcf9113eba33eff0bce8cd2b \ - --hash=sha256:d9719fbbeb185254480ade1f25327c4654f8c00efda3fec36823379cebcdee58 +types-setuptools==82.0.0.20260402 \ + --hash=sha256:4b9a9f6c3c4c65107a3956ad6a6acbccec38e398ff6d5f78d5df7f103dadb8d6 \ + --hash=sha256:63d2b10ba7958396ad79bbc24d2f6311484e452daad4637ffd40407983a27069 # via mypy typing-extensions==4.15.0 \ --hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \ @@ -795,10 +800,14 @@ typing-extensions==4.15.0 \ # via # mypy # setuptools-scm -uv-dynamic-versioning==0.13.0 \ - --hash=sha256:3220cbf10987d862d78e9931957782a274fa438d33efb1fa26b8155353749e06 \ - --hash=sha256:86d37b89fa2b6836a515301f74ea2d56a1bc59a46a74d66a24c869d1fc8f7585 +uv-dynamic-versioning==0.14.0 \ + --hash=sha256:574fbc07e87ace45c01d55967ad3b864871257b98ff5b8ac87c261227ac8db5b \ + --hash=sha256:e087c346a786e98d41292ac2315180fb700cedfb30565fc973d64ce11a112387 # via mcp +vcs-versioning==1.1.1 \ + --hash=sha256:b541e2ba79fc6aaa3850f8a7f88af43d97c1c80649c01142ee4146eddbc599e4 \ + --hash=sha256:fabd75a3cab7dd8ac02fe24a3a9ba936bf258667b5a62ed468c9a1da0f5775bc + # via setuptools-scm versioneer==0.29 \ --hash=sha256:0f1a137bb5d6811e96a79bb0486798aeae9b9c6efc24b389659cebb0ee396cb9 \ --hash=sha256:5ab283b9857211d61b53318b7c792cf68e798e765ee17c27ade9f6c924235731 @@ -823,7 +832,6 @@ wheel==0.46.3 \ # setuptools-git-versioning # shellingham # snowflake-connector-python - # tabulate # tzdata # uvloop @@ -880,6 +888,7 @@ setuptools==80.10.2 \ # pymysql # python-dotenv # pyyaml + # requests # setuptools-git-versioning # setuptools-rust # setuptools-scm @@ -895,9 +904,10 @@ setuptools==80.10.2 \ # trove-classifiers # typeguard # types-pymysql - # types-setuptools # tzdata + # ujson # uvloop + # vcs-versioning # versioneer # websockets # wrapt @@ -906,10 +916,9 @@ setuptools==80.9.0 \ --hash=sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922 \ --hash=sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c # via httptools -setuptools==82.0.0 \ - --hash=sha256:22e0a2d69474c6ae4feb01951cb69d515ed23728cf96d05513d36e42b62b37cb \ - --hash=sha256:70b18734b607bd1da571d097d236cfcfacaf01de45717d59e6e04b96877532e0 +setuptools==82.0.1 \ + --hash=sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9 \ + --hash=sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb # via # python-dateutil - # setuptools-scm - # ujson + # types-setuptools diff --git a/sdk/python/requirements/py3.12-minimal-sdist-requirements.txt b/sdk/python/requirements/py3.12-minimal-sdist-requirements.txt index 33f812556d2..e24f4ca749b 100644 --- a/sdk/python/requirements/py3.12-minimal-sdist-requirements.txt +++ b/sdk/python/requirements/py3.12-minimal-sdist-requirements.txt @@ -8,127 +8,127 @@ aiohappyeyeballs==2.6.1 \ --hash=sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558 \ --hash=sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8 # via aiohttp -aiohttp==3.13.3 \ - --hash=sha256:01ad2529d4b5035578f5081606a465f3b814c542882804e2e8cda61adf5c71bf \ - --hash=sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c \ - --hash=sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c \ - --hash=sha256:084911a532763e9d3dd95adf78a78f4096cd5f58cdc18e6fdbc1b58417a45423 \ - --hash=sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f \ - --hash=sha256:0db318f7a6f065d84cb1e02662c526294450b314a02bd9e2a8e67f0d8564ce40 \ - --hash=sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2 \ - --hash=sha256:1449ceddcdbcf2e0446957863af03ebaaa03f94c090f945411b61269e2cb5daf \ - --hash=sha256:147e422fd1223005c22b4fe080f5d93ced44460f5f9c105406b753612b587821 \ - --hash=sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64 \ - --hash=sha256:215a685b6fbbfcf71dfe96e3eba7a6f58f10da1dfdf4889c7dd856abe430dca7 \ - --hash=sha256:2712039939ec963c237286113c68dbad80a82a4281543f3abf766d9d73228998 \ - --hash=sha256:27234ef6d85c914f9efeb77ff616dbf4ad2380be0cda40b4db086ffc7ddd1b7d \ - --hash=sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea \ - --hash=sha256:2b8d8ddba8f95ba17582226f80e2de99c7a7948e66490ef8d947e272a93e9463 \ - --hash=sha256:2ba0eea45eb5cc3172dbfc497c066f19c41bac70963ea1a67d51fc92e4cf9a80 \ - --hash=sha256:2be0e9ccf23e8a94f6f0650ce06042cefc6ac703d0d7ab6c7a917289f2539ad4 \ - --hash=sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767 \ - --hash=sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43 \ - --hash=sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592 \ - --hash=sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a \ - --hash=sha256:31a83ea4aead760dfcb6962efb1d861db48c34379f2ff72db9ddddd4cda9ea2e \ - --hash=sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687 \ - --hash=sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8 \ - --hash=sha256:37239e9f9a7ea9ac5bf6b92b0260b01f8a22281996da609206a84df860bc1261 \ - --hash=sha256:37da61e244d1749798c151421602884db5270faf479cf0ef03af0ff68954c9dd \ - --hash=sha256:3b61b7169ababd7802f9568ed96142616a9118dd2be0d1866e920e77ec8fa92a \ - --hash=sha256:3d9908a48eb7416dc1f4524e69f1d32e5d90e3981e4e37eb0aa1cd18f9cfa2a4 \ - --hash=sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587 \ - --hash=sha256:4021b51936308aeea0367b8f006dc999ca02bc118a0cc78c303f50a2ff6afb91 \ - --hash=sha256:40c5e40ecc29ba010656c18052b877a1c28f84344825efa106705e835c28530f \ - --hash=sha256:425c126c0dc43861e22cb1c14ba4c8e45d09516d0a3ae0a3f7494b79f5f233a3 \ - --hash=sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344 \ - --hash=sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6 \ - --hash=sha256:49a03727c1bba9a97d3e93c9f93ca03a57300f484b6e935463099841261195d3 \ - --hash=sha256:4ae5b5a0e1926e504c81c5b84353e7a5516d8778fbbff00429fe7b05bb25cbce \ - --hash=sha256:4e239d501f73d6db1522599e14b9b321a7e3b1de66ce33d53a765d975e9f4808 \ - --hash=sha256:56339a36b9f1fc708260c76c87e593e2afb30d26de9ae1eb445b5e051b98a7a1 \ - --hash=sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29 \ - --hash=sha256:5b179331a481cb5529fca8b432d8d3c7001cb217513c94cd72d668d1248688a3 \ - --hash=sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b \ - --hash=sha256:5d2d94f1f5fcbe40838ac51a6ab5704a6f9ea42e72ceda48de5e6b898521da51 \ - --hash=sha256:5dff64413671b0d3e7d5918ea490bdccb97a4ad29b3f311ed423200b2203e01c \ - --hash=sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926 \ - --hash=sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64 \ - --hash=sha256:642f752c3eb117b105acbd87e2c143de710987e09860d674e068c4c2c441034f \ - --hash=sha256:65d2ccb7eabee90ce0503c17716fc77226be026dcc3e65cce859a30db715025b \ - --hash=sha256:693781c45a4033d31d4187d2436f5ac701e7bbfe5df40d917736108c1cc7436e \ - --hash=sha256:694976222c711d1d00ba131904beb60534f93966562f64440d0c9d41b8cdb440 \ - --hash=sha256:697753042d57f4bf7122cab985bf15d0cef23c770864580f5af4f52023a56bd6 \ - --hash=sha256:69c56fbc1993fa17043e24a546959c0178fe2b5782405ad4559e6c13975c15e3 \ - --hash=sha256:6de499a1a44e7de70735d0b39f67c8f25eb3d91eb3103be99ca0fa882cdd987d \ - --hash=sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415 \ - --hash=sha256:75ca857eba4e20ce9f546cd59c7007b33906a4cd48f2ff6ccf1ccfc3b646f279 \ - --hash=sha256:7a4a94eb787e606d0a09404b9c38c113d3b099d508021faa615d70a0131907ce \ - --hash=sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603 \ - --hash=sha256:7bfdc049127717581866fa4708791220970ce291c23e28ccf3922c700740fdc0 \ - --hash=sha256:7e63f210bc1b57ef699035f2b4b6d9ce096b5914414a49b0997c839b2bd2223c \ - --hash=sha256:7f9120f7093c2a32d9647abcaf21e6ad275b4fbec5b55969f978b1a97c7c86bf \ - --hash=sha256:8057c98e0c8472d8846b9c79f56766bcc57e3e8ac7bfd510482332366c56c591 \ - --hash=sha256:80dd4c21b0f6237676449c6baaa1039abae86b91636b6c91a7f8e61c87f89540 \ - --hash=sha256:81e97251d9298386c2b7dbeb490d3d1badbdc69107fb8c9299dd04eb39bddc0e \ - --hash=sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26 \ - --hash=sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a \ - --hash=sha256:859bd3f2156e81dd01432f5849fc73e2243d4a487c4fd26609b1299534ee1845 \ - --hash=sha256:87797e645d9d8e222e04160ee32aa06bc5c163e8499f24db719e7852ec23093a \ - --hash=sha256:87b9aab6d6ed88235aa2970294f496ff1a1f9adcd724d800e9b952395a80ffd9 \ - --hash=sha256:8a60e60746623925eab7d25823329941aee7242d559baa119ca2b253c88a7bd6 \ - --hash=sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba \ - --hash=sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df \ - --hash=sha256:947c26539750deeaee933b000fb6517cc770bbd064bad6033f1cff4803881e43 \ - --hash=sha256:96d604498a7c782cb15a51c406acaea70d8c027ee6b90c569baa6e7b93073679 \ - --hash=sha256:988a8c5e317544fdf0d39871559e67b6341065b87fceac641108c2096d5506b7 \ - --hash=sha256:9a9dc347e5a3dc7dfdbc1f82da0ef29e388ddb2ed281bfce9dd8248a313e62b7 \ - --hash=sha256:9ae8dd55c8e6c4257eae3a20fd2c8f41edaea5992ed67156642493b8daf3cecc \ - --hash=sha256:9af5e68ee47d6534d36791bbe9b646d2a7c7deb6fc24d7943628edfbb3581f29 \ - --hash=sha256:9b174f267b5cfb9a7dba9ee6859cecd234e9a681841eb85068059bc867fb8f02 \ - --hash=sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984 \ - --hash=sha256:9d4c940f02f49483b18b079d1c27ab948721852b281f8b015c058100e9421dd1 \ - --hash=sha256:9ebf57d09e131f5323464bd347135a88622d1c0976e88ce15b670e7ad57e4bd6 \ - --hash=sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632 \ - --hash=sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56 \ - --hash=sha256:a2212ad43c0833a873d0fb3c63fa1bacedd4cf6af2fee62bf4b739ceec3ab239 \ - --hash=sha256:a45530014d7a1e09f4a55f4f43097ba0fd155089372e105e4bff4ca76cb1b168 \ - --hash=sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88 \ - --hash=sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc \ - --hash=sha256:af71fff7bac6bb7508956696dce8f6eec2bbb045eceb40343944b1ae62b5ef11 \ - --hash=sha256:b04be762396457bef43f3597c991e192ee7da460a4953d7e647ee4b1c28e7046 \ - --hash=sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0 \ - --hash=sha256:b1a6102b4d3ebc07dad44fbf07b45bb600300f15b552ddf1851b5390202ea2e3 \ - --hash=sha256:b46020d11d23fe16551466c77823df9cc2f2c1e63cc965daf67fa5eec6ca1877 \ - --hash=sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1 \ - --hash=sha256:b903a4dfee7d347e2d87697d0713be59e0b87925be030c9178c5faa58ea58d5c \ - --hash=sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25 \ - --hash=sha256:b99281b0704c103d4e11e72a76f1b543d4946fea7dd10767e7e1b5f00d4e5704 \ - --hash=sha256:bae5c2ed2eae26cc382020edad80d01f36cb8e746da40b292e68fec40421dc6a \ - --hash=sha256:bb4f7475e359992b580559e008c598091c45b5088f28614e855e42d39c2f1033 \ - --hash=sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1 \ - --hash=sha256:bfc1cc2fe31a6026a8a88e4ecfb98d7f6b1fec150cfd708adbfd1d2f42257c29 \ - --hash=sha256:c014c7ea7fb775dd015b2d3137378b7be0249a448a1612268b5a90c2d81de04d \ - --hash=sha256:c048058117fd649334d81b4b526e94bde3ccaddb20463a815ced6ecbb7d11160 \ - --hash=sha256:c0e2d366af265797506f0283487223146af57815b388623f0357ef7eac9b209d \ - --hash=sha256:c19b90316ad3b24c69cd78d5c9b4f3aa4497643685901185b65166293d36a00f \ - --hash=sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f \ - --hash=sha256:c6b8568a3bb5819a0ad087f16d40e5a3fb6099f39ea1d5625a3edc1e923fc538 \ - --hash=sha256:d32764c6c9aafb7fb55366a224756387cd50bfa720f32b88e0e6fa45b27dcf29 \ - --hash=sha256:d5a372fd5afd301b3a89582817fdcdb6c34124787c70dbcc616f259013e7eef7 \ - --hash=sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72 \ - --hash=sha256:dca68018bf48c251ba17c72ed479f4dafe9dbd5a73707ad8d28a38d11f3d42af \ - --hash=sha256:de2c184bb1fe2cbd2cefba613e9db29a5ab559323f994b6737e370d3da0ac455 \ - --hash=sha256:e3531d63d3bdfa7e3ac5e9b27b2dd7ec9df3206a98e0b3445fa906f233264c57 \ - --hash=sha256:e50a2e1404f063427c9d027378472316201a2290959a295169bcf25992d04558 \ - --hash=sha256:e636b3c5f61da31a92bf0d91da83e58fdfa96f178ba682f11d24f31944cdd28c \ - --hash=sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808 \ - --hash=sha256:f33ed1a2bf1997a36661874b017f5c4b760f41266341af36febaf271d179f6d7 \ - --hash=sha256:f76c1e3fe7d7c8afad7ed193f89a292e1999608170dcc9751a7462a87dfd5bc0 \ - --hash=sha256:f9444f105664c4ce47a2a7171a2418bce5b7bae45fb610f4e2c36045d85911d3 \ - --hash=sha256:fc290605db2a917f6e81b0e1e0796469871f5af381ce15c604a3c5c7e51cb730 \ - --hash=sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa \ - --hash=sha256:fee0c6bc7db1de362252affec009707a17478a00ec69f797d23ca256e36d5940 +aiohttp==3.13.5 \ + --hash=sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5 \ + --hash=sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b \ + --hash=sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9 \ + --hash=sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b \ + --hash=sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8 \ + --hash=sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a \ + --hash=sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2 \ + --hash=sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1 \ + --hash=sha256:147b4f501d0292077f29d5268c16bb7c864a1f054d7001c4c1812c0421ea1ed0 \ + --hash=sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037 \ + --hash=sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416 \ + --hash=sha256:178c7b5e62b454c2bc790786e6058c3cc968613b4419251b478c153a4aec32b1 \ + --hash=sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9 \ + --hash=sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a \ + --hash=sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36 \ + --hash=sha256:206b7b3ef96e4ce211754f0cd003feb28b7d81f0ad26b8d077a5d5161436067f \ + --hash=sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b \ + --hash=sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174 \ + --hash=sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b \ + --hash=sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8 \ + --hash=sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e \ + --hash=sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6 \ + --hash=sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c \ + --hash=sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe \ + --hash=sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9 \ + --hash=sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc \ + --hash=sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800 \ + --hash=sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286 \ + --hash=sha256:347542f0ea3f95b2a955ee6656461fa1c776e401ac50ebce055a6c38454a0adf \ + --hash=sha256:39380e12bd1f2fdab4285b6e055ad48efbaed5c836433b142ed4f5b9be71036a \ + --hash=sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc \ + --hash=sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9 \ + --hash=sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665 \ + --hash=sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832 \ + --hash=sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297 \ + --hash=sha256:4e704c52438f66fdd89588346183d898bb42167cf88f8b7ff1c0f9fc957c348f \ + --hash=sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73 \ + --hash=sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b \ + --hash=sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9 \ + --hash=sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090 \ + --hash=sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49 \ + --hash=sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d \ + --hash=sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46 \ + --hash=sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83 \ + --hash=sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796 \ + --hash=sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be \ + --hash=sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d \ + --hash=sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf \ + --hash=sha256:6f497a6876aa4b1a102b04996ce4c1170c7040d83faa9387dd921c16e30d5c83 \ + --hash=sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25 \ + --hash=sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06 \ + --hash=sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3 \ + --hash=sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6 \ + --hash=sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb \ + --hash=sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88 \ + --hash=sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9 \ + --hash=sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be \ + --hash=sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14 \ + --hash=sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a \ + --hash=sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c \ + --hash=sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3 \ + --hash=sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f \ + --hash=sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d \ + --hash=sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670 \ + --hash=sha256:912d4b6af530ddb1338a66229dac3a25ff11d4448be3ec3d6340583995f56031 \ + --hash=sha256:9277145d36a01653863899c665243871434694bcc3431922c3b35c978061bdb8 \ + --hash=sha256:95d14ca7abefde230f7639ec136ade282655431fd5db03c343b19dda72dd1643 \ + --hash=sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d \ + --hash=sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8 \ + --hash=sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8 \ + --hash=sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1 \ + --hash=sha256:9efcc0f11d850cefcafdd9275b9576ad3bfb539bed96807663b32ad99c4d4b88 \ + --hash=sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb \ + --hash=sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61 \ + --hash=sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4 \ + --hash=sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7 \ + --hash=sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9 \ + --hash=sha256:a8a4d3427e8de1312ddf309cc482186466c79895b3a139fed3259fc01dfa9a5b \ + --hash=sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500 \ + --hash=sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6 \ + --hash=sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2 \ + --hash=sha256:af545c2cffdb0967a96b6249e6f5f7b0d92cdfd267f9d5238d5b9ca63e8edb10 \ + --hash=sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1 \ + --hash=sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3 \ + --hash=sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e \ + --hash=sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a \ + --hash=sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5 \ + --hash=sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95 \ + --hash=sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074 \ + --hash=sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5 \ + --hash=sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b \ + --hash=sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772 \ + --hash=sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a \ + --hash=sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274 \ + --hash=sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94 \ + --hash=sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13 \ + --hash=sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac \ + --hash=sha256:cb979826071c0986a5f08333a36104153478ce6018c58cba7f9caddaf63d5d67 \ + --hash=sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76 \ + --hash=sha256:d147004fede1b12f6013a6dbb2a26a986a671a03c6ea740ddc76500e5f1c399f \ + --hash=sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8 \ + --hash=sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7 \ + --hash=sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8 \ + --hash=sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3 \ + --hash=sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be \ + --hash=sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b \ + --hash=sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c \ + --hash=sha256:e999f0c88a458c836d5fb521814e92ed2172c649200336a6df514987c1488258 \ + --hash=sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c \ + --hash=sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6 \ + --hash=sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56 \ + --hash=sha256:ee5e86776273de1795947d17bddd6bb19e0365fd2af4289c0d2c5454b6b1d36b \ + --hash=sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d \ + --hash=sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a \ + --hash=sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162 \ + --hash=sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1 \ + --hash=sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6 \ + --hash=sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5 \ + --hash=sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540 \ + --hash=sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254 # via aiobotocore aioitertools==0.13.0 \ --hash=sha256:0be0292b856f08dfac90e31f4739432f4cb6d7520ab9eb73e143f4f2fa5259be \ @@ -152,9 +152,9 @@ annotated-types==0.7.0 \ --hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \ --hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89 # via pydantic -anyio==4.12.1 \ - --hash=sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703 \ - --hash=sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c +anyio==4.13.0 \ + --hash=sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708 \ + --hash=sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc # via # httpx # mcp @@ -169,9 +169,9 @@ atpublic==7.0.0 \ --hash=sha256:466ef10d0c8bbd14fd02a5fbd5a8b6af6a846373d91106d3a07c16d72d96b63e \ --hash=sha256:6702bd9e7245eb4e8220a3e222afcef7f87412154732271ee7deee4433b72b4b # via ibis-framework -attrs==25.4.0 \ - --hash=sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11 \ - --hash=sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373 +attrs==26.1.0 \ + --hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \ + --hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32 # via # aiohttp # jsonschema @@ -180,9 +180,9 @@ babel==2.18.0 \ --hash=sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d \ --hash=sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35 # via sphinx -bigtree==1.3.1 \ - --hash=sha256:a22a0ecd9b0abb283f4a1515370dbf1ec93adee70746767272e2c49d7af9f407 \ - --hash=sha256:c8b766b00188c532d3499bfd9e9666b357428db507fc701f088031a0d5c614d5 +bigtree==1.4.0 \ + --hash=sha256:d0d99550ae64ce4529f132602ab875c2ab472c96c942f5704f8c72a17450d3ea \ + --hash=sha256:e5ae2e948168da671d99601c9ed87ab3b48d9d4ea8a98f111e5748e98064c31c # via feast (pyproject.toml) boto3==1.38.27 \ --hash=sha256:94bd7fdd92d5701b362d4df100d21e28f8307a67ff56b6a8b0398119cf22f859 \ @@ -202,9 +202,9 @@ calver==2025.3.31 \ --hash=sha256:07511edf5e7fa75ae97445c8c5921240e0fe62937289a3ebe6963eddd3c691b6 \ --hash=sha256:255d1a70bba8f97dc1eee3af4240ed35980508da69257feef94c79e5c6545fc7 # via feast (pyproject.toml) -certifi==2026.1.4 \ - --hash=sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c \ - --hash=sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120 +certifi==2026.2.25 \ + --hash=sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa \ + --hash=sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7 # via # httpcore # httpx @@ -299,120 +299,136 @@ cffi==2.0.0 \ # via # feast (pyproject.toml) # cryptography -charset-normalizer==3.4.4 \ - --hash=sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad \ - --hash=sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93 \ - --hash=sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394 \ - --hash=sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89 \ - --hash=sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc \ - --hash=sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86 \ - --hash=sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63 \ - --hash=sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d \ - --hash=sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f \ - --hash=sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8 \ - --hash=sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0 \ - --hash=sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505 \ - --hash=sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161 \ - --hash=sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af \ - --hash=sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152 \ - --hash=sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318 \ - --hash=sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72 \ - --hash=sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4 \ - --hash=sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e \ - --hash=sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3 \ - --hash=sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576 \ - --hash=sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c \ - --hash=sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1 \ - --hash=sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8 \ - --hash=sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1 \ - --hash=sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2 \ - --hash=sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44 \ - --hash=sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26 \ - --hash=sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88 \ - --hash=sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016 \ - --hash=sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede \ - --hash=sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf \ - --hash=sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a \ - --hash=sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc \ - --hash=sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0 \ - --hash=sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84 \ - --hash=sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db \ - --hash=sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1 \ - --hash=sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7 \ - --hash=sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed \ - --hash=sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8 \ - --hash=sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133 \ - --hash=sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e \ - --hash=sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef \ - --hash=sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14 \ - --hash=sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2 \ - --hash=sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0 \ - --hash=sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d \ - --hash=sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828 \ - --hash=sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f \ - --hash=sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf \ - --hash=sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6 \ - --hash=sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328 \ - --hash=sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090 \ - --hash=sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa \ - --hash=sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381 \ - --hash=sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c \ - --hash=sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb \ - --hash=sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc \ - --hash=sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a \ - --hash=sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec \ - --hash=sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc \ - --hash=sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac \ - --hash=sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e \ - --hash=sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313 \ - --hash=sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569 \ - --hash=sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3 \ - --hash=sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d \ - --hash=sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525 \ - --hash=sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894 \ - --hash=sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3 \ - --hash=sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9 \ - --hash=sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a \ - --hash=sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9 \ - --hash=sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14 \ - --hash=sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25 \ - --hash=sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50 \ - --hash=sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf \ - --hash=sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1 \ - --hash=sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3 \ - --hash=sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac \ - --hash=sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e \ - --hash=sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815 \ - --hash=sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c \ - --hash=sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6 \ - --hash=sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6 \ - --hash=sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e \ - --hash=sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4 \ - --hash=sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84 \ - --hash=sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69 \ - --hash=sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15 \ - --hash=sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191 \ - --hash=sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0 \ - --hash=sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897 \ - --hash=sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd \ - --hash=sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2 \ - --hash=sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794 \ - --hash=sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d \ - --hash=sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074 \ - --hash=sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3 \ - --hash=sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224 \ - --hash=sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838 \ - --hash=sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a \ - --hash=sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d \ - --hash=sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d \ - --hash=sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f \ - --hash=sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8 \ - --hash=sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490 \ - --hash=sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966 \ - --hash=sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9 \ - --hash=sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3 \ - --hash=sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e \ - --hash=sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608 +charset-normalizer==3.4.7 \ + --hash=sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc \ + --hash=sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c \ + --hash=sha256:07d9e39b01743c3717745f4c530a6349eadbfa043c7577eef86c502c15df2c67 \ + --hash=sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4 \ + --hash=sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0 \ + --hash=sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c \ + --hash=sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5 \ + --hash=sha256:12a6fff75f6bc66711b73a2f0addfc4c8c15a20e805146a02d147a318962c444 \ + --hash=sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153 \ + --hash=sha256:14265bfe1f09498b9d8ec91e9ec9fa52775edf90fcbde092b25f4a33d444fea9 \ + --hash=sha256:16d971e29578a5e97d7117866d15889a4a07befe0e87e703ed63cd90cb348c01 \ + --hash=sha256:177a0ba5f0211d488e295aaf82707237e331c24788d8d76c96c5a41594723217 \ + --hash=sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b \ + --hash=sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c \ + --hash=sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a \ + --hash=sha256:1dc8b0ea451d6e69735094606991f32867807881400f808a106ee1d963c46a83 \ + --hash=sha256:1efde3cae86c8c273f1eb3b287be7d8499420cf2fe7585c41d370d3e790054a5 \ + --hash=sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7 \ + --hash=sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb \ + --hash=sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c \ + --hash=sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1 \ + --hash=sha256:2cd4a60d0e2fb04537162c62bbbb4182f53541fe0ede35cdf270a1c1e723cc42 \ + --hash=sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab \ + --hash=sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df \ + --hash=sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e \ + --hash=sha256:320ade88cfb846b8cd6b4ddf5ee9e80ee0c1f52401f2456b84ae1ae6a1a5f207 \ + --hash=sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18 \ + --hash=sha256:36836d6ff945a00b88ba1e4572d721e60b5b8c98c155d465f56ad19d68f23734 \ + --hash=sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38 \ + --hash=sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110 \ + --hash=sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18 \ + --hash=sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44 \ + --hash=sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d \ + --hash=sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48 \ + --hash=sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e \ + --hash=sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5 \ + --hash=sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d \ + --hash=sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53 \ + --hash=sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790 \ + --hash=sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c \ + --hash=sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b \ + --hash=sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116 \ + --hash=sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d \ + --hash=sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10 \ + --hash=sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6 \ + --hash=sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2 \ + --hash=sha256:6370e8686f662e6a3941ee48ed4742317cafbe5707e36406e9df792cdb535776 \ + --hash=sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a \ + --hash=sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265 \ + --hash=sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008 \ + --hash=sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943 \ + --hash=sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374 \ + --hash=sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246 \ + --hash=sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e \ + --hash=sha256:6e0d51f618228538a3e8f46bd246f87a6cd030565e015803691603f55e12afb5 \ + --hash=sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616 \ + --hash=sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15 \ + --hash=sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41 \ + --hash=sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960 \ + --hash=sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752 \ + --hash=sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e \ + --hash=sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72 \ + --hash=sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7 \ + --hash=sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8 \ + --hash=sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b \ + --hash=sha256:813c0e0132266c08eb87469a642cb30aaff57c5f426255419572aaeceeaa7bf4 \ + --hash=sha256:82b271f5137d07749f7bf32f70b17ab6eaabedd297e75dce75081a24f76eb545 \ + --hash=sha256:84c018e49c3bf790f9c2771c45e9313a08c2c2a6342b162cd650258b57817706 \ + --hash=sha256:8751d2787c9131302398b11e6c8068053dcb55d5a8964e114b6e196cf16cb366 \ + --hash=sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb \ + --hash=sha256:87fad7d9ba98c86bcb41b2dc8dbb326619be2562af1f8ff50776a39e55721c5a \ + --hash=sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e \ + --hash=sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00 \ + --hash=sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f \ + --hash=sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a \ + --hash=sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1 \ + --hash=sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66 \ + --hash=sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356 \ + --hash=sha256:a6c5863edfbe888d9eff9c8b8087354e27618d9da76425c119293f11712a6319 \ + --hash=sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4 \ + --hash=sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad \ + --hash=sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d \ + --hash=sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5 \ + --hash=sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7 \ + --hash=sha256:aef65cd602a6d0e0ff6f9930fcb1c8fec60dd2cfcb6facaf4bdb0e5873042db0 \ + --hash=sha256:af21eb4409a119e365397b2adbaca4c9ccab56543a65d5dbd9f920d6ac29f686 \ + --hash=sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34 \ + --hash=sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49 \ + --hash=sha256:bb8cc7534f51d9a017b93e3e85b260924f909601c3df002bcdb58ddb4dc41a5c \ + --hash=sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1 \ + --hash=sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e \ + --hash=sha256:bd9b23791fe793e4968dba0c447e12f78e425c59fc0e3b97f6450f4781f3ee60 \ + --hash=sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0 \ + --hash=sha256:c0f081d69a6e58272819b70288d3221a6ee64b98df852631c80f293514d3b274 \ + --hash=sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d \ + --hash=sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0 \ + --hash=sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae \ + --hash=sha256:c593052c465475e64bbfe5dbd81680f64a67fdc752c56d7a0ae205dc8aeefe0f \ + --hash=sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d \ + --hash=sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe \ + --hash=sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3 \ + --hash=sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393 \ + --hash=sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1 \ + --hash=sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af \ + --hash=sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44 \ + --hash=sha256:d61f00a0869d77422d9b2aba989e2d24afa6ffd552af442e0e58de4f35ea6d00 \ + --hash=sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c \ + --hash=sha256:dca4bbc466a95ba9c0234ef56d7dd9509f63da22274589ebd4ed7f1f4d4c54e3 \ + --hash=sha256:dd915403e231e6b1809fe9b6d9fc55cf8fb5e02765ac625d9cd623342a7905d7 \ + --hash=sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd \ + --hash=sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e \ + --hash=sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b \ + --hash=sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8 \ + --hash=sha256:e5f4d355f0a2b1a31bc3edec6795b46324349c9cb25eed068049e4f472fb4259 \ + --hash=sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859 \ + --hash=sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46 \ + --hash=sha256:e80c8378d8f3d83cd3164da1ad2df9e37a666cdde7b1cb2298ed0b558064be30 \ + --hash=sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b \ + --hash=sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46 \ + --hash=sha256:ed065083d0898c9d5b4bbec7b026fd755ff7454e6e8b73a67f8c744b13986e24 \ + --hash=sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a \ + --hash=sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24 \ + --hash=sha256:f22dec1690b584cea26fade98b2435c132c1b5f68e39f5a0b7627cd7ae31f1dc \ + --hash=sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215 \ + --hash=sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063 \ + --hash=sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832 \ + --hash=sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6 \ + --hash=sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79 \ + --hash=sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464 # via # requests # snowflake-connector-python @@ -432,56 +448,56 @@ colorama==0.4.6 \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 # via feast (pyproject.toml) -cryptography==46.0.5 \ - --hash=sha256:02f547fce831f5096c9a567fd41bc12ca8f11df260959ecc7c3202555cc47a72 \ - --hash=sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235 \ - --hash=sha256:1abfdb89b41c3be0365328a410baa9df3ff8a9110fb75e7b52e66803ddabc9a9 \ - --hash=sha256:2ae6971afd6246710480e3f15824ed3029a60fc16991db250034efd0b9fb4356 \ - --hash=sha256:2b7a67c9cd56372f3249b39699f2ad479f6991e62ea15800973b956f4b73e257 \ - --hash=sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad \ - --hash=sha256:38946c54b16c885c72c4f59846be9743d699eee2b69b6988e0a00a01f46a61a4 \ - --hash=sha256:3b4995dc971c9fb83c25aa44cf45f02ba86f71ee600d81091c2f0cbae116b06c \ - --hash=sha256:3ce58ba46e1bc2aac4f7d9290223cead56743fa6ab94a5d53292ffaac6a91614 \ - --hash=sha256:3ee190460e2fbe447175cda91b88b84ae8322a104fc27766ad09428754a618ed \ - --hash=sha256:4108d4c09fbbf2789d0c926eb4152ae1760d5a2d97612b92d508d96c861e4d31 \ - --hash=sha256:420d0e909050490d04359e7fdb5ed7e667ca5c3c402b809ae2563d7e66a92229 \ - --hash=sha256:47fb8a66058b80e509c47118ef8a75d14c455e81ac369050f20ba0d23e77fee0 \ - --hash=sha256:4c3341037c136030cb46e4b1e17b7418ea4cbd9dd207e4a6f3b2b24e0d4ac731 \ - --hash=sha256:4d7e3d356b8cd4ea5aff04f129d5f66ebdc7b6f8eae802b93739ed520c47c79b \ - --hash=sha256:4d8ae8659ab18c65ced284993c2265910f6c9e650189d4e3f68445ef82a810e4 \ - --hash=sha256:4e817a8920bfbcff8940ecfd60f23d01836408242b30f1a708d93198393a80b4 \ - --hash=sha256:50bfb6925eff619c9c023b967d5b77a54e04256c4281b0e21336a130cd7fc263 \ - --hash=sha256:556e106ee01aa13484ce9b0239bca667be5004efb0aabbed28d353df86445595 \ - --hash=sha256:582f5fcd2afa31622f317f80426a027f30dc792e9c80ffee87b993200ea115f1 \ - --hash=sha256:5be7bf2fb40769e05739dd0046e7b26f9d4670badc7b032d6ce4db64dddc0678 \ - --hash=sha256:60ee7e19e95104d4c03871d7d7dfb3d22ef8a9b9c6778c94e1c8fcc8365afd48 \ - --hash=sha256:61aa400dce22cb001a98014f647dc21cda08f7915ceb95df0c9eaf84b4b6af76 \ - --hash=sha256:68f68d13f2e1cb95163fa3b4db4bf9a159a418f5f6e7242564fc75fcae667fd0 \ - --hash=sha256:7d1f30a86d2757199cb2d56e48cce14deddf1f9c95f1ef1b64ee91ea43fe2e18 \ - --hash=sha256:7d731d4b107030987fd61a7f8ab512b25b53cef8f233a97379ede116f30eb67d \ - --hash=sha256:803812e111e75d1aa73690d2facc295eaefd4439be1023fefc4995eaea2af90d \ - --hash=sha256:80a8d7bfdf38f87ca30a5391c0c9ce4ed2926918e017c29ddf643d0ed2778ea1 \ - --hash=sha256:8293f3dea7fc929ef7240796ba231413afa7b68ce38fd21da2995549f5961981 \ - --hash=sha256:8456928655f856c6e1533ff59d5be76578a7157224dbd9ce6872f25055ab9ab7 \ - --hash=sha256:890bcb4abd5a2d3f852196437129eb3667d62630333aacc13dfd470fad3aaa82 \ - --hash=sha256:94a76daa32eb78d61339aff7952ea819b1734b46f73646a07decb40e5b3448e2 \ - --hash=sha256:9f16fbdf4da055efb21c22d81b89f155f02ba420558db21288b3d0035bafd5f4 \ - --hash=sha256:a3d1fae9863299076f05cb8a778c467578262fae09f9dc0ee9b12eb4268ce663 \ - --hash=sha256:a3d507bb6a513ca96ba84443226af944b0f7f47dcc9a399d110cd6146481d24c \ - --hash=sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d \ - --hash=sha256:ba2a27ff02f48193fc4daeadf8ad2590516fa3d0adeeb34336b96f7fa64c1e3a \ - --hash=sha256:bc84e875994c3b445871ea7181d424588171efec3e185dced958dad9e001950a \ - --hash=sha256:bfd56bb4b37ed4f330b82402f6f435845a5f5648edf1ad497da51a8452d5d62d \ - --hash=sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b \ - --hash=sha256:c3bcce8521d785d510b2aad26ae2c966092b7daa8f45dd8f44734a104dc0bc1a \ - --hash=sha256:c4143987a42a2397f2fc3b4d7e3a7d313fbe684f67ff443999e803dd75a76826 \ - --hash=sha256:c69fd885df7d089548a42d5ec05be26050ebcd2283d89b3d30676eb32ff87dee \ - --hash=sha256:ced80795227d70549a411a4ab66e8ce307899fad2220ce5ab2f296e687eacde9 \ - --hash=sha256:d66e421495fdb797610a08f43b05269e0a5ea7f5e652a89bfd5a7d3c1dee3648 \ - --hash=sha256:d861ee9e76ace6cf36a6a89b959ec08e7bc2493ee39d07ffe5acb23ef46d27da \ - --hash=sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2 \ - --hash=sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2 \ - --hash=sha256:fe346b143ff9685e40192a4960938545c699054ba11d4f9029f94751e3f71d87 +cryptography==46.0.6 \ + --hash=sha256:02fad249cb0e090b574e30b276a3da6a149e04ee2f049725b1f69e7b8351ec70 \ + --hash=sha256:063b67749f338ca9c5a0b7fe438a52c25f9526b851e24e6c9310e7195aad3b4d \ + --hash=sha256:12cae594e9473bca1a7aceb90536060643128bb274fcea0fc459ab90f7d1ae7a \ + --hash=sha256:12f0fa16cc247b13c43d56d7b35287ff1569b5b1f4c5e87e92cc4fcc00cd10c0 \ + --hash=sha256:22259338084d6ae497a19bae5d4c66b7ca1387d3264d1c2c0e72d9e9b6a77b97 \ + --hash=sha256:26031f1e5ca62fcb9d1fcb34b2b60b390d1aacaa15dc8b895a9ed00968b97b30 \ + --hash=sha256:27550628a518c5c6c903d84f637fbecf287f6cb9ced3804838a1295dc1fd0759 \ + --hash=sha256:2b417edbe8877cda9022dde3a008e2deb50be9c407eef034aeeb3a8b11d9db3c \ + --hash=sha256:2ea0f37e9a9cf0df2952893ad145fd9627d326a59daec9b0802480fa3bcd2ead \ + --hash=sha256:2ef9e69886cbb137c2aef9772c2e7138dc581fad4fcbcf13cc181eb5a3ab6275 \ + --hash=sha256:341359d6c9e68834e204ceaf25936dffeafea3829ab80e9503860dcc4f4dac58 \ + --hash=sha256:380343e0653b1c9d7e1f55b52aaa2dbb2fdf2730088d48c43ca1c7c0abb7cc2f \ + --hash=sha256:3c21d92ed15e9cfc6eb64c1f5a0326db22ca9c2566ca46d845119b45b4400361 \ + --hash=sha256:3dfa6567f2e9e4c5dceb8ccb5a708158a2a871052fa75c8b78cb0977063f1507 \ + --hash=sha256:456b3215172aeefb9284550b162801d62f5f264a081049a3e94307fe20792cfa \ + --hash=sha256:4668298aef7cddeaf5c6ecc244c2302a2b8e40f384255505c22875eebb47888b \ + --hash=sha256:50575a76e2951fe7dbd1f56d181f8c5ceeeb075e9ff88e7ad997d2f42af06e7b \ + --hash=sha256:639301950939d844a9e1c4464d7e07f902fe9a7f6b215bb0d4f28584729935d8 \ + --hash=sha256:64235194bad039a10bb6d2d930ab3323baaec67e2ce36215fd0952fad0930ca8 \ + --hash=sha256:6617f67b1606dfd9fe4dbfa354a9508d4a6d37afe30306fe6c101b7ce3274b72 \ + --hash=sha256:67177e8a9f421aa2d3a170c3e56eca4e0128883cf52a071a7cbf53297f18b175 \ + --hash=sha256:6728c49e3b2c180ef26f8e9f0a883a2c585638db64cf265b49c9ba10652d430e \ + --hash=sha256:6739d56300662c468fddb0e5e291f9b4d084bead381667b9e654c7dd81705124 \ + --hash=sha256:69cf0056d6947edc6e6760e5f17afe4bea06b56a9ac8a06de9d2bd6b532d4f3a \ + --hash=sha256:760997a4b950ff00d418398ad73fbc91aa2894b5c1db7ccb45b4f68b42a63b3c \ + --hash=sha256:79e865c642cfc5c0b3eb12af83c35c5aeff4fa5c672dc28c43721c2c9fdd2f0f \ + --hash=sha256:7e6142674f2a9291463e5e150090b95a8519b2fb6e6aaec8917dd8d094ce750d \ + --hash=sha256:7f417f034f91dcec1cb6c5c35b07cdbb2ef262557f701b4ecd803ee8cefed4f4 \ + --hash=sha256:7f6690b6c55e9c5332c0b59b9c8a3fb232ebf059094c17f9019a51e9827df91c \ + --hash=sha256:8927ccfbe967c7df312ade694f987e7e9e22b2425976ddbf28271d7e58845290 \ + --hash=sha256:8ce35b77aaf02f3b59c90b2c8a05c73bac12cea5b4e8f3fbece1f5fddea5f0ca \ + --hash=sha256:8e7304c4f4e9490e11efe56af6713983460ee0780f16c63f219984dab3af9d2d \ + --hash=sha256:90e5f0a7b3be5f40c3a0a0eafb32c681d8d2c181fc2a1bdabe9b3f611d9f6b1a \ + --hash=sha256:97c8115b27e19e592a05c45d0dd89c57f81f841cc9880e353e0d3bf25b2139ed \ + --hash=sha256:9a693028b9cbe51b5a1136232ee8f2bc242e4e19d456ded3fa7c86e43c713b4a \ + --hash=sha256:9a9c42a2723999a710445bc0d974e345c32adfd8d2fac6d8a251fa829ad31cfb \ + --hash=sha256:a3e84d5ec9ba01f8fd03802b2147ba77f0c8f2617b2aff254cedd551844209c8 \ + --hash=sha256:aad75154a7ac9039936d50cf431719a2f8d4ed3d3c277ac03f3339ded1a5e707 \ + --hash=sha256:b12c6b1e1651e42ab5de8b1e00dc3b6354fdfd778e7fa60541ddacc27cd21410 \ + --hash=sha256:b928a3ca837c77a10e81a814a693f2295200adb3352395fad024559b7be7a736 \ + --hash=sha256:bcb87663e1f7b075e48c3be3ecb5f0b46c8fc50b50a97cf264e7f60242dca3f2 \ + --hash=sha256:c797e2517cb7880f8297e2c0f43bb910e91381339336f75d2c1c2cbf811b70b4 \ + --hash=sha256:c89eb37fae9216985d8734c1afd172ba4927f5a05cfd9bf0e4863c6d5465b013 \ + --hash=sha256:cdcd3edcbc5d55757e5f5f3d330dd00007ae463a7e7aa5bf132d1f22a4b62b19 \ + --hash=sha256:d24c13369e856b94892a89ddf70b332e0b70ad4a5c43cf3e9cb71d6d7ffa1f7b \ + --hash=sha256:d4e4aadb7fc1f88687f47ca20bb7227981b03afaae69287029da08096853b738 \ + --hash=sha256:d9528b535a6c4f8ff37847144b8986a9a143585f0540fbcb1a98115b543aa463 \ + --hash=sha256:ed3775295fb91f70b4027aeba878d79b3e55c0b3e97eaa4de71f8f23a9f2eb77 \ + --hash=sha256:ed418c37d095aeddf5336898a132fba01091f0ac5844e3e8018506f014b6d2c4 # via # google-auth # pyjwt @@ -553,13 +569,13 @@ cython==3.0.12 \ --hash=sha256:feb86122a823937cc06e4c029d80ff69f082ebb0b959ab52a5af6cdd271c5dc3 \ --hash=sha256:ff5c0b6a65b08117d0534941d404833d516dac422eee88c6b4fd55feb409a5ed # via feast (pyproject.toml) -dask[dataframe]==2026.1.2 \ - --hash=sha256:1136683de2750d98ea792670f7434e6c1cfce90cab2cc2f2495a9e60fd25a4fc \ - --hash=sha256:46a0cf3b8d87f78a3d2e6b145aea4418a6d6d606fe6a16c79bd8ca2bb862bc91 +dask[dataframe]==2026.3.0 \ + --hash=sha256:be614b9242b0b38288060fb2d7696125946469c98a1c30e174883fd199e0428d \ + --hash=sha256:f7d96c8274e8a900d217c1ff6ea8d1bbf0b4c2c21e74a409644498d925eb8f85 # via feast (pyproject.toml) -db-dtypes==1.5.0 \ - --hash=sha256:abdbb2e4eb965800ed6f98af0c5c1cafff9063ace09114be2d26a7f046be2c8a \ - --hash=sha256:ad9e94243f53e104bc77dbf9ae44b580d83a770d3694483aba59c9767966daa5 +db-dtypes==1.5.1 \ + --hash=sha256:901099b807c9312bc61a5bddbfb07512884e6c6d5a9edacf24d50bcf303aa5f7 \ + --hash=sha256:ad71a6645e3c1f06d4d32023940576648f43119822f825f0d22587c6ef8afe15 # via # google-cloud-bigquery # pandas-gbq @@ -571,56 +587,50 @@ docutils==0.22.4 \ --hash=sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968 \ --hash=sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de # via sphinx -duckdb==1.4.4 \ - --hash=sha256:0509b39ea7af8cff0198a99d206dca753c62844adab54e545984c2e2c1381616 \ - --hash=sha256:0d636ceda422e7babd5e2f7275f6a0d1a3405e6a01873f00d38b72118d30c10b \ - --hash=sha256:1af6e76fe8bd24875dc56dd8e38300d64dc708cd2e772f67b9fbc635cc3066a3 \ - --hash=sha256:1f8d55843cc940e36261689054f7dfb6ce35b1f5b0953b0d355b6adb654b0d52 \ - --hash=sha256:25874f8b1355e96178079e37312c3ba6d61a2354f51319dae860cf21335c3a20 \ - --hash=sha256:337f8b24e89bc2e12dadcfe87b4eb1c00fd920f68ab07bc9b70960d6523b8bc3 \ - --hash=sha256:452c5b5d6c349dc5d1154eb2062ee547296fcbd0c20e9df1ed00b5e1809089da \ - --hash=sha256:453b115f4777467f35103d8081770ac2f223fb5799178db5b06186e3ab51d1f2 \ - --hash=sha256:47dd4162da6a2be59a0aef640eb08d6360df1cf83c317dcc127836daaf3b7f7c \ - --hash=sha256:49123b579e4a6323e65139210cd72dddc593a72d840211556b60f9703bda8526 \ - --hash=sha256:4c25d5b0febda02b7944e94fdae95aecf952797afc8cb920f677b46a7c251955 \ - --hash=sha256:50f2eb173c573811b44aba51176da7a4e5c487113982be6a6a1c37337ec5fa57 \ - --hash=sha256:53cd6423136ab44383ec9955aefe7599b3fb3dd1fe006161e6396d8167e0e0d4 \ - --hash=sha256:5536eb952a8aa6ae56469362e344d4e6403cc945a80bc8c5c2ebdd85d85eb64b \ - --hash=sha256:59c8d76016dde854beab844935b1ec31de358d4053e792988108e995b18c08e7 \ - --hash=sha256:5ba684f498d4e924c7e8f30dd157da8da34c8479746c5011b6c0e037e9c60ad2 \ - --hash=sha256:5cdc4126ec925edf3112bc656ac9ed23745294b854935fa7a643a216e4455af6 \ - --hash=sha256:5e1933fac5293fea5926b0ee75a55b8cfe7f516d867310a5b251831ab61fe62b \ - --hash=sha256:6703dd1bb650025b3771552333d305d62ddd7ff182de121483d4e042ea6e2e00 \ - --hash=sha256:6792ca647216bd5c4ff16396e4591cfa9b4a72e5ad7cdd312cec6d67e8431a7c \ - --hash=sha256:6cb357cfa3403910e79e2eb46c8e445bb1ee2fd62e9e9588c6b999df4256abc1 \ - --hash=sha256:6fb1225a9ea5877421481d59a6c556a9532c32c16c7ae6ca8d127e2b878c9389 \ - --hash=sha256:707530f6637e91dc4b8125260595299ec9dd157c09f5d16c4186c5988bfbd09a \ - --hash=sha256:7df7351328ffb812a4a289732f500d621e7de9942a3a2c9b6d4afcf4c0e72526 \ - --hash=sha256:7eec0bf271ac622e57b7f6554a27a6e7d1dd2f43d1871f7962c74bcbbede15ba \ - --hash=sha256:8097201bc5fd0779d7fcc2f3f4736c349197235f4cb7171622936343a1aa8dbf \ - --hash=sha256:8bba52fd2acb67668a4615ee17ee51814124223de836d9e2fdcbc4c9021b3d3c \ - --hash=sha256:8e5c2d8a0452df55e092959c0bfc8ab8897ac3ea0f754cb3b0ab3e165cd79aff \ - --hash=sha256:a3c8542db7ffb128aceb7f3b35502ebaddcd4f73f1227569306cc34bad06680c \ - --hash=sha256:b297eff642503fd435a9de5a9cb7db4eccb6f61d61a55b30d2636023f149855f \ - --hash=sha256:bf138201f56e5d6fc276a25138341b3523e2f84733613fc43f02c54465619a95 \ - --hash=sha256:c65d15c440c31e06baaebfd2c06d71ce877e132779d309f1edf0a85d23c07e92 \ - --hash=sha256:c9566a4ed834ec7999db5849f53da0a7ee83d86830c33f471bf0211a1148ca12 \ - --hash=sha256:cd1be3d48577f5b40eb9706c6b2ae10edfe18e78eb28e31a3b922dcff1183597 \ - --hash=sha256:d0440f59e0cd9936a9ebfcf7a13312eda480c79214ffed3878d75947fc3b7d6d \ - --hash=sha256:d525de5f282b03aa8be6db86b1abffdceae5f1055113a03d5b50cd2fb8cf2ef8 \ - --hash=sha256:ddcfd9c6ff234da603a1edd5fd8ae6107f4d042f74951b65f91bc5e2643856b3 \ - --hash=sha256:e041f2fbd6888da090eca96ac167a7eb62d02f778385dd9155ed859f1c6b6dc8 \ - --hash=sha256:e870a441cb1c41d556205deb665749f26347ed13b3a247b53714f5d589596977 \ - --hash=sha256:f28a18cc790217e5b347bb91b2cab27aafc557c58d3d8382e04b4fe55d0c3f66 \ - --hash=sha256:fb94de6d023de9d79b7edc1ae07ee1d0b4f5fa8a9dcec799650b5befdf7aafec +duckdb==1.5.1 \ + --hash=sha256:054ad424b051b334052afac58cb216f3b1ebb8579fc8c641e60f0182e8725ea9 \ + --hash=sha256:05fc91767d0cfc4cf2fa68966ab5b479ac07561752e42dd0ae30327bd160f64a \ + --hash=sha256:0a6acc2040bec1f05de62a2f3f68f4c12f3ec7d6012b4317d0ab1a195af26225 \ + --hash=sha256:26e56b5f0c96189e3288d83cf7b476e23615987902f801e5788dee15ee9f24a9 \ + --hash=sha256:36e8e32621a9e2a9abe75dc15a4b54a3997f2d8b1e53ad754bae48a083c91130 \ + --hash=sha256:40c5220ec93790b18ec6278da9c6ac2608d997ee6d6f7cd44c5c3992764e8e71 \ + --hash=sha256:446d500a2977c6ae2077f340c510a25956da5c77597175c316edfa87248ceda3 \ + --hash=sha256:46f92ada9023e59f27edc048167b31ac9a03911978b1296c845a34462a27f096 \ + --hash=sha256:482f8a13f2600f527e427f73c42b5aa75536f9892868068f0aaf573055a0135f \ + --hash=sha256:553c273a6a8f140adaa6da6a6135c7f95bdc8c2e5f95252fcdf9832d758e2141 \ + --hash=sha256:5ae7c0d744d64e2753149634787cc4ab60f05ef1e542b060eeab719f3cdb7723 \ + --hash=sha256:5d4147422d91ccdc2d2abf6ed24196025e020259d1d267970ae20c13c2ce84b1 \ + --hash=sha256:6af347debc8b721aa72e48671166282da979d5e5ae52dbc660ab417282b48e23 \ + --hash=sha256:6ba302115f63f6482c000ccfd62efdb6c41d9d182a5bcd4a90e7ab8cd13856eb \ + --hash=sha256:6f7361d66cc801d9eb4df734b139cd7b0e3c257a16f3573ebd550ddb255549e6 \ + --hash=sha256:715f05ea198d20d7f8b407b9b84e0023d17f2b9096c194cea702b7840e74f1f7 \ + --hash=sha256:71dddcebbc5a70e946a06c30b59b5dd7999c9833d307168f90fb4e4b672ab63e \ + --hash=sha256:8150c569b2aa4573b51ba8475e814aa41fd53a3d510c1ffb96f1139f46faf611 \ + --hash=sha256:8843bd9594e1387f1e601439e19ad73abdf57356104fd1e53a708255bb95a13d \ + --hash=sha256:8c0088765747ae5d6c9f89987bb36f9fb83564f07090d721344ce8e1abedffea \ + --hash=sha256:972d0dbf283508f9bc446ee09c3838cb7c7f114b5bdceee41753288c97fe2f7c \ + --hash=sha256:a28531cee2a5a42d89f9ba4da53bfeb15681f12acc0263476c8705380dadce07 \ + --hash=sha256:a3be2072315982e232bfe49c9d3db0a59ba67b2240a537ef42656cc772a887c7 \ + --hash=sha256:ac2804043bd1bc10b5da18f8f4c706877197263a510c41be9b4c0062f5783dcc \ + --hash=sha256:afab8b4b1f4469c3879bb049dd039f8fce402712050324e9524a43d7324c5e87 \ + --hash=sha256:b370d1620a34a4538ef66524fcee9de8171fa263c701036a92bc0b4c1f2f9c6d \ + --hash=sha256:b8b0808dba0c63b7633bdaefb34e08fe0612622224f9feb0e7518904b1615101 \ + --hash=sha256:bc7ca6a1a40e7e4c933017e6c09ef18032add793df4e42624c6c0c87e0bebdad \ + --hash=sha256:caa65e1f5bf007430bf657c37cab7ab81a4ddf8d337e3062bcc5085d17ef038b \ + --hash=sha256:d68c5a01a283cb13b79eafe016fe5869aa11bff8c46e7141c70aa0aac808010f \ + --hash=sha256:da137802688190835b4c863cafa77fd7e29dff662ee6d905a9ffc14f00299c91 \ + --hash=sha256:e56a20ab6cdb90a95b0c99652e28de3504ce77129087319c03c9098266183ae5 \ + --hash=sha256:e878ccb7d20872065e1597935fdb5e65efa43220c8edd0d9c4a1a7ff1f3eb277 \ + --hash=sha256:eba81e0b3011c1f23df7ea47ef4ffaa8239817959ae291515b6efd068bde2161 \ + --hash=sha256:ed6d23a3f806898e69c77430ebd8da0c79c219f97b9acbc9a29a653e09740c59 # via ibis-framework durationpy==0.10 \ --hash=sha256:1fa6893409a6e739c9c72334fc65cca1f355dbdd93405d30f726deb5bde42fba \ --hash=sha256:3b41e1b601234296b4fb368338fdcd3e13e0b4fb5b67345948f4f2bf9868b286 # via kubernetes -fastapi==0.129.0 \ - --hash=sha256:61315cebd2e65df5f97ec298c888f9de30430dd0612d59d6480beafbc10655af \ - --hash=sha256:b4946880e48f462692b31c083be0432275cbfb6e2274566b1be91479cc1a84ec +fastapi==0.135.3 \ + --hash=sha256:9b0f590c813acd13d0ab43dd8494138eb58e484bfac405db1f3187cfc5810d98 \ + --hash=sha256:bd6d7caf1a2bdd8d676843cdcd2287729572a1ef524fc4d65c17ae002a1be654 # via # feast (pyproject.toml) # fastapi-mcp @@ -628,9 +638,9 @@ fastapi-mcp==0.4.0 \ --hash=sha256:d4a3fe7966af24d44e4b412720561c95eb12bed999a4443a88221834b3b15aec \ --hash=sha256:d4ca9410996f4c7b8ea0d7b20fdf79878dc359ebf89cbf3b222e0b675a55097d # via feast (pyproject.toml) -filelock==3.24.2 \ - --hash=sha256:667d7dc0b7d1e1064dd5f8f8e80bdac157a6482e8d2e02cd16fd3b6b33bd6556 \ - --hash=sha256:c22803117490f156e59fafce621f0550a7a853e2bbf4f87f112b11d469b6c81b +filelock==3.25.2 \ + --hash=sha256:b64ece2b38f4ca29dd3e810287aa8c48182bbecd1ae6e9ae126c9b35f1382694 \ + --hash=sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70 # via snowflake-connector-python flit-core==3.12.0 \ --hash=sha256:18f63100d6f94385c6ed57a72073443e1a71a4acb4339491615d0f16d6ff01b2 \ @@ -776,9 +786,9 @@ fsspec==2024.9.0 \ # via # feast (pyproject.toml) # dask -google-api-core[grpc]==2.29.0 \ - --hash=sha256:84181be0f8e6b04006df75ddfe728f24489f0af57c96a529ff7cf45bc28797f7 \ - --hash=sha256:d30bc60980daa36e314b5d5a3e5958b0200cb44ca8fa1be2b614e932b75a3ea9 +google-api-core[grpc]==2.30.2 \ + --hash=sha256:9a8113e1a88bdc09a7ff629707f2214d98d61c7f6ceb0ea38c42a095d02dc0f9 \ + --hash=sha256:a4c226766d6af2580577db1f1a51bf53cd262f722b49731ce7414c43068a9594 # via # feast (pyproject.toml) # google-cloud-bigquery @@ -788,9 +798,9 @@ google-api-core[grpc]==2.29.0 \ # google-cloud-datastore # google-cloud-storage # pandas-gbq -google-auth==2.48.0 \ - --hash=sha256:2e2a537873d449434252a9632c28bfc268b0adb1e53f9fb62afc5333a975903f \ - --hash=sha256:4f7e706b0cd3208a3d940a19a822c37a476ddba5450156c3e6624a71f7c841ce +google-auth==2.49.1 \ + --hash=sha256:16d40da1c3c5a0533f57d268fe72e0ebb0ae1cc3b567024122651c045d879b64 \ + --hash=sha256:195ebe3dca18eddd1b3db5edc5189b76c13e96f29e73043b923ebcf3f1a860f7 # via # google-api-core # google-auth-oauthlib @@ -802,37 +812,37 @@ google-auth==2.48.0 \ # google-cloud-storage # pandas-gbq # pydata-google-auth -google-auth-oauthlib==1.2.4 \ - --hash=sha256:0e922eea5f2baacaf8867febb782e46e7b153236c21592ed76ab3ddb77ffd772 \ - --hash=sha256:3ca93859c6cc9003c8e12b2a0868915209d7953f05a70f4880ab57d57e56ee3e +google-auth-oauthlib==1.3.1 \ + --hash=sha256:14c22c7b3dd3d06dbe44264144409039465effdd1eef94f7ce3710e486cc4bfa \ + --hash=sha256:1a139ef23f1318756805b0e95f655c238bffd29655329a2978218248da4ee7f8 # via # pandas-gbq # pydata-google-auth -google-cloud-bigquery[pandas]==3.40.1 \ - --hash=sha256:75afcfb6e007238fe1deefb2182105249321145ff921784fe7b1de2b4ba24506 \ - --hash=sha256:9082a6b8193aba87bed6a2c79cf1152b524c99bb7e7ac33a785e333c09eac868 +google-cloud-bigquery[pandas]==3.41.0 \ + --hash=sha256:2217e488b47ed576360c9b2cc07d59d883a54b83167c0ef37f915c26b01a06fe \ + --hash=sha256:2a5b5a737b401cbd824a6e5eac7554100b878668d908e6548836b5d8aaa4dcaa # via # feast (pyproject.toml) # pandas-gbq -google-cloud-bigquery-storage==2.36.1 \ - --hash=sha256:99ad6b8810d028f0cf368ea0cc54b3cda20e856f05eb4cda51f1db2a70692286 \ - --hash=sha256:fd3917584a41f7a9d9c633b31ff43103869b108224e8a4b765537eb1ea83148c +google-cloud-bigquery-storage==2.37.0 \ + --hash=sha256:1e319c27ef60fc31030f6e0b52e5e891e1cdd50551effe8c6f673a4c3c56fcb6 \ + --hash=sha256:f88ee7f1e49db1e639da3d9a8b79835ca4bc47afbb514fb2adfc0ccb41a7fd97 # via feast (pyproject.toml) -google-cloud-bigtable==2.35.0 \ - --hash=sha256:f355bfce1f239453ec2bb3839b0f4f9937cf34ef06ef29e1ca63d58fd38d0c50 \ - --hash=sha256:f5699012c5fea4bd4bdf7e80e5e3a812a847eb8f41bf8dc2f43095d6d876b83b +google-cloud-bigtable==2.36.0 \ + --hash=sha256:21b2f41231b7368a550b44d5b493b811b3507fcb23eb26d00005cd3f205f2207 \ + --hash=sha256:d5987733c2f60c739f93f259d2037858411cc994ac37cdfbccb6bb159f3ca43e # via feast (pyproject.toml) -google-cloud-core==2.5.0 \ - --hash=sha256:67d977b41ae6c7211ee830c7912e41003ea8194bff15ae7d72fd6f51e57acabc \ - --hash=sha256:7c1b7ef5c92311717bd05301aa1a91ffbc565673d3b0b4163a52d8413a186963 +google-cloud-core==2.5.1 \ + --hash=sha256:3dc94bdec9d05a31d9f355045ed0f369fbc0d8c665076c734f065d729800f811 \ + --hash=sha256:ea62cdf502c20e3e14be8a32c05ed02113d7bef454e40ff3fab6fe1ec9f1f4e7 # via # google-cloud-bigquery # google-cloud-bigtable # google-cloud-datastore # google-cloud-storage -google-cloud-datastore==2.23.0 \ - --hash=sha256:24a1b1d29b902148fe41b109699f76fd3aa60591e9d547c0f8b87d7bf9ff213f \ - --hash=sha256:80049883a4ae928fdcc661ba6803ec267665dc0e6f3ce2da91441079a6bb6387 +google-cloud-datastore==2.24.0 \ + --hash=sha256:81f1d1c12c2906f59507f72742545ab04c38f62ed70b0542057e3cf04a53aa65 \ + --hash=sha256:f087c02a6aa4ac68bbf17f0c048ae3ee355856bf09c51439bfba193741387792 # via feast (pyproject.toml) google-cloud-storage==2.19.0 \ --hash=sha256:aeb971b5c29cf8ab98445082cbfe7b161a1f48ed275822f59ed3f1524ea54fba \ @@ -876,78 +886,78 @@ google-crc32c==1.8.0 \ # google-cloud-bigtable # google-cloud-storage # google-resumable-media -google-resumable-media==2.8.0 \ - --hash=sha256:dd14a116af303845a8d932ddae161a26e86cc229645bc98b39f026f9b1717582 \ - --hash=sha256:f1157ed8b46994d60a1bc432544db62352043113684d4e030ee02e77ebe9a1ae +google-resumable-media==2.8.2 \ + --hash=sha256:82b6d8ccd11765268cdd2a2123f417ec806b8eef3000a9a38dfe3033da5fb220 \ + --hash=sha256:f3354a182ebd193ae3f42e3ef95e6c9b10f128320de23ac7637236713b1acd70 # via # google-cloud-bigquery # google-cloud-storage -googleapis-common-protos[grpc]==1.72.0 \ - --hash=sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038 \ - --hash=sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5 +googleapis-common-protos[grpc]==1.74.0 \ + --hash=sha256:57971e4eeeba6aad1163c1f0fc88543f965bb49129b8bb55b2b7b26ecab084f1 \ + --hash=sha256:702216f78610bb510e3f12ac3cafd281b7ac45cc5d86e90ad87e4d301a3426b5 # via # feast (pyproject.toml) # google-api-core # grpc-google-iam-v1 # grpcio-status -greenlet==3.3.1 \ - --hash=sha256:02925a0bfffc41e542c70aa14c7eda3593e4d7e274bfcccca1827e6c0875902e \ - --hash=sha256:04bee4775f40ecefcdaa9d115ab44736cd4b9c5fba733575bfe9379419582e13 \ - --hash=sha256:070472cd156f0656f86f92e954591644e158fd65aa415ffbe2d44ca77656a8f5 \ - --hash=sha256:09f51496a0bfbaa9d74d36a52d2580d1ef5ed4fdfcff0a73730abfbbbe1403dd \ - --hash=sha256:1108b61b06b5224656121c3c8ee8876161c491cbe74e5c519e0634c837cf93d5 \ - --hash=sha256:12184c61e5d64268a160226fb4818af4df02cfead8379d7f8b99a56c3a54ff3e \ - --hash=sha256:14194f5f4305800ff329cbf02c5fcc88f01886cadd29941b807668a45f0d2336 \ - --hash=sha256:20fedaadd422fa02695f82093f9a98bad3dab5fcda793c658b945fcde2ab27ba \ - --hash=sha256:27289986f4e5b0edec7b5a91063c109f0276abb09a7e9bdab08437525977c946 \ - --hash=sha256:2f080e028001c5273e0b42690eaf359aeef9cb1389da0f171ea51a5dc3c7608d \ - --hash=sha256:301860987846c24cb8964bdec0e31a96ad4a2a801b41b4ef40963c1b44f33451 \ - --hash=sha256:32e4ca9777c5addcbf42ff3915d99030d8e00173a56f80001fb3875998fe410b \ - --hash=sha256:33a956fe78bbbda82bfc95e128d61129b32d66bcf0a20a1f0c08aa4839ffa951 \ - --hash=sha256:34a729e2e4e4ffe9ae2408d5ecaf12f944853f40ad724929b7585bca808a9d6f \ - --hash=sha256:39eda9ba259cc9801da05351eaa8576e9aa83eb9411e8f0c299e05d712a210f2 \ - --hash=sha256:3a300354f27dd86bae5fbf7002e6dd2b3255cd372e9242c933faf5e859b703fe \ - --hash=sha256:3e0f3878ca3a3ff63ab4ea478585942b53df66ddde327b59ecb191b19dbbd62d \ - --hash=sha256:3e63252943c921b90abb035ebe9de832c436401d9c45f262d80e2d06cc659242 \ - --hash=sha256:41848f3230b58c08bb43dee542e74a2a2e34d3c59dc3076cec9151aeeedcae98 \ - --hash=sha256:49f4ad195d45f4a66a0eb9c1ba4832bb380570d361912fa3554746830d332149 \ - --hash=sha256:4b065d3284be43728dd280f6f9a13990b56470b81be20375a207cdc814a983f2 \ - --hash=sha256:4b9721549a95db96689458a1e0ae32412ca18776ed004463df3a9299c1b257ab \ - --hash=sha256:50e1457f4fed12a50e427988a07f0f9df53cf0ee8da23fab16e6732c2ec909d4 \ - --hash=sha256:59913f1e5ada20fde795ba906916aea25d442abcc0593fba7e26c92b7ad76249 \ - --hash=sha256:5fd23b9bc6d37b563211c6abbb1b3cab27db385a4449af5c32e932f93017080c \ - --hash=sha256:6423481193bbbe871313de5fd06a082f2649e7ce6e08015d2a76c1e9186ca5b3 \ - --hash=sha256:65be2f026ca6a176f88fb935ee23c18333ccea97048076aef4db1ef5bc0713ac \ - --hash=sha256:67ea3fc73c8cd92f42467a72b75e8f05ed51a0e9b1d15398c913416f2dafd49f \ - --hash=sha256:71c767cf281a80d02b6c1bdc41c9468e1f5a494fb11bc8688c360524e273d7b1 \ - --hash=sha256:76e39058e68eb125de10c92524573924e827927df5d3891fbc97bd55764a8774 \ - --hash=sha256:7932f5f57609b6a3b82cc11877709aa7a98e3308983ed93552a1c377069b20c8 \ - --hash=sha256:7a3ae05b3d225b4155bda56b072ceb09d05e974bc74be6c3fc15463cf69f33fd \ - --hash=sha256:7ab327905cabb0622adca5971e488064e35115430cec2c35a50fd36e72a315b3 \ - --hash=sha256:7b2fe4150a0cf59f847a67db8c155ac36aed89080a6a639e9f16df5d6c6096f1 \ - --hash=sha256:7e806ca53acf6d15a888405880766ec84721aa4181261cd11a457dfe9a7a4975 \ - --hash=sha256:80aa4d79eb5564f2e0a6144fcc744b5a37c56c4a92d60920720e99210d88db0f \ - --hash=sha256:92497c78adf3ac703b57f1e3813c2d874f27f71a178f9ea5887855da413cd6d2 \ - --hash=sha256:96aff77af063b607f2489473484e39a0bbae730f2ea90c9e5606c9b73c44174a \ - --hash=sha256:aec9ab04e82918e623415947921dea15851b152b822661cce3f8e4393c3df683 \ - --hash=sha256:b066e8b50e28b503f604fa538adc764a638b38cf8e81e025011d26e8a627fa79 \ - --hash=sha256:b31c05dd84ef6871dd47120386aed35323c944d86c3d91a17c4b8d23df62f15b \ - --hash=sha256:bd59acd8529b372775cd0fcbc5f420ae20681c5b045ce25bd453ed8455ab99b5 \ - --hash=sha256:bfb2d1763d777de5ee495c85309460f6fd8146e50ec9d0ae0183dbf6f0a829d1 \ - --hash=sha256:c620051669fd04ac6b60ebc70478210119c56e2d5d5df848baec4312e260e4ca \ - --hash=sha256:c9f9d5e7a9310b7a2f416dd13d2e3fd8b42d803968ea580b7c0f322ccb389b97 \ - --hash=sha256:cb0feb07fe6e6a74615ee62a880007d976cf739b6669cce95daa7373d4fc69c5 \ - --hash=sha256:cc98b9c4e4870fa983436afa999d4eb16b12872fab7071423d5262fa7120d57a \ - --hash=sha256:d842c94b9155f1c9b3058036c24ffb8ff78b428414a19792b2380be9cecf4f36 \ - --hash=sha256:da19609432f353fed186cc1b85e9440db93d489f198b4bdf42ae19cc9d9ac9b4 \ - --hash=sha256:e0093bd1a06d899892427217f0ff2a3c8f306182b8c754336d32e2d587c131b4 \ - --hash=sha256:e2e7e882f83149f0a71ac822ebf156d902e7a5d22c9045e3e0d1daf59cee2cc9 \ - --hash=sha256:e84b51cbebf9ae573b5fbd15df88887815e3253fc000a7d0ff95170e8f7e9729 \ - --hash=sha256:ed6b402bc74d6557a705e197d47f9063733091ed6357b3de33619d8a8d93ac53 +greenlet==3.3.2 \ + --hash=sha256:02b0a8682aecd4d3c6c18edf52bc8e51eacdd75c8eac52a790a210b06aa295fd \ + --hash=sha256:18cb1b7337bca281915b3c5d5ae19f4e76d35e1df80f4ad3c1a7be91fadf1082 \ + --hash=sha256:1a9172f5bf6bd88e6ba5a84e0a68afeac9dc7b6b412b245dd64f52d83c81e55b \ + --hash=sha256:1e692b2dae4cc7077cbb11b47d258533b48c8fde69a33d0d8a82e2fe8d8531d5 \ + --hash=sha256:1ebd458fa8285960f382841da585e02201b53a5ec2bac6b156fc623b5ce4499f \ + --hash=sha256:1fb39a11ee2e4d94be9a76671482be9398560955c9e568550de0224e41104727 \ + --hash=sha256:20154044d9085151bc309e7689d6f7ba10027f8f5a8c0676ad398b951913d89e \ + --hash=sha256:2eaf067fc6d886931c7962e8c6bede15d2f01965560f3359b27c80bde2d151f2 \ + --hash=sha256:34308836d8370bddadb41f5a7ce96879b72e2fdfb4e87729330c6ab52376409f \ + --hash=sha256:394ead29063ee3515b4e775216cb756b2e3b4a7e55ae8fd884f17fa579e6b327 \ + --hash=sha256:3ceec72030dae6ac0c8ed7591b96b70410a8be370b6a477b1dbc072856ad02bd \ + --hash=sha256:4375a58e49522698d3e70cc0b801c19433021b5c37686f7ce9c65b0d5c8677d2 \ + --hash=sha256:43e99d1749147ac21dde49b99c9abffcbc1e2d55c67501465ef0930d6e78e070 \ + --hash=sha256:442b6057453c8cb29b4fb36a2ac689382fc71112273726e2423f7f17dc73bf99 \ + --hash=sha256:45abe8eb6339518180d5a7fa47fa01945414d7cca5ecb745346fc6a87d2750be \ + --hash=sha256:4c956a19350e2c37f2c48b336a3afb4bff120b36076d9d7fb68cb44e05d95b79 \ + --hash=sha256:508c7f01f1791fbc8e011bd508f6794cb95397fdb198a46cb6635eb5b78d85a7 \ + --hash=sha256:527fec58dc9f90efd594b9b700662ed3fb2493c2122067ac9c740d98080a620e \ + --hash=sha256:59b3e2c40f6706b05a9cd299c836c6aa2378cabe25d021acd80f13abf81181cf \ + --hash=sha256:5d0e35379f93a6d0222de929a25ab47b5eb35b5ef4721c2b9cbcc4036129ff1f \ + --hash=sha256:63d10328839d1973e5ba35e98cccbca71b232b14051fd957b6f8b6e8e80d0506 \ + --hash=sha256:64970c33a50551c7c50491671265d8954046cb6e8e2999aacdd60e439b70418a \ + --hash=sha256:6c6f8ba97d17a1e7d664151284cb3315fc5f8353e75221ed4324f84eb162b395 \ + --hash=sha256:8b466dff7a4ffda6ca975979bab80bdadde979e29fc947ac3be4451428d8b0e4 \ + --hash=sha256:8c1fdd7d1b309ff0da81d60a9688a8bd044ac4e18b250320a96fc68d31c209ca \ + --hash=sha256:8c4dd0f3997cf2512f7601563cc90dfb8957c0cff1e3a1b23991d4ea1776c492 \ + --hash=sha256:8d1658d7291f9859beed69a776c10822a0a799bc4bfe1bd4272bb60e62507dab \ + --hash=sha256:8e2cd90d413acbf5e77ae41e5d3c9b3ac1d011a756d7284d7f3f2b806bbd6358 \ + --hash=sha256:8e4ab3cfb02993c8cc248ea73d7dae6cec0253e9afa311c9b37e603ca9fad2ce \ + --hash=sha256:94ad81f0fd3c0c0681a018a976e5c2bd2ca2d9d94895f23e7bb1af4e8af4e2d5 \ + --hash=sha256:97245cc10e5515dbc8c3104b2928f7f02b6813002770cfaffaf9a6e0fc2b94ef \ + --hash=sha256:9bc885b89709d901859cf95179ec9f6bb67a3d2bb1f0e88456461bd4b7f8fd0d \ + --hash=sha256:a2a5be83a45ce6188c045bcc44b0ee037d6a518978de9a5d97438548b953a1ac \ + --hash=sha256:a443358b33c4ec7b05b79a7c8b466f5d275025e750298be7340f8fc63dff2a55 \ + --hash=sha256:a7945dd0eab63ded0a48e4dcade82939783c172290a7903ebde9e184333ca124 \ + --hash=sha256:aa6ac98bdfd716a749b84d4034486863fd81c3abde9aa3cf8eff9127981a4ae4 \ + --hash=sha256:ab0c7e7901a00bc0a7284907273dc165b32e0d109a6713babd04471327ff7986 \ + --hash=sha256:ac8d61d4343b799d1e526db579833d72f23759c71e07181c2d2944e429eb09cd \ + --hash=sha256:ad0c8917dd42a819fe77e6bdfcb84e3379c0de956469301d9fd36427a1ca501f \ + --hash=sha256:ae9e21c84035c490506c17002f5c8ab25f980205c3e61ddb3a2a2a2e6c411fcb \ + --hash=sha256:b26b0f4428b871a751968285a1ac9648944cea09807177ac639b030bddebcea4 \ + --hash=sha256:b568183cf65b94919be4438dc28416b234b678c608cafac8874dfeeb2a9bbe13 \ + --hash=sha256:b6997d360a4e6a4e936c0f9625b1c20416b8a0ea18a8e19cabbefc712e7397ab \ + --hash=sha256:b8bddc5b73c9720bea487b3bffdb1840fe4e3656fba3bd40aa1489e9f37877ff \ + --hash=sha256:c04c5e06ec3e022cbfe2cd4a846e1d4e50087444f875ff6d2c2ad8445495cf1a \ + --hash=sha256:c2e47408e8ce1c6f1ceea0dffcdf6ebb85cc09e55c7af407c99f1112016e45e9 \ + --hash=sha256:c56692189a7d1c7606cb794be0a8381470d95c57ce5be03fb3d0ef57c7853b86 \ + --hash=sha256:ccd21bb86944ca9be6d967cf7691e658e43417782bce90b5d2faeda0ff78a7dd \ + --hash=sha256:cd6f9e2bbd46321ba3bbb4c8a15794d32960e3b0ae2cc4d49a1a53d314805d71 \ + --hash=sha256:d248d8c23c67d2291ffd47af766e2a3aa9fa1c6703155c099feb11f526c63a92 \ + --hash=sha256:d3a62fa76a32b462a97198e4c9e99afb9ab375115e74e9a83ce180e7a496f643 \ + --hash=sha256:e26e72bec7ab387ac80caa7496e0f908ff954f31065b0ffc1f8ecb1338b11b54 \ + --hash=sha256:e3cb43ce200f59483eb82949bf1835a99cf43d7571e900d7c8d5c62cdf25d2f9 # via feast (pyproject.toml) -grpc-google-iam-v1==0.14.3 \ - --hash=sha256:7a7f697e017a067206a3dfef44e4c634a34d3dee135fe7d7a4613fe3e59217e6 \ - --hash=sha256:879ac4ef33136c5491a6300e27575a9ec760f6cdf9a2518798c1b8977a5dc389 +grpc-google-iam-v1==0.14.4 \ + --hash=sha256:392b3796947ed6334e61171d9ab06bf7eb357f554e5fc7556ad7aab6d0e17038 \ + --hash=sha256:412facc320fcbd94034b4df3d557662051d4d8adfa86e0ddb4dca70a3f739964 # via google-cloud-bigtable grpcio==1.62.3 \ --hash=sha256:059444f0ed5dba73ab7dd0ee7e8e6b606df4130d2b0a9f010f84da4ab9f6c2d8 \ @@ -1028,9 +1038,9 @@ grpcio-status==1.62.3 \ --hash=sha256:289bdd7b2459794a12cf95dc0cb727bd4a1742c37bd823f760236c937e53a485 \ --hash=sha256:f9049b762ba8de6b1086789d8315846e094edac2c50beaf462338b301a8fd4b8 # via google-api-core -gunicorn==25.1.0 \ - --hash=sha256:1426611d959fa77e7de89f8c0f32eed6aa03ee735f98c01efba3e281b1c47616 \ - --hash=sha256:d0b1236ccf27f72cfe14bce7caadf467186f19e865094ca84221424e839b8b8b +gunicorn==25.3.0 \ + --hash=sha256:cacea387dab08cd6776501621c295a904fe8e3b7aae9a1a3cbb26f4e7ed54660 \ + --hash=sha256:f74e1b2f9f76f6cd1ca01198968bd2dd65830edc24b6e8e4d78de8320e2fe889 # via # feast (pyproject.toml) # uvicorn-worker @@ -1048,9 +1058,9 @@ hatch-vcs==0.4.0 \ --hash=sha256:093810748fe01db0d451fabcf2c1ac2688caefd232d4ede967090b1c1b07d9f7 \ --hash=sha256:b8a2b6bee54cf6f9fc93762db73890017ae59c9081d1038a41f16235ceaf8b2c # via feast (pyproject.toml) -hatchling==1.28.0 \ - --hash=sha256:4d50b02aece6892b8cd0b3ce6c82cb218594d3ec5836dbde75bf41a21ab004c8 \ - --hash=sha256:dc48722b68b3f4bbfa3ff618ca07cdea6750e7d03481289ffa8be1521d18a961 +hatchling==1.29.0 \ + --hash=sha256:50af9343281f34785fab12da82e445ed987a6efb34fd8c2fc0f6e6630dbcc1b0 \ + --hash=sha256:793c31816d952cee405b83488ce001c719f325d9cda69f1fc4cd750527640ea6 # via # feast (pyproject.toml) # hatch-fancy-pypi-readme @@ -1223,9 +1233,9 @@ idna==3.11 \ # requests # snowflake-connector-python # yarl -imagesize==1.4.1 \ - --hash=sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b \ - --hash=sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a +imagesize==2.0.0 \ + --hash=sha256:5667c5bbb57ab3f1fa4bc366f4fbc971db3d5ed011fd2715fd8001f782718d96 \ + --hash=sha256:8e8358c4a05c304f1fccf7ff96f036e7243a189e9e42e90851993c558cfe9ee3 # via sphinx jinja2==3.1.6 \ --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ @@ -1254,97 +1264,97 @@ kubernetes==35.0.0 \ --hash=sha256:39e2b33b46e5834ef6c3985ebfe2047ab39135d41de51ce7641a7ca5b372a13d \ --hash=sha256:3d00d344944239821458b9efd484d6df9f011da367ecb155dadf9513f05f09ee # via feast (pyproject.toml) -librt==0.8.0 \ - --hash=sha256:001e5330093d887b8b9165823eca6c5c4db183fe4edea4fdc0680bbac5f46944 \ - --hash=sha256:015e2dde6e096d27c10238bf9f6492ba6c65822dfb69d2bf74c41a8e88b7ddef \ - --hash=sha256:02a9fe85410cc9bef045e7cb7fd26fdde6669e6d173f99df659aa7f6335961e9 \ - --hash=sha256:0583aef7e9a720dd40f26a2ad5a1bf2ccbb90059dac2b32ac516df232c701db3 \ - --hash=sha256:05a3dd3f116747f7e1a2b475ccdc6fb637fd4987126d109e03013a79d40bf9e6 \ - --hash=sha256:0a33335eb59921e77c9acc05d0e654e4e32e45b014a4d61517897c11591094f8 \ - --hash=sha256:0ce33a9778e294507f3a0e3468eccb6a698b5166df7db85661543eca1cfc5369 \ - --hash=sha256:1566dbb9d1eb0987264c9b9460d212e809ba908d2f4a3999383a84d765f2f3f1 \ - --hash=sha256:17269dd2745dbe8e42475acb28e419ad92dfa38214224b1b01020b8cac70b645 \ - --hash=sha256:178707cda89d910c3b28bf5aa5f69d3d4734e0f6ae102f753ad79edef83a83c7 \ - --hash=sha256:1c25a131013eadd3c600686a0c0333eb2896483cbc7f65baa6a7ee761017aef9 \ - --hash=sha256:1e6811cac1dcb27ca4c74e0ca4a5917a8e06db0d8408d30daee3a41724bfde7a \ - --hash=sha256:1ef3bd856373cf8e7382402731f43bfe978a8613b4039e49e166e1e0dc590216 \ - --hash=sha256:20f73d4fecba969efc15cdefd030e382502d56bb6f1fc66b580cce582836c9fa \ - --hash=sha256:21b14464bee0b604d80a638cf1ee3148d84ca4cc163dcdcecb46060c1b3605e4 \ - --hash=sha256:24a01c13a2a9bdad20997a4443ebe6e329df063d1978bbe2ebbf637878a46d1e \ - --hash=sha256:25b3e667cbfc9000c4740b282df599ebd91dbdcc1aa6785050e4c1d6be5329ab \ - --hash=sha256:25e82d920d4d62ad741592fcf8d0f3bda0e3fc388a184cb7d2f566c681c5f7b9 \ - --hash=sha256:2b37437e7e4ef5e15a297b36ba9e577f73e29564131d86dd75875705e97402b5 \ - --hash=sha256:2ccdd20d9a72c562ffb73098ac411de351b53a6fbb3390903b2d33078ef90447 \ - --hash=sha256:2e0ffe88ebb5962f8fb0ddcbaaff30f1ea06a79501069310e1e030eafb1ad787 \ - --hash=sha256:375eda7acfce1f15f5ed56cfc960669eefa1ec8732e3e9087c3c4c3f2066759c \ - --hash=sha256:3d2720335020219197380ccfa5c895f079ac364b4c429e96952cd6509934d8eb \ - --hash=sha256:3e36a8da17134ffc29373775d88c04832f9ecfab1880470661813e6c7991ef79 \ - --hash=sha256:3e8b77b5f54d0937b26512774916041756c9eb3e66f1031971e626eea49d0bf4 \ - --hash=sha256:41064a0c07b4cc7a81355ccc305cb097d6027002209ffca51306e65ee8293630 \ - --hash=sha256:421765e8c6b18e64d21c8ead315708a56fc24f44075059702e421d164575fdda \ - --hash=sha256:4831c44b8919e75ca0dfb52052897c1ef59fdae19d3589893fbd068f1e41afbf \ - --hash=sha256:48f84830a8f8ad7918afd743fd7c4eb558728bceab7b0e38fd5a5cf78206a556 \ - --hash=sha256:4b705f85311ee76acec5ee70806990a51f0deb519ea0c29c1d1652d79127604d \ - --hash=sha256:4d3e38797eb482485b486898f89415a6ab163bc291476bd95712e42cf4383c05 \ - --hash=sha256:4eb5e06ebcc668677ed6389164f52f13f71737fc8be471101fa8b4ce77baeb0c \ - --hash=sha256:4f6e975377fbc4c9567cb33ea9ab826031b6c7ec0515bfae66a4fb110d40d6da \ - --hash=sha256:4f764b2424cb04524ff7a486b9c391e93f93dc1bd8305b2136d25e582e99aa2f \ - --hash=sha256:507e94f4bec00b2f590fbe55f48cd518a208e2474a3b90a60aa8f29136ddbada \ - --hash=sha256:56901f1eec031396f230db71c59a01d450715cbbef9856bf636726994331195d \ - --hash=sha256:5cb11061a736a9db45e3c1293cfcb1e3caf205912dfa085734ba750f2197ff9a \ - --hash=sha256:5d0f76fc73480d42285c609c0ea74d79856c160fa828ff9aceab574ea4ecfd7b \ - --hash=sha256:667e2513cf69bfd1e1ed9a00d6c736d5108714ec071192afb737987955888a25 \ - --hash=sha256:671a6152edf3b924d98a5ed5e6982ec9cb30894085482acadce0975f031d4c5c \ - --hash=sha256:693697133c3b32aa9b27f040e3691be210e9ac4d905061859a9ed519b1d5a376 \ - --hash=sha256:6a3146c63220d814c4a2c7d6a1eacc8d5c14aed0ff85115c1dfea868080cd18f \ - --hash=sha256:6b6caff69e25d80c269b1952be8493b4d94ef745f438fa619d7931066bdd26de \ - --hash=sha256:6e1af31a710e17891d9adf0dbd9a5fcd94901a3922a96499abdbf7ce658f4e01 \ - --hash=sha256:70defb797c4d5402166787a6b3c66dfb3fa7f93d118c0509ffafa35a392f4258 \ - --hash=sha256:71fc517efc14f75c2f74b1f0a5d5eb4a8e06aa135c34d18eaf3522f4a53cd62d \ - --hash=sha256:75d1a8cab20b2043f03f7aab730551e9e440adc034d776f15f6f8d582b0a5ad4 \ - --hash=sha256:789911e8fa40a2e82f41120c936b1965f3213c67f5a483fc5a41f5839a05dcbb \ - --hash=sha256:7bd68cebf3131bb920d5984f75fe302d758db33264e44b45ad139385662d7bc3 \ - --hash=sha256:7ce0a8cb67e702dcb06342b2aaaa3da9fb0ddc670417879adfa088b44cf7b3b6 \ - --hash=sha256:7f820210e21e3a8bf8fde2ae3c3d10106d4de9ead28cbfdf6d0f0f41f5b12fa1 \ - --hash=sha256:8070aa3368559de81061ef752770d03ca1f5fc9467d4d512d405bd0483bfffe6 \ - --hash=sha256:82e61cd1c563745ad495387c3b65806bfd453badb4adbc019df3389dddee1bf6 \ - --hash=sha256:82fb4602d1b3e303a58bfe6165992b5a78d823ec646445356c332cd5f5bbaa61 \ - --hash=sha256:88c6e75540f1f10f5e0fc5e87b4b6c290f0e90d1db8c6734f670840494764af8 \ - --hash=sha256:8992ca186a1678107b0af3d0c9303d8c7305981b9914989b9788319ed4d89546 \ - --hash=sha256:92249938ab744a5890580d3cb2b22042f0dce71cdaa7c1369823df62bedf7cbc \ - --hash=sha256:95a719a049f0eefaf1952673223cf00d442952273cbd20cf2ed7ec423a0ef58d \ - --hash=sha256:9646178cd794704d722306c2c920c221abbf080fede3ba539d5afdec16c46dad \ - --hash=sha256:9726305d3e53419d27fc8cdfcd3f9571f0ceae22fa6b5ea1b3662c2e538f833e \ - --hash=sha256:995d24caa6bbb34bcdd4a41df98ac6d1af637cfa8975cb0790e47d6623e70e3e \ - --hash=sha256:9ab3a3475a55b89b87ffd7e6665838e8458e0b596c22e0177e0f961434ec474a \ - --hash=sha256:9f09d4884f882baa39a7e36bbf3eae124c4ca2a223efb91e567381d1c55c6b06 \ - --hash=sha256:a512c88900bdb1d448882f5623a0b1ad27ba81a9bd75dacfe17080b72272ca1f \ - --hash=sha256:a905091a13e0884701226860836d0386b88c72ce5c2fdfba6618e14c72be9f25 \ - --hash=sha256:aaadec87f45a3612b6818d1db5fbfe93630669b7ee5d6bdb6427ae08a1aa2141 \ - --hash=sha256:b055bb3abaf69abed25743d8fc1ab691e4f51a912ee0a6f9a6c84f4bbddb283d \ - --hash=sha256:b4bb00bd71b448f16749909b08a0ff16f58b079e2261c2e1000f2bbb2a4f0a45 \ - --hash=sha256:b9aef96d7593584e31ef6ac1eb9775355b0099fee7651fae3a15bc8657b67b52 \ - --hash=sha256:ba581acad5ac8f33e2ff1746e8a57e001b47c6721873121bf8bbcf7ba8bd3aa4 \ - --hash=sha256:ba9d9e60651615bc614be5e21a82cdb7b1769a029369cf4b4d861e4f19686fb6 \ - --hash=sha256:bbebd2bba5c6ae02907df49150e55870fdd7440d727b6192c46b6f754723dde9 \ - --hash=sha256:bd32add59b58fba3439d48d6f36ac695830388e3da3e92e4fc26d2d02670d19c \ - --hash=sha256:bdab762e2c0b48bab76f1a08acb3f4c77afd2123bedac59446aeaaeed3d086cf \ - --hash=sha256:c5512aae4648152abaf4d48b59890503fcbe86e85abc12fb9b096fe948bdd816 \ - --hash=sha256:c6e4c10761ddbc0d67d2f6e2753daf99908db85d8b901729bf2bf5eaa60e0567 \ - --hash=sha256:cb4b3ad543084ed79f186741470b251b9d269cd8b03556f15a8d1a99a64b7de5 \ - --hash=sha256:cb74cdcbc0103fc988e04e5c58b0b31e8e5dd2babb9182b6f9490488eb36324b \ - --hash=sha256:cc3d107f603b5ee7a79b6aa6f166551b99b32fb4a5303c4dfcb4222fc6a0335e \ - --hash=sha256:d920789eca7ef71df7f31fd547ec0d3002e04d77f30ba6881e08a630e7b2c30e \ - --hash=sha256:daae5e955764be8fd70a93e9e5133c75297f8bce1e802e1d3683b98f77e1c5ab \ - --hash=sha256:db63cf3586a24241e89ca1ce0b56baaec9d371a328bd186c529b27c914c9a1ef \ - --hash=sha256:db953b675079884ffda33d1dca7189fb961b6d372153750beb81880384300817 \ - --hash=sha256:de076eaba208d16efb5962f99539867f8e2c73480988cb513fcf1b5dbb0c9dcf \ - --hash=sha256:e79dbc8f57de360f0ed987dc7de7be814b4803ef0e8fc6d3ff86e16798c99935 \ - --hash=sha256:e9a3a38eb4134ad33122a6d575e6324831f930a771d951a15ce232e0237412c2 \ - --hash=sha256:f04ca50e847abc486fa8f4107250566441e693779a5374ba211e96e238f298b9 \ - --hash=sha256:f1178e0de0c271231a660fbef9be6acdfa1d596803464706862bef6644cc1cae \ - --hash=sha256:f4617cef654fca552f00ce5ffdf4f4b68770f18950e4246ce94629b789b92467 \ - --hash=sha256:fa37f99bff354ff191c6bcdffbc9d7cdd4fc37faccfc9be0ef3a4fd5613977da +librt==0.8.1 \ + --hash=sha256:01170b6729a438f0dedc4a26ed342e3dc4f02d1000b4b19f980e1877f0c297e6 \ + --hash=sha256:039b9f2c506bd0ab0f8725aa5ba339c6f0cd19d3b514b50d134789809c24285d \ + --hash=sha256:05bd41cdee35b0c59c259f870f6da532a2c5ca57db95b5f23689fcb5c9e42440 \ + --hash=sha256:086a32dbb71336627e78cc1d6ee305a68d038ef7d4c39aaff41ae8c9aa46e91a \ + --hash=sha256:08eec3a1fc435f0d09c87b6bf1ec798986a3544f446b864e4099633a56fcd9ed \ + --hash=sha256:0bf69d79a23f4f40b8673a947a234baeeb133b5078b483b7297c5916539cf5d5 \ + --hash=sha256:0c3811485fccfda840861905b8c70bba5ec094e02825598bb9d4ca3936857a04 \ + --hash=sha256:0d2f82168e55ddefd27c01c654ce52379c0750ddc31ee86b4b266bcf4d65f2a3 \ + --hash=sha256:0f2ae3725904f7377e11cc37722d5d401e8b3d5851fb9273d7f4fe04f6b3d37d \ + --hash=sha256:10c42e1f6fd06733ef65ae7bebce2872bcafd8d6e6b0a08fe0a05a23b044fb14 \ + --hash=sha256:153188fe98a72f206042be10a2c6026139852805215ed9539186312d50a8e972 \ + --hash=sha256:172d57ec04346b047ca6af181e1ea4858086c80bdf455f61994c4aa6fc3f866c \ + --hash=sha256:190b109bb69592a3401fe1ffdea41a2e73370ace2ffdc4a0e8e2b39cdea81b78 \ + --hash=sha256:1d3a7da44baf692f0c6aeb5b2a09c5e6fc7a703bca9ffa337ddd2e2da53f7732 \ + --hash=sha256:228c2409c079f8c11fb2e5d7b277077f694cb93443eb760e00b3b83cb8b3176c \ + --hash=sha256:22b46eabd76c1986ee7d231b0765ad387d7673bbd996aa0d0d054b38ac65d8f6 \ + --hash=sha256:237796479f4d0637d6b9cbcb926ff424a97735e68ade6facf402df4ec93375ed \ + --hash=sha256:2c74a2da57a094bd48d03fa5d196da83d2815678385d2978657499063709abe1 \ + --hash=sha256:2cc68eeeef5e906839c7bb0815748b5b0a974ec27125beefc0f942715785b551 \ + --hash=sha256:2eb345e8b33fb748227409c9f1233d4df354d6e54091f0e8fc53acdb2ffedeb7 \ + --hash=sha256:31362dbfe297b23590530007062c32c6f6176f6099646bb2c95ab1b00a57c382 \ + --hash=sha256:3dff3d3ca8db20e783b1bc7de49c0a2ab0b8387f31236d6a026597d07fcd68ac \ + --hash=sha256:43353b943613c5d9c49a25aaffdba46f888ec354e71e3529a00cca3f04d66a7a \ + --hash=sha256:439352ba9373f11cb8e1933da194dcc6206daf779ff8df0ed69c5e39113e6a99 \ + --hash=sha256:4998009e7cb9e896569f4be7004f09d0ed70d386fa99d42b6d363f6d200501ac \ + --hash=sha256:4be2a5c926b9770c9e08e717f05737a269b9d0ebc5d2f0060f0fe3fe9ce47acb \ + --hash=sha256:4beb04b8c66c6ae62f8c1e0b2f097c1ebad9295c929a8d5286c05eae7c2fc7dc \ + --hash=sha256:4c8dfa264b9193c4ee19113c985c95f876fae5e51f731494fc4e0cf594990ba7 \ + --hash=sha256:5212a5bd7fae98dae95710032902edcd2ec4dc994e883294f75c857b83f9aba0 \ + --hash=sha256:52c224e14614b750c0a6d97368e16804a98c684657c7518752c356834fff83bb \ + --hash=sha256:56e04c14b696300d47b3bc5f1d10a00e86ae978886d0cee14e5714fafb5df5d2 \ + --hash=sha256:5bb54f1205a3a6ab41a6fd71dfcdcbd278670d3a90ca502a30d9da583105b6f7 \ + --hash=sha256:5cdc0f588ff4b663ea96c26d2a230c525c6fc62b28314edaaaca8ed5af931ad0 \ + --hash=sha256:5db05697c82b3a2ec53f6e72b2ed373132b0c2e05135f0696784e97d7f5d48e7 \ + --hash=sha256:5e4af413908f77294605e28cfd98063f54b2c790561383971d2f52d113d9c363 \ + --hash=sha256:5fc48998000cbc39ec0d5311312dda93ecf92b39aaf184c5e817d5d440b29624 \ + --hash=sha256:60a78b694c9aee2a0f1aaeaa7d101cf713e92e8423a941d2897f4fa37908dab9 \ + --hash=sha256:64548cde61b692dc0dc379f4b5f59a2f582c2ebe7890d09c1ae3b9e66fa015b7 \ + --hash=sha256:681dc2451d6d846794a828c16c22dc452d924e9f700a485b7ecb887a30aad1fd \ + --hash=sha256:6b1977c4ea97ce5eb7755a78fae68d87e4102e4aaf54985e8b56806849cc06a3 \ + --hash=sha256:6cfa7fe54fd4d1f47130017351a959fe5804bda7a0bc7e07a2cdbc3fdd28d34f \ + --hash=sha256:738f08021b3142c2918c03692608baed43bc51144c29e35807682f8070ee2a3a \ + --hash=sha256:747328be0c5b7075cde86a0e09d7a9196029800ba75a1689332348e998fb85c0 \ + --hash=sha256:758509ea3f1eba2a57558e7e98f4659d0ea7670bff49673b0dde18a3c7e6c0eb \ + --hash=sha256:785ae29c1f5c6e7c2cde2c7c0e148147f4503da3abc5d44d482068da5322fd9e \ + --hash=sha256:7aae78ab5e3206181780e56912d1b9bb9f90a7249ce12f0e8bf531d0462dd0fc \ + --hash=sha256:7b02679a0d783bdae30d443025b94465d8c3dc512f32f5b5031f93f57ac32071 \ + --hash=sha256:7e2f3edca35664499fbb36e4770650c4bd4a08abc1f4458eab9df4ec56389730 \ + --hash=sha256:7e6bad1cd94f6764e1e21950542f818a09316645337fd5ab9a7acc45d99a8f35 \ + --hash=sha256:81fd938344fecb9373ba1b155968c8a329491d2ce38e7ddb76f30ffb938f12dc \ + --hash=sha256:82210adabbc331dbb65d7868b105185464ef13f56f7f76688565ad79f648b0fe \ + --hash=sha256:89815a22daf9c51884fb5dbe4f1ef65ee6a146e0b6a8df05f753e2e4a9359bf4 \ + --hash=sha256:8f1125e6bbf2f1657d9a2f3ccc4a2c9b0c8b176965bb565dd4d86be67eddb4b6 \ + --hash=sha256:8f4bb453f408137d7581be309b2fbc6868a80e7ef60c88e689078ee3a296ae71 \ + --hash=sha256:924817ab3141aca17893386ee13261f1d100d1ef410d70afe4389f2359fea4f0 \ + --hash=sha256:93c2af9e01e0ef80d95ae3c720be101227edae5f2fe7e3dc63d8857fadfc5a1d \ + --hash=sha256:97c2b54ff6717a7a563b72627990bec60d8029df17df423f0ed37d56a17a176b \ + --hash=sha256:9be2f15e53ce4e83cc08adc29b26fb5978db62ef2a366fbdf716c8a6c8901040 \ + --hash=sha256:9e2c6f77b9ad48ce5603b83b7da9ee3e36b3ab425353f695cba13200c5d96596 \ + --hash=sha256:a28f2612ab566b17f3698b0da021ff9960610301607c9a5e8eaca62f5e1c350a \ + --hash=sha256:a355d99c4c0d8e5b770313b8b247411ed40949ca44e33e46a4789b9293a907ee \ + --hash=sha256:a3b4350b13cc0e6f5bec8fa7caf29a8fb8cdc051a3bae45cfbfd7ce64f009965 \ + --hash=sha256:aaab0e307e344cb28d800957ef3ec16605146ef0e59e059a60a176d19543d1b7 \ + --hash=sha256:ac1e7817fd0ed3d14fd7c5df91daed84c48e4c2a11ee99c0547f9f62fdae13da \ + --hash=sha256:adfab487facf03f0d0857b8710cf82d0704a309d8ffc33b03d9302b4c64e91a9 \ + --hash=sha256:b6d7ab1f01aa753188605b09a51faa44a3327400b00b8cce424c71910fc0a128 \ + --hash=sha256:bacdb58d9939d95cc557b4dbaa86527c9db2ac1ed76a18bc8d26f6dc8647d851 \ + --hash=sha256:be46a14693955b3bd96014ccbdb8339ee8c9346fbe11c1b78901b55125f14c73 \ + --hash=sha256:bf512a71a23504ed08103a13c941f763db13fb11177beb3d9244c98c29fb4a61 \ + --hash=sha256:c00e5c884f528c9932d278d5c9cbbea38a6b81eb62c02e06ae53751a83a4d52b \ + --hash=sha256:c25d9e338d5bed46c1632f851babf3d13c78f49a225462017cf5e11e845c5891 \ + --hash=sha256:c336d61d2fe74a3195edc1646d53ff1cddd3a9600b09fa6ab75e5514ba4862a7 \ + --hash=sha256:cc3656283d11540ab0ea01978378e73e10002145117055e03722417aeab30994 \ + --hash=sha256:cf450f498c30af55551ba4f66b9123b7185362ec8b625a773b3d39aa1a717583 \ + --hash=sha256:d0ee06b5b5291f609ddb37b9750985b27bc567791bc87c76a569b3feed8481ac \ + --hash=sha256:d480de377f5b687b6b1bc0c0407426da556e2a757633cc7e4d2e1a057aa688f3 \ + --hash=sha256:d56bc4011975f7460bea7b33e1ff425d2f1adf419935ff6707273c77f8a4ada6 \ + --hash=sha256:dd3c41254ee98604b08bd5b3af5bf0a89740d4ee0711de95b65166bf44091921 \ + --hash=sha256:e0d138c7ae532908cbb342162b2611dbd4d90c941cd25ab82084aaf71d2c0bd0 \ + --hash=sha256:e11769a1dbda4da7b00a76cfffa67aa47cfa66921d2724539eee4b9ede780b79 \ + --hash=sha256:e3f0a41487fd5fad7e760b9e8a90e251e27c2816fbc2cff36a22a0e6bcbbd9dd \ + --hash=sha256:e692aa2d1d604e6ca12d35e51fdc36f4cda6345e28e36374579f7ef3611b3012 \ + --hash=sha256:e70a57ecf89a0f64c24e37f38d3fe217a58169d2fe6ed6d70554964042474023 \ + --hash=sha256:e96baa6820280077a78244b2e06e416480ed859bbd8e5d641cf5742919d8beb4 \ + --hash=sha256:eb5656019db7c4deacf0c1a55a898c5bb8f989be904597fcb5232a2f4828fa05 \ + --hash=sha256:eca45e982fa074090057132e30585a7e8674e9e885d402eae85633e9f449ce6c \ + --hash=sha256:f0af2bd2bc204fa27f3d6711d0f360e6b8c684a035206257a81673ab924aa11e \ + --hash=sha256:f7cdf7f26c2286ffb02e46d7bac56c94655540b26347673bea15fa52a6af17e9 \ + --hash=sha256:fd1a720332ea335ceb544cf0a03f81df92abd4bb887679fd1e460976b0e6214b \ + --hash=sha256:ff8baf1f8d3f4b6b7257fcb75a501f2a5499d0dda57645baa09d4d0d34b19444 # via mypy locket==1.0.0 \ --hash=sha256:5c0d4c052a8bbbf750e056a8e65ccd309086f4f0f18a2eac306a8dfa4112a632 \ @@ -1445,9 +1455,9 @@ markupsafe==3.0.3 \ --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \ --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50 # via jinja2 -mcp==1.26.0 \ - --hash=sha256:904a21c33c25aa98ddbeb47273033c435e595bbacfdb177f4bd87f6dceebe1ca \ - --hash=sha256:db6e2ef491eecc1a0d93711a76f28dec2e05999f93afd48795da1c1137142c66 +mcp==1.27.0 \ + --hash=sha256:5ce1fa81614958e267b21fb2aa34e0aea8e2c6ede60d52aba45fd47246b4d741 \ + --hash=sha256:d3dc35a7eec0d458c1da4976a48f982097ddaab87e278c5511d5a4a56e852b83 # via fastapi-mcp mdurl==0.1.2 \ --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ @@ -1463,128 +1473,114 @@ meson-python==0.15.0 \ --hash=sha256:3ae38253ff02b2e947a05e362a2eaf5a9a09d133c5666b4123399ee5fbf2e591 \ --hash=sha256:fddb73eecd49e89c1c41c87937cd89c2d0b65a1c63ba28238681d4bd9484d26f # via feast (pyproject.toml) -mmh3==5.2.0 \ - --hash=sha256:03e08c6ebaf666ec1e3d6ea657a2d363bb01effd1a9acfe41f9197decaef0051 \ - --hash=sha256:097e13c8b8a66c5753c6968b7640faefe85d8e38992703c1f666eda6ef4c3762 \ - --hash=sha256:0b898cecff57442724a0f52bf42c2de42de63083a91008fb452887e372f9c328 \ - --hash=sha256:10983c10f5c77683bd845751905ba535ec47409874acc759d5ce3ff7ef34398a \ - --hash=sha256:11730eeb16dfcf9674fdea9bb6b8e6dd9b40813b7eb839bc35113649eef38aeb \ - --hash=sha256:127c95336f2a98c51e7682341ab7cb0be3adb9df0819ab8505a726ed1801876d \ - --hash=sha256:12da42c0a55c9d86ab566395324213c319c73ecb0c239fad4726324212b9441c \ - --hash=sha256:132dd943451a7c7546978863d2f5a64977928410782e1a87d583cb60eb89e667 \ - --hash=sha256:1556e31e4bd0ac0c17eaf220be17a09c171d7396919c3794274cb3415a9d3646 \ - --hash=sha256:1a5f4d2e59d6bba8ef01b013c472741835ad961e7c28f50c82b27c57748744a4 \ - --hash=sha256:1ba55d6ca32eeef8b2625e1e4bfc3b3db52bc63014bd7e5df8cc11bf2b036b12 \ - --hash=sha256:1efc8fec8478e9243a78bb993422cf79f8ff85cb4cf6b79647480a31e0d950a8 \ - --hash=sha256:1f8d8b627799f4e2fcc7c034fed8f5f24dc7724ff52f69838a3d6d15f1ad4765 \ - --hash=sha256:1fae471339ae1b9c641f19cf46dfe6ffd7f64b1fba7c4333b99fa3dd7f21ae0a \ - --hash=sha256:1fdb36b940e9261aff0b5177c5b74a36936b902f473180f6c15bde26143681a9 \ - --hash=sha256:2421b9d665a0b1ad724ec7332fb5a98d075f50bc51a6ff854f3a1882bd650d49 \ - --hash=sha256:29c2b9ce61886809d0492a274a5a53047742dea0f703f9c4d5d223c3ea6377d3 \ - --hash=sha256:2c9da0d568569cc87315cb063486d761e38458b8ad513fedd3dc9263e1b81bcd \ - --hash=sha256:2ebfc46b39168ab1cd44670a32ea5489bcbc74a25795c61b6d888c5c2cf654ed \ - --hash=sha256:3193752fc05ea72366c2b63ff24b9a190f422e32d75fdeae71087c08fff26115 \ - --hash=sha256:33576136c06b46a7046b6d83a3d75fbca7d25f84cec743f1ae156362608dc6d2 \ - --hash=sha256:37a358cc881fe796e099c1db6ce07ff757f088827b4e8467ac52b7a7ffdca647 \ - --hash=sha256:382a6bb3f8c6532ea084e7acc5be6ae0c6effa529240836d59352398f002e3fc \ - --hash=sha256:384eda9361a7bf83a85e09447e1feafe081034af9dd428893701b959230d84be \ - --hash=sha256:38d899a156549da8ef6a9f1d6f7ef231228d29f8f69bce2ee12f5fba6d6fd7c5 \ - --hash=sha256:3bc244802ccab5220008cb712ca1508cb6a12f0eb64ad62997156410579a1770 \ - --hash=sha256:3c6041fd9d5fb5fcac57d5c80f521a36b74aea06b8566431c63e4ffc49aced51 \ - --hash=sha256:3ca975c51c5028947bbcfc24966517aac06a01d6c921e30f7c5383c195f87991 \ - --hash=sha256:3d6bfd9662a20c054bc216f861fa330c2dac7c81e7fb8307b5e32ab5b9b4d2e0 \ - --hash=sha256:419005f84ba1cab47a77465a2a843562dadadd6671b8758bf179d82a15ca63eb \ - --hash=sha256:45b590e31bc552c6f8e2150ff1ad0c28dd151e9f87589e7eaf508fbdd8e8e908 \ - --hash=sha256:49037d417419863b222ae47ee562b2de9c3416add0a45c8d7f4e864be8dc4f89 \ - --hash=sha256:4a5f5536b1cbfa72318ab3bfc8a8188b949260baed186b75f0abc75b95d8c051 \ - --hash=sha256:582f9dbeefe15c32a5fa528b79b088b599a1dfe290a4436351c6090f90ddebb8 \ - --hash=sha256:58477cf9ef16664d1ce2b038f87d2dc96d70fe50733a34a7f07da6c9a5e3538c \ - --hash=sha256:58981d6ea9646dbbf9e59a30890cbf9f610df0e4a57dbfe09215116fd90b0093 \ - --hash=sha256:5a5dba98e514fb26241868f6eb90a7f7ca0e039aed779342965ce24ea32ba513 \ - --hash=sha256:5b0b58215befe0f0e120b828f7645e97719bbba9f23b69e268ed0ac7adde8645 \ - --hash=sha256:61ac226af521a572700f863d6ecddc6ece97220ce7174e311948ff8c8919a363 \ - --hash=sha256:63830f846797187c5d3e2dae50f0848fdc86032f5bfdc58ae352f02f857e9025 \ - --hash=sha256:69fc339d7202bea69ef9bd7c39bfdf9fdabc8e6822a01eba62fb43233c1b3932 \ - --hash=sha256:6d541038b3fc360ec538fc116de87462627944765a6750308118f8b509a8eec7 \ - --hash=sha256:6ecb4e750d712abde046858ee6992b65c93f1f71b397fce7975c3860c07365d2 \ - --hash=sha256:72d80005b7634a3a2220f81fbeb94775ebd12794623bb2e1451701ea732b4aa3 \ - --hash=sha256:7303aab41e97adcf010a09efd8f1403e719e59b7705d5e3cfed3dd7571589290 \ - --hash=sha256:7434a27754049144539d2099a6d2da5d88b8bdeedf935180bf42ad59b3607aa3 \ - --hash=sha256:746a5ee71c6d1103d9b560fa147881b5e68fd35da56e54e03d5acefad0e7c055 \ - --hash=sha256:7733ec52296fc1ba22e9b90a245c821adbb943e98c91d8a330a2254612726106 \ - --hash=sha256:7901c893e704ee3c65f92d39b951f8f34ccf8e8566768c58103fb10e55afb8c1 \ - --hash=sha256:7aa18cdb58983ee660c9c400b46272e14fa253c675ed963d3812487f8ca42037 \ - --hash=sha256:7b986d506a8e8ea345791897ba5d8ba0d9d8820cd4fc3e52dbe6de19388de2e7 \ - --hash=sha256:7bbb0df897944b5ec830f3ad883e32c5a7375370a521565f5fe24443bfb2c4f7 \ - --hash=sha256:7c7f0b342fd06044bedd0b6e72177ddc0076f54fd89ee239447f8b271d919d9b \ - --hash=sha256:7e5634565367b6d98dc4aa2983703526ef556b3688ba3065edb4b9b90ede1c54 \ - --hash=sha256:7fddccd4113e7b736706e17a239a696332360cbaddf25ae75b57ba1acce65081 \ - --hash=sha256:81c504ad11c588c8629536b032940f2a359dda3b6cbfd4ad8f74cb24dcd1b0bc \ - --hash=sha256:81df0dae22cd0da87f1c978602750f33d17fb3d21fb0f326c89dc89834fea79b \ - --hash=sha256:86d1be5d63232e6eb93c50881aea55ff06eb86d8e08f9b5417c8c9b10db9db96 \ - --hash=sha256:8b0c53fe0994beade1ad7c0f13bd6fec980a0664bfbe5a6a7d64500b9ab76772 \ - --hash=sha256:8ebf241072cf2777a492d0e09252f8cc2b3edd07dfdb9404b9757bffeb4f2cee \ - --hash=sha256:931d47e08c9c8a67bf75d82f0ada8399eac18b03388818b62bfa42882d571d72 \ - --hash=sha256:932a6eec1d2e2c3c9e630d10f7128d80e70e2d47fe6b8c7ea5e1afbd98733e65 \ - --hash=sha256:941603bfd75a46023807511c1ac2f1b0f39cccc393c15039969806063b27e6db \ - --hash=sha256:956127e663d05edbeec54df38885d943dfa27406594c411139690485128525de \ - --hash=sha256:96f1e1ac44cbb42bcc406e509f70c9af42c594e72ccc7b1257f97554204445f0 \ - --hash=sha256:99bb6a4d809aa4e528ddfe2c85dd5239b78b9dd14be62cca0329db78505e7b50 \ - --hash=sha256:9f64bf06f4bf623325fda3a6d02d36cd69199b9ace99b04bb2d7fd9f89688504 \ - --hash=sha256:a094319ec0db52a04af9fdc391b4d39a1bc72bc8424b47c4411afb05413a44b5 \ - --hash=sha256:a367d4741ac0103f8198c82f429bccb9359f543ca542b06a51f4f0332e8de279 \ - --hash=sha256:a7c0c7845566b9686480e6a7e9044db4afb60038d5fabd19227443f0104eeee4 \ - --hash=sha256:aa6e5d31fdc5ed9e3e95f9873508615a778fe9b523d52c17fc770a3eb39ab6e4 \ - --hash=sha256:ae9d032488fcec32d22be6542d1a836f00247f40f320844dbb361393b5b22773 \ - --hash=sha256:b0271ac12415afd3171ab9a3c7cbfc71dee2c68760a7dc9d05bf8ed6ddfa3a7a \ - --hash=sha256:b0d753ad566c721faa33db7e2e0eddd74b224cdd3eaf8481d76c926603c7a00e \ - --hash=sha256:b29044e1ffdb84fe164d0a7ea05c7316afea93c00f8ed9449cf357c36fc4f814 \ - --hash=sha256:b5995088dd7023d2d9f310a0c67de5a2b2e06a570ecfd00f9ff4ab94a67cde43 \ - --hash=sha256:b5f317a727bba0e633a12e71228bc6a4acb4f471a98b1c003163b917311ea9a9 \ - --hash=sha256:b9a87025121d1c448f24f27ff53a5fe7b6ef980574b4a4f11acaabe702420d63 \ - --hash=sha256:bb0fdc451fb6d86d81ab8f23d881b8d6e37fc373a2deae1c02d27002d2ad7a05 \ - --hash=sha256:bb4fe46bdc6104fbc28db7a6bacb115ee6368ff993366bbd8a2a7f0076e6f0c0 \ - --hash=sha256:bc44fc2b886243d7c0d8daeb37864e16f232e5b56aaec27cc781d848264cfd28 \ - --hash=sha256:bdde97310d59604f2a9119322f61b31546748499a21b44f6715e8ced9308a6c5 \ - --hash=sha256:be1374df449465c9f2500e62eee73a39db62152a8bdfbe12ec5b5c1cd451344d \ - --hash=sha256:be7d3dca9358e01dab1bad881fb2b4e8730cec58d36dd44482bc068bfcd3bc65 \ - --hash=sha256:bf7bee43e17e81671c447e9c83499f53d99bf440bc6d9dc26a841e21acfbe094 \ - --hash=sha256:c3dca4cb5b946ee91b3d6bb700d137b1cd85c20827f89fdf9c16258253489044 \ - --hash=sha256:c3f563e8901960e2eaa64c8e8821895818acabeb41c96f2efbb936f65dbe486c \ - --hash=sha256:c463d7c1c4cfc9d751efeaadd936bbba07b5b0ed81a012b3a9f5a12f0872bd6e \ - --hash=sha256:c4a2f3d83879e3de2eb8cbf562e71563a8ed15ee9b9c2e77ca5d9f73072ac15c \ - --hash=sha256:c5584061fd3da584659b13587f26c6cad25a096246a481636d64375d0c1f6c07 \ - --hash=sha256:c677d78887244bf3095020b73c42b505b700f801c690f8eaa90ad12d3179612f \ - --hash=sha256:c903e71fd8debb35ad2a4184c1316b3cb22f64ce517b4e6747f25b0a34e41266 \ - --hash=sha256:c9ff37ba9f15637e424c2ab57a1a590c52897c845b768e4e0a4958084ec87f22 \ - --hash=sha256:cadc16e8ea64b5d9a47363013e2bea469e121e6e7cb416a7593aeb24f2ad122e \ - --hash=sha256:cedac4f4054b8f7859e5aed41aaa31ad03fce6851901a7fdc2af0275ac533c10 \ - --hash=sha256:d22c9dcafed659fadc605538946c041722b6d1104fe619dbf5cc73b3c8a0ded8 \ - --hash=sha256:d765058da196f68dc721116cab335e696e87e76720e6ef8ee5a24801af65e63d \ - --hash=sha256:d86651fa45799530885ba4dab3d21144486ed15285e8784181a0ab37a4552384 \ - --hash=sha256:dd966df3489ec13848d6c6303429bbace94a153f43d1ae2a55115fd36fd5ca5d \ - --hash=sha256:ddc63328889bcaee77b743309e5c7d2d52cee0d7d577837c91b6e7cc9e755e0b \ - --hash=sha256:dfbead5575f6470c17e955b94f92d62a03dfc3d07f2e6f817d9b93dc211a1515 \ - --hash=sha256:e0f3ed828d709f5b82d8bfe14f8856120718ec4bd44a5b26102c3030a1e12501 \ - --hash=sha256:e1861fb6b1d0453ed7293200139c0a9011eeb1376632e048e3766945b13313c5 \ - --hash=sha256:e5015f0bb6eb50008bed2d4b1ce0f2a294698a926111e4bb202c0987b4f89078 \ - --hash=sha256:e651e17bfde5840e9e4174b01e9e080ce49277b70d424308b36a7969d0d1af73 \ - --hash=sha256:e7884931fe5e788163e7b3c511614130c2c59feffdc21112290a194487efb2e9 \ - --hash=sha256:e79c00eba78f7258e5b354eccd4d7907d60317ced924ea4a5f2e9d83f5453065 \ - --hash=sha256:e912b19cf2378f2967d0c08e86ff4c6c360129887f678e27e4dde970d21b3f4d \ - --hash=sha256:e9a011469b47b752e7d20de296bb34591cdfcbe76c99c2e863ceaa2aa61113d2 \ - --hash=sha256:eb756caf8975882630ce4e9fbbeb9d3401242a72528230422c9ab3a0d278e60c \ - --hash=sha256:eba01ec3bd4a49b9ac5ca2bc6a73ff5f3af53374b8556fcc2966dd2af9eb7779 \ - --hash=sha256:ecbfc0437ddfdced5e7822d1ce4855c9c64f46819d0fdc4482c53f56c707b935 \ - --hash=sha256:eed4bba7ff8a0d37106ba931ab03bdd3915fbb025bcf4e1f0aa02bc8114960c5 \ - --hash=sha256:f35727c5118aba95f0397e18a1a5b8405425581bfe53e821f0fb444cbdc2bc9b \ - --hash=sha256:f698733a8a494466432d611a8f0d1e026f5286dee051beea4b3c3146817e35d5 \ - --hash=sha256:f7f9034c7cf05ddfaac8d7a2e63a3c97a840d4615d0a0e65ba8bdf6f8576e3be \ - --hash=sha256:fa0c966ee727aad5406d516375593c5f058c766b21236ab8985693934bb5085b \ - --hash=sha256:fc9c5f280438cf1c1a8f9abb87dc8ce9630a964120cfb5dd50d1e7ce79690c7a \ - --hash=sha256:fd6e6c3d90660d085f7e73710eab6f5545d4854b81b0135a3526e797009dbda3 \ - --hash=sha256:fdfd3fb739f4e22746e13ad7ba0c6eedf5f454b18d11249724a388868e308ee4 \ - --hash=sha256:ff3d50dc3fe8a98059f99b445dfb62792b5d006c5e0b8f03c6de2813b8376110 +mmh3==5.2.1 \ + --hash=sha256:022aa1a528604e6c83d0a7705fdef0b5355d897a9e0fa3a8d26709ceaa06965d \ + --hash=sha256:0634581290e6714c068f4aa24020acf7880927d1f0084fa753d9799ae9610082 \ + --hash=sha256:08043f7cb1fb9467c3fbbbaea7896986e7fbc81f4d3fd9289a73d9110ab6207a \ + --hash=sha256:0a3984146e414684a6be2862d84fcb1035f4984851cb81b26d933bab6119bf00 \ + --hash=sha256:0bbc17250b10d3466875a40a52520a6bac3c02334ca709207648abd3c223ed5c \ + --hash=sha256:0cc21533878e5586b80d74c281d7f8da7932bc8ace50b8d5f6dbf7e3935f63f1 \ + --hash=sha256:0d0b7e803191db5f714d264044e06189c8ccd3219e936cc184f07106bd17fd7b \ + --hash=sha256:113f78e7463a36dbbcea05bfe688efd7fa759d0f0c56e73c974d60dcfec3dfcc \ + --hash=sha256:169e0d178cb59314456ab30772429a802b25d13227088085b0d49b9fe1533104 \ + --hash=sha256:17fbb47f0885ace8327ce1235d0416dc86a211dcd8cc1e703f41523be32cfec8 \ + --hash=sha256:19bbd3b841174ae6ed588536ab5e1b1fe83d046e668602c20266547298d939a9 \ + --hash=sha256:1d9f9a3ce559a5267014b04b82956993270f63ec91765e13e9fd73daf2d2738e \ + --hash=sha256:1e4ecee40ba19e6975e1120829796770325841c2f153c0e9aecca927194c6a2a \ + --hash=sha256:22b0f9971ec4e07e8223f2beebe96a6cfc779d940b6f27d26604040dd74d3a44 \ + --hash=sha256:26fb5b9c3946bf7f1daed7b37e0c03898a6f062149127570f8ede346390a0825 \ + --hash=sha256:2778fed822d7db23ac5008b181441af0c869455b2e7d001f4019636ac31b6fe4 \ + --hash=sha256:28cfab66577000b9505a0d068c731aee7ca85cd26d4d63881fab17857e0fe1fb \ + --hash=sha256:29bc3973676ae334412efdd367fcd11d036b7be3efc1ce2407ef8676dabfeb82 \ + --hash=sha256:2bd9f19f7f1fcebd74e830f4af0f28adad4975d40d80620be19ffb2b2af56c9f \ + --hash=sha256:2d5d542bf2abd0fd0361e8017d03f7cb5786214ceb4a40eef1539d6585d93386 \ + --hash=sha256:30e4d2084df019880d55f6f7bea35328d9b464ebee090baa372c096dc77556fb \ + --hash=sha256:3619473a0e0d329fd4aec8075628f8f616be2da41605300696206d6f36920c3d \ + --hash=sha256:368625fb01666655985391dbad3860dc0ba7c0d6b9125819f3121ee7292b4ac8 \ + --hash=sha256:3737303ca9ea0f7cb83028781148fcda4f1dac7821db0c47672971dabcf63593 \ + --hash=sha256:3a9fed49c6ce4ed7e73f13182760c65c816da006debe67f37635580dfb0fae00 \ + --hash=sha256:3c38d142c706201db5b2345166eeef1e7740e3e2422b470b8ba5c8727a9b4c7a \ + --hash=sha256:3cb61db880ec11e984348227b333259994c2c85caa775eb7875decb3768db890 \ + --hash=sha256:3d74a03fb57757ece25aa4b3c1c60157a1cece37a020542785f942e2f827eed5 \ + --hash=sha256:3f796b535008708846044c43302719c6956f39ca2d93f2edda5319e79a29efbb \ + --hash=sha256:41105377f6282e8297f182e393a79cfffd521dde37ace52b106373bdcd9ca5cb \ + --hash=sha256:41aac7002a749f08727cb91babff1daf8deac317c0b1f317adc69be0e6c375d1 \ + --hash=sha256:44983e45310ee5b9f73397350251cdf6e63a466406a105f1d16cb5baa659270b \ + --hash=sha256:4cbbde66f1183db040daede83dd86c06d663c5bb2af6de1142b7c8c37923dd74 \ + --hash=sha256:4eda76074cfca2787c8cf1bec603eaebdddd8b061ad5502f85cddae998d54f00 \ + --hash=sha256:4fc6cd65dc4d2fdb2625e288939a3566e36127a84811a4913f02f3d5931da52d \ + --hash=sha256:50885073e2909251d4718634a191c49ae5f527e5e1736d738e365c3e8be8f22b \ + --hash=sha256:5174a697ce042fa77c407e05efe41e03aa56dae9ec67388055820fb48cf4c3ba \ + --hash=sha256:54b64fb2433bc71488e7a449603bf8bd31fbcf9cb56fbe1eb6d459e90b86c37b \ + --hash=sha256:54fe8518abe06a4c3852754bfd498b30cc58e667f376c513eac89a244ce781a4 \ + --hash=sha256:55dbbd8ffbc40d1697d5e2d0375b08599dae8746b0b08dea05eee4ce81648fac \ + --hash=sha256:57b52603e89355ff318025dd55158f6e71396c0f1f609d548e9ea9c94cc6ce0a \ + --hash=sha256:58370d05d033ee97224c81263af123dea3d931025030fd34b61227a768a8858a \ + --hash=sha256:5d87a3584093e1a89987e3d36d82c98d9621b2cb944e22a420aa1401e096758f \ + --hash=sha256:623f938f6a039536cc02b7582a07a080f13fdfd48f87e63201d92d7e34d09a18 \ + --hash=sha256:62815d2c67f2dd1be76a253d88af4e1da19aeaa1820146dec52cf8bee2958b16 \ + --hash=sha256:6290289fa5fb4c70fd7f72016e03633d60388185483ff3b162912c81205ae2cf \ + --hash=sha256:67e41a497bac88cc1de96eeba56eeb933c39d54bc227352f8455aa87c4ca4000 \ + --hash=sha256:6c85c38a279ca9295a69b9b088a2e48aa49737bb1b34e6a9dc6297c110e8d912 \ + --hash=sha256:6f01f044112d43a20be2f13a11683666d87151542ad627fe41a18b9791d2802f \ + --hash=sha256:707151644085dd0f20fe4f4b573d28e5130c4aaa5f587e95b60989c5926653b5 \ + --hash=sha256:723b2681ed4cc07d3401bbea9c201ad4f2a4ca6ba8cddaff6789f715dd2b391e \ + --hash=sha256:72d1cc63bcc91e14933f77d51b3df899d6a07d184ec515ea7f56bff659e124d7 \ + --hash=sha256:7374d6e3ef72afe49697ecd683f3da12f4fc06af2d75433d0580c6746d2fa025 \ + --hash=sha256:7501e9be34cb21e72fcfe672aafd0eee65c16ba2afa9dcb5500a587d3a0580f0 \ + --hash=sha256:76219cd1eefb9bf4af7856e3ae563d15158efa145c0aab01e9933051a1954045 \ + --hash=sha256:7aec798c2b01aaa65a55f1124f3405804184373abb318a3091325aece235f67c \ + --hash=sha256:7be6dfb49e48fd0a7d91ff758a2b51336f1cd21f9d44b20f6801f072bd080cdd \ + --hash=sha256:7e4e1f580033335c6f76d1e0d6b56baf009d1a64d6a4816347e4271ba951f46d \ + --hash=sha256:7e8ec5f606e0809426d2440e0683509fb605a8820a21ebd120dcdba61b74ef7f \ + --hash=sha256:7f196cd7910d71e9d9860da0ff7a77f64d22c1ad931f1dd18559a06e03109fc0 \ + --hash=sha256:82f3802bfc4751f420d591c5c864de538b71cea117fce67e4595c2afede08a15 \ + --hash=sha256:85ffc9920ffc39c5eee1e3ac9100c913a0973996fbad5111f939bbda49204bb7 \ + --hash=sha256:8e6c219e375f6341d0959af814296372d265a8ca1af63825f65e2e87c618f006 \ + --hash=sha256:8f767ba0911602ddef289404e33835a61168314ebd3c729833db2ed685824211 \ + --hash=sha256:8ff038d52ef6aa0f309feeba00c5095c9118d0abf787e8e8454d6048db2037fc \ + --hash=sha256:915e7a2418f10bd1151b1953df06d896db9783c9cfdb9a8ee1f9b3a4331ab503 \ + --hash=sha256:92883836caf50d5255be03d988d75bc93e3f86ba247b7ca137347c323f731deb \ + --hash=sha256:960b1b3efa39872ac8b6cc3a556edd6fb90ed74f08c9c45e028f1005b26aa55d \ + --hash=sha256:9aeaf53eaa075dd63e81512522fd180097312fb2c9f476333309184285c49ce0 \ + --hash=sha256:9d8089d853c7963a8ce87fff93e2a67075c0bc08684a08ea6ad13577c38ffc38 \ + --hash=sha256:a4130d0b9ce5fad6af07421b1aecc7e079519f70d6c05729ab871794eded8617 \ + --hash=sha256:a482ac121de6973897c92c2f31defc6bafb11c83825109275cffce54bb64933f \ + --hash=sha256:add7ac388d1e0bf57259afbcf9ed05621a3bf11ce5ee337e7536f1e1aaf056b0 \ + --hash=sha256:b1f12bd684887a0a5d55e6363ca87056f361e45451105012d329b86ec19dbe0b \ + --hash=sha256:b3f99e1756fc48ad507b95e5d86f2fb21b3d495012ff13e6592ebac14033f166 \ + --hash=sha256:b4cce60d0223074803c9dbe0721ad3fa51dafe7d462fee4b656a1aa01ee07518 \ + --hash=sha256:baeb47635cb33375dee4924cd93d7f5dcaa786c740b08423b0209b824a1ee728 \ + --hash=sha256:bbea5b775f0ac84945191fb83f845a6fd9a21a03ea7f2e187defac7e401616ad \ + --hash=sha256:bbfcb95d9a744e6e2827dfc66ad10e1020e0cac255eb7f85652832d5a264c2fc \ + --hash=sha256:bd6e7d363aa93bd3421b30b6af97064daf47bc96005bddba67c5ffbc6df426b8 \ + --hash=sha256:be77c402d5e882b6fbacfd90823f13da8e0a69658405a39a569c6b58fdb17b03 \ + --hash=sha256:c302245fd6c33d96bd169c7ccf2513c20f4c1e417c07ce9dce107c8bc3f8411f \ + --hash=sha256:c88653877aeb514c089d1b3d473451677b8b9a6d1497dbddf1ae7934518b06d2 \ + --hash=sha256:cae6383181f1e345317742d2ddd88f9e7d2682fa4c9432e3a74e47d92dce0229 \ + --hash=sha256:cd471ede0d802dd936b6fab28188302b2d497f68436025857ca72cd3810423fe \ + --hash=sha256:d106493a60dcb4aef35a0fac85105e150a11cf8bc2b0d388f5a33272d756c966 \ + --hash=sha256:d30b650595fdbe32366b94cb14f30bb2b625e512bd4e1df00611f99dc5c27fd4 \ + --hash=sha256:d51fde50a77f81330523562e3c2734ffdca9c4c9e9d355478117905e1cfe16c6 \ + --hash=sha256:d57dea657357230cc780e13920d7fa7db059d58fe721c80020f94476da4ca0a1 \ + --hash=sha256:d771f085fcdf4035786adfb1d8db026df1eb4b41dac1c3d070d1e49512843227 \ + --hash=sha256:dae0f0bd7d30c0ad61b9a504e8e272cb8391eed3f1587edf933f4f6b33437450 \ + --hash=sha256:db0562c5f71d18596dcd45e854cf2eeba27d7543e1a3acdafb7eef728f7fe85d \ + --hash=sha256:dfd51b4c56b673dfbc43d7d27ef857dd91124801e2806c69bb45585ce0fa019b \ + --hash=sha256:e080c0637aea036f35507e803a4778f119a9b436617694ae1c5c366805f1e997 \ + --hash=sha256:e48d4dbe0f88e53081da605ae68644e5182752803bbc2beb228cca7f1c4454d6 \ + --hash=sha256:e8b4b5580280b9265af3e0409974fb79c64cf7523632d03fbf11df18f8b0181e \ + --hash=sha256:e8b5378de2b139c3a830f0209c1e91f7705919a4b3e563a10955104f5097a70a \ + --hash=sha256:e904f2417f0d6f6d514f3f8b836416c360f306ddaee1f84de8eef1e722d212e5 \ + --hash=sha256:eee884572b06bbe8a2b54f424dbd996139442cf83c76478e1ec162512e0dd2c7 \ + --hash=sha256:f1fbb0a99125b1287c6d9747f937dc66621426836d1a2d50d05aecfc81911b57 \ + --hash=sha256:f40a95186a72fa0b67d15fef0f157bfcda00b4f59c8a07cbe5530d41ac35d105 \ + --hash=sha256:f6e0bfe77d238308839699944164b96a2eeccaf55f2af400f54dc20669d8d5f2 \ + --hash=sha256:f963eafc0a77a6c0562397da004f5876a9bcf7265a7bcc3205e29636bc4a1312 \ + --hash=sha256:fb9d44c25244e11c8be3f12c938ca8ba8404620ef8092245d2093c6ab3df260f \ + --hash=sha256:fc78739b5ec6e4fb02301984a3d442a91406e7700efbe305071e7fd1c78278f2 \ + --hash=sha256:fceef7fe67c81e1585198215e42ad3fdba3a25644beda8fbdaf85f4d7b93175a \ + --hash=sha256:fd96476f04db5ceba1cfa0f21228f67c1f7402296f0e73fee3513aa680ad237b # via feast (pyproject.toml) multidict==6.7.1 \ --hash=sha256:026d264228bcd637d4e060844e39cdc60f86c479e463d49075dedc21b18fbbe0 \ @@ -1737,123 +1733,129 @@ multidict==6.7.1 \ # aiobotocore # aiohttp # yarl -mypy==1.19.1 \ - --hash=sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd \ - --hash=sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b \ - --hash=sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1 \ - --hash=sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba \ - --hash=sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b \ - --hash=sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045 \ - --hash=sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac \ - --hash=sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6 \ - --hash=sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a \ - --hash=sha256:409088884802d511ee52ca067707b90c883426bd95514e8cfda8281dc2effe24 \ - --hash=sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957 \ - --hash=sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042 \ - --hash=sha256:4f28f99c824ecebcdaa2e55d82953e38ff60ee5ec938476796636b86afa3956e \ - --hash=sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec \ - --hash=sha256:7bcfc336a03a1aaa26dfce9fff3e287a3ba99872a157561cbfcebe67c13308e3 \ - --hash=sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718 \ - --hash=sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f \ - --hash=sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331 \ - --hash=sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1 \ - --hash=sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1 \ - --hash=sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13 \ - --hash=sha256:b13cfdd6c87fc3efb69ea4ec18ef79c74c3f98b4e5498ca9b85ab3b2c2329a67 \ - --hash=sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2 \ - --hash=sha256:b7951a701c07ea584c4fe327834b92a30825514c868b1f69c30445093fdd9d5a \ - --hash=sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b \ - --hash=sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8 \ - --hash=sha256:c608937067d2fc5a4dd1a5ce92fd9e1398691b8c5d012d66e1ddd430e9244376 \ - --hash=sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef \ - --hash=sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288 \ - --hash=sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75 \ - --hash=sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74 \ - --hash=sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250 \ - --hash=sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab \ - --hash=sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6 \ - --hash=sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247 \ - --hash=sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925 \ - --hash=sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e \ - --hash=sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e +mypy==1.20.0 \ + --hash=sha256:002b613ae19f4ac7d18b7e168ffe1cb9013b37c57f7411984abbd3b817b0a214 \ + --hash=sha256:00e047c74d3ec6e71a2eb88e9ea551a2edb90c21f993aefa9e0d2a898e0bb732 \ + --hash=sha256:02cca0761c75b42a20a2757ae58713276605eb29a08dd8a6e092aa347c4115ca \ + --hash=sha256:0ecd63f75fdd30327e4ad8b5704bd6d91fc6c1b2e029f8ee14705e1207212489 \ + --hash=sha256:0f42dfaab7ec1baff3b383ad7af562ab0de573c5f6edb44b2dab016082b89948 \ + --hash=sha256:1973868d2adbb4584a3835780b27436f06d1dc606af5be09f187aaa25be1070f \ + --hash=sha256:26c8b52627b6552f47ff11adb4e1509605f094e29815323e487fc0053ebe93d1 \ + --hash=sha256:2721f0ce49cb74a38f00c50da67cb7d36317b5eda38877a49614dc018e91c787 \ + --hash=sha256:2fcedb16d456106e545b2bfd7ef9d24e70b38ec252d2a629823a4d07ebcdb69e \ + --hash=sha256:31b5dbb55293c1bd27c0fc813a0d2bb5ceef9d65ac5afa2e58f829dab7921fd5 \ + --hash=sha256:34506397dbf40c15dc567635d18a21d33827e9ab29014fb83d292a8f4f8953b6 \ + --hash=sha256:367e5c993ba34d5054d11937d0485ad6dfc60ba760fa326c01090fc256adf15c \ + --hash=sha256:379edf079ce44ac8d2805bcf9b3dd7340d4f97aad3a5e0ebabbf9d125b84b442 \ + --hash=sha256:39362cdb4ba5f916e7976fccecaab1ba3a83e35f60fa68b64e9a70e221bb2436 \ + --hash=sha256:4525e7010b1b38334516181c5b81e16180b8e149e6684cee5a727c78186b4e3b \ + --hash=sha256:47781555a7aa5fedcc2d16bcd72e0dc83eb272c10dd657f9fb3f9cc08e2e6abb \ + --hash=sha256:49d11c6f573a5a08f77fad13faff2139f6d0730ebed2cfa9b3d2702671dd7188 \ + --hash=sha256:555493c44a4f5a1b58d611a43333e71a9981c6dbe26270377b6f8174126a0526 \ + --hash=sha256:555658c611099455b2da507582ea20d2043dfdfe7f5ad0add472b1c6238b433f \ + --hash=sha256:697f102c5c1d526bdd761a69f17c6070f9892eebcb94b1a5963d679288c09e78 \ + --hash=sha256:76a70bf840495729be47510856b978f1b0ec7d08f257ca38c9d932720bf6b43e \ + --hash=sha256:7d3243c406773185144527f83be0e0aefc7bf4601b0b2b956665608bf7c98a83 \ + --hash=sha256:931a7630bba591593dcf6e97224a21ff80fb357e7982628d25e3c618e7f598ef \ + --hash=sha256:9804c3ad27f78e54e58b32e7cb532d128b43dbfb9f3f9f06262b821a0f6bd3f5 \ + --hash=sha256:a17c5d0bdcca61ce24a35beb828a2d0d323d3fcf387d7512206888c900193367 \ + --hash=sha256:a6e0641147cbfa7e4e94efdb95c2dab1aff8cfc159ded13e07f308ddccc8c48e \ + --hash=sha256:a79c1eba7ac4209f2d850f0edd0a2f8bba88cbfdfefe6fb76a19e9d4fe5e71a2 \ + --hash=sha256:a9336b5e6712f4adaf5afc3203a99a40b379049104349d747eb3e5a3aa23ac2e \ + --hash=sha256:b20c8b0fd5877abdf402e79a3af987053de07e6fb208c18df6659f708b535134 \ + --hash=sha256:b3a49064504be59e59da664c5e149edc1f26c67c4f8e8456f6ba6aba55033018 \ + --hash=sha256:b503ab55a836136b619b5fc21c8803d810c5b87551af8600b72eecafb0059cb0 \ + --hash=sha256:bd0212976dc57a5bfeede7c219e7cd66568a32c05c9129686dd487c059c1b88a \ + --hash=sha256:c70380fe5d64010f79fb863b9081c7004dd65225d2277333c219d93a10dad4dd \ + --hash=sha256:d99f515f95fd03a90875fdb2cca12ff074aa04490db4d190905851bdf8a549a8 \ + --hash=sha256:e80cf77847d0d3e6e3111b7b25db32a7f8762fd4b9a3a72ce53fe16a2863b281 \ + --hash=sha256:eb96c84efcc33f0b5e0e04beacf00129dd963b67226b01c00b9dfc8affb464c3 \ + --hash=sha256:ebea00201737ad4391142808ed16e875add5c17f676e0912b387739f84991e13 \ + --hash=sha256:efe8d70949c3023698c3fca1e94527e7e790a361ab8116f90d11221421cd8726 \ + --hash=sha256:f13b3e41bce9d257eded794c0f12878af3129d80aacd8a3ee0dee51f3a978651 \ + --hash=sha256:f194db59657c58593a3c47c6dfd7bad4ef4ac12dbc94d01b3a95521f78177e33 \ + --hash=sha256:f49590891d2c2f8a9de15614e32e459a794bcba84693c2394291a2038bbaaa69 \ + --hash=sha256:f75ff57defcd0f1d6e006d721ccdec6c88d4f6a7816eb92f1c4890d979d9ee62 \ + --hash=sha256:f799d9db89fc00446f03281f84a221e50018fc40113a3ba9864b132895619ebe \ + --hash=sha256:f8426d4d75d68714abc17a4292d922f6ba2cfb984b72c2278c437f6dae797865 # via sqlalchemy mypy-extensions==1.1.0 \ --hash=sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505 \ --hash=sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558 # via mypy -numpy==2.4.2 \ - --hash=sha256:00ab83c56211a1d7c07c25e3217ea6695e50a3e2f255053686b081dc0b091a82 \ - --hash=sha256:068cdb2d0d644cdb45670810894f6a0600797a69c05f1ac478e8d31670b8ee75 \ - --hash=sha256:0f01dcf33e73d80bd8dc0f20a71303abbafa26a19e23f6b68d1aa9990af90257 \ - --hash=sha256:0fece1d1f0a89c16b03442eae5c56dc0be0c7883b5d388e0c03f53019a4bfd71 \ - --hash=sha256:12e26134a0331d8dbd9351620f037ec470b7c75929cb8a1537f6bfe411152a1a \ - --hash=sha256:1ae241bbfc6ae276f94a170b14785e561cb5e7f626b6688cf076af4110887413 \ - --hash=sha256:1f92f53998a17265194018d1cc321b2e96e900ca52d54c7c77837b71b9465181 \ - --hash=sha256:209fae046e62d0ce6435fcfe3b1a10537e858249b3d9b05829e2a05218296a85 \ - --hash=sha256:20abd069b9cda45874498b245c8015b18ace6de8546bf50dfa8cea1696ed06ef \ - --hash=sha256:21982668592194c609de53ba4933a7471880ccbaadcc52352694a59ecc860b3a \ - --hash=sha256:25f2059807faea4b077a2b6837391b5d830864b3543627f381821c646f31a63c \ - --hash=sha256:2653de5c24910e49c2b106499803124dde62a5a1fe0eedeaecf4309a5f639390 \ - --hash=sha256:2b8f157c8a6f20eb657e240f8985cc135598b2b46985c5bccbde7616dc9c6b1e \ - --hash=sha256:2fb882da679409066b4603579619341c6d6898fc83a8995199d5249f986e8e8f \ - --hash=sha256:40397bda92382fcec844066efb11f13e1c9a3e2a8e8f318fb72ed8b6db9f60f1 \ - --hash=sha256:444be170853f1f9d528428eceb55f12918e4fda5d8805480f36a002f1415e09b \ - --hash=sha256:47c5a6ed21d9452b10227e5e8a0e1c22979811cad7dcc19d8e3e2fb8fa03f1a3 \ - --hash=sha256:4f069069931240b3fc703f1e23df63443dbd6390614c8c44a87d96cd0ec81eb1 \ - --hash=sha256:52b913ec40ff7ae845687b0b34d8d93b60cb66dcee06996dd5c99f2fc9328657 \ - --hash=sha256:5633c0da313330fd20c484c78cdd3f9b175b55e1a766c4a174230c6b70ad8262 \ - --hash=sha256:5daf6f3914a733336dab21a05cdec343144600e964d2fcdabaac0c0269874b2a \ - --hash=sha256:5eea80d908b2c1f91486eb95b3fb6fab187e569ec9752ab7d9333d2e66bf2d6b \ - --hash=sha256:602f65afdef699cda27ec0b9224ae5dc43e328f4c24c689deaf77133dbee74d0 \ - --hash=sha256:659a6107e31a83c4e33f763942275fd278b21d095094044eb35569e86a21ddae \ - --hash=sha256:66cb9422236317f9d44b67b4d18f44efe6e9c7f8794ac0462978513359461554 \ - --hash=sha256:6d82351358ffbcdcd7b686b90742a9b86632d6c1c051016484fa0b326a0a1548 \ - --hash=sha256:6e9f61981ace1360e42737e2bae58b27bf28a1b27e781721047d84bd754d32e7 \ - --hash=sha256:6ed0be1ee58eef41231a5c943d7d1375f093142702d5723ca2eb07db9b934b05 \ - --hash=sha256:7cdde6de52fb6664b00b056341265441192d1291c130e99183ec0d4b110ff8b1 \ - --hash=sha256:7df2de1e4fba69a51c06c28f5a3de36731eb9639feb8e1cf7e4a7b0daf4cf622 \ - --hash=sha256:7edc794af8b36ca37ef5fcb5e0d128c7e0595c7b96a2318d1badb6fcd8ee86b1 \ - --hash=sha256:7f54844851cdb630ceb623dcec4db3240d1ac13d4990532446761baede94996a \ - --hash=sha256:805cc8de9fd6e7a22da5aed858e0ab16be5a4db6c873dde1d7451c541553aa27 \ - --hash=sha256:8906e71fd8afcb76580404e2a950caef2685df3d2a57fe82a86ac8d33cc007ba \ - --hash=sha256:89f7268c009bc492f506abd6f5265defa7cb3f7487dc21d357c3d290add45082 \ - --hash=sha256:8c50dd1fc8826f5b26a5ee4d77ca55d88a895f4e4819c7ecc2a9f5905047a443 \ - --hash=sha256:8e4549f8a3c6d13d55041925e912bfd834285ef1dd64d6bc7d542583355e2e98 \ - --hash=sha256:8e9afaeb0beff068b4d9cd20d322ba0ee1cecfb0b08db145e4ab4dd44a6b5110 \ - --hash=sha256:98f16a80e917003a12c0580f97b5f875853ebc33e2eaa4bccfc8201ac6869308 \ - --hash=sha256:9e35d3e0144137d9fdae62912e869136164534d64a169f86438bc9561b6ad49f \ - --hash=sha256:9e4424677ce4b47fe73c8b5556d876571f7c6945d264201180db2dc34f676ab5 \ - --hash=sha256:adb6ed2ad29b9e15321d167d152ee909ec73395901b70936f029c3bc6d7f4460 \ - --hash=sha256:aea4f66ff44dfddf8c2cffd66ba6538c5ec67d389285292fe428cb2c738c8aef \ - --hash=sha256:b21041e8cb6a1eb5312dd1d2f80a94d91efffb7a06b70597d44f1bd2dfc315ab \ - --hash=sha256:b2f0073ed0868db1dcd86e052d37279eef185b9c8db5bf61f30f46adac63c909 \ - --hash=sha256:b3a24467af63c67829bfaa61eecf18d5432d4f11992688537be59ecd6ad32f5e \ - --hash=sha256:b9c618d56a29c9cb1c4da979e9899be7578d2e0b3c24d52079c166324c9e8695 \ - --hash=sha256:bba37bc29d4d85761deed3954a1bc62be7cf462b9510b51d367b769a8c8df325 \ - --hash=sha256:bd3a7a9f5847d2fb8c2c6d1c862fa109c31a9abeca1a3c2bd5a64572955b2979 \ - --hash=sha256:be71bf1edb48ebbbf7f6337b5bfd2f895d1902f6335a5830b20141fc126ffba0 \ - --hash=sha256:c02ef4401a506fb60b411467ad501e1429a3487abca4664871d9ae0b46c8ba32 \ - --hash=sha256:c3cd545784805de05aafe1dde61752ea49a359ccba9760c1e5d1c88a93bbf2b7 \ - --hash=sha256:c7ac672d699bf36275c035e16b65539931347d68b70667d28984c9fb34e07fa7 \ - --hash=sha256:cb7bbb88aa74908950d979eeaa24dbdf1a865e3c7e45ff0121d8f70387b55f73 \ - --hash=sha256:cd2bd2bbed13e213d6b55dc1d035a4f91748a7d3edc9480c13898b0353708920 \ - --hash=sha256:cda077c2e5b780200b6b3e09d0b42205a3d1c68f30c6dceb90401c13bff8fe74 \ - --hash=sha256:cf28c0c1d4c4bf00f509fa7eb02c58d7caf221b50b467bcb0d9bbf1584d5c821 \ - --hash=sha256:d0d9b7c93578baafcbc5f0b83eaf17b79d345c6f36917ba0c67f45226911d499 \ - --hash=sha256:d1240d50adff70c2a88217698ca844723068533f3f5c5fa6ee2e3220e3bdb000 \ - --hash=sha256:d30291931c915b2ab5717c2974bb95ee891a1cf22ebc16a8006bd59cd210d40a \ - --hash=sha256:d9f64d786b3b1dd742c946c42d15b07497ed14af1a1f3ce840cce27daa0ce913 \ - --hash=sha256:da6cad4e82cb893db4b69105c604d805e0c3ce11501a55b5e9f9083b47d2ffe8 \ - --hash=sha256:df1b10187212b198dd45fa943d8985a3c8cf854aed4923796e0e019e113a1bda \ - --hash=sha256:e04ae107ac591763a47398bb45b568fc38f02dbc4aa44c063f67a131f99346cb \ - --hash=sha256:e6dee3bb76aa4009d5a912180bf5b2de012532998d094acee25d9cb8dee3e44a \ - --hash=sha256:e7e88598032542bd49af7c4747541422884219056c268823ef6e5e89851c8825 \ - --hash=sha256:e98c97502435b53741540a5717a6749ac2ada901056c7db951d33e11c885cc7d \ - --hash=sha256:ec055f6dae239a6299cace477b479cca2fc125c5675482daf1dd886933a1076f \ - --hash=sha256:f74f0f7779cc7ae07d1810aab8ac6b1464c3eafb9e283a40da7309d5e6e48fbb \ - --hash=sha256:fbde1b0c6e81d56f5dccd95dd4a711d9b95df1ae4009a60887e56b27e8d903fa \ - --hash=sha256:fcf92bee92742edd401ba41135185866f7026c502617f422eb432cfeca4fe236 \ - --hash=sha256:fd49860271d52127d61197bb50b64f58454e9f578cb4b2c001a6de8b1f50b0b1 +numpy==2.4.4 \ + --hash=sha256:07077278157d02f65c43b1b26a3886bce886f95d20aabd11f87932750dfb14ed \ + --hash=sha256:08f2e31ed5e6f04b118e49821397f12767934cfdd12a1ce86a058f91e004ee50 \ + --hash=sha256:0aec54fd785890ecca25a6003fd9a5aed47ad607bbac5cd64f836ad8666f4959 \ + --hash=sha256:0d35aea54ad1d420c812bfa0385c71cd7cc5bcf7c65fed95fc2cd02fe8c79827 \ + --hash=sha256:0d4e437e295f18ec29bc79daf55e8a47a9113df44d66f702f02a293d93a2d6dd \ + --hash=sha256:0dfd3f9d3adbe2920b68b5cd3d51444e13a10792ec7154cd0a2f6e74d4ab3233 \ + --hash=sha256:1378871da56ca8943c2ba674530924bb8ca40cd228358a3b5f302ad60cf875fc \ + --hash=sha256:15716cfef24d3a9762e3acdf87e27f58dc823d1348f765bbea6bef8c639bfa1b \ + --hash=sha256:19710a9ca9992d7174e9c52f643d4272dcd1558c5f7af7f6f8190f633bd651a7 \ + --hash=sha256:23cbfd4c17357c81021f21540da84ee282b9c8fba38a03b7b9d09ba6b951421e \ + --hash=sha256:2483e4584a1cb3092da4470b38866634bafb223cbcd551ee047633fd2584599a \ + --hash=sha256:27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d \ + --hash=sha256:28a650663f7314afc3e6ec620f44f333c386aad9f6fc472030865dc0ebb26ee3 \ + --hash=sha256:2aa0613a5177c264ff5921051a5719d20095ea586ca88cc802c5c218d1c67d3e \ + --hash=sha256:2c194dd721e54ecad9ad387c1d35e63dce5c4450c6dc7dd5611283dda239aabb \ + --hash=sha256:2d19e6e2095506d1736b7d80595e0f252d76b89f5e715c35e06e937679ea7d7a \ + --hash=sha256:2d390634c5182175533585cc89f3608a4682ccb173cc9bb940b2881c8d6f8fa0 \ + --hash=sha256:30caa73029a225b2d40d9fae193e008e24b2026b7ee1a867b7ee8d96ca1a448e \ + --hash=sha256:42c16925aa5a02362f986765f9ebabf20de75cdefdca827d14315c568dcab113 \ + --hash=sha256:45dbed2ab436a9e826e302fcdcbe9133f9b0006e5af7168afb8963a6520da103 \ + --hash=sha256:4636de7fd195197b7535f231b5de9e4b36d2c440b6e566d2e4e4746e6af0ca93 \ + --hash=sha256:4a19d9dba1a76618dd86b164d608566f393f8ec6ac7c44f0cc879011c45e65af \ + --hash=sha256:4bbc7f303d125971f60ec0aaad5e12c62d0d2c925f0ab1273debd0e4ba37aba5 \ + --hash=sha256:4d6d57903571f86180eb98f8f0c839fa9ebbfb031356d87f1361be91e433f5b7 \ + --hash=sha256:4e874c976154687c1f71715b034739b45c7711bec81db01914770373d125e392 \ + --hash=sha256:51fc224f7ca4d92656d5a5eb315f12eb5fe2c97a66249aa7b5f562528a3be38c \ + --hash=sha256:58c8b5929fcb8287cbd6f0a3fae19c6e03a5c48402ae792962ac465224a629a4 \ + --hash=sha256:5a285b3b96f951841799528cd1f4f01cd70e7e0204b4abebac9463eecfcf2a40 \ + --hash=sha256:5c70f1cc1c4efbe316a572e2d8b9b9cc44e89b95f79ca3331553fbb63716e2bf \ + --hash=sha256:62d6b0f03b694173f9fcb1fb317f7222fd0b0b103e784c6549f5e53a27718c44 \ + --hash=sha256:6a246d5914aa1c820c9443ddcee9c02bec3e203b0c080349533fae17727dfd1b \ + --hash=sha256:6aa3236c78803afbcb255045fbef97a9e25a1f6c9888357d205ddc42f4d6eba5 \ + --hash=sha256:6bbe4eb67390b0a0265a2c25458f6b90a409d5d069f1041e6aff1e27e3d9a79e \ + --hash=sha256:715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74 \ + --hash=sha256:72944b19f2324114e9dc86a159787333b77874143efcf89a5167ef83cfee8af0 \ + --hash=sha256:81f4a14bee47aec54f883e0cad2d73986640c1590eb9bfaaba7ad17394481e6e \ + --hash=sha256:846300f379b5b12cc769334464656bc882e0735d27d9726568bc932fdc49d5ec \ + --hash=sha256:86b6f55f5a352b48d7fbfd2dbc3d5b780b2d79f4d3c121f33eb6efb22e9a2015 \ + --hash=sha256:874f200b2a981c647340f841730fc3a2b54c9d940566a3c4149099591e2c4c3d \ + --hash=sha256:8a87ec22c87be071b6bdbd27920b129b94f2fc964358ce38f3822635a3e2e03d \ + --hash=sha256:8b3b60bb7cba2c8c81837661c488637eee696f59a877788a396d33150c35d842 \ + --hash=sha256:8e3ed142f2728df44263aaf5fb1f5b0b99f4070c553a0d7f033be65338329150 \ + --hash=sha256:93e15038125dc1e5345d9b5b68aa7f996ec33b98118d18c6ca0d0b7d6198b7e8 \ + --hash=sha256:989824e9faf85f96ec9c7761cd8d29c531ad857bfa1daa930cba85baaecf1a9a \ + --hash=sha256:99d838547ace2c4aace6c4f76e879ddfe02bb58a80c1549928477862b7a6d6ed \ + --hash=sha256:9b2aec6af35c113b05695ebb5749a787acd63cafc83086a05771d1e1cd1e555f \ + --hash=sha256:9c585a1790d5436a5374bac930dad6ed244c046ed91b2b2a3634eb2971d21008 \ + --hash=sha256:a7164afb23be6e37ad90b2f10426149fd75aee07ca55653d2aa41e66c4ef697e \ + --hash=sha256:ac6b31e35612a26483e20750126d30d0941f949426974cace8e6b5c58a3657b0 \ + --hash=sha256:ad2e2ef14e0b04e544ea2fa0a36463f847f113d314aa02e5b402fdf910ef309e \ + --hash=sha256:b268594bccac7d7cf5844c7732e3f20c50921d94e36d7ec9b79e9857694b1b2f \ + --hash=sha256:b5f0362dc928a6ecd9db58868fca5e48485205e3855957bdedea308f8672ea4a \ + --hash=sha256:ba1f4fc670ed79f876f70082eff4f9583c15fb9a4b89d6188412de4d18ae2f40 \ + --hash=sha256:ba203255017337d39f89bdd58417f03c4426f12beed0440cfd933cb15f8669c7 \ + --hash=sha256:c901b15172510173f5cb310eae652908340f8dede90fff9e3bf6c0d8dfd92f83 \ + --hash=sha256:c9b39d38a9bd2ae1becd7eac1303d031c5c110ad31f2b319c6e7d98b135c934d \ + --hash=sha256:d2a8490669bfe99a233298348acc2d824d496dee0e66e31b66a6022c2ad74a5c \ + --hash=sha256:dddbbd259598d7240b18c9d87c56a9d2fb3b02fe266f49a7c101532e78c1d871 \ + --hash=sha256:df3775294accfdd75f32c74ae39fcba920c9a378a2fc18a12b6820aa8c1fb502 \ + --hash=sha256:e44319a2953c738205bf3354537979eaa3998ed673395b964c1176083dd46252 \ + --hash=sha256:e4a010c27ff6f210ff4c6ef34394cd61470d01014439b192ec22552ee867f2a8 \ + --hash=sha256:e823b8b6edc81e747526f70f71a9c0a07ac4e7ad13020aa736bb7c9d67196115 \ + --hash=sha256:e892aff75639bbef0d2a2cfd55535510df26ff92f63c92cd84ef8d4ba5a5557f \ + --hash=sha256:eea7ac5d2dce4189771cedb559c738a71512768210dc4e4753b107a2048b3d0e \ + --hash=sha256:ef4059d6e5152fa1a39f888e344c73fdc926e1b2dd58c771d67b0acfbf2aa67d \ + --hash=sha256:f169b9a863d34f5d11b8698ead99febeaa17a13ca044961aa8e2662a6c7766a0 \ + --hash=sha256:f2cf083b324a467e1ab358c105f6cad5ea950f50524668a80c486ff1db24e119 \ + --hash=sha256:f8474c4241bc18b750be2abea9d7a9ec84f46ef861dbacf86a4f6e043401f79e \ + --hash=sha256:f983334aea213c99992053ede6168500e5f086ce74fbc4acc3f2b00f5762e9db \ + --hash=sha256:f9e75681b59ddaa5e659898085ae0eaea229d054f2ac0c7e563a62205a700121 \ + --hash=sha256:fbc356aae7adf9e6336d336b9c8111d390a05df88f1805573ebb0807bd06fd1d \ + --hash=sha256:fcfe2045fd2e8f3cb0ce9d4ba6dba6333b8fa05bb8a4939c908cd43322d14c7e # via # feast (pyproject.toml) # dask @@ -1881,6 +1883,7 @@ packaging==26.0 \ # setuptools-scm # snowflake-connector-python # sphinx + # vcs-versioning pandas==2.3.3 \ --hash=sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7 \ --hash=sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593 \ @@ -1946,9 +1949,9 @@ pandas==2.3.3 \ # pandas-gbq # pymilvus # snowflake-connector-python -pandas-gbq==0.33.0 \ - --hash=sha256:499ad18a7b1917e2cc04bbd763ec37c11ecc49030348c45cebb9cbbdb7f909af \ - --hash=sha256:61357e11d73e0ae57cbff31e71fc3ed83da3d16b58b653f715b32ad760527e34 +pandas-gbq==0.34.1 \ + --hash=sha256:6bea5b85937251b976cf9db38151ea59abbff98771179183488d4614694bff67 \ + --hash=sha256:b74932c6ee35dfc81582f39c792e3a68c9ef9bee8c85f25667d9d05dfadd0daf # via google-cloud-bigquery parsy==2.2 \ --hash=sha256:5e981613d9d2d8b68012d1dd0afe928967bea2e4eefdb76c2f545af0dd02a9e7 \ @@ -1976,9 +1979,9 @@ pathspec==1.0.4 \ # hatchling # mypy # scikit-build-core -platformdirs==4.9.2 \ - --hash=sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd \ - --hash=sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291 +platformdirs==4.9.4 \ + --hash=sha256:1ec356301b7dc906d83f371c8f487070e99d3ccf9e501686456394622a01a934 \ + --hash=sha256:68a9a4619a666ea6439f2ff250c12a853cd1cbd5158d258bd824a7df6be2f868 # via snowflake-connector-python pluggy==1.6.0 \ --hash=sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3 \ @@ -2114,25 +2117,25 @@ propcache==0.4.1 \ # via # aiohttp # yarl -proto-plus==1.27.1 \ - --hash=sha256:912a7460446625b792f6448bade9e55cd4e41e6ac10e27009ef71a7f317fa147 \ - --hash=sha256:e4643061f3a4d0de092d62aa4ad09fa4756b2cbb89d4627f3985018216f9fefc +proto-plus==1.27.2 \ + --hash=sha256:6432f75893d3b9e70b9c412f1d2f03f65b11fb164b793d14ae2ca01821d22718 \ + --hash=sha256:b2adde53adadf75737c44d3dcb0104fde65250dfc83ad59168b4aa3e574b6a24 # via # google-api-core # google-cloud-bigquery-storage # google-cloud-bigtable # google-cloud-datastore -protobuf==6.33.5 \ - --hash=sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c \ - --hash=sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02 \ - --hash=sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c \ - --hash=sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd \ - --hash=sha256:8f04fa32763dcdb4973d537d6b54e615cc61108c7cb38fe59310c3192d29510a \ - --hash=sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190 \ - --hash=sha256:a3157e62729aafb8df6da2c03aa5c0937c7266c626ce11a278b6eb7963c4e37c \ - --hash=sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5 \ - --hash=sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0 \ - --hash=sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b +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) # google-api-core @@ -2245,12 +2248,10 @@ pyarrow-hotfix==0.7 \ --hash=sha256:3236f3b5f1260f0e2ac070a55c1a7b339c4bb7267839bd2015e283234e758100 \ --hash=sha256:59399cd58bdd978b2e42816a4183a55c6472d4e33d183351b6069f11ed42661d # via ibis-framework -pyasn1==0.6.2 \ - --hash=sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf \ - --hash=sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b - # via - # pyasn1-modules - # rsa +pyasn1==0.6.3 \ + --hash=sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf \ + --hash=sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde + # via pyasn1-modules pyasn1-modules==0.4.2 \ --hash=sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a \ --hash=sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6 @@ -2395,9 +2396,9 @@ pydantic-core==2.41.5 \ --hash=sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425 \ --hash=sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52 # via pydantic -pydantic-settings==2.13.0 \ - --hash=sha256:95d875514610e8595672800a5c40b073e99e4aae467fa7c8f9c263061ea2e1fe \ - --hash=sha256:d67b576fff39cd086b595441bf9c75d4193ca9c0ed643b90360694d0f1240246 +pydantic-settings==2.13.1 \ + --hash=sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025 \ + --hash=sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237 # via # fastapi-mcp # mcp @@ -2405,16 +2406,16 @@ pydata-google-auth==1.9.1 \ --hash=sha256:0a51ce41c601ca0bc69b8795bf58bedff74b4a6a007c9106c7cbcdec00eaced2 \ --hash=sha256:75ffce5d106e34b717b31844c1639ea505b7d9550dc23b96fb6c20d086b53fa3 # via pandas-gbq -pygments==2.19.2 \ - --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \ - --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b +pygments==2.20.0 \ + --hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \ + --hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176 # via # feast (pyproject.toml) # rich # sphinx -pyjwt[crypto]==2.11.0 \ - --hash=sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623 \ - --hash=sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469 +pyjwt[crypto]==2.12.1 \ + --hash=sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c \ + --hash=sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b # via # feast (pyproject.toml) # mcp @@ -2427,9 +2428,9 @@ pymysql==1.1.2 \ --hash=sha256:4961d3e165614ae65014e361811a724e2044ad3ea3739de9903ae7c21f539f03 \ --hash=sha256:e6b1d89711dd51f8f74b1631fe08f039e7d76cf67a42a323d3178f0f25762ed9 # via feast (pyproject.toml) -pyopenssl==25.3.0 \ - --hash=sha256:1fda6fc034d5e3d179d39e59c1895c9faeaf40a79de5fc4cbbfbe0d36f4a77b6 \ - --hash=sha256:c981cb0a3fd84e8602d7afc209522773b94c1c2446a3c710a75b06fe1beae329 +pyopenssl==26.0.0 \ + --hash=sha256:df94d28498848b98cc1c0ffb8ef1e71e40210d3b0a8064c9d29571ed2904bf81 \ + --hash=sha256:f293934e52936f2e3413b89c6ce36df66a0b34ae1ea3a053b8c5020ff2f513fc # via snowflake-connector-python pyproject-metadata==0.11.0 \ --hash=sha256:85bbecca8694e2c00f63b492c96921d6c228454057c88e7c352b2077fcaa4096 \ @@ -2445,9 +2446,9 @@ python-dateutil==2.9.0.post0 \ # ibis-framework # kubernetes # pandas -python-dotenv==1.2.1 \ - --hash=sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6 \ - --hash=sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61 +python-dotenv==1.2.2 \ + --hash=sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a \ + --hash=sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3 # via # pydantic-settings # pymilvus @@ -2456,9 +2457,9 @@ python-multipart==0.0.22 \ --hash=sha256:2b2cd894c83d21bf49d702499531c7bafd057d730c201782048f7945d82de155 \ --hash=sha256:7340bef99a7e0032613f56dc36027b959fd3b30a787ed62d310e951f7c3a3a58 # via mcp -pytz==2025.2 \ - --hash=sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3 \ - --hash=sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00 +pytz==2026.1.post1 \ + --hash=sha256:3378dde6a0c3d26719182142c56e60c7f9af7e968076f31aae569d72a0358ee1 \ + --hash=sha256:f2fd16142fda348286a75e1a524be810bb05d444e5a081f37f7affc635035f7a # via # pandas # snowflake-connector-python @@ -2551,9 +2552,9 @@ referencing==0.37.0 \ # via # jsonschema # jsonschema-specifications -requests==2.32.5 \ - --hash=sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6 \ - --hash=sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf +requests==2.33.1 \ + --hash=sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517 \ + --hash=sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a # via # feast (pyproject.toml) # fastapi-mcp @@ -2570,9 +2571,9 @@ requests-oauthlib==2.0.0 \ # via # google-auth-oauthlib # kubernetes -rich==14.3.2 \ - --hash=sha256:08e67c3e90884651da3239ea668222d19bea7b589149d8014a21c633420dbb69 \ - --hash=sha256:e712f11c1a562a11843306f5ed999475f09ac31ffb64281f73ab29ffdda8b3b8 +rich==14.3.3 \ + --hash=sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d \ + --hash=sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b # via # fastapi-mcp # ibis-framework @@ -2700,17 +2701,13 @@ rpds-py==0.30.0 \ # via # jsonschema # referencing -rsa==4.9.1 \ - --hash=sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762 \ - --hash=sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75 - # via google-auth s3transfer==0.13.1 \ --hash=sha256:a981aa7429be23fe6dfc13e80e4020057cbab622b08c0315288758d67cabc724 \ --hash=sha256:c3fdba22ba1bd367922f27ec8032d6a1cf5f10c934fb5d68cf60fd5a23d936cf # via boto3 -scikit-build-core==0.11.6 \ - --hash=sha256:5982ccd839735be99cfd3b92a8847c6c196692f476c215da84b79d2ad12f9f1b \ - --hash=sha256:ce6d8fe64e6b4c759ea0fb95d2f8a68f60d2df31c2989838633b8ec930736360 +scikit-build-core==0.12.2 \ + --hash=sha256:562e0bbc9de1a354c87825ccf732080268d6582a0200f648e8c4a2dcb1e3736d \ + --hash=sha256:6ea4730da400f9a998ec3287bd3ebc1d751fe45ad0a93451bead8618adbc02b1 # via feast (pyproject.toml) setuptools==80.10.2 \ --hash=sha256:8b0e9d10c784bf7d262c4e5ec5d4ec94127ce206e8738f29a437945fbc219b70 \ @@ -2721,9 +2718,9 @@ setuptools==80.10.2 \ # pydata-google-auth # pymilvus # setuptools-scm -setuptools-scm==9.2.2 \ - --hash=sha256:1c674ab4665686a0887d7e24c03ab25f24201c213e82ea689d2f3e169ef7ef57 \ - --hash=sha256:30e8f84d2ab1ba7cb0e653429b179395d0c33775d54807fc5f1dd6671801aef7 +setuptools-scm==10.0.5 \ + --hash=sha256:bbba8fe754516cdefd017f4456721775e6ef9662bd7887fb52ae26813d4838c3 \ + --hash=sha256:f611037d8aae618221503b8fa89319f073438252ae3420e01c9ceec249131a0a # via hatch-vcs shellingham==1.5.4 \ --hash=sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686 \ @@ -2739,33 +2736,32 @@ snowballstemmer==3.0.1 \ --hash=sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064 \ --hash=sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895 # via sphinx -snowflake-connector-python[pandas]==4.3.0 \ - --hash=sha256:08f5167a10d380fe66330d5b19d19bd8b4f4af27e9648e3b254e61da025646bf \ - --hash=sha256:120463ca391d9deda3bdb185104ba847e12f73c86ef411cfcf827ce49b64d1af \ - --hash=sha256:26a65c5c93d14c4d221b780fdb2f07b4dd83e848f39eabd4832778bf0e2694d4 \ - --hash=sha256:2e0f66acee330388815fb842f91a46c9cacdefdf02c816354e6adeca8c2c3f86 \ - --hash=sha256:3e2ce47485862fa14ffbf2732f0fd02aa69a7c68a50d5f6286f34ed17527cf87 \ - --hash=sha256:486d17332b9228d2e5975755b434e6a282756a447e0c6605d4e797944fa919da \ - --hash=sha256:55163c5d9b93e10d7217aabd56f776b16c0fe13774f8d5db9188824731da9586 \ - --hash=sha256:676b56eedcc268b7e25a447e736eb8bf8bcacfbc71196c94d6f45746672ee6d5 \ - --hash=sha256:726435b2769135b6282601efb2cd8fd53f7deb1ff2fb7da93d28141fa3c8b17e \ - --hash=sha256:762ffa9673465ccc630aba438d648e0b1a2452ba49669a54a60d1625f36898f3 \ - --hash=sha256:7763c0d5f8e6326ec31f8972cc806fb6d3e07b06ca59f67dfcdf02a34219bcbc \ - --hash=sha256:79cbf5e359cfc33b4c4307df1fe8f78cd5aee56f5c50b98a647fa0cd9ba82cfc \ - --hash=sha256:79f150297b39cfd2481b732554fc4d68b43c83c82eb01e670cc4051cffc089d6 \ - --hash=sha256:7c18b5021ffa6de8313f2c7f0ae6050c36bcee7cb33bb23d40a7fdf3e0a751f2 \ - --hash=sha256:9faa9280e41258fb479ec5395b6a17d3dbb316146832e436aed582b300de655e \ - --hash=sha256:ac18b37e03a29014a9c91aac10c7dbdfa11134c620c6f93dd16f4b99b6a38c2a \ - --hash=sha256:b5a8d91c3e0127360bc3de605df9d02ea4d87e4524a50bf2e7c5c4200f9abf78 \ - --hash=sha256:c1356a2c615e120f913e5235fe87ff8aadbb479ad5a5ac5c0a84881d5fbe981d \ - --hash=sha256:c6fa80373b82125552e691f47b603766ed783f3d90a5782564854aa224aee9d1 \ - --hash=sha256:ca9d22c61f4e3d171b0adad3e9211747917c3a978dfb99564307c1ceadb0f0cd \ - --hash=sha256:ce55b93120f8b429010bf39cc02e739610b6da2ccdd34fcfc0df04849d0fd9d4 \ - --hash=sha256:e3044e6a237b35f750394f199f5e3800dfeb3227c4c8562584877e814d2dc89a \ - --hash=sha256:e42dd9af46fa3ad0e61c1aa6a227357cace481916797ecb92dbb14adb61931e1 \ - --hash=sha256:e5d360d65d42dd97cf82e688a1a7f235b9bc048b4949c9c5c7052ff2783c444e \ - --hash=sha256:e96aaf23f2b021e0d2aac8ac1b541975cd1f6896d9115eefe0938114e694a562 \ - --hash=sha256:f5291c00f610b266ab8c79b1e008b3d0cb29bb5b86a0007529320921b4a3fc3c +snowflake-connector-python[pandas]==4.4.0 \ + --hash=sha256:16fdca775f7ca5ce4a973c07c434f5ab72bef5284e81a5e4ae2fb4d54d28965c \ + --hash=sha256:19d0c1ed033abae715a71b74c53010b180a5247c6924f851e4f7d0b0d58066c4 \ + --hash=sha256:2a6f6a514a10c3bb2d4554132f0b639f43d7e9fbb73fa1fae1c8a75333102686 \ + --hash=sha256:307f41326c702f6976746d2001dacf35adaf567f3f12afb3a5778fbb063c7241 \ + --hash=sha256:43e1a2f3ac51d24406d4eb0c23a8ceb9d6f5cb4854c941e5e1375d8c481e2844 \ + --hash=sha256:52efe2d6543a09807283748dd50a36ec01d52b4f342868132f8f9856b9c95a42 \ + --hash=sha256:56ff04dd9e17edc82128f412aa3776687dc94088f3d6b9144971e169952623cb \ + --hash=sha256:648f49029d699591af0f253e81c5bf60efc4411c7b0149ef074a59a038210a3b \ + --hash=sha256:693a1bef97509f09b7e6f42ea6f743d27819413c04fb3dc543b060d029871c56 \ + --hash=sha256:70d4051e2d9c87258b02672e17e21f5873e0cb49ff9705f6194ccfa25ac0d5fd \ + --hash=sha256:7c2984663a733d06c979aa6c8c1d7691621ec0d3521ef345d57c869ff2f1c4b2 \ + --hash=sha256:8304b4818d3e9de552dcfbdd0bca61bae1583e1c9794e242e58fe44bce701604 \ + --hash=sha256:85a01338d282423611f357cd5392dca2219bbda9a66b44761b11d6ae8ebf1e50 \ + --hash=sha256:96fdca994c4d9f7780e82fc7b4bd3398d856b43de3bae57d44e242ff435a2431 \ + --hash=sha256:9b1a28f843c1c0b582db7854789525d0c8aac4ea5c56e31113684e38220d0af9 \ + --hash=sha256:9fa43d330389df27024757c4f97dabddafbedc74b8bcc189b6a86e8b4d036014 \ + --hash=sha256:a088f108da4653ad1396ddb63a1c757ad614d0862c38f6f69cc77344bdcfeccb \ + --hash=sha256:b9f0ac0c00075321e1720d3876e936ee0256f54832e7463c5193a8dfa54913d5 \ + --hash=sha256:c828248214a49f77b903e05acf887d3ccb9d958b5a979f2ed3663bba1bd0f2b3 \ + --hash=sha256:d6fd334e4d8df7fcb30e6746e5ade845e82de2942268862aa8bce974ae2b86a2 \ + --hash=sha256:d8ac1659c8e588b9502f8d3d03c1ded2f274de0da9c09e62fe007cba5b46d6a5 \ + --hash=sha256:e8e7ce0e8b33aec8b1fc6741eb51dbeb54e2c3a6d282a0d459c355a85f089b08 \ + --hash=sha256:ea6e4083ebea0a814b46f029d64a2fb0ba6e7732952cd8af4406041708ce0e21 \ + --hash=sha256:f5d0e90e68a899c13fda5ca842ff77b5759b1674adf2c72702d3c2b53ca9d27b \ + --hash=sha256:fb628d5ea1999e23bfbaabce4125eb44d56605ca5634b8b1d6092ab22d555598 # via feast (pyproject.toml) sortedcontainers==2.4.0 \ --hash=sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88 \ @@ -2799,85 +2795,89 @@ sphinxcontrib-serializinghtml==2.0.0 \ --hash=sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331 \ --hash=sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d # via sphinx -sqlalchemy[mypy]==2.0.46 \ - --hash=sha256:09168817d6c19954d3b7655da6ba87fcb3a62bb575fb396a81a8b6a9fadfe8b5 \ - --hash=sha256:0cc3117db526cad3e61074100bd2867b533e2c7dc1569e95c14089735d6fb4fe \ - --hash=sha256:181903fe8c1b9082995325f1b2e84ac078b1189e2819380c2303a5f90e114a62 \ - --hash=sha256:1bc3f601f0a818d27bfe139f6766487d9c88502062a2cd3a7ee6c342e81d5047 \ - --hash=sha256:1e6199143d51e3e1168bedd98cc698397404a8f7508831b81b6a29b18b051069 \ - --hash=sha256:2347c3f0efc4de367ba00218e0ae5c4ba2306e47216ef80d6e31761ac97cb0b9 \ - --hash=sha256:261c4b1f101b4a411154f1da2b76497d73abbfc42740029205d4d01fa1052684 \ - --hash=sha256:33e462154edb9493f6c3ad2125931e273bbd0be8ae53f3ecd1c161ea9a1dd366 \ - --hash=sha256:37fee2164cf21417478b6a906adc1a91d69ae9aba8f9533e67ce882f4bb1de53 \ - --hash=sha256:3a9a72b0da8387f15d5810f1facca8f879de9b85af8c645138cba61ea147968c \ - --hash=sha256:3aac08f7546179889c62b53b18ebf1148b10244b3405569c93984b0388d016a7 \ - --hash=sha256:3c32e993bc57be6d177f7d5d31edb93f30726d798ad86ff9066d75d9bf2e0b6b \ - --hash=sha256:412f26bb4ba942d52016edc8d12fb15d91d3cd46b0047ba46e424213ad407bcb \ - --hash=sha256:42a1643dc5427b69aca967dae540a90b0fbf57eaf248f13a90ea5930e0966863 \ - --hash=sha256:4396c948d8217e83e2c202fbdcc0389cf8c93d2c1c5e60fa5c5a955eae0e64be \ - --hash=sha256:4dafb537740eef640c4d6a7c254611dca2df87eaf6d14d6a5fca9d1f4c3fc0fa \ - --hash=sha256:4f52f7291a92381e9b4de9050b0a65ce5d6a763333406861e33906b8aa4906bf \ - --hash=sha256:52fe29b3817bd191cc20bad564237c808967972c97fa683c04b28ec8979ae36f \ - --hash=sha256:56bdd261bfd0895452006d5316cbf35739c53b9bb71a170a331fa0ea560b2ada \ - --hash=sha256:585af6afe518732d9ccd3aea33af2edaae4a7aa881af5d8f6f4fe3a368699597 \ - --hash=sha256:590be24e20e2424a4c3c1b0835e9405fa3d0af5823a1a9fc02e5dff56471515f \ - --hash=sha256:64901e08c33462acc9ec3bad27fc7a5c2b6491665f2aa57564e57a4f5d7c52ad \ - --hash=sha256:6ac245604295b521de49b465bab845e3afe6916bcb2147e5929c8041b4ec0545 \ - --hash=sha256:6f827fd687fa1ba7f51699e1132129eac8db8003695513fcf13fc587e1bd47a5 \ - --hash=sha256:70ed2830b169a9960193f4d4322d22be5c0925357d82cbf485b3369893350908 \ - --hash=sha256:716be5bcabf327b6d5d265dbdc6213a01199be587224eb991ad0d37e83d728fd \ - --hash=sha256:7568fe771f974abadce52669ef3a03150ff03186d8eb82613bc8adc435a03f01 \ - --hash=sha256:77f8071d8fbcbb2dd11b7fd40dedd04e8ebe2eb80497916efedba844298065ef \ - --hash=sha256:82ec52100ec1e6ec671563bbd02d7c7c8d0b9e71a0723c72f22ecf52d1755330 \ - --hash=sha256:895296687ad06dc9b11a024cf68e8d9d3943aa0b4964278d2553b86f1b267735 \ - --hash=sha256:8d3b44b3d0ab2f1319d71d9863d76eeb46766f8cf9e921ac293511804d39813f \ - --hash=sha256:8d679b5f318423eacb61f933a9a0f75535bfca7056daeadbf6bd5bcee6183aee \ - --hash=sha256:8e84b09a9b0f19accedcbeff5c2caf36e0dd537341a33aad8d680336152dc34e \ - --hash=sha256:9094c8b3197db12aa6f05c51c05daaad0a92b8c9af5388569847b03b1007fb1b \ - --hash=sha256:90bde6c6b1827565a95fde597da001212ab436f1b2e0c2dcc7246e14db26e2a3 \ - --hash=sha256:9397b381dcee8a2d6b99447ae85ea2530dcac82ca494d1db877087a13e38926d \ - --hash=sha256:93a12da97cca70cea10d4b4fc602589c4511f96c1f8f6c11817620c021d21d00 \ - --hash=sha256:93bb0aae40b52c57fd74ef9c6933c08c040ba98daf23ad33c3f9893494b8d3ce \ - --hash=sha256:94b1e5f3a5f1ff4f42d5daab047428cd45a3380e51e191360a35cef71c9a7a2a \ - --hash=sha256:965c62be8256d10c11f8907e7a8d3e18127a4c527a5919d85fa87fd9ecc2cfdc \ - --hash=sha256:96c7cca1a4babaaf3bfff3e4e606e38578856917e52f0384635a95b226c87764 \ - --hash=sha256:9bcdce05f056622a632f1d44bb47dbdb677f58cad393612280406ce37530eb6d \ - --hash=sha256:9d80ea2ac519c364a7286e8d765d6cd08648f5b21ca855a8017d9871f075542d \ - --hash=sha256:a1e8cc6cc01da346dc92d9509a63033b9b1bda4fed7a7a7807ed385c7dccdc10 \ - --hash=sha256:ab65cb2885a9f80f979b85aa4e9c9165a31381ca322cbde7c638fe6eefd1ec39 \ - --hash=sha256:af865c18752d416798dae13f83f38927c52f085c52e2f32b8ab0fef46fdd02c2 \ - --hash=sha256:b1e14b2f6965a685c7128bd315e27387205429c2e339eeec55cb75ca4ab0ea2e \ - --hash=sha256:b2a9f9aee38039cf4755891a1e50e1effcc42ea6ba053743f452c372c3152b1b \ - --hash=sha256:be6c0466b4c25b44c5d82b0426b5501de3c424d7a3220e86cd32f319ba56798e \ - --hash=sha256:c4e2cc868b7b5208aec6c960950b7bb821f82c2fe66446c92ee0a571765e91a5 \ - --hash=sha256:c805fa6e5d461329fa02f53f88c914d189ea771b6821083937e79550bf31fc19 \ - --hash=sha256:cf36851ee7219c170bb0793dbc3da3e80c582e04a5437bc601bfe8c85c9216d7 \ - --hash=sha256:db23b1bf8cfe1f7fda19018e7207b20cdb5168f83c437ff7e95d19e39289c447 \ - --hash=sha256:e0c05aff5c6b1bb5fb46a87e0f9d2f733f83ef6cbbbcd5c642b6c01678268061 \ - --hash=sha256:e8ac45e8f4eaac0f9f8043ea0e224158855c6a4329fd4ee37c45c61e3beb518e \ - --hash=sha256:ea3cd46b6713a10216323cda3333514944e510aa691c945334713fca6b5279ff \ - --hash=sha256:ebf7e1e78af38047e08836d33502c7a278915698b7c2145d045f780201679999 \ - --hash=sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e \ - --hash=sha256:ff33c6e6ad006bbc0f34f5faf941cfc62c45841c64c0a058ac38c799f15b5ede +sqlalchemy[mypy]==2.0.48 \ + --hash=sha256:01f6bbd4308b23240cf7d3ef117557c8fd097ec9549d5d8a52977544e35b40ad \ + --hash=sha256:07edba08061bc277bfdc772dd2a1a43978f5a45994dd3ede26391b405c15221e \ + --hash=sha256:10853a53a4a00417a00913d270dddda75815fcb80675874285f41051c094d7dd \ + --hash=sha256:1182437cb2d97988cfea04cf6cdc0b0bb9c74f4d56ec3d08b81e23d621a28cc6 \ + --hash=sha256:144921da96c08feb9e2b052c5c5c1d0d151a292c6135623c6b2c041f2a45f9e0 \ + --hash=sha256:1a89ce07ad2d4b8cfc30bd5889ec40613e028ed80ef47da7d9dd2ce969ad30e0 \ + --hash=sha256:1b4c575df7368b3b13e0cebf01d4679f9a28ed2ae6c1cd0b1d5beffb6b2007dc \ + --hash=sha256:1ccd42229aaac2df431562117ac7e667d702e8e44afdb6cf0e50fa3f18160f0b \ + --hash=sha256:2645b7d8a738763b664a12a1542c89c940daa55196e8d73e55b169cc5c99f65f \ + --hash=sha256:288937433bd44e3990e7da2402fabc44a3c6c25d3704da066b85b89a85474ae0 \ + --hash=sha256:34634e196f620c7a61d18d5cf7dc841ca6daa7961aed75d532b7e58b309ac894 \ + --hash=sha256:348174f228b99f33ca1f773e85510e08927620caa59ffe7803b37170df30332b \ + --hash=sha256:36ac4ddc3d33e852da9cb00ffb08cea62ca05c39711dc67062ca2bb1fae35fd8 \ + --hash=sha256:3713e21ea67bca727eecd4a24bf68bcd414c403faae4989442be60994301ded0 \ + --hash=sha256:389b984139278f97757ea9b08993e7b9d1142912e046ab7d82b3fbaeb0209131 \ + --hash=sha256:426c5ca86415d9b8945c7073597e10de9644802e2ff502b8e1f11a7a2642856b \ + --hash=sha256:4599a95f9430ae0de82b52ff0d27304fe898c17cb5f4099f7438a51b9998ac77 \ + --hash=sha256:49b7bddc1eebf011ea5ab722fdbe67a401caa34a350d278cc7733c0e88fecb1f \ + --hash=sha256:53667b5f668991e279d21f94ccfa6e45b4e3f4500e7591ae59a8012d0f010dcb \ + --hash=sha256:546572a1793cc35857a2ffa1fe0e58571af1779bcc1ffa7c9fb0839885ed69a9 \ + --hash=sha256:583849c743e0e3c9bb7446f5b5addeacedc168d657a69b418063dfdb2d90081c \ + --hash=sha256:5aee45fd2c6c0f2b9cdddf48c48535e7471e42d6fb81adfde801da0bd5b93241 \ + --hash=sha256:5b193a7e29fd9fa56e502920dca47dffe60f97c863494946bd698c6058a55658 \ + --hash=sha256:5ca74f37f3369b45e1f6b7b06afb182af1fd5dde009e4ffd831830d98cbe5fe7 \ + --hash=sha256:68549c403f79a8e25984376480959975212a670405e3913830614432b5daa07a \ + --hash=sha256:69f5bc24904d3bc3640961cddd2523e361257ef68585d6e364166dfbe8c78fae \ + --hash=sha256:6bb85c546591569558571aa1b06aba711b26ae62f111e15e56136d69920e1616 \ + --hash=sha256:6f7b7243850edd0b8b97043f04748f31de50cf426e939def5c16bedb540698f7 \ + --hash=sha256:7001dc9d5f6bb4deb756d5928eaefe1930f6f4179da3924cbd95ee0e9f4dce89 \ + --hash=sha256:7a936f1bb23d370b7c8cc079d5fce4c7d18da87a33c6744e51a93b0f9e97e9b3 \ + --hash=sha256:7c998f2ace8bf76b453b75dbcca500d4f4b9dd3908c13e89b86289b37784848b \ + --hash=sha256:7cddca31edf8b0653090cbb54562ca027c421c58ddde2c0685f49ff56a1690e0 \ + --hash=sha256:8183dc57ae7d9edc1346e007e840a9f3d6aa7b7f165203a99e16f447150140d2 \ + --hash=sha256:82745b03b4043e04600a6b665cb98697c4339b24e34d74b0a2ac0a2488b6f94d \ + --hash=sha256:841a94c66577661c1f088ac958cd767d7c9bf507698f45afffe7a4017049de76 \ + --hash=sha256:858e433f12b0e5b3ed2f8da917433b634f4937d0e8793e5cb33c54a1a01df565 \ + --hash=sha256:908a3fa6908716f803b86896a09a2c4dde5f5ce2bb07aacc71ffebb57986ce99 \ + --hash=sha256:9764014ef5e58aab76220c5664abb5d47d5bc858d9debf821e55cfdd0f128485 \ + --hash=sha256:9c7d0a77e36b5f4b01ca398482230ab792061d243d715299b44a0b55c89fe617 \ + --hash=sha256:a5b429eb84339f9f05e06083f119ad814e6d85e27ecbdf9c551dfdbb128eaf8a \ + --hash=sha256:a66fe406437dd65cacd96a72689a3aaaecaebbcd62d81c5ac1c0fdbeac835096 \ + --hash=sha256:a6b764fb312bd35e47797ad2e63f0d323792837a6ac785a4ca967019357d2bc7 \ + --hash=sha256:b19151e76620a412c2ac1c6f977ab1b9fa7ad43140178345136456d5265b32ed \ + --hash=sha256:b8438ec5594980d405251451c5b7ea9aa58dda38eb7ac35fb7e4c696712ee24f \ + --hash=sha256:b8fc3454b4f3bd0a368001d0e968852dad45a873f8b4babd41bc302ec851a099 \ + --hash=sha256:bcb8ebbf2e2c36cfe01a94f2438012c6a9d494cf80f129d9753bcdf33bfc35a6 \ + --hash=sha256:d404dc897ce10e565d647795861762aa2d06ca3f4a728c5e9a835096c7059018 \ + --hash=sha256:d612c976cbc2d17edfcc4c006874b764e85e990c29ce9bd411f926bbfb02b9a2 \ + --hash=sha256:d64177f443594c8697369c10e4bbcac70ef558e0f7921a1de7e4a3d1734bcf67 \ + --hash=sha256:d854b3970067297f3a7fbd7a4683587134aa9b3877ee15aa29eea478dc68f933 \ + --hash=sha256:d8fcccbbc0c13c13702c471da398b8cd72ba740dca5859f148ae8e0e8e0d3e7e \ + --hash=sha256:e004aa9248e8cb0a5f9b96d003ca7c1c0a5da8decd1066e7b53f59eb8ce7c62b \ + --hash=sha256:e214d546c8ecb5fc22d6e6011746082abf13a9cf46eefb45769c7b31407c97b5 \ + --hash=sha256:e2d0d88686e3d35a76f3e15a34e8c12d73fc94c1dea1cd55782e695cc14086dd \ + --hash=sha256:e2f35b4cccd9ed286ad62e0a3c3ac21e06c02abc60e20aa51a3e305a30f5fa79 \ + --hash=sha256:e3070c03701037aa418b55d36532ecb8f8446ed0135acb71c678dbdf12f5b6e4 \ + --hash=sha256:e5e088bf43f6ee6fec7dbf1ef7ff7774a616c236b5c0cb3e00662dd71a56b571 \ + --hash=sha256:e83e3f959aaa1c9df95c22c528096d94848a1bc819f5d0ebf7ee3df0ca63db6c \ + --hash=sha256:f0dcbc588cd5b725162c076eb9119342f6579c7f7f55057bb7e3c6ff27e13121 \ + --hash=sha256:f27f9da0a7d22b9f981108fd4b62f8b5743423388915a563e651c20d06c1f457 \ + --hash=sha256:f8649a14caa5f8a243628b1d61cf530ad9ae4578814ba726816adb1121fc493e \ + --hash=sha256:fac0fa4e4f55f118fd87177dacb1c6522fe39c28d498d259014020fec9164c29 \ + --hash=sha256:fd08b90d211c086181caed76931ecfa2bdfc83eea3cfccdb0f82abc6c4b876cb # via feast (pyproject.toml) -sqlglot==28.10.1 \ - --hash=sha256:214aef51fd4ce16407022f81cfc80c173409dab6d0f6ae18c52b43f43b31d4dd \ - --hash=sha256:66e0dae43b4bce23314b80e9aef41b8c88fea0e17ada62de095b45262084a8c5 +sqlglot==30.2.1 \ + --hash=sha256:ef4a67cc6f66a8043085eb8ea95fa9541c1625dffa9145ad4e9815a7ba60a199 \ + --hash=sha256:f23d9ee9427ef9d20df15f9b0ffa57d9eb45e52b012219a349d1e6b50ed926d1 # via ibis-framework -sse-starlette==3.2.0 \ - --hash=sha256:5876954bd51920fc2cd51baee47a080eb88a37b5b784e615abb0b283f801cdbf \ - --hash=sha256:8127594edfb51abe44eac9c49e59b0b01f1039d0c7461c6fd91d4e03b70da422 +sse-starlette==3.3.4 \ + --hash=sha256:84bb06e58939a8b38d8341f1bc9792f06c2b53f48c608dd207582b664fc8f3c1 \ + --hash=sha256:aaf92fc067af8a5427192895ac028e947b484ac01edbc3caf00e7e7137c7bef1 # via mcp -starlette==0.52.1 \ - --hash=sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74 \ - --hash=sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933 +starlette==1.0.0 \ + --hash=sha256:6a4beaf1f81bb472fd19ea9b918b50dc3a77a6f2e190a12954b25e6ed5eea149 \ + --hash=sha256:d3ec55e0bb321692d275455ddfd3df75fff145d009685eb40dc91fc66b03d38b # via # fastapi # mcp # sse-starlette -tabulate==0.9.0 \ - --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ - --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f +tabulate==0.10.0 \ + --hash=sha256:e2cfde8f79420f6deeffdeda9aaec3b6bc5abce947655d17ac662b126e48a60d \ + --hash=sha256:f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3 # via feast (pyproject.toml) tenacity==8.5.0 \ --hash=sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78 \ @@ -2887,54 +2887,54 @@ toml==0.10.2 \ --hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \ --hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f # via feast (pyproject.toml) -tomli==2.4.0 \ - --hash=sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729 \ - --hash=sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b \ - --hash=sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d \ - --hash=sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df \ - --hash=sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576 \ - --hash=sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d \ - --hash=sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1 \ - --hash=sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a \ - --hash=sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e \ - --hash=sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc \ - --hash=sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702 \ - --hash=sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6 \ - --hash=sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd \ - --hash=sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4 \ - --hash=sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776 \ - --hash=sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a \ - --hash=sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66 \ - --hash=sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87 \ - --hash=sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2 \ - --hash=sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f \ - --hash=sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475 \ - --hash=sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f \ - --hash=sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95 \ - --hash=sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9 \ - --hash=sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3 \ - --hash=sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9 \ - --hash=sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76 \ - --hash=sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da \ - --hash=sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8 \ - --hash=sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51 \ - --hash=sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86 \ - --hash=sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8 \ - --hash=sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0 \ - --hash=sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b \ - --hash=sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1 \ - --hash=sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e \ - --hash=sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d \ - --hash=sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c \ - --hash=sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867 \ - --hash=sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a \ - --hash=sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c \ - --hash=sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0 \ - --hash=sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4 \ - --hash=sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614 \ - --hash=sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132 \ - --hash=sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa \ - --hash=sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087 +tomli==2.4.1 \ + --hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \ + --hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \ + --hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \ + --hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \ + --hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \ + --hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \ + --hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \ + --hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \ + --hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \ + --hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \ + --hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \ + --hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \ + --hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \ + --hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \ + --hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \ + --hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \ + --hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \ + --hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \ + --hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \ + --hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \ + --hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \ + --hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \ + --hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \ + --hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \ + --hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \ + --hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \ + --hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \ + --hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \ + --hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \ + --hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \ + --hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \ + --hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \ + --hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \ + --hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \ + --hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \ + --hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \ + --hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \ + --hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \ + --hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \ + --hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \ + --hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \ + --hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \ + --hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \ + --hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \ + --hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \ + --hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \ + --hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049 # via fastapi-mcp tomlkit==0.14.0 \ --hash=sha256:592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680 \ @@ -2957,13 +2957,13 @@ trove-classifiers==2026.1.14.14 \ --hash=sha256:00492545a1402b09d4858605ba190ea33243d361e2b01c9c296ce06b5c3325f3 \ --hash=sha256:1f9553927f18d0513d8e5ff80ab8980b8202ce37ecae0e3274ed2ef11880e74d # via hatchling -typeguard==4.5.0 \ - --hash=sha256:749bea21cdb2553e12831bc29f1eae980b22c7de8331ab67ae7db9e85470b5a7 \ - --hash=sha256:cfda388fc88a9ce42a41890900d6f31ee124bea9b73bb84701a32438e92165c3 +typeguard==4.5.1 \ + --hash=sha256:44d2bf329d49a244110a090b55f5f91aa82d9a9834ebfd30bcc73651e4a8cc40 \ + --hash=sha256:f6f8ecbbc819c9bc749983cc67c02391e16a9b43b8b27f15dc70ed7c4a007274 # via feast (pyproject.toml) -typer==0.23.1 \ - --hash=sha256:2070374e4d31c83e7b61362fd859aa683576432fd5b026b060ad6b4cd3b86134 \ - --hash=sha256:3291ad0d3c701cbf522012faccfbb29352ff16ad262db2139e6b01f15781f14e +typer==0.24.1 \ + --hash=sha256:112c1f0ce578bfb4cab9ffdabc68f031416ebcc216536611ba21f04e9aa84c9e \ + --hash=sha256:e39b4732d65fbdcde189ae76cf7cd48aeae72919dea1fdfc16593be016256b45 # via fastapi-mcp types-psutil==7.0.0.20250218 \ --hash=sha256:1447a30c282aafefcf8941ece854e1100eee7b0296a9d9be9977292f0269b121 \ @@ -3008,91 +3008,85 @@ tzdata==2025.3 \ # via # ibis-framework # pandas -ujson==5.11.0 \ - --hash=sha256:0180a480a7d099082501cad1fe85252e4d4bf926b40960fb3d9e87a3a6fbbc80 \ - --hash=sha256:04c41afc195fd477a59db3a84d5b83a871bd648ef371cf8c6f43072d89144eef \ - --hash=sha256:0654a2691fc252c3c525e3d034bb27b8a7546c9d3eb33cd29ce6c9feda361a6a \ - --hash=sha256:090b4d11b380ae25453100b722d0609d5051ffe98f80ec52853ccf8249dfd840 \ - --hash=sha256:109f59885041b14ee9569bf0bb3f98579c3fa0652317b355669939e5fc5ede53 \ - --hash=sha256:10f29e71ecf4ecd93a6610bd8efa8e7b6467454a363c3d6416db65de883eb076 \ - --hash=sha256:1194b943e951092db611011cb8dbdb6cf94a3b816ed07906e14d3bc6ce0e90ab \ - --hash=sha256:12b5e7e22a1fe01058000d1b317d3b65cc3daf61bd2ea7a2b76721fe160fa74d \ - --hash=sha256:16ccb973b7ada0455201808ff11d48fe9c3f034a6ab5bd93b944443c88299f89 \ - --hash=sha256:181fb5b15703a8b9370b25345d2a1fd1359f0f18776b3643d24e13ed9c036d4c \ - --hash=sha256:185f93ebccffebc8baf8302c869fac70dd5dd78694f3b875d03a31b03b062cdb \ - --hash=sha256:1a0a9b76a89827a592656fe12e000cf4f12da9692f51a841a4a07aa4c7ecc41c \ - --hash=sha256:1a325fd2c3a056cf6c8e023f74a0c478dd282a93141356ae7f16d5309f5ff823 \ - --hash=sha256:1aa8a2ab482f09f6c10fba37112af5f957689a79ea598399c85009f2f29898b5 \ - --hash=sha256:1d663b96eb34c93392e9caae19c099ec4133ba21654b081956613327f0e973ac \ - --hash=sha256:29113c003ca33ab71b1b480bde952fbab2a0b6b03a4ee4c3d71687cdcbd1a29d \ - --hash=sha256:30f607c70091483550fbd669a0b37471e5165b317d6c16e75dba2aa967608723 \ - --hash=sha256:3134b783ab314d2298d58cda7e47e7a0f7f71fc6ade6ac86d5dbeaf4b9770fa6 \ - --hash=sha256:34032aeca4510a7c7102bd5933f59a37f63891f30a0706fb46487ab6f0edf8f0 \ - --hash=sha256:3772e4fe6b0c1e025ba3c50841a0ca4786825a4894c8411bf8d3afe3a8061328 \ - --hash=sha256:3d2720e9785f84312b8e2cb0c2b87f1a0b1c53aaab3b2af3ab817d54409012e0 \ - --hash=sha256:416389ec19ef5f2013592f791486bef712ebce0cd59299bf9df1ba40bb2f6e04 \ - --hash=sha256:446e8c11c06048611c9d29ef1237065de0af07cabdd97e6b5b527b957692ec25 \ - --hash=sha256:4598bf3965fc1a936bd84034312bcbe00ba87880ef1ee33e33c1e88f2c398b49 \ - --hash=sha256:48055e1061c1bb1f79e75b4ac39e821f3f35a9b82de17fce92c3140149009bec \ - --hash=sha256:4843f3ab4fe1cc596bb7e02228ef4c25d35b4bb0809d6a260852a4bfcab37ba3 \ - --hash=sha256:49e56ef8066f11b80d620985ae36869a3ff7e4b74c3b6129182ec5d1df0255f3 \ - --hash=sha256:4b42c115c7c6012506e8168315150d1e3f76e7ba0f4f95616f4ee599a1372bbc \ - --hash=sha256:4c9f5d6a27d035dd90a146f7761c2272cf7103de5127c9ab9c4cd39ea61e878a \ - --hash=sha256:5600202a731af24a25e2d7b6eb3f648e4ecd4bb67c4d5cf12f8fab31677469c9 \ - --hash=sha256:65724738c73645db88f70ba1f2e6fb678f913281804d5da2fd02c8c5839af302 \ - --hash=sha256:65f3c279f4ed4bf9131b11972040200c66ae040368abdbb21596bf1564899694 \ - --hash=sha256:674f306e3e6089f92b126eb2fe41bcb65e42a15432c143365c729fdb50518547 \ - --hash=sha256:683f57f0dd3acdd7d9aff1de0528d603aafcb0e6d126e3dc7ce8b020a28f5d01 \ - --hash=sha256:6b6ec7e7321d7fc19abdda3ad809baef935f49673951a8bab486aea975007e02 \ - --hash=sha256:6cd2df62f24c506a0ba322d5e4fe4466d47a9467b57e881ee15a31f7ecf68ff6 \ - --hash=sha256:6dd703c3e86dc6f7044c5ac0b3ae079ed96bf297974598116aa5fb7f655c3a60 \ - --hash=sha256:6eff24e1abd79e0ec6d7eae651dd675ddbc41f9e43e29ef81e16b421da896915 \ - --hash=sha256:7855ccea3f8dad5e66d8445d754fc1cf80265a4272b5f8059ebc7ec29b8d0835 \ - --hash=sha256:787aff4a84da301b7f3bac09bc696e2e5670df829c6f8ecf39916b4e7e24e701 \ - --hash=sha256:7895f0d2d53bd6aea11743bd56e3cb82d729980636cd0ed9b89418bf66591702 \ - --hash=sha256:78c684fb21255b9b90320ba7e199780f653e03f6c2528663768965f4126a5b50 \ - --hash=sha256:7e0ec1646db172beb8d3df4c32a9d78015e671d2000af548252769e33079d9a6 \ - --hash=sha256:7e3cff632c1d78023b15f7e3a81c3745cd3f94c044d1e8fa8efbd6b161997bbc \ - --hash=sha256:7f1a27ab91083b4770e160d17f61b407f587548f2c2b5fbf19f94794c495594a \ - --hash=sha256:80017e870d882d5517d28995b62e4e518a894f932f1e242cbc802a2fd64d365c \ - --hash=sha256:8254e858437c00f17cb72e7a644fc42dad0ebb21ea981b71df6e84b1072aaa7c \ - --hash=sha256:837da4d27fed5fdc1b630bd18f519744b23a0b5ada1bbde1a36ba463f2900c03 \ - --hash=sha256:849e65b696f0d242833f1df4182096cedc50d414215d1371fca85c541fbff629 \ - --hash=sha256:85e6796631165f719084a9af00c79195d3ebf108151452fefdcb1c8bb50f0105 \ - --hash=sha256:86baf341d90b566d61a394869ce77188cc8668f76d7bb2c311d77a00f4bdf844 \ - --hash=sha256:8fa2af7c1459204b7a42e98263b069bd535ea0cd978b4d6982f35af5a04a4241 \ - --hash=sha256:94fcae844f1e302f6f8095c5d1c45a2f0bfb928cccf9f1b99e3ace634b980a2a \ - --hash=sha256:952c0be400229940248c0f5356514123d428cba1946af6fa2bbd7503395fef26 \ - --hash=sha256:99c49400572cd77050894e16864a335225191fd72a818ea6423ae1a06467beac \ - --hash=sha256:9aacbeb23fdbc4b256a7d12e0beb9063a1ba5d9e0dbb2cfe16357c98b4334596 \ - --hash=sha256:a0af6574fc1d9d53f4ff371f58c96673e6d988ed2b5bf666a6143c782fa007e9 \ - --hash=sha256:a31c6b8004438e8c20fc55ac1c0e07dad42941db24176fe9acf2815971f8e752 \ - --hash=sha256:a4df61a6df0a4a8eb5b9b1ffd673429811f50b235539dac586bb7e9e91994138 \ - --hash=sha256:a638425d3c6eed0318df663df44480f4a40dc87cc7c6da44d221418312f6413b \ - --hash=sha256:aa6b3d4f1c0d3f82930f4cbd7fe46d905a4a9205a7c13279789c1263faf06dba \ - --hash=sha256:aa6d7a5e09217ff93234e050e3e380da62b084e26b9f2e277d2606406a2fc2e5 \ - --hash=sha256:ab2cb8351d976e788669c8281465d44d4e94413718af497b4e7342d7b2f78018 \ - --hash=sha256:abae0fb58cc820092a0e9e8ba0051ac4583958495bfa5262a12f628249e3b362 \ - --hash=sha256:b16930f6a0753cdc7d637b33b4e8f10d5e351e1fb83872ba6375f1e87be39746 \ - --hash=sha256:b7b136cc6abc7619124fd897ef75f8e63105298b5ca9bdf43ebd0e1fa0ee105f \ - --hash=sha256:be6b0eaf92cae8cdee4d4c9e074bde43ef1c590ed5ba037ea26c9632fb479c88 \ - --hash=sha256:c44c703842024d796b4c78542a6fcd5c3cb948b9fc2a73ee65b9c86a22ee3638 \ - --hash=sha256:c6618f480f7c9ded05e78a1938873fde68baf96cdd74e6d23c7e0a8441175c4b \ - --hash=sha256:ce076f2df2e1aa62b685086fbad67f2b1d3048369664b4cdccc50707325401f9 \ - --hash=sha256:d06e87eded62ff0e5f5178c916337d2262fdbc03b31688142a3433eabb6511db \ - --hash=sha256:d7c46cb0fe5e7056b9acb748a4c35aa1b428025853032540bb7e41f46767321f \ - --hash=sha256:d8951bb7a505ab2a700e26f691bdfacf395bc7e3111e3416d325b513eea03a58 \ - --hash=sha256:da473b23e3a54448b008d33f742bcd6d5fb2a897e42d1fc6e7bf306ea5d18b1b \ - --hash=sha256:de6e88f62796372fba1de973c11138f197d3e0e1d80bcb2b8aae1e826096d433 \ - --hash=sha256:e204ae6f909f099ba6b6b942131cee359ddda2b6e4ea39c12eb8b991fe2010e0 \ - --hash=sha256:e73df8648c9470af2b6a6bf5250d4744ad2cf3d774dcf8c6e31f018bdd04d764 \ - --hash=sha256:e750c436fb90edf85585f5c62a35b35082502383840962c6983403d1bd96a02c \ - --hash=sha256:e979fbc469a7f77f04ec2f4e853ba00c441bf2b06720aa259f0f720561335e34 \ - --hash=sha256:ecd6ff8a3b5a90c292c2396c2d63c687fd0ecdf17de390d852524393cd9ed052 \ - --hash=sha256:f278b31a7c52eb0947b2db55a5133fbc46b6f0ef49972cd1a80843b72e135aba \ - --hash=sha256:f62b9976fabbcde3ab6e413f4ec2ff017749819a0786d84d7510171109f2d53c \ - --hash=sha256:fa79fdb47701942c2132a9dd2297a1a85941d966d8c87bfd9e29b0cf423f26cc \ - --hash=sha256:fac6c0649d6b7c3682a0a6e18d3de6857977378dce8d419f57a0b20e3d775b39 +ujson==5.12.0 \ + --hash=sha256:006428d3813b87477d72d306c40c09f898a41b968e57b15a7d88454ecc42a3fb \ + --hash=sha256:02f93da7a4115e24f886b04fd56df1ee8741c2ce4ea491b7ab3152f744ad8f8e \ + --hash=sha256:0727363b05ab05ee737a28f6200dc4078bce6b0508e10bd8aab507995a15df61 \ + --hash=sha256:085b6ce182cdd6657481c7c4003a417e0655c4f6e58b76f26ee18f0ae21db827 \ + --hash=sha256:09b4beff9cc91d445d5818632907b85fb06943b61cb346919ce202668bf6794a \ + --hash=sha256:0a3ae28f0b209be5af50b54ca3e2123a3de3a57d87b75f1e5aa3d7961e041983 \ + --hash=sha256:0d2e8db5ade3736a163906154ca686203acc7d1d30736cbf577c730d13653d84 \ + --hash=sha256:0e00cec383eab2406c9e006bd4edb55d284e94bb943fda558326048178d26961 \ + --hash=sha256:0fe6b8b8968e11dd9b2348bd508f0f57cf49ab3512064b36bc4117328218718e \ + --hash=sha256:0fe9128e75c6aa6e9ae06c1408d6edd9179a2fef0fe6d9cda3166b887eba521d \ + --hash=sha256:14b2e1eb528d77bc0f4c5bd1a7ebc05e02b5b41beefb7e8567c9675b8b13bcf4 \ + --hash=sha256:15d416440148f3e56b9b244fdaf8a09fcf5a72e4944b8e119f5bf60417a2bfc8 \ + --hash=sha256:15e555c4caca42411270b2ed2b2ebc7b3a42bb04138cef6c956e1f1d49709fe2 \ + --hash=sha256:16b4fe9c97dc605f5e1887a9e1224287291e35c56cbc379f8aa44b6b7bcfe2bb \ + --hash=sha256:1b5c6ceb65fecd28a1d20d1eba9dbfa992612b86594e4b6d47bb580d2dd6bcb3 \ + --hash=sha256:1d072a403d82aef8090c6d4f728e3a727dfdba1ad3b7fa3a052c3ecbd37e73cb \ + --hash=sha256:2324d9a0502317ffc35d38e153c1b2fa9610ae03775c9d0f8d0cca7b8572b04e \ + --hash=sha256:2a248750abce1c76fbd11b2e1d88b95401e72819295c3b851ec73399d6849b3d \ + --hash=sha256:2ea6206043385343aff0b7da65cf73677f6f5e50de8f1c879e557f4298cac36a \ + --hash=sha256:31348a0ffbfc815ce78daac569d893349d85a0b57e1cd2cdbba50b7f333784da \ + --hash=sha256:38051f36423f084b909aaadb3b41c9c6a2958e86956ba21a8489636911e87504 \ + --hash=sha256:3c2f947e55d3c7cfe124dd4521ee481516f3007d13c6ad4bf6aeb722e190eb1b \ + --hash=sha256:3ed5cb149892141b1e77ef312924a327f2cc718b34247dae346ed66329e1b8be \ + --hash=sha256:3ff4ede90ed771140caa7e1890de17431763a483c54b3c1f88bd30f0cc1affc0 \ + --hash=sha256:40aa43a7a3a8d2f05e79900858053d697a88a605e3887be178b43acbcd781161 \ + --hash=sha256:42d875388fbd091c7ea01edfff260f839ba303038ffb23475ef392012e4d63dd \ + --hash=sha256:457fabc2700a8e6ddb85bc5a1d30d3345fe0d3ec3ee8161a4e032ec585801dfa \ + --hash=sha256:460e76a4daff214ae33ab959494962c93918cb44714ea3e3f748b14aa37f8a87 \ + --hash=sha256:50524f4f6a1c839714dbaff5386a1afb245d2d5ec8213a01fbc99cea7307811e \ + --hash=sha256:51acc750ec7a2df786cdc868fb16fa04abd6269a01d58cf59bafc57978773d8e \ + --hash=sha256:55ede2a7a051b3b7e71a394978a098d71b3783e6b904702ff45483fad434ae2d \ + --hash=sha256:561f89cc82deeae82e37d4a4764184926fb432f740a9691563a391b13f7339a4 \ + --hash=sha256:56ba3f7abbd6b0bb282a544dc38406d1a188d8bb9164f49fdb9c2fee62cb29da \ + --hash=sha256:57930ac9519099b852e190d2c04b1fb5d97ea128db33bce77ed874eccb4c7f09 \ + --hash=sha256:58a11cb49482f1a095a2bd9a1d81dd7c8fb5d2357f959ece85db4e46a825fd00 \ + --hash=sha256:64df53eef4ac857eb5816a56e2885ccf0d7dff6333c94065c93b39c51063e01d \ + --hash=sha256:6879aed770557f0961b252648d36f6fdaab41079d37a2296b5649fd1b35608e0 \ + --hash=sha256:6ad57654570464eb1b040b5c353dee442608e06cff9102b8fcb105565a44c9ed \ + --hash=sha256:6c0aed6a4439994c9666fb8a5b6c4eac94d4ef6ddc95f9b806a599ef83547e3b \ + --hash=sha256:76bf3e7406cf23a3e1ca6a23fb1fb9ea82f4f6bd226fe226e09146b0194f85dc \ + --hash=sha256:7bbf05c38debc90d1a195b11340cc85cb43ab3e753dc47558a3a84a38cbc72da \ + --hash=sha256:7ddb08b3c2f9213df1f2e3eb2fbea4963d80ec0f8de21f0b59898e34f3b3d96d \ + --hash=sha256:7e07f6f644d2c44d53b7a320a084eef98063651912c1b9449b5f45fcbdc6ccd2 \ + --hash=sha256:85833bca01aa5cae326ac759276dc175c5fa3f7b3733b7d543cf27f2df12d1ef \ + --hash=sha256:8712b61eb1b74a4478cfd1c54f576056199e9f093659334aeb5c4a6b385338e5 \ + --hash=sha256:871c0e5102e47995b0e37e8df7819a894a6c3da0d097545cd1f9f1f7d7079927 \ + --hash=sha256:89e302abd3749f6d6699691747969a5d85f7c73081d5ed7e2624c7bd9721a2ab \ + --hash=sha256:937794042342006f707837f38d721426b11b0774d327a2a45c0bd389eb750a87 \ + --hash=sha256:93bc91fdadcf046da37a214eaa714574e7e9b1913568e93bb09527b2ceb7f759 \ + --hash=sha256:94c5f1621cbcab83c03be46441f090b68b9f307b6c7ec44d4e3f6d5997383df4 \ + --hash=sha256:973b7d7145b1ac553a7466a64afa8b31ec2693d7c7fff6a755059e0a2885dfd2 \ + --hash=sha256:99cc80facad240b0c2fb5a633044420878aac87a8e7c348b9486450cba93f27c \ + --hash=sha256:9a5fcbe7b949f2e95c47ea8a80b410fcdf2da61c98553b45a4ee875580418b68 \ + --hash=sha256:9b3b86ec3e818f3dd3e13a9de628e88a9990f4af68ecb0b12dd3de81227f0a26 \ + --hash=sha256:9b3cf13facf6f77c283af0e1713e5e8c47a0fe295af81326cb3cb4380212e797 \ + --hash=sha256:9c5a52987a990eb1bae55f9000994f1afdb0326c154fb089992f839ab3c30688 \ + --hash=sha256:a2d79c6635ccffcbfc1d5c045874ba36b594589be81d50d43472570bb8de9c57 \ + --hash=sha256:a6ec5bf6bc361f2f0f9644907a36ce527715b488988a8df534120e5c34eeda94 \ + --hash=sha256:a7bf9cc97f05048ac8f3e02cd58f0fe62b901453c24345bfde287f4305dcc31c \ + --hash=sha256:ab9056d94e5db513d9313b34394f3a3b83e6301a581c28ad67773434f3faccab \ + --hash=sha256:adf28d13a33f9d750fe7a78fb481cac298fa257d8863d8727b2ea4455ea41235 \ + --hash=sha256:b62cb9a7501e1f5c9ffe190485501349c33e8862dde4377df774e40b8166871f \ + --hash=sha256:bacbd3c69862478cbe1c7ed4325caedec580d8acf31b8ee1b9a1e02a56295cad \ + --hash=sha256:bb349dbba57c76eec25e5917e07f35aabaf0a33b9e67fc13d188002500106487 \ + --hash=sha256:bd03472c36fa3a386a6deb887113b9e3fa40efba8203eb4fe786d3c0ccc724f6 \ + --hash=sha256:bf85a00ac3b56a1e7a19c5be7b02b5180a0895ac4d3c234d717a55e86960691c \ + --hash=sha256:ca0c7ce828bb76ab78b3991904b477c2fd0f711d7815c252d1ef28ff9450b052 \ + --hash=sha256:ccbfd94e59aad4a2566c71912b55f0547ac1680bfac25eb138e6703eb3dd434e \ + --hash=sha256:d1831c07bd4dce53c4b666fa846c7eba4b7c414f2e641a4585b7f50b72f502dc \ + --hash=sha256:d22cad98c2a10bbf6aa083a8980db6ed90d4285a841c4de892890c2b28286ef9 \ + --hash=sha256:d30ad4359413c8821cc7b3707f7ca38aa8bc852ba3b9c5a759ee2d7740157315 \ + --hash=sha256:e0dd3676ea0837cd70ea1879765e9e9f6be063be0436de9b3ea4b775caf83654 \ + --hash=sha256:e584d0cdd37cac355aca52ed788d1a2d939d6837e2870d3b70e585db24025a50 \ + --hash=sha256:e6369ac293d2cc40d52577e4fa3d75a70c1aae2d01fa3580a34a4e6eff9286b9 \ + --hash=sha256:efae5df7a8cc8bdb1037b0f786b044ce281081441df5418c3a0f0e1f86fe7bb3 \ + --hash=sha256:f19b3af31d02a2e79c5f9a6deaab0fb3c116456aeb9277d11720ad433de6dfc6 \ + --hash=sha256:f7a0430d765f9bda043e6aefaba5944d5f21ec43ff4774417d7e296f61917382 \ + --hash=sha256:fb94245a715b4d6e24689de12772b85329a1f9946cbf6187923a64ecdea39e65 # via pymilvus urllib3==2.6.3 \ --hash=sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed \ @@ -3164,6 +3158,10 @@ uvloop==0.22.1 \ --hash=sha256:ef6f0d4cc8a9fa1f6a910230cd53545d9a14479311e87e3cb225495952eb672c \ --hash=sha256:fe94b4564e865d968414598eea1a6de60adba0c040ba4ed05ac1300de402cd42 # via uvicorn +vcs-versioning==1.1.1 \ + --hash=sha256:b541e2ba79fc6aaa3850f8a7f88af43d97c1c80649c01142ee4146eddbc599e4 \ + --hash=sha256:fabd75a3cab7dd8ac02fe24a3a9ba936bf258667b5a62ed468c9a1da0f5775bc + # via setuptools-scm watchfiles==1.1.1 \ --hash=sha256:00485f441d183717038ed2e887a7c868154f216877653121068107b227a2f64c \ --hash=sha256:03fa0f5237118a0c5e496185cafa92878568b652a2e9a9382a5151b1a0380a43 \ @@ -3425,137 +3423,135 @@ wrapt==1.17.3 \ --hash=sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10 \ --hash=sha256:fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c # via aiobotocore -yarl==1.22.0 \ - --hash=sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a \ - --hash=sha256:029866bde8d7b0878b9c160e72305bbf0a7342bcd20b9999381704ae03308dc8 \ - --hash=sha256:078278b9b0b11568937d9509b589ee83ef98ed6d561dfe2020e24a9fd08eaa2b \ - --hash=sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da \ - --hash=sha256:07a524d84df0c10f41e3ee918846e1974aba4ec017f990dc735aad487a0bdfdf \ - --hash=sha256:088e4e08f033db4be2ccd1f34cf29fe994772fb54cfe004bbf54db320af56890 \ - --hash=sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093 \ - --hash=sha256:0cf71bf877efeac18b38d3930594c0948c82b64547c1cf420ba48722fe5509f6 \ - --hash=sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79 \ - --hash=sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683 \ - --hash=sha256:10619d9fdee46d20edc49d3479e2f8269d0779f1b031e6f7c2aa1c76be04b7ed \ - --hash=sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2 \ - --hash=sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff \ - --hash=sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02 \ - --hash=sha256:14291620375b1060613f4aab9ebf21850058b6b1b438f386cc814813d901c60b \ - --hash=sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03 \ - --hash=sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511 \ - --hash=sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c \ - --hash=sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124 \ - --hash=sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c \ - --hash=sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da \ - --hash=sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2 \ - --hash=sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0 \ - --hash=sha256:2e4e1f6f0b4da23e61188676e3ed027ef0baa833a2e633c29ff8530800edccba \ - --hash=sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d \ - --hash=sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53 \ - --hash=sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138 \ - --hash=sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4 \ - --hash=sha256:3aa27acb6de7a23785d81557577491f6c38a5209a254d1191519d07d8fe51748 \ - --hash=sha256:3b06bcadaac49c70f4c88af4ffcfbe3dc155aab3163e75777818092478bcbbe7 \ - --hash=sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d \ - --hash=sha256:3e2daa88dc91870215961e96a039ec73e4937da13cf77ce17f9cad0c18df3503 \ - --hash=sha256:3ea66b1c11c9150f1372f69afb6b8116f2dd7286f38e14ea71a44eee9ec51b9d \ - --hash=sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2 \ - --hash=sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa \ - --hash=sha256:437840083abe022c978470b942ff832c3940b2ad3734d424b7eaffcd07f76737 \ - --hash=sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f \ - --hash=sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1 \ - --hash=sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d \ - --hash=sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694 \ - --hash=sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3 \ - --hash=sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a \ - --hash=sha256:4c52a6e78aef5cf47a98ef8e934755abf53953379b7d53e68b15ff4420e6683d \ - --hash=sha256:4dcc74149ccc8bba31ce1944acee24813e93cfdee2acda3c172df844948ddf7b \ - --hash=sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a \ - --hash=sha256:51af598701f5299012b8416486b40fceef8c26fc87dc6d7d1f6fc30609ea0aa6 \ - --hash=sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b \ - --hash=sha256:595697f68bd1f0c1c159fcb97b661fc9c3f5db46498043555d04805430e79bea \ - --hash=sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5 \ - --hash=sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f \ - --hash=sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df \ - --hash=sha256:5cdac20da754f3a723cceea5b3448e1a2074866406adeb4ef35b469d089adb8f \ - --hash=sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b \ - --hash=sha256:5dbeefd6ca588b33576a01b0ad58aa934bc1b41ef89dee505bf2932b22ddffba \ - --hash=sha256:62441e55958977b8167b2709c164c91a6363e25da322d87ae6dd9c6019ceecf9 \ - --hash=sha256:663e1cadaddae26be034a6ab6072449a8426ddb03d500f43daf952b74553bba0 \ - --hash=sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6 \ - --hash=sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b \ - --hash=sha256:6944b2dc72c4d7f7052683487e3677456050ff77fcf5e6204e98caf785ad1967 \ - --hash=sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2 \ - --hash=sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708 \ - --hash=sha256:6dcbb0829c671f305be48a7227918cfcd11276c2d637a8033a99a02b67bf9eda \ - --hash=sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8 \ - --hash=sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10 \ - --hash=sha256:75976c6945d85dbb9ee6308cd7ff7b1fb9409380c82d6119bd778d8fcfe2931c \ - --hash=sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b \ - --hash=sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028 \ - --hash=sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e \ - --hash=sha256:80ddf7a5f8c86cb3eb4bc9028b07bbbf1f08a96c5c0bc1244be5e8fefcb94147 \ - --hash=sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33 \ - --hash=sha256:84fc3ec96fce86ce5aa305eb4aa9358279d1aa644b71fab7b8ed33fe3ba1a7ca \ - --hash=sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590 \ - --hash=sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c \ - --hash=sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53 \ - --hash=sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74 \ - --hash=sha256:99b6fc1d55782461b78221e95fc357b47ad98b041e8e20f47c1411d0aacddc60 \ - --hash=sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f \ - --hash=sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1 \ - --hash=sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27 \ - --hash=sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520 \ - --hash=sha256:a4fcfc8eb2c34148c118dfa02e6427ca278bfd0f3df7c5f99e33d2c0e81eae3e \ - --hash=sha256:a899cbd98dce6f5d8de1aad31cb712ec0a530abc0a86bd6edaa47c1090138467 \ - --hash=sha256:a9b1ba5610a4e20f655258d5a1fdc7ebe3d837bb0e45b581398b99eb98b1f5ca \ - --hash=sha256:af74f05666a5e531289cb1cc9c883d1de2088b8e5b4de48004e5ca8a830ac859 \ - --hash=sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273 \ - --hash=sha256:b266bd01fedeffeeac01a79ae181719ff848a5a13ce10075adbefc8f1daee70e \ - --hash=sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601 \ - --hash=sha256:b580e71cac3f8113d3135888770903eaf2f507e9421e5697d6ee6d8cd1c7f054 \ - --hash=sha256:b6a6f620cfe13ccec221fa312139135166e47ae169f8253f72a0abc0dae94376 \ - --hash=sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7 \ - --hash=sha256:b85b982afde6df99ecc996990d4ad7ccbdbb70e2a4ba4de0aecde5922ba98a0b \ - --hash=sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb \ - --hash=sha256:ba440ae430c00eee41509353628600212112cd5018d5def7e9b05ea7ac34eb65 \ - --hash=sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784 \ - --hash=sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71 \ - --hash=sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b \ - --hash=sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a \ - --hash=sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c \ - --hash=sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face \ - --hash=sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d \ - --hash=sha256:c7bd6683587567e5a49ee6e336e0612bec8329be1b7d4c8af5687dcdeb67ee1e \ - --hash=sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e \ - --hash=sha256:cb95a9b1adaa48e41815a55ae740cfda005758104049a640a398120bf02515ca \ - --hash=sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9 \ - --hash=sha256:d332fc2e3c94dad927f2112395772a4e4fedbcf8f80efc21ed7cdfae4d574fdb \ - --hash=sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95 \ - --hash=sha256:d5372ca1df0f91a86b047d1277c2aaf1edb32d78bbcefffc81b40ffd18f027ed \ - --hash=sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf \ - --hash=sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca \ - --hash=sha256:dd7afd3f8b0bfb4e0d9fc3c31bfe8a4ec7debe124cfd90619305def3c8ca8cd2 \ - --hash=sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62 \ - --hash=sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df \ - --hash=sha256:e1b329cb8146d7b736677a2440e422eadd775d1806a81db2d4cded80a48efc1a \ - --hash=sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67 \ - --hash=sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f \ - --hash=sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529 \ - --hash=sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486 \ - --hash=sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a \ - --hash=sha256:e6438cc8f23a9c1478633d216b16104a586b9761db62bfacb6425bac0a36679e \ - --hash=sha256:e81fda2fb4a07eda1a2252b216aa0df23ebcd4d584894e9612e80999a78fd95b \ - --hash=sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74 \ - --hash=sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d \ - --hash=sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b \ - --hash=sha256:f0d97c18dfd9a9af4490631905a3f131a8e4c9e80a39353919e2cfed8f00aedc \ - --hash=sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2 \ - --hash=sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e \ - --hash=sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8 \ - --hash=sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82 \ - --hash=sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd \ - --hash=sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249 +yarl==1.23.0 \ + --hash=sha256:03214408cfa590df47728b84c679ae4ef00be2428e11630277be0727eba2d7cc \ + --hash=sha256:041b1a4cefacf65840b4e295c6985f334ba83c30607441ae3cf206a0eed1a2e4 \ + --hash=sha256:0793e2bd0cf14234983bbb371591e6bea9e876ddf6896cdcc93450996b0b5c85 \ + --hash=sha256:0e1fdaa14ef51366d7757b45bde294e95f6c8c049194e793eedb8387c86d5993 \ + --hash=sha256:0e40111274f340d32ebcc0a5668d54d2b552a6cca84c9475859d364b380e3222 \ + --hash=sha256:115136c4a426f9da976187d238e84139ff6b51a20839aa6e3720cd1026d768de \ + --hash=sha256:13a563739ae600a631c36ce096615fe307f131344588b0bc0daec108cdb47b25 \ + --hash=sha256:16c6994ac35c3e74fb0ae93323bf8b9c2a9088d55946109489667c510a7d010e \ + --hash=sha256:170e26584b060879e29fac213e4228ef063f39128723807a312e5c7fec28eff2 \ + --hash=sha256:17235362f580149742739cc3828b80e24029d08cbb9c4bda0242c7b5bc610a8e \ + --hash=sha256:1932b6b8bba8d0160a9d1078aae5838a66039e8832d41d2992daa9a3a08f7860 \ + --hash=sha256:1b6b572edd95b4fa8df75de10b04bc81acc87c1c7d16bcdd2035b09d30acc957 \ + --hash=sha256:1c3a3598a832590c5a3ce56ab5576361b5688c12cb1d39429cf5dba30b510760 \ + --hash=sha256:1c57676bdedc94cd3bc37724cf6f8cd2779f02f6aba48de45feca073e714fe52 \ + --hash=sha256:1dc702e42d0684f42d6519c8d581e49c96cefaaab16691f03566d30658ee8788 \ + --hash=sha256:21d1b7305a71a15b4794b5ff22e8eef96ff4a6d7f9657155e5aa419444b28912 \ + --hash=sha256:23f371bd662cf44a7630d4d113101eafc0cfa7518a2760d20760b26021454719 \ + --hash=sha256:2569b67d616eab450d262ca7cb9f9e19d2f718c70a8b88712859359d0ab17035 \ + --hash=sha256:263cd4f47159c09b8b685890af949195b51d1aa82ba451c5847ca9bc6413c220 \ + --hash=sha256:2803ed8b21ca47a43da80a6fd1ed3019d30061f7061daa35ac54f63933409412 \ + --hash=sha256:2a6940a074fb3c48356ed0158a3ca5699c955ee4185b4d7d619be3c327143e05 \ + --hash=sha256:2e27c8841126e017dd2a054a95771569e6070b9ee1b133366d8b31beb5018a41 \ + --hash=sha256:31c9921eb8bd12633b41ad27686bbb0b1a2a9b8452bfdf221e34f311e9942ed4 \ + --hash=sha256:34b6cf500e61c90f305094911f9acc9c86da1a05a7a3f5be9f68817043f486e4 \ + --hash=sha256:3650dc2480f94f7116c364096bc84b1d602f44224ef7d5c7208425915c0475dd \ + --hash=sha256:389871e65468400d6283c0308e791a640b5ab5c83bcee02a2f51295f95e09748 \ + --hash=sha256:39004f0ad156da43e86aa71f44e033de68a44e5a31fc53507b36dd253970054a \ + --hash=sha256:394906945aa8b19fc14a61cf69743a868bb8c465efe85eee687109cc540b98f4 \ + --hash=sha256:3ceb13c5c858d01321b5d9bb65e4cf37a92169ea470b70fec6f236b2c9dd7e34 \ + --hash=sha256:411225bae281f114067578891bc75534cfb3d92a3b4dfef7a6ca78ba354e6069 \ + --hash=sha256:44bb7bef4ea409384e3f8bc36c063d77ea1b8d4a5b2706956c0d6695f07dcc25 \ + --hash=sha256:4503053d296bc6e4cbd1fad61cf3b6e33b939886c4f249ba7c78b602214fabe2 \ + --hash=sha256:4764a6a7588561a9aef92f65bda2c4fb58fe7c675c0883862e6df97559de0bfb \ + --hash=sha256:4966242ec68afc74c122f8459abd597afd7d8a60dc93d695c1334c5fd25f762f \ + --hash=sha256:4a42e651629dafb64fd5b0286a3580613702b5809ad3f24934ea87595804f2c5 \ + --hash=sha256:4a59ba56f340334766f3a4442e0efd0af895fae9e2b204741ef885c446b3a1a8 \ + --hash=sha256:4c41e021bc6d7affb3364dc1e1e5fa9582b470f283748784bd6ea0558f87f42c \ + --hash=sha256:5023346c4ee7992febc0068e7593de5fa2bf611848c08404b35ebbb76b1b0512 \ + --hash=sha256:50f9d8d531dfb767c565f348f33dd5139a6c43f5cbdf3f67da40d54241df93f6 \ + --hash=sha256:51430653db848d258336cfa0244427b17d12db63d42603a55f0d4546f50f25b5 \ + --hash=sha256:531ef597132086b6cf96faa7c6c1dcd0361dd5f1694e5cc30375907b9b7d3ea9 \ + --hash=sha256:53ad387048f6f09a8969631e4de3f1bf70c50e93545d64af4f751b2498755072 \ + --hash=sha256:53b1ea6ca88ebd4420379c330aea57e258408dd0df9af0992e5de2078dc9f5d5 \ + --hash=sha256:575aa4405a656e61a540f4a80eaa5260f2a38fff7bfdc4b5f611840d76e9e277 \ + --hash=sha256:578110dd426f0d209d1509244e6d4a3f1a3e9077655d98c5f22583d63252a08a \ + --hash=sha256:5ec2f42d41ccbd5df0270d7df31618a8ee267bfa50997f5d720ddba86c4a83a6 \ + --hash=sha256:5ee586fb17ff8f90c91cf73c6108a434b02d69925f44f5f8e0d7f2f260607eae \ + --hash=sha256:5f10fd85e4b75967468af655228fbfd212bdf66db1c0d135065ce288982eda26 \ + --hash=sha256:609d3614d78d74ebe35f54953c5bbd2ac647a7ddb9c30a5d877580f5e86b22f2 \ + --hash=sha256:62694e275c93d54f7ccedcfef57d42761b2aad5234b6be1f3e3026cae4001cd4 \ + --hash=sha256:63e92247f383c85ab00dd0091e8c3fa331a96e865459f5ee80353c70a4a42d70 \ + --hash=sha256:682bae25f0a0dd23a056739f23a134db9f52a63e2afd6bfb37ddc76292bbd723 \ + --hash=sha256:6b41389c19b07c760c7e427a3462e8ab83c4bb087d127f0e854c706ce1b9215c \ + --hash=sha256:6e87a6e8735b44816e7db0b2fbc9686932df473c826b0d9743148432e10bb9b9 \ + --hash=sha256:6f0fd84de0c957b2d280143522c4f91a73aada1923caee763e24a2b3fda9f8a5 \ + --hash=sha256:70efd20be968c76ece7baa8dafe04c5be06abc57f754d6f36f3741f7aa7a208e \ + --hash=sha256:71d006bee8397a4a89f469b8deb22469fe7508132d3c17fa6ed871e79832691c \ + --hash=sha256:73309162a6a571d4cbd3b6a1dcc703c7311843ae0d1578df6f09be4e98df38d4 \ + --hash=sha256:75e3026ab649bf48f9a10c0134512638725b521340293f202a69b567518d94e0 \ + --hash=sha256:76855800ac56f878847a09ce6dba727c93ca2d89c9e9d63002d26b916810b0a2 \ + --hash=sha256:7c6b9461a2a8b47c65eef63bb1c76a4f1c119618ffa99ea79bc5bb1e46c5821b \ + --hash=sha256:803a3c3ce4acc62eaf01eaca1208dcf0783025ef27572c3336502b9c232005e7 \ + --hash=sha256:80e6d33a3d42a7549b409f199857b4fb54e2103fc44fb87605b6663b7a7ff750 \ + --hash=sha256:8419ebd326430d1cbb7efb5292330a2cf39114e82df5cc3d83c9a0d5ebeaf2f2 \ + --hash=sha256:85610b4f27f69984932a7abbe52703688de3724d9f72bceb1cca667deff27474 \ + --hash=sha256:85e9beda1f591bc73e77ea1c51965c68e98dafd0fec72cdd745f77d727466716 \ + --hash=sha256:877b0738624280e34c55680d6054a307aa94f7d52fa0e3034a9cc6e790871da7 \ + --hash=sha256:88f9fb0116fbfcefcab70f85cf4b74a2b6ce5d199c41345296f49d974ddb4123 \ + --hash=sha256:8c4fe09e0780c6c3bf2b7d4af02ee2394439d11a523bbcf095cf4747c2932007 \ + --hash=sha256:93a784271881035ab4406a172edb0faecb6e7d00f4b53dc2f55919d6c9688595 \ + --hash=sha256:94f8575fbdf81749008d980c17796097e645574a3b8c28ee313931068dad14fe \ + --hash=sha256:95451e6ce06c3e104556d73b559f5da6c34a069b6b62946d3ad66afcd51642ea \ + --hash=sha256:99c8a9ed30f4164bc4c14b37a90208836cbf50d4ce2a57c71d0f52c7fb4f7598 \ + --hash=sha256:9a18d6f9359e45722c064c97464ec883eb0e0366d33eda61cb19a244bf222679 \ + --hash=sha256:9cbf44c5cb4a7633d078788e1b56387e3d3cf2b8139a3be38040b22d6c3221c8 \ + --hash=sha256:9ee33b875f0b390564c1fb7bc528abf18c8ee6073b201c6ae8524aca778e2d83 \ + --hash=sha256:a0e317df055958a0c1e79e5d2aa5a5eaa4a6d05a20d4b0c9c3f48918139c9fc6 \ + --hash=sha256:a2df6afe50dea8ae15fa34c9f824a3ee958d785fd5d089063d960bae1daa0a3f \ + --hash=sha256:a31de1613658308efdb21ada98cbc86a97c181aa050ba22a808120bb5be3ab94 \ + --hash=sha256:a3d2bff8f37f8d0f96c7ec554d16945050d54462d6e95414babaa18bfafc7f51 \ + --hash=sha256:a41bcf68efd19073376eb8cf948b8d9be0af26256403e512bb18f3966f1f9120 \ + --hash=sha256:a82836cab5f197a0514235aaf7ffccdc886ccdaa2324bc0aafdd4ae898103039 \ + --hash=sha256:a8d00f29b42f534cc8aa3931cfe773b13b23e561e10d2b26f27a8d309b0e82a1 \ + --hash=sha256:aafe5dcfda86c8af00386d7781d4c2181b5011b7be3f2add5e99899ea925df05 \ + --hash=sha256:ab5f043cb8a2d71c981c09c510da013bc79fd661f5c60139f00dd3c3cc4f2ffb \ + --hash=sha256:ac09d42f48f80c9ee1635b2fcaa819496a44502737660d3c0f2ade7526d29144 \ + --hash=sha256:aecfed0b41aa72b7881712c65cf764e39ce2ec352324f5e0837c7048d9e6daaa \ + --hash=sha256:b2c6b50c7b0464165472b56b42d4c76a7b864597007d9c085e8b63e185cf4a7a \ + --hash=sha256:b35d13d549077713e4414f927cdc388d62e543987c572baee613bf82f11a4b99 \ + --hash=sha256:b39cb32a6582750b6cc77bfb3c49c0f8760dc18dc96ec9fb55fbb0f04e08b928 \ + --hash=sha256:b5405bb8f0e783a988172993cfc627e4d9d00432d6bbac65a923041edacf997d \ + --hash=sha256:baaf55442359053c7d62f6f8413a62adba3205119bcb6f49594894d8be47e5e3 \ + --hash=sha256:bd654fad46d8d9e823afbb4f87c79160b5a374ed1ff5bde24e542e6ba8f41434 \ + --hash=sha256:be61f6fff406ca40e3b1d84716fde398fc08bc63dd96d15f3a14230a0973ed86 \ + --hash=sha256:bf49a3ae946a87083ef3a34c8f677ae4243f5b824bfc4c69672e72b3d6719d46 \ + --hash=sha256:c4a80f77dc1acaaa61f0934176fccca7096d9b1ff08c8ba9cddf5ae034a24319 \ + --hash=sha256:c75eb09e8d55bceb4367e83496ff8ef2bc7ea6960efb38e978e8073ea59ecb67 \ + --hash=sha256:c7f8dc16c498ff06497c015642333219871effba93e4a2e8604a06264aca5c5c \ + --hash=sha256:c8aa34a5c864db1087d911a0b902d60d203ea3607d91f615acd3f3108ac32169 \ + --hash=sha256:cbb0fef01f0c6b38cb0f39b1f78fc90b807e0e3c86a7ff3ce74ad77ce5c7880c \ + --hash=sha256:cde9a2ecd91668bcb7f077c4966d8ceddb60af01b52e6e3e2680e4cf00ad1a59 \ + --hash=sha256:cff6d44cb13d39db2663a22b22305d10855efa0fa8015ddeacc40bc59b9d8107 \ + --hash=sha256:d1009abedb49ae95b136a8904a3f71b342f849ffeced2d3747bf29caeda218c4 \ + --hash=sha256:d38c1e8231722c4ce40d7593f28d92b5fc72f3e9774fe73d7e800ec32299f63a \ + --hash=sha256:d53834e23c015ee83a99377db6e5e37d8484f333edb03bd15b4bc312cc7254fb \ + --hash=sha256:d7504f2b476d21653e4d143f44a175f7f751cd41233525312696c76aa3dbb23f \ + --hash=sha256:dbf507e9ef5688bada447a24d68b4b58dd389ba93b7afc065a2ba892bea54769 \ + --hash=sha256:dc52310451fc7c629e13c4e061cbe2dd01684d91f2f8ee2821b083c58bd72432 \ + --hash=sha256:dd00607bffbf30250fe108065f07453ec124dbf223420f57f5e749b04295e090 \ + --hash=sha256:dda608c88cf709b1d406bdfcd84d8d63cff7c9e577a403c6108ce8ce9dcc8764 \ + --hash=sha256:debe9c4f41c32990771be5c22b56f810659f9ddf3d63f67abfdcaa2c6c9c5c1d \ + --hash=sha256:e09fd068c2e169a7070d83d3bde728a4d48de0549f975290be3c108c02e499b4 \ + --hash=sha256:e0fd068364a6759bc794459f0a735ab151d11304346332489c7972bacbe9e72b \ + --hash=sha256:e4c53f8347cd4200f0d70a48ad059cabaf24f5adc6ba08622a23423bc7efa10d \ + --hash=sha256:e5723c01a56c5028c807c701aa66722916d2747ad737a046853f6c46f4875543 \ + --hash=sha256:e7b0460976dc75cb87ad9cc1f9899a4b97751e7d4e77ab840fc9b6d377b8fd24 \ + --hash=sha256:e9d9a4d06d3481eab79803beb4d9bd6f6a8e781ec078ac70d7ef2dcc29d1bea5 \ + --hash=sha256:ead11956716a940c1abc816b7df3fa2b84d06eaed8832ca32f5c5e058c65506b \ + --hash=sha256:ed5f69ce7be7902e5c70ea19eb72d20abf7d725ab5d49777d696e32d4fc1811d \ + --hash=sha256:f2af5c81a1f124609d5f33507082fc3f739959d4719b56877ab1ee7e7b3d602b \ + --hash=sha256:f40e782d49630ad384db66d4d8b73ff4f1b8955dc12e26b09a3e3af064b3b9d6 \ + --hash=sha256:f514f6474e04179d3d33175ed3f3e31434d3130d42ec153540d5b157deefd735 \ + --hash=sha256:f69f57305656a4852f2a7203efc661d8c042e6cc67f7acd97d8667fb448a426e \ + --hash=sha256:fb1e8b8d66c278b21d13b0a7ca22c41dd757a7c209c6b12c313e445c31dd3b28 \ + --hash=sha256:fb4948814a2a98e3912505f09c9e7493b1506226afb1f881825368d6fb776ee3 \ + --hash=sha256:fda207c815b253e34f7e1909840fd14299567b1c0eb4908f8c2ce01a41265401 \ + --hash=sha256:fe8f8f5e70e6dbdfca9882cd9deaac058729bcf323cf7a58660901e55c9c94f6 \ + --hash=sha256:fffc45637bcd6538de8b85f51e3df3223e4ad89bccbfca0481c08c7fc8b7ed7d # via aiohttp # The following packages were excluded from the output: diff --git a/sdk/python/requirements/py3.12-requirements.txt b/sdk/python/requirements/py3.12-requirements.txt index fd1728e2ab2..bd0810289bc 100644 --- a/sdk/python/requirements/py3.12-requirements.txt +++ b/sdk/python/requirements/py3.12-requirements.txt @@ -8,140 +8,156 @@ annotated-types==0.7.0 \ --hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \ --hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89 # via pydantic -anyio==4.12.1 \ - --hash=sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703 \ - --hash=sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c +anyio==4.13.0 \ + --hash=sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708 \ + --hash=sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc # via # starlette # watchfiles -attrs==25.4.0 \ - --hash=sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11 \ - --hash=sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373 +attrs==26.1.0 \ + --hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \ + --hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32 # via # jsonschema # referencing -bigtree==1.3.1 \ - --hash=sha256:a22a0ecd9b0abb283f4a1515370dbf1ec93adee70746767272e2c49d7af9f407 \ - --hash=sha256:c8b766b00188c532d3499bfd9e9666b357428db507fc701f088031a0d5c614d5 +bigtree==1.4.0 \ + --hash=sha256:d0d99550ae64ce4529f132602ab875c2ab472c96c942f5704f8c72a17450d3ea \ + --hash=sha256:e5ae2e948168da671d99601c9ed87ab3b48d9d4ea8a98f111e5748e98064c31c # via feast (pyproject.toml) -certifi==2026.1.4 \ - --hash=sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c \ - --hash=sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120 +certifi==2026.2.25 \ + --hash=sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa \ + --hash=sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7 # via requests -charset-normalizer==3.4.4 \ - --hash=sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad \ - --hash=sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93 \ - --hash=sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394 \ - --hash=sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89 \ - --hash=sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc \ - --hash=sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86 \ - --hash=sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63 \ - --hash=sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d \ - --hash=sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f \ - --hash=sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8 \ - --hash=sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0 \ - --hash=sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505 \ - --hash=sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161 \ - --hash=sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af \ - --hash=sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152 \ - --hash=sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318 \ - --hash=sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72 \ - --hash=sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4 \ - --hash=sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e \ - --hash=sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3 \ - --hash=sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576 \ - --hash=sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c \ - --hash=sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1 \ - --hash=sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8 \ - --hash=sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1 \ - --hash=sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2 \ - --hash=sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44 \ - --hash=sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26 \ - --hash=sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88 \ - --hash=sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016 \ - --hash=sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede \ - --hash=sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf \ - --hash=sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a \ - --hash=sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc \ - --hash=sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0 \ - --hash=sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84 \ - --hash=sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db \ - --hash=sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1 \ - --hash=sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7 \ - --hash=sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed \ - --hash=sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8 \ - --hash=sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133 \ - --hash=sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e \ - --hash=sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef \ - --hash=sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14 \ - --hash=sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2 \ - --hash=sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0 \ - --hash=sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d \ - --hash=sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828 \ - --hash=sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f \ - --hash=sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf \ - --hash=sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6 \ - --hash=sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328 \ - --hash=sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090 \ - --hash=sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa \ - --hash=sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381 \ - --hash=sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c \ - --hash=sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb \ - --hash=sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc \ - --hash=sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a \ - --hash=sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec \ - --hash=sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc \ - --hash=sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac \ - --hash=sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e \ - --hash=sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313 \ - --hash=sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569 \ - --hash=sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3 \ - --hash=sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d \ - --hash=sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525 \ - --hash=sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894 \ - --hash=sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3 \ - --hash=sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9 \ - --hash=sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a \ - --hash=sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9 \ - --hash=sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14 \ - --hash=sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25 \ - --hash=sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50 \ - --hash=sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf \ - --hash=sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1 \ - --hash=sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3 \ - --hash=sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac \ - --hash=sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e \ - --hash=sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815 \ - --hash=sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c \ - --hash=sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6 \ - --hash=sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6 \ - --hash=sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e \ - --hash=sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4 \ - --hash=sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84 \ - --hash=sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69 \ - --hash=sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15 \ - --hash=sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191 \ - --hash=sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0 \ - --hash=sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897 \ - --hash=sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd \ - --hash=sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2 \ - --hash=sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794 \ - --hash=sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d \ - --hash=sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074 \ - --hash=sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3 \ - --hash=sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224 \ - --hash=sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838 \ - --hash=sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a \ - --hash=sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d \ - --hash=sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d \ - --hash=sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f \ - --hash=sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8 \ - --hash=sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490 \ - --hash=sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966 \ - --hash=sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9 \ - --hash=sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3 \ - --hash=sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e \ - --hash=sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608 +charset-normalizer==3.4.7 \ + --hash=sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc \ + --hash=sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c \ + --hash=sha256:07d9e39b01743c3717745f4c530a6349eadbfa043c7577eef86c502c15df2c67 \ + --hash=sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4 \ + --hash=sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0 \ + --hash=sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c \ + --hash=sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5 \ + --hash=sha256:12a6fff75f6bc66711b73a2f0addfc4c8c15a20e805146a02d147a318962c444 \ + --hash=sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153 \ + --hash=sha256:14265bfe1f09498b9d8ec91e9ec9fa52775edf90fcbde092b25f4a33d444fea9 \ + --hash=sha256:16d971e29578a5e97d7117866d15889a4a07befe0e87e703ed63cd90cb348c01 \ + --hash=sha256:177a0ba5f0211d488e295aaf82707237e331c24788d8d76c96c5a41594723217 \ + --hash=sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b \ + --hash=sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c \ + --hash=sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a \ + --hash=sha256:1dc8b0ea451d6e69735094606991f32867807881400f808a106ee1d963c46a83 \ + --hash=sha256:1efde3cae86c8c273f1eb3b287be7d8499420cf2fe7585c41d370d3e790054a5 \ + --hash=sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7 \ + --hash=sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb \ + --hash=sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c \ + --hash=sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1 \ + --hash=sha256:2cd4a60d0e2fb04537162c62bbbb4182f53541fe0ede35cdf270a1c1e723cc42 \ + --hash=sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab \ + --hash=sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df \ + --hash=sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e \ + --hash=sha256:320ade88cfb846b8cd6b4ddf5ee9e80ee0c1f52401f2456b84ae1ae6a1a5f207 \ + --hash=sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18 \ + --hash=sha256:36836d6ff945a00b88ba1e4572d721e60b5b8c98c155d465f56ad19d68f23734 \ + --hash=sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38 \ + --hash=sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110 \ + --hash=sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18 \ + --hash=sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44 \ + --hash=sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d \ + --hash=sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48 \ + --hash=sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e \ + --hash=sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5 \ + --hash=sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d \ + --hash=sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53 \ + --hash=sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790 \ + --hash=sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c \ + --hash=sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b \ + --hash=sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116 \ + --hash=sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d \ + --hash=sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10 \ + --hash=sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6 \ + --hash=sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2 \ + --hash=sha256:6370e8686f662e6a3941ee48ed4742317cafbe5707e36406e9df792cdb535776 \ + --hash=sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a \ + --hash=sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265 \ + --hash=sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008 \ + --hash=sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943 \ + --hash=sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374 \ + --hash=sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246 \ + --hash=sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e \ + --hash=sha256:6e0d51f618228538a3e8f46bd246f87a6cd030565e015803691603f55e12afb5 \ + --hash=sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616 \ + --hash=sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15 \ + --hash=sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41 \ + --hash=sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960 \ + --hash=sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752 \ + --hash=sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e \ + --hash=sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72 \ + --hash=sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7 \ + --hash=sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8 \ + --hash=sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b \ + --hash=sha256:813c0e0132266c08eb87469a642cb30aaff57c5f426255419572aaeceeaa7bf4 \ + --hash=sha256:82b271f5137d07749f7bf32f70b17ab6eaabedd297e75dce75081a24f76eb545 \ + --hash=sha256:84c018e49c3bf790f9c2771c45e9313a08c2c2a6342b162cd650258b57817706 \ + --hash=sha256:8751d2787c9131302398b11e6c8068053dcb55d5a8964e114b6e196cf16cb366 \ + --hash=sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb \ + --hash=sha256:87fad7d9ba98c86bcb41b2dc8dbb326619be2562af1f8ff50776a39e55721c5a \ + --hash=sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e \ + --hash=sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00 \ + --hash=sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f \ + --hash=sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a \ + --hash=sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1 \ + --hash=sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66 \ + --hash=sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356 \ + --hash=sha256:a6c5863edfbe888d9eff9c8b8087354e27618d9da76425c119293f11712a6319 \ + --hash=sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4 \ + --hash=sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad \ + --hash=sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d \ + --hash=sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5 \ + --hash=sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7 \ + --hash=sha256:aef65cd602a6d0e0ff6f9930fcb1c8fec60dd2cfcb6facaf4bdb0e5873042db0 \ + --hash=sha256:af21eb4409a119e365397b2adbaca4c9ccab56543a65d5dbd9f920d6ac29f686 \ + --hash=sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34 \ + --hash=sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49 \ + --hash=sha256:bb8cc7534f51d9a017b93e3e85b260924f909601c3df002bcdb58ddb4dc41a5c \ + --hash=sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1 \ + --hash=sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e \ + --hash=sha256:bd9b23791fe793e4968dba0c447e12f78e425c59fc0e3b97f6450f4781f3ee60 \ + --hash=sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0 \ + --hash=sha256:c0f081d69a6e58272819b70288d3221a6ee64b98df852631c80f293514d3b274 \ + --hash=sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d \ + --hash=sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0 \ + --hash=sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae \ + --hash=sha256:c593052c465475e64bbfe5dbd81680f64a67fdc752c56d7a0ae205dc8aeefe0f \ + --hash=sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d \ + --hash=sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe \ + --hash=sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3 \ + --hash=sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393 \ + --hash=sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1 \ + --hash=sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af \ + --hash=sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44 \ + --hash=sha256:d61f00a0869d77422d9b2aba989e2d24afa6ffd552af442e0e58de4f35ea6d00 \ + --hash=sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c \ + --hash=sha256:dca4bbc466a95ba9c0234ef56d7dd9509f63da22274589ebd4ed7f1f4d4c54e3 \ + --hash=sha256:dd915403e231e6b1809fe9b6d9fc55cf8fb5e02765ac625d9cd623342a7905d7 \ + --hash=sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd \ + --hash=sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e \ + --hash=sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b \ + --hash=sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8 \ + --hash=sha256:e5f4d355f0a2b1a31bc3edec6795b46324349c9cb25eed068049e4f472fb4259 \ + --hash=sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859 \ + --hash=sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46 \ + --hash=sha256:e80c8378d8f3d83cd3164da1ad2df9e37a666cdde7b1cb2298ed0b558064be30 \ + --hash=sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b \ + --hash=sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46 \ + --hash=sha256:ed065083d0898c9d5b4bbec7b026fd755ff7454e6e8b73a67f8c744b13986e24 \ + --hash=sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a \ + --hash=sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24 \ + --hash=sha256:f22dec1690b584cea26fade98b2435c132c1b5f68e39f5a0b7627cd7ae31f1dc \ + --hash=sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215 \ + --hash=sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063 \ + --hash=sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832 \ + --hash=sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6 \ + --hash=sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79 \ + --hash=sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464 # via requests click==8.3.1 \ --hash=sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a \ @@ -158,25 +174,25 @@ colorama==0.4.6 \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 # via feast (pyproject.toml) -dask[dataframe]==2026.1.2 \ - --hash=sha256:1136683de2750d98ea792670f7434e6c1cfce90cab2cc2f2495a9e60fd25a4fc \ - --hash=sha256:46a0cf3b8d87f78a3d2e6b145aea4418a6d6d606fe6a16c79bd8ca2bb862bc91 +dask[dataframe]==2026.3.0 \ + --hash=sha256:be614b9242b0b38288060fb2d7696125946469c98a1c30e174883fd199e0428d \ + --hash=sha256:f7d96c8274e8a900d217c1ff6ea8d1bbf0b4c2c21e74a409644498d925eb8f85 # via feast (pyproject.toml) dill==0.3.9 \ --hash=sha256:468dff3b89520b474c0397703366b7b95eebe6303f108adf9b19da1f702be87a \ --hash=sha256:81aa267dddf68cbfe8029c42ca9ec6a4ab3b22371d1c450abc54422577b4512c # via feast (pyproject.toml) -fastapi==0.129.0 \ - --hash=sha256:61315cebd2e65df5f97ec298c888f9de30430dd0612d59d6480beafbc10655af \ - --hash=sha256:b4946880e48f462692b31c083be0432275cbfb6e2274566b1be91479cc1a84ec +fastapi==0.135.3 \ + --hash=sha256:9b0f590c813acd13d0ab43dd8494138eb58e484bfac405db1f3187cfc5810d98 \ + --hash=sha256:bd6d7caf1a2bdd8d676843cdcd2287729572a1ef524fc4d65c17ae002a1be654 # via feast (pyproject.toml) -fsspec==2026.2.0 \ - --hash=sha256:6544e34b16869f5aacd5b90bdf1a71acb37792ea3ddf6125ee69a22a53fb8bff \ - --hash=sha256:98de475b5cb3bd66bedd5c4679e87b4fdfe1a3bf4d707b151b3c07e58c9a2437 +fsspec==2026.3.0 \ + --hash=sha256:1ee6a0e28677557f8c2f994e3eea77db6392b4de9cd1f5d7a9e87a0ae9d01b41 \ + --hash=sha256:d2ceafaad1b3457968ed14efa28798162f1638dbb5d2a6868a2db002a5ee39a4 # via dask -gunicorn==25.1.0 \ - --hash=sha256:1426611d959fa77e7de89f8c0f32eed6aa03ee735f98c01efba3e281b1c47616 \ - --hash=sha256:d0b1236ccf27f72cfe14bce7caadf467186f19e865094ca84221424e839b8b8b +gunicorn==25.3.0 \ + --hash=sha256:cacea387dab08cd6776501621c295a904fe8e3b7aae9a1a3cbb26f4e7ed54660 \ + --hash=sha256:f74e1b2f9f76f6cd1ca01198968bd2dd65830edc24b6e8e4d78de8320e2fe889 # via # feast (pyproject.toml) # uvicorn-worker @@ -247,97 +263,97 @@ jsonschema-specifications==2025.9.1 \ --hash=sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe \ --hash=sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d # via jsonschema -librt==0.8.0 \ - --hash=sha256:001e5330093d887b8b9165823eca6c5c4db183fe4edea4fdc0680bbac5f46944 \ - --hash=sha256:015e2dde6e096d27c10238bf9f6492ba6c65822dfb69d2bf74c41a8e88b7ddef \ - --hash=sha256:02a9fe85410cc9bef045e7cb7fd26fdde6669e6d173f99df659aa7f6335961e9 \ - --hash=sha256:0583aef7e9a720dd40f26a2ad5a1bf2ccbb90059dac2b32ac516df232c701db3 \ - --hash=sha256:05a3dd3f116747f7e1a2b475ccdc6fb637fd4987126d109e03013a79d40bf9e6 \ - --hash=sha256:0a33335eb59921e77c9acc05d0e654e4e32e45b014a4d61517897c11591094f8 \ - --hash=sha256:0ce33a9778e294507f3a0e3468eccb6a698b5166df7db85661543eca1cfc5369 \ - --hash=sha256:1566dbb9d1eb0987264c9b9460d212e809ba908d2f4a3999383a84d765f2f3f1 \ - --hash=sha256:17269dd2745dbe8e42475acb28e419ad92dfa38214224b1b01020b8cac70b645 \ - --hash=sha256:178707cda89d910c3b28bf5aa5f69d3d4734e0f6ae102f753ad79edef83a83c7 \ - --hash=sha256:1c25a131013eadd3c600686a0c0333eb2896483cbc7f65baa6a7ee761017aef9 \ - --hash=sha256:1e6811cac1dcb27ca4c74e0ca4a5917a8e06db0d8408d30daee3a41724bfde7a \ - --hash=sha256:1ef3bd856373cf8e7382402731f43bfe978a8613b4039e49e166e1e0dc590216 \ - --hash=sha256:20f73d4fecba969efc15cdefd030e382502d56bb6f1fc66b580cce582836c9fa \ - --hash=sha256:21b14464bee0b604d80a638cf1ee3148d84ca4cc163dcdcecb46060c1b3605e4 \ - --hash=sha256:24a01c13a2a9bdad20997a4443ebe6e329df063d1978bbe2ebbf637878a46d1e \ - --hash=sha256:25b3e667cbfc9000c4740b282df599ebd91dbdcc1aa6785050e4c1d6be5329ab \ - --hash=sha256:25e82d920d4d62ad741592fcf8d0f3bda0e3fc388a184cb7d2f566c681c5f7b9 \ - --hash=sha256:2b37437e7e4ef5e15a297b36ba9e577f73e29564131d86dd75875705e97402b5 \ - --hash=sha256:2ccdd20d9a72c562ffb73098ac411de351b53a6fbb3390903b2d33078ef90447 \ - --hash=sha256:2e0ffe88ebb5962f8fb0ddcbaaff30f1ea06a79501069310e1e030eafb1ad787 \ - --hash=sha256:375eda7acfce1f15f5ed56cfc960669eefa1ec8732e3e9087c3c4c3f2066759c \ - --hash=sha256:3d2720335020219197380ccfa5c895f079ac364b4c429e96952cd6509934d8eb \ - --hash=sha256:3e36a8da17134ffc29373775d88c04832f9ecfab1880470661813e6c7991ef79 \ - --hash=sha256:3e8b77b5f54d0937b26512774916041756c9eb3e66f1031971e626eea49d0bf4 \ - --hash=sha256:41064a0c07b4cc7a81355ccc305cb097d6027002209ffca51306e65ee8293630 \ - --hash=sha256:421765e8c6b18e64d21c8ead315708a56fc24f44075059702e421d164575fdda \ - --hash=sha256:4831c44b8919e75ca0dfb52052897c1ef59fdae19d3589893fbd068f1e41afbf \ - --hash=sha256:48f84830a8f8ad7918afd743fd7c4eb558728bceab7b0e38fd5a5cf78206a556 \ - --hash=sha256:4b705f85311ee76acec5ee70806990a51f0deb519ea0c29c1d1652d79127604d \ - --hash=sha256:4d3e38797eb482485b486898f89415a6ab163bc291476bd95712e42cf4383c05 \ - --hash=sha256:4eb5e06ebcc668677ed6389164f52f13f71737fc8be471101fa8b4ce77baeb0c \ - --hash=sha256:4f6e975377fbc4c9567cb33ea9ab826031b6c7ec0515bfae66a4fb110d40d6da \ - --hash=sha256:4f764b2424cb04524ff7a486b9c391e93f93dc1bd8305b2136d25e582e99aa2f \ - --hash=sha256:507e94f4bec00b2f590fbe55f48cd518a208e2474a3b90a60aa8f29136ddbada \ - --hash=sha256:56901f1eec031396f230db71c59a01d450715cbbef9856bf636726994331195d \ - --hash=sha256:5cb11061a736a9db45e3c1293cfcb1e3caf205912dfa085734ba750f2197ff9a \ - --hash=sha256:5d0f76fc73480d42285c609c0ea74d79856c160fa828ff9aceab574ea4ecfd7b \ - --hash=sha256:667e2513cf69bfd1e1ed9a00d6c736d5108714ec071192afb737987955888a25 \ - --hash=sha256:671a6152edf3b924d98a5ed5e6982ec9cb30894085482acadce0975f031d4c5c \ - --hash=sha256:693697133c3b32aa9b27f040e3691be210e9ac4d905061859a9ed519b1d5a376 \ - --hash=sha256:6a3146c63220d814c4a2c7d6a1eacc8d5c14aed0ff85115c1dfea868080cd18f \ - --hash=sha256:6b6caff69e25d80c269b1952be8493b4d94ef745f438fa619d7931066bdd26de \ - --hash=sha256:6e1af31a710e17891d9adf0dbd9a5fcd94901a3922a96499abdbf7ce658f4e01 \ - --hash=sha256:70defb797c4d5402166787a6b3c66dfb3fa7f93d118c0509ffafa35a392f4258 \ - --hash=sha256:71fc517efc14f75c2f74b1f0a5d5eb4a8e06aa135c34d18eaf3522f4a53cd62d \ - --hash=sha256:75d1a8cab20b2043f03f7aab730551e9e440adc034d776f15f6f8d582b0a5ad4 \ - --hash=sha256:789911e8fa40a2e82f41120c936b1965f3213c67f5a483fc5a41f5839a05dcbb \ - --hash=sha256:7bd68cebf3131bb920d5984f75fe302d758db33264e44b45ad139385662d7bc3 \ - --hash=sha256:7ce0a8cb67e702dcb06342b2aaaa3da9fb0ddc670417879adfa088b44cf7b3b6 \ - --hash=sha256:7f820210e21e3a8bf8fde2ae3c3d10106d4de9ead28cbfdf6d0f0f41f5b12fa1 \ - --hash=sha256:8070aa3368559de81061ef752770d03ca1f5fc9467d4d512d405bd0483bfffe6 \ - --hash=sha256:82e61cd1c563745ad495387c3b65806bfd453badb4adbc019df3389dddee1bf6 \ - --hash=sha256:82fb4602d1b3e303a58bfe6165992b5a78d823ec646445356c332cd5f5bbaa61 \ - --hash=sha256:88c6e75540f1f10f5e0fc5e87b4b6c290f0e90d1db8c6734f670840494764af8 \ - --hash=sha256:8992ca186a1678107b0af3d0c9303d8c7305981b9914989b9788319ed4d89546 \ - --hash=sha256:92249938ab744a5890580d3cb2b22042f0dce71cdaa7c1369823df62bedf7cbc \ - --hash=sha256:95a719a049f0eefaf1952673223cf00d442952273cbd20cf2ed7ec423a0ef58d \ - --hash=sha256:9646178cd794704d722306c2c920c221abbf080fede3ba539d5afdec16c46dad \ - --hash=sha256:9726305d3e53419d27fc8cdfcd3f9571f0ceae22fa6b5ea1b3662c2e538f833e \ - --hash=sha256:995d24caa6bbb34bcdd4a41df98ac6d1af637cfa8975cb0790e47d6623e70e3e \ - --hash=sha256:9ab3a3475a55b89b87ffd7e6665838e8458e0b596c22e0177e0f961434ec474a \ - --hash=sha256:9f09d4884f882baa39a7e36bbf3eae124c4ca2a223efb91e567381d1c55c6b06 \ - --hash=sha256:a512c88900bdb1d448882f5623a0b1ad27ba81a9bd75dacfe17080b72272ca1f \ - --hash=sha256:a905091a13e0884701226860836d0386b88c72ce5c2fdfba6618e14c72be9f25 \ - --hash=sha256:aaadec87f45a3612b6818d1db5fbfe93630669b7ee5d6bdb6427ae08a1aa2141 \ - --hash=sha256:b055bb3abaf69abed25743d8fc1ab691e4f51a912ee0a6f9a6c84f4bbddb283d \ - --hash=sha256:b4bb00bd71b448f16749909b08a0ff16f58b079e2261c2e1000f2bbb2a4f0a45 \ - --hash=sha256:b9aef96d7593584e31ef6ac1eb9775355b0099fee7651fae3a15bc8657b67b52 \ - --hash=sha256:ba581acad5ac8f33e2ff1746e8a57e001b47c6721873121bf8bbcf7ba8bd3aa4 \ - --hash=sha256:ba9d9e60651615bc614be5e21a82cdb7b1769a029369cf4b4d861e4f19686fb6 \ - --hash=sha256:bbebd2bba5c6ae02907df49150e55870fdd7440d727b6192c46b6f754723dde9 \ - --hash=sha256:bd32add59b58fba3439d48d6f36ac695830388e3da3e92e4fc26d2d02670d19c \ - --hash=sha256:bdab762e2c0b48bab76f1a08acb3f4c77afd2123bedac59446aeaaeed3d086cf \ - --hash=sha256:c5512aae4648152abaf4d48b59890503fcbe86e85abc12fb9b096fe948bdd816 \ - --hash=sha256:c6e4c10761ddbc0d67d2f6e2753daf99908db85d8b901729bf2bf5eaa60e0567 \ - --hash=sha256:cb4b3ad543084ed79f186741470b251b9d269cd8b03556f15a8d1a99a64b7de5 \ - --hash=sha256:cb74cdcbc0103fc988e04e5c58b0b31e8e5dd2babb9182b6f9490488eb36324b \ - --hash=sha256:cc3d107f603b5ee7a79b6aa6f166551b99b32fb4a5303c4dfcb4222fc6a0335e \ - --hash=sha256:d920789eca7ef71df7f31fd547ec0d3002e04d77f30ba6881e08a630e7b2c30e \ - --hash=sha256:daae5e955764be8fd70a93e9e5133c75297f8bce1e802e1d3683b98f77e1c5ab \ - --hash=sha256:db63cf3586a24241e89ca1ce0b56baaec9d371a328bd186c529b27c914c9a1ef \ - --hash=sha256:db953b675079884ffda33d1dca7189fb961b6d372153750beb81880384300817 \ - --hash=sha256:de076eaba208d16efb5962f99539867f8e2c73480988cb513fcf1b5dbb0c9dcf \ - --hash=sha256:e79dbc8f57de360f0ed987dc7de7be814b4803ef0e8fc6d3ff86e16798c99935 \ - --hash=sha256:e9a3a38eb4134ad33122a6d575e6324831f930a771d951a15ce232e0237412c2 \ - --hash=sha256:f04ca50e847abc486fa8f4107250566441e693779a5374ba211e96e238f298b9 \ - --hash=sha256:f1178e0de0c271231a660fbef9be6acdfa1d596803464706862bef6644cc1cae \ - --hash=sha256:f4617cef654fca552f00ce5ffdf4f4b68770f18950e4246ce94629b789b92467 \ - --hash=sha256:fa37f99bff354ff191c6bcdffbc9d7cdd4fc37faccfc9be0ef3a4fd5613977da +librt==0.8.1 \ + --hash=sha256:01170b6729a438f0dedc4a26ed342e3dc4f02d1000b4b19f980e1877f0c297e6 \ + --hash=sha256:039b9f2c506bd0ab0f8725aa5ba339c6f0cd19d3b514b50d134789809c24285d \ + --hash=sha256:05bd41cdee35b0c59c259f870f6da532a2c5ca57db95b5f23689fcb5c9e42440 \ + --hash=sha256:086a32dbb71336627e78cc1d6ee305a68d038ef7d4c39aaff41ae8c9aa46e91a \ + --hash=sha256:08eec3a1fc435f0d09c87b6bf1ec798986a3544f446b864e4099633a56fcd9ed \ + --hash=sha256:0bf69d79a23f4f40b8673a947a234baeeb133b5078b483b7297c5916539cf5d5 \ + --hash=sha256:0c3811485fccfda840861905b8c70bba5ec094e02825598bb9d4ca3936857a04 \ + --hash=sha256:0d2f82168e55ddefd27c01c654ce52379c0750ddc31ee86b4b266bcf4d65f2a3 \ + --hash=sha256:0f2ae3725904f7377e11cc37722d5d401e8b3d5851fb9273d7f4fe04f6b3d37d \ + --hash=sha256:10c42e1f6fd06733ef65ae7bebce2872bcafd8d6e6b0a08fe0a05a23b044fb14 \ + --hash=sha256:153188fe98a72f206042be10a2c6026139852805215ed9539186312d50a8e972 \ + --hash=sha256:172d57ec04346b047ca6af181e1ea4858086c80bdf455f61994c4aa6fc3f866c \ + --hash=sha256:190b109bb69592a3401fe1ffdea41a2e73370ace2ffdc4a0e8e2b39cdea81b78 \ + --hash=sha256:1d3a7da44baf692f0c6aeb5b2a09c5e6fc7a703bca9ffa337ddd2e2da53f7732 \ + --hash=sha256:228c2409c079f8c11fb2e5d7b277077f694cb93443eb760e00b3b83cb8b3176c \ + --hash=sha256:22b46eabd76c1986ee7d231b0765ad387d7673bbd996aa0d0d054b38ac65d8f6 \ + --hash=sha256:237796479f4d0637d6b9cbcb926ff424a97735e68ade6facf402df4ec93375ed \ + --hash=sha256:2c74a2da57a094bd48d03fa5d196da83d2815678385d2978657499063709abe1 \ + --hash=sha256:2cc68eeeef5e906839c7bb0815748b5b0a974ec27125beefc0f942715785b551 \ + --hash=sha256:2eb345e8b33fb748227409c9f1233d4df354d6e54091f0e8fc53acdb2ffedeb7 \ + --hash=sha256:31362dbfe297b23590530007062c32c6f6176f6099646bb2c95ab1b00a57c382 \ + --hash=sha256:3dff3d3ca8db20e783b1bc7de49c0a2ab0b8387f31236d6a026597d07fcd68ac \ + --hash=sha256:43353b943613c5d9c49a25aaffdba46f888ec354e71e3529a00cca3f04d66a7a \ + --hash=sha256:439352ba9373f11cb8e1933da194dcc6206daf779ff8df0ed69c5e39113e6a99 \ + --hash=sha256:4998009e7cb9e896569f4be7004f09d0ed70d386fa99d42b6d363f6d200501ac \ + --hash=sha256:4be2a5c926b9770c9e08e717f05737a269b9d0ebc5d2f0060f0fe3fe9ce47acb \ + --hash=sha256:4beb04b8c66c6ae62f8c1e0b2f097c1ebad9295c929a8d5286c05eae7c2fc7dc \ + --hash=sha256:4c8dfa264b9193c4ee19113c985c95f876fae5e51f731494fc4e0cf594990ba7 \ + --hash=sha256:5212a5bd7fae98dae95710032902edcd2ec4dc994e883294f75c857b83f9aba0 \ + --hash=sha256:52c224e14614b750c0a6d97368e16804a98c684657c7518752c356834fff83bb \ + --hash=sha256:56e04c14b696300d47b3bc5f1d10a00e86ae978886d0cee14e5714fafb5df5d2 \ + --hash=sha256:5bb54f1205a3a6ab41a6fd71dfcdcbd278670d3a90ca502a30d9da583105b6f7 \ + --hash=sha256:5cdc0f588ff4b663ea96c26d2a230c525c6fc62b28314edaaaca8ed5af931ad0 \ + --hash=sha256:5db05697c82b3a2ec53f6e72b2ed373132b0c2e05135f0696784e97d7f5d48e7 \ + --hash=sha256:5e4af413908f77294605e28cfd98063f54b2c790561383971d2f52d113d9c363 \ + --hash=sha256:5fc48998000cbc39ec0d5311312dda93ecf92b39aaf184c5e817d5d440b29624 \ + --hash=sha256:60a78b694c9aee2a0f1aaeaa7d101cf713e92e8423a941d2897f4fa37908dab9 \ + --hash=sha256:64548cde61b692dc0dc379f4b5f59a2f582c2ebe7890d09c1ae3b9e66fa015b7 \ + --hash=sha256:681dc2451d6d846794a828c16c22dc452d924e9f700a485b7ecb887a30aad1fd \ + --hash=sha256:6b1977c4ea97ce5eb7755a78fae68d87e4102e4aaf54985e8b56806849cc06a3 \ + --hash=sha256:6cfa7fe54fd4d1f47130017351a959fe5804bda7a0bc7e07a2cdbc3fdd28d34f \ + --hash=sha256:738f08021b3142c2918c03692608baed43bc51144c29e35807682f8070ee2a3a \ + --hash=sha256:747328be0c5b7075cde86a0e09d7a9196029800ba75a1689332348e998fb85c0 \ + --hash=sha256:758509ea3f1eba2a57558e7e98f4659d0ea7670bff49673b0dde18a3c7e6c0eb \ + --hash=sha256:785ae29c1f5c6e7c2cde2c7c0e148147f4503da3abc5d44d482068da5322fd9e \ + --hash=sha256:7aae78ab5e3206181780e56912d1b9bb9f90a7249ce12f0e8bf531d0462dd0fc \ + --hash=sha256:7b02679a0d783bdae30d443025b94465d8c3dc512f32f5b5031f93f57ac32071 \ + --hash=sha256:7e2f3edca35664499fbb36e4770650c4bd4a08abc1f4458eab9df4ec56389730 \ + --hash=sha256:7e6bad1cd94f6764e1e21950542f818a09316645337fd5ab9a7acc45d99a8f35 \ + --hash=sha256:81fd938344fecb9373ba1b155968c8a329491d2ce38e7ddb76f30ffb938f12dc \ + --hash=sha256:82210adabbc331dbb65d7868b105185464ef13f56f7f76688565ad79f648b0fe \ + --hash=sha256:89815a22daf9c51884fb5dbe4f1ef65ee6a146e0b6a8df05f753e2e4a9359bf4 \ + --hash=sha256:8f1125e6bbf2f1657d9a2f3ccc4a2c9b0c8b176965bb565dd4d86be67eddb4b6 \ + --hash=sha256:8f4bb453f408137d7581be309b2fbc6868a80e7ef60c88e689078ee3a296ae71 \ + --hash=sha256:924817ab3141aca17893386ee13261f1d100d1ef410d70afe4389f2359fea4f0 \ + --hash=sha256:93c2af9e01e0ef80d95ae3c720be101227edae5f2fe7e3dc63d8857fadfc5a1d \ + --hash=sha256:97c2b54ff6717a7a563b72627990bec60d8029df17df423f0ed37d56a17a176b \ + --hash=sha256:9be2f15e53ce4e83cc08adc29b26fb5978db62ef2a366fbdf716c8a6c8901040 \ + --hash=sha256:9e2c6f77b9ad48ce5603b83b7da9ee3e36b3ab425353f695cba13200c5d96596 \ + --hash=sha256:a28f2612ab566b17f3698b0da021ff9960610301607c9a5e8eaca62f5e1c350a \ + --hash=sha256:a355d99c4c0d8e5b770313b8b247411ed40949ca44e33e46a4789b9293a907ee \ + --hash=sha256:a3b4350b13cc0e6f5bec8fa7caf29a8fb8cdc051a3bae45cfbfd7ce64f009965 \ + --hash=sha256:aaab0e307e344cb28d800957ef3ec16605146ef0e59e059a60a176d19543d1b7 \ + --hash=sha256:ac1e7817fd0ed3d14fd7c5df91daed84c48e4c2a11ee99c0547f9f62fdae13da \ + --hash=sha256:adfab487facf03f0d0857b8710cf82d0704a309d8ffc33b03d9302b4c64e91a9 \ + --hash=sha256:b6d7ab1f01aa753188605b09a51faa44a3327400b00b8cce424c71910fc0a128 \ + --hash=sha256:bacdb58d9939d95cc557b4dbaa86527c9db2ac1ed76a18bc8d26f6dc8647d851 \ + --hash=sha256:be46a14693955b3bd96014ccbdb8339ee8c9346fbe11c1b78901b55125f14c73 \ + --hash=sha256:bf512a71a23504ed08103a13c941f763db13fb11177beb3d9244c98c29fb4a61 \ + --hash=sha256:c00e5c884f528c9932d278d5c9cbbea38a6b81eb62c02e06ae53751a83a4d52b \ + --hash=sha256:c25d9e338d5bed46c1632f851babf3d13c78f49a225462017cf5e11e845c5891 \ + --hash=sha256:c336d61d2fe74a3195edc1646d53ff1cddd3a9600b09fa6ab75e5514ba4862a7 \ + --hash=sha256:cc3656283d11540ab0ea01978378e73e10002145117055e03722417aeab30994 \ + --hash=sha256:cf450f498c30af55551ba4f66b9123b7185362ec8b625a773b3d39aa1a717583 \ + --hash=sha256:d0ee06b5b5291f609ddb37b9750985b27bc567791bc87c76a569b3feed8481ac \ + --hash=sha256:d480de377f5b687b6b1bc0c0407426da556e2a757633cc7e4d2e1a057aa688f3 \ + --hash=sha256:d56bc4011975f7460bea7b33e1ff425d2f1adf419935ff6707273c77f8a4ada6 \ + --hash=sha256:dd3c41254ee98604b08bd5b3af5bf0a89740d4ee0711de95b65166bf44091921 \ + --hash=sha256:e0d138c7ae532908cbb342162b2611dbd4d90c941cd25ab82084aaf71d2c0bd0 \ + --hash=sha256:e11769a1dbda4da7b00a76cfffa67aa47cfa66921d2724539eee4b9ede780b79 \ + --hash=sha256:e3f0a41487fd5fad7e760b9e8a90e251e27c2816fbc2cff36a22a0e6bcbbd9dd \ + --hash=sha256:e692aa2d1d604e6ca12d35e51fdc36f4cda6345e28e36374579f7ef3611b3012 \ + --hash=sha256:e70a57ecf89a0f64c24e37f38d3fe217a58169d2fe6ed6d70554964042474023 \ + --hash=sha256:e96baa6820280077a78244b2e06e416480ed859bbd8e5d641cf5742919d8beb4 \ + --hash=sha256:eb5656019db7c4deacf0c1a55a898c5bb8f989be904597fcb5232a2f4828fa05 \ + --hash=sha256:eca45e982fa074090057132e30585a7e8674e9e885d402eae85633e9f449ce6c \ + --hash=sha256:f0af2bd2bc204fa27f3d6711d0f360e6b8c684a035206257a81673ab924aa11e \ + --hash=sha256:f7cdf7f26c2286ffb02e46d7bac56c94655540b26347673bea15fa52a6af17e9 \ + --hash=sha256:fd1a720332ea335ceb544cf0a03f81df92abd4bb887679fd1e460976b0e6214b \ + --hash=sha256:ff8baf1f8d3f4b6b7257fcb75a501f2a5499d0dda57645baa09d4d0d34b19444 # via mypy locket==1.0.0 \ --hash=sha256:5c0d4c052a8bbbf750e056a8e65ccd309086f4f0f18a2eac306a8dfa4112a632 \ @@ -434,246 +450,238 @@ markupsafe==3.0.3 \ --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \ --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50 # via jinja2 -mmh3==5.2.0 \ - --hash=sha256:03e08c6ebaf666ec1e3d6ea657a2d363bb01effd1a9acfe41f9197decaef0051 \ - --hash=sha256:097e13c8b8a66c5753c6968b7640faefe85d8e38992703c1f666eda6ef4c3762 \ - --hash=sha256:0b898cecff57442724a0f52bf42c2de42de63083a91008fb452887e372f9c328 \ - --hash=sha256:10983c10f5c77683bd845751905ba535ec47409874acc759d5ce3ff7ef34398a \ - --hash=sha256:11730eeb16dfcf9674fdea9bb6b8e6dd9b40813b7eb839bc35113649eef38aeb \ - --hash=sha256:127c95336f2a98c51e7682341ab7cb0be3adb9df0819ab8505a726ed1801876d \ - --hash=sha256:12da42c0a55c9d86ab566395324213c319c73ecb0c239fad4726324212b9441c \ - --hash=sha256:132dd943451a7c7546978863d2f5a64977928410782e1a87d583cb60eb89e667 \ - --hash=sha256:1556e31e4bd0ac0c17eaf220be17a09c171d7396919c3794274cb3415a9d3646 \ - --hash=sha256:1a5f4d2e59d6bba8ef01b013c472741835ad961e7c28f50c82b27c57748744a4 \ - --hash=sha256:1ba55d6ca32eeef8b2625e1e4bfc3b3db52bc63014bd7e5df8cc11bf2b036b12 \ - --hash=sha256:1efc8fec8478e9243a78bb993422cf79f8ff85cb4cf6b79647480a31e0d950a8 \ - --hash=sha256:1f8d8b627799f4e2fcc7c034fed8f5f24dc7724ff52f69838a3d6d15f1ad4765 \ - --hash=sha256:1fae471339ae1b9c641f19cf46dfe6ffd7f64b1fba7c4333b99fa3dd7f21ae0a \ - --hash=sha256:1fdb36b940e9261aff0b5177c5b74a36936b902f473180f6c15bde26143681a9 \ - --hash=sha256:2421b9d665a0b1ad724ec7332fb5a98d075f50bc51a6ff854f3a1882bd650d49 \ - --hash=sha256:29c2b9ce61886809d0492a274a5a53047742dea0f703f9c4d5d223c3ea6377d3 \ - --hash=sha256:2c9da0d568569cc87315cb063486d761e38458b8ad513fedd3dc9263e1b81bcd \ - --hash=sha256:2ebfc46b39168ab1cd44670a32ea5489bcbc74a25795c61b6d888c5c2cf654ed \ - --hash=sha256:3193752fc05ea72366c2b63ff24b9a190f422e32d75fdeae71087c08fff26115 \ - --hash=sha256:33576136c06b46a7046b6d83a3d75fbca7d25f84cec743f1ae156362608dc6d2 \ - --hash=sha256:37a358cc881fe796e099c1db6ce07ff757f088827b4e8467ac52b7a7ffdca647 \ - --hash=sha256:382a6bb3f8c6532ea084e7acc5be6ae0c6effa529240836d59352398f002e3fc \ - --hash=sha256:384eda9361a7bf83a85e09447e1feafe081034af9dd428893701b959230d84be \ - --hash=sha256:38d899a156549da8ef6a9f1d6f7ef231228d29f8f69bce2ee12f5fba6d6fd7c5 \ - --hash=sha256:3bc244802ccab5220008cb712ca1508cb6a12f0eb64ad62997156410579a1770 \ - --hash=sha256:3c6041fd9d5fb5fcac57d5c80f521a36b74aea06b8566431c63e4ffc49aced51 \ - --hash=sha256:3ca975c51c5028947bbcfc24966517aac06a01d6c921e30f7c5383c195f87991 \ - --hash=sha256:3d6bfd9662a20c054bc216f861fa330c2dac7c81e7fb8307b5e32ab5b9b4d2e0 \ - --hash=sha256:419005f84ba1cab47a77465a2a843562dadadd6671b8758bf179d82a15ca63eb \ - --hash=sha256:45b590e31bc552c6f8e2150ff1ad0c28dd151e9f87589e7eaf508fbdd8e8e908 \ - --hash=sha256:49037d417419863b222ae47ee562b2de9c3416add0a45c8d7f4e864be8dc4f89 \ - --hash=sha256:4a5f5536b1cbfa72318ab3bfc8a8188b949260baed186b75f0abc75b95d8c051 \ - --hash=sha256:582f9dbeefe15c32a5fa528b79b088b599a1dfe290a4436351c6090f90ddebb8 \ - --hash=sha256:58477cf9ef16664d1ce2b038f87d2dc96d70fe50733a34a7f07da6c9a5e3538c \ - --hash=sha256:58981d6ea9646dbbf9e59a30890cbf9f610df0e4a57dbfe09215116fd90b0093 \ - --hash=sha256:5a5dba98e514fb26241868f6eb90a7f7ca0e039aed779342965ce24ea32ba513 \ - --hash=sha256:5b0b58215befe0f0e120b828f7645e97719bbba9f23b69e268ed0ac7adde8645 \ - --hash=sha256:61ac226af521a572700f863d6ecddc6ece97220ce7174e311948ff8c8919a363 \ - --hash=sha256:63830f846797187c5d3e2dae50f0848fdc86032f5bfdc58ae352f02f857e9025 \ - --hash=sha256:69fc339d7202bea69ef9bd7c39bfdf9fdabc8e6822a01eba62fb43233c1b3932 \ - --hash=sha256:6d541038b3fc360ec538fc116de87462627944765a6750308118f8b509a8eec7 \ - --hash=sha256:6ecb4e750d712abde046858ee6992b65c93f1f71b397fce7975c3860c07365d2 \ - --hash=sha256:72d80005b7634a3a2220f81fbeb94775ebd12794623bb2e1451701ea732b4aa3 \ - --hash=sha256:7303aab41e97adcf010a09efd8f1403e719e59b7705d5e3cfed3dd7571589290 \ - --hash=sha256:7434a27754049144539d2099a6d2da5d88b8bdeedf935180bf42ad59b3607aa3 \ - --hash=sha256:746a5ee71c6d1103d9b560fa147881b5e68fd35da56e54e03d5acefad0e7c055 \ - --hash=sha256:7733ec52296fc1ba22e9b90a245c821adbb943e98c91d8a330a2254612726106 \ - --hash=sha256:7901c893e704ee3c65f92d39b951f8f34ccf8e8566768c58103fb10e55afb8c1 \ - --hash=sha256:7aa18cdb58983ee660c9c400b46272e14fa253c675ed963d3812487f8ca42037 \ - --hash=sha256:7b986d506a8e8ea345791897ba5d8ba0d9d8820cd4fc3e52dbe6de19388de2e7 \ - --hash=sha256:7bbb0df897944b5ec830f3ad883e32c5a7375370a521565f5fe24443bfb2c4f7 \ - --hash=sha256:7c7f0b342fd06044bedd0b6e72177ddc0076f54fd89ee239447f8b271d919d9b \ - --hash=sha256:7e5634565367b6d98dc4aa2983703526ef556b3688ba3065edb4b9b90ede1c54 \ - --hash=sha256:7fddccd4113e7b736706e17a239a696332360cbaddf25ae75b57ba1acce65081 \ - --hash=sha256:81c504ad11c588c8629536b032940f2a359dda3b6cbfd4ad8f74cb24dcd1b0bc \ - --hash=sha256:81df0dae22cd0da87f1c978602750f33d17fb3d21fb0f326c89dc89834fea79b \ - --hash=sha256:86d1be5d63232e6eb93c50881aea55ff06eb86d8e08f9b5417c8c9b10db9db96 \ - --hash=sha256:8b0c53fe0994beade1ad7c0f13bd6fec980a0664bfbe5a6a7d64500b9ab76772 \ - --hash=sha256:8ebf241072cf2777a492d0e09252f8cc2b3edd07dfdb9404b9757bffeb4f2cee \ - --hash=sha256:931d47e08c9c8a67bf75d82f0ada8399eac18b03388818b62bfa42882d571d72 \ - --hash=sha256:932a6eec1d2e2c3c9e630d10f7128d80e70e2d47fe6b8c7ea5e1afbd98733e65 \ - --hash=sha256:941603bfd75a46023807511c1ac2f1b0f39cccc393c15039969806063b27e6db \ - --hash=sha256:956127e663d05edbeec54df38885d943dfa27406594c411139690485128525de \ - --hash=sha256:96f1e1ac44cbb42bcc406e509f70c9af42c594e72ccc7b1257f97554204445f0 \ - --hash=sha256:99bb6a4d809aa4e528ddfe2c85dd5239b78b9dd14be62cca0329db78505e7b50 \ - --hash=sha256:9f64bf06f4bf623325fda3a6d02d36cd69199b9ace99b04bb2d7fd9f89688504 \ - --hash=sha256:a094319ec0db52a04af9fdc391b4d39a1bc72bc8424b47c4411afb05413a44b5 \ - --hash=sha256:a367d4741ac0103f8198c82f429bccb9359f543ca542b06a51f4f0332e8de279 \ - --hash=sha256:a7c0c7845566b9686480e6a7e9044db4afb60038d5fabd19227443f0104eeee4 \ - --hash=sha256:aa6e5d31fdc5ed9e3e95f9873508615a778fe9b523d52c17fc770a3eb39ab6e4 \ - --hash=sha256:ae9d032488fcec32d22be6542d1a836f00247f40f320844dbb361393b5b22773 \ - --hash=sha256:b0271ac12415afd3171ab9a3c7cbfc71dee2c68760a7dc9d05bf8ed6ddfa3a7a \ - --hash=sha256:b0d753ad566c721faa33db7e2e0eddd74b224cdd3eaf8481d76c926603c7a00e \ - --hash=sha256:b29044e1ffdb84fe164d0a7ea05c7316afea93c00f8ed9449cf357c36fc4f814 \ - --hash=sha256:b5995088dd7023d2d9f310a0c67de5a2b2e06a570ecfd00f9ff4ab94a67cde43 \ - --hash=sha256:b5f317a727bba0e633a12e71228bc6a4acb4f471a98b1c003163b917311ea9a9 \ - --hash=sha256:b9a87025121d1c448f24f27ff53a5fe7b6ef980574b4a4f11acaabe702420d63 \ - --hash=sha256:bb0fdc451fb6d86d81ab8f23d881b8d6e37fc373a2deae1c02d27002d2ad7a05 \ - --hash=sha256:bb4fe46bdc6104fbc28db7a6bacb115ee6368ff993366bbd8a2a7f0076e6f0c0 \ - --hash=sha256:bc44fc2b886243d7c0d8daeb37864e16f232e5b56aaec27cc781d848264cfd28 \ - --hash=sha256:bdde97310d59604f2a9119322f61b31546748499a21b44f6715e8ced9308a6c5 \ - --hash=sha256:be1374df449465c9f2500e62eee73a39db62152a8bdfbe12ec5b5c1cd451344d \ - --hash=sha256:be7d3dca9358e01dab1bad881fb2b4e8730cec58d36dd44482bc068bfcd3bc65 \ - --hash=sha256:bf7bee43e17e81671c447e9c83499f53d99bf440bc6d9dc26a841e21acfbe094 \ - --hash=sha256:c3dca4cb5b946ee91b3d6bb700d137b1cd85c20827f89fdf9c16258253489044 \ - --hash=sha256:c3f563e8901960e2eaa64c8e8821895818acabeb41c96f2efbb936f65dbe486c \ - --hash=sha256:c463d7c1c4cfc9d751efeaadd936bbba07b5b0ed81a012b3a9f5a12f0872bd6e \ - --hash=sha256:c4a2f3d83879e3de2eb8cbf562e71563a8ed15ee9b9c2e77ca5d9f73072ac15c \ - --hash=sha256:c5584061fd3da584659b13587f26c6cad25a096246a481636d64375d0c1f6c07 \ - --hash=sha256:c677d78887244bf3095020b73c42b505b700f801c690f8eaa90ad12d3179612f \ - --hash=sha256:c903e71fd8debb35ad2a4184c1316b3cb22f64ce517b4e6747f25b0a34e41266 \ - --hash=sha256:c9ff37ba9f15637e424c2ab57a1a590c52897c845b768e4e0a4958084ec87f22 \ - --hash=sha256:cadc16e8ea64b5d9a47363013e2bea469e121e6e7cb416a7593aeb24f2ad122e \ - --hash=sha256:cedac4f4054b8f7859e5aed41aaa31ad03fce6851901a7fdc2af0275ac533c10 \ - --hash=sha256:d22c9dcafed659fadc605538946c041722b6d1104fe619dbf5cc73b3c8a0ded8 \ - --hash=sha256:d765058da196f68dc721116cab335e696e87e76720e6ef8ee5a24801af65e63d \ - --hash=sha256:d86651fa45799530885ba4dab3d21144486ed15285e8784181a0ab37a4552384 \ - --hash=sha256:dd966df3489ec13848d6c6303429bbace94a153f43d1ae2a55115fd36fd5ca5d \ - --hash=sha256:ddc63328889bcaee77b743309e5c7d2d52cee0d7d577837c91b6e7cc9e755e0b \ - --hash=sha256:dfbead5575f6470c17e955b94f92d62a03dfc3d07f2e6f817d9b93dc211a1515 \ - --hash=sha256:e0f3ed828d709f5b82d8bfe14f8856120718ec4bd44a5b26102c3030a1e12501 \ - --hash=sha256:e1861fb6b1d0453ed7293200139c0a9011eeb1376632e048e3766945b13313c5 \ - --hash=sha256:e5015f0bb6eb50008bed2d4b1ce0f2a294698a926111e4bb202c0987b4f89078 \ - --hash=sha256:e651e17bfde5840e9e4174b01e9e080ce49277b70d424308b36a7969d0d1af73 \ - --hash=sha256:e7884931fe5e788163e7b3c511614130c2c59feffdc21112290a194487efb2e9 \ - --hash=sha256:e79c00eba78f7258e5b354eccd4d7907d60317ced924ea4a5f2e9d83f5453065 \ - --hash=sha256:e912b19cf2378f2967d0c08e86ff4c6c360129887f678e27e4dde970d21b3f4d \ - --hash=sha256:e9a011469b47b752e7d20de296bb34591cdfcbe76c99c2e863ceaa2aa61113d2 \ - --hash=sha256:eb756caf8975882630ce4e9fbbeb9d3401242a72528230422c9ab3a0d278e60c \ - --hash=sha256:eba01ec3bd4a49b9ac5ca2bc6a73ff5f3af53374b8556fcc2966dd2af9eb7779 \ - --hash=sha256:ecbfc0437ddfdced5e7822d1ce4855c9c64f46819d0fdc4482c53f56c707b935 \ - --hash=sha256:eed4bba7ff8a0d37106ba931ab03bdd3915fbb025bcf4e1f0aa02bc8114960c5 \ - --hash=sha256:f35727c5118aba95f0397e18a1a5b8405425581bfe53e821f0fb444cbdc2bc9b \ - --hash=sha256:f698733a8a494466432d611a8f0d1e026f5286dee051beea4b3c3146817e35d5 \ - --hash=sha256:f7f9034c7cf05ddfaac8d7a2e63a3c97a840d4615d0a0e65ba8bdf6f8576e3be \ - --hash=sha256:fa0c966ee727aad5406d516375593c5f058c766b21236ab8985693934bb5085b \ - --hash=sha256:fc9c5f280438cf1c1a8f9abb87dc8ce9630a964120cfb5dd50d1e7ce79690c7a \ - --hash=sha256:fd6e6c3d90660d085f7e73710eab6f5545d4854b81b0135a3526e797009dbda3 \ - --hash=sha256:fdfd3fb739f4e22746e13ad7ba0c6eedf5f454b18d11249724a388868e308ee4 \ - --hash=sha256:ff3d50dc3fe8a98059f99b445dfb62792b5d006c5e0b8f03c6de2813b8376110 +mmh3==5.2.1 \ + --hash=sha256:022aa1a528604e6c83d0a7705fdef0b5355d897a9e0fa3a8d26709ceaa06965d \ + --hash=sha256:0634581290e6714c068f4aa24020acf7880927d1f0084fa753d9799ae9610082 \ + --hash=sha256:08043f7cb1fb9467c3fbbbaea7896986e7fbc81f4d3fd9289a73d9110ab6207a \ + --hash=sha256:0a3984146e414684a6be2862d84fcb1035f4984851cb81b26d933bab6119bf00 \ + --hash=sha256:0bbc17250b10d3466875a40a52520a6bac3c02334ca709207648abd3c223ed5c \ + --hash=sha256:0cc21533878e5586b80d74c281d7f8da7932bc8ace50b8d5f6dbf7e3935f63f1 \ + --hash=sha256:0d0b7e803191db5f714d264044e06189c8ccd3219e936cc184f07106bd17fd7b \ + --hash=sha256:113f78e7463a36dbbcea05bfe688efd7fa759d0f0c56e73c974d60dcfec3dfcc \ + --hash=sha256:169e0d178cb59314456ab30772429a802b25d13227088085b0d49b9fe1533104 \ + --hash=sha256:17fbb47f0885ace8327ce1235d0416dc86a211dcd8cc1e703f41523be32cfec8 \ + --hash=sha256:19bbd3b841174ae6ed588536ab5e1b1fe83d046e668602c20266547298d939a9 \ + --hash=sha256:1d9f9a3ce559a5267014b04b82956993270f63ec91765e13e9fd73daf2d2738e \ + --hash=sha256:1e4ecee40ba19e6975e1120829796770325841c2f153c0e9aecca927194c6a2a \ + --hash=sha256:22b0f9971ec4e07e8223f2beebe96a6cfc779d940b6f27d26604040dd74d3a44 \ + --hash=sha256:26fb5b9c3946bf7f1daed7b37e0c03898a6f062149127570f8ede346390a0825 \ + --hash=sha256:2778fed822d7db23ac5008b181441af0c869455b2e7d001f4019636ac31b6fe4 \ + --hash=sha256:28cfab66577000b9505a0d068c731aee7ca85cd26d4d63881fab17857e0fe1fb \ + --hash=sha256:29bc3973676ae334412efdd367fcd11d036b7be3efc1ce2407ef8676dabfeb82 \ + --hash=sha256:2bd9f19f7f1fcebd74e830f4af0f28adad4975d40d80620be19ffb2b2af56c9f \ + --hash=sha256:2d5d542bf2abd0fd0361e8017d03f7cb5786214ceb4a40eef1539d6585d93386 \ + --hash=sha256:30e4d2084df019880d55f6f7bea35328d9b464ebee090baa372c096dc77556fb \ + --hash=sha256:3619473a0e0d329fd4aec8075628f8f616be2da41605300696206d6f36920c3d \ + --hash=sha256:368625fb01666655985391dbad3860dc0ba7c0d6b9125819f3121ee7292b4ac8 \ + --hash=sha256:3737303ca9ea0f7cb83028781148fcda4f1dac7821db0c47672971dabcf63593 \ + --hash=sha256:3a9fed49c6ce4ed7e73f13182760c65c816da006debe67f37635580dfb0fae00 \ + --hash=sha256:3c38d142c706201db5b2345166eeef1e7740e3e2422b470b8ba5c8727a9b4c7a \ + --hash=sha256:3cb61db880ec11e984348227b333259994c2c85caa775eb7875decb3768db890 \ + --hash=sha256:3d74a03fb57757ece25aa4b3c1c60157a1cece37a020542785f942e2f827eed5 \ + --hash=sha256:3f796b535008708846044c43302719c6956f39ca2d93f2edda5319e79a29efbb \ + --hash=sha256:41105377f6282e8297f182e393a79cfffd521dde37ace52b106373bdcd9ca5cb \ + --hash=sha256:41aac7002a749f08727cb91babff1daf8deac317c0b1f317adc69be0e6c375d1 \ + --hash=sha256:44983e45310ee5b9f73397350251cdf6e63a466406a105f1d16cb5baa659270b \ + --hash=sha256:4cbbde66f1183db040daede83dd86c06d663c5bb2af6de1142b7c8c37923dd74 \ + --hash=sha256:4eda76074cfca2787c8cf1bec603eaebdddd8b061ad5502f85cddae998d54f00 \ + --hash=sha256:4fc6cd65dc4d2fdb2625e288939a3566e36127a84811a4913f02f3d5931da52d \ + --hash=sha256:50885073e2909251d4718634a191c49ae5f527e5e1736d738e365c3e8be8f22b \ + --hash=sha256:5174a697ce042fa77c407e05efe41e03aa56dae9ec67388055820fb48cf4c3ba \ + --hash=sha256:54b64fb2433bc71488e7a449603bf8bd31fbcf9cb56fbe1eb6d459e90b86c37b \ + --hash=sha256:54fe8518abe06a4c3852754bfd498b30cc58e667f376c513eac89a244ce781a4 \ + --hash=sha256:55dbbd8ffbc40d1697d5e2d0375b08599dae8746b0b08dea05eee4ce81648fac \ + --hash=sha256:57b52603e89355ff318025dd55158f6e71396c0f1f609d548e9ea9c94cc6ce0a \ + --hash=sha256:58370d05d033ee97224c81263af123dea3d931025030fd34b61227a768a8858a \ + --hash=sha256:5d87a3584093e1a89987e3d36d82c98d9621b2cb944e22a420aa1401e096758f \ + --hash=sha256:623f938f6a039536cc02b7582a07a080f13fdfd48f87e63201d92d7e34d09a18 \ + --hash=sha256:62815d2c67f2dd1be76a253d88af4e1da19aeaa1820146dec52cf8bee2958b16 \ + --hash=sha256:6290289fa5fb4c70fd7f72016e03633d60388185483ff3b162912c81205ae2cf \ + --hash=sha256:67e41a497bac88cc1de96eeba56eeb933c39d54bc227352f8455aa87c4ca4000 \ + --hash=sha256:6c85c38a279ca9295a69b9b088a2e48aa49737bb1b34e6a9dc6297c110e8d912 \ + --hash=sha256:6f01f044112d43a20be2f13a11683666d87151542ad627fe41a18b9791d2802f \ + --hash=sha256:707151644085dd0f20fe4f4b573d28e5130c4aaa5f587e95b60989c5926653b5 \ + --hash=sha256:723b2681ed4cc07d3401bbea9c201ad4f2a4ca6ba8cddaff6789f715dd2b391e \ + --hash=sha256:72d1cc63bcc91e14933f77d51b3df899d6a07d184ec515ea7f56bff659e124d7 \ + --hash=sha256:7374d6e3ef72afe49697ecd683f3da12f4fc06af2d75433d0580c6746d2fa025 \ + --hash=sha256:7501e9be34cb21e72fcfe672aafd0eee65c16ba2afa9dcb5500a587d3a0580f0 \ + --hash=sha256:76219cd1eefb9bf4af7856e3ae563d15158efa145c0aab01e9933051a1954045 \ + --hash=sha256:7aec798c2b01aaa65a55f1124f3405804184373abb318a3091325aece235f67c \ + --hash=sha256:7be6dfb49e48fd0a7d91ff758a2b51336f1cd21f9d44b20f6801f072bd080cdd \ + --hash=sha256:7e4e1f580033335c6f76d1e0d6b56baf009d1a64d6a4816347e4271ba951f46d \ + --hash=sha256:7e8ec5f606e0809426d2440e0683509fb605a8820a21ebd120dcdba61b74ef7f \ + --hash=sha256:7f196cd7910d71e9d9860da0ff7a77f64d22c1ad931f1dd18559a06e03109fc0 \ + --hash=sha256:82f3802bfc4751f420d591c5c864de538b71cea117fce67e4595c2afede08a15 \ + --hash=sha256:85ffc9920ffc39c5eee1e3ac9100c913a0973996fbad5111f939bbda49204bb7 \ + --hash=sha256:8e6c219e375f6341d0959af814296372d265a8ca1af63825f65e2e87c618f006 \ + --hash=sha256:8f767ba0911602ddef289404e33835a61168314ebd3c729833db2ed685824211 \ + --hash=sha256:8ff038d52ef6aa0f309feeba00c5095c9118d0abf787e8e8454d6048db2037fc \ + --hash=sha256:915e7a2418f10bd1151b1953df06d896db9783c9cfdb9a8ee1f9b3a4331ab503 \ + --hash=sha256:92883836caf50d5255be03d988d75bc93e3f86ba247b7ca137347c323f731deb \ + --hash=sha256:960b1b3efa39872ac8b6cc3a556edd6fb90ed74f08c9c45e028f1005b26aa55d \ + --hash=sha256:9aeaf53eaa075dd63e81512522fd180097312fb2c9f476333309184285c49ce0 \ + --hash=sha256:9d8089d853c7963a8ce87fff93e2a67075c0bc08684a08ea6ad13577c38ffc38 \ + --hash=sha256:a4130d0b9ce5fad6af07421b1aecc7e079519f70d6c05729ab871794eded8617 \ + --hash=sha256:a482ac121de6973897c92c2f31defc6bafb11c83825109275cffce54bb64933f \ + --hash=sha256:add7ac388d1e0bf57259afbcf9ed05621a3bf11ce5ee337e7536f1e1aaf056b0 \ + --hash=sha256:b1f12bd684887a0a5d55e6363ca87056f361e45451105012d329b86ec19dbe0b \ + --hash=sha256:b3f99e1756fc48ad507b95e5d86f2fb21b3d495012ff13e6592ebac14033f166 \ + --hash=sha256:b4cce60d0223074803c9dbe0721ad3fa51dafe7d462fee4b656a1aa01ee07518 \ + --hash=sha256:baeb47635cb33375dee4924cd93d7f5dcaa786c740b08423b0209b824a1ee728 \ + --hash=sha256:bbea5b775f0ac84945191fb83f845a6fd9a21a03ea7f2e187defac7e401616ad \ + --hash=sha256:bbfcb95d9a744e6e2827dfc66ad10e1020e0cac255eb7f85652832d5a264c2fc \ + --hash=sha256:bd6e7d363aa93bd3421b30b6af97064daf47bc96005bddba67c5ffbc6df426b8 \ + --hash=sha256:be77c402d5e882b6fbacfd90823f13da8e0a69658405a39a569c6b58fdb17b03 \ + --hash=sha256:c302245fd6c33d96bd169c7ccf2513c20f4c1e417c07ce9dce107c8bc3f8411f \ + --hash=sha256:c88653877aeb514c089d1b3d473451677b8b9a6d1497dbddf1ae7934518b06d2 \ + --hash=sha256:cae6383181f1e345317742d2ddd88f9e7d2682fa4c9432e3a74e47d92dce0229 \ + --hash=sha256:cd471ede0d802dd936b6fab28188302b2d497f68436025857ca72cd3810423fe \ + --hash=sha256:d106493a60dcb4aef35a0fac85105e150a11cf8bc2b0d388f5a33272d756c966 \ + --hash=sha256:d30b650595fdbe32366b94cb14f30bb2b625e512bd4e1df00611f99dc5c27fd4 \ + --hash=sha256:d51fde50a77f81330523562e3c2734ffdca9c4c9e9d355478117905e1cfe16c6 \ + --hash=sha256:d57dea657357230cc780e13920d7fa7db059d58fe721c80020f94476da4ca0a1 \ + --hash=sha256:d771f085fcdf4035786adfb1d8db026df1eb4b41dac1c3d070d1e49512843227 \ + --hash=sha256:dae0f0bd7d30c0ad61b9a504e8e272cb8391eed3f1587edf933f4f6b33437450 \ + --hash=sha256:db0562c5f71d18596dcd45e854cf2eeba27d7543e1a3acdafb7eef728f7fe85d \ + --hash=sha256:dfd51b4c56b673dfbc43d7d27ef857dd91124801e2806c69bb45585ce0fa019b \ + --hash=sha256:e080c0637aea036f35507e803a4778f119a9b436617694ae1c5c366805f1e997 \ + --hash=sha256:e48d4dbe0f88e53081da605ae68644e5182752803bbc2beb228cca7f1c4454d6 \ + --hash=sha256:e8b4b5580280b9265af3e0409974fb79c64cf7523632d03fbf11df18f8b0181e \ + --hash=sha256:e8b5378de2b139c3a830f0209c1e91f7705919a4b3e563a10955104f5097a70a \ + --hash=sha256:e904f2417f0d6f6d514f3f8b836416c360f306ddaee1f84de8eef1e722d212e5 \ + --hash=sha256:eee884572b06bbe8a2b54f424dbd996139442cf83c76478e1ec162512e0dd2c7 \ + --hash=sha256:f1fbb0a99125b1287c6d9747f937dc66621426836d1a2d50d05aecfc81911b57 \ + --hash=sha256:f40a95186a72fa0b67d15fef0f157bfcda00b4f59c8a07cbe5530d41ac35d105 \ + --hash=sha256:f6e0bfe77d238308839699944164b96a2eeccaf55f2af400f54dc20669d8d5f2 \ + --hash=sha256:f963eafc0a77a6c0562397da004f5876a9bcf7265a7bcc3205e29636bc4a1312 \ + --hash=sha256:fb9d44c25244e11c8be3f12c938ca8ba8404620ef8092245d2093c6ab3df260f \ + --hash=sha256:fc78739b5ec6e4fb02301984a3d442a91406e7700efbe305071e7fd1c78278f2 \ + --hash=sha256:fceef7fe67c81e1585198215e42ad3fdba3a25644beda8fbdaf85f4d7b93175a \ + --hash=sha256:fd96476f04db5ceba1cfa0f21228f67c1f7402296f0e73fee3513aa680ad237b # via feast (pyproject.toml) -mypy==1.19.1 \ - --hash=sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd \ - --hash=sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b \ - --hash=sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1 \ - --hash=sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba \ - --hash=sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b \ - --hash=sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045 \ - --hash=sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac \ - --hash=sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6 \ - --hash=sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a \ - --hash=sha256:409088884802d511ee52ca067707b90c883426bd95514e8cfda8281dc2effe24 \ - --hash=sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957 \ - --hash=sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042 \ - --hash=sha256:4f28f99c824ecebcdaa2e55d82953e38ff60ee5ec938476796636b86afa3956e \ - --hash=sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec \ - --hash=sha256:7bcfc336a03a1aaa26dfce9fff3e287a3ba99872a157561cbfcebe67c13308e3 \ - --hash=sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718 \ - --hash=sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f \ - --hash=sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331 \ - --hash=sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1 \ - --hash=sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1 \ - --hash=sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13 \ - --hash=sha256:b13cfdd6c87fc3efb69ea4ec18ef79c74c3f98b4e5498ca9b85ab3b2c2329a67 \ - --hash=sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2 \ - --hash=sha256:b7951a701c07ea584c4fe327834b92a30825514c868b1f69c30445093fdd9d5a \ - --hash=sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b \ - --hash=sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8 \ - --hash=sha256:c608937067d2fc5a4dd1a5ce92fd9e1398691b8c5d012d66e1ddd430e9244376 \ - --hash=sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef \ - --hash=sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288 \ - --hash=sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75 \ - --hash=sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74 \ - --hash=sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250 \ - --hash=sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab \ - --hash=sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6 \ - --hash=sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247 \ - --hash=sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925 \ - --hash=sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e \ - --hash=sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e +mypy==1.20.0 \ + --hash=sha256:002b613ae19f4ac7d18b7e168ffe1cb9013b37c57f7411984abbd3b817b0a214 \ + --hash=sha256:00e047c74d3ec6e71a2eb88e9ea551a2edb90c21f993aefa9e0d2a898e0bb732 \ + --hash=sha256:02cca0761c75b42a20a2757ae58713276605eb29a08dd8a6e092aa347c4115ca \ + --hash=sha256:0ecd63f75fdd30327e4ad8b5704bd6d91fc6c1b2e029f8ee14705e1207212489 \ + --hash=sha256:0f42dfaab7ec1baff3b383ad7af562ab0de573c5f6edb44b2dab016082b89948 \ + --hash=sha256:1973868d2adbb4584a3835780b27436f06d1dc606af5be09f187aaa25be1070f \ + --hash=sha256:26c8b52627b6552f47ff11adb4e1509605f094e29815323e487fc0053ebe93d1 \ + --hash=sha256:2721f0ce49cb74a38f00c50da67cb7d36317b5eda38877a49614dc018e91c787 \ + --hash=sha256:2fcedb16d456106e545b2bfd7ef9d24e70b38ec252d2a629823a4d07ebcdb69e \ + --hash=sha256:31b5dbb55293c1bd27c0fc813a0d2bb5ceef9d65ac5afa2e58f829dab7921fd5 \ + --hash=sha256:34506397dbf40c15dc567635d18a21d33827e9ab29014fb83d292a8f4f8953b6 \ + --hash=sha256:367e5c993ba34d5054d11937d0485ad6dfc60ba760fa326c01090fc256adf15c \ + --hash=sha256:379edf079ce44ac8d2805bcf9b3dd7340d4f97aad3a5e0ebabbf9d125b84b442 \ + --hash=sha256:39362cdb4ba5f916e7976fccecaab1ba3a83e35f60fa68b64e9a70e221bb2436 \ + --hash=sha256:4525e7010b1b38334516181c5b81e16180b8e149e6684cee5a727c78186b4e3b \ + --hash=sha256:47781555a7aa5fedcc2d16bcd72e0dc83eb272c10dd657f9fb3f9cc08e2e6abb \ + --hash=sha256:49d11c6f573a5a08f77fad13faff2139f6d0730ebed2cfa9b3d2702671dd7188 \ + --hash=sha256:555493c44a4f5a1b58d611a43333e71a9981c6dbe26270377b6f8174126a0526 \ + --hash=sha256:555658c611099455b2da507582ea20d2043dfdfe7f5ad0add472b1c6238b433f \ + --hash=sha256:697f102c5c1d526bdd761a69f17c6070f9892eebcb94b1a5963d679288c09e78 \ + --hash=sha256:76a70bf840495729be47510856b978f1b0ec7d08f257ca38c9d932720bf6b43e \ + --hash=sha256:7d3243c406773185144527f83be0e0aefc7bf4601b0b2b956665608bf7c98a83 \ + --hash=sha256:931a7630bba591593dcf6e97224a21ff80fb357e7982628d25e3c618e7f598ef \ + --hash=sha256:9804c3ad27f78e54e58b32e7cb532d128b43dbfb9f3f9f06262b821a0f6bd3f5 \ + --hash=sha256:a17c5d0bdcca61ce24a35beb828a2d0d323d3fcf387d7512206888c900193367 \ + --hash=sha256:a6e0641147cbfa7e4e94efdb95c2dab1aff8cfc159ded13e07f308ddccc8c48e \ + --hash=sha256:a79c1eba7ac4209f2d850f0edd0a2f8bba88cbfdfefe6fb76a19e9d4fe5e71a2 \ + --hash=sha256:a9336b5e6712f4adaf5afc3203a99a40b379049104349d747eb3e5a3aa23ac2e \ + --hash=sha256:b20c8b0fd5877abdf402e79a3af987053de07e6fb208c18df6659f708b535134 \ + --hash=sha256:b3a49064504be59e59da664c5e149edc1f26c67c4f8e8456f6ba6aba55033018 \ + --hash=sha256:b503ab55a836136b619b5fc21c8803d810c5b87551af8600b72eecafb0059cb0 \ + --hash=sha256:bd0212976dc57a5bfeede7c219e7cd66568a32c05c9129686dd487c059c1b88a \ + --hash=sha256:c70380fe5d64010f79fb863b9081c7004dd65225d2277333c219d93a10dad4dd \ + --hash=sha256:d99f515f95fd03a90875fdb2cca12ff074aa04490db4d190905851bdf8a549a8 \ + --hash=sha256:e80cf77847d0d3e6e3111b7b25db32a7f8762fd4b9a3a72ce53fe16a2863b281 \ + --hash=sha256:eb96c84efcc33f0b5e0e04beacf00129dd963b67226b01c00b9dfc8affb464c3 \ + --hash=sha256:ebea00201737ad4391142808ed16e875add5c17f676e0912b387739f84991e13 \ + --hash=sha256:efe8d70949c3023698c3fca1e94527e7e790a361ab8116f90d11221421cd8726 \ + --hash=sha256:f13b3e41bce9d257eded794c0f12878af3129d80aacd8a3ee0dee51f3a978651 \ + --hash=sha256:f194db59657c58593a3c47c6dfd7bad4ef4ac12dbc94d01b3a95521f78177e33 \ + --hash=sha256:f49590891d2c2f8a9de15614e32e459a794bcba84693c2394291a2038bbaaa69 \ + --hash=sha256:f75ff57defcd0f1d6e006d721ccdec6c88d4f6a7816eb92f1c4890d979d9ee62 \ + --hash=sha256:f799d9db89fc00446f03281f84a221e50018fc40113a3ba9864b132895619ebe \ + --hash=sha256:f8426d4d75d68714abc17a4292d922f6ba2cfb984b72c2278c437f6dae797865 # via sqlalchemy mypy-extensions==1.1.0 \ --hash=sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505 \ --hash=sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558 # via mypy -numpy==2.4.2 \ - --hash=sha256:00ab83c56211a1d7c07c25e3217ea6695e50a3e2f255053686b081dc0b091a82 \ - --hash=sha256:068cdb2d0d644cdb45670810894f6a0600797a69c05f1ac478e8d31670b8ee75 \ - --hash=sha256:0f01dcf33e73d80bd8dc0f20a71303abbafa26a19e23f6b68d1aa9990af90257 \ - --hash=sha256:0fece1d1f0a89c16b03442eae5c56dc0be0c7883b5d388e0c03f53019a4bfd71 \ - --hash=sha256:12e26134a0331d8dbd9351620f037ec470b7c75929cb8a1537f6bfe411152a1a \ - --hash=sha256:1ae241bbfc6ae276f94a170b14785e561cb5e7f626b6688cf076af4110887413 \ - --hash=sha256:1f92f53998a17265194018d1cc321b2e96e900ca52d54c7c77837b71b9465181 \ - --hash=sha256:209fae046e62d0ce6435fcfe3b1a10537e858249b3d9b05829e2a05218296a85 \ - --hash=sha256:20abd069b9cda45874498b245c8015b18ace6de8546bf50dfa8cea1696ed06ef \ - --hash=sha256:21982668592194c609de53ba4933a7471880ccbaadcc52352694a59ecc860b3a \ - --hash=sha256:25f2059807faea4b077a2b6837391b5d830864b3543627f381821c646f31a63c \ - --hash=sha256:2653de5c24910e49c2b106499803124dde62a5a1fe0eedeaecf4309a5f639390 \ - --hash=sha256:2b8f157c8a6f20eb657e240f8985cc135598b2b46985c5bccbde7616dc9c6b1e \ - --hash=sha256:2fb882da679409066b4603579619341c6d6898fc83a8995199d5249f986e8e8f \ - --hash=sha256:40397bda92382fcec844066efb11f13e1c9a3e2a8e8f318fb72ed8b6db9f60f1 \ - --hash=sha256:444be170853f1f9d528428eceb55f12918e4fda5d8805480f36a002f1415e09b \ - --hash=sha256:47c5a6ed21d9452b10227e5e8a0e1c22979811cad7dcc19d8e3e2fb8fa03f1a3 \ - --hash=sha256:4f069069931240b3fc703f1e23df63443dbd6390614c8c44a87d96cd0ec81eb1 \ - --hash=sha256:52b913ec40ff7ae845687b0b34d8d93b60cb66dcee06996dd5c99f2fc9328657 \ - --hash=sha256:5633c0da313330fd20c484c78cdd3f9b175b55e1a766c4a174230c6b70ad8262 \ - --hash=sha256:5daf6f3914a733336dab21a05cdec343144600e964d2fcdabaac0c0269874b2a \ - --hash=sha256:5eea80d908b2c1f91486eb95b3fb6fab187e569ec9752ab7d9333d2e66bf2d6b \ - --hash=sha256:602f65afdef699cda27ec0b9224ae5dc43e328f4c24c689deaf77133dbee74d0 \ - --hash=sha256:659a6107e31a83c4e33f763942275fd278b21d095094044eb35569e86a21ddae \ - --hash=sha256:66cb9422236317f9d44b67b4d18f44efe6e9c7f8794ac0462978513359461554 \ - --hash=sha256:6d82351358ffbcdcd7b686b90742a9b86632d6c1c051016484fa0b326a0a1548 \ - --hash=sha256:6e9f61981ace1360e42737e2bae58b27bf28a1b27e781721047d84bd754d32e7 \ - --hash=sha256:6ed0be1ee58eef41231a5c943d7d1375f093142702d5723ca2eb07db9b934b05 \ - --hash=sha256:7cdde6de52fb6664b00b056341265441192d1291c130e99183ec0d4b110ff8b1 \ - --hash=sha256:7df2de1e4fba69a51c06c28f5a3de36731eb9639feb8e1cf7e4a7b0daf4cf622 \ - --hash=sha256:7edc794af8b36ca37ef5fcb5e0d128c7e0595c7b96a2318d1badb6fcd8ee86b1 \ - --hash=sha256:7f54844851cdb630ceb623dcec4db3240d1ac13d4990532446761baede94996a \ - --hash=sha256:805cc8de9fd6e7a22da5aed858e0ab16be5a4db6c873dde1d7451c541553aa27 \ - --hash=sha256:8906e71fd8afcb76580404e2a950caef2685df3d2a57fe82a86ac8d33cc007ba \ - --hash=sha256:89f7268c009bc492f506abd6f5265defa7cb3f7487dc21d357c3d290add45082 \ - --hash=sha256:8c50dd1fc8826f5b26a5ee4d77ca55d88a895f4e4819c7ecc2a9f5905047a443 \ - --hash=sha256:8e4549f8a3c6d13d55041925e912bfd834285ef1dd64d6bc7d542583355e2e98 \ - --hash=sha256:8e9afaeb0beff068b4d9cd20d322ba0ee1cecfb0b08db145e4ab4dd44a6b5110 \ - --hash=sha256:98f16a80e917003a12c0580f97b5f875853ebc33e2eaa4bccfc8201ac6869308 \ - --hash=sha256:9e35d3e0144137d9fdae62912e869136164534d64a169f86438bc9561b6ad49f \ - --hash=sha256:9e4424677ce4b47fe73c8b5556d876571f7c6945d264201180db2dc34f676ab5 \ - --hash=sha256:adb6ed2ad29b9e15321d167d152ee909ec73395901b70936f029c3bc6d7f4460 \ - --hash=sha256:aea4f66ff44dfddf8c2cffd66ba6538c5ec67d389285292fe428cb2c738c8aef \ - --hash=sha256:b21041e8cb6a1eb5312dd1d2f80a94d91efffb7a06b70597d44f1bd2dfc315ab \ - --hash=sha256:b2f0073ed0868db1dcd86e052d37279eef185b9c8db5bf61f30f46adac63c909 \ - --hash=sha256:b3a24467af63c67829bfaa61eecf18d5432d4f11992688537be59ecd6ad32f5e \ - --hash=sha256:b9c618d56a29c9cb1c4da979e9899be7578d2e0b3c24d52079c166324c9e8695 \ - --hash=sha256:bba37bc29d4d85761deed3954a1bc62be7cf462b9510b51d367b769a8c8df325 \ - --hash=sha256:bd3a7a9f5847d2fb8c2c6d1c862fa109c31a9abeca1a3c2bd5a64572955b2979 \ - --hash=sha256:be71bf1edb48ebbbf7f6337b5bfd2f895d1902f6335a5830b20141fc126ffba0 \ - --hash=sha256:c02ef4401a506fb60b411467ad501e1429a3487abca4664871d9ae0b46c8ba32 \ - --hash=sha256:c3cd545784805de05aafe1dde61752ea49a359ccba9760c1e5d1c88a93bbf2b7 \ - --hash=sha256:c7ac672d699bf36275c035e16b65539931347d68b70667d28984c9fb34e07fa7 \ - --hash=sha256:cb7bbb88aa74908950d979eeaa24dbdf1a865e3c7e45ff0121d8f70387b55f73 \ - --hash=sha256:cd2bd2bbed13e213d6b55dc1d035a4f91748a7d3edc9480c13898b0353708920 \ - --hash=sha256:cda077c2e5b780200b6b3e09d0b42205a3d1c68f30c6dceb90401c13bff8fe74 \ - --hash=sha256:cf28c0c1d4c4bf00f509fa7eb02c58d7caf221b50b467bcb0d9bbf1584d5c821 \ - --hash=sha256:d0d9b7c93578baafcbc5f0b83eaf17b79d345c6f36917ba0c67f45226911d499 \ - --hash=sha256:d1240d50adff70c2a88217698ca844723068533f3f5c5fa6ee2e3220e3bdb000 \ - --hash=sha256:d30291931c915b2ab5717c2974bb95ee891a1cf22ebc16a8006bd59cd210d40a \ - --hash=sha256:d9f64d786b3b1dd742c946c42d15b07497ed14af1a1f3ce840cce27daa0ce913 \ - --hash=sha256:da6cad4e82cb893db4b69105c604d805e0c3ce11501a55b5e9f9083b47d2ffe8 \ - --hash=sha256:df1b10187212b198dd45fa943d8985a3c8cf854aed4923796e0e019e113a1bda \ - --hash=sha256:e04ae107ac591763a47398bb45b568fc38f02dbc4aa44c063f67a131f99346cb \ - --hash=sha256:e6dee3bb76aa4009d5a912180bf5b2de012532998d094acee25d9cb8dee3e44a \ - --hash=sha256:e7e88598032542bd49af7c4747541422884219056c268823ef6e5e89851c8825 \ - --hash=sha256:e98c97502435b53741540a5717a6749ac2ada901056c7db951d33e11c885cc7d \ - --hash=sha256:ec055f6dae239a6299cace477b479cca2fc125c5675482daf1dd886933a1076f \ - --hash=sha256:f74f0f7779cc7ae07d1810aab8ac6b1464c3eafb9e283a40da7309d5e6e48fbb \ - --hash=sha256:fbde1b0c6e81d56f5dccd95dd4a711d9b95df1ae4009a60887e56b27e8d903fa \ - --hash=sha256:fcf92bee92742edd401ba41135185866f7026c502617f422eb432cfeca4fe236 \ - --hash=sha256:fd49860271d52127d61197bb50b64f58454e9f578cb4b2c001a6de8b1f50b0b1 +numpy==2.4.4 \ + --hash=sha256:07077278157d02f65c43b1b26a3886bce886f95d20aabd11f87932750dfb14ed \ + --hash=sha256:08f2e31ed5e6f04b118e49821397f12767934cfdd12a1ce86a058f91e004ee50 \ + --hash=sha256:0aec54fd785890ecca25a6003fd9a5aed47ad607bbac5cd64f836ad8666f4959 \ + --hash=sha256:0d35aea54ad1d420c812bfa0385c71cd7cc5bcf7c65fed95fc2cd02fe8c79827 \ + --hash=sha256:0d4e437e295f18ec29bc79daf55e8a47a9113df44d66f702f02a293d93a2d6dd \ + --hash=sha256:0dfd3f9d3adbe2920b68b5cd3d51444e13a10792ec7154cd0a2f6e74d4ab3233 \ + --hash=sha256:1378871da56ca8943c2ba674530924bb8ca40cd228358a3b5f302ad60cf875fc \ + --hash=sha256:15716cfef24d3a9762e3acdf87e27f58dc823d1348f765bbea6bef8c639bfa1b \ + --hash=sha256:19710a9ca9992d7174e9c52f643d4272dcd1558c5f7af7f6f8190f633bd651a7 \ + --hash=sha256:23cbfd4c17357c81021f21540da84ee282b9c8fba38a03b7b9d09ba6b951421e \ + --hash=sha256:2483e4584a1cb3092da4470b38866634bafb223cbcd551ee047633fd2584599a \ + --hash=sha256:27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d \ + --hash=sha256:28a650663f7314afc3e6ec620f44f333c386aad9f6fc472030865dc0ebb26ee3 \ + --hash=sha256:2aa0613a5177c264ff5921051a5719d20095ea586ca88cc802c5c218d1c67d3e \ + --hash=sha256:2c194dd721e54ecad9ad387c1d35e63dce5c4450c6dc7dd5611283dda239aabb \ + --hash=sha256:2d19e6e2095506d1736b7d80595e0f252d76b89f5e715c35e06e937679ea7d7a \ + --hash=sha256:2d390634c5182175533585cc89f3608a4682ccb173cc9bb940b2881c8d6f8fa0 \ + --hash=sha256:30caa73029a225b2d40d9fae193e008e24b2026b7ee1a867b7ee8d96ca1a448e \ + --hash=sha256:42c16925aa5a02362f986765f9ebabf20de75cdefdca827d14315c568dcab113 \ + --hash=sha256:45dbed2ab436a9e826e302fcdcbe9133f9b0006e5af7168afb8963a6520da103 \ + --hash=sha256:4636de7fd195197b7535f231b5de9e4b36d2c440b6e566d2e4e4746e6af0ca93 \ + --hash=sha256:4a19d9dba1a76618dd86b164d608566f393f8ec6ac7c44f0cc879011c45e65af \ + --hash=sha256:4bbc7f303d125971f60ec0aaad5e12c62d0d2c925f0ab1273debd0e4ba37aba5 \ + --hash=sha256:4d6d57903571f86180eb98f8f0c839fa9ebbfb031356d87f1361be91e433f5b7 \ + --hash=sha256:4e874c976154687c1f71715b034739b45c7711bec81db01914770373d125e392 \ + --hash=sha256:51fc224f7ca4d92656d5a5eb315f12eb5fe2c97a66249aa7b5f562528a3be38c \ + --hash=sha256:58c8b5929fcb8287cbd6f0a3fae19c6e03a5c48402ae792962ac465224a629a4 \ + --hash=sha256:5a285b3b96f951841799528cd1f4f01cd70e7e0204b4abebac9463eecfcf2a40 \ + --hash=sha256:5c70f1cc1c4efbe316a572e2d8b9b9cc44e89b95f79ca3331553fbb63716e2bf \ + --hash=sha256:62d6b0f03b694173f9fcb1fb317f7222fd0b0b103e784c6549f5e53a27718c44 \ + --hash=sha256:6a246d5914aa1c820c9443ddcee9c02bec3e203b0c080349533fae17727dfd1b \ + --hash=sha256:6aa3236c78803afbcb255045fbef97a9e25a1f6c9888357d205ddc42f4d6eba5 \ + --hash=sha256:6bbe4eb67390b0a0265a2c25458f6b90a409d5d069f1041e6aff1e27e3d9a79e \ + --hash=sha256:715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74 \ + --hash=sha256:72944b19f2324114e9dc86a159787333b77874143efcf89a5167ef83cfee8af0 \ + --hash=sha256:81f4a14bee47aec54f883e0cad2d73986640c1590eb9bfaaba7ad17394481e6e \ + --hash=sha256:846300f379b5b12cc769334464656bc882e0735d27d9726568bc932fdc49d5ec \ + --hash=sha256:86b6f55f5a352b48d7fbfd2dbc3d5b780b2d79f4d3c121f33eb6efb22e9a2015 \ + --hash=sha256:874f200b2a981c647340f841730fc3a2b54c9d940566a3c4149099591e2c4c3d \ + --hash=sha256:8a87ec22c87be071b6bdbd27920b129b94f2fc964358ce38f3822635a3e2e03d \ + --hash=sha256:8b3b60bb7cba2c8c81837661c488637eee696f59a877788a396d33150c35d842 \ + --hash=sha256:8e3ed142f2728df44263aaf5fb1f5b0b99f4070c553a0d7f033be65338329150 \ + --hash=sha256:93e15038125dc1e5345d9b5b68aa7f996ec33b98118d18c6ca0d0b7d6198b7e8 \ + --hash=sha256:989824e9faf85f96ec9c7761cd8d29c531ad857bfa1daa930cba85baaecf1a9a \ + --hash=sha256:99d838547ace2c4aace6c4f76e879ddfe02bb58a80c1549928477862b7a6d6ed \ + --hash=sha256:9b2aec6af35c113b05695ebb5749a787acd63cafc83086a05771d1e1cd1e555f \ + --hash=sha256:9c585a1790d5436a5374bac930dad6ed244c046ed91b2b2a3634eb2971d21008 \ + --hash=sha256:a7164afb23be6e37ad90b2f10426149fd75aee07ca55653d2aa41e66c4ef697e \ + --hash=sha256:ac6b31e35612a26483e20750126d30d0941f949426974cace8e6b5c58a3657b0 \ + --hash=sha256:ad2e2ef14e0b04e544ea2fa0a36463f847f113d314aa02e5b402fdf910ef309e \ + --hash=sha256:b268594bccac7d7cf5844c7732e3f20c50921d94e36d7ec9b79e9857694b1b2f \ + --hash=sha256:b5f0362dc928a6ecd9db58868fca5e48485205e3855957bdedea308f8672ea4a \ + --hash=sha256:ba1f4fc670ed79f876f70082eff4f9583c15fb9a4b89d6188412de4d18ae2f40 \ + --hash=sha256:ba203255017337d39f89bdd58417f03c4426f12beed0440cfd933cb15f8669c7 \ + --hash=sha256:c901b15172510173f5cb310eae652908340f8dede90fff9e3bf6c0d8dfd92f83 \ + --hash=sha256:c9b39d38a9bd2ae1becd7eac1303d031c5c110ad31f2b319c6e7d98b135c934d \ + --hash=sha256:d2a8490669bfe99a233298348acc2d824d496dee0e66e31b66a6022c2ad74a5c \ + --hash=sha256:dddbbd259598d7240b18c9d87c56a9d2fb3b02fe266f49a7c101532e78c1d871 \ + --hash=sha256:df3775294accfdd75f32c74ae39fcba920c9a378a2fc18a12b6820aa8c1fb502 \ + --hash=sha256:e44319a2953c738205bf3354537979eaa3998ed673395b964c1176083dd46252 \ + --hash=sha256:e4a010c27ff6f210ff4c6ef34394cd61470d01014439b192ec22552ee867f2a8 \ + --hash=sha256:e823b8b6edc81e747526f70f71a9c0a07ac4e7ad13020aa736bb7c9d67196115 \ + --hash=sha256:e892aff75639bbef0d2a2cfd55535510df26ff92f63c92cd84ef8d4ba5a5557f \ + --hash=sha256:eea7ac5d2dce4189771cedb559c738a71512768210dc4e4753b107a2048b3d0e \ + --hash=sha256:ef4059d6e5152fa1a39f888e344c73fdc926e1b2dd58c771d67b0acfbf2aa67d \ + --hash=sha256:f169b9a863d34f5d11b8698ead99febeaa17a13ca044961aa8e2662a6c7766a0 \ + --hash=sha256:f2cf083b324a467e1ab358c105f6cad5ea950f50524668a80c486ff1db24e119 \ + --hash=sha256:f8474c4241bc18b750be2abea9d7a9ec84f46ef861dbacf86a4f6e043401f79e \ + --hash=sha256:f983334aea213c99992053ede6168500e5f086ce74fbc4acc3f2b00f5762e9db \ + --hash=sha256:f9e75681b59ddaa5e659898085ae0eaea229d054f2ac0c7e563a62205a700121 \ + --hash=sha256:fbc356aae7adf9e6336d336b9c8111d390a05df88f1805573ebb0807bd06fd1d \ + --hash=sha256:fcfe2045fd2e8f3cb0ce9d4ba6dba6333b8fa05bb8a4939c908cd43322d14c7e # via # feast (pyproject.toml) # dask @@ -755,17 +763,15 @@ prometheus-client==0.24.1 \ --hash=sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055 \ --hash=sha256:7e0ced7fbbd40f7b84962d5d2ab6f17ef88a72504dcf7c0b40737b43b2a461f9 # via feast (pyproject.toml) -protobuf==6.33.5 \ - --hash=sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c \ - --hash=sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02 \ - --hash=sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c \ - --hash=sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd \ - --hash=sha256:8f04fa32763dcdb4973d537d6b54e615cc61108c7cb38fe59310c3192d29510a \ - --hash=sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190 \ - --hash=sha256:a3157e62729aafb8df6da2c03aa5c0937c7266c626ce11a278b6eb7963c4e37c \ - --hash=sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5 \ - --hash=sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0 \ - --hash=sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b +protobuf==7.34.1 \ + --hash=sha256:34b84ce27680df7cca9f231043ada0daa55d0c44a2ddfaa58ec1d0d89d8bf60a \ + --hash=sha256:403b093a6e28a960372b44e5eb081775c9b056e816a8029c61231743d63f881a \ + --hash=sha256:5185e0e948d07abe94bb76ec9b8416b604cfe5da6f871d67aad30cbf24c3110b \ + --hash=sha256:8ff40ce8cd688f7265326b38d5a1bed9bfdf5e6723d49961432f83e21d5713e4 \ + --hash=sha256:9ce42245e704cc5027be797c1db1eb93184d44d1cdd71811fb2d9b25ad541280 \ + --hash=sha256:bb3812cd53aefea2b028ef42bd780f5b96407247f20c6ef7c679807e9d188f11 \ + --hash=sha256:d8b2cc79c4d8f62b293ad9b11ec3aebce9af481fa73e64556969f7345ebf9fc7 \ + --hash=sha256:e97b55646e6ce5cbb0954a8c28cd39a5869b59090dfaa7df4598a7fba869468c # via feast (pyproject.toml) psutil==7.2.2 \ --hash=sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372 \ @@ -973,25 +979,25 @@ pydantic-core==2.41.5 \ --hash=sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425 \ --hash=sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52 # via pydantic -pygments==2.19.2 \ - --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \ - --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b +pygments==2.20.0 \ + --hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \ + --hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176 # via feast (pyproject.toml) -pyjwt==2.11.0 \ - --hash=sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623 \ - --hash=sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469 +pyjwt==2.12.1 \ + --hash=sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c \ + --hash=sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b # via feast (pyproject.toml) python-dateutil==2.9.0.post0 \ --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 # via pandas -python-dotenv==1.2.1 \ - --hash=sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6 \ - --hash=sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61 +python-dotenv==1.2.2 \ + --hash=sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a \ + --hash=sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3 # via uvicorn -pytz==2025.2 \ - --hash=sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3 \ - --hash=sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00 +pytz==2026.1.post1 \ + --hash=sha256:3378dde6a0c3d26719182142c56e60c7f9af7e968076f31aae569d72a0358ee1 \ + --hash=sha256:f2fd16142fda348286a75e1a524be810bb05d444e5a081f37f7affc635035f7a # via pandas pyyaml==6.0.3 \ --hash=sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c \ @@ -1077,9 +1083,9 @@ referencing==0.37.0 \ # via # jsonschema # jsonschema-specifications -requests==2.32.5 \ - --hash=sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6 \ - --hash=sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf +requests==2.33.1 \ + --hash=sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517 \ + --hash=sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a # via feast (pyproject.toml) rpds-py==0.30.0 \ --hash=sha256:07ae8a593e1c3c6b82ca3292efbe73c30b61332fd612e05abee07c79359f292f \ @@ -1204,74 +1210,78 @@ six==1.17.0 \ --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \ --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81 # via python-dateutil -sqlalchemy[mypy]==2.0.46 \ - --hash=sha256:09168817d6c19954d3b7655da6ba87fcb3a62bb575fb396a81a8b6a9fadfe8b5 \ - --hash=sha256:0cc3117db526cad3e61074100bd2867b533e2c7dc1569e95c14089735d6fb4fe \ - --hash=sha256:181903fe8c1b9082995325f1b2e84ac078b1189e2819380c2303a5f90e114a62 \ - --hash=sha256:1bc3f601f0a818d27bfe139f6766487d9c88502062a2cd3a7ee6c342e81d5047 \ - --hash=sha256:1e6199143d51e3e1168bedd98cc698397404a8f7508831b81b6a29b18b051069 \ - --hash=sha256:2347c3f0efc4de367ba00218e0ae5c4ba2306e47216ef80d6e31761ac97cb0b9 \ - --hash=sha256:261c4b1f101b4a411154f1da2b76497d73abbfc42740029205d4d01fa1052684 \ - --hash=sha256:33e462154edb9493f6c3ad2125931e273bbd0be8ae53f3ecd1c161ea9a1dd366 \ - --hash=sha256:37fee2164cf21417478b6a906adc1a91d69ae9aba8f9533e67ce882f4bb1de53 \ - --hash=sha256:3a9a72b0da8387f15d5810f1facca8f879de9b85af8c645138cba61ea147968c \ - --hash=sha256:3aac08f7546179889c62b53b18ebf1148b10244b3405569c93984b0388d016a7 \ - --hash=sha256:3c32e993bc57be6d177f7d5d31edb93f30726d798ad86ff9066d75d9bf2e0b6b \ - --hash=sha256:412f26bb4ba942d52016edc8d12fb15d91d3cd46b0047ba46e424213ad407bcb \ - --hash=sha256:42a1643dc5427b69aca967dae540a90b0fbf57eaf248f13a90ea5930e0966863 \ - --hash=sha256:4396c948d8217e83e2c202fbdcc0389cf8c93d2c1c5e60fa5c5a955eae0e64be \ - --hash=sha256:4dafb537740eef640c4d6a7c254611dca2df87eaf6d14d6a5fca9d1f4c3fc0fa \ - --hash=sha256:4f52f7291a92381e9b4de9050b0a65ce5d6a763333406861e33906b8aa4906bf \ - --hash=sha256:52fe29b3817bd191cc20bad564237c808967972c97fa683c04b28ec8979ae36f \ - --hash=sha256:56bdd261bfd0895452006d5316cbf35739c53b9bb71a170a331fa0ea560b2ada \ - --hash=sha256:585af6afe518732d9ccd3aea33af2edaae4a7aa881af5d8f6f4fe3a368699597 \ - --hash=sha256:590be24e20e2424a4c3c1b0835e9405fa3d0af5823a1a9fc02e5dff56471515f \ - --hash=sha256:64901e08c33462acc9ec3bad27fc7a5c2b6491665f2aa57564e57a4f5d7c52ad \ - --hash=sha256:6ac245604295b521de49b465bab845e3afe6916bcb2147e5929c8041b4ec0545 \ - --hash=sha256:6f827fd687fa1ba7f51699e1132129eac8db8003695513fcf13fc587e1bd47a5 \ - --hash=sha256:70ed2830b169a9960193f4d4322d22be5c0925357d82cbf485b3369893350908 \ - --hash=sha256:716be5bcabf327b6d5d265dbdc6213a01199be587224eb991ad0d37e83d728fd \ - --hash=sha256:7568fe771f974abadce52669ef3a03150ff03186d8eb82613bc8adc435a03f01 \ - --hash=sha256:77f8071d8fbcbb2dd11b7fd40dedd04e8ebe2eb80497916efedba844298065ef \ - --hash=sha256:82ec52100ec1e6ec671563bbd02d7c7c8d0b9e71a0723c72f22ecf52d1755330 \ - --hash=sha256:895296687ad06dc9b11a024cf68e8d9d3943aa0b4964278d2553b86f1b267735 \ - --hash=sha256:8d3b44b3d0ab2f1319d71d9863d76eeb46766f8cf9e921ac293511804d39813f \ - --hash=sha256:8d679b5f318423eacb61f933a9a0f75535bfca7056daeadbf6bd5bcee6183aee \ - --hash=sha256:8e84b09a9b0f19accedcbeff5c2caf36e0dd537341a33aad8d680336152dc34e \ - --hash=sha256:9094c8b3197db12aa6f05c51c05daaad0a92b8c9af5388569847b03b1007fb1b \ - --hash=sha256:90bde6c6b1827565a95fde597da001212ab436f1b2e0c2dcc7246e14db26e2a3 \ - --hash=sha256:9397b381dcee8a2d6b99447ae85ea2530dcac82ca494d1db877087a13e38926d \ - --hash=sha256:93a12da97cca70cea10d4b4fc602589c4511f96c1f8f6c11817620c021d21d00 \ - --hash=sha256:93bb0aae40b52c57fd74ef9c6933c08c040ba98daf23ad33c3f9893494b8d3ce \ - --hash=sha256:94b1e5f3a5f1ff4f42d5daab047428cd45a3380e51e191360a35cef71c9a7a2a \ - --hash=sha256:965c62be8256d10c11f8907e7a8d3e18127a4c527a5919d85fa87fd9ecc2cfdc \ - --hash=sha256:96c7cca1a4babaaf3bfff3e4e606e38578856917e52f0384635a95b226c87764 \ - --hash=sha256:9bcdce05f056622a632f1d44bb47dbdb677f58cad393612280406ce37530eb6d \ - --hash=sha256:9d80ea2ac519c364a7286e8d765d6cd08648f5b21ca855a8017d9871f075542d \ - --hash=sha256:a1e8cc6cc01da346dc92d9509a63033b9b1bda4fed7a7a7807ed385c7dccdc10 \ - --hash=sha256:ab65cb2885a9f80f979b85aa4e9c9165a31381ca322cbde7c638fe6eefd1ec39 \ - --hash=sha256:af865c18752d416798dae13f83f38927c52f085c52e2f32b8ab0fef46fdd02c2 \ - --hash=sha256:b1e14b2f6965a685c7128bd315e27387205429c2e339eeec55cb75ca4ab0ea2e \ - --hash=sha256:b2a9f9aee38039cf4755891a1e50e1effcc42ea6ba053743f452c372c3152b1b \ - --hash=sha256:be6c0466b4c25b44c5d82b0426b5501de3c424d7a3220e86cd32f319ba56798e \ - --hash=sha256:c4e2cc868b7b5208aec6c960950b7bb821f82c2fe66446c92ee0a571765e91a5 \ - --hash=sha256:c805fa6e5d461329fa02f53f88c914d189ea771b6821083937e79550bf31fc19 \ - --hash=sha256:cf36851ee7219c170bb0793dbc3da3e80c582e04a5437bc601bfe8c85c9216d7 \ - --hash=sha256:db23b1bf8cfe1f7fda19018e7207b20cdb5168f83c437ff7e95d19e39289c447 \ - --hash=sha256:e0c05aff5c6b1bb5fb46a87e0f9d2f733f83ef6cbbbcd5c642b6c01678268061 \ - --hash=sha256:e8ac45e8f4eaac0f9f8043ea0e224158855c6a4329fd4ee37c45c61e3beb518e \ - --hash=sha256:ea3cd46b6713a10216323cda3333514944e510aa691c945334713fca6b5279ff \ - --hash=sha256:ebf7e1e78af38047e08836d33502c7a278915698b7c2145d045f780201679999 \ - --hash=sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e \ - --hash=sha256:ff33c6e6ad006bbc0f34f5faf941cfc62c45841c64c0a058ac38c799f15b5ede +sqlalchemy[mypy]==2.0.48 \ + --hash=sha256:01f6bbd4308b23240cf7d3ef117557c8fd097ec9549d5d8a52977544e35b40ad \ + --hash=sha256:07edba08061bc277bfdc772dd2a1a43978f5a45994dd3ede26391b405c15221e \ + --hash=sha256:10853a53a4a00417a00913d270dddda75815fcb80675874285f41051c094d7dd \ + --hash=sha256:1182437cb2d97988cfea04cf6cdc0b0bb9c74f4d56ec3d08b81e23d621a28cc6 \ + --hash=sha256:144921da96c08feb9e2b052c5c5c1d0d151a292c6135623c6b2c041f2a45f9e0 \ + --hash=sha256:1a89ce07ad2d4b8cfc30bd5889ec40613e028ed80ef47da7d9dd2ce969ad30e0 \ + --hash=sha256:1b4c575df7368b3b13e0cebf01d4679f9a28ed2ae6c1cd0b1d5beffb6b2007dc \ + --hash=sha256:1ccd42229aaac2df431562117ac7e667d702e8e44afdb6cf0e50fa3f18160f0b \ + --hash=sha256:2645b7d8a738763b664a12a1542c89c940daa55196e8d73e55b169cc5c99f65f \ + --hash=sha256:288937433bd44e3990e7da2402fabc44a3c6c25d3704da066b85b89a85474ae0 \ + --hash=sha256:34634e196f620c7a61d18d5cf7dc841ca6daa7961aed75d532b7e58b309ac894 \ + --hash=sha256:348174f228b99f33ca1f773e85510e08927620caa59ffe7803b37170df30332b \ + --hash=sha256:36ac4ddc3d33e852da9cb00ffb08cea62ca05c39711dc67062ca2bb1fae35fd8 \ + --hash=sha256:3713e21ea67bca727eecd4a24bf68bcd414c403faae4989442be60994301ded0 \ + --hash=sha256:389b984139278f97757ea9b08993e7b9d1142912e046ab7d82b3fbaeb0209131 \ + --hash=sha256:426c5ca86415d9b8945c7073597e10de9644802e2ff502b8e1f11a7a2642856b \ + --hash=sha256:4599a95f9430ae0de82b52ff0d27304fe898c17cb5f4099f7438a51b9998ac77 \ + --hash=sha256:49b7bddc1eebf011ea5ab722fdbe67a401caa34a350d278cc7733c0e88fecb1f \ + --hash=sha256:53667b5f668991e279d21f94ccfa6e45b4e3f4500e7591ae59a8012d0f010dcb \ + --hash=sha256:546572a1793cc35857a2ffa1fe0e58571af1779bcc1ffa7c9fb0839885ed69a9 \ + --hash=sha256:583849c743e0e3c9bb7446f5b5addeacedc168d657a69b418063dfdb2d90081c \ + --hash=sha256:5aee45fd2c6c0f2b9cdddf48c48535e7471e42d6fb81adfde801da0bd5b93241 \ + --hash=sha256:5b193a7e29fd9fa56e502920dca47dffe60f97c863494946bd698c6058a55658 \ + --hash=sha256:5ca74f37f3369b45e1f6b7b06afb182af1fd5dde009e4ffd831830d98cbe5fe7 \ + --hash=sha256:68549c403f79a8e25984376480959975212a670405e3913830614432b5daa07a \ + --hash=sha256:69f5bc24904d3bc3640961cddd2523e361257ef68585d6e364166dfbe8c78fae \ + --hash=sha256:6bb85c546591569558571aa1b06aba711b26ae62f111e15e56136d69920e1616 \ + --hash=sha256:6f7b7243850edd0b8b97043f04748f31de50cf426e939def5c16bedb540698f7 \ + --hash=sha256:7001dc9d5f6bb4deb756d5928eaefe1930f6f4179da3924cbd95ee0e9f4dce89 \ + --hash=sha256:7a936f1bb23d370b7c8cc079d5fce4c7d18da87a33c6744e51a93b0f9e97e9b3 \ + --hash=sha256:7c998f2ace8bf76b453b75dbcca500d4f4b9dd3908c13e89b86289b37784848b \ + --hash=sha256:7cddca31edf8b0653090cbb54562ca027c421c58ddde2c0685f49ff56a1690e0 \ + --hash=sha256:8183dc57ae7d9edc1346e007e840a9f3d6aa7b7f165203a99e16f447150140d2 \ + --hash=sha256:82745b03b4043e04600a6b665cb98697c4339b24e34d74b0a2ac0a2488b6f94d \ + --hash=sha256:841a94c66577661c1f088ac958cd767d7c9bf507698f45afffe7a4017049de76 \ + --hash=sha256:858e433f12b0e5b3ed2f8da917433b634f4937d0e8793e5cb33c54a1a01df565 \ + --hash=sha256:908a3fa6908716f803b86896a09a2c4dde5f5ce2bb07aacc71ffebb57986ce99 \ + --hash=sha256:9764014ef5e58aab76220c5664abb5d47d5bc858d9debf821e55cfdd0f128485 \ + --hash=sha256:9c7d0a77e36b5f4b01ca398482230ab792061d243d715299b44a0b55c89fe617 \ + --hash=sha256:a5b429eb84339f9f05e06083f119ad814e6d85e27ecbdf9c551dfdbb128eaf8a \ + --hash=sha256:a66fe406437dd65cacd96a72689a3aaaecaebbcd62d81c5ac1c0fdbeac835096 \ + --hash=sha256:a6b764fb312bd35e47797ad2e63f0d323792837a6ac785a4ca967019357d2bc7 \ + --hash=sha256:b19151e76620a412c2ac1c6f977ab1b9fa7ad43140178345136456d5265b32ed \ + --hash=sha256:b8438ec5594980d405251451c5b7ea9aa58dda38eb7ac35fb7e4c696712ee24f \ + --hash=sha256:b8fc3454b4f3bd0a368001d0e968852dad45a873f8b4babd41bc302ec851a099 \ + --hash=sha256:bcb8ebbf2e2c36cfe01a94f2438012c6a9d494cf80f129d9753bcdf33bfc35a6 \ + --hash=sha256:d404dc897ce10e565d647795861762aa2d06ca3f4a728c5e9a835096c7059018 \ + --hash=sha256:d612c976cbc2d17edfcc4c006874b764e85e990c29ce9bd411f926bbfb02b9a2 \ + --hash=sha256:d64177f443594c8697369c10e4bbcac70ef558e0f7921a1de7e4a3d1734bcf67 \ + --hash=sha256:d854b3970067297f3a7fbd7a4683587134aa9b3877ee15aa29eea478dc68f933 \ + --hash=sha256:d8fcccbbc0c13c13702c471da398b8cd72ba740dca5859f148ae8e0e8e0d3e7e \ + --hash=sha256:e004aa9248e8cb0a5f9b96d003ca7c1c0a5da8decd1066e7b53f59eb8ce7c62b \ + --hash=sha256:e214d546c8ecb5fc22d6e6011746082abf13a9cf46eefb45769c7b31407c97b5 \ + --hash=sha256:e2d0d88686e3d35a76f3e15a34e8c12d73fc94c1dea1cd55782e695cc14086dd \ + --hash=sha256:e2f35b4cccd9ed286ad62e0a3c3ac21e06c02abc60e20aa51a3e305a30f5fa79 \ + --hash=sha256:e3070c03701037aa418b55d36532ecb8f8446ed0135acb71c678dbdf12f5b6e4 \ + --hash=sha256:e5e088bf43f6ee6fec7dbf1ef7ff7774a616c236b5c0cb3e00662dd71a56b571 \ + --hash=sha256:e83e3f959aaa1c9df95c22c528096d94848a1bc819f5d0ebf7ee3df0ca63db6c \ + --hash=sha256:f0dcbc588cd5b725162c076eb9119342f6579c7f7f55057bb7e3c6ff27e13121 \ + --hash=sha256:f27f9da0a7d22b9f981108fd4b62f8b5743423388915a563e651c20d06c1f457 \ + --hash=sha256:f8649a14caa5f8a243628b1d61cf530ad9ae4578814ba726816adb1121fc493e \ + --hash=sha256:fac0fa4e4f55f118fd87177dacb1c6522fe39c28d498d259014020fec9164c29 \ + --hash=sha256:fd08b90d211c086181caed76931ecfa2bdfc83eea3cfccdb0f82abc6c4b876cb # via feast (pyproject.toml) -starlette==0.52.1 \ - --hash=sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74 \ - --hash=sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933 +starlette==1.0.0 \ + --hash=sha256:6a4beaf1f81bb472fd19ea9b918b50dc3a77a6f2e190a12954b25e6ed5eea149 \ + --hash=sha256:d3ec55e0bb321692d275455ddfd3df75fff145d009685eb40dc91fc66b03d38b # via fastapi -tabulate==0.9.0 \ - --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ - --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f +tabulate==0.10.0 \ + --hash=sha256:e2cfde8f79420f6deeffdeda9aaec3b6bc5abce947655d17ac662b126e48a60d \ + --hash=sha256:f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3 # via feast (pyproject.toml) tenacity==8.5.0 \ --hash=sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78 \ @@ -1291,9 +1301,9 @@ tqdm==4.67.3 \ --hash=sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb \ --hash=sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf # via feast (pyproject.toml) -typeguard==4.5.0 \ - --hash=sha256:749bea21cdb2553e12831bc29f1eae980b22c7de8331ab67ae7db9e85470b5a7 \ - --hash=sha256:cfda388fc88a9ce42a41890900d6f31ee124bea9b73bb84701a32438e92165c3 +typeguard==4.5.1 \ + --hash=sha256:44d2bf329d49a244110a090b55f5f91aa82d9a9834ebfd30bcc73651e4a8cc40 \ + --hash=sha256:f6f8ecbbc819c9bc749983cc67c02391e16a9b43b8b27f15dc70ed7c4a007274 # via feast (pyproject.toml) typing-extensions==4.15.0 \ --hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \ diff --git a/sdk/python/tests/README.md b/sdk/python/tests/README.md index 5b930129026..418e2131928 100644 --- a/sdk/python/tests/README.md +++ b/sdk/python/tests/README.md @@ -48,19 +48,21 @@ $ tree │ ├── test_offline_write.py │ ├── test_push_features_to_offline_store.py │ ├── test_s3_custom_endpoint.py -│ └── test_universal_historical_retrieval.py +│ ├── test_universal_historical_retrieval.py +│ └── test_universal_types.py +├── cli +│ └── test_universal_cli.py ├── online_store │ ├── test_online_retrieval.py │ ├── test_push_features_to_online_store.py -│ └── test_universal_online.py +│ ├── test_universal_online.py +│ └── test_universal_online_types.py └── registration ├── test_feature_store.py ├── test_inference.py ├── test_registry.py ├── test_sql_registry.py - ├── test_universal_cli.py - ├── test_universal_odfv_feature_inference.py - └── test_universal_types.py + └── test_universal_odfv_feature_inference.py ``` diff --git a/sdk/python/tests/benchmarks/test_bigquery_partition_pruning_benchmark.py b/sdk/python/tests/benchmarks/test_bigquery_partition_pruning_benchmark.py new file mode 100644 index 00000000000..00123e79664 --- /dev/null +++ b/sdk/python/tests/benchmarks/test_bigquery_partition_pruning_benchmark.py @@ -0,0 +1,135 @@ +import os +from datetime import datetime, timedelta, timezone +from unittest.mock import Mock, patch + +import pytest + +from feast.infra.offline_stores.bigquery import ( + BigQueryOfflineStore, + BigQueryOfflineStoreConfig, +) +from feast.infra.offline_stores.bigquery_source import BigQuerySource +from feast.infra.online_stores.sqlite import SqliteOnlineStoreConfig +from feast.repo_config import RepoConfig + +__doc__ = """ +Environment variables: + FEAST_BQ_BENCH_PROJECT: BigQuery project to run dry-run queries in + FEAST_BQ_BENCH_TABLE: BigQuery table in Feast format: project:dataset.table + FEAST_BQ_BENCH_TIMESTAMP_FIELD: event timestamp column name used by Feast + FEAST_BQ_BENCH_PARTITION_COLUMN: partition column to prune (e.g. _PARTITIONDATE) + FEAST_BQ_BENCH_LOCATION: optional BigQuery location + FEAST_BQ_BENCH_START: optional ISO datetime (e.g. 2026-01-01T00:00:00+00:00) + FEAST_BQ_BENCH_END: optional ISO datetime + FEAST_BQ_BENCH_REQUIRE_REDUCTION: if truthy, requires strict byte reduction +""" + + +def _required_env(name: str) -> str: + val = os.environ.get(name) + if not val: + pytest.skip(f"Missing env var {name}") + return val + + +def _optional_iso_datetime(name: str) -> datetime | None: + val = os.environ.get(name) + if not val: + return None + return datetime.fromisoformat(val.replace("Z", "+00:00")) + + +def _estimate_bytes_processed(project: str, location: str | None, sql: str) -> int: + try: + from google.cloud import bigquery + except Exception as e: + pytest.skip(str(e)) + client = bigquery.Client(project=project, location=location) + job_config = bigquery.QueryJobConfig(dry_run=True, use_query_cache=False) + job = client.query(sql, job_config=job_config) + return int(job.total_bytes_processed or 0) + + +@pytest.mark.benchmark(group="bigquery_partition_pruning") +@patch("feast.infra.offline_stores.bigquery._get_bigquery_client") +def test_bigquery_partition_pruning_bytes_processed( + mock_get_bigquery_client, benchmark +): + mock_get_bigquery_client.return_value = Mock() + + project = _required_env("FEAST_BQ_BENCH_PROJECT") + table = _required_env("FEAST_BQ_BENCH_TABLE") + timestamp_field = _required_env("FEAST_BQ_BENCH_TIMESTAMP_FIELD") + partition_column = _required_env("FEAST_BQ_BENCH_PARTITION_COLUMN") + location = os.environ.get("FEAST_BQ_BENCH_LOCATION") + + end = _optional_iso_datetime("FEAST_BQ_BENCH_END") + if end is None: + end = datetime.now(tz=timezone.utc).replace(microsecond=0) + start = _optional_iso_datetime("FEAST_BQ_BENCH_START") + if start is None: + start = end - timedelta(days=7) + + repo_config = RepoConfig( + registry="gs://ml-test/repo/registry.db", + project="bench", + provider="gcp", + online_store=SqliteOnlineStoreConfig(type="sqlite"), + offline_store=BigQueryOfflineStoreConfig(type="bigquery", dataset="feast"), + ) + + source_without_partition = BigQuerySource( + table=table, + timestamp_field=timestamp_field, + ) + source_with_partition = BigQuerySource( + table=table, + timestamp_field=timestamp_field, + date_partition_column=partition_column, + ) + + job_without = BigQueryOfflineStore.pull_all_from_table_or_query( + config=repo_config, + data_source=source_without_partition, + join_key_columns=[], + feature_name_columns=[], + timestamp_field=timestamp_field, + start_date=start, + end_date=end, + ) + job_with = BigQueryOfflineStore.pull_all_from_table_or_query( + config=repo_config, + data_source=source_with_partition, + join_key_columns=[], + feature_name_columns=[], + timestamp_field=timestamp_field, + start_date=start, + end_date=end, + ) + + sql_without = job_without.to_sql() + sql_with = job_with.to_sql() + + def measure(): + bytes_without = _estimate_bytes_processed(project, location, sql_without) + bytes_with = _estimate_bytes_processed(project, location, sql_with) + return bytes_without, bytes_with + + bytes_without, bytes_with = benchmark(measure) + benchmark.extra_info["total_bytes_processed_without_partition_filter"] = ( + bytes_without + ) + benchmark.extra_info["total_bytes_processed_with_partition_filter"] = bytes_with + if bytes_without > 0: + benchmark.extra_info["bytes_ratio_with_over_without"] = ( + bytes_with / bytes_without + ) + + if os.environ.get("FEAST_BQ_BENCH_REQUIRE_REDUCTION", "").lower() in ( + "1", + "true", + "yes", + ): + assert bytes_with < bytes_without + else: + assert bytes_with <= bytes_without diff --git a/sdk/python/tests/benchmarks/test_key_encoding_benchmarks.py b/sdk/python/tests/benchmarks/test_key_encoding_benchmarks.py new file mode 100644 index 00000000000..b34cabbdb37 --- /dev/null +++ b/sdk/python/tests/benchmarks/test_key_encoding_benchmarks.py @@ -0,0 +1,465 @@ +""" +Benchmarks for entity key serialization/deserialization performance. + +This module provides comprehensive performance tests for the key encoding utilities +to validate and track the performance improvements from optimization efforts. +""" + +import time + +import pytest + +from feast.infra.key_encoding_utils import ( + deserialize_entity_key, + serialize_entity_key, + serialize_entity_key_prefix, +) +from feast.protos.feast.types.EntityKey_pb2 import EntityKey as EntityKeyProto +from feast.protos.feast.types.Value_pb2 import Value as ValueProto + + +@pytest.fixture +def single_entity_key(): + """Single entity key (most common case - 90% of usage)""" + return EntityKeyProto( + join_keys=["user_id"], entity_values=[ValueProto(string_val="user123")] + ) + + +@pytest.fixture +def single_entity_key_int(): + """Single entity key with int64 value""" + return EntityKeyProto( + join_keys=["user_id"], entity_values=[ValueProto(int64_val=123456789)] + ) + + +@pytest.fixture +def multi_entity_key_small(): + """Small multi-entity key (2-3 entities)""" + return EntityKeyProto( + join_keys=["user_id", "session_id"], + entity_values=[ + ValueProto(string_val="user123"), + ValueProto(string_val="sess456"), + ], + ) + + +@pytest.fixture +def multi_entity_key_large(): + """Large multi-entity key (5+ entities)""" + return EntityKeyProto( + join_keys=["user_id", "session_id", "device_id", "app_version", "region"], + entity_values=[ + ValueProto(string_val="user123"), + ValueProto(string_val="sess456"), + ValueProto(string_val="dev789"), + ValueProto(string_val="v1.2.3"), + ValueProto(string_val="us-west-2"), + ], + ) + + +@pytest.fixture +def mixed_value_types_key(): + """Entity key with mixed value types""" + return EntityKeyProto( + join_keys=["user_id", "timestamp", "count", "score"], + entity_values=[ + ValueProto(string_val="user123"), + ValueProto(unix_timestamp_val=1758823656), + ValueProto(int64_val=42), + ValueProto(int32_val=95), + ], + ) + + +@pytest.fixture +def batch_entity_keys(single_entity_key, multi_entity_key_small): + """Batch of entity keys for bulk operation testing""" + keys = [] + # Generate 100 single entity keys (typical batch size) + for i in range(80): # 80% single entities + keys.append( + EntityKeyProto( + join_keys=["user_id"], entity_values=[ValueProto(string_val=f"user{i}")] + ) + ) + + # Add 20 multi-entity keys + for i in range(20): + keys.append( + EntityKeyProto( + join_keys=["user_id", "session_id"], + entity_values=[ + ValueProto(string_val=f"user{i}"), + ValueProto(string_val=f"sess{i}"), + ], + ) + ) + + return keys + + +# Serialization Benchmarks + + +@pytest.mark.benchmark(group="serialize_single") +@pytest.mark.parametrize("entity_key_serialization_version", [3]) +def test_serialize_single_entity_string( + benchmark, single_entity_key, entity_key_serialization_version +): + """Benchmark single entity key serialization (string value) - most common case.""" + result = benchmark( + serialize_entity_key, single_entity_key, entity_key_serialization_version + ) + assert len(result) > 0 + + +@pytest.mark.benchmark(group="serialize_single") +@pytest.mark.parametrize("entity_key_serialization_version", [3]) +def test_serialize_single_entity_int( + benchmark, single_entity_key_int, entity_key_serialization_version +): + """Benchmark single entity key serialization (int64 value).""" + result = benchmark( + serialize_entity_key, single_entity_key_int, entity_key_serialization_version + ) + assert len(result) > 0 + + +@pytest.mark.benchmark(group="serialize_multi") +@pytest.mark.parametrize("entity_key_serialization_version", [3]) +def test_serialize_multi_entity_small( + benchmark, multi_entity_key_small, entity_key_serialization_version +): + """Benchmark small multi-entity key serialization.""" + result = benchmark( + serialize_entity_key, multi_entity_key_small, entity_key_serialization_version + ) + assert len(result) > 0 + + +@pytest.mark.benchmark(group="serialize_multi") +@pytest.mark.parametrize("entity_key_serialization_version", [3]) +def test_serialize_multi_entity_large( + benchmark, multi_entity_key_large, entity_key_serialization_version +): + """Benchmark large multi-entity key serialization.""" + result = benchmark( + serialize_entity_key, multi_entity_key_large, entity_key_serialization_version + ) + assert len(result) > 0 + + +@pytest.mark.benchmark(group="serialize_mixed") +@pytest.mark.parametrize("entity_key_serialization_version", [3]) +def test_serialize_mixed_value_types( + benchmark, mixed_value_types_key, entity_key_serialization_version +): + """Benchmark serialization with mixed value types.""" + result = benchmark( + serialize_entity_key, mixed_value_types_key, entity_key_serialization_version + ) + assert len(result) > 0 + + +# Deserialization Benchmarks + + +@pytest.mark.benchmark(group="deserialize_single") +@pytest.mark.parametrize("entity_key_serialization_version", [3]) +def test_deserialize_single_entity_string( + benchmark, single_entity_key, entity_key_serialization_version +): + """Benchmark single entity key deserialization (string value).""" + serialized = serialize_entity_key( + single_entity_key, entity_key_serialization_version + ) + result = benchmark( + deserialize_entity_key, serialized, entity_key_serialization_version + ) + assert result == single_entity_key + + +@pytest.mark.benchmark(group="deserialize_single") +@pytest.mark.parametrize("entity_key_serialization_version", [3]) +def test_deserialize_single_entity_int( + benchmark, single_entity_key_int, entity_key_serialization_version +): + """Benchmark single entity key deserialization (int64 value).""" + serialized = serialize_entity_key( + single_entity_key_int, entity_key_serialization_version + ) + result = benchmark( + deserialize_entity_key, serialized, entity_key_serialization_version + ) + assert result == single_entity_key_int + + +@pytest.mark.benchmark(group="deserialize_multi") +@pytest.mark.parametrize("entity_key_serialization_version", [3]) +def test_deserialize_multi_entity_small( + benchmark, multi_entity_key_small, entity_key_serialization_version +): + """Benchmark small multi-entity key deserialization.""" + serialized = serialize_entity_key( + multi_entity_key_small, entity_key_serialization_version + ) + result = benchmark( + deserialize_entity_key, serialized, entity_key_serialization_version + ) + assert result == multi_entity_key_small + + +@pytest.mark.benchmark(group="deserialize_multi") +@pytest.mark.parametrize("entity_key_serialization_version", [3]) +def test_deserialize_multi_entity_large( + benchmark, multi_entity_key_large, entity_key_serialization_version +): + """Benchmark large multi-entity key deserialization.""" + serialized = serialize_entity_key( + multi_entity_key_large, entity_key_serialization_version + ) + result = benchmark( + deserialize_entity_key, serialized, entity_key_serialization_version + ) + assert result == multi_entity_key_large + + +@pytest.mark.benchmark(group="deserialize_mixed") +@pytest.mark.parametrize("entity_key_serialization_version", [3]) +def test_deserialize_mixed_value_types( + benchmark, mixed_value_types_key, entity_key_serialization_version +): + """Benchmark deserialization with mixed value types.""" + serialized = serialize_entity_key( + mixed_value_types_key, entity_key_serialization_version + ) + result = benchmark( + deserialize_entity_key, serialized, entity_key_serialization_version + ) + assert result == mixed_value_types_key + + +# Round-trip Benchmarks + + +@pytest.mark.benchmark(group="roundtrip_single") +def test_roundtrip_single_entity(benchmark, single_entity_key): + """Benchmark complete serialize + deserialize round-trip for single entity.""" + + def roundtrip(): + serialized = serialize_entity_key(single_entity_key, 3) + return deserialize_entity_key(serialized, 3) + + result = benchmark(roundtrip) + assert result == single_entity_key + + +@pytest.mark.benchmark(group="roundtrip_multi") +def test_roundtrip_multi_entity(benchmark, multi_entity_key_small): + """Benchmark complete serialize + deserialize round-trip for multi-entity.""" + + def roundtrip(): + serialized = serialize_entity_key(multi_entity_key_small, 3) + return deserialize_entity_key(serialized, 3) + + result = benchmark(roundtrip) + assert result == multi_entity_key_small + + +# Prefix Serialization Benchmarks + + +@pytest.mark.benchmark(group="prefix") +def test_serialize_entity_key_prefix_single(benchmark): + """Benchmark entity key prefix serialization for single key.""" + result = benchmark(serialize_entity_key_prefix, ["user_id"], 3) + assert len(result) > 0 + + +@pytest.mark.benchmark(group="prefix") +def test_serialize_entity_key_prefix_multi(benchmark): + """Benchmark entity key prefix serialization for multiple keys.""" + keys = ["user_id", "session_id", "device_id"] + result = benchmark(serialize_entity_key_prefix, keys, 3) + assert len(result) > 0 + + +# Bulk Operations Benchmarks + + +@pytest.mark.benchmark(group="bulk_serialize") +def test_bulk_serialize_batch(benchmark, batch_entity_keys): + """Benchmark batch serialization of 100 mixed entity keys.""" + + def bulk_serialize(): + results = [] + for entity_key in batch_entity_keys: + serialized = serialize_entity_key(entity_key, 3) + results.append(serialized) + return results + + results = benchmark(bulk_serialize) + assert len(results) == 100 + + +@pytest.mark.benchmark(group="bulk_deserialize") +def test_bulk_deserialize_batch(benchmark, batch_entity_keys): + """Benchmark batch deserialization of 100 mixed entity keys.""" + # Pre-serialize all keys + serialized_keys = [serialize_entity_key(key, 3) for key in batch_entity_keys] + + def bulk_deserialize(): + results = [] + for serialized in serialized_keys: + deserialized = deserialize_entity_key(serialized, 3) + results.append(deserialized) + return results + + results = benchmark(bulk_deserialize) + assert len(results) == 100 + + +@pytest.mark.benchmark(group="bulk_roundtrip") +def test_bulk_roundtrip_batch(benchmark, batch_entity_keys): + """Benchmark bulk serialize + deserialize for realistic workload.""" + + def bulk_roundtrip(): + results = [] + for entity_key in batch_entity_keys: + serialized = serialize_entity_key(entity_key, 3) + deserialized = deserialize_entity_key(serialized, 3) + results.append(deserialized) + return results + + results = benchmark(bulk_roundtrip) + assert len(results) == 100 + + +# Memory Efficiency Tests + + +def test_memory_efficiency_serialization(single_entity_key): + """Test memory usage during serialization (not a benchmark, just validation).""" + import os + + import psutil + + process = psutil.Process(os.getpid()) + initial_memory = process.memory_info().rss + + # Perform many serializations + for i in range(10000): + entity_key = EntityKeyProto( + join_keys=["user_id"], entity_values=[ValueProto(string_val=f"user{i}")] + ) + serialize_entity_key(entity_key, 3) + + final_memory = process.memory_info().rss + memory_increase = final_memory - initial_memory + + # Memory increase should be minimal (< 10MB for 10k operations) + # This validates that we're not leaking memory in the optimized version + assert memory_increase < 10 * 1024 * 1024, ( + f"Memory usage increased by {memory_increase / 1024 / 1024:.2f} MB" + ) + + +# Performance Regression Tests + + +def test_performance_regression_single_entity(): + """Regression test: single entity serialization should be faster than baseline.""" + entity_key = EntityKeyProto( + join_keys=["user_id"], entity_values=[ValueProto(string_val="user123")] + ) + + # Warm up + for _ in range(100): + serialize_entity_key(entity_key, 3) + + # Time 1000 operations + start_time = time.perf_counter() + for _ in range(1000): + serialize_entity_key(entity_key, 3) + elapsed = time.perf_counter() - start_time + + # Should be able to do 1000 single entity serializations in < 100ms + # Using a generous threshold to avoid flaky failures on CI runners + assert elapsed < 0.1, ( + f"Single entity serialization too slow: {elapsed:.4f}s for 1000 operations" + ) + + +def test_performance_regression_deserialization(): + """Regression test: deserialization should be fast with memoryview optimization.""" + entity_key = EntityKeyProto( + join_keys=["user_id", "session_id"], + entity_values=[ + ValueProto(string_val="user123"), + ValueProto(string_val="sess456"), + ], + ) + + serialized = serialize_entity_key(entity_key, 3) + + # Warm up + for _ in range(100): + deserialize_entity_key(serialized, 3) + + # Time 1000 operations + start_time = time.perf_counter() + for _ in range(1000): + deserialize_entity_key(serialized, 3) + elapsed = time.perf_counter() - start_time + + # Should be able to do 1000 deserializations in < 200ms + # Using a generous threshold to avoid flaky failures on CI runners + assert elapsed < 0.2, ( + f"Deserialization too slow: {elapsed:.4f}s for 1000 operations" + ) + + +# Binary Compatibility Tests + + +def test_binary_format_consistency_single(): + """Ensure optimizations don't change binary format for single entities.""" + entity_key = EntityKeyProto( + join_keys=["user_id"], entity_values=[ValueProto(string_val="test")] + ) + + # Serialize multiple times - results should be identical + results = [] + for _ in range(10): + serialized = serialize_entity_key(entity_key, 3) + results.append(serialized) + + # All results should be identical + for result in results[1:]: + assert result == results[0], "Binary format inconsistency detected" + + +def test_binary_format_consistency_multi(): + """Ensure optimizations don't change binary format for multi-entity keys.""" + entity_key = EntityKeyProto( + join_keys=["user", "session", "device"], + entity_values=[ + ValueProto(string_val="u1"), + ValueProto(string_val="s1"), + ValueProto(string_val="d1"), + ], + ) + + # Serialize multiple times - results should be identical + results = [] + for _ in range(10): + serialized = serialize_entity_key(entity_key, 3) + results.append(serialized) + + # All results should be identical + for result in results[1:]: + assert result == results[0], "Binary format inconsistency detected" diff --git a/sdk/python/feast/infra/offline_stores/contrib/ray_offline_store/tests/__init__.py b/sdk/python/tests/component/.gitkeep similarity index 100% rename from sdk/python/feast/infra/offline_stores/contrib/ray_offline_store/tests/__init__.py rename to sdk/python/tests/component/.gitkeep diff --git a/sdk/python/feast/infra/online_stores/ikv_online_store/__init__.py b/sdk/python/tests/component/__init__.py similarity index 100% rename from sdk/python/feast/infra/online_stores/ikv_online_store/__init__.py rename to sdk/python/tests/component/__init__.py diff --git a/sdk/python/tests/integration/feature_repos/universal/data_sources/__init__.py b/sdk/python/tests/component/ray/.gitkeep similarity index 100% rename from sdk/python/tests/integration/feature_repos/universal/data_sources/__init__.py rename to sdk/python/tests/component/ray/.gitkeep diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store/__init__.py b/sdk/python/tests/component/ray/__init__.py similarity index 100% rename from sdk/python/tests/integration/feature_repos/universal/online_store/__init__.py rename to sdk/python/tests/component/ray/__init__.py diff --git a/sdk/python/tests/integration/compute_engines/ray_compute/conftest.py b/sdk/python/tests/component/ray/conftest.py similarity index 87% rename from sdk/python/tests/integration/compute_engines/ray_compute/conftest.py rename to sdk/python/tests/component/ray/conftest.py index 885b1555ec7..d2d46b7c9a7 100644 --- a/sdk/python/tests/integration/compute_engines/ray_compute/conftest.py +++ b/sdk/python/tests/component/ray/conftest.py @@ -4,7 +4,7 @@ auto-discovered by pytest. """ -from tests.integration.compute_engines.ray_compute.ray_shared_utils import ( +from tests.component.ray.ray_shared_utils import ( entity_df, feature_dataset, ray_environment, diff --git a/sdk/python/tests/integration/compute_engines/ray_compute/ray_shared_utils.py b/sdk/python/tests/component/ray/ray_shared_utils.py similarity index 98% rename from sdk/python/tests/integration/compute_engines/ray_compute/ray_shared_utils.py rename to sdk/python/tests/component/ray/ray_shared_utils.py index 6b28949f401..ba79685d6cb 100644 --- a/sdk/python/tests/integration/compute_engines/ray_compute/ray_shared_utils.py +++ b/sdk/python/tests/component/ray/ray_shared_utils.py @@ -14,7 +14,7 @@ from feast.data_source import DataSource from feast.infra.ray_initializer import shutdown_ray from feast.utils import _utc_now -from tests.integration.feature_repos.repo_configuration import ( +from tests.universal.feature_repos.repo_configuration import ( construct_test_environment, ) diff --git a/sdk/python/tests/integration/compute_engines/ray_compute/repo_configuration.py b/sdk/python/tests/component/ray/repo_configuration.py similarity index 71% rename from sdk/python/tests/integration/compute_engines/ray_compute/repo_configuration.py rename to sdk/python/tests/component/ray/repo_configuration.py index 37d0d020ccd..f18185c35c9 100644 --- a/sdk/python/tests/integration/compute_engines/ray_compute/repo_configuration.py +++ b/sdk/python/tests/component/ray/repo_configuration.py @@ -3,19 +3,16 @@ from feast.infra.offline_stores.contrib.ray_repo_configuration import ( RayDataSourceCreator, ) -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) -from tests.integration.feature_repos.universal.online_store.redis import ( - RedisOnlineStoreCreator, -) def get_ray_compute_engine_test_config() -> IntegrationTestRepoConfig: """Get test configuration for Ray compute engine.""" return IntegrationTestRepoConfig( provider="local", - online_store_creator=RedisOnlineStoreCreator, + online_store={"type": "sqlite"}, offline_store_creator=RayDataSourceCreator, batch_engine={ "type": "ray.engine", diff --git a/sdk/python/tests/integration/compute_engines/ray_compute/test_compute.py b/sdk/python/tests/component/ray/test_compute.py similarity index 99% rename from sdk/python/tests/integration/compute_engines/ray_compute/test_compute.py rename to sdk/python/tests/component/ray/test_compute.py index ef4bfa131da..87a86b983e0 100644 --- a/sdk/python/tests/integration/compute_engines/ray_compute/test_compute.py +++ b/sdk/python/tests/component/ray/test_compute.py @@ -21,7 +21,7 @@ ) from feast.transformation.ray_transformation import RayTransformation from feast.types import Float32, Int32, Int64 -from tests.integration.compute_engines.ray_compute.ray_shared_utils import ( +from tests.component.ray.ray_shared_utils import ( driver, now, ) diff --git a/sdk/python/tests/unit/infra/compute_engines/ray_compute/test_nodes.py b/sdk/python/tests/component/ray/test_nodes.py similarity index 100% rename from sdk/python/tests/unit/infra/compute_engines/ray_compute/test_nodes.py rename to sdk/python/tests/component/ray/test_nodes.py diff --git a/sdk/python/tests/integration/compute_engines/ray_compute/test_source_feature_views.py b/sdk/python/tests/component/ray/test_source_feature_views.py similarity index 99% rename from sdk/python/tests/integration/compute_engines/ray_compute/test_source_feature_views.py rename to sdk/python/tests/component/ray/test_source_feature_views.py index 7d8f23e1bf6..73f64c67dbe 100644 --- a/sdk/python/tests/integration/compute_engines/ray_compute/test_source_feature_views.py +++ b/sdk/python/tests/component/ray/test_source_feature_views.py @@ -10,7 +10,7 @@ MaterializationJobStatus, ) from feast.types import Float32, Int32, Int64 -from tests.integration.compute_engines.ray_compute.ray_shared_utils import ( +from tests.component.ray.ray_shared_utils import ( create_entity_df, create_feature_dataset, create_unique_sink_source, diff --git a/sdk/python/tests/integration/offline_store/test_hybrid_offline_store.py b/sdk/python/tests/component/spark/.gitkeep similarity index 100% rename from sdk/python/tests/integration/offline_store/test_hybrid_offline_store.py rename to sdk/python/tests/component/spark/.gitkeep diff --git a/sdk/python/tests/component/spark/__init__.py b/sdk/python/tests/component/spark/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sdk/python/tests/component/spark/conftest.py b/sdk/python/tests/component/spark/conftest.py new file mode 100644 index 00000000000..8bcd1772296 --- /dev/null +++ b/sdk/python/tests/component/spark/conftest.py @@ -0,0 +1,23 @@ +import pytest +from pyspark.sql import SparkSession + + +@pytest.fixture(scope="session") +def spark_session(): + spark = ( + SparkSession.builder.appName("FeastSparkTests") + .master("local[*]") + .config("spark.sql.shuffle.partitions", "1") + .config("spark.driver.host", "127.0.0.1") + .config("spark.driver.bindAddress", "127.0.0.1") + .getOrCreate() + ) + + yield spark + + spark.stop() + + +@pytest.fixture +def spark_fixture(spark_session): + yield spark_session diff --git a/sdk/python/tests/integration/compute_engines/spark/test_compute.py b/sdk/python/tests/component/spark/test_compute.py similarity index 99% rename from sdk/python/tests/integration/compute_engines/spark/test_compute.py rename to sdk/python/tests/component/spark/test_compute.py index e0855ae31f3..803cd505513 100644 --- a/sdk/python/tests/integration/compute_engines/spark/test_compute.py +++ b/sdk/python/tests/component/spark/test_compute.py @@ -19,7 +19,7 @@ SparkOfflineStore, ) from feast.types import Float32, Int32, Int64 -from tests.integration.compute_engines.spark.utils import ( +from tests.component.spark.utils import ( _check_offline_features, _check_online_features, create_entity_df, diff --git a/sdk/python/tests/integration/compute_engines/spark/test_compute_dag.py b/sdk/python/tests/component/spark/test_compute_dag.py similarity index 99% rename from sdk/python/tests/integration/compute_engines/spark/test_compute_dag.py rename to sdk/python/tests/component/spark/test_compute_dag.py index 24277d9a323..04b8a0b2edf 100644 --- a/sdk/python/tests/integration/compute_engines/spark/test_compute_dag.py +++ b/sdk/python/tests/component/spark/test_compute_dag.py @@ -19,7 +19,7 @@ SparkSource, ) from feast.types import Float32, Int32, Int64 -from tests.integration.compute_engines.spark.utils import ( +from tests.component.spark.utils import ( _check_offline_features, _check_online_features, create_entity_df, diff --git a/sdk/python/tests/unit/infra/compute_engines/spark/test_nodes.py b/sdk/python/tests/component/spark/test_nodes.py similarity index 93% rename from sdk/python/tests/unit/infra/compute_engines/spark/test_nodes.py rename to sdk/python/tests/component/spark/test_nodes.py index 7fcc332aefb..c8ed1157d86 100644 --- a/sdk/python/tests/unit/infra/compute_engines/spark/test_nodes.py +++ b/sdk/python/tests/component/spark/test_nodes.py @@ -1,9 +1,6 @@ from datetime import datetime, timedelta from unittest.mock import MagicMock -import pytest -from pyspark.sql import SparkSession - from feast.aggregation import Aggregation from feast.infra.compute_engines.dag.context import ColumnInfo, ExecutionContext from feast.infra.compute_engines.dag.model import DAGFormat @@ -19,22 +16,6 @@ ) -@pytest.fixture(scope="session") -def spark_session(): - spark = ( - SparkSession.builder.appName("FeastSparkTests") - .master("local[*]") - .config("spark.sql.shuffle.partitions", "1") - .config("spark.driver.host", "127.0.0.1") - .config("spark.driver.bindAddress", "127.0.0.1") - .getOrCreate() - ) - - yield spark - - spark.stop() - - def test_spark_transformation_node_executes_udf(spark_session): # Sample Spark input df = spark_session.createDataFrame( diff --git a/sdk/python/tests/unit/infra/offline_stores/contrib/spark_offline_store/test_spark.py b/sdk/python/tests/component/spark/test_spark.py similarity index 100% rename from sdk/python/tests/unit/infra/offline_stores/contrib/spark_offline_store/test_spark.py rename to sdk/python/tests/component/spark/test_spark.py diff --git a/sdk/python/tests/integration/materialization/contrib/spark/test_spark_materialization_engine.py b/sdk/python/tests/component/spark/test_spark_materialization_engine.py similarity index 90% rename from sdk/python/tests/integration/materialization/contrib/spark/test_spark_materialization_engine.py rename to sdk/python/tests/component/spark/test_spark_materialization_engine.py index 03f942c2f96..dbd4d842914 100644 --- a/sdk/python/tests/integration/materialization/contrib/spark/test_spark_materialization_engine.py +++ b/sdk/python/tests/component/spark/test_spark_materialization_engine.py @@ -10,13 +10,13 @@ ) from feast.types import Float32 from tests.data.data_creator import create_basic_driver_dataset -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) -from tests.integration.feature_repos.repo_configuration import ( +from tests.universal.feature_repos.repo_configuration import ( construct_test_environment, ) -from tests.integration.feature_repos.universal.online_store.redis import ( +from tests.universal.feature_repos.universal.online_store.redis import ( RedisOnlineStoreCreator, ) from tests.utils.e2e_test_validation import validate_offline_online_store_consistency diff --git a/sdk/python/tests/unit/infra/offline_stores/contrib/spark_offline_store/test_spark_table_format_integration.py b/sdk/python/tests/component/spark/test_spark_table_format_integration.py similarity index 100% rename from sdk/python/tests/unit/infra/offline_stores/contrib/spark_offline_store/test_spark_table_format_integration.py rename to sdk/python/tests/component/spark/test_spark_table_format_integration.py diff --git a/sdk/python/tests/component/spark/test_spark_transformation.py b/sdk/python/tests/component/spark/test_spark_transformation.py new file mode 100644 index 00000000000..1345c77f0f4 --- /dev/null +++ b/sdk/python/tests/component/spark/test_spark_transformation.py @@ -0,0 +1,105 @@ +from unittest.mock import patch + +from pyspark.sql.functions import col, regexp_replace +from pyspark.testing.utils import assertDataFrameEqual + +from feast.transformation.base import Transformation +from feast.transformation.mode import TransformationMode +from feast.transformation.spark_transformation import SparkTransformation + + +def get_sample_df(spark): + sample_data = [ + {"name": "John D.", "age": 30}, + {"name": "Alice G.", "age": 25}, + {"name": "Bob T.", "age": 35}, + {"name": "Eve A.", "age": 28}, + ] + df = spark.createDataFrame(sample_data) + return df + + +def get_expected_df(spark): + expected_data = [ + {"name": "John D.", "age": 30}, + {"name": "Alice G.", "age": 25}, + {"name": "Bob T.", "age": 35}, + {"name": "Eve A.", "age": 28}, + ] + + expected_df = spark.createDataFrame(expected_data) + return expected_df + + +def remove_extra_spaces(df, column_name): + df_transformed = df.withColumn( + column_name, regexp_replace(col(column_name), "\\s+", " ") + ) + return df_transformed + + +def remove_extra_spaces_sql(df, column_name): + sql = f""" + SELECT + age, + regexp_replace({column_name}, '\\\\s+', ' ') as {column_name} + FROM {df} + """ + return sql + + +def test_spark_transformation(spark_fixture): + with patch( + "feast.infra.compute_engines.spark.utils.get_or_create_new_spark_session" + ) as m: + m.return_value = spark_fixture + spark = spark_fixture + df = get_sample_df(spark) + + spark_transformation = Transformation( + mode=TransformationMode.SPARK, + udf=remove_extra_spaces, + udf_string="remove extra spaces", + ) + + transformed_df = spark_transformation.transform(df, "name") + expected_df = get_expected_df(spark) + assertDataFrameEqual(transformed_df, expected_df) + + +def test_spark_transformation_init_transformation(spark_fixture): + with patch( + "feast.infra.compute_engines.spark.utils.get_or_create_new_spark_session" + ) as m: + m.return_value = spark_fixture + spark = spark_fixture + df = get_sample_df(spark) + + spark_transformation = SparkTransformation( + mode=TransformationMode.SPARK, + udf=remove_extra_spaces, + udf_string="remove extra spaces", + ) + + transformed_df = spark_transformation.transform(df, "name") + expected_df = get_expected_df(spark) + assertDataFrameEqual(transformed_df, expected_df) + + +def test_spark_transformation_sql(spark_fixture): + with patch( + "feast.infra.compute_engines.spark.utils.get_or_create_new_spark_session" + ) as m: + m.return_value = spark_fixture + spark = spark_fixture + df = get_sample_df(spark) + + spark_transformation = SparkTransformation( + mode=TransformationMode.SPARK_SQL, + udf=remove_extra_spaces_sql, + udf_string="remove extra spaces sql", + ) + + transformed_df = spark_transformation.transform(df, "name") + expected_df = get_expected_df(spark) + assertDataFrameEqual(transformed_df, expected_df) diff --git a/sdk/python/tests/integration/compute_engines/spark/utils.py b/sdk/python/tests/component/spark/utils.py similarity index 94% rename from sdk/python/tests/integration/compute_engines/spark/utils.py rename to sdk/python/tests/component/spark/utils.py index 20ffba4eff1..f12eef58948 100644 --- a/sdk/python/tests/integration/compute_engines/spark/utils.py +++ b/sdk/python/tests/component/spark/utils.py @@ -7,13 +7,13 @@ from feast.infra.offline_stores.contrib.spark_offline_store.tests.data_source import ( SparkDataSourceCreator, ) -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) -from tests.integration.feature_repos.repo_configuration import ( +from tests.universal.feature_repos.repo_configuration import ( construct_test_environment, ) -from tests.integration.feature_repos.universal.online_store.redis import ( +from tests.universal.feature_repos.universal.online_store.redis import ( RedisOnlineStoreCreator, ) diff --git a/sdk/python/tests/conftest.py b/sdk/python/tests/conftest.py index a57846c7e2e..8302e313a2d 100644 --- a/sdk/python/tests/conftest.py +++ b/sdk/python/tests/conftest.py @@ -36,10 +36,10 @@ create_document_dataset, create_image_dataset, ) -from tests.integration.feature_repos.integration_test_repo_config import ( # noqa: E402 +from tests.universal.feature_repos.integration_test_repo_config import ( # noqa: E402 IntegrationTestRepoConfig, ) -from tests.integration.feature_repos.repo_configuration import ( # noqa: E402 +from tests.universal.feature_repos.repo_configuration import ( # noqa: E402 AVAILABLE_OFFLINE_STORES, AVAILABLE_ONLINE_STORES, OFFLINE_STORE_TO_PROVIDER_CONFIG, @@ -49,10 +49,10 @@ construct_universal_feature_views, construct_universal_test_data, ) -from tests.integration.feature_repos.universal.data_sources.file import ( # noqa: E402 +from tests.universal.feature_repos.universal.data_sources.file import ( # noqa: E402 FileDataSourceCreator, ) -from tests.integration.feature_repos.universal.entities import ( # noqa: E402 +from tests.universal.feature_repos.universal.entities import ( # noqa: E402 customer, driver, location, @@ -101,6 +101,10 @@ def pytest_configure(config): "markers", "universal_offline_stores: mark tests that can be run against different offline stores", ) + config.addinivalue_line( + "markers", + "ray_offline_stores_only: mark tests that currently only work with Ray offline store", + ) def pytest_addoption(parser): @@ -431,6 +435,9 @@ def fake_ingest_data(): "conv_rate": [0.5], "acc_rate": [0.6], "avg_daily_trips": [4], + "driver_metadata": [None], + "driver_config": [None], + "driver_profile": [None], "event_timestamp": [pd.Timestamp(_utc_now()).round("ms")], "created": [pd.Timestamp(_utc_now()).round("ms")], } diff --git a/sdk/python/tests/doctest/test_all.py b/sdk/python/tests/doctest/test_all.py index 802ae513e16..bf9e63be6e2 100644 --- a/sdk/python/tests/doctest/test_all.py +++ b/sdk/python/tests/doctest/test_all.py @@ -72,27 +72,41 @@ def test_docstrings(): for package in current_packages: try: - for _, name, is_pkg in pkgutil.walk_packages(package.__path__): + for _, name, is_pkg in pkgutil.walk_packages( + package.__path__, onerror=lambda _: None + ): if name in FILES_TO_IGNORE: continue full_name = package.__name__ + "." + name + temp_module = None try: # https://github.com/feast-dev/feast/issues/5088 # Skip ray_transformation doctests - they hang on macOS due to # Ray worker spawning issues with uv-managed environments if ( - "ikv" not in full_name - and "milvus" not in full_name + "milvus" not in full_name and "openlineage" not in full_name and "ray_transformation" not in full_name + and "qdrant" not in full_name ): temp_module = importlib.import_module(full_name) if is_pkg: next_packages.append(temp_module) - except ModuleNotFoundError: + except Exception: # noqa: BLE001 + # Gracefully skip modules that fail to import due to: + # - ModuleNotFoundError: optional system dependency missing + # - FeastExtrasDependencyImportError: optional Python extra + # missing (e.g. pymongo, couchbase) + # - TypeError or other errors: third-party libraries with + # internal incompatibilities at import time (e.g. + # qdrant_client raises TypeError when a grpc EnumTypeWrapper + # is used with the | union operator on Python < 3.12) pass + if temp_module is None: + continue + # Retrieve the setup and teardown functions defined in this file. relative_path_from_feast = full_name.split(".", 1)[1] function_suffix = relative_path_from_feast.replace(".", "_") diff --git a/sdk/python/tests/example_repos/example_feature_repo_1.py b/sdk/python/tests/example_repos/example_feature_repo_1.py index 492b8c5555d..4cdcb9622a4 100644 --- a/sdk/python/tests/example_repos/example_feature_repo_1.py +++ b/sdk/python/tests/example_repos/example_feature_repo_1.py @@ -5,7 +5,7 @@ from feast import Entity, FeatureService, FeatureView, Field, FileSource, PushSource from feast.on_demand_feature_view import on_demand_feature_view from feast.types import Array, Float32, Int64, String -from tests.integration.feature_repos.universal.feature_views import TAGS +from tests.universal.feature_repos.universal.feature_views import TAGS # Note that file source paths are not validated, so there doesn't actually need to be any data # at the paths for these file sources. Since these paths are effectively fake, this example diff --git a/sdk/python/tests/example_repos/example_feature_repo_with_project_1.py b/sdk/python/tests/example_repos/example_feature_repo_with_project_1.py index ad04d7ae664..a6db2d63a33 100644 --- a/sdk/python/tests/example_repos/example_feature_repo_with_project_1.py +++ b/sdk/python/tests/example_repos/example_feature_repo_with_project_1.py @@ -6,7 +6,7 @@ from feast.on_demand_feature_view import on_demand_feature_view from feast.project import Project from feast.types import Array, Float32, Int64, String -from tests.integration.feature_repos.universal.feature_views import TAGS +from tests.universal.feature_repos.universal.feature_views import TAGS # Note that file source paths are not validated, so there doesn't actually need to be any data # at the paths for these file sources. Since these paths are effectively fake, this example diff --git a/sdk/python/tests/foo_provider.py b/sdk/python/tests/foo_provider.py index a04ff3cc456..82cfc7fb513 100644 --- a/sdk/python/tests/foo_provider.py +++ b/sdk/python/tests/foo_provider.py @@ -155,6 +155,7 @@ def retrieve_online_documents( query: List[float], top_k: int, distance_metric: Optional[str] = None, + include_feature_view_version_metadata: bool = False, ) -> List[ Tuple[ Optional[datetime], @@ -174,6 +175,7 @@ def retrieve_online_documents_v2( top_k: int, distance_metric: Optional[str] = None, query_string: Optional[str] = None, + include_feature_view_version_metadata: bool = False, ) -> List[ Tuple[ Optional[datetime], @@ -206,6 +208,7 @@ def get_online_features( registry: BaseRegistry, project: str, full_feature_names: bool = False, + include_feature_view_version_metadata: bool = False, ) -> OnlineResponse: pass @@ -220,6 +223,7 @@ async def get_online_features_async( registry: BaseRegistry, project: str, full_feature_names: bool = False, + include_feature_view_version_metadata: bool = False, ) -> OnlineResponse: pass diff --git a/sdk/python/tests/integration/cli/__init__.py b/sdk/python/tests/integration/cli/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sdk/python/tests/integration/registration/test_universal_cli.py b/sdk/python/tests/integration/cli/test_universal_cli.py similarity index 99% rename from sdk/python/tests/integration/registration/test_universal_cli.py rename to sdk/python/tests/integration/cli/test_universal_cli.py index 735f71407f6..ed9aea7ff91 100644 --- a/sdk/python/tests/integration/registration/test_universal_cli.py +++ b/sdk/python/tests/integration/cli/test_universal_cli.py @@ -7,7 +7,7 @@ from assertpy import assertpy from feast.feature_store import FeatureStore -from tests.integration.feature_repos.universal.data_sources.file import ( +from tests.universal.feature_repos.universal.data_sources.file import ( FileDataSourceCreator, ) from tests.utils.basic_read_write_test import basic_rw_test diff --git a/sdk/python/tests/integration/compute_engines/ray_compute/__init__.py b/sdk/python/tests/integration/compute_engines/ray_compute/__init__.py deleted file mode 100644 index 7938db59420..00000000000 --- a/sdk/python/tests/integration/compute_engines/ray_compute/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Ray compute engine integration tests.""" diff --git a/sdk/python/tests/integration/dbt/conftest.py b/sdk/python/tests/integration/dbt/conftest.py index d1df145f3ec..00ee01e7027 100644 --- a/sdk/python/tests/integration/dbt/conftest.py +++ b/sdk/python/tests/integration/dbt/conftest.py @@ -29,4 +29,7 @@ def pytest_collection_modifyitems(config, items): # noqa: ARG001 reason="dbt manifest.json not found - run 'dbt build' first or use dbt-integration-test workflow" ) for item in items: - item.add_marker(skip_marker) + if str(TEST_DBT_PROJECT_DIR) in str(item.fspath) or "/dbt/" in str( + item.fspath + ): + item.add_marker(skip_marker) diff --git a/sdk/python/tests/integration/materialization/kubernetes/test_k8s.py b/sdk/python/tests/integration/materialization/kubernetes/test_k8s.py index a944ae3e943..bb8d17da5bd 100644 --- a/sdk/python/tests/integration/materialization/kubernetes/test_k8s.py +++ b/sdk/python/tests/integration/materialization/kubernetes/test_k8s.py @@ -4,14 +4,14 @@ from feast import Entity, Feature, FeatureView, ValueType from tests.data.data_creator import create_basic_driver_dataset -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, RegistryLocation, ) -from tests.integration.feature_repos.repo_configuration import ( +from tests.universal.feature_repos.repo_configuration import ( construct_test_environment, ) -from tests.integration.feature_repos.universal.data_sources.redshift import ( +from tests.universal.feature_repos.universal.data_sources.redshift import ( RedshiftDataSourceCreator, ) from tests.utils.e2e_test_validation import validate_offline_online_store_consistency diff --git a/sdk/python/tests/integration/materialization/test_lambda.py b/sdk/python/tests/integration/materialization/test_lambda.py index f0c1e108694..8e317d7059f 100644 --- a/sdk/python/tests/integration/materialization/test_lambda.py +++ b/sdk/python/tests/integration/materialization/test_lambda.py @@ -7,14 +7,14 @@ from feast.field import Field from feast.types import Float32 from tests.data.data_creator import create_basic_driver_dataset -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, RegistryLocation, ) -from tests.integration.feature_repos.repo_configuration import ( +from tests.universal.feature_repos.repo_configuration import ( construct_test_environment, ) -from tests.integration.feature_repos.universal.data_sources.redshift import ( +from tests.universal.feature_repos.universal.data_sources.redshift import ( RedshiftDataSourceCreator, ) from tests.utils.e2e_test_validation import validate_offline_online_store_consistency diff --git a/sdk/python/tests/integration/materialization/test_snowflake.py b/sdk/python/tests/integration/materialization/test_snowflake.py index a783eac0380..e6f600746d2 100644 --- a/sdk/python/tests/integration/materialization/test_snowflake.py +++ b/sdk/python/tests/integration/materialization/test_snowflake.py @@ -9,13 +9,13 @@ from feast.types import Array, Bool, Bytes, Float64, Int32, Int64, String, UnixTimestamp from feast.utils import _utc_now from tests.data.data_creator import create_basic_driver_dataset -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) -from tests.integration.feature_repos.repo_configuration import ( +from tests.universal.feature_repos.repo_configuration import ( construct_test_environment, ) -from tests.integration.feature_repos.universal.data_sources.snowflake import ( +from tests.universal.feature_repos.universal.data_sources.snowflake import ( SnowflakeDataSourceCreator, ) from tests.utils.e2e_test_validation import validate_offline_online_store_consistency diff --git a/sdk/python/tests/integration/materialization/test_universal_materialization.py b/sdk/python/tests/integration/materialization/test_universal_materialization.py index cf15746bf9e..3bf1eac51c2 100644 --- a/sdk/python/tests/integration/materialization/test_universal_materialization.py +++ b/sdk/python/tests/integration/materialization/test_universal_materialization.py @@ -10,8 +10,6 @@ ) from feast.on_demand_feature_view import on_demand_feature_view from feast.types import Float32, Float64 -from tests.data.data_creator import create_basic_driver_dataset -from tests.utils.e2e_test_validation import validate_offline_online_store_consistency def _create_test_entities(): @@ -217,37 +215,6 @@ def odfv_multi(df: pd.DataFrame) -> pd.DataFrame: assert resp["price_plus_revenue"][0] == 105.0 -@pytest.mark.integration -@pytest.mark.universal_offline_stores -@pytest.mark.parametrize("materialization_pull_latest", [True, False]) -def test_universal_materialization_consistency( - environment, materialization_pull_latest -): - environment.materialization.pull_latest_features = materialization_pull_latest - - fs = environment.feature_store - df = create_basic_driver_dataset() - ds = environment.data_source_creator.create_data_source( - df, - fs.project, - field_mapping={"ts_1": "ts"}, - ) - driver = Entity( - name="driver_id", - join_keys=["driver_id"], - ) - driver_stats_fv = FeatureView( - name="driver_hourly_stats", - entities=[driver], - ttl=timedelta(weeks=52), - schema=[Field(name="value", dtype=Float32)], - source=ds, - ) - fs.apply([driver, driver_stats_fv]) - split_dt = df["ts_1"][4].to_pydatetime() - timedelta(seconds=1) - validate_offline_online_store_consistency(fs, driver_stats_fv, split_dt) - - @pytest.mark.integration def test_odfv_write_methods(environment): """ diff --git a/sdk/python/tests/integration/offline_store/test_dqm_validation.py b/sdk/python/tests/integration/offline_store/test_dqm_validation.py index 710dd6ca2e6..3fce9f07597 100644 --- a/sdk/python/tests/integration/offline_store/test_dqm_validation.py +++ b/sdk/python/tests/integration/offline_store/test_dqm_validation.py @@ -18,10 +18,10 @@ from feast.protos.feast.serving.ServingService_pb2 import FieldStatus from feast.utils import _utc_now, make_tzaware from feast.wait import wait_retry_backoff -from tests.integration.feature_repos.repo_configuration import ( +from tests.universal.feature_repos.repo_configuration import ( construct_universal_feature_views, ) -from tests.integration.feature_repos.universal.entities import ( +from tests.universal.feature_repos.universal.entities import ( customer, driver, location, diff --git a/sdk/python/tests/integration/offline_store/test_feature_logging.py b/sdk/python/tests/integration/offline_store/test_feature_logging.py index 53147d242ef..dc98ba69d2c 100644 --- a/sdk/python/tests/integration/offline_store/test_feature_logging.py +++ b/sdk/python/tests/integration/offline_store/test_feature_logging.py @@ -13,15 +13,15 @@ ) from feast.feature_service import FeatureService from feast.wait import wait_retry_backoff -from tests.integration.feature_repos.repo_configuration import ( +from tests.universal.feature_repos.repo_configuration import ( construct_universal_feature_views, ) -from tests.integration.feature_repos.universal.entities import ( +from tests.universal.feature_repos.universal.entities import ( customer, driver, location, ) -from tests.integration.feature_repos.universal.feature_views import conv_rate_plus_100 +from tests.universal.feature_repos.universal.feature_views import conv_rate_plus_100 from tests.utils.test_log_creator import prepare_logs, to_logs_dataset diff --git a/sdk/python/tests/integration/offline_store/test_non_entity_mode.py b/sdk/python/tests/integration/offline_store/test_non_entity_mode.py new file mode 100644 index 00000000000..f17352fb356 --- /dev/null +++ b/sdk/python/tests/integration/offline_store/test_non_entity_mode.py @@ -0,0 +1,138 @@ +from datetime import timedelta + +import pandas as pd +import pytest + +from feast.utils import _utc_now +from tests.universal.feature_repos.repo_configuration import ( + construct_universal_feature_views, +) +from tests.universal.feature_repos.universal.entities import driver + + +@pytest.mark.integration +@pytest.mark.universal_offline_stores +@pytest.mark.ray_offline_stores_only +def test_non_entity_mode_basic(environment, universal_data_sources): + """Test historical features retrieval without entity_df (non-entity mode). + + This tests the basic functionality where entity_df=None and start_date/end_date + are provided to retrieve all features within the time range. + """ + store = environment.feature_store + + (entities, datasets, data_sources) = universal_data_sources + feature_views = construct_universal_feature_views(data_sources) + + store.apply( + [ + driver(), + feature_views.driver, + ] + ) + + # Use the environment's start and end dates for the query + start_date = environment.start_date + end_date = environment.end_date + + # Non-entity mode: entity_df=None with start_date and end_date + result_df = store.get_historical_features( + entity_df=None, + features=[ + "driver_stats:conv_rate", + "driver_stats:acc_rate", + "driver_stats:avg_daily_trips", + ], + full_feature_names=False, + start_date=start_date, + end_date=end_date, + ).to_df() + + # Verify data was retrieved + assert len(result_df) > 0, "Non-entity mode should return data" + assert "conv_rate" in result_df.columns + assert "acc_rate" in result_df.columns + assert "avg_daily_trips" in result_df.columns + assert "event_timestamp" in result_df.columns + assert "driver_id" in result_df.columns + + # Verify timestamps are within the requested range + result_df["event_timestamp"] = pd.to_datetime( + result_df["event_timestamp"], utc=True + ) + assert (result_df["event_timestamp"] >= start_date).all() + assert (result_df["event_timestamp"] <= end_date).all() + + +@pytest.mark.integration +@pytest.mark.universal_offline_stores +@pytest.mark.ray_offline_stores_only +def test_non_entity_mode_preserves_multiple_timestamps( + environment, universal_data_sources +): + """Test that non-entity mode preserves multiple transactions per entity ID. + + This is a regression test for the fix that ensures distinct (entity_key, event_timestamp) + combinations are preserved, not just distinct entity keys. This is critical for + proper point-in-time joins when an entity has multiple transactions. + """ + store = environment.feature_store + + (entities, datasets, data_sources) = universal_data_sources + feature_views = construct_universal_feature_views(data_sources) + + store.apply( + [ + driver(), + feature_views.driver, + ] + ) + + now = _utc_now() + ts1 = pd.Timestamp(now - timedelta(hours=2)).round("ms") + ts2 = pd.Timestamp(now - timedelta(hours=1)).round("ms") + ts3 = pd.Timestamp(now).round("ms") + + # Write data with multiple timestamps for the same entity (driver_id=9001) + df_to_write = pd.DataFrame.from_dict( + { + "event_timestamp": [ts1, ts2, ts3], + "driver_id": [9001, 9001, 9001], # Same entity, different timestamps + "conv_rate": [0.1, 0.2, 0.3], + "acc_rate": [0.9, 0.8, 0.7], + "avg_daily_trips": [10, 20, 30], + "driver_metadata": [None, None, None], + "driver_config": [None, None, None], + "driver_profile": [None, None, None], + "created": [ts1, ts2, ts3], + }, + ) + + store.write_to_offline_store( + feature_views.driver.name, df_to_write, allow_registry_cache=False + ) + + # Query without entity_df - should get all 3 rows for driver_id=9001 + result_df = store.get_historical_features( + entity_df=None, + features=[ + "driver_stats:conv_rate", + "driver_stats:acc_rate", + ], + full_feature_names=False, + start_date=ts1 - timedelta(minutes=1), + end_date=ts3 + timedelta(minutes=1), + ).to_df() + + # Filter to just our test entity + result_df = result_df[result_df["driver_id"] == 9001] + + # Verify we got all 3 rows with different timestamps (not just 1 row) + assert len(result_df) == 3, ( + f"Expected 3 rows for driver_id=9001 (one per timestamp), got {len(result_df)}" + ) + + # Verify the feature values are correct for each timestamp + result_df = result_df.sort_values("event_timestamp").reset_index(drop=True) + assert list(result_df["conv_rate"]) == [0.1, 0.2, 0.3] + assert list(result_df["acc_rate"]) == [0.9, 0.8, 0.7] diff --git a/sdk/python/tests/integration/offline_store/test_offline_write.py b/sdk/python/tests/integration/offline_store/test_offline_write.py index 21672991b94..df60e40ed56 100644 --- a/sdk/python/tests/integration/offline_store/test_offline_write.py +++ b/sdk/python/tests/integration/offline_store/test_offline_write.py @@ -1,3 +1,4 @@ +import json import random from datetime import timedelta @@ -6,12 +7,12 @@ import pytest from feast import FeatureView, Field -from feast.types import Float32, Int32 +from feast.types import Float32, Int32, Json, Map, String, Struct from feast.utils import _utc_now -from tests.integration.feature_repos.repo_configuration import ( +from tests.universal.feature_repos.repo_configuration import ( construct_universal_feature_views, ) -from tests.integration.feature_repos.universal.entities import driver +from tests.universal.feature_repos.universal.entities import driver @pytest.mark.integration @@ -36,6 +37,18 @@ def test_reorder_columns(environment, universal_data_sources): "event_timestamp": [ts, ts], "acc_rate": [random.random(), random.random()], "driver_id": [1001, 1001], + "driver_metadata": [ + {"vehicle_type": "sedan", "rating": "4.5"}, + {"vehicle_type": "suv", "rating": "3.8"}, + ], + "driver_config": [ + json.dumps({"max_distance_km": 100, "preferred_zones": ["north"]}), + json.dumps({"max_distance_km": 50, "preferred_zones": ["south"]}), + ], + "driver_profile": [ + {"name": "driver_1001", "age": "30"}, + {"name": "driver_1001", "age": "30"}, + ], }, ) @@ -66,7 +79,13 @@ def test_writing_incorrect_schema_fails(environment, universal_data_sources): "created": [ts, ts], }, ) - expected_missing = ["acc_rate", "avg_daily_trips"] + expected_missing = [ + "acc_rate", + "avg_daily_trips", + "driver_config", + "driver_metadata", + "driver_profile", + ] expected_extra = ["incorrect_schema"] with pytest.raises(ValueError, match="missing_expected_columns") as excinfo: @@ -92,6 +111,12 @@ def test_writing_consecutively_to_offline_store(environment, universal_data_sour Field(name="avg_daily_trips", dtype=Int32), Field(name="conv_rate", dtype=Float32), Field(name="acc_rate", dtype=Float32), + Field(name="driver_metadata", dtype=Map), + Field(name="driver_config", dtype=Json), + Field( + name="driver_profile", + dtype=Struct({"name": String, "age": String}), + ), ], source=data_sources.driver, ttl=timedelta( @@ -132,6 +157,18 @@ def test_writing_consecutively_to_offline_store(environment, universal_data_sour "acc_rate": [random.random(), random.random()], "avg_daily_trips": [random.randint(0, 10), random.randint(0, 10)], "created": [ts, ts], + "driver_metadata": [ + {"vehicle_type": "sedan", "rating": "4.5"}, + {"vehicle_type": "suv", "rating": "3.8"}, + ], + "driver_config": [ + json.dumps({"max_distance_km": 100, "preferred_zones": ["north"]}), + json.dumps({"max_distance_km": 50, "preferred_zones": ["south"]}), + ], + "driver_profile": [ + {"name": "driver_1001", "age": "30"}, + {"name": "driver_1001", "age": "35"}, + ], }, ) first_df = first_df.astype({"conv_rate": "float32", "acc_rate": "float32"}) @@ -176,6 +213,18 @@ def test_writing_consecutively_to_offline_store(environment, universal_data_sour "acc_rate": [random.random(), random.random()], "avg_daily_trips": [random.randint(0, 10), random.randint(0, 10)], "created": [ts, ts], + "driver_metadata": [ + {"vehicle_type": "truck", "rating": "4.0"}, + {"vehicle_type": "sedan", "rating": "4.2"}, + ], + "driver_config": [ + json.dumps({"max_distance_km": 150, "preferred_zones": ["east"]}), + json.dumps({"max_distance_km": 200, "preferred_zones": ["west"]}), + ], + "driver_profile": [ + {"name": "driver_1001", "age": "31"}, + {"name": "driver_1001", "age": "36"}, + ], }, ) second_df = second_df.astype({"conv_rate": "float32", "acc_rate": "float32"}) diff --git a/sdk/python/tests/integration/offline_store/test_persist.py b/sdk/python/tests/integration/offline_store/test_persist.py index 8e6f1829174..80b024310b1 100644 --- a/sdk/python/tests/integration/offline_store/test_persist.py +++ b/sdk/python/tests/integration/offline_store/test_persist.py @@ -2,10 +2,10 @@ from feast.errors import SavedDatasetLocationAlreadyExists from feast.saved_dataset import SavedDatasetStorage -from tests.integration.feature_repos.repo_configuration import ( +from tests.universal.feature_repos.repo_configuration import ( construct_universal_feature_views, ) -from tests.integration.feature_repos.universal.entities import ( +from tests.universal.feature_repos.universal.entities import ( customer, driver, location, diff --git a/sdk/python/tests/integration/offline_store/test_push_features_to_offline_store.py b/sdk/python/tests/integration/offline_store/test_push_features_to_offline_store.py index 5e3d72e671b..7d038063ee5 100644 --- a/sdk/python/tests/integration/offline_store/test_push_features_to_offline_store.py +++ b/sdk/python/tests/integration/offline_store/test_push_features_to_offline_store.py @@ -4,10 +4,10 @@ from feast.data_source import PushMode from feast.utils import _utc_now -from tests.integration.feature_repos.repo_configuration import ( +from tests.universal.feature_repos.repo_configuration import ( construct_universal_feature_views, ) -from tests.integration.feature_repos.universal.entities import location +from tests.universal.feature_repos.universal.entities import location @pytest.mark.integration diff --git a/sdk/python/tests/integration/offline_store/test_s3_custom_endpoint.py b/sdk/python/tests/integration/offline_store/test_s3_custom_endpoint.py index 645e0f7331f..45426c63b8d 100644 --- a/sdk/python/tests/integration/offline_store/test_s3_custom_endpoint.py +++ b/sdk/python/tests/integration/offline_store/test_s3_custom_endpoint.py @@ -3,12 +3,12 @@ import pytest from feast.feature_store import FeastObject -from tests.integration.feature_repos.repo_configuration import ( +from tests.universal.feature_repos.repo_configuration import ( IntegrationTestRepoConfig, construct_test_environment, construct_universal_feature_views, ) -from tests.integration.feature_repos.universal.entities import customer, driver +from tests.universal.feature_repos.universal.entities import customer, driver # TODO: Allow integration tests to run using different credentials. @@ -21,7 +21,7 @@ def test_registration_and_retrieval_from_custom_s3_endpoint( universal_data_sources, ): config = IntegrationTestRepoConfig( - offline_store_creator="tests.integration.feature_repos.universal.data_sources.file.S3FileDataSourceCreator" + offline_store_creator="tests.universal.feature_repos.universal.data_sources.file.S3FileDataSourceCreator" ) import os diff --git a/sdk/python/tests/integration/offline_store/test_universal_historical_retrieval.py b/sdk/python/tests/integration/offline_store/test_universal_historical_retrieval.py index a56609e53ce..af0de479f3e 100644 --- a/sdk/python/tests/integration/offline_store/test_universal_historical_retrieval.py +++ b/sdk/python/tests/integration/offline_store/test_universal_historical_retrieval.py @@ -16,19 +16,16 @@ ) from feast.types import Float32, Int32, String from feast.utils import _utc_now -from tests.integration.feature_repos.repo_configuration import ( +from tests.universal.feature_repos.repo_configuration import ( construct_universal_feature_views, table_name_from_data_source, ) -from tests.integration.feature_repos.universal.data_sources.file import ( +from tests.universal.feature_repos.universal.data_sources.file import ( RemoteOfflineOidcAuthStoreDataSourceCreator, RemoteOfflineStoreDataSourceCreator, RemoteOfflineTlsStoreDataSourceCreator, ) -from tests.integration.feature_repos.universal.data_sources.snowflake import ( - SnowflakeDataSourceCreator, -) -from tests.integration.feature_repos.universal.entities import ( +from tests.universal.feature_repos.universal.entities import ( customer, driver, location, @@ -279,7 +276,7 @@ def test_historical_features_with_entities_from_query( raise pytest.skip("Offline source is not sql-based") data_source_creator = environment.data_source_creator - if isinstance(data_source_creator, SnowflakeDataSourceCreator): + if type(data_source_creator).__name__ == "SnowflakeDataSourceCreator": entity_df_query = f""" SELECT "customer_id", "driver_id", "order_id", "origin_id", "destination_id", "event_timestamp" FROM "{orders_table}" @@ -731,3 +728,214 @@ def test_historical_features_field_mapping( actual_df, sort_by=["driver_id"], ) + + +@pytest.mark.integration +@pytest.mark.universal_offline_stores(only=["file"]) +def test_historical_features_non_entity_retrieval(environment): + """Test get_historical_features with entity_df=None using start_date/end_date. + + This exercises the non-entity retrieval path where a synthetic entity_df is + generated internally. Regression test for the bug where start_date was used + instead of end_date for min_event_timestamp in the synthetic entity_df. + """ + store = environment.feature_store + + now = datetime.now().replace(microsecond=0, second=0, minute=0) + two_days_ago = now - timedelta(days=2) + one_day_ago = now - timedelta(days=1) + + driver_stats_df = pd.DataFrame( + data=[ + { + "driver_id": 1001, + "avg_daily_trips": 10, + "event_timestamp": two_days_ago, + "created": two_days_ago, + }, + { + "driver_id": 1001, + "avg_daily_trips": 20, + "event_timestamp": one_day_ago, + "created": one_day_ago, + }, + { + "driver_id": 1001, + "avg_daily_trips": 30, + "event_timestamp": now, + "created": now, + }, + { + "driver_id": 1002, + "avg_daily_trips": 100, + "event_timestamp": two_days_ago, + "created": two_days_ago, + }, + { + "driver_id": 1002, + "avg_daily_trips": 200, + "event_timestamp": one_day_ago, + "created": one_day_ago, + }, + { + "driver_id": 1002, + "avg_daily_trips": 300, + "event_timestamp": now, + "created": now, + }, + ] + ) + + start_date = now - timedelta(days=3) + end_date = now + timedelta(hours=1) + + driver_stats_data_source = environment.data_source_creator.create_data_source( + df=driver_stats_df, + destination_name=f"test_driver_stats_{int(time.time_ns())}_{random.randint(1000, 9999)}", + timestamp_field="event_timestamp", + created_timestamp_column="created", + ) + + driver_entity = Entity(name="driver", join_keys=["driver_id"]) + driver_fv = FeatureView( + name="driver_stats", + entities=[driver_entity], + schema=[Field(name="avg_daily_trips", dtype=Int32)], + source=driver_stats_data_source, + ) + + store.apply([driver_entity, driver_fv]) + + offline_job = store.get_historical_features( + entity_df=None, + features=["driver_stats:avg_daily_trips"], + full_feature_names=False, + start_date=start_date, + end_date=end_date, + ) + + actual_df = offline_job.to_df() + + assert not actual_df.empty, "Result should not be empty" + assert "avg_daily_trips" in actual_df.columns + + actual_driver_ids = set(actual_df["driver_id"].tolist()) + assert 1001 in actual_driver_ids, "driver 1001 should be in results" + assert 1002 in actual_driver_ids, "driver 1002 should be in results" + + # Verify timestamps fall within the requested range. + # Strip tz info to avoid tz-naive vs tz-aware comparison issues. + ts_start = pd.Timestamp(start_date).tz_localize(None) + ts_end = pd.Timestamp(end_date).tz_localize(None) + for ts in actual_df["event_timestamp"]: + ts_val = pd.Timestamp(ts).tz_localize(None) + assert ts_val >= ts_start, f"Timestamp {ts_val} before start_date" + assert ts_val <= ts_end, f"Timestamp {ts_val} after end_date" + + # The latest features must be present -- this is the critical regression check. + # With the old bug (using start_date instead of end_date), the synthetic entity_df + # had wrong max_event_timestamp causing the latest rows to be missed. + actual_trips = set(actual_df["avg_daily_trips"].tolist()) + assert 30 in actual_trips, "Latest trip value 30 for driver 1001 should be present" + assert 300 in actual_trips, ( + "Latest trip value 300 for driver 1002 should be present" + ) + + +@pytest.mark.integration +@pytest.mark.universal_offline_stores +@pytest.mark.parametrize("full_feature_names", [True, False], ids=lambda v: f"full:{v}") +def test_odfv_projection(environment, universal_data_sources, full_feature_names): + """ + Test that requesting a subset of ODFV features only returns those features. + + Regression test for issue #6099: OnDemandFeatureViews should honor output + projection in offline retrieval, matching the behavior of online retrieval. + + Before the fix, offline retrieval would return ALL ODFV output features even + when only a subset was requested, while online retrieval correctly returned + only the requested features. + """ + store = environment.feature_store + + (entities, datasets, data_sources) = universal_data_sources + + feature_views = construct_universal_feature_views(data_sources) + + # Add request data needed for ODFV + entity_df_with_request_data = datasets.entity_df.copy(deep=True) + entity_df_with_request_data["val_to_add"] = [ + i for i in range(len(entity_df_with_request_data)) + ] + + store.apply([driver(), *feature_views.values()]) + + # The conv_rate_plus_100 ODFV has 3 output features: + # - conv_rate_plus_100 + # - conv_rate_plus_val_to_add + # - conv_rate_plus_100_rounded + + # Test 1: Request only ONE ODFV feature + job = store.get_historical_features( + entity_df=entity_df_with_request_data, + features=[ + "conv_rate_plus_100:conv_rate_plus_100", # Request only this one + ], + full_feature_names=full_feature_names, + ) + + actual_df = job.to_df() + + # Determine expected column names based on full_feature_names setting + expected_feature = ( + "conv_rate_plus_100__conv_rate_plus_100" + if full_feature_names + else "conv_rate_plus_100" + ) + unrequested_feature_1 = ( + "conv_rate_plus_100__conv_rate_plus_val_to_add" + if full_feature_names + else "conv_rate_plus_val_to_add" + ) + unrequested_feature_2 = ( + "conv_rate_plus_100__conv_rate_plus_100_rounded" + if full_feature_names + else "conv_rate_plus_100_rounded" + ) + + # Verify the requested feature is present + assert expected_feature in actual_df.columns, ( + f"Requested feature '{expected_feature}' should be in the result" + ) + + # Verify unrequested ODFV features are NOT present (this is the key fix) + assert unrequested_feature_1 not in actual_df.columns, ( + f"Unrequested ODFV feature '{unrequested_feature_1}' should NOT be in the result. " + f"This indicates the bug from issue #6099 still exists." + ) + assert unrequested_feature_2 not in actual_df.columns, ( + f"Unrequested ODFV feature '{unrequested_feature_2}' should NOT be in the result. " + f"This indicates the bug from issue #6099 still exists." + ) + + # Test 2: Request TWO out of THREE ODFV features + job2 = store.get_historical_features( + entity_df=entity_df_with_request_data, + features=[ + "conv_rate_plus_100:conv_rate_plus_100", + "conv_rate_plus_100:conv_rate_plus_val_to_add", + # Deliberately NOT requesting conv_rate_plus_100_rounded + ], + full_feature_names=full_feature_names, + ) + + actual_df2 = job2.to_df() + + # Verify the two requested features are present + assert expected_feature in actual_df2.columns + assert unrequested_feature_1 in actual_df2.columns + + # Verify the unrequested feature is NOT present + assert unrequested_feature_2 not in actual_df2.columns, ( + f"Unrequested ODFV feature '{unrequested_feature_2}' should NOT be in the result" + ) diff --git a/sdk/python/tests/integration/offline_store/test_universal_materialization.py b/sdk/python/tests/integration/offline_store/test_universal_materialization.py new file mode 100644 index 00000000000..bbb41bf5d36 --- /dev/null +++ b/sdk/python/tests/integration/offline_store/test_universal_materialization.py @@ -0,0 +1,39 @@ +from datetime import timedelta + +import pytest + +from feast import Entity, FeatureView, Field +from feast.types import Float32 +from tests.data.data_creator import create_basic_driver_dataset +from tests.utils.e2e_test_validation import validate_offline_online_store_consistency + + +@pytest.mark.integration +@pytest.mark.universal_offline_stores +@pytest.mark.parametrize("materialization_pull_latest", [True, False]) +def test_universal_materialization_consistency( + environment, materialization_pull_latest +): + environment.materialization.pull_latest_features = materialization_pull_latest + + fs = environment.feature_store + df = create_basic_driver_dataset() + ds = environment.data_source_creator.create_data_source( + df, + fs.project, + field_mapping={"ts_1": "ts"}, + ) + driver = Entity( + name="driver_id", + join_keys=["driver_id"], + ) + driver_stats_fv = FeatureView( + name="driver_hourly_stats", + entities=[driver], + ttl=timedelta(weeks=52), + schema=[Field(name="value", dtype=Float32)], + source=ds, + ) + fs.apply([driver, driver_stats_fv]) + split_dt = df["ts_1"][4].to_pydatetime() - timedelta(seconds=1) + validate_offline_online_store_consistency(fs, driver_stats_fv, split_dt) diff --git a/sdk/python/tests/integration/registration/test_universal_types.py b/sdk/python/tests/integration/offline_store/test_universal_types.py similarity index 58% rename from sdk/python/tests/integration/registration/test_universal_types.py rename to sdk/python/tests/integration/offline_store/test_universal_types.py index b464cf2f766..011508dd634 100644 --- a/sdk/python/tests/integration/registration/test_universal_types.py +++ b/sdk/python/tests/integration/offline_store/test_universal_types.py @@ -1,7 +1,6 @@ import logging -from dataclasses import dataclass from datetime import datetime, timedelta -from typing import Any, Dict, List, Optional, Tuple, Union +from typing import Any, Dict, List, Tuple, Union import numpy as np import pandas as pd @@ -10,24 +9,48 @@ from feast.infra.offline_stores.offline_store import RetrievalJob from feast.types import ( - Array, - Bool, - FeastType, Float32, Float64, Int32, Int64, String, - UnixTimestamp, ) from feast.utils import _utc_now from tests.data.data_creator import create_basic_driver_dataset -from tests.integration.feature_repos.universal.entities import driver -from tests.integration.feature_repos.universal.feature_views import driver_feature_view +from tests.universal.feature_repos.universal.entities import driver +from tests.universal.feature_repos.universal.feature_views import driver_feature_view +from tests.utils.type_test_utils import ( + TypeTestConfig, + get_feast_type, + get_type_test_fixtures, + populate_test_configs, +) logger = logging.getLogger(__name__) +OFFLINE_TYPE_TEST_CONFIGS: List[TypeTestConfig] = populate_test_configs() + + +@pytest.fixture( + params=OFFLINE_TYPE_TEST_CONFIGS, + ids=[str(c) for c in OFFLINE_TYPE_TEST_CONFIGS], +) +def offline_types_test_fixtures(request, environment): + config: TypeTestConfig = request.param + if environment.provider == "aws" and config.feature_is_list is True: + pytest.skip("Redshift doesn't support list features") + if ( + environment.data_source_creator.__class__.__name__ + == "ClickhouseDataSourceCreator" + and config.feature_is_list + and not config.has_empty_list + ): + pytest.skip("Clickhouse doesn't support Nullable(Array) type features") + + return get_type_test_fixtures(request, environment) + + @pytest.mark.integration @pytest.mark.universal_offline_stores @pytest.mark.parametrize("entity_type", [Int32, Int64, String]) @@ -48,7 +71,7 @@ def test_entity_inference_types_match(environment, entity_type): data_source=data_source, name=f"fv_entity_type_{entity_type.name.lower()}", infer_entities=True, # Forces entity inference by not including a field for the entity. - dtype=_get_feast_type("int32", False), + dtype=get_feast_type("int32", False), entity_type=entity_type, ) @@ -88,7 +111,7 @@ def test_feature_get_historical_features_types_match( fv = driver_feature_view( data_source=data_source, name="get_historical_features_types_match", - dtype=_get_feast_type(config.feature_dtype, config.feature_is_list), + dtype=get_feast_type(config.feature_dtype, config.feature_is_list), ) fs.apply([fv, entity]) @@ -127,88 +150,6 @@ def test_feature_get_historical_features_types_match( ) -@pytest.mark.integration -@pytest.mark.universal_online_stores(only=["sqlite"]) -def test_feature_get_online_features_types_match( - online_types_test_fixtures, environment -): - config, data_source, fv = online_types_test_fixtures - entity = driver() - fv = driver_feature_view( - data_source=data_source, - name="get_online_features_types_match", - dtype=_get_feast_type(config.feature_dtype, config.feature_is_list), - ) - fs = environment.feature_store - features = [fv.name + ":value"] - fs.apply([fv, entity]) - fs.materialize( - environment.start_date, - environment.end_date - - timedelta(hours=1), # throwing out last record to make sure - # we can successfully infer type even from all empty values - ) - - online_features = fs.get_online_features( - features=features, - entity_rows=[{"driver_id": 1}], - ).to_dict() - - feature_list_dtype_to_expected_online_response_value_type = { - "int32": int, - "int64": int, - "float": float, - "string": str, - "bool": bool, - "datetime": datetime, - } - expected_dtype = feature_list_dtype_to_expected_online_response_value_type[ - config.feature_dtype - ] - - assert len(online_features["value"]) == 1 - - if config.feature_is_list: - for feature in online_features["value"]: - assert isinstance(feature, list), "Feature value should be a list" - assert config.has_empty_list or len(feature) > 0, ( - "List of values should not be empty" - ) - for element in feature: - assert isinstance(element, expected_dtype) - else: - for feature in online_features["value"]: - assert isinstance(feature, expected_dtype) - - -def _get_feast_type(feature_dtype: str, feature_is_list: bool) -> FeastType: - dtype: Optional[FeastType] = None - if feature_is_list is True: - if feature_dtype == "int32": - dtype = Array(Int32) - elif feature_dtype == "int64": - dtype = Array(Int64) - elif feature_dtype == "float": - dtype = Array(Float32) - elif feature_dtype == "bool": - dtype = Array(Bool) - elif feature_dtype == "datetime": - dtype = Array(UnixTimestamp) - else: - if feature_dtype == "int32": - dtype = Int32 - elif feature_dtype == "int64": - dtype = Int64 - elif feature_dtype == "float": - dtype = Float32 - elif feature_dtype == "bool": - dtype = Bool - elif feature_dtype == "datetime": - dtype = UnixTimestamp - assert dtype - return dtype - - def assert_expected_historical_feature_types( feature_dtype: str, historical_features_df: pd.DataFrame ): @@ -293,96 +234,3 @@ def assert_expected_arrow_types( assert arrow_type_checker(pa_type.value_type) else: assert arrow_type_checker(pa_type) - - -def populate_test_configs(offline: bool): - feature_dtypes = [ - "int32", - "int64", - "float", - "bool", - "datetime", - ] - configs: List[TypeTestConfig] = [] - for feature_dtype in feature_dtypes: - for feature_is_list in [True, False]: - for has_empty_list in [True, False]: - # For non list features `has_empty_list` does nothing - if feature_is_list is False and has_empty_list is True: - continue - - configs.append( - TypeTestConfig( - feature_dtype=feature_dtype, - feature_is_list=feature_is_list, - has_empty_list=has_empty_list, - ) - ) - return configs - - -@dataclass(frozen=True, repr=True) -class TypeTestConfig: - feature_dtype: str - feature_is_list: bool - has_empty_list: bool - - -OFFLINE_TYPE_TEST_CONFIGS: List[TypeTestConfig] = populate_test_configs(offline=True) -ONLINE_TYPE_TEST_CONFIGS: List[TypeTestConfig] = populate_test_configs(offline=False) - - -@pytest.fixture( - params=OFFLINE_TYPE_TEST_CONFIGS, - ids=[str(c) for c in OFFLINE_TYPE_TEST_CONFIGS], -) -def offline_types_test_fixtures(request, environment): - config: TypeTestConfig = request.param - if environment.provider == "aws" and config.feature_is_list is True: - pytest.skip("Redshift doesn't support list features") - if ( - environment.data_source_creator.__class__.__name__ - == "ClickhouseDataSourceCreator" - and config.feature_is_list - and not config.has_empty_list - ): - pytest.skip("Clickhouse doesn't support Nullable(Array) type features") - - return get_fixtures(request, environment) - - -@pytest.fixture( - params=ONLINE_TYPE_TEST_CONFIGS, - ids=[str(c) for c in ONLINE_TYPE_TEST_CONFIGS], -) -def online_types_test_fixtures(request, environment): - return get_fixtures(request, environment) - - -def get_fixtures(request, environment): - config: TypeTestConfig = request.param - # Lower case needed because Redshift lower-cases all table names - destination_name = ( - f"feature_type_{config.feature_dtype}{config.feature_is_list}".replace( - ".", "" - ).lower() - ) - config = request.param - df = create_basic_driver_dataset( - Int64, - config.feature_dtype, - config.feature_is_list, - config.has_empty_list, - ) - data_source = environment.data_source_creator.create_data_source( - df, - destination_name=destination_name, - field_mapping={"ts_1": "ts"}, - ) - fv = driver_feature_view( - data_source=data_source, - name=destination_name, - dtype=_get_feast_type(config.feature_dtype, config.feature_is_list), - ) - - return config, data_source, fv diff --git a/sdk/python/tests/integration/online_store/__init__.py b/sdk/python/tests/integration/online_store/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sdk/python/tests/integration/online_store/test_mysql_versioning.py b/sdk/python/tests/integration/online_store/test_mysql_versioning.py new file mode 100644 index 00000000000..d1d132681c5 --- /dev/null +++ b/sdk/python/tests/integration/online_store/test_mysql_versioning.py @@ -0,0 +1,187 @@ +"""Integration tests for MySQL online store feature view versioning. + +Run with: pytest --integration sdk/python/tests/integration/online_store/test_mysql_versioning.py +""" + +import shutil +from datetime import datetime, timedelta, timezone + +import pytest + +from feast import Entity, FeatureView +from feast.field import Field +from feast.infra.online_stores.mysql_online_store.mysql import MySQLOnlineStore +from feast.protos.feast.types.EntityKey_pb2 import EntityKey as EntityKeyProto +from feast.protos.feast.types.Value_pb2 import Value as ValueProto +from feast.repo_config import RegistryConfig, RepoConfig +from feast.types import Float32, Int64 +from feast.value_type import ValueType + + +def _make_feature_view(name="driver_stats", version="latest"): + entity = Entity( + name="driver_id", + join_keys=["driver_id"], + value_type=ValueType.INT64, + ) + return FeatureView( + name=name, + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + ], + version=version, + ) + + +def _make_entity_key(driver_id: int) -> EntityKeyProto: + entity_key = EntityKeyProto() + entity_key.join_keys.append("driver_id") + val = ValueProto() + val.int64_val = driver_id + entity_key.entity_values.append(val) + return entity_key + + +def _write_and_read(store, config, fv, driver_id=1001, trips=42): + entity_key = _make_entity_key(driver_id) + val = ValueProto() + val.int64_val = trips + now = datetime.now(tz=timezone.utc) + store.online_write_batch( + config, fv, [(entity_key, {"trips_today": val}, now, now)], None + ) + return store.online_read(config, fv, [entity_key], ["trips_today"]) + + +@pytest.mark.integration +@pytest.mark.skipif( + not shutil.which("docker"), + reason="Docker not available", +) +class TestMySQLVersioningIntegration: + """Integration tests for MySQL versioning with a real database.""" + + @pytest.fixture(autouse=True) + def setup_mysql(self): + try: + from testcontainers.mysql import MySqlContainer + except ImportError: + pytest.skip("testcontainers[mysql] not installed") + + self.container = MySqlContainer( + "mysql:8.0", + username="root", + password="testpass", # pragma: allowlist secret + dbname="feast", + ).with_exposed_ports(3306) + self.container.start() + self.port = self.container.get_exposed_port(3306) + yield + self.container.stop() + + def _make_config(self, enable_versioning=False): + from feast.infra.online_stores.mysql_online_store.mysql import ( + MySQLOnlineStoreConfig, + ) + + return RepoConfig( + project="test_project", + provider="local", + online_store=MySQLOnlineStoreConfig( + type="mysql", + host="localhost", + port=int(self.port), + user="root", + password="testpass", # pragma: allowlist secret + database="feast", + ), + registry=RegistryConfig( + path="/tmp/test_mysql_registry.pb", + enable_online_feature_view_versioning=enable_versioning, + ), + entity_key_serialization_version=3, + ) + + def test_write_read_without_versioning(self): + config = self._make_config(enable_versioning=False) + store = MySQLOnlineStore() + fv = _make_feature_view() + store.update(config, [], [fv], [], [], False) + + result = _write_and_read(store, config, fv) + assert result[0][1] is not None + assert result[0][1]["trips_today"].int64_val == 42 + + def test_write_read_with_versioning_v1(self): + config = self._make_config(enable_versioning=True) + store = MySQLOnlineStore() + fv = _make_feature_view() + fv.current_version_number = 1 + store.update(config, [], [fv], [], [], False) + + result = _write_and_read(store, config, fv) + assert result[0][1] is not None + assert result[0][1]["trips_today"].int64_val == 42 + + def test_version_isolation(self): + """Data written to v1 is not visible from v2.""" + config = self._make_config(enable_versioning=True) + store = MySQLOnlineStore() + + fv_v1 = _make_feature_view() + fv_v1.current_version_number = 1 + store.update(config, [], [fv_v1], [], [], False) + _write_and_read(store, config, fv_v1, driver_id=1001, trips=10) + + fv_v2 = _make_feature_view() + fv_v2.current_version_number = 2 + store.update(config, [], [fv_v2], [], [], False) + + entity_key = _make_entity_key(1001) + result = store.online_read(config, fv_v2, [entity_key], ["trips_today"]) + assert result[0] == (None, None) + + result = store.online_read(config, fv_v1, [entity_key], ["trips_today"]) + assert result[0][1] is not None + assert result[0][1]["trips_today"].int64_val == 10 + + def test_projection_version_tag_routes_to_correct_table(self): + """projection.version_tag routes reads to the correct versioned table.""" + config = self._make_config(enable_versioning=True) + store = MySQLOnlineStore() + + fv_v1 = _make_feature_view() + fv_v1.current_version_number = 1 + store.update(config, [], [fv_v1], [], [], False) + _write_and_read(store, config, fv_v1, driver_id=1001, trips=100) + + fv_v2 = _make_feature_view() + fv_v2.current_version_number = 2 + store.update(config, [], [fv_v2], [], [], False) + _write_and_read(store, config, fv_v2, driver_id=1001, trips=200) + + fv_read = _make_feature_view() + fv_read.projection.version_tag = 1 + entity_key = _make_entity_key(1001) + result = store.online_read(config, fv_read, [entity_key], ["trips_today"]) + assert result[0][1]["trips_today"].int64_val == 100 + + fv_read2 = _make_feature_view() + fv_read2.projection.version_tag = 2 + result = store.online_read(config, fv_read2, [entity_key], ["trips_today"]) + assert result[0][1]["trips_today"].int64_val == 200 + + def test_teardown_versioned_table(self): + config = self._make_config(enable_versioning=True) + store = MySQLOnlineStore() + + fv = _make_feature_view() + fv.current_version_number = 1 + store.update(config, [], [fv], [], [], False) + _write_and_read(store, config, fv) + + store.teardown(config, [fv], []) diff --git a/sdk/python/tests/integration/online_store/test_postgres_versioning.py b/sdk/python/tests/integration/online_store/test_postgres_versioning.py new file mode 100644 index 00000000000..9816c2a43c2 --- /dev/null +++ b/sdk/python/tests/integration/online_store/test_postgres_versioning.py @@ -0,0 +1,205 @@ +"""Integration tests for PostgreSQL online store feature view versioning. + +Run with: pytest --integration sdk/python/tests/integration/online_store/test_postgres_versioning.py +""" + +import shutil +from datetime import datetime, timedelta, timezone + +import pytest + +from feast import Entity, FeatureView +from feast.field import Field +from feast.infra.online_stores.postgres_online_store.postgres import ( + PostgreSQLOnlineStore, +) +from feast.protos.feast.types.EntityKey_pb2 import EntityKey as EntityKeyProto +from feast.protos.feast.types.Value_pb2 import Value as ValueProto +from feast.repo_config import RegistryConfig, RepoConfig +from feast.types import Float32, Int64 +from feast.value_type import ValueType + + +def _make_feature_view(name="driver_stats", version="latest"): + entity = Entity( + name="driver_id", + join_keys=["driver_id"], + value_type=ValueType.INT64, + ) + return FeatureView( + name=name, + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + ], + version=version, + ) + + +def _make_entity_key(driver_id: int) -> EntityKeyProto: + entity_key = EntityKeyProto() + entity_key.join_keys.append("driver_id") + val = ValueProto() + val.int64_val = driver_id + entity_key.entity_values.append(val) + return entity_key + + +def _write_and_read(store, config, fv, driver_id=1001, trips=42): + entity_key = _make_entity_key(driver_id) + val = ValueProto() + val.int64_val = trips + now = datetime.now(tz=timezone.utc) + store.online_write_batch( + config, fv, [(entity_key, {"trips_today": val}, now, now)], None + ) + return store.online_read(config, fv, [entity_key], ["trips_today"]) + + +@pytest.mark.integration +@pytest.mark.skipif( + not shutil.which("docker"), + reason="Docker not available", +) +class TestPostgresVersioningIntegration: + """Integration tests for PostgreSQL versioning with a real database.""" + + @pytest.fixture(autouse=True) + def setup_postgres(self): + try: + from testcontainers.postgres import PostgresContainer + except ImportError: + pytest.skip("testcontainers[postgres] not installed") + + self.container = PostgresContainer( + "postgres:16", + username="root", + password="testpass", # pragma: allowlist secret + dbname="test", + ).with_exposed_ports(5432) + self.container.start() + self.port = self.container.get_exposed_port(5432) + yield + self.container.stop() + + def _make_config(self, enable_versioning=False): + from feast.infra.online_stores.postgres_online_store.postgres import ( + PostgreSQLOnlineStoreConfig, + ) + + return RepoConfig( + project="test_project", + provider="local", + online_store=PostgreSQLOnlineStoreConfig( + type="postgres", + host="localhost", + port=int(self.port), + user="root", + password="testpass", # pragma: allowlist secret + database="test", + sslmode="disable", + ), + registry=RegistryConfig( + path="/tmp/test_pg_registry.pb", + enable_online_feature_view_versioning=enable_versioning, + ), + entity_key_serialization_version=3, + ) + + def test_write_read_without_versioning(self): + config = self._make_config(enable_versioning=False) + store = PostgreSQLOnlineStore() + fv = _make_feature_view() + store.update(config, [], [fv], [], [], False) + + result = _write_and_read(store, config, fv) + assert result[0][1] is not None + assert result[0][1]["trips_today"].int64_val == 42 + + def test_write_read_with_versioning_v1(self): + config = self._make_config(enable_versioning=True) + store = PostgreSQLOnlineStore() + fv = _make_feature_view() + fv.current_version_number = 1 + store.update(config, [], [fv], [], [], False) + + result = _write_and_read(store, config, fv) + assert result[0][1] is not None + assert result[0][1]["trips_today"].int64_val == 42 + + def test_version_isolation(self): + """Data written to v1 is not visible from v2.""" + config = self._make_config(enable_versioning=True) + store = PostgreSQLOnlineStore() + + fv_v1 = _make_feature_view() + fv_v1.current_version_number = 1 + store.update(config, [], [fv_v1], [], [], False) + _write_and_read(store, config, fv_v1, driver_id=1001, trips=10) + + fv_v2 = _make_feature_view() + fv_v2.current_version_number = 2 + store.update(config, [], [fv_v2], [], [], False) + + entity_key = _make_entity_key(1001) + result = store.online_read(config, fv_v2, [entity_key], ["trips_today"]) + assert result[0] == (None, None) + + result = store.online_read(config, fv_v1, [entity_key], ["trips_today"]) + assert result[0][1] is not None + assert result[0][1]["trips_today"].int64_val == 10 + + def test_projection_version_tag_routes_to_correct_table(self): + """projection.version_tag routes reads to the correct versioned table.""" + config = self._make_config(enable_versioning=True) + store = PostgreSQLOnlineStore() + + fv_v1 = _make_feature_view() + fv_v1.current_version_number = 1 + store.update(config, [], [fv_v1], [], [], False) + _write_and_read(store, config, fv_v1, driver_id=1001, trips=100) + + fv_v2 = _make_feature_view() + fv_v2.current_version_number = 2 + store.update(config, [], [fv_v2], [], [], False) + _write_and_read(store, config, fv_v2, driver_id=1001, trips=200) + + fv_read = _make_feature_view() + fv_read.projection.version_tag = 1 + entity_key = _make_entity_key(1001) + result = store.online_read(config, fv_read, [entity_key], ["trips_today"]) + assert result[0][1]["trips_today"].int64_val == 100 + + fv_read2 = _make_feature_view() + fv_read2.projection.version_tag = 2 + result = store.online_read(config, fv_read2, [entity_key], ["trips_today"]) + assert result[0][1]["trips_today"].int64_val == 200 + + def test_teardown_versioned_table(self): + """teardown() drops the versioned table without error.""" + config = self._make_config(enable_versioning=True) + store = PostgreSQLOnlineStore() + + fv = _make_feature_view() + fv.current_version_number = 1 + store.update(config, [], [fv], [], [], False) + _write_and_read(store, config, fv) + + # Should not raise + store.teardown(config, [fv], []) + + def test_update_deletes_versioned_table(self): + """update() with tables_to_delete correctly drops versioned tables.""" + config = self._make_config(enable_versioning=True) + store = PostgreSQLOnlineStore() + + fv = _make_feature_view() + fv.current_version_number = 1 + store.update(config, [], [fv], [], [], False) + _write_and_read(store, config, fv, driver_id=1001, trips=50) + + # Delete the versioned table + store.update(config, [fv], [], [], [], False) diff --git a/sdk/python/tests/integration/online_store/test_push_features_to_online_store.py b/sdk/python/tests/integration/online_store/test_push_features_to_online_store.py index 8986e21c57d..536864ed97e 100644 --- a/sdk/python/tests/integration/online_store/test_push_features_to_online_store.py +++ b/sdk/python/tests/integration/online_store/test_push_features_to_online_store.py @@ -2,10 +2,10 @@ import pytest from feast.utils import _utc_now -from tests.integration.feature_repos.repo_configuration import ( +from tests.universal.feature_repos.repo_configuration import ( construct_universal_feature_views, ) -from tests.integration.feature_repos.universal.entities import location +from tests.universal.feature_repos.universal.entities import location @pytest.fixture @@ -47,7 +47,7 @@ def test_push_features_and_read(store): @pytest.mark.integration -@pytest.mark.universal_online_stores(only=["dynamodb"]) +@pytest.mark.universal_online_stores(only=["dynamodb", "mongodb"]) async def test_push_features_and_read_async(store): await store.push_async("location_stats_push_source", _ingest_df()) diff --git a/sdk/python/tests/integration/online_store/test_remote_online_store.py b/sdk/python/tests/integration/online_store/test_remote_online_store.py index 80166abf431..3ee3d161d14 100644 --- a/sdk/python/tests/integration/online_store/test_remote_online_store.py +++ b/sdk/python/tests/integration/online_store/test_remote_online_store.py @@ -1,3 +1,4 @@ +import json import logging import os import tempfile @@ -383,6 +384,18 @@ def test_remote_online_store_read_write(auth_config, tls_mode): "avg_daily_trips": [50, 45], "event_timestamp": [pd.Timestamp(_utc_now()).round("ms")] * 2, "created": [pd.Timestamp(_utc_now()).round("ms")] * 2, + "driver_metadata": [ + {"vehicle_type": "sedan", "rating": "4.5"}, + {"vehicle_type": "suv", "rating": "3.8"}, + ], + "driver_config": [ + json.dumps({"max_distance_km": 100, "preferred_zones": ["north"]}), + json.dumps({"max_distance_km": 50, "preferred_zones": ["south"]}), + ], + "driver_profile": [ + {"name": "driver_1000", "age": "30"}, + {"name": "driver_1001", "age": "35"}, + ], } ) diff --git a/sdk/python/tests/integration/materialization/test_universal_e2e.py b/sdk/python/tests/integration/online_store/test_universal_e2e.py similarity index 84% rename from sdk/python/tests/integration/materialization/test_universal_e2e.py rename to sdk/python/tests/integration/online_store/test_universal_e2e.py index 202ae859aed..cfacbca59af 100644 --- a/sdk/python/tests/integration/materialization/test_universal_e2e.py +++ b/sdk/python/tests/integration/online_store/test_universal_e2e.py @@ -2,8 +2,8 @@ import pytest -from tests.integration.feature_repos.universal.entities import driver -from tests.integration.feature_repos.universal.feature_views import driver_feature_view +from tests.universal.feature_repos.universal.entities import driver +from tests.universal.feature_repos.universal.feature_views import driver_feature_view from tests.utils.e2e_test_validation import validate_offline_online_store_consistency diff --git a/sdk/python/tests/integration/online_store/test_universal_online.py b/sdk/python/tests/integration/online_store/test_universal_online.py index 51296f31607..0c27585139e 100644 --- a/sdk/python/tests/integration/online_store/test_universal_online.py +++ b/sdk/python/tests/integration/online_store/test_universal_online.py @@ -32,12 +32,12 @@ ) from feast.utils import _utc_now from feast.wait import wait_retry_backoff -from tests.integration.feature_repos.repo_configuration import ( +from tests.universal.feature_repos.repo_configuration import ( Environment, construct_universal_feature_views, ) -from tests.integration.feature_repos.universal.entities import driver, item -from tests.integration.feature_repos.universal.feature_views import ( +from tests.universal.feature_repos.universal.entities import driver, item +from tests.universal.feature_repos.universal.feature_views import ( TAGS, create_driver_hourly_stats_feature_view, create_item_embeddings_feature_view, @@ -258,6 +258,9 @@ def test_write_to_online_store(environment, universal_data_sources): "conv_rate": [0.85], "acc_rate": [0.91], "avg_daily_trips": [14], + "driver_metadata": [None], + "driver_config": [None], + "driver_profile": [None], "event_timestamp": [pd.Timestamp(_utc_now()).round("ms")], "created": [pd.Timestamp(_utc_now()).round("ms")], } @@ -435,6 +438,9 @@ def setup_feature_store_universal_feature_views( "conv_rate": [0.5, 0.3], "acc_rate": [0.6, 0.4], "avg_daily_trips": [4, 5], + "driver_metadata": [None, None], + "driver_config": [None, None], + "driver_profile": [None, None], "event_timestamp": [ pd.to_datetime(1646263500, utc=True, unit="s"), pd.to_datetime(1646263600, utc=True, unit="s"), @@ -517,7 +523,7 @@ async def _do_async_retrieval_test(environment, universal_data_sources): @pytest.mark.asyncio @pytest.mark.integration -@pytest.mark.universal_online_stores(only=["redis", "postgres"]) +@pytest.mark.universal_online_stores(only=["redis", "postgres", "mongodb"]) async def test_async_online_retrieval_with_event_timestamps( environment, universal_data_sources ): @@ -1153,6 +1159,12 @@ def test_retrieve_online_documents_v2(environment, fake_document_data): assert len(vector_results["text_field"]) == 5 assert len(vector_results["category"]) == 5 + assert all(isinstance(v, list) for v in vector_results["embedding"]) + assert all(isinstance(v, float) for v in vector_results["distance"]) + assert all(isinstance(v, str) for v in vector_results["text_field"]) + assert all(isinstance(v, str) for v in vector_results["category"]) + assert all(isinstance(v, int) for v in vector_results["item_id"]) + # Test 2: Vector similarity search with Cosine distance vector_results = fs.retrieve_online_documents_v2( features=[ @@ -1171,6 +1183,12 @@ def test_retrieve_online_documents_v2(environment, fake_document_data): assert len(vector_results["text_field"]) == 5 assert len(vector_results["category"]) == 5 + assert all(isinstance(v, list) for v in vector_results["embedding"]) + assert all(isinstance(v, float) for v in vector_results["distance"]) + assert all(isinstance(v, str) for v in vector_results["text_field"]) + assert all(isinstance(v, str) for v in vector_results["category"]) + assert all(isinstance(v, int) for v in vector_results["item_id"]) + # Test 3: Full text search text_results = fs.retrieve_online_documents_v2( features=[ @@ -1189,6 +1207,11 @@ def test_retrieve_online_documents_v2(environment, fake_document_data): assert len(text_results["category"]) == 5 assert len(text_results["item_id"]) == 5 + assert all(isinstance(v, str) for v in text_results["text_field"]) + assert all(isinstance(v, float) for v in text_results["text_rank"]) + assert all(isinstance(v, str) for v in text_results["category"]) + assert all(isinstance(v, int) for v in text_results["item_id"]) + # Verify text rank values are between 0 and 1 assert all(0 <= rank <= 1 for rank in text_results["text_rank"]) @@ -1218,22 +1241,12 @@ def test_retrieve_online_documents_v2(environment, fake_document_data): assert len(hybrid_results["category"]) == 5 assert len(hybrid_results["item_id"]) == 5 - # Test 5: Hybrid search with different text query - hybrid_results = fs.retrieve_online_documents_v2( - features=[ - "item_embeddings:embedding", - "item_embeddings:text_field", - "item_embeddings:category", - "item_embeddings:item_id", - ], - query=query_embedding, - query_string="Category-1", - top_k=5, - distance_metric="L2", - ).to_dict() - - # Verify results contain only documents from Category-1 - assert all(cat == "Category-1" for cat in hybrid_results["category"]) + assert all(isinstance(v, list) for v in hybrid_results["embedding"]) + assert all(isinstance(v, float) for v in hybrid_results["distance"]) + assert all(isinstance(v, str) for v in hybrid_results["text_field"]) + assert all(isinstance(v, float) for v in hybrid_results["text_rank"]) + assert all(isinstance(v, str) for v in hybrid_results["category"]) + assert all(isinstance(v, int) for v in hybrid_results["item_id"]) # Test 6: Full text search with no matches no_match_results = fs.retrieve_online_documents_v2( diff --git a/sdk/python/tests/integration/online_store/test_universal_online_types.py b/sdk/python/tests/integration/online_store/test_universal_online_types.py new file mode 100644 index 00000000000..7340d00f274 --- /dev/null +++ b/sdk/python/tests/integration/online_store/test_universal_online_types.py @@ -0,0 +1,77 @@ +from datetime import datetime, timedelta +from typing import List + +import pytest + +from tests.universal.feature_repos.universal.entities import driver +from tests.universal.feature_repos.universal.feature_views import driver_feature_view +from tests.utils.type_test_utils import ( + TypeTestConfig, + get_feast_type, + get_type_test_fixtures, + populate_test_configs, +) + +ONLINE_TYPE_TEST_CONFIGS: List[TypeTestConfig] = populate_test_configs() + + +@pytest.fixture( + params=ONLINE_TYPE_TEST_CONFIGS, + ids=[str(c) for c in ONLINE_TYPE_TEST_CONFIGS], +) +def online_types_test_fixtures(request, environment): + return get_type_test_fixtures(request, environment) + + +@pytest.mark.integration +@pytest.mark.universal_online_stores(only=["sqlite"]) +def test_feature_get_online_features_types_match( + online_types_test_fixtures, environment +): + config, data_source, fv = online_types_test_fixtures + entity = driver() + fv = driver_feature_view( + data_source=data_source, + name="get_online_features_types_match", + dtype=get_feast_type(config.feature_dtype, config.feature_is_list), + ) + fs = environment.feature_store + features = [fv.name + ":value"] + fs.apply([fv, entity]) + fs.materialize( + environment.start_date, + environment.end_date + - timedelta(hours=1), # throwing out last record to make sure + # we can successfully infer type even from all empty values + ) + + online_features = fs.get_online_features( + features=features, + entity_rows=[{"driver_id": 1}], + ).to_dict() + + feature_list_dtype_to_expected_online_response_value_type = { + "int32": int, + "int64": int, + "float": float, + "string": str, + "bool": bool, + "datetime": datetime, + } + expected_dtype = feature_list_dtype_to_expected_online_response_value_type[ + config.feature_dtype + ] + + assert len(online_features["value"]) == 1 + + if config.feature_is_list: + for feature in online_features["value"]: + assert isinstance(feature, list), "Feature value should be a list" + assert config.has_empty_list or len(feature) > 0, ( + "List of values should not be empty" + ) + for element in feature: + assert isinstance(element, expected_dtype) + else: + for feature in online_features["value"]: + assert isinstance(feature, expected_dtype) diff --git a/sdk/python/tests/integration/registration/rest_api/conftest.py b/sdk/python/tests/integration/registration/rest_api/conftest.py deleted file mode 100644 index 36c358a9aa6..00000000000 --- a/sdk/python/tests/integration/registration/rest_api/conftest.py +++ /dev/null @@ -1,150 +0,0 @@ -import os -from pathlib import Path - -import pytest -import requests -from kubernetes import client, config - -from tests.integration.registration.rest_api.support import ( - applyFeastProject, - create_feast_project, - create_namespace, - create_route, - delete_namespace, - deploy_and_validate_pod, - execPodCommand, - get_pod_name_by_prefix, - run_kubectl_apply_with_sed, - run_kubectl_command, - validate_feature_store_cr_status, -) - - -class FeastRestClient: - def __init__(self, base_url): - self.base_url = base_url.rstrip("/") - self.api_prefix = "/api/v1" - - def _build_url(self, endpoint): - if not endpoint.startswith("/"): - endpoint = "/" + endpoint - return f"{self.base_url}{self.api_prefix}{endpoint}" - - def get(self, endpoint, params=None): - params = params or {} - params.setdefault("allow_cache", "false") - url = self._build_url(endpoint) - return requests.get(url, params=params, verify=False) - - -@pytest.fixture(scope="session") -def feast_rest_client(): - # Load kubeconfig and initialize Kubernetes client - config.load_kube_config() - api_instance = client.CoreV1Api() - - # Get the directory containing this conftest.py file - test_dir = Path(__file__).parent - resource_dir = test_dir / "resource" - - # Constants and environment values - namespace = "test-ns-feast-rest" - credit_scoring = "credit-scoring" - driver_ranking = "driver-ranking" - service_name = "feast-test-s3-registry-rest" - run_on_openshift = os.getenv("RUN_ON_OPENSHIFT_CI", "false").lower() == "true" - - # Create test namespace - create_namespace(api_instance, namespace) - - try: - if not run_on_openshift: - # Deploy dependencies - deploy_and_validate_pod( - namespace, str(resource_dir / "redis.yaml"), "app=redis" - ) - deploy_and_validate_pod( - namespace, str(resource_dir / "postgres.yaml"), "app=postgres" - ) - - # Create and validate FeatureStore CRs - create_feast_project( - str(resource_dir / "feast_config_credit_scoring.yaml"), - namespace, - credit_scoring, - ) - validate_feature_store_cr_status(namespace, credit_scoring) - - create_feast_project( - str(resource_dir / "feast_config_driver_ranking.yaml"), - namespace, - driver_ranking, - ) - validate_feature_store_cr_status(namespace, driver_ranking) - - # Deploy ingress and get route URL - run_kubectl_command( - [ - "apply", - "-f", - str(resource_dir / "feast-registry-nginx.yaml"), - "-n", - namespace, - ] - ) - ingress_host = run_kubectl_command( - [ - "get", - "ingress", - "feast-registry-ingress", - "-n", - namespace, - "-o", - "jsonpath={.spec.rules[0].host}", - ] - ) - route_url = f"http://{ingress_host}" - - # Apply feast projects - - applyFeastProject(namespace, credit_scoring) - - applyFeastProject(namespace, driver_ranking) - - # Create Saved Datasets and Permissions - pod_name = get_pod_name_by_prefix(namespace, credit_scoring) - - # Apply datasets - execPodCommand( - namespace, pod_name, ["python", "create_ui_visible_datasets.py"] - ) - - # Apply permissions - execPodCommand(namespace, pod_name, ["python", "permissions_apply.py"]) - - else: - # OpenShift cluster setup using S3-based registry - aws_access_key = os.getenv("AWS_ACCESS_KEY") - aws_secret_key = os.getenv("AWS_SECRET_KEY") - aws_bucket = os.getenv("AWS_BUCKET_NAME") - registry_path = os.getenv("AWS_REGISTRY_FILE_PATH") - - run_kubectl_apply_with_sed( - aws_access_key, - aws_secret_key, - aws_bucket, - registry_path, - str(resource_dir / "feast_config_rhoai.yaml"), - namespace, - ) - validate_feature_store_cr_status(namespace, "test-s3") - route_url = create_route(namespace, credit_scoring, service_name) - if not route_url: - raise RuntimeError("Route URL could not be fetched.") - - print(f"\n Connected to Feast REST at: {route_url}") - yield FeastRestClient(route_url) - - finally: - print(f"\n Deleting namespace: {namespace}") - delete_namespace(api_instance, namespace) diff --git a/sdk/python/tests/integration/registration/test_feature_store.py b/sdk/python/tests/integration/registration/test_feature_store.py index b59af900190..93334fbda19 100644 --- a/sdk/python/tests/integration/registration/test_feature_store.py +++ b/sdk/python/tests/integration/registration/test_feature_store.py @@ -14,15 +14,23 @@ from datetime import timedelta from tempfile import mkstemp +import pandas as pd import pytest from pytest_lazyfixture import lazy_fixture +from feast import FileSource +from feast.data_format import AvroFormat +from feast.data_source import KafkaSource from feast.entity import Entity -from feast.feature_store import FeatureStore +from feast.errors import ConflictingFeatureViewNames +from feast.feature_store import FeatureStore, _validate_feature_views from feast.feature_view import FeatureView +from feast.field import Field from feast.infra.online_stores.sqlite import SqliteOnlineStoreConfig +from feast.on_demand_feature_view import on_demand_feature_view from feast.repo_config import RepoConfig -from feast.types import Float64, Int64, String +from feast.stream_feature_view import StreamFeatureView +from feast.types import Float32, Float64, Int64, String from tests.utils.data_source_test_creator import prep_file_source @@ -75,3 +83,146 @@ def feature_store_with_local_registry(): entity_key_serialization_version=3, ) ) + + +@pytest.mark.integration +def test_validate_feature_views_cross_type_conflict(): + """ + Test that _validate_feature_views() catches cross-type name conflicts. + + This is a unit test for the validation that happens during feast plan/apply. + The validation must catch conflicts across FeatureView, StreamFeatureView, + and OnDemandFeatureView to prevent silent data correctness bugs in + get_online_features (which uses fixed-order lookup). + + See: https://github.com/feast-dev/feast/issues/5995 + """ + # Create a simple entity + entity = Entity(name="driver_entity", join_keys=["test_key"]) + + # Create a regular FeatureView + file_source = FileSource(name="my_file_source", path="test.parquet") + feature_view = FeatureView( + name="my_feature_view", + entities=[entity], + schema=[Field(name="feature1", dtype=Float32)], + source=file_source, + ) + + # Create a StreamFeatureView with the SAME name + stream_source = KafkaSource( + name="kafka", + timestamp_field="event_timestamp", + kafka_bootstrap_servers="", + message_format=AvroFormat(""), + topic="topic", + batch_source=file_source, + watermark_delay_threshold=timedelta(days=1), + ) + stream_feature_view = StreamFeatureView( + name="my_feature_view", # Same name as FeatureView! + entities=[entity], + ttl=timedelta(days=30), + schema=[Field(name="feature1", dtype=Float32)], + source=stream_source, + ) + + # Validate should raise ConflictingFeatureViewNames + with pytest.raises(ConflictingFeatureViewNames) as exc_info: + _validate_feature_views([feature_view, stream_feature_view]) + + # Verify error message contains type information + error_message = str(exc_info.value) + assert "my_feature_view" in error_message + assert "FeatureView" in error_message + assert "StreamFeatureView" in error_message + + +def test_validate_feature_views_same_type_conflict(): + """ + Test that _validate_feature_views() also catches same-type name conflicts + with a proper error message indicating duplicate FeatureViews. + """ + # Create a simple entity + entity = Entity(name="driver_entity", join_keys=["test_key"]) + + # Create two FeatureViews with the same name + file_source = FileSource(name="my_file_source", path="test.parquet") + fv1 = FeatureView( + name="duplicate_fv", + entities=[entity], + schema=[Field(name="feature1", dtype=Float32)], + source=file_source, + ) + fv2 = FeatureView( + name="duplicate_fv", # Same name! + entities=[entity], + schema=[Field(name="feature2", dtype=Float32)], + source=file_source, + ) + + # Validate should raise ConflictingFeatureViewNames + with pytest.raises(ConflictingFeatureViewNames) as exc_info: + _validate_feature_views([fv1, fv2]) + + # Verify error message indicates same-type duplicate + error_message = str(exc_info.value) + assert "duplicate_fv" in error_message + assert "Multiple FeatureViews" in error_message + assert "case-insensitively unique" in error_message + + +def test_validate_feature_views_case_insensitive(): + """ + Test that _validate_feature_views() catches case-insensitive conflicts. + """ + entity = Entity(name="driver_entity", join_keys=["test_key"]) + file_source = FileSource(name="my_file_source", path="test.parquet") + + fv1 = FeatureView( + name="MyFeatureView", + entities=[entity], + schema=[Field(name="feature1", dtype=Float32)], + source=file_source, + ) + fv2 = FeatureView( + name="myfeatureview", # Same name, different case! + entities=[entity], + schema=[Field(name="feature2", dtype=Float32)], + source=file_source, + ) + + # Validate should raise ConflictingFeatureViewNames (case-insensitive) + with pytest.raises(ConflictingFeatureViewNames): + _validate_feature_views([fv1, fv2]) + + +def test_validate_feature_views_odfv_conflict(): + """ + Test that _validate_feature_views() catches OnDemandFeatureView name conflicts. + """ + entity = Entity(name="driver_entity", join_keys=["test_key"]) + file_source = FileSource(name="my_file_source", path="test.parquet") + + fv = FeatureView( + name="shared_name", + entities=[entity], + schema=[Field(name="feature1", dtype=Float32)], + source=file_source, + ) + + @on_demand_feature_view( + sources=[fv], + schema=[Field(name="output", dtype=Float32)], + ) + def shared_name(inputs: pd.DataFrame) -> pd.DataFrame: + return pd.DataFrame({"output": inputs["feature1"] * 2}) + + # Validate should raise ConflictingFeatureViewNames + with pytest.raises(ConflictingFeatureViewNames) as exc_info: + _validate_feature_views([fv, shared_name]) + + error_message = str(exc_info.value) + assert "shared_name" in error_message + assert "FeatureView" in error_message + assert "OnDemandFeatureView" in error_message diff --git a/sdk/python/tests/integration/registration/test_universal_odfv_feature_inference.py b/sdk/python/tests/integration/registration/test_universal_odfv_feature_inference.py index 151f629289f..e1b936a3042 100644 --- a/sdk/python/tests/integration/registration/test_universal_odfv_feature_inference.py +++ b/sdk/python/tests/integration/registration/test_universal_odfv_feature_inference.py @@ -6,8 +6,8 @@ from feast.infra.offline_stores.file_source import FileSource from feast.types import Float64 from feast.utils import _utc_now -from tests.integration.feature_repos.universal.entities import customer, driver, item -from tests.integration.feature_repos.universal.feature_views import ( +from tests.universal.feature_repos.universal.entities import customer, driver, item +from tests.universal.feature_repos.universal.feature_views import ( conv_rate_plus_100_feature_view, create_conv_rate_request_source, create_driver_hourly_stats_batch_feature_view, @@ -18,7 +18,6 @@ @pytest.mark.integration -@pytest.mark.universal_offline_stores @pytest.mark.parametrize("infer_features", [True, False], ids=lambda v: str(v)) def test_infer_odfv_features(environment, universal_data_sources, infer_features): store = environment.feature_store diff --git a/sdk/python/tests/integration/registration/test_universal_registry.py b/sdk/python/tests/integration/registration/test_universal_registry.py index 29b31ef1b75..fb09395d789 100644 --- a/sdk/python/tests/integration/registration/test_universal_registry.py +++ b/sdk/python/tests/integration/registration/test_universal_registry.py @@ -35,7 +35,7 @@ from feast.data_format import AvroFormat, ParquetFormat from feast.data_source import KafkaSource from feast.entity import Entity -from feast.errors import FeatureViewNotFoundException +from feast.errors import ConflictingFeatureViewNames, FeatureViewNotFoundException from feast.feature_view import FeatureView from feast.field import Field from feast.infra.infra_object import Infra @@ -56,7 +56,7 @@ from feast.types import Array, Bytes, Float32, Int32, Int64, String from feast.utils import _utc_now from feast.value_type import ValueType -from tests.integration.feature_repos.universal.entities import driver +from tests.universal.feature_repos.universal.entities import driver @pytest.fixture @@ -386,33 +386,41 @@ def mock_remote_registry(): yield registry -if os.getenv("FEAST_IS_LOCAL_TEST", "False") == "False": - all_fixtures = [lazy_fixture("s3_registry"), lazy_fixture("gcs_registry")] +all_fixtures = [ + lazy_fixture("local_registry"), + pytest.param( + lazy_fixture("pg_registry"), + marks=pytest.mark.xdist_group(name="pg_registry"), + ), + pytest.param( + lazy_fixture("mysql_registry"), + marks=pytest.mark.xdist_group(name="mysql_registry"), + ), + lazy_fixture("sqlite_registry"), + pytest.param( + lazy_fixture("mock_remote_registry"), + marks=pytest.mark.rbac_remote_integration_test, + ), +] + +if os.getenv("FEAST_IS_LOCAL_TEST", "False") != "True": + all_fixtures.extend( + [ + lazy_fixture("s3_registry"), + lazy_fixture("gcs_registry"), + pytest.param( + lazy_fixture("hdfs_registry"), + marks=pytest.mark.xdist_group(name="hdfs_registry"), + ), + ] + ) else: - all_fixtures = [ - lazy_fixture("local_registry"), + all_fixtures.append( pytest.param( lazy_fixture("minio_registry"), marks=pytest.mark.xdist_group(name="minio_registry"), - ), - pytest.param( - lazy_fixture("pg_registry"), - marks=pytest.mark.xdist_group(name="pg_registry"), - ), - pytest.param( - lazy_fixture("mysql_registry"), - marks=pytest.mark.xdist_group(name="mysql_registry"), - ), - lazy_fixture("sqlite_registry"), - pytest.param( - lazy_fixture("mock_remote_registry"), - marks=pytest.mark.rbac_remote_integration_test, - ), - pytest.param( - lazy_fixture("hdfs_registry"), - marks=pytest.mark.xdist_group(name="hdfs_registry"), - ), - ] + ) + ) sql_fixtures = [ pytest.param( @@ -611,6 +619,81 @@ def test_apply_feature_view_success(test_registry: BaseRegistry): test_registry.teardown() +@pytest.mark.integration +@pytest.mark.parametrize( + "test_registry", + all_fixtures, +) +def test_apply_feature_view_without_source_success(test_registry: BaseRegistry): + """Test that a FeatureView with no source can be applied, retrieved, updated, and deleted.""" + entity = Entity(name="fs1_my_entity_1", join_keys=["test"]) + + fv1 = FeatureView( + name="my_feature_view_no_source", + schema=[ + Field(name="test", dtype=Int64), + Field(name="fs1_my_feature_1", dtype=Int64), + Field(name="fs1_my_feature_2", dtype=String), + Field(name="fs1_my_feature_3", dtype=Array(String)), + ], + entities=[entity], + tags={"team": "matchmaking"}, + source=None, + ttl=timedelta(minutes=5), + ) + + project = "project" + + # Register Feature View + test_registry.apply_feature_view(fv1, project) + + feature_views = test_registry.list_feature_views(project, tags=fv1.tags) + + assert len(feature_views) == 1 + assert feature_views[0].name == "my_feature_view_no_source" + assert feature_views[0].batch_source is None + assert feature_views[0].stream_source is None + assert feature_views[0].features[0].name == "fs1_my_feature_1" + assert feature_views[0].features[0].dtype == Int64 + assert feature_views[0].features[1].name == "fs1_my_feature_2" + assert feature_views[0].features[1].dtype == String + assert feature_views[0].features[2].name == "fs1_my_feature_3" + assert feature_views[0].features[2].dtype == Array(String) + + feature_view = test_registry.get_feature_view("my_feature_view_no_source", project) + any_feature_view = test_registry.get_any_feature_view( + "my_feature_view_no_source", project + ) + + assert feature_view.name == "my_feature_view_no_source" + assert feature_view.batch_source is None + assert feature_view.stream_source is None + assert feature_view.ttl == timedelta(minutes=5) + assert feature_view == any_feature_view + + # After the first apply, created_timestamp should equal last_updated_timestamp. + assert feature_view.created_timestamp == feature_view.last_updated_timestamp + + # Update the feature view and verify created_timestamp is preserved. + fv1.ttl = timedelta(minutes=10) + test_registry.apply_feature_view(fv1, project) + feature_views = test_registry.list_feature_views(project) + assert len(feature_views) == 1 + updated_feature_view = test_registry.get_feature_view( + "my_feature_view_no_source", project + ) + assert updated_feature_view.ttl == timedelta(minutes=10) + assert updated_feature_view.batch_source is None + assert updated_feature_view.created_timestamp == feature_view.created_timestamp + + # Delete the feature view. + test_registry.delete_feature_view("my_feature_view_no_source", project) + feature_views = test_registry.list_feature_views(project) + assert len(feature_views) == 0 + + test_registry.teardown() + + @pytest.mark.integration @pytest.mark.parametrize( "test_registry", @@ -1993,3 +2076,119 @@ def test_commit_for_read_only_user(): assert len(entities) == 1 write_registry.teardown() + + +@pytest.mark.integration +@pytest.mark.parametrize( + "test_registry", + # mock_remote_registry excluded: the mock gRPC channel does not propagate + # server-side errors, so ConflictingFeatureViewNames is not raised client-side. + [f for f in all_fixtures if "mock_remote" not in str(f)], +) +def test_cross_type_feature_view_name_conflict(test_registry: BaseRegistry): + """ + Test that feature view names must be unique across all feature view types. + + This validates the fix for feast-dev/feast#5995: If a FeatureView and + StreamFeatureView share the same name, get_online_features would silently + return the wrong one (fixed order lookup). This test ensures such conflicts + are caught during registration. + """ + project = "project" + + # Create a simple entity + entity = Entity(name="driver_entity", join_keys=["test_key"]) + + # Create a regular FeatureView + file_source = FileSource(name="my_file_source", path="test.parquet") + feature_view = FeatureView( + name="shared_feature_view_name", + entities=[entity], + schema=[Field(name="feature1", dtype=Float32)], + source=file_source, + ) + + # Create a StreamFeatureView with the SAME name + stream_source = KafkaSource( + name="kafka", + timestamp_field="event_timestamp", + kafka_bootstrap_servers="", + message_format=AvroFormat(""), + topic="topic", + batch_source=FileSource(path="some path"), + watermark_delay_threshold=timedelta(days=1), + ) + + def simple_udf(x: int): + return x + 3 + + stream_feature_view = StreamFeatureView( + name="shared_feature_view_name", # Same name as FeatureView! + entities=[entity], + ttl=timedelta(days=30), + schema=[Field(name="feature1", dtype=Float32)], + source=stream_source, + udf=simple_udf, + ) + + # Register the regular FeatureView first - should succeed + test_registry.apply_feature_view(feature_view, project) + + # Attempt to register StreamFeatureView with same name - should fail + with pytest.raises(ConflictingFeatureViewNames) as exc_info: + test_registry.apply_feature_view(stream_feature_view, project) + + # Verify error message contains the conflicting types + error_message = str(exc_info.value) + assert "shared_feature_view_name" in error_message + + # Cleanup + test_registry.delete_feature_view("shared_feature_view_name", project) + test_registry.teardown() + + +@pytest.mark.integration +@pytest.mark.parametrize( + "test_registry", + [f for f in all_fixtures if "mock_remote" not in str(f)], +) +def test_cross_type_feature_view_odfv_conflict(test_registry: BaseRegistry): + """ + Test that OnDemandFeatureView names must be unique across all feature view types. + """ + project = "project" + + # Create a simple entity + entity = Entity(name="driver_entity", join_keys=["test_key"]) + + # Create a regular FeatureView + file_source = FileSource(name="my_file_source", path="test.parquet") + feature_view = FeatureView( + name="shared_odfv_name", + entities=[entity], + schema=[Field(name="feature1", dtype=Float32)], + source=file_source, + ) + + # Create an OnDemandFeatureView with the SAME name + @on_demand_feature_view( + sources=[feature_view], + schema=[Field(name="output", dtype=Float32)], + ) + def shared_odfv_name(inputs: pd.DataFrame) -> pd.DataFrame: + return pd.DataFrame({"output": inputs["feature1"] * 2}) + + # Register the regular FeatureView first - should succeed + test_registry.apply_feature_view(feature_view, project) + + # Attempt to register OnDemandFeatureView with same name - should fail + with pytest.raises(ConflictingFeatureViewNames) as exc_info: + test_registry.apply_feature_view(shared_odfv_name, project) + + # Verify error message contains the conflicting types + error_message = str(exc_info.value) + assert "shared_odfv_name" in error_message + + # Cleanup + test_registry.delete_feature_view("shared_odfv_name", project) + test_registry.teardown() diff --git a/sdk/python/tests/integration/registration/test_versioning.py b/sdk/python/tests/integration/registration/test_versioning.py new file mode 100644 index 00000000000..72289e72a4f --- /dev/null +++ b/sdk/python/tests/integration/registration/test_versioning.py @@ -0,0 +1,1418 @@ +"""Integration tests for feature view versioning.""" + +import os +import tempfile +from datetime import timedelta +from pathlib import Path + +import pytest + +from feast import FeatureStore +from feast.entity import Entity +from feast.errors import FeatureViewPinConflict, FeatureViewVersionNotFound +from feast.feature_service import FeatureService +from feast.feature_view import FeatureView +from feast.field import Field +from feast.infra.online_stores.sqlite import SqliteOnlineStoreConfig +from feast.infra.registry.registry import Registry +from feast.repo_config import RegistryConfig, RepoConfig +from feast.stream_feature_view import StreamFeatureView +from feast.types import Float32, Int64 +from feast.value_type import ValueType + + +@pytest.fixture +def registry(): + """Create a file-based Registry for testing. Version history is always-on.""" + with tempfile.TemporaryDirectory() as tmpdir: + registry_path = Path(tmpdir) / "registry.pb" + config = RegistryConfig(path=str(registry_path)) + reg = Registry("test_project", config, None) + yield reg + + +@pytest.fixture +def registry_no_online_versioning(): + """Create a file-based Registry without online versioning (default).""" + with tempfile.TemporaryDirectory() as tmpdir: + registry_path = Path(tmpdir) / "registry.pb" + config = RegistryConfig(path=str(registry_path)) + reg = Registry("test_project", config, None) + yield reg + + +@pytest.fixture +def entity(): + return Entity( + name="driver_id", + join_keys=["driver_id"], + value_type=ValueType.INT64, + ) + + +@pytest.fixture +def make_fv(entity): + def _make(description="test feature view", version="latest", **kwargs): + return FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + ], + description=description, + version=version, + **kwargs, + ) + + return _make + + +@pytest.fixture +def make_sfv(entity): + def _make(description="test stream feature view", udf=None, **kwargs): + from feast.data_source import PushSource + from feast.infra.offline_stores.file_source import FileSource + + def default_udf(df): + return df + + # Create batch source + batch_source = FileSource(name="test_batch_source", path="test.parquet") + + # Create a simple push source for testing + source = PushSource(name="test_push_source", batch_source=batch_source) + + return StreamFeatureView( + name="driver_stats_stream", + entities=[entity], + ttl=timedelta(hours=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + ], + description=description, + udf=udf or default_udf, + source=source, + **kwargs, + ) + + return _make + + +# OnDemandFeatureView tests removed due to transformation comparison issues + + +class TestFileRegistryVersioning: + def test_first_apply_creates_v0(self, registry, make_fv): + fv = make_fv() + registry.apply_feature_view(fv, "test_project", commit=True) + + versions = registry.list_feature_view_versions("driver_stats", "test_project") + assert len(versions) == 1 + assert versions[0]["version"] == "v0" + assert versions[0]["version_number"] == 0 + + def test_modify_and_reapply_creates_new_version(self, registry, make_fv, entity): + fv1 = make_fv(description="version one") + registry.apply_feature_view(fv1, "test_project", commit=True) + + # Create a schema change by adding a new feature + fv2 = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + Field(name="new_feature", dtype=Float32), # Schema change + ], + description="version two", + ) + registry.apply_feature_view(fv2, "test_project", commit=True) + + versions = registry.list_feature_view_versions("driver_stats", "test_project") + assert len(versions) == 2 + assert versions[0]["version"] == "v0" + assert versions[1]["version"] == "v1" + + def test_idempotent_apply_no_new_version(self, registry, make_fv): + fv = make_fv(description="same definition") + registry.apply_feature_view(fv, "test_project", commit=True) + + # Apply identical FV again + fv_same = make_fv(description="same definition") + registry.apply_feature_view(fv_same, "test_project", commit=True) + + versions = registry.list_feature_view_versions("driver_stats", "test_project") + assert len(versions) == 1 # No new version created + + def test_pin_to_v0(self, registry, make_fv, entity): + # Create v0 + fv1 = make_fv(description="original") + registry.apply_feature_view(fv1, "test_project", commit=True) + + # Create v1 with schema change + fv2 = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + Field(name="new_field", dtype=Float32), # Schema change + ], + description="updated", + ) + registry.apply_feature_view(fv2, "test_project", commit=True) + + # Pin to v0 (definition must match active FV, only version changes) + fv_pin = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + Field(name="new_field", dtype=Float32), # Keep current schema + ], + description="updated", + version="v0", + ) + registry.apply_feature_view(fv_pin, "test_project", commit=True) + + # Verify active entry has v0's content + active_fv = registry.get_feature_view("driver_stats", "test_project") + assert active_fv.description == "original" + assert active_fv.version == "v0" + + def test_explicit_version_creates_when_not_exists(self, registry, make_fv): + """Explicit version on a new FV creates that version (forward declaration).""" + fv = make_fv(description="forward declared v1", version="v1") + registry.apply_feature_view(fv, "test_project", commit=True) + + versions = registry.list_feature_view_versions("driver_stats", "test_project") + assert len(versions) == 1 + assert versions[0]["version_number"] == 1 + + active_fv = registry.get_feature_view("driver_stats", "test_project") + assert active_fv.current_version_number == 1 + + def test_explicit_version_reverts_when_exists(self, registry, make_fv, entity): + """Explicit version on an existing FV reverts to that snapshot (pin/revert).""" + # Create v0 + fv1 = make_fv(description="original") + registry.apply_feature_view(fv1, "test_project", commit=True) + + # Create v1 with schema change + fv2 = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + Field(name="new_field", dtype=Float32), + ], + description="updated", + ) + registry.apply_feature_view(fv2, "test_project", commit=True) + + # Pin to v0 (definition must match active FV, only version changes) + fv_pin = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + Field(name="new_field", dtype=Float32), + ], + description="updated", + version="v0", + ) + registry.apply_feature_view(fv_pin, "test_project", commit=True) + + active_fv = registry.get_feature_view("driver_stats", "test_project") + assert active_fv.description == "original" + assert active_fv.version == "v0" + + def test_forward_declare_nonexistent_version(self, registry, make_fv): + """Forward-declaring a version that doesn't exist creates it.""" + fv = make_fv() + registry.apply_feature_view(fv, "test_project", commit=True) + + # Forward-declare v5 — should create it, not raise + fv_v5 = make_fv(description="forward declared v5", version="v5") + registry.apply_feature_view(fv_v5, "test_project", commit=True) + + versions = registry.list_feature_view_versions("driver_stats", "test_project") + version_numbers = [v["version_number"] for v in versions] + assert 5 in version_numbers + + # The active FV should now be the forward-declared v5 + active_fv = registry.get_feature_view("driver_stats", "test_project") + assert active_fv.current_version_number == 5 + assert active_fv.description == "forward declared v5" + + def test_apply_after_pin_creates_new_version(self, registry, make_fv, entity): + # Create v0 + fv1 = make_fv(description="v0 desc") + registry.apply_feature_view(fv1, "test_project", commit=True) + + # Create v1 with schema change + fv2 = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + Field(name="v1_field", dtype=Float32), # Schema change + ], + description="v1 desc", + ) + registry.apply_feature_view(fv2, "test_project", commit=True) + + # Pin to v0 (definition must match active FV, only version changes) + fv_pin = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + Field(name="v1_field", dtype=Float32), # Keep current schema + ], + description="v1 desc", + version="v0", + ) + registry.apply_feature_view(fv_pin, "test_project", commit=True) + + # Apply new content with another schema change (should create new version) + fv3 = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + Field(name="v1_field", dtype=Float32), + Field(name="v2_field", dtype=Float32), # Another schema change + ], + description="v2 desc after pin", + ) + registry.apply_feature_view(fv3, "test_project", commit=True) + + versions = registry.list_feature_view_versions("driver_stats", "test_project") + # Should have v0, v1, and potentially more versions + assert len(versions) >= 2 + + def test_pin_with_modified_definition_raises(self, registry, make_fv, entity): + # Create v0 + fv1 = make_fv(description="original") + registry.apply_feature_view(fv1, "test_project", commit=True) + + # Create v1 with schema change + fv2 = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + Field(name="new_field", dtype=Float32), # Schema change + ], + description="updated", + ) + registry.apply_feature_view(fv2, "test_project", commit=True) + + # Attempt to pin to v0 while also changing schema (sneaky change) + fv_pin = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + Field(name="new_field", dtype=Float32), + Field(name="sneaky_field", dtype=Float32), # Sneaky schema change + ], + description="updated", + version="v0", + ) + with pytest.raises(FeatureViewPinConflict): + registry.apply_feature_view(fv_pin, "test_project", commit=True) + + def test_pin_without_modification_succeeds(self, registry, make_fv, entity): + # Create v0 + fv1 = make_fv(description="original") + registry.apply_feature_view(fv1, "test_project", commit=True) + + # Create v1 with schema change + fv2 = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + Field(name="new_field", dtype=Float32), # Schema change + ], + description="updated", + ) + registry.apply_feature_view(fv2, "test_project", commit=True) + + # Pin to v0 with same definition as active (only version changes) + fv_pin = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + Field(name="new_field", dtype=Float32), # Keep current schema + ], + description="updated", + version="v0", + ) + registry.apply_feature_view(fv_pin, "test_project", commit=True) + + # Verify active entry has v0's content + active_fv = registry.get_feature_view("driver_stats", "test_project") + assert active_fv.description == "original" + assert active_fv.version == "v0" + + def test_get_feature_view_by_version(self, registry, make_fv, entity): + # Create v0 + fv1 = make_fv(description="version zero") + registry.apply_feature_view(fv1, "test_project", commit=True) + + # Create v1 with schema change and different description + fv2 = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + Field(name="v1_field", dtype=Float32), # Schema change + ], + description="version one", + ) + registry.apply_feature_view(fv2, "test_project", commit=True) + + # Retrieve v0 snapshot + fv_v0 = registry.get_feature_view_by_version("driver_stats", "test_project", 0) + assert fv_v0.description == "version zero" + assert fv_v0.current_version_number == 0 + + # Retrieve v1 snapshot + fv_v1 = registry.get_feature_view_by_version("driver_stats", "test_project", 1) + assert fv_v1.description == "version one" + assert fv_v1.current_version_number == 1 + + def test_get_feature_view_by_version_not_found(self, registry, make_fv): + fv = make_fv() + registry.apply_feature_view(fv, "test_project", commit=True) + + with pytest.raises(FeatureViewVersionNotFound): + registry.get_feature_view_by_version("driver_stats", "test_project", 99) + + def test_version_in_proto_roundtrip(self, registry, make_fv): + fv = make_fv(version="v3") + # Manually set version number for testing + fv.current_version_number = 3 + + proto = fv.to_proto() + assert proto.spec.version == "v3" + assert proto.meta.current_version_number == 3 + + fv2 = FeatureView.from_proto(proto) + assert fv2.version == "v3" + assert fv2.current_version_number == 3 + + +class TestRefinedVersioningBehavior: + """Test that only schema and UDF changes create new versions.""" + + def test_metadata_changes_no_new_version(self, registry, make_fv): + """Verify metadata changes don't create new versions.""" + fv = make_fv(description="original description", tags={"team": "ml"}) + registry.apply_feature_view(fv, "test_project", commit=True) + + # Modify only metadata + fv_updated = make_fv( + description="updated description", + tags={"team": "ml", "env": "prod"}, + owner="new_owner@company.com", + ) + registry.apply_feature_view(fv_updated, "test_project", commit=True) + + # Should not create new version + versions = registry.list_feature_view_versions("driver_stats", "test_project") + assert len(versions) == 1 # Still just v0 + assert versions[0]["version_number"] == 0 + + def test_schema_changes_create_new_version(self, registry, make_fv, entity): + """Verify schema changes create new versions.""" + fv = make_fv() + registry.apply_feature_view(fv, "test_project", commit=True) + + # Add a new feature (schema change) + fv_with_new_feature = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + Field(name="new_feature", dtype=Float32), # New field + ], + description="same description", # Keep same metadata + ) + registry.apply_feature_view(fv_with_new_feature, "test_project", commit=True) + + # Should create new version + versions = registry.list_feature_view_versions("driver_stats", "test_project") + assert len(versions) == 2 # v0 and v1 + assert versions[1]["version_number"] == 1 + + def test_configuration_changes_no_new_version(self, registry, make_fv): + """Verify configuration changes don't create new versions.""" + fv = make_fv(online=True, offline=True) + registry.apply_feature_view(fv, "test_project", commit=True) + + # Change configuration fields + fv_config_updated = make_fv( + online=False, # Configuration change + offline=False, # Configuration change + description="same description", # Keep same metadata + ) + registry.apply_feature_view(fv_config_updated, "test_project", commit=True) + + # Should not create new version + versions = registry.list_feature_view_versions("driver_stats", "test_project") + assert len(versions) == 1 # Still just v0 + assert versions[0]["version_number"] == 0 + + def test_entity_changes_create_new_version(self, registry, make_fv): + """Verify entity changes create new versions.""" + fv = make_fv() + registry.apply_feature_view(fv, "test_project", commit=True) + + # Create new entity and add it (schema change) + new_entity = Entity( + name="vehicle_id", + join_keys=["vehicle_id"], + value_type=ValueType.INT64, # Match the field type + ) + + fv_with_new_entity = FeatureView( + name="driver_stats", + entities=[ + Entity( + name="driver_id", + join_keys=["driver_id"], + value_type=ValueType.INT64, + ), + new_entity, + ], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="vehicle_id", dtype=Int64), # New entity field + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + ], + description="same description", + ) + registry.apply_feature_view(fv_with_new_entity, "test_project", commit=True) + + # Should create new version due to entity change + versions = registry.list_feature_view_versions("driver_stats", "test_project") + assert len(versions) == 2 # v0 and v1 + assert versions[1]["version_number"] == 1 + + def test_stream_feature_view_udf_changes_create_new_version( + self, registry, make_sfv + ): + """Verify UDF changes create new versions (StreamFeatureView).""" + + def original_transform(df): + return df + + def updated_transform(df): + df["new_col"] = df["trips_today"] * 2 + return df + + sfv = make_sfv(udf=original_transform) + registry.apply_feature_view(sfv, "test_project", commit=True) + + sfv_updated = make_sfv( + udf=updated_transform, + description="same description", # Keep same metadata + ) + registry.apply_feature_view(sfv_updated, "test_project", commit=True) + + # Should create new version due to UDF change + versions = registry.list_feature_view_versions( + "driver_stats_stream", "test_project" + ) + assert len(versions) == 2 # v0 and v1 + + # TODO: Add tests for OnDemandFeatureView once transformation comparison issues are resolved + # The current issue is that PythonTransformation.__eq__ has strict type checking + # that prevents proper comparison between objects created at different times + + +class TestVersionMetadataIntegration: + """Integration tests for version metadata functionality in responses.""" + + def test_version_metadata_disabled_by_default(self, registry, make_fv): + """Test that version metadata is not included by default.""" + from feast.protos.feast.serving.ServingService_pb2 import ( + GetOnlineFeaturesResponse, + ) + from feast.utils import _populate_response_from_feature_data + + # Create and register a versioned feature view + fv = make_fv(description="test version metadata") + registry.apply_feature_view(fv, "test_project", commit=True) + + # Get the feature view with version info + active_fv = registry.get_feature_view("driver_stats", "test_project") + assert hasattr(active_fv, "current_version_number") + + # Mock response generation without version metadata + response = GetOnlineFeaturesResponse() + _populate_response_from_feature_data( + requested_features=["trips_today"], + read_rows=[], + indexes=(), + online_features_response=response, + full_feature_names=True, + table=active_fv, + output_len=0, + include_feature_view_version_metadata=False, # Default behavior + ) + + # Verify no version metadata is included + assert len(response.metadata.feature_view_metadata) == 0 + # Feature names should still be populated + assert len(response.metadata.feature_names.val) == 1 + + def test_version_metadata_included_when_requested(self, registry, make_fv, entity): + """Test that version metadata is included when requested.""" + from feast.protos.feast.serving.ServingService_pb2 import ( + GetOnlineFeaturesResponse, + ) + from feast.utils import _populate_response_from_feature_data + + # Create v0 + fv1 = make_fv(description="first version") + registry.apply_feature_view(fv1, "test_project", commit=True) + + # Create v1 by modifying schema + fv2 = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + Field(name="total_earnings", dtype=Float32), # New field + ], + description="second version", + ) + registry.apply_feature_view(fv2, "test_project", commit=True) + + # Get v1 (latest version) + active_fv = registry.get_feature_view("driver_stats", "test_project") + assert active_fv.current_version_number == 1 + + # Mock response generation with version metadata + response = GetOnlineFeaturesResponse() + _populate_response_from_feature_data( + requested_features=["trips_today", "total_earnings"], + read_rows=[], + indexes=(), + online_features_response=response, + full_feature_names=False, # Test without prefixes + table=active_fv, + output_len=0, + include_feature_view_version_metadata=True, # Enable metadata + ) + + # Verify version metadata is included + assert len(response.metadata.feature_view_metadata) == 1 + fv_metadata = response.metadata.feature_view_metadata[0] + assert fv_metadata.name == "driver_stats" + assert fv_metadata.version == 1 + + # Verify feature names are clean (no @v1 suffix) + feature_names = list(response.metadata.feature_names.val) + assert feature_names == ["trips_today", "total_earnings"] + assert all("@" not in name for name in feature_names) + + def test_version_metadata_clean_names_with_prefixes(self, registry, make_fv): + """Test that feature names are clean even with full_feature_names=True.""" + from feast.protos.feast.serving.ServingService_pb2 import ( + GetOnlineFeaturesResponse, + ) + from feast.utils import _populate_response_from_feature_data + + # Create versioned feature view + fv = make_fv(description="test clean names") + registry.apply_feature_view(fv, "test_project", commit=True) + active_fv = registry.get_feature_view("driver_stats", "test_project") + + # Test with full feature names (prefixed) + response = GetOnlineFeaturesResponse() + _populate_response_from_feature_data( + requested_features=["trips_today"], + read_rows=[], + indexes=(), + online_features_response=response, + full_feature_names=True, # Enable prefixes + table=active_fv, + output_len=0, + include_feature_view_version_metadata=True, + ) + + # Feature names should be prefixed but clean (no @v0) + feature_names = list(response.metadata.feature_names.val) + assert len(feature_names) == 1 + assert feature_names[0] == "driver_stats__trips_today" # Clean prefix + assert "@" not in feature_names[0] # No version in name + + # Version metadata should be separate + assert len(response.metadata.feature_view_metadata) == 1 + assert response.metadata.feature_view_metadata[0].name == "driver_stats" + assert response.metadata.feature_view_metadata[0].version == 0 + + def test_version_metadata_multiple_feature_views(self, registry, entity): + """Test version metadata with multiple feature views.""" + from feast.protos.feast.serving.ServingService_pb2 import ( + GetOnlineFeaturesResponse, + ) + from feast.utils import _populate_response_from_feature_data + + # Create first feature view + fv1 = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + ], + description="driver features", + ) + registry.apply_feature_view(fv1, "test_project", commit=True) + + # Create second feature view + fv2 = FeatureView( + name="user_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="total_bookings", dtype=Int64), + ], + description="user features", + ) + registry.apply_feature_view(fv2, "test_project", commit=True) + + # Modify user_stats to create v1 + fv2_v1 = FeatureView( + name="user_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="total_bookings", dtype=Int64), + Field(name="cancellation_rate", dtype=Float32), # New field + ], + description="user features v1", + ) + registry.apply_feature_view(fv2_v1, "test_project", commit=True) + + # Get feature views + driver_fv = registry.get_feature_view("driver_stats", "test_project") # v0 + user_fv = registry.get_feature_view("user_stats", "test_project") # v1 + + # Simulate processing multiple feature views in response + response = GetOnlineFeaturesResponse() + + # Process first feature view + _populate_response_from_feature_data( + requested_features=["trips_today"], + read_rows=[], + indexes=(), + online_features_response=response, + full_feature_names=False, + table=driver_fv, + output_len=0, + include_feature_view_version_metadata=True, + ) + + # Process second feature view + _populate_response_from_feature_data( + requested_features=["total_bookings", "cancellation_rate"], + read_rows=[], + indexes=(), + online_features_response=response, + full_feature_names=False, + table=user_fv, + output_len=0, + include_feature_view_version_metadata=True, + ) + + # Verify both feature views are in metadata + assert len(response.metadata.feature_view_metadata) == 2 + + fv_metadata_by_name = { + fvm.name: fvm for fvm in response.metadata.feature_view_metadata + } + assert "driver_stats" in fv_metadata_by_name + assert "user_stats" in fv_metadata_by_name + + # Check versions + assert fv_metadata_by_name["driver_stats"].version == 0 + assert fv_metadata_by_name["user_stats"].version == 1 + + # Verify feature names are clean + feature_names = list(response.metadata.feature_names.val) + assert feature_names == ["trips_today", "total_bookings", "cancellation_rate"] + assert all("@" not in name for name in feature_names) + + def test_version_metadata_prevents_duplicates(self, registry, make_fv): + """Test that duplicate feature view metadata is not added.""" + from feast.protos.feast.serving.ServingService_pb2 import ( + GetOnlineFeaturesResponse, + ) + from feast.utils import _populate_response_from_feature_data + + fv = make_fv(description="test duplicates") + registry.apply_feature_view(fv, "test_project", commit=True) + active_fv = registry.get_feature_view("driver_stats", "test_project") + + response = GetOnlineFeaturesResponse() + + # Process same feature view twice (simulating multiple features from same view) + _populate_response_from_feature_data( + requested_features=["trips_today"], + read_rows=[], + indexes=(), + online_features_response=response, + full_feature_names=False, + table=active_fv, + output_len=0, + include_feature_view_version_metadata=True, + ) + + _populate_response_from_feature_data( + requested_features=["avg_rating"], + read_rows=[], + indexes=(), + online_features_response=response, + full_feature_names=False, + table=active_fv, + output_len=0, + include_feature_view_version_metadata=True, + ) + + # Should only have one metadata entry despite processing twice + assert len(response.metadata.feature_view_metadata) == 1 + assert response.metadata.feature_view_metadata[0].name == "driver_stats" + + # But should have both feature names + feature_names = list(response.metadata.feature_names.val) + assert len(feature_names) == 2 + assert "trips_today" in feature_names + assert "avg_rating" in feature_names + + def test_version_metadata_backward_compatibility(self, registry, make_fv): + """Test that existing code without version metadata still works.""" + from feast.protos.feast.serving.ServingService_pb2 import ( + GetOnlineFeaturesResponse, + ) + from feast.utils import _populate_response_from_feature_data + + fv = make_fv(description="backward compatibility test") + registry.apply_feature_view(fv, "test_project", commit=True) + active_fv = registry.get_feature_view("driver_stats", "test_project") + + # Test calling without the new parameter (should default to False) + response = GetOnlineFeaturesResponse() + _populate_response_from_feature_data( + requested_features=["trips_today"], + read_rows=[], + indexes=(), + online_features_response=response, + full_feature_names=True, + table=active_fv, + output_len=0, + # Note: include_feature_view_version_metadata parameter omitted + ) + + # Should work and not include version metadata + assert len(response.metadata.feature_view_metadata) == 0 + assert len(response.metadata.feature_names.val) == 1 + + +class TestOnlineVersioningDisabled: + """Tests that online versioning guard works for version-qualified refs.""" + + def test_version_qualified_ref_raises_when_online_versioning_disabled( + self, registry_no_online_versioning, make_fv, entity + ): + """Using @v2 refs raises ValueError when online versioning is disabled.""" + from feast.utils import _get_feature_views_to_use + + fv = make_fv(description="test fv") + registry_no_online_versioning.apply_feature_view( + fv, "test_project", commit=True + ) + + # Create v1 with schema change + fv2 = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + Field(name="new_field", dtype=Float32), + ], + description="version one", + ) + registry_no_online_versioning.apply_feature_view( + fv2, "test_project", commit=True + ) + + # Version-qualified ref should raise + with pytest.raises(ValueError, match="online versioning is disabled"): + _get_feature_views_to_use( + registry=registry_no_online_versioning, + project="test_project", + features=["driver_stats@v1:trips_today"], + allow_cache=False, + hide_dummy_entity=False, + ) + + +class TestFeatureServiceVersioningGates: + """Tests that feature services are gated when referencing versioned feature views.""" + + @pytest.fixture + def versioned_fv_and_entity(self): + """Create a versioned feature view (v1) and its entity.""" + entity = Entity( + name="driver_id", + join_keys=["driver_id"], + value_type=ValueType.INT64, + ) + # v0 definition + fv_v0 = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + ], + description="v0", + ) + # v1 definition (schema change) + fv_v1 = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + ], + description="v1", + ) + return entity, fv_v0, fv_v1 + + @pytest.fixture + def unversioned_fv_and_entity(self): + """Create an unversioned feature view (v0 only) and its entity.""" + entity = Entity( + name="driver_id", + join_keys=["driver_id"], + value_type=ValueType.INT64, + ) + fv = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + ], + description="only version", + ) + return entity, fv + + def _make_store(self, tmpdir, enable_versioning=False): + """Create a FeatureStore with optional online versioning.""" + registry_path = os.path.join(tmpdir, "registry.db") + online_path = os.path.join(tmpdir, "online.db") + return FeatureStore( + config=RepoConfig( + registry=RegistryConfig( + path=registry_path, + enable_online_feature_view_versioning=enable_versioning, + ), + project="test_project", + provider="local", + online_store=SqliteOnlineStoreConfig(path=online_path), + entity_key_serialization_version=3, + ) + ) + + def test_feature_service_apply_succeeds_with_versioned_fv_when_flag_off( + self, versioned_fv_and_entity + ): + """Apply a feature service referencing a versioned FV with flag off -> succeeds.""" + entity, fv_v0, fv_v1 = versioned_fv_and_entity + + with tempfile.TemporaryDirectory() as tmpdir: + store = self._make_store(tmpdir, enable_versioning=False) + + # Apply v0 first, then v1 to create version history + store.apply([entity, fv_v0]) + store.apply([entity, fv_v1]) + + # Now create a feature service referencing the versioned FV + fs = FeatureService( + name="driver_service", + features=[fv_v1], + ) + store.apply([fs]) # Should not raise + + def test_feature_service_apply_succeeds_with_versioned_fv_when_flag_on( + self, versioned_fv_and_entity + ): + """Apply a feature service referencing a versioned FV with flag on -> succeeds.""" + entity, fv_v0, fv_v1 = versioned_fv_and_entity + + with tempfile.TemporaryDirectory() as tmpdir: + store = self._make_store(tmpdir, enable_versioning=True) + + # Apply v0 first, then v1 to create version history + store.apply([entity, fv_v0]) + store.apply([entity, fv_v1]) + + # Feature service referencing versioned FV should succeed + fs = FeatureService( + name="driver_service", + features=[fv_v1], + ) + store.apply([fs]) # Should not raise + + def test_feature_service_retrieval_succeeds_with_versioned_fv_when_flag_off( + self, versioned_fv_and_entity + ): + """get_online_features with a feature service referencing a versioned FV, flag off -> succeeds.""" + entity, fv_v0, fv_v1 = versioned_fv_and_entity + from feast.utils import _get_feature_views_to_use + + with tempfile.TemporaryDirectory() as tmpdir: + # First apply with flag on so the feature service can be registered + store_on = self._make_store(tmpdir, enable_versioning=True) + store_on.apply([entity, fv_v0]) + store_on.apply([entity, fv_v1]) + fs = FeatureService( + name="driver_service", + features=[fv_v1], + ) + store_on.apply([fs]) + + # Now create a store with the flag off to test retrieval + store_off = self._make_store(tmpdir, enable_versioning=False) + registered_fs = store_off.registry.get_feature_service( + "driver_service", "test_project" + ) + + fvs, _ = _get_feature_views_to_use( + registry=store_off.registry, + project="test_project", + features=registered_fs, + allow_cache=False, + hide_dummy_entity=False, + ) + + assert len(fvs) == 1 + + def test_feature_service_with_unversioned_fv_succeeds( + self, unversioned_fv_and_entity + ): + """Feature service with v0 FV works fine regardless of flag.""" + entity, fv = unversioned_fv_and_entity + + with tempfile.TemporaryDirectory() as tmpdir: + store = self._make_store(tmpdir, enable_versioning=False) + + # Apply unversioned FV and feature service + fs = FeatureService( + name="driver_service", + features=[fv], + ) + store.apply([entity, fv, fs]) # Should not raise + + def test_feature_service_serves_versioned_fv_when_flag_on( + self, versioned_fv_and_entity + ): + """With online versioning on, FeatureService projections do not carry version_tag; + the FV in the registry carries current_version_number.""" + from feast.utils import _get_feature_views_to_use + + entity, fv_v0, fv_v1 = versioned_fv_and_entity + + with tempfile.TemporaryDirectory() as tmpdir: + store = self._make_store(tmpdir, enable_versioning=True) + + # Apply v0 then v1 to create version history + store.apply([entity, fv_v0]) + store.apply([entity, fv_v1]) + + # Create and apply a feature service referencing the versioned FV + fs = FeatureService( + name="driver_service", + features=[fv_v1], + ) + store.apply([fs]) + + # Retrieve the registered feature service + registered_fs = store.registry.get_feature_service( + "driver_service", "test_project" + ) + + fvs, _ = _get_feature_views_to_use( + registry=store.registry, + project="test_project", + features=registered_fs, + allow_cache=False, + hide_dummy_entity=False, + ) + + assert len(fvs) == 1 + assert fvs[0].projection.version_tag is None + assert fvs[0].projection.name_to_use() == "driver_stats" + + # Verify the FV in the registry has the correct version + fv_from_registry = store.registry.get_feature_view( + "driver_stats", "test_project" + ) + assert fv_from_registry.current_version_number == 1 + + def test_feature_service_feature_refs_are_plain_when_flag_on( + self, versioned_fv_and_entity + ): + """With online versioning on, _get_features() produces plain (non-versioned) refs for FeatureService.""" + from feast.utils import _get_features + + entity, fv_v0, fv_v1 = versioned_fv_and_entity + + with tempfile.TemporaryDirectory() as tmpdir: + store = self._make_store(tmpdir, enable_versioning=True) + + # Apply v0 then v1 to create version history + store.apply([entity, fv_v0]) + store.apply([entity, fv_v1]) + + # Create and apply a feature service referencing the versioned FV + fs = FeatureService( + name="driver_service", + features=[fv_v1], + ) + store.apply([fs]) + + # Retrieve the registered feature service + registered_fs = store.registry.get_feature_service( + "driver_service", "test_project" + ) + + refs = _get_features( + registry=store.registry, + project="test_project", + features=registered_fs, + allow_cache=False, + ) + + # Refs should be plain (no version qualifier) + for ref in refs: + assert "@v" not in ref, f"Expected plain ref, got: {ref}" + + # Check specific ref format + assert "driver_stats:trips_today" in refs + + def test_unpin_from_versioned_to_latest(self, versioned_fv_and_entity): + """Pin a FV to v1, then apply with version='latest' (no schema change) -> unpinned.""" + entity, fv_v0, fv_v1 = versioned_fv_and_entity + + with tempfile.TemporaryDirectory() as tmpdir: + store = self._make_store(tmpdir, enable_versioning=True) + + # Apply v0 then v1 to create version history (v1 has schema change) + store.apply([entity, fv_v0]) + store.apply([entity, fv_v1]) + + # Verify it's pinned to v1 + reloaded = store.registry.get_feature_view("driver_stats", "test_project") + assert reloaded.current_version_number == 1 + + # Now re-apply the same schema with version="latest" to unpin + fv_latest = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + ], + version="latest", + description="v1", + ) + store.apply([entity, fv_latest]) + + # Reload and verify unpinned + reloaded = store.registry.get_feature_view("driver_stats", "test_project") + assert reloaded.current_version_number is None + assert reloaded.version == "latest" + + +class TestNoPromote: + """Tests for the no_promote flag on apply_feature_view.""" + + def test_no_promote_saves_version_without_updating_active( + self, registry, make_fv, entity + ): + """Apply v0, then schema change with no_promote=True. + Version record for v1 should exist, but active FV keeps v0's schema.""" + fv0 = make_fv(description="original v0") + registry.apply_feature_view(fv0, "test_project", commit=True) + + # Schema change with no_promote + fv1 = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + Field(name="new_feature", dtype=Float32), # Schema change + ], + description="staged v1", + ) + registry.apply_feature_view(fv1, "test_project", commit=True, no_promote=True) + + # Version v1 should exist in history + versions = registry.list_feature_view_versions("driver_stats", "test_project") + assert len(versions) == 2 + assert versions[0]["version_number"] == 0 + assert versions[1]["version_number"] == 1 + + # Active FV should still be v0 (initial apply with version="latest" + # has current_version_number=None since proto 0 maps to None for latest) + active = registry.get_feature_view("driver_stats", "test_project") + assert active.current_version_number is None + assert active.description == "original v0" + # v0 schema has 3 fields (driver_id, trips_today, avg_rating) + feature_names = {f.name for f in active.schema} + assert "new_feature" not in feature_names + + def test_no_promote_then_regular_apply_promotes(self, registry, make_fv, entity): + """Apply with no_promote, then re-apply the same schema change without + no_promote. The new version should now be promoted to active.""" + fv0 = make_fv(description="original") + registry.apply_feature_view(fv0, "test_project", commit=True) + + # Schema change with no_promote + fv1_schema = [ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + Field(name="extra", dtype=Float32), + ] + fv1 = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=fv1_schema, + description="staged v1", + ) + registry.apply_feature_view(fv1, "test_project", commit=True, no_promote=True) + + # Now apply same schema change without no_promote + fv1_promote = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=fv1_schema, + description="promoted v1", + ) + registry.apply_feature_view( + fv1_promote, "test_project", commit=True, no_promote=False + ) + + # Active FV should now have the new schema + active = registry.get_feature_view("driver_stats", "test_project") + feature_names = {f.name for f in active.schema} + assert "extra" in feature_names + + def test_no_promote_then_explicit_pin_promotes(self, registry, make_fv, entity): + """Apply with no_promote, then pin to v1. Active should now be v1.""" + fv0 = make_fv(description="original") + registry.apply_feature_view(fv0, "test_project", commit=True) + + # Schema change with no_promote + fv1 = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + Field(name="pinned_feature", dtype=Float32), + ], + description="staged v1", + ) + registry.apply_feature_view(fv1, "test_project", commit=True, no_promote=True) + + # Active is still v0 (initial apply with version="latest" + # has current_version_number=None since proto 0 maps to None for latest) + active = registry.get_feature_view("driver_stats", "test_project") + assert active.current_version_number is None + + # Pin to v1 (user's definition must match current active, only version changes) + fv_pin = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + ], + description="original", + version="v1", + ) + registry.apply_feature_view(fv_pin, "test_project", commit=True) + + # Active should now be v1's snapshot + active = registry.get_feature_view("driver_stats", "test_project") + assert active.current_version_number == 1 + feature_names = {f.name for f in active.schema} + assert "pinned_feature" in feature_names + + def test_no_promote_noop_without_schema_change(self, registry, make_fv): + """Apply with no_promote but no schema change — metadata-only update, + no new version should be created.""" + fv0 = make_fv(description="original") + registry.apply_feature_view(fv0, "test_project", commit=True) + + # Same schema, different description (metadata-only) + fv_same = make_fv(description="updated description only") + registry.apply_feature_view( + fv_same, "test_project", commit=True, no_promote=True + ) + + # Still only v0 + versions = registry.list_feature_view_versions("driver_stats", "test_project") + assert len(versions) == 1 + assert versions[0]["version_number"] == 0 + + def test_no_promote_version_accessible_by_explicit_ref( + self, registry, make_fv, entity + ): + """After no_promote apply, the new version should be accessible via + get_feature_view_by_version().""" + fv0 = make_fv(description="original") + registry.apply_feature_view(fv0, "test_project", commit=True) + + # Schema change with no_promote + fv1 = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + Field(name="avg_rating", dtype=Float32), + Field(name="explicit_feature", dtype=Float32), + ], + description="staged v1", + ) + registry.apply_feature_view(fv1, "test_project", commit=True, no_promote=True) + + # Should be accessible by explicit version ref + v1_fv = registry.get_feature_view_by_version("driver_stats", "test_project", 1) + assert v1_fv.current_version_number == 1 + feature_names = {f.name for f in v1_fv.schema} + assert "explicit_feature" in feature_names + + # v0 should also still be accessible + v0_fv = registry.get_feature_view_by_version("driver_stats", "test_project", 0) + assert v0_fv.current_version_number == 0 + feature_names_v0 = {f.name for f in v0_fv.schema} + assert "explicit_feature" not in feature_names_v0 + + +class TestFeatureViewNameValidation: + """Tests that feature view names with reserved characters are rejected on apply.""" + + def test_apply_feature_view_with_at_sign_raises(self, registry, entity): + """Applying a feature view with '@' in its name should raise ValueError.""" + fv = FeatureView( + name="my_weirdly_@_named_fv", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + ], + ) + with pytest.raises(ValueError, match="must not contain '@'"): + registry.apply_feature_view(fv, "test_project", commit=True) + + def test_apply_feature_view_with_colon_raises(self, registry, entity): + """Applying a feature view with ':' in its name should raise ValueError.""" + fv = FeatureView( + name="my:weird:fv", + entities=[entity], + ttl=timedelta(days=1), + schema=[ + Field(name="driver_id", dtype=Int64), + Field(name="trips_today", dtype=Int64), + ], + ) + with pytest.raises(ValueError, match="must not contain ':'"): + registry.apply_feature_view(fv, "test_project", commit=True) diff --git a/sdk/python/tests/integration/rest_api/conftest.py b/sdk/python/tests/integration/rest_api/conftest.py new file mode 100644 index 00000000000..d7aa0b4a3c5 --- /dev/null +++ b/sdk/python/tests/integration/rest_api/conftest.py @@ -0,0 +1,182 @@ +import os +import time +from pathlib import Path + +import pytest +import requests +from kubernetes import client, config + +from tests.integration.rest_api.support import ( + applyFeastProject, + create_feast_project, + create_namespace, + create_route, + delete_namespace, + deploy_and_validate_pod, + execPodCommand, + get_pod_name_by_prefix, + run_kubectl_command, + validate_feature_store_cr_status, +) + + +class FeastRestClient: + def __init__(self, base_url): + self.base_url = base_url.rstrip("/") + self.api_prefix = "/api/v1" + + def _build_url(self, endpoint): + if not endpoint.startswith("/"): + endpoint = "/" + endpoint + return f"{self.base_url}{self.api_prefix}{endpoint}" + + def get(self, endpoint, params=None): + params = params or {} + params.setdefault("allow_cache", "false") + url = self._build_url(endpoint) + return requests.get(url, params=params, verify=False) + + +def _wait_for_http_ready( + route_url: str, + timeout: int = 300, + interval: int = 5, + initial_delay: int = 30, +) -> None: + """ + Poll the HTTP endpoint until it returns a non-502 response. + + After Pod/CR readiness is confirmed, the backend behind the ingress may + still be initializing. This helper avoids the race condition where tests + start before the Feast server is ready, causing all requests to return 502. + """ + health_url = f"{route_url}/api/v1/projects" + last_status = None + + if initial_delay > 0: + print( + f"\n Waiting {initial_delay}s for backend to start after apply/dataset creation..." + ) + time.sleep(initial_delay) + + deadline = time.time() + timeout + print( + f"\n Waiting for HTTP endpoint to become ready (timeout={timeout}s): {health_url}" + ) + + while time.time() < deadline: + try: + resp = requests.get(health_url, timeout=10, verify=False) + last_status = resp.status_code + if resp.status_code != 502: + print(f" HTTP endpoint is ready (status={resp.status_code})") + return + print( + f" HTTP endpoint returned {resp.status_code}, retrying in {interval}s..." + ) + except requests.exceptions.RequestException as exc: + last_status = str(exc) + print(f" HTTP request failed ({exc}), retrying in {interval}s...") + + time.sleep(interval) + + raise RuntimeError( + f"HTTP endpoint {health_url} did not become ready within {timeout}s " + f"(last status: {last_status})" + ) + + +@pytest.fixture(scope="session") +def feast_rest_client(): + # Load kubeconfig and initialize Kubernetes client + config.load_kube_config() + api_instance = client.CoreV1Api() + + # Get the directory containing this conftest.py file + test_dir = Path(__file__).parent + resource_dir = test_dir / "resource" + + # Constants and environment values + namespace = "test-ns-feast-rest" + credit_scoring = "credit-scoring" + driver_ranking = "driver-ranking" + # Registry REST service name created by the operator for credit-scoring (kind and OpenShift) + registry_rest_service = "feast-credit-scoring-registry-rest" + run_on_openshift = os.getenv("RUN_ON_OPENSHIFT_CI", "false").lower() == "true" + + # Create test namespace + create_namespace(api_instance, namespace) + + try: + # Deploy dependencies (same for kind and OpenShift) + deploy_and_validate_pod( + namespace, str(resource_dir / "redis.yaml"), "app=redis" + ) + deploy_and_validate_pod( + namespace, str(resource_dir / "postgres.yaml"), "app=postgres" + ) + + # Create and validate FeatureStore CRs (SQL registry, same as kind) + create_feast_project( + str(resource_dir / "feast_config_credit_scoring.yaml"), + namespace, + credit_scoring, + ) + validate_feature_store_cr_status(namespace, credit_scoring) + + create_feast_project( + str(resource_dir / "feast_config_driver_ranking.yaml"), + namespace, + driver_ranking, + ) + validate_feature_store_cr_status(namespace, driver_ranking) + + if run_on_openshift: + # OpenShift: expose registry REST via route (no nginx ingress) + route_url = create_route(namespace, credit_scoring, registry_rest_service) + else: + # Kind: deploy nginx ingress and get route URL + run_kubectl_command( + [ + "apply", + "-f", + str(resource_dir / "feast-registry-nginx.yaml"), + "-n", + namespace, + ] + ) + ingress_host = run_kubectl_command( + [ + "get", + "ingress", + "feast-registry-ingress", + "-n", + namespace, + "-o", + "jsonpath={.spec.rules[0].host}", + ] + ) + route_url = f"http://{ingress_host}" + + # Apply feast projects + applyFeastProject(namespace, credit_scoring) + applyFeastProject(namespace, driver_ranking) + + # Create Saved Datasets and Permissions + pod_name = get_pod_name_by_prefix(namespace, credit_scoring) + execPodCommand(namespace, pod_name, ["python", "create_ui_visible_datasets.py"]) + execPodCommand(namespace, pod_name, ["python", "permissions_apply.py"]) + if not route_url: + raise RuntimeError("Route URL could not be fetched.") + + # Wait for the HTTP endpoint to become ready before running tests. + # Pod/CR readiness does not guarantee the backend is serving traffic; + # the ingress may return 502 while the Feast server is still starting. + _wait_for_http_ready(route_url) + + print(f"\n Connected to Feast REST at: {route_url}") + yield FeastRestClient(route_url) + + finally: + print(f"\n Deleting namespace: {namespace}") + delete_namespace(api_instance, namespace) diff --git a/sdk/python/tests/integration/registration/rest_api/resource/feast-registry-nginx.yaml b/sdk/python/tests/integration/rest_api/resource/feast-registry-nginx.yaml similarity index 100% rename from sdk/python/tests/integration/registration/rest_api/resource/feast-registry-nginx.yaml rename to sdk/python/tests/integration/rest_api/resource/feast-registry-nginx.yaml diff --git a/sdk/python/tests/integration/registration/rest_api/resource/feast_config_credit_scoring.yaml b/sdk/python/tests/integration/rest_api/resource/feast_config_credit_scoring.yaml similarity index 100% rename from sdk/python/tests/integration/registration/rest_api/resource/feast_config_credit_scoring.yaml rename to sdk/python/tests/integration/rest_api/resource/feast_config_credit_scoring.yaml diff --git a/sdk/python/tests/integration/registration/rest_api/resource/feast_config_driver_ranking.yaml b/sdk/python/tests/integration/rest_api/resource/feast_config_driver_ranking.yaml similarity index 100% rename from sdk/python/tests/integration/registration/rest_api/resource/feast_config_driver_ranking.yaml rename to sdk/python/tests/integration/rest_api/resource/feast_config_driver_ranking.yaml diff --git a/sdk/python/tests/integration/registration/rest_api/resource/feast_config_rhoai.yaml b/sdk/python/tests/integration/rest_api/resource/feast_config_rhoai.yaml similarity index 100% rename from sdk/python/tests/integration/registration/rest_api/resource/feast_config_rhoai.yaml rename to sdk/python/tests/integration/rest_api/resource/feast_config_rhoai.yaml diff --git a/sdk/python/tests/integration/registration/rest_api/resource/postgres.yaml b/sdk/python/tests/integration/rest_api/resource/postgres.yaml similarity index 92% rename from sdk/python/tests/integration/registration/rest_api/resource/postgres.yaml rename to sdk/python/tests/integration/rest_api/resource/postgres.yaml index ca0de81d15c..34ac2eb620b 100644 --- a/sdk/python/tests/integration/registration/rest_api/resource/postgres.yaml +++ b/sdk/python/tests/integration/rest_api/resource/postgres.yaml @@ -25,7 +25,7 @@ spec: spec: containers: - name: postgres - image: 'postgres:16-alpine' + image: 'quay.io/feastdev-ci/feast-test-images:postgres-17-alpine' ports: - containerPort: 5432 envFrom: diff --git a/sdk/python/tests/integration/registration/rest_api/resource/redis.yaml b/sdk/python/tests/integration/rest_api/resource/redis.yaml similarity index 89% rename from sdk/python/tests/integration/registration/rest_api/resource/redis.yaml rename to sdk/python/tests/integration/rest_api/resource/redis.yaml index 297205b8a79..8701cf7fcdd 100644 --- a/sdk/python/tests/integration/registration/rest_api/resource/redis.yaml +++ b/sdk/python/tests/integration/rest_api/resource/redis.yaml @@ -15,7 +15,7 @@ spec: spec: containers: - name: redis - image: 'quay.io/sclorg/redis-7-c9s' + image: 'quay.io/feastdev-ci/feast-test-images:redis-7-alpine' ports: - containerPort: 6379 env: diff --git a/sdk/python/tests/integration/registration/rest_api/support.py b/sdk/python/tests/integration/rest_api/support.py similarity index 100% rename from sdk/python/tests/integration/registration/rest_api/support.py rename to sdk/python/tests/integration/rest_api/support.py diff --git a/sdk/python/tests/integration/registration/rest_api/test_registry_rest_api.py b/sdk/python/tests/integration/rest_api/test_registry_rest_api.py similarity index 100% rename from sdk/python/tests/integration/registration/rest_api/test_registry_rest_api.py rename to sdk/python/tests/integration/rest_api/test_registry_rest_api.py diff --git a/sdk/python/tests/integration/test_mcp_feature_server.py b/sdk/python/tests/integration/test_mcp_feature_server.py index 6920c2e3f2a..0e59a71dfae 100644 --- a/sdk/python/tests/integration/test_mcp_feature_server.py +++ b/sdk/python/tests/integration/test_mcp_feature_server.py @@ -4,6 +4,7 @@ import pytest from fastapi import FastAPI from fastapi.testclient import TestClient +from pydantic import ValidationError from feast.feature_store import FeatureStore from feast.infra.mcp_servers.mcp_config import McpFeatureServerConfig @@ -49,7 +50,7 @@ def test_mcp_server_functionality_with_mock_store(self): mcp_server_version="1.0.0", ) - mock_mcp_instance = Mock() + mock_mcp_instance = Mock(spec_set=["mount_sse", "mount_http", "mount"]) mock_fast_api_mcp.return_value = mock_mcp_instance result = add_mcp_support_to_app(mock_app, mock_store, config) @@ -58,7 +59,7 @@ def test_mcp_server_functionality_with_mock_store(self): self.assertIsNotNone(result) self.assertEqual(result, mock_mcp_instance) mock_fast_api_mcp.assert_called_once() - mock_mcp_instance.mount.assert_called_once() + mock_mcp_instance.mount_sse.assert_called_once() @patch("feast.infra.mcp_servers.mcp_server.MCP_AVAILABLE", True) @patch("feast.infra.mcp_servers.mcp_server.FastApiMCP") @@ -77,7 +78,7 @@ def test_complete_mcp_setup_flow(self, mock_fast_api_mcp): transformation_service_endpoint="localhost:6566", ) - mock_mcp_instance = Mock() + mock_mcp_instance = Mock(spec_set=["mount_sse", "mount_http", "mount"]) mock_fast_api_mcp.return_value = mock_mcp_instance # Execute the flow @@ -90,7 +91,7 @@ def test_complete_mcp_setup_flow(self, mock_fast_api_mcp): name="e2e-test-server", description="Feast Feature Store MCP Server - Access feature store data and operations through MCP", ) - mock_mcp_instance.mount.assert_called_once() + mock_mcp_instance.mount_sse.assert_called_once() self.assertEqual(result, mock_mcp_instance) @pytest.mark.skipif( @@ -160,36 +161,29 @@ def test_feature_server_with_mcp_config(self): def test_mcp_server_configuration_validation(self): """Test comprehensive MCP server configuration validation.""" # Test various configuration combinations - test_configs = [ - { - "enabled": True, - "mcp_enabled": True, - "mcp_server_name": "test-server-1", - "mcp_server_version": "1.0.0", - "mcp_transport": "sse", - }, - { - "enabled": True, - "mcp_enabled": True, - "mcp_server_name": "test-server-2", - "mcp_server_version": "2.0.0", - "mcp_transport": "websocket", - }, - { - "enabled": False, - "mcp_enabled": False, - "mcp_server_name": "disabled-server", - "mcp_server_version": "1.0.0", - "mcp_transport": None, - }, - ] - - for config_dict in test_configs: - config = McpFeatureServerConfig(**config_dict) - self.assertEqual(config.enabled, config_dict["enabled"]) - self.assertEqual(config.mcp_enabled, config_dict["mcp_enabled"]) - self.assertEqual(config.mcp_server_name, config_dict["mcp_server_name"]) - self.assertEqual( - config.mcp_server_version, config_dict["mcp_server_version"] + for transport in ["sse", "http"]: + config = McpFeatureServerConfig( + enabled=True, + mcp_enabled=True, + mcp_server_name="test-server", + mcp_server_version="1.0.0", + mcp_transport=transport, + ) + self.assertEqual(config.mcp_transport, transport) + + config_default = McpFeatureServerConfig( + enabled=True, + mcp_enabled=True, + mcp_server_name="test-server-default", + mcp_server_version="1.0.0", + ) + self.assertEqual(config_default.mcp_transport, "sse") + + with self.assertRaises(ValidationError): + McpFeatureServerConfig( + enabled=True, + mcp_enabled=True, + mcp_server_name="bad-transport", + mcp_server_version="1.0.0", + mcp_transport="websocket", ) - self.assertEqual(config.mcp_transport, config_dict["mcp_transport"]) diff --git a/sdk/python/tests/unit/api/test_api_rest_registry.py b/sdk/python/tests/unit/api/test_api_rest_registry.py index afba602ddac..3e6cb5e7e3d 100644 --- a/sdk/python/tests/unit/api/test_api_rest_registry.py +++ b/sdk/python/tests/unit/api/test_api_rest_registry.py @@ -1503,11 +1503,50 @@ def test_metrics_resource_counts_via_rest(fastapi_test_app): assert "featureViews" in counts assert "featureServices" in counts - # Verify counts are integers for key, value in counts.items(): assert isinstance(value, int) assert value >= 0 + # Verify feature services summaries + assert "featureServices" in data + assert isinstance(data["featureServices"], list) + assert len(data["featureServices"]) == counts["featureServices"] + for fs in data["featureServices"]: + assert "name" in fs + assert "project" in fs + assert fs["project"] == "demo_project" + service_names = [fs["name"] for fs in data["featureServices"]] + assert "user_service" in service_names + + # Verify feature views summaries with detail + assert "featureViews" in data + assert isinstance(data["featureViews"], list) + assert len(data["featureViews"]) == counts["featureViews"] + for fv in data["featureViews"]: + assert "name" in fv + assert "project" in fv + assert "type" in fv + assert "featureCount" in fv + assert isinstance(fv["featureCount"], int) + assert fv["featureCount"] >= 0 + assert fv["project"] == "demo_project" + fv_names = [fv["name"] for fv in data["featureViews"]] + assert "user_profile" in fv_names + user_profile_fv = next( + fv for fv in data["featureViews"] if fv["name"] == "user_profile" + ) + assert user_profile_fv["featureCount"] == 2 + + # Verify projects list + assert "projects" in data + assert isinstance(data["projects"], list) + assert len(data["projects"]) == 1 + assert data["projects"][0]["name"] == "demo_project" + + # Verify registry last updated + assert "registryLastUpdated" in data + assert data["registryLastUpdated"] is not None + # Test without project parameter (should return all projects) response = fastapi_test_app.get("/metrics/resource_counts") assert response.status_code == 200 @@ -1527,6 +1566,116 @@ def test_metrics_resource_counts_via_rest(fastapi_test_app): assert "demo_project" in per_project assert isinstance(per_project["demo_project"], dict) + # Verify metadata in all-projects mode + assert "featureServices" in data + assert isinstance(data["featureServices"], list) + + assert "featureViews" in data + assert isinstance(data["featureViews"], list) + for fv in data["featureViews"]: + assert "name" in fv + assert "project" in fv + assert "type" in fv + assert "featureCount" in fv + + assert "projects" in data + assert isinstance(data["projects"], list) + assert len(data["projects"]) >= 1 + for proj in data["projects"]: + assert "name" in proj + assert "description" in proj + + assert "registryLastUpdated" in data + assert data["registryLastUpdated"] is not None + + +def test_metrics_resource_counts_with_permission_errors(fastapi_test_app): + """ + Test that /metrics/resource_counts returns 200 with zero counts for + resource types that raise FeastPermissionError, instead of failing + the entire request. This simulates the scenario where access is + restricted for some resource types via GroupBasedPolicy, + NamespaceBasedPolicy, or CombinedGroupNamespacePolicy. + """ + from unittest.mock import patch + + from feast.errors import FeastPermissionError + + original_get = fastapi_test_app.get + + # First, get the baseline counts to know which resources have data + baseline = original_get("/metrics/resource_counts?project=demo_project").json() + baseline_counts = baseline["counts"] + + # Patch grpc_call to raise FeastPermissionError for entities and data sources + # while allowing other resource types to succeed + original_grpc_call = None + + def grpc_call_entities_denied(handler_fn, request): + handler_name = getattr(handler_fn, "__name__", "") + if handler_name in ("ListEntities", "ListDataSources"): + raise FeastPermissionError(f"Permission denied for {handler_name}") + return original_grpc_call(handler_fn, request) + + with patch("feast.api.registry.rest.metrics.grpc_call") as mock_grpc_call: + import feast.api.registry.rest.metrics as metrics_module + + original_grpc_call = metrics_module.__dict__.get("grpc_call") + # Restore actual import since patch replaces it + from feast.api.registry.rest.rest_utils import grpc_call as real_grpc_call + + original_grpc_call = real_grpc_call + mock_grpc_call.side_effect = grpc_call_entities_denied + + response = fastapi_test_app.get("/metrics/resource_counts?project=demo_project") + + assert response.status_code == 200, ( + f"Expected 200 but got {response.status_code}: {response.text}" + ) + data = response.json() + assert "counts" in data + counts = data["counts"] + + # Denied resource types should have 0 counts + assert counts["entities"] == 0 + assert counts["dataSources"] == 0 + + # Permitted resource types should still have their original counts + assert counts["featureViews"] == baseline_counts["featureViews"] + assert counts["featureServices"] == baseline_counts["featureServices"] + assert counts["features"] == baseline_counts["features"] + assert counts["savedDatasets"] == baseline_counts["savedDatasets"] + + # Permitted metadata summaries should still be populated + assert len(data["featureViews"]) == baseline_counts["featureViews"] + assert len(data["featureServices"]) == baseline_counts["featureServices"] + + # Now test with ALL resource types denied + def grpc_call_all_denied(handler_fn, request): + handler_name = getattr(handler_fn, "__name__", "") + if handler_name.startswith("List") and handler_name != "ListProjects": + raise FeastPermissionError(f"Permission denied for {handler_name}") + return real_grpc_call(handler_fn, request) + + with patch("feast.api.registry.rest.metrics.grpc_call") as mock_grpc_call: + mock_grpc_call.side_effect = grpc_call_all_denied + + response = fastapi_test_app.get("/metrics/resource_counts?project=demo_project") + + assert response.status_code == 200 + data = response.json() + counts = data["counts"] + + # All counts should be 0 when all resource types are denied + for resource_type, count in counts.items(): + assert count == 0, ( + f"Expected 0 for {resource_type} when permission denied, got {count}" + ) + + # Metadata summaries should be empty when all permissions are denied + assert data["featureViews"] == [] + assert data["featureServices"] == [] + def test_feature_views_all_types_and_resource_counts_match(fastapi_test_app): """ @@ -1851,3 +2000,19 @@ def test_all_endpoints_return_404_for_invalid_objects(fastapi_test_app): data = response.json() assert data["status_code"] == 404 assert data["error_type"] == "FeastObjectNotFoundException" + + +def test_metrics_resource_counts_nonexistent_project(fastapi_test_app): + """Test /metrics/resource_counts with a non-existent project returns empty data.""" + response = fastapi_test_app.get( + "/metrics/resource_counts?project=nonexistent_project" + ) + assert response.status_code == 200 + data = response.json() + + counts = data["counts"] + for value in counts.values(): + assert value == 0 + assert data["featureServices"] == [] + assert data["featureViews"] == [] + assert "registryLastUpdated" in data diff --git a/sdk/python/tests/unit/cli/test_cli_apply_duplicates.py b/sdk/python/tests/unit/cli/test_cli_apply_duplicates.py index b3e350fe73c..cf5b64dbd20 100644 --- a/sdk/python/tests/unit/cli/test_cli_apply_duplicates.py +++ b/sdk/python/tests/unit/cli/test_cli_apply_duplicates.py @@ -8,7 +8,7 @@ def test_cli_apply_duplicated_featureview_names() -> None: run_simple_apply_test( example_repo_file_name="example_feature_repo_with_duplicated_featureview_names.py", - expected_error=b"Please ensure that all feature view names are case-insensitively unique", + expected_error=b"Feature view names must be case-insensitively unique", ) @@ -152,9 +152,7 @@ def test_cli_apply_imported_featureview_with_duplication() -> None: rc, output = runner.run_with_output(["apply"], cwd=repo_path) assert rc != 0 - assert ( - b"More than one feature view with name driver_hourly_stats found." in output - ) + assert b"Multiple FeatureViews with name 'driver_hourly_stats' found." in output def test_cli_apply_duplicated_featureview_names_multiple_py_files() -> None: @@ -195,6 +193,5 @@ def test_cli_apply_duplicated_featureview_names_multiple_py_files() -> None: assert ( rc != 0 - and b"Please ensure that all feature view names are case-insensitively unique" - in output + and b"Feature view names must be case-insensitively unique" in output ) diff --git a/sdk/python/tests/unit/infra/compute_engines/ray_compute/__init__.py b/sdk/python/tests/unit/infra/compute_engines/ray_compute/__init__.py deleted file mode 100644 index 2734c36c704..00000000000 --- a/sdk/python/tests/unit/infra/compute_engines/ray_compute/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Ray compute engine unit tests.""" diff --git a/sdk/python/tests/unit/infra/compute_engines/test_backend_factory.py b/sdk/python/tests/unit/infra/compute_engines/test_backend_factory.py new file mode 100644 index 00000000000..ee0ebf1e8ec --- /dev/null +++ b/sdk/python/tests/unit/infra/compute_engines/test_backend_factory.py @@ -0,0 +1,55 @@ +from unittest.mock import MagicMock, patch + +import pandas as pd +import pyarrow +import pytest + +from feast.infra.compute_engines.backends.factory import BackendFactory +from feast.infra.compute_engines.backends.pandas_backend import PandasBackend + + +class TestBackendFactoryFromName: + def test_pandas_backend(self): + backend = BackendFactory.from_name("pandas") + assert isinstance(backend, PandasBackend) + + @patch( + "feast.infra.compute_engines.backends.factory.BackendFactory._get_polars_backend" + ) + def test_polars_backend(self, mock_get_polars): + mock_backend = MagicMock() + mock_get_polars.return_value = mock_backend + + result = BackendFactory.from_name("polars") + assert result is mock_backend + + def test_unsupported_name_raises(self): + with pytest.raises(ValueError, match="Unsupported backend name"): + BackendFactory.from_name("dask") + + +class TestBackendFactoryInferFromEntityDf: + def test_pandas_dataframe_returns_pandas_backend(self): + """A non-empty pandas DataFrame is detected via isinstance check.""" + df = pd.DataFrame({"a": [1, 2]}) + backend = BackendFactory.infer_from_entity_df(df) + assert isinstance(backend, PandasBackend) + + def test_empty_pandas_dataframe_returns_pandas_backend(self): + """An empty pandas DataFrame returns PandasBackend.""" + df = pd.DataFrame() + backend = BackendFactory.infer_from_entity_df(df) + assert isinstance(backend, PandasBackend) + + def test_pyarrow_table(self): + table = pyarrow.table({"a": [1, 2]}) + backend = BackendFactory.infer_from_entity_df(table) + assert isinstance(backend, PandasBackend) + + def test_none_input(self): + backend = BackendFactory.infer_from_entity_df(None) + assert isinstance(backend, PandasBackend) + + def test_empty_string_input(self): + backend = BackendFactory.infer_from_entity_df("") + assert isinstance(backend, PandasBackend) diff --git a/sdk/python/tests/unit/infra/compute_engines/test_local_compute_engine.py b/sdk/python/tests/unit/infra/compute_engines/test_local_compute_engine.py new file mode 100644 index 00000000000..3396a45c995 --- /dev/null +++ b/sdk/python/tests/unit/infra/compute_engines/test_local_compute_engine.py @@ -0,0 +1,67 @@ +from unittest.mock import MagicMock + +from feast.infra.compute_engines.base import ComputeEngine +from feast.infra.compute_engines.local.compute import ( + LocalComputeEngine, + LocalComputeEngineConfig, +) + + +class TestLocalComputeEngineConfig: + def test_default_type(self): + config = LocalComputeEngineConfig() + assert config.type == "local" + + def test_default_backend_none(self): + config = LocalComputeEngineConfig() + assert config.backend is None + + def test_custom_backend(self): + config = LocalComputeEngineConfig(backend="polars") + assert config.backend == "polars" + + +class TestLocalComputeEngine: + def _make_engine(self): + return LocalComputeEngine( + repo_config=MagicMock(), + offline_store=MagicMock(), + online_store=MagicMock(), + ) + + def test_is_compute_engine(self): + engine = self._make_engine() + assert isinstance(engine, ComputeEngine) + + def test_update_is_noop(self): + engine = self._make_engine() + # Should not raise + engine.update( + project="test", + views_to_delete=[], + views_to_keep=[], + entities_to_delete=[], + entities_to_keep=[], + ) + + def test_teardown_is_noop(self): + engine = self._make_engine() + # Should not raise + engine.teardown_infra( + project="test", + fvs=[], + entities=[], + ) + + def test_stores_config(self): + repo_config = MagicMock() + offline = MagicMock() + online = MagicMock() + engine = LocalComputeEngine( + repo_config=repo_config, + offline_store=offline, + online_store=online, + ) + assert engine.repo_config is repo_config + assert engine.offline_store is offline + assert engine.online_store is online diff --git a/sdk/python/tests/unit/infra/compute_engines/test_local_job.py b/sdk/python/tests/unit/infra/compute_engines/test_local_job.py new file mode 100644 index 00000000000..2f4a1ac48fd --- /dev/null +++ b/sdk/python/tests/unit/infra/compute_engines/test_local_job.py @@ -0,0 +1,100 @@ +from unittest.mock import MagicMock + +import pytest + +from feast.infra.common.materialization_job import MaterializationJobStatus +from feast.infra.compute_engines.local.job import ( + LocalMaterializationJob, + LocalRetrievalJob, +) + + +class TestLocalMaterializationJob: + def test_status(self): + job = LocalMaterializationJob( + job_id="test-job-1", + status=MaterializationJobStatus.SUCCEEDED, + ) + assert job.status() == MaterializationJobStatus.SUCCEEDED + + def test_job_id(self): + job = LocalMaterializationJob( + job_id="test-job-1", + status=MaterializationJobStatus.RUNNING, + ) + assert job.job_id() == "test-job-1" + + def test_error_none_by_default(self): + job = LocalMaterializationJob( + job_id="test-job-1", + status=MaterializationJobStatus.SUCCEEDED, + ) + assert job.error() is None + + def test_error_stored(self): + err = RuntimeError("something failed") + job = LocalMaterializationJob( + job_id="test-job-1", + status=MaterializationJobStatus.ERROR, + error=err, + ) + assert job.error() is err + + def test_should_not_be_retried(self): + job = LocalMaterializationJob( + job_id="test-job-1", + status=MaterializationJobStatus.ERROR, + ) + assert job.should_be_retried() is False + + def test_url_is_none(self): + job = LocalMaterializationJob( + job_id="test-job-1", + status=MaterializationJobStatus.SUCCEEDED, + ) + assert job.url() is None + + +class TestLocalRetrievalJob: + def test_full_feature_names(self): + job = LocalRetrievalJob( + plan=None, + context=MagicMock(), + full_feature_names=True, + ) + assert job.full_feature_names is True + + def test_full_feature_names_false(self): + job = LocalRetrievalJob( + plan=None, + context=MagicMock(), + full_feature_names=False, + ) + assert job.full_feature_names is False + + def test_error_none_by_default(self): + job = LocalRetrievalJob(plan=None, context=MagicMock()) + assert job.error() is None + + def test_error_stored(self): + err = ValueError("bad data") + job = LocalRetrievalJob(plan=None, context=MagicMock(), error=err) + assert job.error() is err + + def test_on_demand_feature_views_default_empty(self): + job = LocalRetrievalJob(plan=None, context=MagicMock()) + assert job.on_demand_feature_views == [] + + def test_metadata_default_none(self): + job = LocalRetrievalJob(plan=None, context=MagicMock()) + assert job.metadata is None + + def test_to_remote_storage_raises(self): + job = LocalRetrievalJob(plan=None, context=MagicMock()) + with pytest.raises(NotImplementedError, match="Remote storage"): + job.to_remote_storage() + + def test_to_sql_raises(self): + job = LocalRetrievalJob(plan=None, context=MagicMock()) + with pytest.raises(NotImplementedError, match="SQL generation"): + job.to_sql() diff --git a/sdk/python/tests/unit/infra/compute_engines/test_materialization_job.py b/sdk/python/tests/unit/infra/compute_engines/test_materialization_job.py new file mode 100644 index 00000000000..8d6ab4f2288 --- /dev/null +++ b/sdk/python/tests/unit/infra/compute_engines/test_materialization_job.py @@ -0,0 +1,59 @@ +from datetime import datetime +from unittest.mock import MagicMock + +from feast.infra.common.materialization_job import ( + MaterializationJobStatus, + MaterializationTask, +) + + +class TestMaterializationJobStatus: + def test_all_statuses_defined(self): + expected = { + "WAITING", + "RUNNING", + "AVAILABLE", + "ERROR", + "CANCELLING", + "CANCELLED", + "SUCCEEDED", + "PAUSED", + "RETRYING", + } + actual = {s.name for s in MaterializationJobStatus} + assert actual == expected + + +class TestMaterializationTask: + def test_creation(self): + mock_fv = MagicMock() + task = MaterializationTask( + project="my_project", + feature_view=mock_fv, + start_time=datetime(2024, 1, 1), + end_time=datetime(2024, 1, 2), + ) + assert task.project == "my_project" + assert task.feature_view is mock_fv + assert task.start_time == datetime(2024, 1, 1) + assert task.end_time == datetime(2024, 1, 2) + + def test_default_only_latest(self): + mock_fv = MagicMock() + task = MaterializationTask( + project="p", + feature_view=mock_fv, + start_time=datetime(2024, 1, 1), + end_time=datetime(2024, 1, 2), + ) + assert task.only_latest is True + + def test_default_disable_event_timestamp(self): + mock_fv = MagicMock() + task = MaterializationTask( + project="p", + feature_view=mock_fv, + start_time=datetime(2024, 1, 1), + end_time=datetime(2024, 1, 2), + ) + assert task.disable_event_timestamp is False diff --git a/sdk/python/tests/unit/infra/compute_engines/test_topo_sort.py b/sdk/python/tests/unit/infra/compute_engines/test_topo_sort.py new file mode 100644 index 00000000000..5bec3f63734 --- /dev/null +++ b/sdk/python/tests/unit/infra/compute_engines/test_topo_sort.py @@ -0,0 +1,90 @@ +from unittest.mock import MagicMock + +from feast.infra.compute_engines.algorithms.topo import ( + topological_sort, + topological_sort_multiple, +) +from feast.infra.compute_engines.dag.node import DAGNode + + +def _make_node(name, inputs=None): + """Create a mock DAGNode.""" + node = MagicMock(spec=DAGNode) + node.name = name + node.inputs = inputs or [] + return node + + +class TestTopologicalSort: + def test_single_node(self): + root = _make_node("root") + result = topological_sort(root) + assert len(result) == 1 + assert result[0] is root + + def test_linear_chain(self): + """A -> B -> C should produce [A, B, C].""" + a = _make_node("A") + b = _make_node("B", inputs=[a]) + c = _make_node("C", inputs=[b]) + + result = topological_sort(c) + assert len(result) == 3 + # Dependencies must come before dependents + assert result.index(a) < result.index(b) + assert result.index(b) < result.index(c) + + def test_diamond_dependency(self): + """ + A → B + A → C + B,C → D + Should visit A before B and C, and B/C before D. + """ + a = _make_node("A") + b = _make_node("B", inputs=[a]) + c = _make_node("C", inputs=[a]) + d = _make_node("D", inputs=[b, c]) + + result = topological_sort(d) + assert len(result) == 4 + assert result.index(a) < result.index(b) + assert result.index(a) < result.index(c) + assert result.index(b) < result.index(d) + assert result.index(c) < result.index(d) + + def test_no_duplicates(self): + """Shared dependencies should appear only once.""" + shared = _make_node("shared") + b = _make_node("B", inputs=[shared]) + c = _make_node("C", inputs=[shared]) + root = _make_node("root", inputs=[b, c]) + + result = topological_sort(root) + assert result.count(shared) == 1 + + +class TestTopologicalSortMultiple: + def test_multiple_roots_no_overlap(self): + r1 = _make_node("root1") + r2 = _make_node("root2") + + result = topological_sort_multiple([r1, r2]) + assert len(result) == 2 + assert r1 in result + assert r2 in result + + def test_multiple_roots_with_shared_dep(self): + shared = _make_node("shared") + r1 = _make_node("root1", inputs=[shared]) + r2 = _make_node("root2", inputs=[shared]) + + result = topological_sort_multiple([r1, r2]) + assert len(result) == 3 + assert result.count(shared) == 1 + assert result.index(shared) < result.index(r1) + assert result.index(shared) < result.index(r2) + + def test_empty_roots(self): + result = topological_sort_multiple([]) + assert result == [] diff --git a/sdk/python/tests/unit/infra/feature_servers/test_mcp_server.py b/sdk/python/tests/unit/infra/feature_servers/test_mcp_server.py index f5748be1acc..b23372d9eab 100644 --- a/sdk/python/tests/unit/infra/feature_servers/test_mcp_server.py +++ b/sdk/python/tests/unit/infra/feature_servers/test_mcp_server.py @@ -1,6 +1,9 @@ import unittest +from types import SimpleNamespace from unittest.mock import Mock, patch +from pydantic import ValidationError + from feast.feature_store import FeatureStore from feast.infra.mcp_servers.mcp_config import McpFeatureServerConfig @@ -17,7 +20,7 @@ def test_default_config(self): self.assertFalse(config.mcp_enabled) self.assertEqual(config.mcp_server_name, "feast-mcp-server") self.assertEqual(config.mcp_server_version, "1.0.0") - self.assertIsNone(config.mcp_transport) + self.assertEqual(config.mcp_transport, "sse") self.assertEqual(config.transformation_service_endpoint, "localhost:6566") def test_custom_config(self): @@ -41,11 +44,11 @@ def test_custom_config(self): def test_config_validation(self): """Test configuration validation.""" - # Test valid transport options - valid_transports = ["sse", "websocket", None] - for transport in valid_transports: + for transport in ["sse", "http"]: config = McpFeatureServerConfig(mcp_transport=transport) self.assertEqual(config.mcp_transport, transport) + with self.assertRaises(ValidationError): + McpFeatureServerConfig(mcp_transport="websocket") def test_config_inheritance(self): """Test that McpFeatureServerConfig properly inherits from BaseFeatureServerConfig.""" @@ -66,12 +69,13 @@ def test_add_mcp_support_success(self, mock_fast_api_mcp): mock_app = Mock() mock_store = Mock(spec=FeatureStore) - mock_config = Mock() - mock_config.mcp_server_name = "test-server" - mock_config.mcp_server_version = "1.0.0" + mock_config = SimpleNamespace( + mcp_server_name="test-server", + mcp_server_version="1.0.0", + mcp_transport="sse", + ) - # Mock the FastApiMCP instance - mock_mcp_instance = Mock() + mock_mcp_instance = Mock(spec_set=["mount_sse", "mount", "mount_http"]) mock_fast_api_mcp.return_value = mock_mcp_instance result = add_mcp_support_to_app(mock_app, mock_store, mock_config) @@ -83,8 +87,7 @@ def test_add_mcp_support_success(self, mock_fast_api_mcp): description="Feast Feature Store MCP Server - Access feature store data and operations through MCP", ) - # Verify mount was called - mock_mcp_instance.mount.assert_called_once() + mock_mcp_instance.mount_sse.assert_called_once() # Verify the result self.assertEqual(result, mock_mcp_instance) @@ -96,11 +99,9 @@ def test_add_mcp_support_with_defaults(self, mock_fast_api_mcp): mock_app = Mock() mock_store = Mock(spec=FeatureStore) - mock_config = Mock() - # Don't set mcp_server_name to test default - del mock_config.mcp_server_name + mock_config = SimpleNamespace(mcp_transport="sse") - mock_mcp_instance = Mock() + mock_mcp_instance = Mock(spec_set=["mount_sse", "mount", "mount_http"]) mock_fast_api_mcp.return_value = mock_mcp_instance result = add_mcp_support_to_app(mock_app, mock_store, mock_config) @@ -114,6 +115,40 @@ def test_add_mcp_support_with_defaults(self, mock_fast_api_mcp): self.assertEqual(result, mock_mcp_instance) + @patch("feast.infra.mcp_servers.mcp_server.FastApiMCP") + def test_add_mcp_support_http_transport(self, mock_fast_api_mcp): + from feast.infra.mcp_servers.mcp_server import add_mcp_support_to_app + + mock_app = Mock() + mock_store = Mock(spec=FeatureStore) + mock_config = SimpleNamespace( + mcp_server_name="test-server", mcp_transport="http" + ) + + mock_mcp_instance = Mock(spec_set=["mount_http"]) + mock_fast_api_mcp.return_value = mock_mcp_instance + + result = add_mcp_support_to_app(mock_app, mock_store, mock_config) + mock_mcp_instance.mount_http.assert_called_once() + self.assertEqual(result, mock_mcp_instance) + + @patch("feast.infra.mcp_servers.mcp_server.FastApiMCP") + def test_add_mcp_support_http_missing_mount_http_fails(self, mock_fast_api_mcp): + from feast.infra.mcp_servers.mcp_server import ( + McpTransportNotSupportedError, + add_mcp_support_to_app, + ) + + mock_app = Mock() + mock_store = Mock(spec=FeatureStore) + mock_config = SimpleNamespace(mcp_transport="http") + + mock_mcp_instance = Mock(spec_set=["mount"]) + mock_fast_api_mcp.return_value = mock_mcp_instance + + with self.assertRaises(McpTransportNotSupportedError): + add_mcp_support_to_app(mock_app, mock_store, mock_config) + @patch("feast.infra.mcp_servers.mcp_server.FastApiMCP") @patch("feast.infra.mcp_servers.mcp_server.logger") def test_add_mcp_support_with_exception(self, mock_logger, mock_fast_api_mcp): @@ -122,8 +157,9 @@ def test_add_mcp_support_with_exception(self, mock_logger, mock_fast_api_mcp): mock_app = Mock() mock_store = Mock(spec=FeatureStore) - mock_config = Mock() - mock_config.mcp_server_name = "test-server" + mock_config = SimpleNamespace( + mcp_server_name="test-server", mcp_transport="sse" + ) # Mock FastApiMCP to raise an exception mock_fast_api_mcp.side_effect = Exception("MCP initialization failed") @@ -135,7 +171,8 @@ def test_add_mcp_support_with_exception(self, mock_logger, mock_fast_api_mcp): # Verify error was logged mock_logger.error.assert_called_once_with( - "Failed to initialize MCP integration: MCP initialization failed" + "Failed to initialize MCP integration: MCP initialization failed", + exc_info=True, ) @patch("feast.infra.mcp_servers.mcp_server.FastApiMCP") @@ -145,10 +182,11 @@ def test_add_mcp_support_mount_exception(self, mock_fast_api_mcp): mock_app = Mock() mock_store = Mock(spec=FeatureStore) - mock_config = Mock() - mock_config.mcp_server_name = "test-server" + mock_config = SimpleNamespace( + mcp_server_name="test-server", mcp_transport="sse" + ) - mock_mcp_instance = Mock() + mock_mcp_instance = Mock(spec_set=["mount"]) mock_mcp_instance.mount.side_effect = Exception("Mount failed") mock_fast_api_mcp.return_value = mock_mcp_instance @@ -203,3 +241,20 @@ def test_add_mcp_support_if_enabled_exception(self, mock_logger): mock_logger.error.assert_called_with( "Error checking/adding MCP support: Test error" ) + + @patch("feast.infra.mcp_servers.mcp_server.add_mcp_support_to_app") + def test_add_mcp_support_if_enabled_transport_not_supported_fails(self, mock_add): + from feast.feature_server import _add_mcp_support_if_enabled + from feast.infra.mcp_servers.mcp_server import McpTransportNotSupportedError + + mock_app = Mock() + mock_store = Mock() + mock_store.config.feature_server = Mock() + mock_store.config.feature_server.type = "mcp" + mock_store.config.feature_server.mcp_enabled = True + mock_store.config.feature_server.mcp_transport = "http" + + mock_add.side_effect = McpTransportNotSupportedError("bad") + + with self.assertRaises(McpTransportNotSupportedError): + _add_mcp_support_if_enabled(mock_app, mock_store) diff --git a/sdk/python/tests/unit/infra/offline_stores/contrib/postgres_offline_store/test_postgres.py b/sdk/python/tests/unit/infra/offline_stores/contrib/postgres_offline_store/test_postgres.py index fad837e4c16..0cb0d98eeae 100644 --- a/sdk/python/tests/unit/infra/offline_stores/contrib/postgres_offline_store/test_postgres.py +++ b/sdk/python/tests/unit/infra/offline_stores/contrib/postgres_offline_store/test_postgres.py @@ -615,6 +615,71 @@ def test_non_entity_mode_with_both_dates(self): assert "start_date" not in str(e) assert "end_date" not in str(e) + def test_non_entity_entity_df_uses_end_date(self): + """Test that the synthetic entity_df uses end_date, not start_date. + + Regression test: the old code used pd.date_range(start=start_date, ...)[:1] + which put start_date in the entity_df. Since PIT joins use + MAX(entity_timestamp) as the upper bound, start_date made end_date + unreachable. The fix uses [end_date] directly. + """ + test_repo_config = RepoConfig( + project="test_project", + registry="test_registry", + provider="local", + offline_store=_mock_offline_store_config(), + ) + + feature_view = _mock_feature_view("test_fv", ttl=timedelta(days=1)) + start_date = datetime(2023, 1, 1, tzinfo=timezone.utc) + end_date = datetime(2023, 1, 7, tzinfo=timezone.utc) + + mock_get_entity_schema = MagicMock( + return_value={"event_timestamp": "timestamp"} + ) + + with ( + patch.multiple( + "feast.infra.offline_stores.contrib.postgres_offline_store.postgres", + _get_conn=MagicMock(), + _upload_entity_df=MagicMock(), + _get_entity_schema=mock_get_entity_schema, + _get_entity_df_event_timestamp_range=MagicMock( + return_value=(start_date, end_date) + ), + ), + patch( + "feast.infra.offline_stores.contrib.postgres_offline_store.postgres.offline_utils.get_expected_join_keys", + return_value=[], + ), + patch( + "feast.infra.offline_stores.contrib.postgres_offline_store.postgres.offline_utils.assert_expected_columns_in_entity_df", + ), + patch( + "feast.infra.offline_stores.contrib.postgres_offline_store.postgres.offline_utils.get_feature_view_query_context", + return_value=[], + ), + ): + PostgreSQLOfflineStore.get_historical_features( + config=test_repo_config, + feature_views=[feature_view], + feature_refs=["test_fv:feature1"], + entity_df=None, + registry=MagicMock(), + project="test_project", + start_date=start_date, + end_date=end_date, + ) + + # _get_entity_schema is called with the synthetic entity_df + df = mock_get_entity_schema.call_args[0][0] + assert len(df) == 1 + ts = df["event_timestamp"].iloc[0] + # The entity_df must use end_date, not start_date + assert ts == end_date, ( + f"entity_df timestamp should be end_date ({end_date}), got {ts}" + ) + def test_non_entity_mode_with_end_date_only(self): """Test non-entity retrieval calculates start_date from TTL""" test_repo_config = RepoConfig( diff --git a/sdk/python/tests/unit/infra/offline_stores/test_bigquery.py b/sdk/python/tests/unit/infra/offline_stores/test_bigquery.py index 662be20b316..7dbf06e94a8 100644 --- a/sdk/python/tests/unit/infra/offline_stores/test_bigquery.py +++ b/sdk/python/tests/unit/infra/offline_stores/test_bigquery.py @@ -1,3 +1,4 @@ +from datetime import datetime, timezone from unittest.mock import Mock, patch import pandas as pd @@ -5,9 +6,11 @@ import pytest from feast.infra.offline_stores.bigquery import ( + BigQueryOfflineStore, BigQueryOfflineStoreConfig, BigQueryRetrievalJob, ) +from feast.infra.offline_stores.bigquery_source import BigQuerySource from feast.infra.online_stores.sqlite import SqliteOnlineStoreConfig from feast.repo_config import RepoConfig @@ -82,3 +85,70 @@ def test_to_arrow_timeout(self, big_query_result): self.retrieval_job._execute_query.assert_called_once_with( query=self.query, timeout=30 ) + + +@patch("feast.infra.offline_stores.bigquery._get_bigquery_client") +def test_pull_latest_from_table_or_query_partition_pruning(mock_get_bigquery_client): + mock_get_bigquery_client.return_value = Mock() + test_repo_config = RepoConfig( + registry="gs://ml-test/repo/registry.db", + project="test", + provider="gcp", + online_store=SqliteOnlineStoreConfig(type="sqlite"), + offline_store=BigQueryOfflineStoreConfig(type="bigquery", dataset="feast"), + ) + test_data_source = BigQuerySource( + table="project:dataset.table", + timestamp_field="event_timestamp", + date_partition_column="partition_date", + ) + retrieval_job = BigQueryOfflineStore.pull_latest_from_table_or_query( + config=test_repo_config, + data_source=test_data_source, + join_key_columns=["driver_id"], + feature_name_columns=["feature1"], + timestamp_field="event_timestamp", + created_timestamp_column=None, + start_date=datetime(2021, 1, 1, tzinfo=timezone.utc), + end_date=datetime(2021, 1, 2, tzinfo=timezone.utc), + ) + actual_query = retrieval_job.to_sql() + assert ( + "event_timestamp BETWEEN TIMESTAMP('2021-01-01T00:00:00+00:00') AND TIMESTAMP('2021-01-02T00:00:00+00:00')" + in actual_query + ) + assert "partition_date >= '2021-01-01'" in actual_query + assert "partition_date <= '2021-01-02'" in actual_query + + +@patch("feast.infra.offline_stores.bigquery._get_bigquery_client") +def test_pull_all_from_table_or_query_partition_pruning(mock_get_bigquery_client): + mock_get_bigquery_client.return_value = Mock() + test_repo_config = RepoConfig( + registry="gs://ml-test/repo/registry.db", + project="test", + provider="gcp", + online_store=SqliteOnlineStoreConfig(type="sqlite"), + offline_store=BigQueryOfflineStoreConfig(type="bigquery", dataset="feast"), + ) + test_data_source = BigQuerySource( + table="project:dataset.table", + timestamp_field="event_timestamp", + date_partition_column="partition_date", + ) + retrieval_job = BigQueryOfflineStore.pull_all_from_table_or_query( + config=test_repo_config, + data_source=test_data_source, + join_key_columns=["driver_id"], + feature_name_columns=["feature1"], + timestamp_field="event_timestamp", + start_date=datetime(2021, 1, 1, tzinfo=timezone.utc), + end_date=datetime(2021, 1, 2, tzinfo=timezone.utc), + ) + actual_query = retrieval_job.to_sql() + assert ( + "event_timestamp BETWEEN TIMESTAMP('2021-01-01T00:00:00+00:00') AND TIMESTAMP('2021-01-02T00:00:00+00:00')" + in actual_query + ) + assert "partition_date >= '2021-01-01'" in actual_query + assert "partition_date <= '2021-01-02'" in actual_query diff --git a/sdk/python/tests/unit/infra/offline_stores/test_clickhouse.py b/sdk/python/tests/unit/infra/offline_stores/test_clickhouse.py index f5440ed367d..7789cde72b3 100644 --- a/sdk/python/tests/unit/infra/offline_stores/test_clickhouse.py +++ b/sdk/python/tests/unit/infra/offline_stores/test_clickhouse.py @@ -1,5 +1,6 @@ import logging import threading +from datetime import datetime, timedelta, timezone from unittest.mock import MagicMock, patch import pytest @@ -133,3 +134,109 @@ def test_clickhouse_config_handles_none_additional_client_args(): config = ClickhouseConfig(**raw_config) assert config.additional_client_args is None + + +class TestNonEntityRetrieval: + """Test the non-entity retrieval logic (entity_df=None) for ClickHouse.""" + + _MODULE = "feast.infra.offline_stores.contrib.clickhouse_offline_store.clickhouse" + + def _call_get_historical_features(self, feature_views, **kwargs): + """Call get_historical_features with entity_df=None, mocking the pipeline.""" + from feast.infra.offline_stores.contrib.clickhouse_offline_store.clickhouse import ( + ClickhouseOfflineStore, + ClickhouseOfflineStoreConfig, + ) + from feast.repo_config import RepoConfig + + config = RepoConfig( + project="test_project", + registry="test_registry", + provider="local", + offline_store=ClickhouseOfflineStoreConfig( + type="clickhouse", + host="localhost", + port=9000, + database="test_db", + user="default", + password="password", + ), + ) + + end = kwargs.get("end_date", datetime(2023, 1, 7, tzinfo=timezone.utc)) + + with ( + patch.multiple( + self._MODULE, + _upload_entity_df=MagicMock(), + _get_entity_schema=MagicMock( + return_value={"event_timestamp": "timestamp"} + ), + _get_entity_df_event_timestamp_range=MagicMock( + return_value=(end - timedelta(days=1), end) + ), + ), + patch( + f"{self._MODULE}.offline_utils.get_expected_join_keys", + return_value=[], + ), + patch( + f"{self._MODULE}.offline_utils.assert_expected_columns_in_entity_df", + ), + patch( + f"{self._MODULE}.offline_utils.get_feature_view_query_context", + return_value=[], + ), + ): + refs = [f"{fv.name}:feature1" for fv in feature_views] + return ClickhouseOfflineStore.get_historical_features( + config=config, + feature_views=feature_views, + feature_refs=refs, + entity_df=None, + registry=MagicMock(), + project="test_project", + **kwargs, + ) + + @staticmethod + def _make_feature_view(name, ttl=None): + from feast.entity import Entity + from feast.feature_view import FeatureView, Field + from feast.infra.offline_stores.contrib.clickhouse_offline_store.clickhouse_source import ( + ClickhouseSource, + ) + from feast.types import Float32 + + return FeatureView( + name=name, + entities=[Entity(name="driver_id", join_keys=["driver_id"])], + ttl=ttl, + source=ClickhouseSource( + name=f"{name}_source", + table=f"{name}_table", + timestamp_field="event_timestamp", + ), + schema=[ + Field(name="feature1", dtype=Float32), + ], + ) + + def test_non_entity_mode_with_end_date(self): + """entity_df=None with explicit end_date produces a valid RetrievalJob.""" + from feast.infra.offline_stores.offline_store import RetrievalJob + + fv = self._make_feature_view("test_fv") + job = self._call_get_historical_features( + [fv], + end_date=datetime(2023, 1, 7, tzinfo=timezone.utc), + ) + assert isinstance(job, RetrievalJob) + + def test_non_entity_mode_defaults_end_date(self): + """entity_df=None without end_date defaults to now.""" + from feast.infra.offline_stores.offline_store import RetrievalJob + + fv = self._make_feature_view("test_fv") + job = self._call_get_historical_features([fv]) + assert isinstance(job, RetrievalJob) diff --git a/sdk/python/tests/unit/infra/offline_stores/test_dask_non_entity.py b/sdk/python/tests/unit/infra/offline_stores/test_dask_non_entity.py index f3d78ff5a9b..4f8ad322eee 100644 --- a/sdk/python/tests/unit/infra/offline_stores/test_dask_non_entity.py +++ b/sdk/python/tests/unit/infra/offline_stores/test_dask_non_entity.py @@ -311,7 +311,7 @@ def test_non_entity_mode_with_end_date_only_calculates_start_from_ttl( # Latest value should be 0.3 (from 2023-01-07) assert 0.3 in driver1_data["conv_rate"].values - @patch("feast.infra.offline_stores.dask.datetime") + @patch("feast.utils.datetime") def test_no_dates_provided_defaults_to_current_time_and_filters_data( self, mock_datetime, monkeypatch ): diff --git a/sdk/python/tests/unit/infra/online_store/test_dynamodb_online_store.py b/sdk/python/tests/unit/infra/online_store/test_dynamodb_online_store.py index 6dd8a99f884..7e5558e19d7 100644 --- a/sdk/python/tests/unit/infra/online_store/test_dynamodb_online_store.py +++ b/sdk/python/tests/unit/infra/online_store/test_dynamodb_online_store.py @@ -780,3 +780,273 @@ def test_dynamodb_update_online_store_int_list(repo_config, dynamodb_online_stor assert len(result) == 1 scores = result[0][1]["scores"] assert _extract_int32_list(scores) == [10, 20, 30] + + +@mock_dynamodb +def test_dynamodb_online_store_online_read_empty_entities( + repo_config, dynamodb_online_store +): + """Test DynamoDBOnlineStore online_read with empty entity list.""" + db_table_name = f"{TABLE_NAME}_empty_entities" + create_test_table(PROJECT, db_table_name, REGION) + + returned_items = dynamodb_online_store.online_read( + config=repo_config, + table=MockFeatureView(name=db_table_name), + entity_keys=[], + ) + assert returned_items == [] + + +@mock_dynamodb +def test_dynamodb_online_store_online_read_parallel_batches( + repo_config, dynamodb_online_store +): + """Test DynamoDBOnlineStore online_read with multiple batches (parallel execution). + + With batch_size=100 (default), 250 entities should create 3 batches + that are executed in parallel via ThreadPoolExecutor. + """ + n_samples = 250 + db_table_name = f"{TABLE_NAME}_parallel_batches" + create_test_table(PROJECT, db_table_name, REGION) + data = create_n_customer_test_samples(n=n_samples) + insert_data_test_table(data, PROJECT, db_table_name, REGION) + + entity_keys, features, *rest = zip(*data) + returned_items = dynamodb_online_store.online_read( + config=repo_config, + table=MockFeatureView(name=db_table_name), + entity_keys=entity_keys, + ) + + # Verify all items returned + assert len(returned_items) == n_samples + # Verify order is preserved + assert [item[1] for item in returned_items] == list(features) + + +@mock_dynamodb +def test_dynamodb_online_store_online_read_single_batch_no_parallel( + repo_config, dynamodb_online_store +): + """Test DynamoDBOnlineStore online_read with single batch (no parallelization). + + With batch_size=100, 50 entities should use single batch path + without ThreadPoolExecutor overhead. + """ + n_samples = 50 + db_table_name = f"{TABLE_NAME}_single_batch" + create_test_table(PROJECT, db_table_name, REGION) + data = create_n_customer_test_samples(n=n_samples) + insert_data_test_table(data, PROJECT, db_table_name, REGION) + + entity_keys, features, *rest = zip(*data) + returned_items = dynamodb_online_store.online_read( + config=repo_config, + table=MockFeatureView(name=db_table_name), + entity_keys=entity_keys, + ) + + assert len(returned_items) == n_samples + assert [item[1] for item in returned_items] == list(features) + + +@mock_dynamodb +def test_dynamodb_online_store_online_read_order_preservation_across_batches( + repo_config, dynamodb_online_store +): + """Test that entity order is preserved across parallel batch reads. + + This is critical: parallel execution must not change the order of results. + """ + n_samples = 150 # 2 batches with batch_size=100 + db_table_name = f"{TABLE_NAME}_order_preservation" + create_test_table(PROJECT, db_table_name, REGION) + data = create_n_customer_test_samples(n=n_samples) + insert_data_test_table(data, PROJECT, db_table_name, REGION) + + entity_keys, features, *rest = zip(*data) + + # Read multiple times to verify consistent ordering + for _ in range(3): + returned_items = dynamodb_online_store.online_read( + config=repo_config, + table=MockFeatureView(name=db_table_name), + entity_keys=entity_keys, + ) + assert len(returned_items) == n_samples + # Verify exact order matches + for i, (returned, expected) in enumerate(zip(returned_items, features)): + assert returned[1] == expected, f"Mismatch at index {i}" + + +@mock_dynamodb +def test_dynamodb_online_store_online_read_small_batch_size(dynamodb_online_store): + """Test parallel reads with small batch_size. + + Verifies correctness with small batch sizes that create multiple batches. + """ + small_batch_config = RepoConfig( + registry=REGISTRY, + project=PROJECT, + provider=PROVIDER, + online_store=DynamoDBOnlineStoreConfig(region=REGION, batch_size=5), + offline_store=DaskOfflineStoreConfig(), + entity_key_serialization_version=3, + ) + + n_samples = 25 # 5 batches with batch_size=5 + db_table_name = f"{TABLE_NAME}_small_batch" + create_test_table(PROJECT, db_table_name, REGION) + data = create_n_customer_test_samples(n=n_samples) + insert_data_test_table(data, PROJECT, db_table_name, REGION) + + entity_keys, features, *rest = zip(*data) + returned_items = dynamodb_online_store.online_read( + config=small_batch_config, + table=MockFeatureView(name=db_table_name), + entity_keys=entity_keys, + ) + + assert len(returned_items) == n_samples + assert [item[1] for item in returned_items] == list(features) + + +@mock_dynamodb +def test_dynamodb_online_store_online_read_many_batches(dynamodb_online_store): + """Test parallel reads with many batches (>10). + + Verifies correctness when number of batches exceeds max_workers cap. + """ + many_batch_config = RepoConfig( + registry=REGISTRY, + project=PROJECT, + provider=PROVIDER, + online_store=DynamoDBOnlineStoreConfig(region=REGION, batch_size=10), + offline_store=DaskOfflineStoreConfig(), + entity_key_serialization_version=3, + ) + + n_samples = 150 # 15 batches with batch_size=10 + db_table_name = f"{TABLE_NAME}_many_batches" + create_test_table(PROJECT, db_table_name, REGION) + data = create_n_customer_test_samples(n=n_samples) + insert_data_test_table(data, PROJECT, db_table_name, REGION) + + entity_keys, features, *rest = zip(*data) + returned_items = dynamodb_online_store.online_read( + config=many_batch_config, + table=MockFeatureView(name=db_table_name), + entity_keys=entity_keys, + ) + + assert len(returned_items) == n_samples + assert [item[1] for item in returned_items] == list(features) + + +@mock_dynamodb +def test_dynamodb_online_store_max_workers_capped_at_config(dynamodb_online_store): + """Verify ThreadPoolExecutor max_workers uses max_read_workers config. + + Bug: Old code used min(len(batches), batch_size) which fails with small batch_size. + Fix: New code uses min(len(batches), max_read_workers) for proper parallelization. + + This test uses batch_size=5 with 15 batches to expose the bug: + - OLD (buggy): max_workers = min(15, 5) = 5 (insufficient parallelism) + - NEW (fixed): max_workers = min(15, 10) = 10 (uses max_read_workers default) + """ + # Use small batch_size to expose the bug + small_batch_config = RepoConfig( + registry=REGISTRY, + project=PROJECT, + provider=PROVIDER, + online_store=DynamoDBOnlineStoreConfig(region=REGION, batch_size=5), + offline_store=DaskOfflineStoreConfig(), + entity_key_serialization_version=3, + ) + + n_samples = 75 # 15 batches with batch_size=5 + db_table_name = f"{TABLE_NAME}_max_workers_cap" + create_test_table(PROJECT, db_table_name, REGION) + data = create_n_customer_test_samples(n=n_samples) + insert_data_test_table(data, PROJECT, db_table_name, REGION) + + entity_keys, features, *rest = zip(*data) + + with patch( + "feast.infra.online_stores.dynamodb.ThreadPoolExecutor" + ) as mock_executor: + # Configure mock to work like real ThreadPoolExecutor + mock_executor.return_value.__enter__.return_value.map.return_value = iter( + [{"Responses": {}} for _ in range(15)] + ) + + dynamodb_online_store.online_read( + config=small_batch_config, + table=MockFeatureView(name=db_table_name), + entity_keys=entity_keys, + ) + + # Verify ThreadPoolExecutor was called with max_workers=10 (capped at 10, NOT batch_size=5) + mock_executor.assert_called_once() + call_kwargs = mock_executor.call_args + assert call_kwargs[1]["max_workers"] == 10, ( + f"Expected max_workers=10 (capped), got {call_kwargs[1]['max_workers']}. " + f"If got 5, the bug is using batch_size instead of 10 as cap." + ) + + +@mock_dynamodb +def test_dynamodb_online_store_thread_safety_uses_shared_client( + dynamodb_online_store, +): + """Verify multi-batch reads use a shared thread-safe boto3 client. + + boto3 clients ARE thread-safe, so we share a single client across threads + for better performance (avoids creating new sessions per thread). + https://docs.aws.amazon.com/boto3/latest/guide/clients.html#multithreading-or-multiprocessing-with-clients + """ + config = RepoConfig( + registry=REGISTRY, + project=PROJECT, + provider=PROVIDER, + online_store=DynamoDBOnlineStoreConfig(region=REGION, batch_size=50), + offline_store=DaskOfflineStoreConfig(), + entity_key_serialization_version=3, + ) + + n_samples = 150 # 3 batches + db_table_name = f"{TABLE_NAME}_thread_safety" + create_test_table(PROJECT, db_table_name, REGION) + data = create_n_customer_test_samples(n=n_samples) + insert_data_test_table(data, PROJECT, db_table_name, REGION) + + entity_keys, features, *rest = zip(*data) + + # Track clients created to verify thread-safety via shared client + clients_created = [] + original_client = boto3.client + + def tracking_client(*args, **kwargs): + client = original_client(*args, **kwargs) + clients_created.append(id(client)) + return client + + with patch.object(boto3, "client", side_effect=tracking_client): + returned_items = dynamodb_online_store.online_read( + config=config, + table=MockFeatureView(name=db_table_name), + entity_keys=entity_keys, + ) + + # Verify results are correct (functional correctness) + assert len(returned_items) == n_samples + + # Verify only one client was created (shared across threads) + # The client is cached and reused for all batch requests + dynamodb_clients = [c for c in clients_created] + assert len(set(dynamodb_clients)) == 1, ( + f"Expected 1 shared client for thread-safety, " + f"got {len(set(dynamodb_clients))} unique clients" + ) diff --git a/sdk/python/tests/unit/infra/online_store/test_helpers.py b/sdk/python/tests/unit/infra/online_store/test_helpers.py new file mode 100644 index 00000000000..2d65dff5203 --- /dev/null +++ b/sdk/python/tests/unit/infra/online_store/test_helpers.py @@ -0,0 +1,150 @@ +import struct +from datetime import datetime, timezone +from unittest.mock import MagicMock, patch + +import mmh3 + +from feast.infra.online_stores.helpers import ( + _mmh3, + _redis_key, + _redis_key_prefix, + _to_naive_utc, + compute_entity_id, + get_online_store_from_config, +) +from feast.protos.feast.types.EntityKey_pb2 import EntityKey as EntityKeyProto +from feast.protos.feast.types.Value_pb2 import Value as ValueProto + + +def _make_entity_key(join_keys, values): + """Helper to build an EntityKeyProto.""" + entity_key = EntityKeyProto() + for k in join_keys: + entity_key.join_keys.append(k) + for v in values: + entity_key.entity_values.append(v) + return entity_key + + +class TestRedisKey: + def test_redis_key_produces_bytes(self): + entity_key = _make_entity_key(["user_id"], [ValueProto(string_val="user_1")]) + result = _redis_key("my_project", entity_key) + assert isinstance(result, bytes) + + def test_redis_key_contains_project(self): + entity_key = _make_entity_key(["user_id"], [ValueProto(string_val="user_1")]) + result = _redis_key("my_project", entity_key) + assert b"my_project" in result + + def test_redis_key_different_projects_produce_different_keys(self): + entity_key = _make_entity_key(["user_id"], [ValueProto(string_val="user_1")]) + key_a = _redis_key("project_a", entity_key) + key_b = _redis_key("project_b", entity_key) + assert key_a != key_b + + def test_redis_key_different_entities_produce_different_keys(self): + ek1 = _make_entity_key(["user_id"], [ValueProto(string_val="user_1")]) + ek2 = _make_entity_key(["user_id"], [ValueProto(string_val="user_2")]) + assert _redis_key("proj", ek1) != _redis_key("proj", ek2) + + def test_redis_key_serialization_version_changes_key(self): + entity_key = _make_entity_key(["user_id"], [ValueProto(string_val="user_1")]) + key_v2 = _redis_key("proj", entity_key, entity_key_serialization_version=2) + key_v3 = _redis_key("proj", entity_key, entity_key_serialization_version=3) + assert key_v2 != key_v3 + + +class TestRedisKeyPrefix: + def test_returns_bytes(self): + result = _redis_key_prefix(["user_id"]) + assert isinstance(result, bytes) + + def test_different_keys_produce_different_prefixes(self): + prefix_a = _redis_key_prefix(["user_id"]) + prefix_b = _redis_key_prefix(["merchant_id"]) + assert prefix_a != prefix_b + + +class TestMmh3: + def test_returns_bytes(self): + result = _mmh3("test_key") + assert isinstance(result, bytes) + + def test_consistent_hash(self): + assert _mmh3("hello") == _mmh3("hello") + + def test_different_keys_different_hashes(self): + assert _mmh3("key_a") != _mmh3("key_b") + + def test_hash_length(self): + result = _mmh3("test") + assert len(result) == 4 # 32-bit hash = 4 bytes + + def test_little_endian_format(self): + """Verify the hash matches the expected little-endian encoding.""" + key = "test_key" + key_hash = mmh3.hash(key, signed=False) + expected = bytes.fromhex(struct.pack(" FeatureView: + return FeatureView( + name=name, + entities=[entity], + ttl=timedelta(days=1), + schema=[Field(name="conv_rate", dtype=Float32)], + source=source, + ) + + +def test_feature_view_name_conflict_between_stream_and_batch(sqlite_registry): + entity = Entity( + name="driver", + value_type=ValueType.STRING, + join_keys=["driver_id"], + ) + sqlite_registry.apply_entity(entity, "test_project") + + file_source = FileSource( + path="driver_stats.parquet", + timestamp_field="event_timestamp", + created_timestamp_column="created", + ) + + batch_view = _build_feature_view("driver_activity", entity, file_source) + sqlite_registry.apply_feature_view(batch_view, "test_project") + + push_source = PushSource(name="driver_push", batch_source=file_source) + stream_view = StreamFeatureView( + name="driver_activity", + source=push_source, + entities=[entity], + schema=[Field(name="conv_rate", dtype=Float32)], + timestamp_field="event_timestamp", + ) + + with pytest.raises(ConflictingFeatureViewNames): + sqlite_registry.apply_feature_view(stream_view, "test_project") diff --git a/sdk/python/tests/unit/infra/scaffolding/test_repo_operations.py b/sdk/python/tests/unit/infra/scaffolding/test_repo_operations.py index 672c8f43d96..b31aee51c1e 100644 --- a/sdk/python/tests/unit/infra/scaffolding/test_repo_operations.py +++ b/sdk/python/tests/unit/infra/scaffolding/test_repo_operations.py @@ -28,15 +28,27 @@ def feature_repo(feastignore_contents: Optional[str]): (repo_root / "bar").mkdir() (repo_root / "bar/subdir1").mkdir() (repo_root / "bar/subdir1/subdir2").mkdir() + (repo_root / "foo/__pycache__").mkdir() + (repo_root / "foo/.pytest_cache").mkdir() + (repo_root / "foo/.ipynb_checkpoints").mkdir() + (repo_root / "bar/subdir1/.ipynb_checkpoints").mkdir() + (repo_root / "bar/subdir1/subdir2/.ipynb_checkpoints").mkdir() (repo_root / "a.py").touch() (repo_root / ".ipynb_checkpoints/test-checkpoint.py").touch() (repo_root / "foo/b.py").touch() + (repo_root / "foo/__pycache__/b.cpython.pyc").touch() + (repo_root / "foo/.pytest_cache/test-README.md").touch() + (repo_root / "foo/.ipynb_checkpoints/foo-checkpoint.py").touch() (repo_root / "foo1/c.py").touch() (repo_root / "foo1/bar/d.py").touch() (repo_root / "bar/e.py").touch() (repo_root / "bar/subdir1/f.py").touch() + (repo_root / "bar/subdir1/.ipynb_checkpoints/subdir1-checkpoint.py").touch() (repo_root / "bar/subdir1/subdir2/g.py").touch() + ( + repo_root / "bar/subdir1/subdir2/.ipynb_checkpoints/nested-checkpoint.py" + ).touch() if feastignore_contents: with open(repo_root / ".feastignore", "w") as f: @@ -80,6 +92,7 @@ def test_feastignore_no_stars(): { (repo_root / "foo/b.py").resolve(), (repo_root / "bar/subdir1/f.py").resolve(), + (repo_root / "foo/.ipynb_checkpoints/foo-checkpoint.py").resolve(), } ) assertpy.assert_that(get_repo_files(repo_root)).is_equal_to( @@ -110,6 +123,13 @@ def test_feastignore_with_stars(): { (repo_root / "foo/b.py").resolve(), (repo_root / "bar/subdir1/f.py").resolve(), + ( + repo_root + / "bar/subdir1/subdir2/.ipynb_checkpoints/nested-checkpoint.py" + ).resolve(), + ( + repo_root / "bar/subdir1/.ipynb_checkpoints/subdir1-checkpoint.py" + ).resolve(), (repo_root / "bar/e.py").resolve(), (repo_root / "bar/subdir1/f.py").resolve(), (repo_root / "bar/subdir1/subdir2/g.py").resolve(), @@ -135,6 +155,13 @@ def test_feastignore_with_stars2(): assertpy.assert_that(get_ignore_files(repo_root, ignore_paths)).is_equal_to( { (repo_root / "bar/subdir1/f.py").resolve(), + ( + repo_root + / "bar/subdir1/subdir2/.ipynb_checkpoints/nested-checkpoint.py" + ).resolve(), + ( + repo_root / "bar/subdir1/.ipynb_checkpoints/subdir1-checkpoint.py" + ).resolve(), (repo_root / "bar/e.py").resolve(), (repo_root / "bar/subdir1/f.py").resolve(), (repo_root / "bar/subdir1/subdir2/g.py").resolve(), diff --git a/sdk/python/tests/unit/infra/test_key_encoding_utils.py b/sdk/python/tests/unit/infra/test_key_encoding_utils.py index 14433a41e65..ba481adf234 100644 --- a/sdk/python/tests/unit/infra/test_key_encoding_utils.py +++ b/sdk/python/tests/unit/infra/test_key_encoding_utils.py @@ -4,6 +4,7 @@ deserialize_entity_key, reserialize_entity_v2_key_to_v3, serialize_entity_key, + serialize_entity_key_prefix, ) from feast.protos.feast.types.EntityKey_pb2 import EntityKey as EntityKeyProto from feast.protos.feast.types.Value_pb2 import Value as ValueProto @@ -151,3 +152,186 @@ def test_reserialize_entity_v2_key_to_v3(): join_keys=["user"], entity_values=[ValueProto(int64_val=int(2**15))], ) + + +def test_single_entity_fast_path(): + """Test that single entity optimization works correctly.""" + entity_key_proto = EntityKeyProto( + join_keys=["user_id"], + entity_values=[ValueProto(string_val="test_user")], + ) + + serialized_key = serialize_entity_key( + entity_key_proto, entity_key_serialization_version=3 + ) + deserialized_key = deserialize_entity_key( + serialized_key, entity_key_serialization_version=3 + ) + + assert deserialized_key == entity_key_proto + + +def test_empty_entity_key(): + """Test handling of empty entity keys.""" + entity_key_proto = EntityKeyProto(join_keys=[], entity_values=[]) + + serialized_key = serialize_entity_key( + entity_key_proto, entity_key_serialization_version=3 + ) + deserialized_key = deserialize_entity_key( + serialized_key, entity_key_serialization_version=3 + ) + + assert deserialized_key == entity_key_proto + + +def test_binary_format_deterministic(): + """Test that serialization is deterministic (same input produces same output).""" + entity_key_proto = EntityKeyProto( + join_keys=["customer", "user", "session"], + entity_values=[ + ValueProto(string_val="cust1"), + ValueProto(string_val="user1"), + ValueProto(string_val="sess1"), + ], + ) + + # Serialize the same entity multiple times + serializations = [] + for _ in range(5): + serialized = serialize_entity_key( + entity_key_proto, entity_key_serialization_version=3 + ) + serializations.append(serialized) + + # All serializations should be identical + for s in serializations[1:]: + assert s == serializations[0], "Serialization is not deterministic" + + +def test_optimization_preserves_sorting(): + """Test that optimizations preserve the sorting behavior for multi-entity keys.""" + # Create entity key with unsorted keys + entity_key_proto = EntityKeyProto( + join_keys=["zebra", "alpha", "beta"], + entity_values=[ + ValueProto(string_val="z_val"), + ValueProto(string_val="a_val"), + ValueProto(string_val="b_val"), + ], + ) + + serialized = serialize_entity_key( + entity_key_proto, entity_key_serialization_version=3 + ) + deserialized = deserialize_entity_key( + serialized, entity_key_serialization_version=3 + ) + + # Keys should be sorted in the result + expected_sorted_keys = ["alpha", "beta", "zebra"] + expected_sorted_values = ["a_val", "b_val", "z_val"] + + assert deserialized.join_keys == expected_sorted_keys + assert [v.string_val for v in deserialized.entity_values] == expected_sorted_values + + +def test_performance_bounds_single_entity(): + """Regression test to ensure single entity performance meets minimum bounds.""" + import time + + entity_key = EntityKeyProto( + join_keys=["user_id"], entity_values=[ValueProto(string_val="user123")] + ) + + # Measure serialization time for 1000 operations + start = time.perf_counter() + for _ in range(1000): + serialize_entity_key(entity_key, entity_key_serialization_version=3) + serialize_time = time.perf_counter() - start + + # Measure deserialization time + serialized = serialize_entity_key(entity_key, entity_key_serialization_version=3) + start = time.perf_counter() + for _ in range(1000): + deserialize_entity_key(serialized, entity_key_serialization_version=3) + deserialize_time = time.perf_counter() - start + + # Performance bounds with generous thresholds to avoid flaky failures on CI runners + assert serialize_time < 0.2, f"Serialization too slow: {serialize_time:.4f}s" + assert deserialize_time < 0.2, f"Deserialization too slow: {deserialize_time:.4f}s" + + +def test_non_ascii_prefix_compatibility(): + """Critical test: ensure prefix serialization matches full entity key serialization for non-ASCII keys.""" + # Test with non-ASCII characters that have different byte vs character lengths + non_ascii_keys = ["用户ID", "사용자ID", "идентификатор", "مُعرِّف"] + + for key in non_ascii_keys: + # Test single key prefix + prefix_result = serialize_entity_key_prefix( + [key], entity_key_serialization_version=3 + ) + + # Create full entity key and serialize it + entity_key = EntityKeyProto( + join_keys=[key], entity_values=[ValueProto(string_val="test_value")] + ) + full_result = serialize_entity_key( + entity_key, entity_key_serialization_version=3 + ) + + # The prefix should match the beginning of the full serialization + # Extract just the key portion (skip entity count, but include key metadata) + prefix_len = len(prefix_result) + assert full_result[:prefix_len] == prefix_result, ( + f"Prefix mismatch for non-ASCII key '{key}': " + f"Character length: {len(key)}, " + f"UTF-8 byte length: {len(key.encode('utf8'))}" + ) + + +def test_ascii_prefix_compatibility(): + """Verify prefix compatibility still works for ASCII keys.""" + ascii_keys = ["user_id", "session_id", "device_id"] + + for key in ascii_keys: + prefix_result = serialize_entity_key_prefix( + [key], entity_key_serialization_version=3 + ) + + entity_key = EntityKeyProto( + join_keys=[key], entity_values=[ValueProto(string_val="test_value")] + ) + full_result = serialize_entity_key( + entity_key, entity_key_serialization_version=3 + ) + + prefix_len = len(prefix_result) + assert full_result[:prefix_len] == prefix_result, ( + f"Prefix mismatch for ASCII key '{key}'" + ) + + +def test_multi_key_non_ascii_prefix_compatibility(): + """Test multi-key prefix compatibility with non-ASCII characters.""" + mixed_keys = ["user_id", "用户会话", "session_id"] # Mix ASCII and non-ASCII + + prefix_result = serialize_entity_key_prefix( + mixed_keys, entity_key_serialization_version=3 + ) + + entity_key = EntityKeyProto( + join_keys=mixed_keys, + entity_values=[ + ValueProto(string_val="test1"), + ValueProto(string_val="test2"), + ValueProto(string_val="test3"), + ], + ) + full_result = serialize_entity_key(entity_key, entity_key_serialization_version=3) + + prefix_len = len(prefix_result) + assert full_result[:prefix_len] == prefix_result, ( + "Multi-key prefix mismatch with non-ASCII" + ) diff --git a/sdk/python/tests/unit/local_feast_tests/test_feature_service.py b/sdk/python/tests/unit/local_feast_tests/test_feature_service.py index 75ceb463085..c331f2913de 100644 --- a/sdk/python/tests/unit/local_feast_tests/test_feature_service.py +++ b/sdk/python/tests/unit/local_feast_tests/test_feature_service.py @@ -6,7 +6,7 @@ create_driver_hourly_stats_df, create_global_daily_stats_df, ) -from tests.integration.feature_repos.universal.feature_views import TAGS +from tests.universal.feature_repos.universal.feature_views import TAGS from tests.utils.basic_read_write_test import basic_rw_test from tests.utils.cli_repo_creator import CliRunner, get_example_repo @@ -71,7 +71,7 @@ def test_apply_with_fv_inference() -> None: fs = store.get_feature_service("all_stats") assert len(fs.feature_view_projections) == 2 - assert len(fs.feature_view_projections[0].features) == 3 + assert len(fs.feature_view_projections[0].features) == 6 assert len(fs.feature_view_projections[0].desired_features) == 0 assert len(fs.feature_view_projections[1].features) == 2 assert len(fs.feature_view_projections[1].desired_features) == 0 diff --git a/sdk/python/tests/unit/local_feast_tests/test_local_feature_store.py b/sdk/python/tests/unit/local_feast_tests/test_local_feature_store.py index debe14beee2..9b7660bf692 100644 --- a/sdk/python/tests/unit/local_feast_tests/test_local_feature_store.py +++ b/sdk/python/tests/unit/local_feast_tests/test_local_feature_store.py @@ -11,6 +11,7 @@ from feast.data_format import AvroFormat, ParquetFormat from feast.data_source import KafkaSource from feast.entity import Entity +from feast.errors import ConflictingFeatureViewNames from feast.feast_object import ALL_RESOURCE_TYPES from feast.feature_store import FeatureStore from feast.feature_view import DUMMY_ENTITY_ID, DUMMY_ENTITY_NAME, FeatureView @@ -24,7 +25,7 @@ from feast.repo_config import RegistryConfig, RepoConfig from feast.stream_feature_view import stream_feature_view from feast.types import Array, Bytes, Float32, Int64, String, ValueType, from_value_type -from tests.integration.feature_repos.universal.feature_views import TAGS +from tests.universal.feature_repos.universal.feature_views import TAGS from tests.utils.cli_repo_creator import CliRunner, get_example_repo from tests.utils.data_source_test_creator import prep_file_source @@ -534,16 +535,10 @@ def test_apply_conflicting_feature_view_names(feature_store_with_local_registry) source=FileSource(path="customer_stats.parquet"), tags={}, ) - try: + with pytest.raises(ConflictingFeatureViewNames) as exc_info: feature_store_with_local_registry.apply([driver_stats, customer_stats]) - error = None - except ValueError as e: - error = e - assert ( - isinstance(error, ValueError) - and "Please ensure that all feature view names are case-insensitively unique" - in error.args[0] - ) + + assert "Feature view names must be case-insensitively unique" in str(exc_info.value) feature_store_with_local_registry.teardown() diff --git a/sdk/python/tests/unit/online_store/test_mongodb_online_retrieval.py b/sdk/python/tests/unit/online_store/test_mongodb_online_retrieval.py new file mode 100644 index 00000000000..cfadc3151fd --- /dev/null +++ b/sdk/python/tests/unit/online_store/test_mongodb_online_retrieval.py @@ -0,0 +1,305 @@ +""" +Unit tests for MongoDB online store. + +Docker-dependent tests are marked with ``@_requires_docker`` and are skipped when +Docker is unavailable. Pure Python tests (no container needed) run in all environments. +""" + +from datetime import datetime, timedelta, timezone + +import pytest + +pytest.importorskip("pymongo") + +from feast import FeatureView, Field, FileSource # noqa: E402 +from feast.infra.online_stores.mongodb_online_store.mongodb import ( # noqa: E402 + MongoDBOnlineStore, +) +from feast.protos.feast.types.EntityKey_pb2 import EntityKey as EntityKeyProto +from feast.protos.feast.types.Value_pb2 import Value as ValueProto +from feast.types import Int64 +from feast.utils import _utc_now +from tests.universal.feature_repos.universal.feature_views import TAGS +from tests.utils.cli_repo_creator import CliRunner, get_example_repo + +# Check if Docker is available +docker_available = False +try: + import docker + from testcontainers.mongodb import MongoDbContainer + + # Try to connect to Docker daemon + try: + client = docker.from_env() + client.ping() + docker_available = True + except Exception: + pass +except ImportError: + pass + +# Applied per-test so that pure Python tests still run without Docker. +_requires_docker = pytest.mark.skipif( + not docker_available, + reason="Docker is not available or not running. Start Docker daemon to run these tests.", +) + + +@pytest.fixture(scope="module") +def mongodb_container(): + """Start a MongoDB container for testing.""" + container = MongoDbContainer( + "mongo:latest", + username="test", + password="test", # pragma: allowlist secret + ).with_exposed_ports(27017) + container.start() + yield container + container.stop() + + +@pytest.fixture +def mongodb_connection_string(mongodb_container): + """Get MongoDB connection string from the container.""" + exposed_port = mongodb_container.get_exposed_port(27017) + return f"mongodb://test:test@localhost:{exposed_port}" # pragma: allowlist secret + + +@_requires_docker +def test_mongodb_online_features(mongodb_connection_string): + """ + Test reading from MongoDB online store using testcontainers. + """ + runner = CliRunner() + with ( + runner.local_repo( + get_example_repo("example_feature_repo_1.py"), + offline_store="file", + online_store="mongodb", + teardown=False, # Disable CLI teardown since container will be stopped by fixture + ) as store + ): + # Update the connection string to use the test container + store.config.online_store.connection_string = mongodb_connection_string + + # Write some data to two tables + driver_locations_fv = store.get_feature_view(name="driver_locations") + customer_profile_fv = store.get_feature_view(name="customer_profile") + customer_driver_combined_fv = store.get_feature_view( + name="customer_driver_combined" + ) + + provider = store._get_provider() + + driver_key = EntityKeyProto( + join_keys=["driver_id"], entity_values=[ValueProto(int64_val=1)] + ) + provider.online_write_batch( + config=store.config, + table=driver_locations_fv, + data=[ + ( + driver_key, + { + "lat": ValueProto(double_val=0.1), + "lon": ValueProto(string_val="1.0"), + }, + _utc_now(), + _utc_now(), + ) + ], + progress=None, + ) + + customer_key = EntityKeyProto( + join_keys=["customer_id"], entity_values=[ValueProto(string_val="5")] + ) + provider.online_write_batch( + config=store.config, + table=customer_profile_fv, + data=[ + ( + customer_key, + { + "avg_orders_day": ValueProto(float_val=1.0), + "name": ValueProto(string_val="John"), + "age": ValueProto(int64_val=3), + }, + _utc_now(), + _utc_now(), + ) + ], + progress=None, + ) + + customer_key = EntityKeyProto( + join_keys=["customer_id", "driver_id"], + entity_values=[ValueProto(string_val="5"), ValueProto(int64_val=1)], + ) + provider.online_write_batch( + config=store.config, + table=customer_driver_combined_fv, + data=[ + ( + customer_key, + {"trips": ValueProto(int64_val=7)}, + _utc_now(), + _utc_now(), + ) + ], + progress=None, + ) + + assert len(store.list_entities()) == 3 + assert len(store.list_entities(tags=TAGS)) == 2 + + # Retrieve features using two keys + result = store.get_online_features( + features=[ + "driver_locations:lon", + "customer_profile:avg_orders_day", + "customer_profile:name", + "customer_driver_combined:trips", + ], + entity_rows=[ + {"driver_id": 1, "customer_id": "5"}, + {"driver_id": 1, "customer_id": 5}, + ], + full_feature_names=False, + ).to_dict() + + assert "lon" in result + assert "avg_orders_day" in result + assert "name" in result + assert result["driver_id"] == [1, 1] + assert result["customer_id"] == ["5", "5"] + assert result["lon"] == ["1.0", "1.0"] + assert result["avg_orders_day"] == [1.0, 1.0] + assert result["name"] == ["John", "John"] + assert result["trips"] == [7, 7] + + # Ensure features are still in result when keys not found + result = store.get_online_features( + features=["customer_driver_combined:trips"], + entity_rows=[{"driver_id": 0, "customer_id": 0}], + full_feature_names=False, + ).to_dict() + + assert result["trips"] == [None] + + +# --------------------------------------------------------------------------- +# Pure Python tests — no Docker required +# --------------------------------------------------------------------------- + + +def _make_fv(*field_names: str) -> FeatureView: + """Build a minimal FeatureView with Int64 features for use in unit tests.""" + return FeatureView( + name="test_fv", + entities=[], + schema=[Field(name=n, dtype=Int64) for n in field_names], + source=FileSource(path="fake.parquet", timestamp_field="event_timestamp"), + ttl=timedelta(days=1), + ) + + +def test_convert_raw_docs_missing_entity(): + """Entity key absent from docs → result tuple is (None, None) for that position.""" + fv = _make_fv("score") + ts = datetime(2024, 1, 1, tzinfo=timezone.utc) + ids = [b"present", b"missing"] + docs = { + b"present": { + "features": {"test_fv": {"score": 42}}, + "event_timestamps": {"test_fv": ts}, + } + } + + results = MongoDBOnlineStore._convert_raw_docs_to_proto(ids, docs, fv) + + assert len(results) == 2 + ts_out, feats_out = results[0] + assert ts_out == ts + assert feats_out["score"].int64_val == 42 + assert results[1] == (None, None) + + +def test_convert_raw_docs_partial_doc(): + """Entity exists but one feature key is absent → empty ValueProto for that feature.""" + fv = _make_fv("present_feat", "missing_feat") + ts = datetime(2024, 1, 1, tzinfo=timezone.utc) + ids = [b"entity1"] + docs = { + b"entity1": { + # missing_feat intentionally omitted (e.g. schema migration scenario) + "features": {"test_fv": {"present_feat": 99}}, + "event_timestamps": {"test_fv": ts}, + } + } + + results = MongoDBOnlineStore._convert_raw_docs_to_proto(ids, docs, fv) + + assert len(results) == 1 + ts_out, feats_out = results[0] + assert ts_out == ts + assert feats_out["present_feat"].int64_val == 99 + assert feats_out["missing_feat"] == ValueProto() # null / not-set + + +def test_convert_raw_docs_entity_exists_but_fv_not_written(): + """Entity doc exists (written by another FV) but this FV was never written → (None, None). + + MongoDB stores all feature views for the same entity in one document. + If FV "driver_stats" was written, an entity doc exists for driver_1. + A subsequent read for FV "pricing" (never written) must return (None, None), + not a truthy dict of empty ValueProtos. + """ + pricing_fv = _make_fv("price") + ts = datetime(2024, 1, 1, tzinfo=timezone.utc) + ids = [b"driver_1"] + # doc was created by driver_stats, pricing key is absent entirely + docs = { + b"driver_1": { + "features": {"driver_stats": {"acc_rate": 0.9}}, + "event_timestamps": {"driver_stats": ts}, + } + } + + results = MongoDBOnlineStore._convert_raw_docs_to_proto(ids, docs, pricing_fv) + + assert len(results) == 1 + assert results[0] == (None, None) + + +def test_convert_raw_docs_ordering(): + """Result order matches the ids list regardless of dict insertion order in docs.""" + fv = _make_fv("score") + ts = datetime(2024, 1, 1, tzinfo=timezone.utc) + + # Request entity keys in z → a → m order + ids = [b"entity_z", b"entity_a", b"entity_m"] + + # docs is in a different order (simulating arbitrary MongoDB cursor return order) + docs = { + b"entity_a": { + "features": {"test_fv": {"score": 2}}, + "event_timestamps": {"test_fv": ts}, + }, + b"entity_m": { + "features": {"test_fv": {"score": 3}}, + "event_timestamps": {"test_fv": ts}, + }, + b"entity_z": { + "features": {"test_fv": {"score": 1}}, + "event_timestamps": {"test_fv": ts}, + }, + } + + results = MongoDBOnlineStore._convert_raw_docs_to_proto(ids, docs, fv) + + assert len(results) == 3 + # Results must follow the ids order: z=1, a=2, m=3 + assert results[0][1]["score"].int64_val == 1 # entity_z + assert results[1][1]["score"].int64_val == 2 # entity_a + assert results[2][1]["score"].int64_val == 3 # entity_m diff --git a/sdk/python/tests/unit/online_store/test_online_retrieval.py b/sdk/python/tests/unit/online_store/test_online_retrieval.py index 501586f7828..60f583ad669 100644 --- a/sdk/python/tests/unit/online_store/test_online_retrieval.py +++ b/sdk/python/tests/unit/online_store/test_online_retrieval.py @@ -21,7 +21,7 @@ from feast.torch_wrapper import get_torch from feast.types import ValueType from feast.utils import _utc_now -from tests.integration.feature_repos.universal.feature_views import TAGS +from tests.universal.feature_repos.universal.feature_views import TAGS from tests.utils.cli_repo_creator import CliRunner, get_example_repo diff --git a/sdk/python/tests/unit/permissions/auth/server/mock_utils.py b/sdk/python/tests/unit/permissions/auth/server/mock_utils.py index 5bde4d4ecbc..4d62bbf4348 100644 --- a/sdk/python/tests/unit/permissions/auth/server/mock_utils.py +++ b/sdk/python/tests/unit/permissions/auth/server/mock_utils.py @@ -32,14 +32,14 @@ async def mock_oath2(self, request): } monkeypatch.setattr( "feast.permissions.client.oidc_authentication_client_manager.requests.get", - lambda url: discovery_response, + lambda url, verify=True: discovery_response, ) token_response = Mock(spec=Response) token_response.status_code = 200 token_response.json.return_value = {"access_token": "my-token"} monkeypatch.setattr( "feast.permissions.client.oidc_authentication_client_manager.requests.post", - lambda url, data, headers: token_response, + lambda url, data, headers, verify=True: token_response, ) monkeypatch.setattr( diff --git a/sdk/python/tests/unit/permissions/auth/test_token_parser.py b/sdk/python/tests/unit/permissions/auth/test_token_parser.py index 8ac0f2b6d5e..fdec71e109a 100644 --- a/sdk/python/tests/unit/permissions/auth/test_token_parser.py +++ b/sdk/python/tests/unit/permissions/auth/test_token_parser.py @@ -50,10 +50,138 @@ def test_oidc_token_validation_success( assertpy.assert_that(user).is_type_of(User) if isinstance(user, User): assertpy.assert_that(user.username).is_equal_to("my-name") - assertpy.assert_that(user.roles.sort()).is_equal_to(["reader", "writer"].sort()) + assertpy.assert_that(sorted(user.roles)).is_equal_to( + sorted(["reader", "writer"]) + ) assertpy.assert_that(user.has_matching_role(["reader"])).is_true() assertpy.assert_that(user.has_matching_role(["writer"])).is_true() assertpy.assert_that(user.has_matching_role(["updater"])).is_false() + assertpy.assert_that(user.groups).is_equal_to([]) + assertpy.assert_that(user.namespaces).is_equal_to([]) + + +@patch( + "feast.permissions.auth.oidc_token_parser.OAuth2AuthorizationCodeBearer.__call__" +) +@patch("feast.permissions.auth.oidc_token_parser.PyJWKClient.get_signing_key_from_jwt") +@patch("feast.permissions.auth.oidc_token_parser.jwt.decode") +@patch("feast.permissions.oidc_service.OIDCDiscoveryService._fetch_discovery_data") +def test_oidc_token_missing_roles_key_returns_empty( + mock_discovery_data, mock_jwt, mock_signing_key, mock_oauth2, oidc_config +): + signing_key = MagicMock() + signing_key.key = "a-key" + mock_signing_key.return_value = signing_key + + mock_discovery_data.return_value = { + "authorization_endpoint": "https://localhost:8080/realms/master/protocol/openid-connect/auth", + "token_endpoint": "https://localhost:8080/realms/master/protocol/openid-connect/token", + "jwks_uri": "https://localhost:8080/realms/master/protocol/openid-connect/certs", + } + + user_data = { + "preferred_username": "my-name", + "resource_access": {_CLIENT_ID: {}}, + } + mock_jwt.return_value = user_data + + access_token = "aaa-bbb-ccc" + token_parser = OidcTokenParser(auth_config=oidc_config) + user = asyncio.run( + token_parser.user_details_from_access_token(access_token=access_token) + ) + + assertpy.assert_that(user).is_type_of(User) + if isinstance(user, User): + assertpy.assert_that(user.username).is_equal_to("my-name") + assertpy.assert_that(user.roles).is_equal_to([]) + + +@patch( + "feast.permissions.auth.oidc_token_parser.OAuth2AuthorizationCodeBearer.__call__" +) +@patch("feast.permissions.auth.oidc_token_parser.PyJWKClient.get_signing_key_from_jwt") +@patch("feast.permissions.auth.oidc_token_parser.jwt.decode") +@patch("feast.permissions.oidc_service.OIDCDiscoveryService._fetch_discovery_data") +def test_oidc_token_extracts_groups( + mock_discovery_data, mock_jwt, mock_signing_key, mock_oauth2, oidc_config +): + signing_key = MagicMock() + signing_key.key = "a-key" + mock_signing_key.return_value = signing_key + + mock_discovery_data.return_value = { + "authorization_endpoint": "https://localhost:8080/realms/master/protocol/openid-connect/auth", + "token_endpoint": "https://localhost:8080/realms/master/protocol/openid-connect/token", + "jwks_uri": "https://localhost:8080/realms/master/protocol/openid-connect/certs", + } + + user_data = { + "preferred_username": "my-name", + "resource_access": {_CLIENT_ID: {"roles": ["reader"]}}, + "groups": ["banking-admin", "data-engineers"], + } + mock_jwt.return_value = user_data + + access_token = "aaa-bbb-ccc" + token_parser = OidcTokenParser(auth_config=oidc_config) + user = asyncio.run( + token_parser.user_details_from_access_token(access_token=access_token) + ) + + assertpy.assert_that(user).is_type_of(User) + if isinstance(user, User): + assertpy.assert_that(user.groups).is_equal_to( + ["banking-admin", "data-engineers"] + ) + assertpy.assert_that(user.has_matching_group(["banking-admin"])).is_true() + assertpy.assert_that(user.has_matching_group(["unknown-group"])).is_false() + assertpy.assert_that(user.namespaces).is_equal_to([]) + + +@patch( + "feast.permissions.auth.oidc_token_parser.OAuth2AuthorizationCodeBearer.__call__" +) +@patch("feast.permissions.auth.oidc_token_parser.PyJWKClient.get_signing_key_from_jwt") +@patch("feast.permissions.auth.oidc_token_parser.jwt.decode") +@patch("feast.permissions.oidc_service.OIDCDiscoveryService._fetch_discovery_data") +def test_oidc_token_extracts_groups_and_roles( + mock_discovery_data, mock_jwt, mock_signing_key, mock_oauth2, oidc_config +): + signing_key = MagicMock() + signing_key.key = "a-key" + mock_signing_key.return_value = signing_key + + mock_discovery_data.return_value = { + "authorization_endpoint": "https://localhost:8080/realms/master/protocol/openid-connect/auth", + "token_endpoint": "https://localhost:8080/realms/master/protocol/openid-connect/token", + "jwks_uri": "https://localhost:8080/realms/master/protocol/openid-connect/certs", + } + + user_data = { + "preferred_username": "my-name", + "resource_access": {_CLIENT_ID: {"roles": ["reader", "writer"]}}, + "groups": ["banking-admin", "data-engineers"], + } + mock_jwt.return_value = user_data + + access_token = "aaa-bbb-ccc" + token_parser = OidcTokenParser(auth_config=oidc_config) + user = asyncio.run( + token_parser.user_details_from_access_token(access_token=access_token) + ) + + assertpy.assert_that(user).is_type_of(User) + if isinstance(user, User): + assertpy.assert_that(user.username).is_equal_to("my-name") + assertpy.assert_that(sorted(user.roles)).is_equal_to( + sorted(["reader", "writer"]) + ) + assertpy.assert_that(user.groups).is_equal_to( + ["banking-admin", "data-engineers"] + ) + assertpy.assert_that(user.has_matching_role(["reader"])).is_true() + assertpy.assert_that(user.has_matching_group(["banking-admin"])).is_true() @patch( @@ -131,8 +259,8 @@ async def mock_oath2(self, request): assertpy.assert_that(user).is_type_of(User) if isinstance(user, User): assertpy.assert_that(user.username).is_equal_to("my-name") - assertpy.assert_that(user.roles.sort()).is_equal_to( - ["reader", "writer"].sort() + assertpy.assert_that(sorted(user.roles)).is_equal_to( + sorted(["reader", "writer"]) ) assertpy.assert_that(user.has_matching_role(["reader"])).is_true() assertpy.assert_that(user.has_matching_role(["writer"])).is_true() @@ -175,7 +303,7 @@ def test_k8s_token_validation_success( assertpy.assert_that(user).is_type_of(User) if isinstance(user, User): assertpy.assert_that(user.username).is_equal_to(f"{sa_namespace}:{sa_name}") - assertpy.assert_that(user.roles.sort()).is_equal_to(roles.sort()) + assertpy.assert_that(sorted(user.roles)).is_equal_to(sorted(roles)) for r in roles: assertpy.assert_that(user.has_matching_role([r])).is_true() assertpy.assert_that(user.has_matching_role(["foo"])).is_false() @@ -259,7 +387,91 @@ def test_k8s_inter_server_comm( assertpy.assert_that(user).is_type_of(User) if isinstance(user, User): assertpy.assert_that(user.username).is_equal_to(f"{sa_namespace}:{sa_name}") - assertpy.assert_that(user.roles.sort()).is_equal_to(roles.sort()) + assertpy.assert_that(sorted(user.roles)).is_equal_to(sorted(roles)) for r in roles: assertpy.assert_that(user.has_matching_role([r])).is_true() assertpy.assert_that(user.has_matching_role(["foo"])).is_false() + + +# --------------------------------------------------------------------------- +# OidcTokenParser — SA token routing +# --------------------------------------------------------------------------- + + +@patch("feast.permissions.auth.oidc_token_parser.jwt.decode") +@patch("feast.permissions.oidc_service.OIDCDiscoveryService._fetch_discovery_data") +def test_oidc_parser_handles_sa_token_via_token_review( + mock_discovery_data, mock_jwt_decode, oidc_config +): + """When a token contains kubernetes.io claim, _handle_sa_token is called (not the OIDC JWKS path).""" + mock_discovery_data.return_value = { + "authorization_endpoint": "https://localhost:8080/auth", + "token_endpoint": "https://localhost:8080/token", + "jwks_uri": "https://localhost:8080/certs", + } + + mock_jwt_decode.return_value = { + "kubernetes.io": {"namespace": "feast"}, + "sub": "system:serviceaccount:feast:feast", + } + + sa_user = User( + username="system:serviceaccount:feast:feast", + roles=[], + groups=[], + namespaces=["feast"], + ) + + token_parser = OidcTokenParser(auth_config=oidc_config) + + with patch.object( + token_parser, + "_validate_k8s_sa_token_and_extract_namespace", + return_value=sa_user, + ) as mock_handle: + user = asyncio.run( + token_parser.user_details_from_access_token(access_token="sa-token") + ) + mock_handle.assert_called_once_with("sa-token") + + assertpy.assert_that(user.username).is_equal_to("system:serviceaccount:feast:feast") + assertpy.assert_that(user.namespaces).is_equal_to(["feast"]) + assertpy.assert_that(user.roles).is_equal_to([]) + assertpy.assert_that(user.groups).is_equal_to([]) + + +@patch( + "feast.permissions.auth.oidc_token_parser.OAuth2AuthorizationCodeBearer.__call__" +) +@patch("feast.permissions.auth.oidc_token_parser.PyJWKClient.get_signing_key_from_jwt") +@patch("feast.permissions.auth.oidc_token_parser.jwt.decode") +@patch("feast.permissions.oidc_service.OIDCDiscoveryService._fetch_discovery_data") +def test_oidc_parser_routes_keycloak_token_normally( + mock_discovery_data, mock_jwt_decode, mock_signing_key, mock_oauth2, oidc_config +): + """When a token does NOT contain kubernetes.io claim, it should follow the OIDC path.""" + signing_key = MagicMock() + signing_key.key = "a-key" + mock_signing_key.return_value = signing_key + + mock_discovery_data.return_value = { + "authorization_endpoint": "https://localhost:8080/auth", + "token_endpoint": "https://localhost:8080/token", + "jwks_uri": "https://localhost:8080/certs", + } + + keycloak_payload = { + "preferred_username": "testuser", + "resource_access": {_CLIENT_ID: {"roles": ["reader"]}}, + "groups": ["data-team"], + } + mock_jwt_decode.return_value = keycloak_payload + + token_parser = OidcTokenParser(auth_config=oidc_config) + user = asyncio.run( + token_parser.user_details_from_access_token(access_token="keycloak-jwt") + ) + + assertpy.assert_that(user.username).is_equal_to("testuser") + assertpy.assert_that(user.roles).is_equal_to(["reader"]) + assertpy.assert_that(user.groups).is_equal_to(["data-team"]) diff --git a/sdk/python/tests/unit/permissions/test_oidc_token_passthrough.py b/sdk/python/tests/unit/permissions/test_oidc_token_passthrough.py new file mode 100644 index 00000000000..e0766ad6b0e --- /dev/null +++ b/sdk/python/tests/unit/permissions/test_oidc_token_passthrough.py @@ -0,0 +1,431 @@ +""" +Tests for OIDC client-side token passthrough feature. + +Covers: + - Config validation (OidcClientAuthConfig) + - Token manager (OidcAuthClientManager.get_token) + - Routing (RepoConfig.auth_config property) +""" + +import os +from unittest.mock import MagicMock, patch + +import pytest + +from feast.permissions.auth_model import OidcClientAuthConfig +from feast.permissions.client.oidc_authentication_client_manager import ( + OidcAuthClientManager, +) +from feast.repo_config import RepoConfig + +# --------------------------------------------------------------------------- +# Config validation +# --------------------------------------------------------------------------- + + +class TestOidcClientAuthConfigValidation: + def test_bare_oidc_valid(self): + cfg = OidcClientAuthConfig(type="oidc") + assert cfg.token_env_var is None + assert cfg.auth_discovery_url is None + assert cfg.client_id is None + + def test_token_alone_valid(self): + cfg = OidcClientAuthConfig(type="oidc", token="eyJhbGciOiJSUzI1NiJ9.test") + assert cfg.token == "eyJhbGciOiJSUzI1NiJ9.test" + + def test_token_env_var_alone_valid(self): + cfg = OidcClientAuthConfig(type="oidc", token_env_var="MY_VAR") + assert cfg.token_env_var == "MY_VAR" + + def test_token_plus_custom_env_var_invalid(self): + with pytest.raises(ValueError, match="Only one of"): + OidcClientAuthConfig( + type="oidc", + token="eyJtoken", + token_env_var="MY_VAR", + ) + + def test_client_secret_without_discovery_url_invalid(self): + with pytest.raises( + ValueError, match="Incomplete configuration for 'client_credentials'" + ): + OidcClientAuthConfig( + type="oidc", + client_secret="my-secret", # pragma: allowlist secret + ) + + def test_full_client_credentials_valid(self): + cfg = OidcClientAuthConfig( + type="oidc", + client_secret="my-secret", # pragma: allowlist secret + auth_discovery_url="https://idp.example.com/.well-known/openid-configuration", + client_id="feast-client", + ) + assert cfg.client_secret == "my-secret" # pragma: allowlist secret + + def test_full_ropg_valid(self): + cfg = OidcClientAuthConfig( + type="oidc", + username="user1", + password="pass1", # pragma: allowlist secret + client_secret="my-secret", # pragma: allowlist secret + auth_discovery_url="https://idp.example.com/.well-known/openid-configuration", + client_id="feast-client", + ) + assert cfg.username == "user1" + + def test_ropg_without_discovery_url_invalid(self): + with pytest.raises( + ValueError, match="Incomplete configuration for 'client_credentials'" + ): + OidcClientAuthConfig( + type="oidc", + username="user1", + password="pass1", # pragma: allowlist secret + client_secret="my-secret", # pragma: allowlist secret + ) + + def test_username_without_client_secret_invalid(self): + with pytest.raises( + ValueError, match="Incomplete configuration for 'client_credentials'" + ): + OidcClientAuthConfig( + type="oidc", + username="user1", + password="pass1", # pragma: allowlist secret + ) + + def test_token_plus_client_secret_invalid(self): + with pytest.raises(ValueError, match="Only one of"): + OidcClientAuthConfig( + type="oidc", + token="jwt", + client_secret="secret", # pragma: allowlist secret + auth_discovery_url="https://idp/.well-known/openid-configuration", + client_id="feast-client", + ) + + def test_token_env_var_with_discovery_url_invalid(self): + with pytest.raises( + ValueError, match="Incomplete configuration for 'client_credentials'" + ): + OidcClientAuthConfig( + type="oidc", + token_env_var="MY_VAR", + auth_discovery_url="https://idp/.well-known/openid-configuration", + client_id="feast-client", + ) + + def test_token_with_discovery_url_invalid(self): + with pytest.raises( + ValueError, match="Incomplete configuration for 'client_credentials'" + ): + OidcClientAuthConfig( + type="oidc", + token="eyJ.test", + auth_discovery_url="https://idp/.well-known/openid-configuration", + client_id="feast-client", + ) + + +# --------------------------------------------------------------------------- +# Token manager +# --------------------------------------------------------------------------- + + +class TestOidcAuthClientManagerGetToken: + def _make_manager(self, **kwargs) -> OidcAuthClientManager: + cfg = OidcClientAuthConfig(type="oidc", **kwargs) + return OidcAuthClientManager(cfg) + + @patch( + "feast.permissions.client.oidc_authentication_client_manager.OIDCDiscoveryService" + ) + def test_token_returned_directly(self, mock_discovery_cls): + mgr = self._make_manager(token="my-static-jwt") + assert mgr.get_token() == "my-static-jwt" + mock_discovery_cls.assert_not_called() + + @patch( + "feast.permissions.client.oidc_authentication_client_manager.OidcAuthClientManager._read_sa_token", + return_value=None, + ) + def test_no_token_source_raises(self, _mock_sa): + mgr = self._make_manager() + with pytest.raises(PermissionError, match="No OIDC token source configured"): + mgr.get_token() + + @patch.dict(os.environ, {"FEAST_OIDC_TOKEN": "env-jwt-value"}) + @patch( + "feast.permissions.client.oidc_authentication_client_manager.OIDCDiscoveryService" + ) + def test_explicit_feast_env_var(self, mock_discovery_cls): + mgr = self._make_manager(token_env_var="FEAST_OIDC_TOKEN") + assert mgr.get_token() == "env-jwt-value" + mock_discovery_cls.assert_not_called() + + @patch.dict(os.environ, {"FEAST_OIDC_TOKEN": "fallback-jwt"}) + @patch( + "feast.permissions.client.oidc_authentication_client_manager.OIDCDiscoveryService" + ) + def test_bare_config_falls_back_to_well_known_env(self, mock_discovery_cls): + mgr = self._make_manager() + assert mgr.get_token() == "fallback-jwt" + mock_discovery_cls.assert_not_called() + + @patch.dict(os.environ, {"FEAST_OIDC_TOKEN": "should-not-win"}, clear=False) + @patch("feast.permissions.client.oidc_authentication_client_manager.requests") + @patch( + "feast.permissions.client.oidc_authentication_client_manager.OIDCDiscoveryService" + ) + def test_network_config_not_overridden_by_well_known_env( + self, mock_discovery_cls, mock_requests + ): + mock_discovery_instance = MagicMock() + mock_discovery_instance.get_token_url.return_value = "https://idp/token" + mock_discovery_cls.return_value = mock_discovery_instance + + mock_response = MagicMock() + mock_response.status_code = 200 + mock_response.json.return_value = {"access_token": "idp-token"} + mock_requests.post.return_value = mock_response + + mgr = self._make_manager( + client_secret="secret", # pragma: allowlist secret + auth_discovery_url="https://idp/.well-known/openid-configuration", + client_id="feast-client", + ) + assert mgr.get_token() == "idp-token" + + @patch.dict(os.environ, {"CUSTOM_TOKEN_VAR": "custom-env-jwt"}) + @patch( + "feast.permissions.client.oidc_authentication_client_manager.OIDCDiscoveryService" + ) + def test_custom_env_var_read(self, mock_discovery_cls): + mgr = self._make_manager(token_env_var="CUSTOM_TOKEN_VAR") + assert mgr.get_token() == "custom-env-jwt" + mock_discovery_cls.assert_not_called() + + @patch.dict(os.environ, {}, clear=False) + @patch("feast.permissions.client.oidc_authentication_client_manager.requests") + @patch( + "feast.permissions.client.oidc_authentication_client_manager.OIDCDiscoveryService" + ) + def test_fallthrough_to_client_credentials(self, mock_discovery_cls, mock_requests): + os.environ.pop("FEAST_OIDC_TOKEN", None) + + mock_discovery_instance = MagicMock() + mock_discovery_instance.get_token_url.return_value = "https://idp/token" + mock_discovery_cls.return_value = mock_discovery_instance + + mock_response = MagicMock() + mock_response.status_code = 200 + mock_response.json.return_value = {"access_token": "network-token"} + mock_requests.post.return_value = mock_response + + mgr = self._make_manager( + client_secret="secret", # pragma: allowlist secret + auth_discovery_url="https://idp/.well-known/openid-configuration", + client_id="feast-client", + ) + assert mgr.get_token() == "network-token" + mock_discovery_cls.assert_called_once() + + @patch.dict(os.environ, {}, clear=False) + @patch("feast.permissions.client.oidc_authentication_client_manager.requests") + @patch( + "feast.permissions.client.oidc_authentication_client_manager.OIDCDiscoveryService" + ) + def test_ropg_flow(self, mock_discovery_cls, mock_requests): + os.environ.pop("FEAST_OIDC_TOKEN", None) + + mock_discovery_instance = MagicMock() + mock_discovery_instance.get_token_url.return_value = "https://idp/token" + mock_discovery_cls.return_value = mock_discovery_instance + + mock_response = MagicMock() + mock_response.status_code = 200 + mock_response.json.return_value = {"access_token": "ropg-token"} + mock_requests.post.return_value = mock_response + + mgr = self._make_manager( + username="user1", + password="pass1", # pragma: allowlist secret + client_secret="secret", # pragma: allowlist secret + auth_discovery_url="https://idp/.well-known/openid-configuration", + client_id="feast-client", + ) + assert mgr.get_token() == "ropg-token" + + call_args = mock_requests.post.call_args + assert call_args[1]["data"]["grant_type"] == "password" + assert call_args[1]["data"]["username"] == "user1" + + @patch( + "feast.permissions.client.oidc_authentication_client_manager.OIDCDiscoveryService" + ) + def test_token_takes_priority_over_env_var(self, mock_discovery_cls): + with patch.dict(os.environ, {"FEAST_OIDC_TOKEN": "env-token"}): + mgr = self._make_manager(token="config-token") + assert mgr.get_token() == "config-token" + mock_discovery_cls.assert_not_called() + + @patch.dict(os.environ, {}, clear=False) + def test_configured_env_var_missing_raises(self): + os.environ.pop("MY_CUSTOM_VAR", None) + mgr = self._make_manager(token_env_var="MY_CUSTOM_VAR") + with pytest.raises(PermissionError, match="token_env_var='MY_CUSTOM_VAR'"): + mgr.get_token() + + @patch.dict(os.environ, {"FEAST_OIDC_TOKEN": "stale-token"}, clear=False) + def test_configured_env_var_missing_does_not_fall_through(self): + os.environ.pop("MY_CUSTOM_VAR", None) + mgr = self._make_manager(token_env_var="MY_CUSTOM_VAR") + with pytest.raises(PermissionError, match="token_env_var='MY_CUSTOM_VAR'"): + mgr.get_token() + + # --- SA token file fallback tests --- + + @patch.dict(os.environ, {}, clear=False) + @patch( + "feast.permissions.client.oidc_authentication_client_manager.OidcAuthClientManager._read_sa_token", + return_value="sa-jwt-from-file", + ) + def test_sa_token_file_read(self, _mock_sa): + os.environ.pop("FEAST_OIDC_TOKEN", None) + mgr = self._make_manager() + assert mgr.get_token() == "sa-jwt-from-file" + + @patch.dict(os.environ, {}, clear=False) + @patch( + "feast.permissions.client.oidc_authentication_client_manager.OidcAuthClientManager._read_sa_token", + return_value=None, + ) + def test_sa_token_file_missing_raises(self, _mock_sa): + os.environ.pop("FEAST_OIDC_TOKEN", None) + mgr = self._make_manager() + with pytest.raises(PermissionError, match="No OIDC token source configured"): + mgr.get_token() + + @patch.dict(os.environ, {"FEAST_OIDC_TOKEN": "env-token"}, clear=False) + @patch( + "feast.permissions.client.oidc_authentication_client_manager.OidcAuthClientManager._read_sa_token", + return_value="sa-jwt-from-file", + ) + def test_feast_env_takes_priority_over_sa_token(self, _mock_sa): + mgr = self._make_manager() + assert mgr.get_token() == "env-token" + _mock_sa.assert_not_called() + + @patch( + "feast.permissions.client.oidc_authentication_client_manager.OidcAuthClientManager._read_sa_token", + return_value="sa-jwt-from-file", + ) + @patch( + "feast.permissions.client.oidc_authentication_client_manager.OIDCDiscoveryService" + ) + def test_explicit_token_skips_sa_file(self, mock_discovery_cls, _mock_sa): + mgr = self._make_manager(token="my-explicit-token") + assert mgr.get_token() == "my-explicit-token" + _mock_sa.assert_not_called() + + @patch.dict(os.environ, {}, clear=False) + @patch( + "feast.permissions.client.oidc_authentication_client_manager.OidcAuthClientManager._read_sa_token", + return_value="sa-jwt-from-file", + ) + @patch("feast.permissions.client.oidc_authentication_client_manager.requests") + @patch( + "feast.permissions.client.oidc_authentication_client_manager.OIDCDiscoveryService" + ) + def test_client_secret_skips_sa_file( + self, mock_discovery_cls, mock_requests, _mock_sa + ): + os.environ.pop("FEAST_OIDC_TOKEN", None) + + mock_discovery_instance = MagicMock() + mock_discovery_instance.get_token_url.return_value = "https://idp/token" + mock_discovery_cls.return_value = mock_discovery_instance + + mock_response = MagicMock() + mock_response.status_code = 200 + mock_response.json.return_value = {"access_token": "network-token"} + mock_requests.post.return_value = mock_response + + mgr = self._make_manager( + client_secret="secret", # pragma: allowlist secret + auth_discovery_url="https://idp/.well-known/openid-configuration", + client_id="feast-client", + ) + assert mgr.get_token() == "network-token" + _mock_sa.assert_not_called() + + +# --------------------------------------------------------------------------- +# Routing (RepoConfig.auth_config property) +# --------------------------------------------------------------------------- + + +class TestOidcClientRouting: + def _make_repo_config(self, auth_dict: dict) -> RepoConfig: + return RepoConfig( + project="test_project", + registry="data/registry.db", + provider="local", + auth=auth_dict, + ) + + def test_bare_oidc_routes_to_client(self): + rc = self._make_repo_config({"type": "oidc"}) + assert isinstance(rc.auth_config, OidcClientAuthConfig) + + def test_token_routes_to_client(self): + rc = self._make_repo_config({"type": "oidc", "token": "x"}) + assert isinstance(rc.auth_config, OidcClientAuthConfig) + assert rc.auth_config.token == "x" + + def test_token_env_var_routes_to_client(self): + rc = self._make_repo_config({"type": "oidc", "token_env_var": "MY_VAR"}) + assert isinstance(rc.auth_config, OidcClientAuthConfig) + assert rc.auth_config.token_env_var == "MY_VAR" + + def test_server_config_routes_to_oidc_auth_config(self): + from feast.permissions.auth_model import OidcAuthConfig + + rc = self._make_repo_config( + { + "type": "oidc", + "auth_discovery_url": "https://idp/.well-known/openid-configuration", + "client_id": "feast-server", + } + ) + assert isinstance(rc.auth_config, OidcAuthConfig) + assert type(rc.auth_config) is OidcAuthConfig + + def test_ropg_routes_to_client(self): + rc = self._make_repo_config( + { + "type": "oidc", + "auth_discovery_url": "https://idp/.well-known/openid-configuration", + "client_id": "feast-client", + "client_secret": "secret", # pragma: allowlist secret + "username": "user1", + "password": "pass1", # pragma: allowlist secret + } + ) + assert isinstance(rc.auth_config, OidcClientAuthConfig) + + def test_incomplete_ropg_routes_to_client_with_actionable_error(self): + with pytest.raises( + ValueError, match="Incomplete configuration for 'client_credentials'" + ): + self._make_repo_config( + { + "type": "oidc", + "auth_discovery_url": "https://idp/.well-known/openid-configuration", + "client_id": "feast-client", + "username": "user1", + "password": "pass1", # pragma: allowlist secret + } + ).auth_config diff --git a/sdk/python/tests/unit/test_aggregation_ops.py b/sdk/python/tests/unit/test_aggregation_ops.py index 0a5f0bd6ed5..fd4f147f5d8 100644 --- a/sdk/python/tests/unit/test_aggregation_ops.py +++ b/sdk/python/tests/unit/test_aggregation_ops.py @@ -1,13 +1,18 @@ +from datetime import timedelta + +import pandas as pd import pytest -from feast.aggregation import aggregation_specs_to_agg_ops +from feast.aggregation import Aggregation, aggregation_specs_to_agg_ops +from feast.aggregation.tiling.base import get_ir_metadata_for_aggregation class DummyAggregation: - def __init__(self, *, function: str, column: str, time_window=None): + def __init__(self, *, function: str, column: str, time_window=None, name: str = ""): self.function = function self.column = column self.time_window = time_window + self.name = name def test_aggregation_specs_to_agg_ops_success(): @@ -42,3 +47,91 @@ def test_aggregation_specs_to_agg_ops_time_window_unsupported(error_message: str agg_specs, time_window_unsupported_error_message=error_message, ) + + +def test_aggregation_specs_to_agg_ops_custom_name(): + agg_specs = [ + DummyAggregation( + function="sum", + column="seconds_watched", + name="sum_seconds_watched_per_ad_1d", + ), + ] + + agg_ops = aggregation_specs_to_agg_ops( + agg_specs, + time_window_unsupported_error_message="Time window aggregation is not supported.", + ) + + assert agg_ops == { + "sum_seconds_watched_per_ad_1d": ("sum", "seconds_watched"), + } + + +def test_aggregation_specs_to_agg_ops_mixed_names(): + agg_specs = [ + DummyAggregation(function="sum", column="trips", name="total_trips"), + DummyAggregation(function="mean", column="fare"), + ] + + agg_ops = aggregation_specs_to_agg_ops( + agg_specs, + time_window_unsupported_error_message="Time window aggregation is not supported.", + ) + + assert agg_ops == { + "total_trips": ("sum", "trips"), + "mean_fare": ("mean", "fare"), + } + + +def test_aggregation_round_trip_with_name(): + agg = Aggregation( + column="seconds_watched", + function="sum", + time_window=timedelta(days=1), + name="sum_seconds_watched_per_ad_1d", + ) + proto = agg.to_proto() + assert proto.name == "sum_seconds_watched_per_ad_1d" + + restored = Aggregation.from_proto(proto) + assert restored.name == "sum_seconds_watched_per_ad_1d" + assert restored == agg + + +def test_count_distinct_agg_ops(): + """aggregation_specs_to_agg_ops maps count_distinct to the nunique pandas function.""" + agg_specs = [DummyAggregation(function="count_distinct", column="item_id")] + + agg_ops = aggregation_specs_to_agg_ops( + agg_specs, + time_window_unsupported_error_message="no windows", + ) + + assert agg_ops == {"count_distinct_item_id": ("nunique", "item_id")} + + +def test_count_distinct_result(): + """count_distinct via nunique returns the number of unique values per group.""" + from feast.infra.compute_engines.backends.pandas_backend import PandasBackend + + agg_specs = [DummyAggregation(function="count_distinct", column="item_id")] + agg_ops = aggregation_specs_to_agg_ops( + agg_specs, + time_window_unsupported_error_message="no windows", + ) + + df = pd.DataFrame({"user": ["A", "A", "B"], "item_id": [1, 2, 1]}) + result = PandasBackend().groupby_agg(df, ["user"], agg_ops) + result = result.set_index("user") + + assert result.loc["A", "count_distinct_item_id"] == 2 + assert result.loc["B", "count_distinct_item_id"] == 1 + + +def test_count_distinct_tiling_raises(): + """get_ir_metadata_for_aggregation raises ValueError for count_distinct.""" + agg = Aggregation(column="item_id", function="count_distinct") + with pytest.raises(ValueError, match="count_distinct does not support tiling"): + get_ir_metadata_for_aggregation(agg, "count_distinct_item_id") diff --git a/sdk/python/tests/unit/test_arrow_error_decorator.py b/sdk/python/tests/unit/test_arrow_error_decorator.py index fc350d34c0a..af753ad8f00 100644 --- a/sdk/python/tests/unit/test_arrow_error_decorator.py +++ b/sdk/python/tests/unit/test_arrow_error_decorator.py @@ -1,8 +1,15 @@ +from unittest.mock import MagicMock, patch + import pyarrow.flight as fl import pytest +from pydantic import ValidationError -from feast.arrow_error_handler import arrow_client_error_handling_decorator -from feast.errors import PermissionNotFoundException +from feast.arrow_error_handler import ( + _get_exception_data, + arrow_client_error_handling_decorator, +) +from feast.errors import FeatureViewNotFoundException, PermissionNotFoundException +from feast.infra.offline_stores.remote import RemoteOfflineStoreConfig permissionError = PermissionNotFoundException("dummy_name", "dummy_project") @@ -31,3 +38,194 @@ def test_rest_error_handling_with_feast_exception(error, expected_raised_error): match=str(expected_raised_error), ): decorated_method(error) + + +class TestArrowClientRetry: + @patch("feast.arrow_error_handler.time.sleep") + def test_retries_on_flight_unavailable_error(self, mock_sleep): + client = MagicMock() + client._connection_retries = 3 + call_count = 0 + + @arrow_client_error_handling_decorator + def flaky_method(self_arg): + nonlocal call_count + call_count += 1 + if call_count < 3: + raise fl.FlightUnavailableError("Connection refused") + return "success" + + result = flaky_method(client) + assert result == "success" + assert call_count == 3 + assert mock_sleep.call_count == 2 + + @patch("feast.arrow_error_handler.time.sleep") + def test_raises_after_max_retries_exhausted(self, mock_sleep): + client = MagicMock() + client._connection_retries = 3 + + @arrow_client_error_handling_decorator + def always_unavailable(self_arg): + raise fl.FlightUnavailableError("Connection refused") + + with pytest.raises(fl.FlightUnavailableError, match="Connection refused"): + always_unavailable(client) + assert mock_sleep.call_count == 3 + + @patch("feast.arrow_error_handler.time.sleep") + def test_respects_connection_retries_from_client(self, mock_sleep): + client = MagicMock() + client._connection_retries = 1 + call_count = 0 + + @arrow_client_error_handling_decorator + def method_on_client(self_arg): + nonlocal call_count + call_count += 1 + raise fl.FlightUnavailableError("Connection refused") + + with pytest.raises(fl.FlightUnavailableError): + method_on_client(client) + + assert call_count == 2 # 1 initial + 1 retry + assert mock_sleep.call_count == 1 + + @patch("feast.arrow_error_handler.time.sleep") + def test_no_retry_on_non_transient_errors(self, mock_sleep): + client = MagicMock() + client._connection_retries = 3 + call_count = 0 + + @arrow_client_error_handling_decorator + def method_with_error(self_arg): + nonlocal call_count + call_count += 1 + raise fl.FlightError("Permanent error") + + with pytest.raises(fl.FlightError, match="Permanent error"): + method_with_error(client) + + assert call_count == 1 + mock_sleep.assert_not_called() + + @patch("feast.arrow_error_handler.time.sleep") + def test_exponential_backoff_timing(self, mock_sleep): + client = MagicMock() + client._connection_retries = 3 + + @arrow_client_error_handling_decorator + def always_unavailable(self_arg): + raise fl.FlightUnavailableError("Connection refused") + + with pytest.raises(fl.FlightUnavailableError): + always_unavailable(client) + + wait_times = [call.args[0] for call in mock_sleep.call_args_list] + assert wait_times == [0.5, 1.0, 2.0] + + @patch("feast.arrow_error_handler.time.sleep") + def test_zero_retries_disables_retry(self, mock_sleep): + client = MagicMock() + client._connection_retries = 0 + call_count = 0 + + @arrow_client_error_handling_decorator + def method_on_client(self_arg): + nonlocal call_count + call_count += 1 + raise fl.FlightUnavailableError("Connection refused") + + with pytest.raises(fl.FlightUnavailableError): + method_on_client(client) + + assert call_count == 1 + mock_sleep.assert_not_called() + + @patch("feast.arrow_error_handler.time.sleep") + def test_no_retry_for_standalone_stream_functions(self, mock_sleep): + """Standalone functions (write_table, read_all) where args[0] is a + writer/reader should not retry since broken streams can't be reused.""" + writer = MagicMock(spec=[]) # no _connection_retries attribute + call_count = 0 + + @arrow_client_error_handling_decorator + def write_table(w): + nonlocal call_count + call_count += 1 + raise fl.FlightUnavailableError("stream broken") + + with pytest.raises(fl.FlightUnavailableError, match="stream broken"): + write_table(writer) + + assert call_count == 1 + mock_sleep.assert_not_called() + + @patch("feast.arrow_error_handler.time.sleep") + def test_negative_connection_retries_treated_as_zero(self, mock_sleep): + """Negative _connection_retries must not skip function execution.""" + client = MagicMock() + client._connection_retries = -1 + call_count = 0 + + @arrow_client_error_handling_decorator + def method_on_client(self_arg): + nonlocal call_count + call_count += 1 + return "ok" + + result = method_on_client(client) + assert result == "ok" + assert call_count == 1 + mock_sleep.assert_not_called() + + def test_config_rejects_negative_connection_retries(self): + with pytest.raises(ValidationError): + RemoteOfflineStoreConfig(host="localhost", connection_retries=-1) + + +class TestGetExceptionData: + def test_non_string_input_returns_empty(self): + assert _get_exception_data(12345) == "" + assert _get_exception_data(None) == "" + assert _get_exception_data(b"bytes") == "" + + def test_no_flight_error_prefix_returns_empty(self): + assert _get_exception_data("some random error") == "" + + def test_flight_error_prefix_without_json_returns_empty(self): + assert _get_exception_data("Flight error: no json here") == "" + + def test_extracts_json_from_flight_error(self): + fv_error = FeatureViewNotFoundException("my_view", "my_project") + error_str = f"Flight error: {fv_error.to_error_detail()}" + result = _get_exception_data(error_str) + assert '"class": "FeatureViewNotFoundException"' in result + assert '"module": "feast.errors"' in result + + def test_extracts_json_with_trailing_text(self): + fv_error = FeatureViewNotFoundException("my_view", "my_project") + error_str = ( + f"Flight error: {fv_error.to_error_detail()}. " + "gRPC client debug context: some extra info" + ) + result = _get_exception_data(error_str) + assert '"class": "FeatureViewNotFoundException"' in result + assert '"module": "feast.errors"' in result + + def test_extracts_json_with_grpc_debug_context_containing_braces(self): + fv_error = FeatureViewNotFoundException("my_view", "my_project") + error_str = ( + f"Flight error: {fv_error.to_error_detail()}. " + "gRPC client debug context: UNKNOWN:Error received from peer " + 'ipv4:127.0.0.1:59930 {grpc_message:"Flight error: ...", ' + 'grpc_status:2, created_time:"2026-03-17T17:32:07"}' + ) + result = _get_exception_data(error_str) + assert '"class": "FeatureViewNotFoundException"' in result + assert '"module": "feast.errors"' in result + from feast.errors import FeastError + + reconstructed = FeastError.from_error_detail(result) + assert reconstructed is not None + assert "my_view" in str(reconstructed) diff --git a/sdk/python/tests/unit/test_doc_embedder.py b/sdk/python/tests/unit/test_doc_embedder.py new file mode 100644 index 00000000000..2a9e324e0c4 --- /dev/null +++ b/sdk/python/tests/unit/test_doc_embedder.py @@ -0,0 +1,653 @@ +import os +from unittest.mock import MagicMock, Mock, patch + +import numpy as np +import pandas as pd +import pytest + +from feast.chunker import BaseChunker, ChunkingConfig, TextChunker +from feast.doc_embedder import DocEmbedder, LogicalLayerFn, default_logical_layer_fn +from feast.embedder import BaseEmbedder, EmbeddingConfig, MultiModalEmbedder + + +@pytest.fixture +def sample_documents_df(): + """Small DataFrame with 3 documents of varying lengths.""" + return pd.DataFrame( + { + "id": ["doc1", "doc2", "doc3"], + "text": [ + " ".join([f"word{i}" for i in range(150)]), + " ".join([f"term{i}" for i in range(200)]), + " ".join([f"item{i}" for i in range(50)]), + ], + "type": ["article", "paper", "note"], + } + ) + + +class TestTextChunker: + def test_basic_chunking(self): + """Given ~200 words, returns chunks with correct keys and count.""" + chunker = TextChunker() + text = " ".join([f"word{i}" for i in range(200)]) + + chunks = chunker.load_parse_and_chunk( + source=text, source_id="doc1", source_column="text" + ) + + assert len(chunks) > 0 + for chunk in chunks: + assert "chunk_id" in chunk + assert "original_id" in chunk + assert "text" in chunk + assert "chunk_index" in chunk + assert chunk["original_id"] == "doc1" + + assert len(chunks) == 3 + assert chunks[0]["chunk_id"] == "doc1_0" + assert chunks[1]["chunk_id"] == "doc1_1" + assert chunks[2]["chunk_id"] == "doc1_2" + assert chunks[0]["chunk_index"] == 0 + assert chunks[2]["chunk_index"] == 2 + + def test_overlap(self): + """Consecutive chunks share exactly chunk_overlap words.""" + config = ChunkingConfig( + chunk_size=10, chunk_overlap=3, min_chunk_size=3, max_chunk_chars=None + ) + chunker = TextChunker(config=config) + text = " ".join([f"w{i}" for i in range(20)]) + + chunks = chunker.load_parse_and_chunk( + source=text, source_id="doc1", source_column="text" + ) + assert len(chunks) >= 2 + + words_0 = chunks[0]["text"].split() + words_1 = chunks[1]["text"].split() + + assert words_0[-3:] == words_1[:3] + + def test_min_chunk_size_filters_small_trailing(self): + """Trailing chunk smaller than min_chunk_size is dropped.""" + config = ChunkingConfig( + chunk_size=10, chunk_overlap=0, min_chunk_size=5, max_chunk_chars=None + ) + chunker = TextChunker(config=config) + text = " ".join([f"w{i}" for i in range(13)]) + + chunks = chunker.load_parse_and_chunk( + source=text, source_id="doc1", source_column="text" + ) + + assert len(chunks) == 1 + + def test_max_chunk_chars_truncation(self): + """Chunks exceeding max_chunk_chars are truncated.""" + config = ChunkingConfig( + chunk_size=100, chunk_overlap=0, min_chunk_size=1, max_chunk_chars=50 + ) + chunker = TextChunker(config=config) + text = " ".join([f"longword{i}" for i in range(200)]) + + chunks = chunker.load_parse_and_chunk( + source=text, source_id="doc1", source_column="text" + ) + + assert len(chunks) > 0 + for chunk in chunks: + assert len(chunk["text"]) <= 50 + + def test_empty_text_returns_no_chunks(self): + """Empty string produces zero chunks.""" + chunker = TextChunker() + + chunks = chunker.load_parse_and_chunk( + source="", source_id="doc1", source_column="text" + ) + + assert chunks == [] + + def test_chunk_dataframe(self, sample_documents_df): + """Chunking a multi-row DataFrame returns a flattened DataFrame.""" + chunker = TextChunker() + + result = chunker.chunk_dataframe( + df=sample_documents_df, + id_column="id", + source_column="text", + type_column="type", + ) + + assert isinstance(result, pd.DataFrame) + assert "chunk_id" in result.columns + assert "original_id" in result.columns + assert "text" in result.columns + assert "chunk_index" in result.columns + assert len(result) >= len(sample_documents_df) + assert set(result["original_id"].unique()) == {"doc1", "doc2", "doc3"} + + +def test_base_chunker_cannot_instantiate(): + """BaseChunker is abstract and cannot be instantiated directly.""" + with pytest.raises(TypeError): + BaseChunker() + + +def test_base_embedder_cannot_instantiate(): + """BaseEmbedder is abstract and cannot be instantiated directly.""" + with pytest.raises(TypeError): + BaseEmbedder() + + +class TestMultiModalEmbedder: + def test_supported_modalities(self): + """After init, supported_modalities returns text and image.""" + embedder = MultiModalEmbedder() + modalities = embedder.supported_modalities + + assert "text" in modalities + assert "image" in modalities + + def test_unsupported_modality_raises(self): + """Calling embed with unsupported modality raises ValueError.""" + embedder = MultiModalEmbedder() + + with pytest.raises(ValueError, match="Unsupported modality: 'video'"): + embedder.embed(["test"], "video") + + def test_text_embed_mocked(self): + """Text embedding calls encode with correct batch_size and show_progress.""" + embedder = MultiModalEmbedder() + + mock_model = MagicMock() + mock_model.encode.return_value = np.array([[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]]) + embedder._text_model = mock_model + + result = embedder.embed(["hello", "world"], "text") + + mock_model.encode.assert_called_once_with( + ["hello", "world"], + batch_size=64, + show_progress_bar=True, + ) + assert result.shape == (2, 3) + + def test_text_embed_custom_config(self): + """Text embedding respects custom EmbeddingConfig values.""" + config = EmbeddingConfig(batch_size=16, show_progress=False) + embedder = MultiModalEmbedder(config=config) + + mock_model = MagicMock() + mock_model.encode.return_value = np.array([[0.1, 0.2]]) + embedder._text_model = mock_model + + embedder.embed(["hello"], "text") + + mock_model.encode.assert_called_once_with( + ["hello"], + batch_size=16, + show_progress_bar=False, + ) + + def test_lazy_loading(self): + """Models are None until first accessed.""" + embedder = MultiModalEmbedder() + + assert embedder._text_model is None + assert embedder._image_model is None + assert embedder._image_processor is None + + def test_get_embedding_dim_text(self): + """get_embedding_dim for text delegates to text_model.""" + embedder = MultiModalEmbedder() + mock_model = MagicMock() + mock_model.get_sentence_embedding_dimension.return_value = 384 + embedder._text_model = mock_model + + assert embedder.get_embedding_dim("text") == 384 + mock_model.get_sentence_embedding_dimension.assert_called_once() + + def test_get_embedding_dim_unknown_modality(self): + """get_embedding_dim returns None for unrecognized modalities.""" + embedder = MultiModalEmbedder() + + assert embedder.get_embedding_dim("audio") is None + + def test_embed_dataframe(self): + """embed_dataframe adds embedding columns via column_mapping.""" + embedder = MultiModalEmbedder() + embedder.embed = Mock(return_value=np.array([[0.1, 0.2], [0.3, 0.4]])) + + df = pd.DataFrame({"text": ["hello", "world"], "id": [1, 2]}) + result = embedder.embed_dataframe( + df, column_mapping={"text": ("text", "text_embedding")} + ) + + assert "text_embedding" in result.columns + assert len(result) == 2 + embedder.embed.assert_called_once_with(["hello", "world"], "text") + + +def test_logical_layer_fn_protocol_check(): + """A matching function is recognized as LogicalLayerFn.""" + + def my_fn(df: pd.DataFrame) -> pd.DataFrame: + return df + + assert isinstance(my_fn, LogicalLayerFn) + + +def test_default_logical_layer_fn_output(): + """default_logical_layer_fn transforms columns correctly.""" + input_df = pd.DataFrame( + { + "chunk_id": ["c1", "c2"], + "text": ["hello", "world"], + "text_embedding": [[0.1, 0.2], [0.3, 0.4]], + "original_id": ["doc1", "doc1"], + } + ) + + result = default_logical_layer_fn(input_df) + + assert list(result.columns) == [ + "passage_id", + "text", + "embedding", + "event_timestamp", + "source_id", + ] + assert result["passage_id"].tolist() == ["c1", "c2"] + assert result["text"].tolist() == ["hello", "world"] + assert result["embedding"].tolist() == [[0.1, 0.2], [0.3, 0.4]] + assert result["source_id"].tolist() == ["doc1", "doc1"] + assert len(result["event_timestamp"]) == 2 + + +class TestDocEmbedder: + @patch("feast.repo_operations.apply_total") + @patch("feast.repo_config.load_repo_config") + def test_init_no_feature_view(self, mock_load_config, mock_apply_total, tmp_path): + """With create_feature_view=False, generate_repo_file is not called.""" + mock_chunker = MagicMock(spec=BaseChunker) + mock_embedder = MagicMock(spec=BaseEmbedder) + + with patch("feast.doc_embedder.generate_repo_file") as mock_gen: + doc_embedder = DocEmbedder( + repo_path=str(tmp_path), + feature_view_name="test_view", + chunker=mock_chunker, + embedder=mock_embedder, + create_feature_view=False, + ) + + mock_gen.assert_not_called() + assert doc_embedder.repo_path == str(tmp_path) + assert doc_embedder.feature_view_name == "test_view" + assert doc_embedder.chunker is mock_chunker + assert doc_embedder.embedder is mock_embedder + assert doc_embedder.logical_layer_fn is default_logical_layer_fn + + @patch("feast.repo_operations.apply_total") + @patch("feast.repo_config.load_repo_config") + def test_init_creates_feature_view( + self, mock_load_config, mock_apply_total, tmp_path + ): + """With create_feature_view=True, generate_repo_file and apply_repo are called.""" + mock_chunker = MagicMock(spec=BaseChunker) + mock_embedder = MagicMock(spec=BaseEmbedder) + mock_embedder.get_embedding_dim.return_value = None + + with patch("feast.doc_embedder.generate_repo_file") as mock_gen: + DocEmbedder( + repo_path=str(tmp_path), + feature_view_name="test_view", + chunker=mock_chunker, + embedder=mock_embedder, + create_feature_view=True, + ) + + mock_gen.assert_called_once_with( + repo_path=str(tmp_path), + feature_view_name="test_view", + vector_length=384, + ) + mock_load_config.assert_called_once() + mock_apply_total.assert_called_once() + + @patch("feast.repo_operations.apply_total") + @patch("feast.repo_config.load_repo_config") + def test_init_creates_feature_view_with_explicit_vector_length( + self, mock_load_config, mock_apply_total, tmp_path + ): + """Explicit vector_length overrides auto-detection.""" + mock_chunker = MagicMock(spec=BaseChunker) + mock_embedder = MagicMock(spec=BaseEmbedder) + + with patch("feast.doc_embedder.generate_repo_file") as mock_gen: + DocEmbedder( + repo_path=str(tmp_path), + feature_view_name="test_view", + chunker=mock_chunker, + embedder=mock_embedder, + create_feature_view=True, + vector_length=256, + ) + + mock_gen.assert_called_once_with( + repo_path=str(tmp_path), + feature_view_name="test_view", + vector_length=256, + ) + + @patch("feast.repo_operations.apply_total") + @patch("feast.repo_config.load_repo_config") + def test_init_creates_feature_view_auto_detects_vector_length( + self, mock_load_config, mock_apply_total, tmp_path + ): + """Auto-detected vector_length from embedder is used when not explicitly set.""" + mock_chunker = MagicMock(spec=BaseChunker) + mock_embedder = MagicMock(spec=BaseEmbedder) + mock_embedder.get_embedding_dim.return_value = 512 + + with patch("feast.doc_embedder.generate_repo_file") as mock_gen: + DocEmbedder( + repo_path=str(tmp_path), + feature_view_name="test_view", + chunker=mock_chunker, + embedder=mock_embedder, + create_feature_view=True, + ) + + mock_gen.assert_called_once_with( + repo_path=str(tmp_path), + feature_view_name="test_view", + vector_length=512, + ) + mock_embedder.get_embedding_dim.assert_called_once_with("text") + + @patch("feast.repo_operations.apply_total") + @patch("feast.repo_config.load_repo_config") + @patch("feast.feature_store.FeatureStore") + def test_embed_documents_full_chain( + self, mock_fs_cls, mock_load_config, mock_apply_total, tmp_path + ): + """embed_documents wires chunk -> embed -> logical_layer -> save correctly.""" + mock_chunker = MagicMock(spec=BaseChunker) + chunked_df = pd.DataFrame( + { + "chunk_id": ["doc1_0", "doc1_1"], + "original_id": ["doc1", "doc1"], + "text": ["chunk text 1", "chunk text 2"], + "chunk_index": [0, 1], + } + ) + mock_chunker.chunk_dataframe.return_value = chunked_df + + mock_embedder = MagicMock(spec=BaseEmbedder) + embedded_df = chunked_df.copy() + embedded_df["text_embedding"] = [[0.1, 0.2], [0.3, 0.4]] + mock_embedder.embed_dataframe.return_value = embedded_df + + transformed_df = pd.DataFrame( + { + "passage_id": ["doc1_0", "doc1_1"], + "text": ["chunk text 1", "chunk text 2"], + "embedding": [[0.1, 0.2], [0.3, 0.4]], + "source_id": ["doc1", "doc1"], + } + ) + logical_fn_tracker = MagicMock() + + def mock_logical_fn(df: pd.DataFrame) -> pd.DataFrame: + logical_fn_tracker(df) + return transformed_df + + doc_embedder = DocEmbedder( + repo_path=str(tmp_path), + chunker=mock_chunker, + embedder=mock_embedder, + logical_layer_fn=mock_logical_fn, + create_feature_view=False, + ) + + input_df = pd.DataFrame( + { + "id": ["doc1"], + "text": ["some long document text"], + "type": ["article"], + } + ) + + result = doc_embedder.embed_documents( + documents=input_df, + id_column="id", + source_column="text", + type_column="type", + ) + + mock_chunker.chunk_dataframe.assert_called_once() + chunk_kwargs = mock_chunker.chunk_dataframe.call_args[1] + assert chunk_kwargs["id_column"] == "id" + assert chunk_kwargs["source_column"] == "text" + assert chunk_kwargs["type_column"] == "type" + + mock_embedder.embed_dataframe.assert_called_once() + embed_args = mock_embedder.embed_dataframe.call_args + pd.testing.assert_frame_equal(embed_args[0][0], chunked_df) + assert embed_args[1]["column_mapping"] == {"text": ("text", "text_embedding")} + + logical_fn_tracker.assert_called_once() + pd.testing.assert_frame_equal(logical_fn_tracker.call_args[0][0], embedded_df) + + mock_fs_cls.return_value.write_to_online_store.assert_called_once() + save_kwargs = mock_fs_cls.return_value.write_to_online_store.call_args[1] + assert save_kwargs["feature_view_name"] == "text_feature_view" + + pd.testing.assert_frame_equal(result, transformed_df) + + @patch("feast.repo_operations.apply_total") + @patch("feast.repo_config.load_repo_config") + @patch("feast.feature_store.FeatureStore") + def test_embed_documents_default_column_mapping( + self, mock_fs_cls, mock_load_config, mock_apply_total, tmp_path + ): + """When column_mapping=None, default mapping is used.""" + mock_chunker = MagicMock(spec=BaseChunker) + mock_chunker.chunk_dataframe.return_value = pd.DataFrame( + { + "chunk_id": ["c1"], + "original_id": ["d1"], + "text": ["t"], + "chunk_index": [0], + } + ) + + mock_embedder = MagicMock(spec=BaseEmbedder) + mock_embedder.embed_dataframe.return_value = pd.DataFrame( + { + "chunk_id": ["c1"], + "original_id": ["d1"], + "text": ["t"], + "chunk_index": [0], + "text_embedding": [[0.1]], + } + ) + + doc_embedder = DocEmbedder( + repo_path=str(tmp_path), + chunker=mock_chunker, + embedder=mock_embedder, + create_feature_view=False, + ) + + doc_embedder.embed_documents( + documents=pd.DataFrame({"id": ["d1"], "text": ["t"]}), + id_column="id", + source_column="text", + column_mapping=None, + ) + + embed_call = mock_embedder.embed_dataframe.call_args + assert embed_call[1]["column_mapping"] == {"text": ("text", "text_embedding")} + + @patch("feast.repo_operations.apply_total") + @patch("feast.repo_config.load_repo_config") + @patch("feast.feature_store.FeatureStore") + def test_embed_documents_custom_column_mapping( + self, mock_fs_cls, mock_load_config, mock_apply_total, tmp_path + ): + """Custom column_mapping is forwarded to the embedder.""" + mock_chunker = MagicMock(spec=BaseChunker) + mock_chunker.chunk_dataframe.return_value = pd.DataFrame( + { + "chunk_id": ["c1"], + "original_id": ["d1"], + "content": ["t"], + "chunk_index": [0], + } + ) + + mock_embedder = MagicMock(spec=BaseEmbedder) + mock_embedder.embed_dataframe.return_value = pd.DataFrame( + { + "chunk_id": ["c1"], + "original_id": ["d1"], + "content": ["t"], + "chunk_index": [0], + "content_embedding": [[0.1]], + } + ) + + def mock_logical_fn(df: pd.DataFrame) -> pd.DataFrame: + return pd.DataFrame({"passage_id": ["c1"], "embedding": [[0.1]]}) + + doc_embedder = DocEmbedder( + repo_path=str(tmp_path), + chunker=mock_chunker, + embedder=mock_embedder, + logical_layer_fn=mock_logical_fn, + create_feature_view=False, + ) + + custom_mapping = ("text", "content_embedding") + doc_embedder.embed_documents( + documents=pd.DataFrame({"id": ["d1"], "content": ["t"]}), + id_column="id", + source_column="content", + column_mapping=custom_mapping, + ) + + embed_call = mock_embedder.embed_dataframe.call_args + assert embed_call[1]["column_mapping"] == { + "content": ("text", "content_embedding") + } + + @patch("feast.repo_operations.apply_total") + @patch("feast.repo_config.load_repo_config") + def test_apply_repo_restores_cwd( + self, mock_load_config, mock_apply_total, tmp_path + ): + """apply_repo restores os.getcwd() even if apply_total changes it.""" + mock_chunker = MagicMock(spec=BaseChunker) + mock_embedder = MagicMock(spec=BaseEmbedder) + + doc_embedder = DocEmbedder( + repo_path=str(tmp_path), + chunker=mock_chunker, + embedder=mock_embedder, + create_feature_view=False, + ) + + cwd_before = os.getcwd() + mock_apply_total.side_effect = lambda **kwargs: os.chdir(str(tmp_path)) + + doc_embedder.apply_repo() + + assert os.getcwd() == cwd_before + + @patch("feast.repo_operations.apply_total") + @patch("feast.repo_config.load_repo_config") + @patch("feast.feature_store.FeatureStore") + def test_save_to_online_store( + self, mock_fs_cls, mock_load_config, mock_apply_total, tmp_path + ): + """save_to_online_store creates FeatureStore and writes data.""" + mock_chunker = MagicMock(spec=BaseChunker) + mock_embedder = MagicMock(spec=BaseEmbedder) + + doc_embedder = DocEmbedder( + repo_path=str(tmp_path), + chunker=mock_chunker, + embedder=mock_embedder, + create_feature_view=False, + ) + + test_df = pd.DataFrame({"col": [1, 2]}) + doc_embedder.save_to_online_store(df=test_df, feature_view_name="my_view") + + mock_fs_cls.assert_called_with(repo_path=str(tmp_path)) + mock_fs_cls.return_value.write_to_online_store.assert_called_once_with( + feature_view_name="my_view", + df=test_df, + ) + + +@patch("feast.repo_operations.apply_total") +@patch("feast.repo_config.load_repo_config") +@patch("feast.feature_store.FeatureStore") +def test_end_to_end_pipeline(mock_fs_cls, mock_load_config, mock_apply_total, tmp_path): + """Full pipeline: real TextChunker + mocked embedder + default logical layer.""" + chunker = TextChunker( + config=ChunkingConfig( + chunk_size=10, + chunk_overlap=2, + min_chunk_size=3, + max_chunk_chars=None, + ) + ) + + mock_embedder = MagicMock(spec=BaseEmbedder) + + def fake_embed_dataframe(df, column_mapping): + df = df.copy() + for _src_col, (_modality, out_col) in column_mapping.items(): + df[out_col] = [[0.1, 0.2, 0.3]] * len(df) + return df + + mock_embedder.embed_dataframe.side_effect = fake_embed_dataframe + + doc_embedder = DocEmbedder( + repo_path=str(tmp_path), + chunker=chunker, + embedder=mock_embedder, + logical_layer_fn=default_logical_layer_fn, + create_feature_view=False, + ) + + documents = pd.DataFrame( + { + "id": ["doc1", "doc2"], + "text": [ + " ".join([f"word{i}" for i in range(30)]), + " ".join([f"term{i}" for i in range(25)]), + ], + } + ) + + result = doc_embedder.embed_documents( + documents=documents, + id_column="id", + source_column="text", + ) + + assert "passage_id" in result.columns + assert "text" in result.columns + assert "embedding" in result.columns + assert "event_timestamp" in result.columns + assert "source_id" in result.columns + assert len(result) > 2 + assert set(result["source_id"].unique()) == {"doc1", "doc2"} + mock_fs_cls.return_value.write_to_online_store.assert_called_once() diff --git a/sdk/python/tests/unit/test_feature_server.py b/sdk/python/tests/unit/test_feature_server.py index c271fad7fad..0fef1aea463 100644 --- a/sdk/python/tests/unit/test_feature_server.py +++ b/sdk/python/tests/unit/test_feature_server.py @@ -24,7 +24,13 @@ from feast.errors import PushSourceNotFoundException from feast.feature_server import get_app from feast.online_response import OnlineResponse -from feast.protos.feast.serving.ServingService_pb2 import GetOnlineFeaturesResponse +from feast.protos.feast.serving.ServingService_pb2 import ( + FeatureList, + FieldStatus, + GetOnlineFeaturesResponse, + GetOnlineFeaturesResponseMetadata, +) +from feast.protos.feast.types.Value_pb2 import Value from feast.utils import _utc_now from tests.foo_provider import FooProvider from tests.utils.cli_repo_creator import CliRunner, get_example_repo @@ -664,3 +670,82 @@ def load_artifacts(app: FastAPI): assert lookup_tables["sentiment_labels"]["LABEL_1"] == "neutral" assert lookup_tables["sentiment_labels"]["LABEL_2"] == "positive" assert lookup_tables["emoji_sentiment"]["😊"] == "positive" + + +def _build_online_response_with_features(): + """Build a GetOnlineFeaturesResponse with real feature data.""" + feature_names = ["driver_id", "driver_lat", "driver_long"] + proto = GetOnlineFeaturesResponse( + metadata=GetOnlineFeaturesResponseMetadata( + feature_names=FeatureList(val=feature_names), + ), + results=[ + GetOnlineFeaturesResponse.FeatureVector( + values=[Value(int64_val=123)], + statuses=[FieldStatus.PRESENT], + ), + GetOnlineFeaturesResponse.FeatureVector( + values=[Value(double_val=42.0)], + statuses=[FieldStatus.PRESENT], + ), + GetOnlineFeaturesResponse.FeatureVector( + values=[Value(double_val=-73.5)], + statuses=[FieldStatus.PRESENT], + ), + ], + status=True, + ) + return OnlineResponse(proto) + + +@pytest.mark.parametrize("async_online_read", [True, False]) +def test_get_online_features_non_empty_response(async_online_read, mock_fs_factory): + """Non-empty responses must pass FastAPI response_model validation (no 500).""" + fs = mock_fs_factory(online_read=async_online_read) + response_obj = _build_online_response_with_features() + fs.get_online_features = MagicMock(return_value=response_obj) + fs.get_online_features_async = AsyncMock(return_value=response_obj) + + client = TestClient(get_app(fs)) + resp = client.post("/get-online-features", json=get_online_features_body()) + assert resp.status_code == 200 + + body = resp.json() + assert body["metadata"]["feature_names"] == [ + "driver_id", + "driver_lat", + "driver_long", + ] + assert len(body["results"]) == 3 + assert body["results"][0]["values"] == [123] + assert body["results"][0]["statuses"] == ["PRESENT"] + + +def test_metadata_model_accepts_raw_proto_dict(): + """OnlineFeaturesMetadataResponse must accept the un-patched MessageToDict + format where feature_names is ``{"val": [...]}}`` instead of a flat list.""" + from feast.feature_server import ( + OnlineFeaturesMetadataResponse, + OnlineFeaturesResponse, + ) + + meta = OnlineFeaturesMetadataResponse.model_validate( + {"feature_names": {"val": ["feat_a", "feat_b"]}} + ) + assert meta.feature_names == ["feat_a", "feat_b"] + + meta_flat = OnlineFeaturesMetadataResponse.model_validate( + {"feature_names": ["feat_a", "feat_b"]} + ) + assert meta_flat.feature_names == ["feat_a", "feat_b"] + + full = OnlineFeaturesResponse.model_validate( + { + "metadata": {"feature_names": {"val": ["x", "y"]}}, + "results": [ + {"values": [1], "statuses": ["PRESENT"], "event_timestamps": []} + ], + } + ) + assert full.metadata is not None + assert full.metadata.feature_names == ["x", "y"] diff --git a/sdk/python/tests/unit/test_feature_view_versioning.py b/sdk/python/tests/unit/test_feature_view_versioning.py new file mode 100644 index 00000000000..80c2bc808ea --- /dev/null +++ b/sdk/python/tests/unit/test_feature_view_versioning.py @@ -0,0 +1,558 @@ +import pytest + +from feast.utils import _parse_feature_ref, _strip_version_from_ref +from feast.version_utils import ( + generate_version_id, + normalize_version_string, + parse_version, + version_tag, +) + + +class TestParseVersion: + def test_latest_string(self): + is_latest, num = parse_version("latest") + assert is_latest is True + assert num == 0 + + def test_empty_string(self): + is_latest, num = parse_version("") + assert is_latest is True + assert num == 0 + + def test_latest_case_insensitive(self): + is_latest, num = parse_version("Latest") + assert is_latest is True + + def test_v_format(self): + is_latest, num = parse_version("v2") + assert is_latest is False + assert num == 2 + + def test_version_format(self): + is_latest, num = parse_version("version3") + assert is_latest is False + assert num == 3 + + def test_case_insensitive_v(self): + is_latest, num = parse_version("V5") + assert is_latest is False + assert num == 5 + + def test_case_insensitive_version(self): + is_latest, num = parse_version("Version10") + assert is_latest is False + assert num == 10 + + def test_v0(self): + is_latest, num = parse_version("v0") + assert is_latest is False + assert num == 0 + + def test_invalid_format(self): + with pytest.raises(ValueError, match="Invalid version string"): + parse_version("abc") + + def test_invalid_format_no_number(self): + with pytest.raises(ValueError, match="Invalid version string"): + parse_version("v") + + def test_invalid_format_negative(self): + with pytest.raises(ValueError, match="Invalid version string"): + parse_version("v-1") + + +class TestNormalizeVersionString: + def test_empty_to_latest(self): + assert normalize_version_string("") == "latest" + + def test_latest_unchanged(self): + assert normalize_version_string("latest") == "latest" + + def test_v2_canonical(self): + assert normalize_version_string("v2") == "v2" + + def test_version2_to_v2(self): + assert normalize_version_string("version2") == "v2" + + def test_V3_to_v3(self): + assert normalize_version_string("V3") == "v3" + + +class TestVersionTag: + def test_simple(self): + assert version_tag(0) == "v0" + assert version_tag(5) == "v5" + assert version_tag(100) == "v100" + + +class TestGenerateVersionId: + def test_is_uuid(self): + vid = generate_version_id() + assert len(vid) == 36 + assert vid.count("-") == 4 + + def test_unique(self): + v1 = generate_version_id() + v2 = generate_version_id() + assert v1 != v2 + + +class TestFeatureViewVersionField: + def test_feature_view_default_version(self): + from datetime import timedelta + + from feast.entity import Entity + from feast.feature_view import FeatureView + + entity = Entity(name="entity_id", join_keys=["entity_id"]) + fv = FeatureView( + name="test_fv", + entities=[entity], + ttl=timedelta(days=1), + ) + assert fv.version == "latest" + assert fv.current_version_number is None + + def test_feature_view_explicit_version(self): + from datetime import timedelta + + from feast.entity import Entity + from feast.feature_view import FeatureView + + entity = Entity(name="entity_id", join_keys=["entity_id"]) + fv = FeatureView( + name="test_fv", + entities=[entity], + ttl=timedelta(days=1), + version="v2", + ) + assert fv.version == "v2" + + def test_feature_view_proto_roundtrip(self): + from datetime import timedelta + + from feast.entity import Entity + from feast.feature_view import FeatureView + + entity = Entity(name="entity_id", join_keys=["entity_id"]) + fv = FeatureView( + name="test_fv", + entities=[entity], + ttl=timedelta(days=1), + version="v3", + ) + fv.current_version_number = 3 + + proto = fv.to_proto() + assert proto.spec.version == "v3" + assert proto.meta.current_version_number == 3 + + fv2 = FeatureView.from_proto(proto) + assert fv2.version == "v3" + assert fv2.current_version_number == 3 + + def test_feature_view_proto_roundtrip_v0(self): + from datetime import timedelta + + from feast.entity import Entity + from feast.feature_view import FeatureView + + entity = Entity(name="entity_id", join_keys=["entity_id"]) + fv = FeatureView( + name="test_fv", + entities=[entity], + ttl=timedelta(days=1), + version="v0", + ) + fv.current_version_number = 0 + + proto = fv.to_proto() + assert proto.spec.version == "v0" + assert proto.meta.current_version_number == 0 + + fv2 = FeatureView.from_proto(proto) + assert fv2.version == "v0" + assert fv2.current_version_number == 0 + + def test_feature_view_proto_roundtrip_latest_zero(self): + """version='latest' with current_version_number=None is preserved as + None through proto roundtrip (proto default 0 without spec.version + is treated as None for backward compatibility).""" + from datetime import timedelta + + from feast.entity import Entity + from feast.feature_view import FeatureView + + entity = Entity(name="entity_id", join_keys=["entity_id"]) + fv = FeatureView( + name="test_fv", + entities=[entity], + ttl=timedelta(days=1), + # default version="latest", current_version_number=None + ) + assert fv.current_version_number is None + + proto = fv.to_proto() + fv2 = FeatureView.from_proto(proto) + assert fv2.version == "latest" + # Proto default 0 without spec.version is treated as None + assert fv2.current_version_number is None + + def test_feature_view_equality_with_version(self): + from datetime import timedelta + + from feast.entity import Entity + from feast.feature_view import FeatureView + + entity = Entity(name="entity_id", join_keys=["entity_id"]) + fv1 = FeatureView( + name="test_fv", + entities=[entity], + ttl=timedelta(days=1), + version="v2", + ) + fv2 = FeatureView( + name="test_fv", + entities=[entity], + ttl=timedelta(days=1), + version="version2", + ) + # v2 and version2 should be equivalent + assert fv1 == fv2 + + def test_feature_view_inequality_different_version(self): + from datetime import timedelta + + from feast.entity import Entity + from feast.feature_view import FeatureView + + entity = Entity(name="entity_id", join_keys=["entity_id"]) + fv1 = FeatureView( + name="test_fv", + entities=[entity], + ttl=timedelta(days=1), + version="latest", + ) + fv2 = FeatureView( + name="test_fv", + entities=[entity], + ttl=timedelta(days=1), + version="v2", + ) + assert fv1 != fv2 + + def test_feature_view_empty_version_equals_latest(self): + from datetime import timedelta + + from feast.entity import Entity + from feast.feature_view import FeatureView + + entity = Entity(name="entity_id", join_keys=["entity_id"]) + fv1 = FeatureView( + name="test_fv", + entities=[entity], + ttl=timedelta(days=1), + ) + fv2 = FeatureView( + name="test_fv", + entities=[entity], + ttl=timedelta(days=1), + version="latest", + ) + assert fv1 == fv2 + + def test_feature_view_copy_preserves_version(self): + import copy + from datetime import timedelta + + from feast.entity import Entity + from feast.feature_view import FeatureView + + entity = Entity(name="entity_id", join_keys=["entity_id"]) + fv = FeatureView( + name="test_fv", + entities=[entity], + ttl=timedelta(days=1), + version="v5", + ) + fv_copy = copy.copy(fv) + assert fv_copy.version == "v5" + + +class TestOnDemandFeatureViewVersionField: + def test_odfv_default_version(self): + from feast.data_source import RequestSource + from feast.field import Field + from feast.on_demand_feature_view import OnDemandFeatureView + from feast.types import Float32 + + request_source = RequestSource( + name="vals_to_add", + schema=[ + Field(name="val_to_add", dtype=Float32), + Field(name="val_to_add_2", dtype=Float32), + ], + ) + odfv = OnDemandFeatureView( + name="test_odfv", + sources=[request_source], + schema=[Field(name="output", dtype=Float32)], + feature_transformation=_dummy_transformation(), + mode="python", + ) + assert odfv.version == "latest" + + def test_odfv_proto_roundtrip(self): + from feast.data_source import RequestSource + from feast.field import Field + from feast.on_demand_feature_view import OnDemandFeatureView + from feast.types import Float32 + + request_source = RequestSource( + name="vals_to_add", + schema=[ + Field(name="val_to_add", dtype=Float32), + Field(name="val_to_add_2", dtype=Float32), + ], + ) + odfv = OnDemandFeatureView( + name="test_odfv", + sources=[request_source], + schema=[Field(name="output", dtype=Float32)], + feature_transformation=_dummy_transformation(), + mode="python", + version="v1", + ) + odfv.current_version_number = 1 + + proto = odfv.to_proto() + assert proto.spec.version == "v1" + assert proto.meta.current_version_number == 1 + + odfv2 = OnDemandFeatureView.from_proto(proto) + assert odfv2.version == "v1" + assert odfv2.current_version_number == 1 + + +class TestParseFeatureRef: + def test_bare_ref(self): + fv, version, feat = _parse_feature_ref("driver_stats:trips") + assert fv == "driver_stats" + assert version is None + assert feat == "trips" + + def test_versioned_ref(self): + fv, version, feat = _parse_feature_ref("driver_stats@v2:trips") + assert fv == "driver_stats" + assert version == 2 + assert feat == "trips" + + def test_latest_ref(self): + fv, version, feat = _parse_feature_ref("driver_stats@latest:trips") + assert fv == "driver_stats" + assert version is None + assert feat == "trips" + + def test_v0_ref(self): + fv, version, feat = _parse_feature_ref("driver_stats@v0:trips") + assert fv == "driver_stats" + assert version == 0 + assert feat == "trips" + + def test_uppercase_v(self): + fv, version, feat = _parse_feature_ref("driver_stats@V3:trips") + assert fv == "driver_stats" + assert version == 3 + assert feat == "trips" + + def test_invalid_no_colon(self): + with pytest.raises(ValueError, match="Invalid feature reference"): + _parse_feature_ref("driver_stats_trips") + + def test_unrecognized_version_falls_back(self): + """Unrecognized version format falls back to treating full fv_part as the name.""" + fv, version, feat = _parse_feature_ref("driver_stats@abc:trips") + assert fv == "driver_stats@abc" + assert version is None + assert feat == "trips" + + def test_empty_version(self): + fv, version, feat = _parse_feature_ref("driver_stats@:trips") + assert fv == "driver_stats" + assert version is None + assert feat == "trips" + + def test_at_sign_in_fv_name_falls_back_gracefully(self): + """Legacy FV name with @ falls back to treating whole pre-colon string as name.""" + fv, version, feat = _parse_feature_ref("my@weird:feature") + assert fv == "my@weird" + assert version is None + assert feat == "feature" + + def test_at_sign_with_valid_version_still_parses(self): + """A valid @v suffix still parses as a version.""" + fv, version, feat = _parse_feature_ref("stats@v2:trips") + assert fv == "stats" + assert version == 2 + assert feat == "trips" + + +class TestEnsureValidRejectsReservedChars: + def test_at_sign_in_name_raises(self): + from datetime import timedelta + + from feast.entity import Entity + from feast.feature_view import FeatureView + + entity = Entity(name="entity_id", join_keys=["entity_id"]) + fv = FeatureView( + name="my@weird_fv", + entities=[entity], + ttl=timedelta(days=1), + ) + with pytest.raises(ValueError, match="must not contain '@'"): + fv.ensure_valid() + + def test_colon_in_name_raises(self): + from datetime import timedelta + + from feast.entity import Entity + from feast.feature_view import FeatureView + + entity = Entity(name="entity_id", join_keys=["entity_id"]) + fv = FeatureView( + name="my:weird_fv", + entities=[entity], + ttl=timedelta(days=1), + ) + with pytest.raises(ValueError, match="must not contain ':'"): + fv.ensure_valid() + + def test_valid_name_passes(self): + from datetime import timedelta + + from feast.entity import Entity + from feast.feature_view import FeatureView + + entity = Entity(name="entity_id", join_keys=["entity_id"]) + fv = FeatureView( + name="driver_stats", + entities=[entity], + ttl=timedelta(days=1), + ) + fv.ensure_valid() # Should not raise + + +class TestStripVersionFromRef: + def test_bare_ref(self): + assert _strip_version_from_ref("driver_stats:trips") == "driver_stats:trips" + + def test_versioned_ref(self): + assert _strip_version_from_ref("driver_stats@v2:trips") == "driver_stats:trips" + + def test_latest_ref(self): + assert ( + _strip_version_from_ref("driver_stats@latest:trips") == "driver_stats:trips" + ) + + +class TestTableId: + def test_no_version(self): + from datetime import timedelta + + from feast.entity import Entity + from feast.feature_view import FeatureView + from feast.infra.online_stores.sqlite import _table_id + + entity = Entity(name="entity_id", join_keys=["entity_id"]) + fv = FeatureView( + name="test_fv", + entities=[entity], + ttl=timedelta(days=1), + ) + assert _table_id("my_project", fv) == "my_project_test_fv" + + def test_v0_no_suffix(self): + from datetime import timedelta + + from feast.entity import Entity + from feast.feature_view import FeatureView + from feast.infra.online_stores.sqlite import _table_id + + entity = Entity(name="entity_id", join_keys=["entity_id"]) + fv = FeatureView( + name="test_fv", + entities=[entity], + ttl=timedelta(days=1), + ) + fv.current_version_number = 0 + assert _table_id("my_project", fv) == "my_project_test_fv" + + def test_v1_with_suffix(self): + from datetime import timedelta + + from feast.entity import Entity + from feast.feature_view import FeatureView + from feast.infra.online_stores.sqlite import _table_id + + entity = Entity(name="entity_id", join_keys=["entity_id"]) + fv = FeatureView( + name="test_fv", + entities=[entity], + ttl=timedelta(days=1), + ) + fv.current_version_number = 1 + assert ( + _table_id("my_project", fv, enable_versioning=True) + == "my_project_test_fv_v1" + ) + + def test_v5_with_suffix(self): + from datetime import timedelta + + from feast.entity import Entity + from feast.feature_view import FeatureView + from feast.infra.online_stores.sqlite import _table_id + + entity = Entity(name="entity_id", join_keys=["entity_id"]) + fv = FeatureView( + name="test_fv", + entities=[entity], + ttl=timedelta(days=1), + ) + fv.current_version_number = 5 + assert ( + _table_id("my_project", fv, enable_versioning=True) + == "my_project_test_fv_v5" + ) + + +class TestValidateFeatureRefsVersioned: + def test_versioned_refs_no_collision_with_full_names(self): + from feast.utils import _validate_feature_refs + + # Different versions of the same feature should not collide with full names + refs = ["driver_stats@v1:trips", "driver_stats@v2:trips"] + _validate_feature_refs(refs, full_feature_names=True) # Should not raise + + def test_versioned_refs_collision_without_full_names(self): + from feast.errors import FeatureNameCollisionError + from feast.utils import _validate_feature_refs + + # Same feature name from different versions collides without full names + refs = ["driver_stats@v1:trips", "driver_stats@v2:trips"] + with pytest.raises(FeatureNameCollisionError): + _validate_feature_refs(refs, full_feature_names=False) + + +def _dummy_transformation(): + from feast.transformation.python_transformation import PythonTransformation + + def identity(features_df): + return features_df + + return PythonTransformation( + udf=identity, + udf_string="def identity(features_df):\n return features_df\n", + ) diff --git a/sdk/python/tests/unit/test_feature_views.py b/sdk/python/tests/unit/test_feature_views.py index 9030e6e0c69..3427cfdfc4b 100644 --- a/sdk/python/tests/unit/test_feature_views.py +++ b/sdk/python/tests/unit/test_feature_views.py @@ -23,6 +23,18 @@ from feast.utils import _utc_now, make_tzaware +def test_create_feature_view_without_source(): + fv = FeatureView(name="test_no_source", ttl=timedelta(days=1)) + assert fv.batch_source is None + assert fv.stream_source is None + + proto = fv.to_proto() + assert not proto.spec.HasField("batch_source") + + fv_roundtrip = FeatureView.from_proto(proto) + assert fv_roundtrip.batch_source is None + + def test_create_feature_view_with_conflicting_entities(): user1 = Entity(name="user1", join_keys=["user_id"]) user2 = Entity(name="user2", join_keys=["user_id"]) @@ -48,7 +60,7 @@ def test_create_batch_feature_view(): udf=lambda x: x, ) - with pytest.raises(TypeError): + with pytest.raises(ValueError): BatchFeatureView( name="test batch feature view", entities=[], ttl=timedelta(days=30) ) diff --git a/sdk/python/tests/unit/test_grpc_server_write_protos.py b/sdk/python/tests/unit/test_grpc_server_write_protos.py new file mode 100644 index 00000000000..31c3e5c84c8 --- /dev/null +++ b/sdk/python/tests/unit/test_grpc_server_write_protos.py @@ -0,0 +1,159 @@ +import pytest + +from feast.infra.contrib.grpc_server import parse_typed +from feast.protos.feast.serving.GrpcServer_pb2 import ( + PushRequest, + WriteToOnlineStoreRequest, +) +from feast.protos.feast.types.Value_pb2 import ( + Int64List, + Map, + Null, + StringSet, + Value, +) + + +def test_push_request_string_features(): + request = PushRequest( + features={"driver_id": "1001", "conv_rate": "0.5"}, + stream_feature_view="driver_stats", + to="online", + ) + assert request.features["driver_id"] == "1001" + assert request.features["conv_rate"] == "0.5" + assert len(request.typed_features) == 0 + + +def test_push_request_typed_features(): + request = PushRequest( + typed_features={ + "driver_id": Value(int64_val=1001), + "conv_rate": Value(float_val=0.5), + "active": Value(bool_val=True), + "label": Value(string_val="fast"), + }, + stream_feature_view="driver_stats", + to="online", + ) + assert request.typed_features["driver_id"].int64_val == 1001 + assert request.typed_features["conv_rate"].float_val == pytest.approx(0.5) + assert request.typed_features["active"].bool_val is True + assert request.typed_features["label"].string_val == "fast" + assert len(request.features) == 0 + + +def test_push_request_typed_features_val_case(): + """WhichOneof('val') returns the correct field name for each value type.""" + cases = [ + (Value(int32_val=1), "int32_val"), + (Value(int64_val=2), "int64_val"), + (Value(float_val=1.0), "float_val"), + (Value(double_val=2.0), "double_val"), + (Value(bool_val=True), "bool_val"), + (Value(string_val="x"), "string_val"), + ] + for value, expected_case in cases: + assert value.WhichOneof("val") == expected_case + + +def test_write_to_online_store_request_string_features(): + request = WriteToOnlineStoreRequest( + features={"driver_id": "1001", "avg_daily_trips": "10"}, + feature_view_name="driver_hourly_stats", + ) + assert request.features["driver_id"] == "1001" + assert request.features["avg_daily_trips"] == "10" + assert len(request.typed_features) == 0 + + +def test_write_to_online_store_request_typed_features(): + request = WriteToOnlineStoreRequest( + typed_features={ + "driver_id": Value(int64_val=1001), + "avg_daily_trips": Value(int32_val=10), + "conv_rate": Value(float_val=0.42), + }, + feature_view_name="driver_hourly_stats", + ) + assert request.typed_features["driver_id"].int64_val == 1001 + assert request.typed_features["avg_daily_trips"].int32_val == 10 + assert request.typed_features["conv_rate"].float_val == pytest.approx(0.42) + assert len(request.features) == 0 + + +def test_push_request_string_and_typed_features_are_independent(): + """Setting features does not affect typed_features and vice versa.""" + r1 = PushRequest( + features={"driver_id": "1001"}, stream_feature_view="s", to="online" + ) + r2 = PushRequest( + typed_features={"driver_id": Value(int64_val=1001)}, + stream_feature_view="s", + to="online", + ) + assert len(r1.typed_features) == 0 + assert len(r2.features) == 0 + + +def test_write_to_online_store_string_and_typed_features_are_independent(): + r1 = WriteToOnlineStoreRequest( + features={"driver_id": "1001"}, feature_view_name="fv" + ) + r2 = WriteToOnlineStoreRequest( + typed_features={"driver_id": Value(int64_val=1001)}, feature_view_name="fv" + ) + assert len(r1.typed_features) == 0 + assert len(r2.features) == 0 + + +def test_parse_typed_null_val_becomes_none(): + """Value(null_val=NULL) must produce None in the DataFrame, not the integer 0.""" + df = parse_typed( + { + "present": Value(int64_val=42), + "missing": Value(null_val=Null.NULL), + } + ) + assert df["present"].iloc[0] == 42 + assert df["missing"].iloc[0] is None + + +def test_parse_typed_unset_val_becomes_none(): + """A Value with no oneof field set (WhichOneof returns None) must also produce None.""" + df = parse_typed({"empty": Value()}) + assert df["empty"].iloc[0] is None + + +def test_parse_typed_list_val_unwrapped_to_python_list(): + """Compound list values are unwrapped from their protobuf wrapper to a plain list.""" + df = parse_typed( + { + "ids": Value(int64_list_val=Int64List(val=[1, 2, 3])), + } + ) + assert df["ids"].iloc[0] == [1, 2, 3] + + +def test_parse_typed_set_val_unwrapped_to_python_list(): + """Compound set values are unwrapped from their protobuf wrapper to a plain list.""" + df = parse_typed( + { + "tags": Value(string_set_val=StringSet(val=["a", "b"])), + } + ) + assert sorted(df["tags"].iloc[0]) == ["a", "b"] + + +def test_parse_typed_map_val_unwrapped_to_python_dict(): + """Map values are unwrapped from their protobuf Map wrapper to a plain dict.""" + df = parse_typed( + { + "scores": Value( + map_val=Map(val={"x": Value(float_val=1.0), "y": Value(float_val=2.0)}) + ), + } + ) + result = df["scores"].iloc[0] + assert isinstance(result, dict) + assert set(result.keys()) == {"x", "y"} diff --git a/sdk/python/tests/unit/test_metrics.py b/sdk/python/tests/unit/test_metrics.py new file mode 100644 index 00000000000..17aaa5d1337 --- /dev/null +++ b/sdk/python/tests/unit/test_metrics.py @@ -0,0 +1,1002 @@ +# Copyright 2025 The Feast Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from datetime import datetime, timedelta, timezone +from unittest.mock import MagicMock, patch + +import pytest + +from feast.metrics import ( + feature_freshness_seconds, + materialization_duration_seconds, + materialization_result_total, + online_features_entity_count, + online_features_request_count, + online_store_read_duration_seconds, + push_request_count, + request_count, + request_latency, + track_materialization, + track_online_features_entities, + track_online_store_read, + track_push, + track_request_latency, + track_transformation, + track_write_transformation, + transformation_duration_seconds, + update_feature_freshness, + write_transformation_duration_seconds, +) + + +@pytest.fixture(autouse=True) +def _enable_metrics(): + """Enable all metric categories for each test, then restore.""" + import feast.metrics as m + + original = m._config + m._config = m._MetricsFlags( + enabled=True, + resource=True, + request=True, + online_features=True, + push=True, + materialization=True, + freshness=True, + ) + yield + m._config = original + + +class TestTrackRequestLatency: + def test_success_increments_counter_and_records_latency(self): + before_count = request_count.labels( + endpoint="/test", status="success" + )._value.get() + + with track_request_latency("/test"): + pass + + after_count = request_count.labels( + endpoint="/test", status="success" + )._value.get() + assert after_count == before_count + 1 + + def test_error_increments_error_counter(self): + before_count = request_count.labels( + endpoint="/test-err", status="error" + )._value.get() + + with pytest.raises(ValueError): + with track_request_latency("/test-err"): + raise ValueError("boom") + + after_count = request_count.labels( + endpoint="/test-err", status="error" + )._value.get() + assert after_count == before_count + 1 + + def test_latency_is_recorded(self): + before_sum = request_latency.labels( + endpoint="/test-latency", feature_count="", feature_view_count="" + )._sum.get() + + with track_request_latency("/test-latency"): + import time + + time.sleep(0.01) + + after_sum = request_latency.labels( + endpoint="/test-latency", feature_count="", feature_view_count="" + )._sum.get() + assert after_sum > before_sum + + def test_feature_count_and_feature_view_count_labels(self): + """Latency histogram carries feature_count and feature_view_count labels.""" + label_set = dict( + endpoint="/get-online-features", + feature_count="5", + feature_view_count="2", + ) + before_sum = request_latency.labels(**label_set)._sum.get() + + with track_request_latency( + "/get-online-features", feature_count="5", feature_view_count="2" + ): + pass + + after_sum = request_latency.labels(**label_set)._sum.get() + assert after_sum > before_sum + + def test_default_labels_are_empty_string(self): + """Non-online-features endpoints get empty-string labels by default.""" + label_set = dict( + endpoint="/materialize", feature_count="", feature_view_count="" + ) + before_sum = request_latency.labels(**label_set)._sum.get() + + with track_request_latency("/materialize"): + pass + + after_sum = request_latency.labels(**label_set)._sum.get() + assert after_sum > before_sum + + def test_labels_updated_via_yielded_context(self): + """Labels set on the yielded context are used in the final metrics.""" + label_set = dict( + endpoint="/ctx-update", feature_count="3", feature_view_count="1" + ) + before_sum = request_latency.labels(**label_set)._sum.get() + + with track_request_latency("/ctx-update") as ctx: + ctx.feature_count = "3" + ctx.feature_view_count = "1" + + after_sum = request_latency.labels(**label_set)._sum.get() + assert after_sum > before_sum + + def test_error_before_labels_set_still_records(self): + """Errors before labels are updated still record with default labels.""" + before_count = request_count.labels( + endpoint="/early-fail", status="error" + )._value.get() + + with pytest.raises(RuntimeError): + with track_request_latency("/early-fail") as _ctx: + raise RuntimeError("auth failed") + + after_count = request_count.labels( + endpoint="/early-fail", status="error" + )._value.get() + assert after_count == before_count + 1 + + recorded_sum = request_latency.labels( + endpoint="/early-fail", feature_count="", feature_view_count="" + )._sum.get() + assert recorded_sum > 0 + + +class TestMetricsOptIn: + """Verify that when a category is disabled, its helpers are true no-ops.""" + + @staticmethod + def _all_off(): + import feast.metrics as m + + m._config = m._MetricsFlags() # everything False + + def test_track_request_latency_noop_when_disabled(self): + self._all_off() + label_set = dict( + endpoint="/disabled-test", feature_count="", feature_view_count="" + ) + before_sum = request_latency.labels(**label_set)._sum.get() + + with track_request_latency("/disabled-test"): + pass + + assert request_latency.labels(**label_set)._sum.get() == before_sum + + def test_track_online_features_entities_noop_when_disabled(self): + self._all_off() + before = online_features_request_count._value.get() + track_online_features_entities(100) + assert online_features_request_count._value.get() == before + + def test_track_push_noop_when_disabled(self): + self._all_off() + before = push_request_count.labels( + push_source="src", mode="online" + )._value.get() + track_push("src", "online") + assert ( + push_request_count.labels(push_source="src", mode="online")._value.get() + == before + ) + + def test_track_materialization_noop_when_disabled(self): + self._all_off() + before = materialization_result_total.labels( + feature_view="fv_disabled", status="success" + )._value.get() + track_materialization("fv_disabled", success=True, duration_seconds=1.0) + assert ( + materialization_result_total.labels( + feature_view="fv_disabled", status="success" + )._value.get() + == before + ) + + +class TestGranularCategoryControl: + """Verify individual category toggles work independently.""" + + def test_request_disabled_but_push_enabled(self): + import feast.metrics as m + + m._config = m._MetricsFlags( + enabled=True, + request=False, + push=True, + resource=True, + online_features=True, + materialization=True, + freshness=True, + ) + + # request should be no-op + label_set = dict( + endpoint="/granular-req", feature_count="", feature_view_count="" + ) + before_req = request_latency.labels(**label_set)._sum.get() + with track_request_latency("/granular-req"): + pass + assert request_latency.labels(**label_set)._sum.get() == before_req + + # push should still record + before_push = push_request_count.labels( + push_source="s", mode="online" + )._value.get() + track_push("s", "online") + assert ( + push_request_count.labels(push_source="s", mode="online")._value.get() + == before_push + 1 + ) + + def test_online_features_disabled_but_materialization_enabled(self): + import feast.metrics as m + + m._config = m._MetricsFlags( + enabled=True, + online_features=False, + materialization=True, + resource=True, + request=True, + push=True, + freshness=True, + ) + + # online_features should be no-op + before_of = online_features_request_count._value.get() + track_online_features_entities(50) + assert online_features_request_count._value.get() == before_of + + # materialization should still record + before_mat = materialization_result_total.labels( + feature_view="fv_gran", status="success" + )._value.get() + track_materialization("fv_gran", success=True, duration_seconds=1.0) + assert ( + materialization_result_total.labels( + feature_view="fv_gran", status="success" + )._value.get() + == before_mat + 1 + ) + + def test_only_resource_enabled(self): + """When only resource is on, all request-path helpers are no-ops.""" + import feast.metrics as m + + m._config = m._MetricsFlags( + enabled=True, + resource=True, + request=False, + online_features=False, + push=False, + materialization=False, + freshness=False, + ) + + label_set = dict(endpoint="/res-only", feature_count="", feature_view_count="") + before_req = request_latency.labels(**label_set)._sum.get() + before_of = online_features_request_count._value.get() + before_push = push_request_count.labels( + push_source="x", mode="offline" + )._value.get() + before_mat = materialization_result_total.labels( + feature_view="fv_res", status="success" + )._value.get() + + with track_request_latency("/res-only"): + pass + track_online_features_entities(10) + track_push("x", "offline") + track_materialization("fv_res", success=True, duration_seconds=1.0) + + assert request_latency.labels(**label_set)._sum.get() == before_req + assert online_features_request_count._value.get() == before_of + assert ( + push_request_count.labels(push_source="x", mode="offline")._value.get() + == before_push + ) + assert ( + materialization_result_total.labels( + feature_view="fv_res", status="success" + )._value.get() + == before_mat + ) + + +class TestMetricsYamlConfig: + """Verify metrics config in feature_store.yaml is respected. + + We mock out everything past the metrics-gate check in ``start_server`` + so these tests never actually launch a real HTTP server. + """ + + @staticmethod + def _call_start_server(mock_store, cli_metrics: bool): + """Call start_server with enough mocking to avoid side-effects.""" + from feast.feature_server import start_server + + with ( + patch("feast.feature_server.feast_metrics") as mock_fm, + patch("feast.feature_server.str_to_auth_manager_type"), + patch("feast.feature_server.init_security_manager"), + patch("feast.feature_server.init_auth_manager"), + patch( + "feast.feature_server.FeastServeApplication", + side_effect=RuntimeError("stop"), + ) + if hasattr(__import__("sys"), "platform") + and __import__("sys").platform != "win32" + else patch("uvicorn.run", side_effect=RuntimeError("stop")), + ): + try: + start_server( + store=mock_store, + host="127.0.0.1", + port=6566, + no_access_log=True, + workers=1, + worker_connections=1000, + max_requests=1000, + max_requests_jitter=50, + keep_alive_timeout=30, + registry_ttl_sec=60, + tls_key_path="", + tls_cert_path="", + metrics=cli_metrics, + ) + except (RuntimeError, Exception): + pass + return mock_fm + + def test_metrics_enabled_from_yaml_config(self): + """start_server enables metrics when config has metrics.enabled=True, + even though the CLI flag is False.""" + from types import SimpleNamespace + + metrics_cfg = SimpleNamespace(enabled=True) + fs_cfg = SimpleNamespace(metrics=metrics_cfg) + mock_store = MagicMock() + mock_store.config = SimpleNamespace(feature_server=fs_cfg) + + mock_fm = self._call_start_server(mock_store, cli_metrics=False) + mock_fm.build_metrics_flags.assert_called_once_with(metrics_cfg) + mock_fm.start_metrics_server.assert_called_once() + + def test_cli_flag_enables_metrics_without_yaml_config(self): + """start_server enables metrics when --metrics is passed even without + any feature_server config section.""" + from types import SimpleNamespace + + mock_store = MagicMock() + mock_store.config = SimpleNamespace(feature_server=None) + + mock_fm = self._call_start_server(mock_store, cli_metrics=True) + mock_fm.build_metrics_flags.assert_called_once_with(None) + mock_fm.start_metrics_server.assert_called_once() + + def test_metrics_not_started_when_both_disabled(self): + """start_server does NOT start metrics when neither CLI nor config enables it.""" + from types import SimpleNamespace + + mock_store = MagicMock() + mock_store.config = SimpleNamespace( + feature_server=SimpleNamespace(metrics=SimpleNamespace(enabled=False)), + ) + + mock_fm = self._call_start_server(mock_store, cli_metrics=False) + mock_fm.start_metrics_server.assert_not_called() + + def test_metrics_not_started_when_config_is_none(self): + """start_server does NOT start metrics when feature_server config is None + and CLI flag is also False.""" + from types import SimpleNamespace + + mock_store = MagicMock() + mock_store.config = SimpleNamespace(feature_server=None) + + mock_fm = self._call_start_server(mock_store, cli_metrics=False) + mock_fm.start_metrics_server.assert_not_called() + + +class TestTrackOnlineFeaturesEntities: + def test_increments_request_count(self): + before = online_features_request_count._value.get() + track_online_features_entities(10) + assert online_features_request_count._value.get() == before + 1 + + def test_records_entity_count(self): + before_count = online_features_entity_count._sum.get() + track_online_features_entities(42) + assert online_features_entity_count._sum.get() >= before_count + 42 + + +class TestTrackPush: + def test_increments_push_counter(self): + before = push_request_count.labels( + push_source="my_source", mode="online" + )._value.get() + track_push("my_source", "online") + assert ( + push_request_count.labels( + push_source="my_source", mode="online" + )._value.get() + == before + 1 + ) + + +class TestTrackMaterialization: + def test_success_counter(self): + before = materialization_result_total.labels( + feature_view="fv1", status="success" + )._value.get() + track_materialization("fv1", success=True, duration_seconds=1.5) + assert ( + materialization_result_total.labels( + feature_view="fv1", status="success" + )._value.get() + == before + 1 + ) + + def test_failure_counter(self): + before = materialization_result_total.labels( + feature_view="fv2", status="failure" + )._value.get() + track_materialization("fv2", success=False, duration_seconds=0.5) + assert ( + materialization_result_total.labels( + feature_view="fv2", status="failure" + )._value.get() + == before + 1 + ) + + def test_duration_histogram(self): + before_sum = materialization_duration_seconds.labels( + feature_view="fv3" + )._sum.get() + track_materialization("fv3", success=True, duration_seconds=3.7) + after_sum = materialization_duration_seconds.labels( + feature_view="fv3" + )._sum.get() + assert pytest.approx(after_sum - before_sum, abs=0.01) == 3.7 + + +class TestUpdateFeatureFreshness: + def test_sets_freshness_for_materialized_views(self): + mock_fv = MagicMock() + mock_fv.name = "test_fv" + mock_fv.most_recent_end_time = datetime.now(tz=timezone.utc) - timedelta( + minutes=5 + ) + + mock_store = MagicMock() + mock_store.project = "test_project" + mock_store.list_feature_views.return_value = [mock_fv] + + update_feature_freshness(mock_store) + + staleness = feature_freshness_seconds.labels( + feature_view="test_fv", project="test_project" + )._value.get() + assert 280 < staleness < 320 + + def test_skips_unmaterialized_views(self): + mock_fv = MagicMock() + mock_fv.name = "unmaterialized_fv" + mock_fv.most_recent_end_time = None + + mock_store = MagicMock() + mock_store.project = "test_project" + mock_store.list_feature_views.return_value = [mock_fv] + + update_feature_freshness(mock_store) + + def test_handles_naive_datetime(self): + mock_fv = MagicMock() + mock_fv.name = "naive_fv" + # Simulate a naive UTC datetime (no tzinfo), as Feast typically stores + naive_utc_now = datetime.now(tz=timezone.utc).replace(tzinfo=None) + mock_fv.most_recent_end_time = naive_utc_now - timedelta(hours=1) + + mock_store = MagicMock() + mock_store.project = "test_project" + mock_store.list_feature_views.return_value = [mock_fv] + + update_feature_freshness(mock_store) + + staleness = feature_freshness_seconds.labels( + feature_view="naive_fv", project="test_project" + )._value.get() + assert 3500 < staleness < 3700 + + def test_handles_registry_errors_gracefully(self): + mock_store = MagicMock() + mock_store.list_feature_views.side_effect = Exception("registry down") + + update_feature_freshness(mock_store) + + +class TestResolveFeatureCounts: + """Verify _resolve_feature_counts for both feature-ref lists and FeatureService.""" + + def test_feature_ref_list(self): + from feast.feature_server import _resolve_feature_counts + + refs = ["driver_fv:conv_rate", "driver_fv:acc_rate", "vehicle_fv:mileage"] + feat_count, fv_count = _resolve_feature_counts(refs) + assert feat_count == "3" + assert fv_count == "2" + + def test_single_feature_view(self): + from feast.feature_server import _resolve_feature_counts + + refs = ["fv1:a", "fv1:b", "fv1:c"] + feat_count, fv_count = _resolve_feature_counts(refs) + assert feat_count == "3" + assert fv_count == "1" + + def test_empty_list(self): + from feast.feature_server import _resolve_feature_counts + + feat_count, fv_count = _resolve_feature_counts([]) + assert feat_count == "0" + assert fv_count == "0" + + def test_feature_service(self): + from feast.feature_server import _resolve_feature_counts + + proj1 = MagicMock() + proj1.features = [MagicMock(), MagicMock()] + proj2 = MagicMock() + proj2.features = [MagicMock()] + + fs_svc = MagicMock() + fs_svc.feature_view_projections = [proj1, proj2] + + from feast.feature_service import FeatureService + + fs_svc.__class__ = FeatureService + + feat_count, fv_count = _resolve_feature_counts(fs_svc) + assert feat_count == "3" + assert fv_count == "2" + + +class TestFeatureServerMetricsIntegration: + """Test that feature server endpoints record metrics.""" + + @pytest.fixture + def mock_fs_factory(self): + from tests.foo_provider import FooProvider + + def builder(**async_support): + provider = FooProvider.with_async_support(**async_support) + fs = MagicMock() + fs._get_provider.return_value = provider + from feast.online_response import OnlineResponse + from feast.protos.feast.serving.ServingService_pb2 import ( + GetOnlineFeaturesResponse, + ) + + empty_response = OnlineResponse(GetOnlineFeaturesResponse(results=[])) + fs.get_online_features = MagicMock(return_value=empty_response) + fs.push = MagicMock() + fs.get_online_features_async = MagicMock(return_value=empty_response) + fs.push_async = MagicMock() + return fs + + return builder + + def test_get_online_features_records_metrics(self, mock_fs_factory): + from fastapi.testclient import TestClient + + from feast.feature_server import get_app + + fs = mock_fs_factory(online_read=False) + client = TestClient(get_app(fs)) + + before_req = request_count.labels( + endpoint="/get-online-features", status="success" + )._value.get() + before_entity = online_features_request_count._value.get() + + client.post( + "/get-online-features", + json={ + "features": ["fv:feat1"], + "entities": {"id": [1, 2, 3]}, + }, + ) + + assert ( + request_count.labels( + endpoint="/get-online-features", status="success" + )._value.get() + == before_req + 1 + ) + assert online_features_request_count._value.get() == before_entity + 1 + + @pytest.mark.parametrize( + "features,expected_feat_count,expected_fv_count", + [ + (["fv1:a"], "1", "1"), + (["fv1:a", "fv1:b", "fv2:c"], "3", "2"), + ( + ["fv1:a", "fv1:b", "fv2:c", "fv2:d", "fv3:e"], + "5", + "3", + ), + ], + ids=["1_feat_1_fv", "3_feats_2_fvs", "5_feats_3_fvs"], + ) + def test_latency_labels_with_varying_request_sizes( + self, mock_fs_factory, features, expected_feat_count, expected_fv_count + ): + """Verify feature_count and feature_view_count labels change with request size.""" + from fastapi.testclient import TestClient + + from feast.feature_server import get_app + + fs = mock_fs_factory(online_read=False) + client = TestClient(get_app(fs)) + + label_set = dict( + endpoint="/get-online-features", + feature_count=expected_feat_count, + feature_view_count=expected_fv_count, + ) + before_sum = request_latency.labels(**label_set)._sum.get() + + client.post( + "/get-online-features", + json={ + "features": features, + "entities": {"id": [1]}, + }, + ) + + after_sum = request_latency.labels(**label_set)._sum.get() + assert after_sum > before_sum + + def test_push_records_metrics(self, mock_fs_factory): + from fastapi.testclient import TestClient + + from feast.feature_server import get_app + from feast.utils import _utc_now + + fs = mock_fs_factory(online_write=False) + client = TestClient(get_app(fs)) + + before = push_request_count.labels( + push_source="driver_locations_push", mode="online" + )._value.get() + + client.post( + "/push", + json={ + "push_source_name": "driver_locations_push", + "df": { + "driver_lat": [42.0], + "driver_long": ["42.0"], + "driver_id": [123], + "event_timestamp": [str(_utc_now())], + "created_timestamp": [str(_utc_now())], + }, + "to": "online", + }, + ) + + assert ( + push_request_count.labels( + push_source="driver_locations_push", mode="online" + )._value.get() + == before + 1 + ) + + +class TestBuildMetricsFlags: + """Verify build_metrics_flags correctly maps MetricsConfig to _MetricsFlags.""" + + def test_no_config_enables_all(self): + from feast.metrics import build_metrics_flags + + flags = build_metrics_flags(None) + assert flags.enabled is True + assert flags.resource is True + assert flags.request is True + assert flags.online_features is True + assert flags.push is True + assert flags.materialization is True + assert flags.freshness is True + + def test_selective_disable(self): + from types import SimpleNamespace + + from feast.metrics import build_metrics_flags + + mc = SimpleNamespace( + enabled=True, + resource=True, + request=False, + online_features=True, + push=False, + materialization=True, + freshness=False, + ) + flags = build_metrics_flags(mc) + assert flags.enabled is True + assert flags.resource is True + assert flags.request is False + assert flags.online_features is True + assert flags.push is False + assert flags.materialization is True + assert flags.freshness is False + + def test_all_categories_disabled(self): + from types import SimpleNamespace + + from feast.metrics import build_metrics_flags + + mc = SimpleNamespace( + enabled=True, + resource=False, + request=False, + online_features=False, + push=False, + materialization=False, + freshness=False, + ) + flags = build_metrics_flags(mc) + assert flags.enabled is True + assert flags.resource is False + assert flags.request is False + + +class TestCleanupMultiprocessDir: + """Verify the atexit handler only deletes the temp dir in the owner process.""" + + def test_cleanup_skipped_in_forked_child(self, tmp_path): + """Simulate a forked worker: _owns_mp_dir=True but _owner_pid != current PID.""" + import feast.metrics as m + + original_dir = m._prometheus_mp_dir + original_owns = m._owns_mp_dir + original_pid = m._owner_pid + + fake_dir = tmp_path / "feast_metrics_test" + fake_dir.mkdir() + + m._prometheus_mp_dir = str(fake_dir) + m._owns_mp_dir = True + m._owner_pid = -1 # Different from os.getpid() + + try: + m._cleanup_multiprocess_dir() + assert fake_dir.exists(), ( + "Directory should NOT be deleted when _owner_pid != os.getpid()" + ) + finally: + m._prometheus_mp_dir = original_dir + m._owns_mp_dir = original_owns + m._owner_pid = original_pid + + def test_cleanup_runs_in_owner_process(self, tmp_path): + """The owner process (matching PID) should delete the directory.""" + import os + + import feast.metrics as m + + original_dir = m._prometheus_mp_dir + original_owns = m._owns_mp_dir + original_pid = m._owner_pid + + fake_dir = tmp_path / "feast_metrics_test" + fake_dir.mkdir() + + m._prometheus_mp_dir = str(fake_dir) + m._owns_mp_dir = True + m._owner_pid = os.getpid() + + try: + m._cleanup_multiprocess_dir() + assert not fake_dir.exists(), ( + "Directory SHOULD be deleted when _owner_pid == os.getpid()" + ) + finally: + m._prometheus_mp_dir = original_dir + m._owns_mp_dir = original_owns + m._owner_pid = original_pid + + +class TestTrackOnlineStoreRead: + """Tests for the online store read duration metric.""" + + def test_records_duration(self): + before_sum = online_store_read_duration_seconds._sum.get() + + track_online_store_read(0.123) + + assert online_store_read_duration_seconds._sum.get() >= before_sum + 0.123 + + def test_noop_when_online_features_disabled(self): + import feast.metrics as m + + m._config = m._MetricsFlags(enabled=True, online_features=False) + + before_sum = online_store_read_duration_seconds._sum.get() + + track_online_store_read(0.5) + + assert online_store_read_duration_seconds._sum.get() == before_sum + + m._config = m._MetricsFlags( + enabled=True, + resource=True, + request=True, + online_features=True, + push=True, + materialization=True, + freshness=True, + ) + + +class TestTrackTransformation: + """Tests for the ODFV transformation duration metric.""" + + def test_records_python_mode(self): + labels = ("my_odfv", "python") + before = transformation_duration_seconds._metrics.get(labels, None) + before_sum = before._sum.get() if before else 0.0 + + track_transformation("my_odfv", "python", 0.042) + + sample = transformation_duration_seconds._metrics[labels] + assert sample._sum.get() >= before_sum + 0.042 + + def test_records_pandas_mode(self): + labels = ("my_odfv", "pandas") + before = transformation_duration_seconds._metrics.get(labels, None) + before_sum = before._sum.get() if before else 0.0 + + track_transformation("my_odfv", "pandas", 0.15) + + sample = transformation_duration_seconds._metrics[labels] + assert sample._sum.get() >= before_sum + 0.15 + + def test_noop_when_online_features_disabled(self): + import feast.metrics as m + + m._config = m._MetricsFlags(enabled=True, online_features=False) + + labels = ("disabled_odfv", "python") + before = transformation_duration_seconds._metrics.get(labels, None) + before_sum = before._sum.get() if before else 0.0 + + track_transformation("disabled_odfv", "python", 1.0) + + sample = transformation_duration_seconds._metrics.get(labels, None) + after_sum = sample._sum.get() if sample else 0.0 + assert after_sum == before_sum + + m._config = m._MetricsFlags( + enabled=True, + resource=True, + request=True, + online_features=True, + push=True, + materialization=True, + freshness=True, + ) + + def test_multiple_odfvs_tracked_independently(self): + labels_a = ("odfv_a", "python") + labels_b = ("odfv_b", "pandas") + before_a = transformation_duration_seconds._metrics.get(labels_a, None) + before_a_sum = before_a._sum.get() if before_a else 0.0 + before_b = transformation_duration_seconds._metrics.get(labels_b, None) + before_b_sum = before_b._sum.get() if before_b else 0.0 + + track_transformation("odfv_a", "python", 0.01) + track_transformation("odfv_b", "pandas", 0.05) + + sample_a = transformation_duration_seconds._metrics[labels_a] + sample_b = transformation_duration_seconds._metrics[labels_b] + assert sample_a._sum.get() >= before_a_sum + 0.01 + assert sample_b._sum.get() >= before_b_sum + 0.05 + + +class TestTrackWriteTransformation: + """Tests for the write-path ODFV transformation duration metric.""" + + def test_records_python_mode(self): + labels = ("write_odfv", "python") + before = write_transformation_duration_seconds._metrics.get(labels, None) + before_sum = before._sum.get() if before else 0.0 + + track_write_transformation("write_odfv", "python", 0.033) + + sample = write_transformation_duration_seconds._metrics[labels] + assert sample._sum.get() >= before_sum + 0.033 + + def test_records_pandas_mode(self): + labels = ("write_odfv", "pandas") + before = write_transformation_duration_seconds._metrics.get(labels, None) + before_sum = before._sum.get() if before else 0.0 + + track_write_transformation("write_odfv", "pandas", 0.12) + + sample = write_transformation_duration_seconds._metrics[labels] + assert sample._sum.get() >= before_sum + 0.12 + + def test_noop_when_online_features_disabled(self): + import feast.metrics as m + + m._config = m._MetricsFlags(enabled=True, online_features=False) + + labels = ("disabled_write_odfv", "python") + before = write_transformation_duration_seconds._metrics.get(labels, None) + before_sum = before._sum.get() if before else 0.0 + + track_write_transformation("disabled_write_odfv", "python", 1.0) + + sample = write_transformation_duration_seconds._metrics.get(labels, None) + after_sum = sample._sum.get() if sample else 0.0 + assert after_sum == before_sum + + m._config = m._MetricsFlags( + enabled=True, + resource=True, + request=True, + online_features=True, + push=True, + materialization=True, + freshness=True, + ) + + def test_separate_from_read_transform_metric(self): + """Write and read transform metrics are independent histograms.""" + read_labels = ("shared_odfv", "python") + write_labels = ("shared_odfv", "python") + + read_before = transformation_duration_seconds._metrics.get(read_labels, None) + read_before_sum = read_before._sum.get() if read_before else 0.0 + write_before = write_transformation_duration_seconds._metrics.get( + write_labels, None + ) + write_before_sum = write_before._sum.get() if write_before else 0.0 + + track_transformation("shared_odfv", "python", 0.01) + track_write_transformation("shared_odfv", "python", 0.05) + + read_after = transformation_duration_seconds._metrics[read_labels] + write_after = write_transformation_duration_seconds._metrics[write_labels] + + read_delta = read_after._sum.get() - read_before_sum + write_delta = write_after._sum.get() - write_before_sum + + assert abs(read_delta - 0.01) < 0.001 + assert abs(write_delta - 0.05) < 0.001 diff --git a/sdk/python/tests/unit/test_offline_server.py b/sdk/python/tests/unit/test_offline_server.py index c5f309eb323..f30c3aef037 100644 --- a/sdk/python/tests/unit/test_offline_server.py +++ b/sdk/python/tests/unit/test_offline_server.py @@ -1,6 +1,7 @@ import os import tempfile from datetime import datetime, timedelta +from unittest.mock import patch import assertpy import pandas as pd @@ -345,3 +346,28 @@ def _test_pull_all_from_table_or_query(temp_dir, fs: FeatureStore): start_date=start_date, end_date=end_date, ).to_df() + + +def test_get_feature_view_by_name_propagates_transient_errors(): + """Transient registry errors must not be swallowed and misreported as + FeatureViewNotFoundException.""" + with tempfile.TemporaryDirectory() as temp_dir: + store = default_store(str(temp_dir)) + location = "grpc+tcp://localhost:0" + + _init_auth_manager(store=store) + server = OfflineServer(store=store, location=location) + + transient_error = ConnectionError("registry temporarily unavailable") + + with patch.object( + server.store.registry, + "get_feature_view", + side_effect=transient_error, + ): + with pytest.raises(ConnectionError, match="registry temporarily"): + server.get_feature_view_by_name( + fv_name="driver_hourly_stats", + name_alias=None, + project=PROJECT_NAME, + ) diff --git a/sdk/python/tests/unit/test_on_demand_feature_view.py b/sdk/python/tests/unit/test_on_demand_feature_view.py index 505146aa612..07e9e6a0b94 100644 --- a/sdk/python/tests/unit/test_on_demand_feature_view.py +++ b/sdk/python/tests/unit/test_on_demand_feature_view.py @@ -418,3 +418,175 @@ def another_transform(features_df: pd.DataFrame) -> pd.DataFrame: deserialized = OnDemandFeatureView.from_proto(proto) assert deserialized.name == CUSTOM_FUNCTION_NAME + + +def test_track_metrics_defaults_to_false(): + file_source = FileSource(name="my-file-source", path="test.parquet") + feature_view = FeatureView( + name="my-feature-view", + entities=[], + schema=[ + Field(name="feature1", dtype=Float32), + Field(name="feature2", dtype=Float32), + ], + source=file_source, + ) + odfv = OnDemandFeatureView( + name="metrics-default-odfv", + sources=[feature_view], + schema=[Field(name="output1", dtype=Float32)], + feature_transformation=PandasTransformation( + udf=udf1, udf_string="udf1 source code" + ), + ) + assert odfv.track_metrics is False + + +def test_track_metrics_true_persists_via_proto(): + file_source = FileSource(name="my-file-source", path="test.parquet") + feature_view = FeatureView( + name="my-feature-view", + entities=[], + schema=[ + Field(name="feature1", dtype=Float32), + Field(name="feature2", dtype=Float32), + ], + source=file_source, + ) + odfv = OnDemandFeatureView( + name="tracked-metrics-odfv", + sources=[feature_view], + schema=[Field(name="output1", dtype=Float32)], + feature_transformation=PandasTransformation( + udf=udf1, udf_string="udf1 source code" + ), + track_metrics=True, + ) + assert odfv.track_metrics is True + + proto = odfv.to_proto() + assert proto.spec.tags.get("feast:track_metrics") == "true" + + restored = OnDemandFeatureView.from_proto(proto) + assert restored.track_metrics is True + assert "feast:track_metrics" not in restored.tags, ( + "Internal feast:track_metrics tag leaked into user-facing self.tags " + "after proto round-trip" + ) + + +def test_track_metrics_proto_roundtrip_preserves_user_tags(): + """User tags must survive a proto round-trip without internal tag pollution.""" + file_source = FileSource(name="my-file-source", path="test.parquet") + feature_view = FeatureView( + name="my-feature-view", + entities=[], + schema=[ + Field(name="feature1", dtype=Float32), + Field(name="feature2", dtype=Float32), + ], + source=file_source, + ) + user_tags = {"team": "ml-platform", "priority": "high"} + odfv = OnDemandFeatureView( + name="tagged-odfv", + sources=[feature_view], + schema=[Field(name="output1", dtype=Float32)], + feature_transformation=PandasTransformation( + udf=udf1, udf_string="udf1 source code" + ), + tags=user_tags, + track_metrics=True, + ) + assert odfv.tags == user_tags + + proto = odfv.to_proto() + restored = OnDemandFeatureView.from_proto(proto) + + assert restored.tags == user_tags + assert restored.track_metrics is True + + +def test_track_metrics_false_not_stored_in_tags(): + file_source = FileSource(name="my-file-source", path="test.parquet") + feature_view = FeatureView( + name="my-feature-view", + entities=[], + schema=[ + Field(name="feature1", dtype=Float32), + Field(name="feature2", dtype=Float32), + ], + source=file_source, + ) + odfv = OnDemandFeatureView( + name="no-metrics-odfv", + sources=[feature_view], + schema=[Field(name="output1", dtype=Float32)], + feature_transformation=PandasTransformation( + udf=udf1, udf_string="udf1 source code" + ), + track_metrics=False, + ) + proto = odfv.to_proto() + assert "feast:track_metrics" not in proto.spec.tags + + restored = OnDemandFeatureView.from_proto(proto) + assert restored.track_metrics is False + + +def test_copy_preserves_track_metrics(): + """__copy__ must carry track_metrics so FeatureService projections keep timing enabled.""" + import copy + + file_source = FileSource(name="my-file-source", path="test.parquet") + feature_view = FeatureView( + name="my-feature-view", + entities=[], + schema=[ + Field(name="feature1", dtype=Float32), + Field(name="feature2", dtype=Float32), + ], + source=file_source, + ) + odfv = OnDemandFeatureView( + name="tracked-odfv", + sources=[feature_view], + schema=[Field(name="output1", dtype=Float32)], + feature_transformation=PandasTransformation( + udf=udf1, udf_string="udf1 source code" + ), + track_metrics=True, + ) + assert odfv.track_metrics is True + + copied = copy.copy(odfv) + assert copied.track_metrics is True, ( + "__copy__ lost track_metrics; ODFV timing metrics will be silently disabled " + "when using FeatureService projections" + ) + + +def test_eq_considers_track_metrics(): + """__eq__ must distinguish ODFVs that differ only in track_metrics.""" + file_source = FileSource(name="my-file-source", path="test.parquet") + feature_view = FeatureView( + name="my-feature-view", + entities=[], + schema=[ + Field(name="feature1", dtype=Float32), + Field(name="feature2", dtype=Float32), + ], + source=file_source, + ) + common = dict( + name="eq-odfv", + sources=[feature_view], + schema=[Field(name="output1", dtype=Float32)], + feature_transformation=PandasTransformation( + udf=udf1, udf_string="udf1 source code" + ), + ) + odfv_tracked = OnDemandFeatureView(**common, track_metrics=True) + odfv_untracked = OnDemandFeatureView(**common, track_metrics=False) + + assert odfv_tracked != odfv_untracked diff --git a/sdk/python/tests/unit/test_on_demand_python_transformation.py b/sdk/python/tests/unit/test_on_demand_python_transformation.py index 6a0f777b283..3ce02255c7c 100644 --- a/sdk/python/tests/unit/test_on_demand_python_transformation.py +++ b/sdk/python/tests/unit/test_on_demand_python_transformation.py @@ -400,291 +400,292 @@ def test_stored_writes(self): class TestOnDemandPythonTransformationAllDataTypes(unittest.TestCase): def setUp(self): - with tempfile.TemporaryDirectory() as data_dir: - self.store = FeatureStore( - config=RepoConfig( - project="test_on_demand_python_transformation", - registry=os.path.join(data_dir, "registry.db"), - provider="local", - entity_key_serialization_version=3, - online_store=SqliteOnlineStoreConfig( - path=os.path.join(data_dir, "online.db") - ), - ) + self.data_dir = tempfile.mkdtemp() + data_dir = self.data_dir + self.store = FeatureStore( + config=RepoConfig( + project="test_on_demand_python_transformation", + registry=os.path.join(data_dir, "registry.db"), + provider="local", + entity_key_serialization_version=3, + online_store=SqliteOnlineStoreConfig( + path=os.path.join(data_dir, "online.db") + ), ) + ) - # Generate test data. - end_date = datetime.now().replace(microsecond=0, second=0, minute=0) - start_date = end_date - timedelta(days=15) + # Generate test data. + end_date = datetime.now().replace(microsecond=0, second=0, minute=0) + start_date = end_date - timedelta(days=15) - driver_entities = [1001, 1002, 1003, 1004, 1005] - driver_df = create_driver_hourly_stats_df( - driver_entities, start_date, end_date - ) - driver_stats_path = os.path.join(data_dir, "driver_stats.parquet") - driver_df.to_parquet( - path=driver_stats_path, allow_truncated_timestamps=True - ) + driver_entities = [1001, 1002, 1003, 1004, 1005] + driver_df = create_driver_hourly_stats_df(driver_entities, start_date, end_date) + driver_stats_path = os.path.join(data_dir, "driver_stats.parquet") + driver_df.to_parquet(path=driver_stats_path, allow_truncated_timestamps=True) - driver = Entity(name="driver", join_keys=["driver_id"]) + driver = Entity(name="driver", join_keys=["driver_id"]) - driver_stats_source = FileSource( - name="driver_hourly_stats_source", - path=driver_stats_path, - timestamp_field="event_timestamp", - created_timestamp_column="created", - ) + driver_stats_source = FileSource( + name="driver_hourly_stats_source", + path=driver_stats_path, + timestamp_field="event_timestamp", + created_timestamp_column="created", + ) - driver_stats_fv = FeatureView( - name="driver_hourly_stats", - entities=[driver], - ttl=timedelta(days=0), - schema=[ - Field(name="conv_rate", dtype=Float32), - Field(name="acc_rate", dtype=Float32), - Field(name="avg_daily_trips", dtype=Int64), - ], - online=True, - source=driver_stats_source, - ) - assert driver_stats_fv.entities == [driver.name] - assert driver_stats_fv.entity_columns == [] + driver_stats_fv = FeatureView( + name="driver_hourly_stats", + entities=[driver], + ttl=timedelta(days=0), + schema=[ + Field(name="conv_rate", dtype=Float32), + Field(name="acc_rate", dtype=Float32), + Field(name="avg_daily_trips", dtype=Int64), + ], + online=True, + source=driver_stats_source, + ) + assert driver_stats_fv.entities == [driver.name] + assert driver_stats_fv.entity_columns == [] - request_source = RequestSource( - name="request_source", - schema=[ - Field(name="avg_daily_trip_rank_thresholds", dtype=Array(Int64)), - Field(name="avg_daily_trip_rank_names", dtype=Array(String)), - ], - ) - input_request = RequestSource( - name="vals_to_add", - schema=[ - Field(name="val_to_add", dtype=Int64), - Field(name="val_to_add_2", dtype=Int64), - ], - ) + request_source = RequestSource( + name="request_source", + schema=[ + Field(name="avg_daily_trip_rank_thresholds", dtype=Array(Int64)), + Field(name="avg_daily_trip_rank_names", dtype=Array(String)), + ], + ) + input_request = RequestSource( + name="vals_to_add", + schema=[ + Field(name="val_to_add", dtype=Int64), + Field(name="val_to_add_2", dtype=Int64), + ], + ) - @on_demand_feature_view( - sources=[request_source, driver_stats_fv], - schema=[ - Field(name="highest_achieved_rank", dtype=String), - Field(name="avg_daily_trips_plus_one", dtype=Int64), - Field(name="conv_rate_plus_acc", dtype=Float64), - Field(name="is_highest_rank", dtype=Bool), - Field(name="achieved_ranks", dtype=Array(String)), - Field(name="trips_until_next_rank_int", dtype=Array(Int64)), - Field(name="trips_until_next_rank_float", dtype=Array(Float64)), - Field(name="achieved_ranks_mask", dtype=Array(Bool)), - ], - mode="python", - ) - def python_view(inputs: dict[str, Any]) -> dict[str, Any]: - output = {} - trips_until_next_rank = [ - [max(threshold - row[1], 0) for threshold in row[0]] - for row in zip( - inputs["avg_daily_trip_rank_thresholds"], - inputs["avg_daily_trips"], - ) - ] - mask = [[value <= 0 for value in row] for row in trips_until_next_rank] - ranks = [ - [rank if mask else "Locked" for mask, rank in zip(*row)] - for row in zip(mask, inputs["avg_daily_trip_rank_names"]) - ] - highest_rank = [ - ([rank for rank in row if rank != "Locked"][-1:] or ["None"])[0] - for row in ranks - ] + @on_demand_feature_view( + sources=[request_source, driver_stats_fv], + schema=[ + Field(name="highest_achieved_rank", dtype=String), + Field(name="avg_daily_trips_plus_one", dtype=Int64), + Field(name="conv_rate_plus_acc", dtype=Float64), + Field(name="is_highest_rank", dtype=Bool), + Field(name="achieved_ranks", dtype=Array(String)), + Field(name="trips_until_next_rank_int", dtype=Array(Int64)), + Field(name="trips_until_next_rank_float", dtype=Array(Float64)), + Field(name="achieved_ranks_mask", dtype=Array(Bool)), + ], + mode="python", + ) + def python_view(inputs: dict[str, Any]) -> dict[str, Any]: + output = {} + trips_until_next_rank = [ + [max(threshold - row[1], 0) for threshold in row[0]] + for row in zip( + inputs["avg_daily_trip_rank_thresholds"], + inputs["avg_daily_trips"], + ) + ] + mask = [[value <= 0 for value in row] for row in trips_until_next_rank] + ranks = [ + [rank if mask else "Locked" for mask, rank in zip(*row)] + for row in zip(mask, inputs["avg_daily_trip_rank_names"]) + ] + highest_rank = [ + ([rank for rank in row if rank != "Locked"][-1:] or ["None"])[0] + for row in ranks + ] - output["conv_rate_plus_acc"] = [ - sum(row) for row in zip(inputs["conv_rate"], inputs["acc_rate"]) - ] - output["avg_daily_trips_plus_one"] = [ - row + 1 for row in inputs["avg_daily_trips"] - ] - output["highest_achieved_rank"] = highest_rank - output["is_highest_rank"] = [row[-1] != "Locked" for row in ranks] + output["conv_rate_plus_acc"] = [ + sum(row) for row in zip(inputs["conv_rate"], inputs["acc_rate"]) + ] + output["avg_daily_trips_plus_one"] = [ + row + 1 for row in inputs["avg_daily_trips"] + ] + output["highest_achieved_rank"] = highest_rank + output["is_highest_rank"] = [row[-1] != "Locked" for row in ranks] - output["trips_until_next_rank_int"] = trips_until_next_rank - output["trips_until_next_rank_float"] = [ - [float(value) for value in row] for row in trips_until_next_rank - ] - output["achieved_ranks_mask"] = mask - output["achieved_ranks"] = ranks - return output + output["trips_until_next_rank_int"] = trips_until_next_rank + output["trips_until_next_rank_float"] = [ + [float(value) for value in row] for row in trips_until_next_rank + ] + output["achieved_ranks_mask"] = mask + output["achieved_ranks"] = ranks + return output - @on_demand_feature_view( - sources=[ - driver_stats_fv, - input_request, - ], - schema=[ - Field(name="conv_rate_plus_val1", dtype=Float64), - Field(name="conv_rate_plus_val2", dtype=Float64), - ], - mode="pandas", + @on_demand_feature_view( + sources=[ + driver_stats_fv, + input_request, + ], + schema=[ + Field(name="conv_rate_plus_val1", dtype=Float64), + Field(name="conv_rate_plus_val2", dtype=Float64), + ], + mode="pandas", + ) + def pandas_view(features_df: pd.DataFrame) -> pd.DataFrame: + df = pd.DataFrame() + df["conv_rate_plus_val1"] = ( + features_df["conv_rate"] + features_df["val_to_add"] ) - def pandas_view(features_df: pd.DataFrame) -> pd.DataFrame: - df = pd.DataFrame() - df["conv_rate_plus_val1"] = ( - features_df["conv_rate"] + features_df["val_to_add"] - ) - df["conv_rate_plus_val2"] = ( - features_df["conv_rate"] + features_df["val_to_add_2"] - ) - return df - - self.store.apply( - [ - driver, - driver_stats_source, - driver_stats_fv, - python_view, - pandas_view, - input_request, - request_source, - ] + df["conv_rate_plus_val2"] = ( + features_df["conv_rate"] + features_df["val_to_add_2"] ) - fv_applied = self.store.get_feature_view("driver_hourly_stats") - assert fv_applied.entities == [driver.name] - # Note here that after apply() is called, the entity_columns are populated with the join_key - assert fv_applied.entity_columns[0].name == driver.join_key + return df - self.store.write_to_online_store( - feature_view_name="driver_hourly_stats", df=driver_df - ) + self.store.apply( + [ + driver, + driver_stats_source, + driver_stats_fv, + python_view, + pandas_view, + input_request, + request_source, + ] + ) + fv_applied = self.store.get_feature_view("driver_hourly_stats") + assert fv_applied.entities == [driver.name] + # Note here that after apply() is called, the entity_columns are populated with the join_key + assert fv_applied.entity_columns[0].name == driver.join_key - batch_sample = pd.DataFrame(driver_entities, columns=["driver_id"]) - batch_sample["val_to_add"] = 0 - batch_sample["val_to_add_2"] = 1 - batch_sample["event_timestamp"] = start_date - batch_sample["created"] = start_date - fv_only_cols = ["driver_id", "event_timestamp", "created"] + self.store.write_to_online_store( + feature_view_name="driver_hourly_stats", df=driver_df + ) - resp_base_fv = self.store.get_historical_features( - entity_df=batch_sample[fv_only_cols], - features=[ - "driver_hourly_stats:conv_rate", - "driver_hourly_stats:acc_rate", - "driver_hourly_stats:avg_daily_trips", - ], - ).to_df() - assert resp_base_fv is not None - assert sorted(resp_base_fv.columns) == [ - "acc_rate", - "avg_daily_trips", - "conv_rate", - "created__", - "driver_id", - "event_timestamp", - ] - resp = self.store.get_historical_features( - entity_df=batch_sample, - features=[ - "driver_hourly_stats:conv_rate", - "driver_hourly_stats:acc_rate", - "driver_hourly_stats:avg_daily_trips", - "pandas_view:conv_rate_plus_val1", - "pandas_view:conv_rate_plus_val2", - ], - ).to_df() - assert resp is not None - assert resp["conv_rate_plus_val1"].isnull().sum() == 0 - - batch_sample["avg_daily_trip_rank_thresholds"] = [ - [100, 250, 500, 1000] - ] * batch_sample.shape[0] - batch_sample["avg_daily_trip_rank_names"] = [ - ["Bronze", "Silver", "Gold", "Platinum"] - ] * batch_sample.shape[0] - resp_python = self.store.get_historical_features( - entity_df=batch_sample, - features=[ - "driver_hourly_stats:conv_rate", - "driver_hourly_stats:acc_rate", - "driver_hourly_stats:avg_daily_trips", - "python_view:conv_rate_plus_acc", - ], - ).to_df() - assert resp_python is not None - assert resp_python["conv_rate_plus_acc"].isnull().sum() == 0 - - # Now testing feature retrieval for driver ids not in the dataset - missing_batch_sample = pd.DataFrame([1234567890], columns=["driver_id"]) - missing_batch_sample["val_to_add"] = 0 - missing_batch_sample["val_to_add_2"] = 1 - missing_batch_sample["event_timestamp"] = start_date - missing_batch_sample["created"] = start_date - resp_offline = self.store.get_historical_features( - entity_df=missing_batch_sample, - features=[ - "driver_hourly_stats:conv_rate", - "driver_hourly_stats:acc_rate", - "driver_hourly_stats:avg_daily_trips", - "pandas_view:conv_rate_plus_val1", - "pandas_view:conv_rate_plus_val2", - ], - ).to_df() - assert resp_offline is not None - assert resp_offline["conv_rate_plus_val1"].isnull().sum() == 1 - assert sorted(resp_offline.columns) == [ - "acc_rate", - "avg_daily_trips", - "conv_rate", - "conv_rate_plus_val1", - "conv_rate_plus_val2", - "created__", - "driver_id", - "event_timestamp", - "val_to_add", - "val_to_add_2", - ] - resp_online_missing_entity = self.store.get_online_features( - entity_rows=[ - {"driver_id": 1234567890, "val_to_add": 0, "val_to_add_2": 1} - ], - features=[ - "driver_hourly_stats:conv_rate", - "driver_hourly_stats:acc_rate", - "driver_hourly_stats:avg_daily_trips", - "pandas_view:conv_rate_plus_val1", - "pandas_view:conv_rate_plus_val2", - ], - ) - assert resp_online_missing_entity is not None - resp_online = self.store.get_online_features( - entity_rows=[{"driver_id": 1001, "val_to_add": 0, "val_to_add_2": 1}], - features=[ - "driver_hourly_stats:conv_rate", - "driver_hourly_stats:acc_rate", - "driver_hourly_stats:avg_daily_trips", - "pandas_view:conv_rate_plus_val1", - "pandas_view:conv_rate_plus_val2", - ], - ).to_df() - assert resp_online is not None - assert sorted(resp_online.columns) == [ - "acc_rate", - "avg_daily_trips", - "conv_rate", - "conv_rate_plus_val1", - "conv_rate_plus_val2", - "driver_id", - # It does not have the items below - # "created__", - # "event_timestamp", - # "val_to_add", - # "val_to_add_2", - ] - # Note online and offline columns will not match because: - # you want to be space efficient online when considering the impact of network latency so you want to send - # and receive the minimally required set of data, which means after transformation you only need to send the - # output in the response. - # Offline, you will probably prioritize reproducibility and being able to iterate, which means you will want - # the underlying inputs into your transformation, so the extra data is tolerable. - assert sorted(resp_online.columns) != sorted(resp_offline.columns) + batch_sample = pd.DataFrame(driver_entities, columns=["driver_id"]) + batch_sample["val_to_add"] = 0 + batch_sample["val_to_add_2"] = 1 + batch_sample["event_timestamp"] = start_date + batch_sample["created"] = start_date + fv_only_cols = ["driver_id", "event_timestamp", "created"] + + resp_base_fv = self.store.get_historical_features( + entity_df=batch_sample[fv_only_cols], + features=[ + "driver_hourly_stats:conv_rate", + "driver_hourly_stats:acc_rate", + "driver_hourly_stats:avg_daily_trips", + ], + ).to_df() + assert resp_base_fv is not None + assert sorted(resp_base_fv.columns) == [ + "acc_rate", + "avg_daily_trips", + "conv_rate", + "created__", + "driver_id", + "event_timestamp", + ] + resp = self.store.get_historical_features( + entity_df=batch_sample, + features=[ + "driver_hourly_stats:conv_rate", + "driver_hourly_stats:acc_rate", + "driver_hourly_stats:avg_daily_trips", + "pandas_view:conv_rate_plus_val1", + "pandas_view:conv_rate_plus_val2", + ], + ).to_df() + assert resp is not None + assert resp["conv_rate_plus_val1"].isnull().sum() == 0 + + batch_sample["avg_daily_trip_rank_thresholds"] = [ + [100, 250, 500, 1000] + ] * batch_sample.shape[0] + batch_sample["avg_daily_trip_rank_names"] = [ + ["Bronze", "Silver", "Gold", "Platinum"] + ] * batch_sample.shape[0] + resp_python = self.store.get_historical_features( + entity_df=batch_sample, + features=[ + "driver_hourly_stats:conv_rate", + "driver_hourly_stats:acc_rate", + "driver_hourly_stats:avg_daily_trips", + "python_view:conv_rate_plus_acc", + ], + ).to_df() + assert resp_python is not None + assert resp_python["conv_rate_plus_acc"].isnull().sum() == 0 + + # Now testing feature retrieval for driver ids not in the dataset + missing_batch_sample = pd.DataFrame([1234567890], columns=["driver_id"]) + missing_batch_sample["val_to_add"] = 0 + missing_batch_sample["val_to_add_2"] = 1 + missing_batch_sample["event_timestamp"] = start_date + missing_batch_sample["created"] = start_date + resp_offline = self.store.get_historical_features( + entity_df=missing_batch_sample, + features=[ + "driver_hourly_stats:conv_rate", + "driver_hourly_stats:acc_rate", + "driver_hourly_stats:avg_daily_trips", + "pandas_view:conv_rate_plus_val1", + "pandas_view:conv_rate_plus_val2", + ], + ).to_df() + assert resp_offline is not None + assert resp_offline["conv_rate_plus_val1"].isnull().sum() == 1 + assert sorted(resp_offline.columns) == [ + "acc_rate", + "avg_daily_trips", + "conv_rate", + "conv_rate_plus_val1", + "conv_rate_plus_val2", + "created__", + "driver_id", + "event_timestamp", + "val_to_add", + "val_to_add_2", + ] + resp_online_missing_entity = self.store.get_online_features( + entity_rows=[{"driver_id": 1234567890, "val_to_add": 0, "val_to_add_2": 1}], + features=[ + "driver_hourly_stats:conv_rate", + "driver_hourly_stats:acc_rate", + "driver_hourly_stats:avg_daily_trips", + "pandas_view:conv_rate_plus_val1", + "pandas_view:conv_rate_plus_val2", + ], + ) + assert resp_online_missing_entity is not None + resp_online = self.store.get_online_features( + entity_rows=[{"driver_id": 1001, "val_to_add": 0, "val_to_add_2": 1}], + features=[ + "driver_hourly_stats:conv_rate", + "driver_hourly_stats:acc_rate", + "driver_hourly_stats:avg_daily_trips", + "pandas_view:conv_rate_plus_val1", + "pandas_view:conv_rate_plus_val2", + ], + ).to_df() + assert resp_online is not None + assert sorted(resp_online.columns) == [ + "acc_rate", + "avg_daily_trips", + "conv_rate", + "conv_rate_plus_val1", + "conv_rate_plus_val2", + "driver_id", + # It does not have the items below + # "created__", + # "event_timestamp", + # "val_to_add", + # "val_to_add_2", + ] + # Note online and offline columns will not match because: + # you want to be space efficient online when considering the impact of network latency so you want to send + # and receive the minimally required set of data, which means after transformation you only need to send the + # output in the response. + # Offline, you will probably prioritize reproducibility and being able to iterate, which means you will want + # the underlying inputs into your transformation, so the extra data is tolerable. + assert sorted(resp_online.columns) != sorted(resp_offline.columns) + + def tearDown(self): + import shutil + + if hasattr(self, "data_dir"): + shutil.rmtree(self.data_dir, ignore_errors=True) def test_setup(self): pass diff --git a/sdk/python/tests/unit/test_proto_json.py b/sdk/python/tests/unit/test_proto_json.py index b5e01744e44..6b3c7181ad7 100644 --- a/sdk/python/tests/unit/test_proto_json.py +++ b/sdk/python/tests/unit/test_proto_json.py @@ -103,6 +103,33 @@ def test_feature_list(proto_json_patch): ) +def test_nested_collection_json_roundtrip(proto_json_patch): + """Nested collection values (list of lists) should survive JSON roundtrip.""" + from feast.protos.feast.types.Value_pb2 import Value + + # Build a Value with list_val containing [[1,2],[3,4,5]] + value_proto = Value() + inner1 = value_proto.list_val.val.add() + inner1.int64_list_val.val.extend([1, 2]) + inner2 = value_proto.list_val.val.add() + inner2.int64_list_val.val.extend([3, 4, 5]) + + # Serialize to JSON + value_json = MessageToDict(value_proto) + assert isinstance(value_json, list) + assert len(value_json) == 2 + assert value_json[0] == [1, 2] + assert value_json[1] == [3, 4, 5] + + # Deserialize back from JSON + feature_vector_str = '{"values": [[[1, 2], [3, 4, 5]]]}' + feature_vector_proto = FeatureVector() + Parse(feature_vector_str, feature_vector_proto) + assert len(feature_vector_proto.values) == 1 + assert feature_vector_proto.values[0].WhichOneof("val") == "list_val" + assert len(feature_vector_proto.values[0].list_val.val) == 2 + + @pytest.fixture(scope="module") def proto_json_patch(): proto_json.patch() diff --git a/sdk/python/tests/unit/test_type_map.py b/sdk/python/tests/unit/test_type_map.py index 8508b490d78..8ec854d64a0 100644 --- a/sdk/python/tests/unit/test_type_map.py +++ b/sdk/python/tests/unit/test_type_map.py @@ -1,15 +1,29 @@ +import uuid + import numpy as np import pandas as pd +import pyarrow import pytest from feast.protos.feast.types.Value_pb2 import Map, MapList from feast.type_map import ( + _convert_value_type_str_to_value_type, _python_dict_to_map_proto, _python_list_to_map_list_proto, + arrow_to_pg_type, + feast_value_type_to_pa, feast_value_type_to_python_type, + pa_to_feast_value_type, + pa_to_redshift_value_type, + pg_type_to_feast_value_type, python_type_to_feast_value_type, python_values_to_proto_values, + redshift_to_feast_value_type, + snowflake_type_to_feast_value_type, + spark_to_feast_value_type, ) +from feast.types import Array, from_feast_to_pyarrow_type +from feast.types import Map as FeastMap from feast.value_type import ValueType @@ -461,3 +475,1373 @@ def test_multiple_set_values(self): assert feast_value_type_to_python_type(protos[0]) == {1, 2, 3} assert feast_value_type_to_python_type(protos[1]) == {4, 5} assert feast_value_type_to_python_type(protos[2]) == {6} + + +class TestMapArrowTypeSupport: + """Test cases for MAP and MAP_LIST Arrow type conversions.""" + + def test_feast_value_type_to_pa_map(self): + """Test that ValueType.MAP converts to a PyArrow map type.""" + pa_type = feast_value_type_to_pa(ValueType.MAP) + assert isinstance(pa_type, pyarrow.MapType) + assert pa_type.key_type == pyarrow.string() + + def test_feast_value_type_to_pa_map_list(self): + """Test that ValueType.MAP_LIST converts to a PyArrow list of maps.""" + pa_type = feast_value_type_to_pa(ValueType.MAP_LIST) + assert isinstance(pa_type, pyarrow.ListType) + assert isinstance(pa_type.value_type, pyarrow.MapType) + + def test_pa_to_feast_value_type_map(self): + """Test that PyArrow map type string converts to ValueType.MAP.""" + result = pa_to_feast_value_type("map") + assert result == ValueType.MAP + + def test_pa_to_feast_value_type_map_various_value_types(self): + """Test that various PyArrow map type strings all convert to MAP.""" + assert pa_to_feast_value_type("map") == ValueType.MAP + assert pa_to_feast_value_type("map") == ValueType.MAP + assert pa_to_feast_value_type("map") == ValueType.MAP + + def test_from_feast_to_pyarrow_type_map(self): + """Test that Feast Map type converts to PyArrow map type.""" + pa_type = from_feast_to_pyarrow_type(FeastMap) + assert isinstance(pa_type, pyarrow.MapType) + + def test_from_feast_to_pyarrow_type_array_map(self): + """Test that Feast Array(Map) converts to PyArrow list of maps.""" + pa_type = from_feast_to_pyarrow_type(Array(FeastMap)) + assert isinstance(pa_type, pyarrow.ListType) + assert isinstance(pa_type.value_type, pyarrow.MapType) + + def test_convert_value_type_str_map(self): + """Test that 'MAP' string converts to ValueType.MAP.""" + assert _convert_value_type_str_to_value_type("MAP") == ValueType.MAP + + def test_convert_value_type_str_map_list(self): + """Test that 'MAP_LIST' string converts to ValueType.MAP_LIST.""" + assert _convert_value_type_str_to_value_type("MAP_LIST") == ValueType.MAP_LIST + + def test_arrow_to_pg_type_map(self): + """Test that Arrow map type converts to Postgres jsonb.""" + assert arrow_to_pg_type("map") == "jsonb" + assert arrow_to_pg_type("map") == "jsonb" + + def test_pg_type_to_feast_value_type_json(self): + """Test that Postgres json/jsonb types convert to ValueType.MAP.""" + assert pg_type_to_feast_value_type("json") == ValueType.MAP + assert pg_type_to_feast_value_type("jsonb") == ValueType.MAP + + def test_pg_type_to_feast_value_type_json_array(self): + """Test that Postgres json[]/jsonb[] types convert to ValueType.MAP_LIST.""" + assert pg_type_to_feast_value_type("json[]") == ValueType.MAP_LIST + assert pg_type_to_feast_value_type("jsonb[]") == ValueType.MAP_LIST + + def test_snowflake_variant_to_map(self): + """Test that Snowflake VARIANT/OBJECT types convert to ValueType.MAP.""" + assert snowflake_type_to_feast_value_type("VARIANT") == ValueType.MAP + assert snowflake_type_to_feast_value_type("OBJECT") == ValueType.MAP + + def test_redshift_super_to_map(self): + """Test that Redshift super type converts to ValueType.MAP.""" + assert redshift_to_feast_value_type("super") == ValueType.MAP + + def test_map_roundtrip_proto_to_arrow_type(self): + """Test that MAP type survives a full conversion roundtrip.""" + pa_type = feast_value_type_to_pa(ValueType.MAP) + pa_type_str = str(pa_type) + roundtrip = pa_to_feast_value_type(pa_type_str) + assert roundtrip == ValueType.MAP + + def test_spark_map_to_feast(self): + """Test that Spark map types convert to ValueType.MAP.""" + assert spark_to_feast_value_type("map") == ValueType.MAP + assert spark_to_feast_value_type("map") == ValueType.MAP + assert spark_to_feast_value_type("MAP") == ValueType.MAP + + def test_spark_array_map_to_feast(self): + """Test that Spark array> types convert to ValueType.MAP_LIST.""" + assert ( + spark_to_feast_value_type("array>") == ValueType.MAP_LIST + ) + + def test_spark_unknown_still_returns_null(self): + """Test that unrecognized Spark types still return NULL.""" + assert spark_to_feast_value_type("interval") == ValueType.NULL + + def test_spark_struct_to_feast_struct(self): + """Test that Spark struct types now convert to ValueType.STRUCT.""" + assert spark_to_feast_value_type("struct") == ValueType.STRUCT + + +class TestEnableValidationOnFeatureView: + """Test that enable_validation is a real parameter on FeatureView.""" + + def test_feature_view_has_enable_validation_default_false(self): + """Test that FeatureView has enable_validation defaulting to False.""" + import inspect + + from feast.feature_view import FeatureView + + sig = inspect.signature(FeatureView.__init__) + assert "enable_validation" in sig.parameters + assert sig.parameters["enable_validation"].default is False + + def test_batch_feature_view_has_enable_validation(self): + """Test that BatchFeatureView has enable_validation parameter.""" + import inspect + + from feast.batch_feature_view import BatchFeatureView + + sig = inspect.signature(BatchFeatureView.__init__) + assert "enable_validation" in sig.parameters + assert sig.parameters["enable_validation"].default is False + + def test_stream_feature_view_has_enable_validation(self): + """Test that StreamFeatureView has enable_validation parameter.""" + import inspect + + from feast.stream_feature_view import StreamFeatureView + + sig = inspect.signature(StreamFeatureView.__init__) + assert "enable_validation" in sig.parameters + assert sig.parameters["enable_validation"].default is False + + +class TestRedshiftDynamoDBMapSupport: + """Test cases for DynamoDB + Redshift map type round-trips.""" + + def test_pa_to_redshift_value_type_map(self): + """Test that Arrow map type maps to Redshift 'super' type.""" + pa_type = feast_value_type_to_pa(ValueType.MAP) + assert pa_to_redshift_value_type(pa_type) == "super" + + def test_pa_to_redshift_value_type_map_list(self): + """Test that Arrow list-of-map type maps to Redshift 'super' type.""" + pa_type = feast_value_type_to_pa(ValueType.MAP_LIST) + assert pa_to_redshift_value_type(pa_type) == "super" + + def test_json_string_to_map_proto(self): + """Test that JSON strings are parsed to MAP protos during materialization.""" + json_str = '{"key1": "value1", "key2": "value2"}' + protos = python_values_to_proto_values([json_str], ValueType.MAP) + converted = feast_value_type_to_python_type(protos[0]) + assert isinstance(converted, dict) + assert converted["key1"] == "value1" + assert converted["key2"] == "value2" + + def test_json_string_to_map_list_proto(self): + """Test that JSON strings are parsed to MAP_LIST protos during materialization.""" + json_str = '[{"a": "1"}, {"b": "2"}]' + protos = python_values_to_proto_values([json_str], ValueType.MAP_LIST) + converted = feast_value_type_to_python_type(protos[0]) + assert isinstance(converted, list) + assert len(converted) == 2 + assert converted[0]["a"] == "1" + + def test_dict_still_works_for_map(self): + """Test that regular Python dicts still work for MAP (no regression).""" + test_dict = {"x": "y", "a": 1} + protos = python_values_to_proto_values([test_dict], ValueType.MAP) + converted = feast_value_type_to_python_type(protos[0]) + assert isinstance(converted, dict) + assert converted["x"] == "y" + + def test_none_map_still_works(self): + """Test that None MAP values still produce empty proto (no regression).""" + protos = python_values_to_proto_values([None], ValueType.MAP) + converted = feast_value_type_to_python_type(protos[0]) + assert converted is None + + def test_redshift_super_roundtrip(self): + """Test full type conversion roundtrip: Redshift super → Feast MAP → Arrow → Redshift super.""" + feast_type = redshift_to_feast_value_type("super") + assert feast_type == ValueType.MAP + pa_type = feast_value_type_to_pa(feast_type) + redshift_type = pa_to_redshift_value_type(pa_type) + assert redshift_type == "super" + + +class TestJsonTypeSupport: + """Test cases for JSON value type.""" + + def test_simple_json_conversion(self): + """Test basic JSON type conversion: Python dict -> proto (json_val) -> Python.""" + test_data = {"name": "Alice", "age": 30, "active": True} + protos = python_values_to_proto_values([test_data], ValueType.JSON) + converted = feast_value_type_to_python_type(protos[0]) + + assert isinstance(converted, dict) + assert converted["name"] == "Alice" + assert converted["age"] == 30 + assert converted["active"] is True + + def test_json_string_passthrough(self): + """Test that a raw JSON string is stored and returned correctly.""" + json_str = '{"key": "value", "count": 42}' + protos = python_values_to_proto_values([json_str], ValueType.JSON) + converted = feast_value_type_to_python_type(protos[0]) + + assert isinstance(converted, dict) + assert converted["key"] == "value" + assert converted["count"] == 42 + + def test_json_array_value(self): + """Test JSON type with an array as the top-level value.""" + test_data = [1, 2, 3, "four"] + protos = python_values_to_proto_values([test_data], ValueType.JSON) + converted = feast_value_type_to_python_type(protos[0]) + + assert isinstance(converted, list) + assert converted == [1, 2, 3, "four"] + + def test_json_nested(self): + """Test deeply nested JSON structures.""" + test_data = { + "level1": {"level2": {"level3": {"value": "deep"}}}, + "array": [{"a": 1}, {"b": 2}], + } + protos = python_values_to_proto_values([test_data], ValueType.JSON) + converted = feast_value_type_to_python_type(protos[0]) + + assert converted["level1"]["level2"]["level3"]["value"] == "deep" + assert converted["array"][0]["a"] == 1 + + def test_null_json(self): + """Test None JSON conversion.""" + protos = python_values_to_proto_values([None], ValueType.JSON) + converted = feast_value_type_to_python_type(protos[0]) + assert converted is None + + def test_json_list_conversion(self): + """Test JSON_LIST type conversion.""" + test_data = [ + {"name": "Alice"}, + '{"name": "Bob"}', + {"count": 42}, + ] + protos = python_values_to_proto_values([test_data], ValueType.JSON_LIST) + converted = feast_value_type_to_python_type(protos[0]) + + assert isinstance(converted, list) + assert len(converted) == 3 + assert converted[0] == {"name": "Alice"} + assert converted[1] == {"name": "Bob"} + assert converted[2] == {"count": 42} + + def test_null_json_list(self): + """Test None JSON_LIST conversion.""" + protos = python_values_to_proto_values([None], ValueType.JSON_LIST) + converted = feast_value_type_to_python_type(protos[0]) + assert converted is None + + def test_multiple_json_values(self): + """Test conversion of multiple JSON values.""" + test_values = [ + {"x": 1}, + {"y": 2}, + None, + {"z": 3}, + ] + protos = python_values_to_proto_values(test_values, ValueType.JSON) + converted = [feast_value_type_to_python_type(p) for p in protos] + + assert converted[0] == {"x": 1} + assert converted[1] == {"y": 2} + assert converted[2] is None + assert converted[3] == {"z": 3} + + def test_feast_value_type_to_pa_json(self): + """Test that ValueType.JSON converts to PyArrow large_string.""" + pa_type = feast_value_type_to_pa(ValueType.JSON) + assert pa_type == pyarrow.large_string() + + def test_feast_value_type_to_pa_json_list(self): + """Test that ValueType.JSON_LIST converts to PyArrow list of large_string.""" + pa_type = feast_value_type_to_pa(ValueType.JSON_LIST) + assert isinstance(pa_type, pyarrow.ListType) + assert pa_type.value_type == pyarrow.large_string() + + def test_convert_value_type_str_json(self): + """Test that 'JSON' string converts to ValueType.JSON.""" + assert _convert_value_type_str_to_value_type("JSON") == ValueType.JSON + assert _convert_value_type_str_to_value_type("JSON_LIST") == ValueType.JSON_LIST + + def test_arrow_to_pg_type_json(self): + """Test that Arrow large_string converts to Postgres jsonb.""" + assert arrow_to_pg_type("large_string") == "jsonb" + + def test_bq_json_to_feast(self): + """Test that BigQuery JSON type converts to ValueType.JSON.""" + from feast.type_map import bq_to_feast_value_type + + assert bq_to_feast_value_type("JSON") == ValueType.JSON + + def test_spark_struct_not_json(self): + """Test that Spark struct types map to STRUCT not JSON.""" + assert spark_to_feast_value_type("struct") == ValueType.STRUCT + + def test_snowflake_json_to_feast(self): + """Test that Snowflake JSON type converts to ValueType.JSON.""" + assert snowflake_type_to_feast_value_type("JSON") == ValueType.JSON + + def test_json_feast_type_aliases(self): + """Test Json FeastType alias and conversions.""" + from feast.types import Json, from_feast_to_pyarrow_type + + pa_type = from_feast_to_pyarrow_type(Json) + assert pa_type == pyarrow.large_string() + + def test_json_value_types_mapping(self): + """Test JSON types in VALUE_TYPES_TO_FEAST_TYPES.""" + from feast.types import VALUE_TYPES_TO_FEAST_TYPES, Json + + assert VALUE_TYPES_TO_FEAST_TYPES[ValueType.JSON] == Json + + def test_pa_to_feast_value_type_large_string(self): + """Test that large_string arrow type converts to ValueType.JSON.""" + result = pa_to_feast_value_type("large_string") + assert result == ValueType.JSON + + +class TestStructTypeSupport: + """Test cases for STRUCT value type.""" + + def test_simple_struct_conversion(self): + """Test basic STRUCT type conversion: Python dict -> proto (struct_val) -> Python dict.""" + test_data = {"name": "Alice", "age": 30} + protos = python_values_to_proto_values([test_data], ValueType.STRUCT) + converted = feast_value_type_to_python_type(protos[0]) + + assert isinstance(converted, dict) + assert converted["name"] == "Alice" + assert converted["age"] == 30 + + def test_nested_struct_conversion(self): + """Test nested STRUCT type conversion.""" + test_data = { + "address": {"street": "123 Main St", "city": "NYC"}, + "name": "Alice", + } + protos = python_values_to_proto_values([test_data], ValueType.STRUCT) + converted = feast_value_type_to_python_type(protos[0]) + + assert converted["address"]["street"] == "123 Main St" + assert converted["address"]["city"] == "NYC" + assert converted["name"] == "Alice" + + def test_null_struct(self): + """Test None STRUCT conversion.""" + protos = python_values_to_proto_values([None], ValueType.STRUCT) + converted = feast_value_type_to_python_type(protos[0]) + assert converted is None + + def test_struct_list_conversion(self): + """Test STRUCT_LIST type conversion.""" + test_data = [ + {"name": "Alice", "age": 30}, + {"name": "Bob", "age": 25}, + ] + protos = python_values_to_proto_values([test_data], ValueType.STRUCT_LIST) + converted = feast_value_type_to_python_type(protos[0]) + + assert isinstance(converted, list) + assert len(converted) == 2 + assert converted[0]["name"] == "Alice" + assert converted[1]["age"] == 25 + + def test_null_struct_list(self): + """Test None STRUCT_LIST conversion.""" + protos = python_values_to_proto_values([None], ValueType.STRUCT_LIST) + converted = feast_value_type_to_python_type(protos[0]) + assert converted is None + + def test_multiple_struct_values(self): + """Test conversion of multiple STRUCT values.""" + test_values = [ + {"x": 1}, + None, + {"y": 2, "z": 3}, + ] + protos = python_values_to_proto_values(test_values, ValueType.STRUCT) + converted = [feast_value_type_to_python_type(p) for p in protos] + + assert converted[0] == {"x": 1} + assert converted[1] is None + assert converted[2] == {"y": 2, "z": 3} + + def test_struct_class_creation(self): + """Test Struct FeastType creation and validation.""" + from feast.types import Int32, String, Struct + + struct_type = Struct({"name": String, "age": Int32}) + assert struct_type.to_value_type() == ValueType.STRUCT + assert "name" in struct_type.fields + assert struct_type.fields["name"] == String + assert struct_type.fields["age"] == Int32 + + def test_struct_empty_raises(self): + """Test that empty Struct raises ValueError.""" + from feast.types import Struct + + with pytest.raises(ValueError, match="at least one field"): + Struct({}) + + def test_struct_to_pyarrow(self): + """Test Struct type converts to PyArrow struct.""" + from feast.types import Int32, String, Struct + + struct_type = Struct({"name": String, "age": Int32}) + pa_type = struct_type.to_pyarrow_type() + + assert pyarrow.types.is_struct(pa_type) + assert pa_type.get_field_index("name") >= 0 + assert pa_type.get_field_index("age") >= 0 + + def test_struct_from_feast_to_pyarrow(self): + """Test from_feast_to_pyarrow_type handles Struct.""" + from feast.types import Int32, String, Struct + + struct_type = Struct({"name": String, "age": Int32}) + pa_type = from_feast_to_pyarrow_type(struct_type) + + assert pyarrow.types.is_struct(pa_type) + + def test_array_of_struct(self): + """Test Array(Struct(...)) works.""" + from feast.types import Array, Int32, String, Struct + + struct_type = Struct({"name": String, "value": Int32}) + array_type = Array(struct_type) + + assert array_type.to_value_type() == ValueType.STRUCT_LIST + pa_type = from_feast_to_pyarrow_type(array_type) + assert isinstance(pa_type, pyarrow.ListType) + assert pyarrow.types.is_struct(pa_type.value_type) + + def test_feast_value_type_to_pa_struct(self): + """Test that ValueType.STRUCT converts to PyArrow struct (empty default).""" + pa_type = feast_value_type_to_pa(ValueType.STRUCT) + assert pyarrow.types.is_struct(pa_type) + + def test_feast_value_type_to_pa_struct_list(self): + """Test that ValueType.STRUCT_LIST converts to PyArrow list of struct.""" + pa_type = feast_value_type_to_pa(ValueType.STRUCT_LIST) + assert isinstance(pa_type, pyarrow.ListType) + assert pyarrow.types.is_struct(pa_type.value_type) + + def test_convert_value_type_str_struct(self): + """Test that 'STRUCT' string converts to ValueType.STRUCT.""" + assert _convert_value_type_str_to_value_type("STRUCT") == ValueType.STRUCT + assert ( + _convert_value_type_str_to_value_type("STRUCT_LIST") + == ValueType.STRUCT_LIST + ) + + def test_spark_struct_to_feast(self): + """Test that Spark struct types convert to ValueType.STRUCT.""" + assert spark_to_feast_value_type("struct") == ValueType.STRUCT + assert spark_to_feast_value_type("STRUCT") == ValueType.STRUCT + + def test_spark_array_struct_to_feast(self): + """Test that Spark array> types convert to STRUCT_LIST.""" + assert ( + spark_to_feast_value_type("array>") == ValueType.STRUCT_LIST + ) + + def test_bq_struct_to_feast(self): + """Test that BigQuery STRUCT/RECORD types convert to ValueType.STRUCT.""" + from feast.type_map import bq_to_feast_value_type + + assert bq_to_feast_value_type("STRUCT") == ValueType.STRUCT + assert bq_to_feast_value_type("RECORD") == ValueType.STRUCT + + def test_pa_to_feast_value_type_struct(self): + """Test that struct arrow type string converts to ValueType.STRUCT.""" + result = pa_to_feast_value_type("struct") + assert result == ValueType.STRUCT + + def test_struct_schema_persistence(self): + """Test that Struct schema is preserved through Field serialization/deserialization.""" + from feast.field import Field + from feast.types import Int32, String, Struct + + struct_type = Struct({"street": String, "zip": Int32}) + field = Field(name="address", dtype=struct_type) + + proto = field.to_proto() + restored = Field.from_proto(proto) + + assert isinstance(restored.dtype, Struct) + assert "street" in restored.dtype.fields + assert "zip" in restored.dtype.fields + assert restored.dtype.fields["street"] == String + assert restored.dtype.fields["zip"] == Int32 + + def test_struct_json_string_parsing(self): + """Test that JSON string input is parsed for STRUCT type.""" + json_str = '{"name": "Alice", "score": 95}' + protos = python_values_to_proto_values([json_str], ValueType.STRUCT) + converted = feast_value_type_to_python_type(protos[0]) + + assert isinstance(converted, dict) + assert converted["name"] == "Alice" + assert converted["score"] == 95 + + def test_struct_equality(self): + """Test Struct type equality.""" + from feast.types import Int32, String, Struct + + s1 = Struct({"name": String, "age": Int32}) + s2 = Struct({"name": String, "age": Int32}) + s3 = Struct({"name": String}) + + assert s1 == s2 + assert s1 != s3 + + def test_from_feast_type_struct(self): + """Test from_feast_type works for Struct.""" + from feast.types import Int32, String, Struct, from_feast_type + + struct_type = Struct({"name": String, "age": Int32}) + value_type = from_feast_type(struct_type) + assert value_type == ValueType.STRUCT + + def test_from_value_type_struct(self): + """Test from_value_type works for STRUCT (returns placeholder).""" + from feast.types import Struct, from_value_type + + feast_type = from_value_type(ValueType.STRUCT) + assert isinstance(feast_type, Struct) + + def test_from_value_type_struct_list(self): + """Test from_value_type works for STRUCT_LIST (returns placeholder Array(Struct)).""" + from feast.types import Array, Struct, from_value_type + + feast_type = from_value_type(ValueType.STRUCT_LIST) + assert isinstance(feast_type, Array) + assert isinstance(feast_type.base_type, Struct) + + +class TestJsonValidation: + """Test JSON well-formedness validation.""" + + def test_proto_conversion_valid_json_string(self): + """Valid JSON strings should convert without error.""" + valid_json = '{"key": "value", "num": 42}' + protos = python_values_to_proto_values([valid_json], ValueType.JSON) + assert protos[0].json_val == valid_json + + def test_proto_conversion_invalid_json_string_raises(self): + """Invalid JSON strings should raise ValueError during proto conversion.""" + import pytest + + invalid_json = "this is not json {{" + with pytest.raises(ValueError, match="Invalid JSON string for JSON type"): + python_values_to_proto_values([invalid_json], ValueType.JSON) + + def test_proto_conversion_dict_no_validation_needed(self): + """Python dicts are valid by definition and should not raise.""" + data = {"name": "Alice", "items": [1, 2, 3]} + protos = python_values_to_proto_values([data], ValueType.JSON) + converted = feast_value_type_to_python_type(protos[0]) + assert converted == data + + def test_proto_conversion_list_no_validation_needed(self): + """Python lists are valid by definition and should not raise.""" + data = [1, "two", {"three": 3}] + protos = python_values_to_proto_values([data], ValueType.JSON) + converted = feast_value_type_to_python_type(protos[0]) + assert converted == data + + def test_proto_conversion_none_passes(self): + """None values should pass through without validation.""" + protos = python_values_to_proto_values([None], ValueType.JSON) + converted = feast_value_type_to_python_type(protos[0]) + assert converted is None + + def test_proto_conversion_json_list_invalid_string_raises(self): + """Invalid JSON strings in JSON_LIST should raise ValueError.""" + import pytest + + data = ['{"valid": true}', "not-json"] + with pytest.raises(ValueError, match="Invalid JSON string in JSON_LIST"): + python_values_to_proto_values([data], ValueType.JSON_LIST) + + def test_proto_conversion_json_list_valid_mixed(self): + """JSON_LIST with valid strings and dicts should succeed.""" + data = ['{"a": 1}', {"b": 2}] + protos = python_values_to_proto_values([data], ValueType.JSON_LIST) + converted = feast_value_type_to_python_type(protos[0]) + assert len(converted) == 2 + assert converted[0] == {"a": 1} + assert converted[1] == {"b": 2} + + def test_proto_conversion_json_scalar_string(self): + """JSON scalar values like numbers-as-strings should validate.""" + protos = python_values_to_proto_values(["42"], ValueType.JSON) + converted = feast_value_type_to_python_type(protos[0]) + assert converted == 42 + + def test_proto_conversion_json_null_string(self): + """The JSON string 'null' is valid JSON.""" + protos = python_values_to_proto_values(["null"], ValueType.JSON) + converted = feast_value_type_to_python_type(protos[0]) + assert converted is None + + def test_proto_conversion_json_empty_string_raises(self): + """An empty string is not valid JSON.""" + import pytest + + with pytest.raises(ValueError, match="Invalid JSON string for JSON type"): + python_values_to_proto_values([""], ValueType.JSON) + + def test_local_validation_node_valid_json(self): + """LocalValidationNode should accept valid JSON strings.""" + from feast.infra.compute_engines.local.nodes import LocalValidationNode + + table = pyarrow.table( + {"config": ['{"a": 1}', '{"b": 2}', "null"]}, + schema=pyarrow.schema([pyarrow.field("config", pyarrow.string())]), + ) + + node = LocalValidationNode( + name="test_validate", + validation_config={ + "columns": {"config": pyarrow.large_string()}, + "json_columns": {"config"}, + }, + backend=None, + ) + # Should not raise + node._validate_schema(table) + + def test_local_validation_node_invalid_json(self): + """LocalValidationNode should reject invalid JSON strings.""" + import pytest + + from feast.infra.compute_engines.local.nodes import LocalValidationNode + + table = pyarrow.table( + {"config": ['{"valid": true}', "not-json-at-all", '{"ok": 1}']}, + schema=pyarrow.schema([pyarrow.field("config", pyarrow.string())]), + ) + + node = LocalValidationNode( + name="test_validate", + validation_config={ + "columns": {"config": pyarrow.large_string()}, + "json_columns": {"config"}, + }, + backend=None, + ) + with pytest.raises(ValueError, match="invalid JSON value"): + node._validate_schema(table) + + def test_local_validation_node_skips_nulls(self): + """LocalValidationNode should skip null values in JSON columns.""" + from feast.infra.compute_engines.local.nodes import LocalValidationNode + + table = pyarrow.table( + {"config": ['{"a": 1}', None, '{"b": 2}']}, + schema=pyarrow.schema([pyarrow.field("config", pyarrow.string())]), + ) + + node = LocalValidationNode( + name="test_validate", + validation_config={ + "columns": {"config": pyarrow.large_string()}, + "json_columns": {"config"}, + }, + backend=None, + ) + # Should not raise + node._validate_schema(table) + + def test_local_validation_node_no_json_columns(self): + """LocalValidationNode should skip JSON validation if no json_columns.""" + from feast.infra.compute_engines.local.nodes import LocalValidationNode + + table = pyarrow.table( + {"data": ["not-json"]}, + schema=pyarrow.schema([pyarrow.field("data", pyarrow.string())]), + ) + + node = LocalValidationNode( + name="test_validate", + validation_config={ + "columns": {"data": pyarrow.string()}, + }, + backend=None, + ) + # Should not raise — no json_columns configured + node._validate_schema(table) + + def test_local_validation_node_error_message_shows_row_and_detail(self): + """Error message should include the row number and parse error.""" + import pytest + + from feast.infra.compute_engines.local.nodes import LocalValidationNode + + table = pyarrow.table( + {"config": ['{"ok": 1}', '{"ok": 2}', "{bad}"]}, + schema=pyarrow.schema([pyarrow.field("config", pyarrow.string())]), + ) + + node = LocalValidationNode( + name="test_validate", + validation_config={ + "columns": {"config": pyarrow.large_string()}, + "json_columns": {"config"}, + }, + backend=None, + ) + with pytest.raises(ValueError, match="row 2"): + node._validate_schema(table) + + +class TestSparkNativeTypeValidation: + """Test Spark-native type mapping and compatibility checking.""" + + def test_feast_string_to_spark_string(self): + from pyspark.sql.types import StringType + + from feast.infra.compute_engines.spark.nodes import from_feast_to_spark_type + from feast.types import String + + assert from_feast_to_spark_type(String) == StringType() + + def test_feast_int32_to_spark_integer(self): + from pyspark.sql.types import IntegerType + + from feast.infra.compute_engines.spark.nodes import from_feast_to_spark_type + from feast.types import Int32 + + assert from_feast_to_spark_type(Int32) == IntegerType() + + def test_feast_int64_to_spark_long(self): + from pyspark.sql.types import LongType + + from feast.infra.compute_engines.spark.nodes import from_feast_to_spark_type + from feast.types import Int64 + + assert from_feast_to_spark_type(Int64) == LongType() + + def test_feast_float32_to_spark_float(self): + from pyspark.sql.types import FloatType + + from feast.infra.compute_engines.spark.nodes import from_feast_to_spark_type + from feast.types import Float32 + + assert from_feast_to_spark_type(Float32) == FloatType() + + def test_feast_float64_to_spark_double(self): + from pyspark.sql.types import DoubleType + + from feast.infra.compute_engines.spark.nodes import from_feast_to_spark_type + from feast.types import Float64 + + assert from_feast_to_spark_type(Float64) == DoubleType() + + def test_feast_bool_to_spark_boolean(self): + from pyspark.sql.types import BooleanType + + from feast.infra.compute_engines.spark.nodes import from_feast_to_spark_type + from feast.types import Bool + + assert from_feast_to_spark_type(Bool) == BooleanType() + + def test_feast_bytes_to_spark_binary(self): + from pyspark.sql.types import BinaryType + + from feast.infra.compute_engines.spark.nodes import from_feast_to_spark_type + from feast.types import Bytes + + assert from_feast_to_spark_type(Bytes) == BinaryType() + + def test_feast_timestamp_to_spark_timestamp(self): + from pyspark.sql.types import TimestampType + + from feast.infra.compute_engines.spark.nodes import from_feast_to_spark_type + from feast.types import UnixTimestamp + + assert from_feast_to_spark_type(UnixTimestamp) == TimestampType() + + def test_feast_map_to_spark_map(self): + from pyspark.sql.types import MapType, StringType + + from feast.infra.compute_engines.spark.nodes import from_feast_to_spark_type + from feast.types import Map + + assert from_feast_to_spark_type(Map) == MapType(StringType(), StringType()) + + def test_feast_json_to_spark_string(self): + from pyspark.sql.types import StringType + + from feast.infra.compute_engines.spark.nodes import from_feast_to_spark_type + from feast.types import Json + + assert from_feast_to_spark_type(Json) == StringType() + + def test_feast_array_int_to_spark_array(self): + from pyspark.sql.types import ArrayType, IntegerType + + from feast.infra.compute_engines.spark.nodes import from_feast_to_spark_type + from feast.types import Array, Int32 + + assert from_feast_to_spark_type(Array(Int32)) == ArrayType(IntegerType()) + + def test_feast_array_map_to_spark_array(self): + from pyspark.sql.types import ArrayType, MapType, StringType + + from feast.infra.compute_engines.spark.nodes import from_feast_to_spark_type + from feast.types import Array, Map + + assert from_feast_to_spark_type(Array(Map)) == ArrayType( + MapType(StringType(), StringType()) + ) + + def test_feast_struct_to_spark_struct(self): + from pyspark.sql.types import IntegerType, StringType, StructField, StructType + + from feast.infra.compute_engines.spark.nodes import from_feast_to_spark_type + from feast.types import Int32, String, Struct + + struct = Struct({"name": String, "age": Int32}) + expected = StructType( + [ + StructField("name", StringType(), True), + StructField("age", IntegerType(), True), + ] + ) + assert from_feast_to_spark_type(struct) == expected + + def test_feast_array_struct_to_spark_array_struct(self): + from pyspark.sql.types import ( + ArrayType, + IntegerType, + StringType, + StructField, + StructType, + ) + + from feast.infra.compute_engines.spark.nodes import from_feast_to_spark_type + from feast.types import Array, Int32, String, Struct + + struct = Struct({"name": String, "age": Int32}) + expected = ArrayType( + StructType( + [ + StructField("name", StringType(), True), + StructField("age", IntegerType(), True), + ] + ) + ) + assert from_feast_to_spark_type(Array(struct)) == expected + + def test_unsupported_type_returns_none(self): + from feast.infra.compute_engines.spark.nodes import from_feast_to_spark_type + from feast.types import Invalid + + assert from_feast_to_spark_type(Invalid) is None + + # Compatibility tests + + def test_exact_match_compatible(self): + from pyspark.sql.types import StringType + + from feast.infra.compute_engines.spark.nodes import _spark_types_compatible + + assert _spark_types_compatible(StringType(), StringType()) + + def test_map_struct_compatible(self): + from pyspark.sql.types import MapType, StringType, StructType + + from feast.infra.compute_engines.spark.nodes import _spark_types_compatible + + assert _spark_types_compatible( + MapType(StringType(), StringType()), StructType([]) + ) + + def test_struct_map_compatible(self): + from pyspark.sql.types import MapType, StringType, StructType + + from feast.infra.compute_engines.spark.nodes import _spark_types_compatible + + assert _spark_types_compatible( + StructType([]), MapType(StringType(), StringType()) + ) + + def test_integer_long_widening_compatible(self): + from pyspark.sql.types import IntegerType, LongType + + from feast.infra.compute_engines.spark.nodes import _spark_types_compatible + + assert _spark_types_compatible(IntegerType(), LongType()) + assert _spark_types_compatible(LongType(), IntegerType()) + + def test_float_double_widening_compatible(self): + from pyspark.sql.types import DoubleType, FloatType + + from feast.infra.compute_engines.spark.nodes import _spark_types_compatible + + assert _spark_types_compatible(FloatType(), DoubleType()) + assert _spark_types_compatible(DoubleType(), FloatType()) + + def test_string_vs_integer_incompatible(self): + from pyspark.sql.types import IntegerType, StringType + + from feast.infra.compute_engines.spark.nodes import _spark_types_compatible + + assert not _spark_types_compatible(StringType(), IntegerType()) + + def test_bool_vs_double_incompatible(self): + from pyspark.sql.types import BooleanType, DoubleType + + from feast.infra.compute_engines.spark.nodes import _spark_types_compatible + + assert not _spark_types_compatible(BooleanType(), DoubleType()) + + def test_array_element_compatibility(self): + from pyspark.sql.types import ArrayType, IntegerType, LongType + + from feast.infra.compute_engines.spark.nodes import _spark_types_compatible + + assert _spark_types_compatible(ArrayType(IntegerType()), ArrayType(LongType())) + + def test_array_element_incompatibility(self): + from pyspark.sql.types import ArrayType, IntegerType, StringType + + from feast.infra.compute_engines.spark.nodes import _spark_types_compatible + + assert not _spark_types_compatible( + ArrayType(StringType()), ArrayType(IntegerType()) + ) + + +class TestUuidTypes: + """Test cases for UUID and TIME_UUID value types.""" + + def test_uuid_string_roundtrip(self): + """UUID string -> proto -> uuid.UUID object roundtrip.""" + test_uuid = uuid.uuid4() + protos = python_values_to_proto_values([str(test_uuid)], ValueType.UUID) + assert protos[0].uuid_val == str(test_uuid) + + result = feast_value_type_to_python_type(protos[0]) + assert isinstance(result, uuid.UUID) + assert result == test_uuid + + def test_uuid_object_serialization(self): + """uuid.UUID object -> proto serialization (str conversion automatic).""" + test_uuid = uuid.uuid4() + protos = python_values_to_proto_values([test_uuid], ValueType.UUID) + assert protos[0].uuid_val == str(test_uuid) + + def test_time_uuid_roundtrip(self): + """TIME_UUID string -> proto -> uuid.UUID object roundtrip.""" + test_uuid = uuid.uuid1() + protos = python_values_to_proto_values([str(test_uuid)], ValueType.TIME_UUID) + assert protos[0].time_uuid_val == str(test_uuid) + + result = feast_value_type_to_python_type(protos[0]) + assert isinstance(result, uuid.UUID) + assert result == test_uuid + + def test_uuid_without_feature_type_returns_uuid(self): + """With dedicated uuid_val proto field, UUID is identified without feature_type hint.""" + test_uuid = uuid.uuid4() + protos = python_values_to_proto_values([str(test_uuid)], ValueType.UUID) + + # No feature_type hint needed — uuid_val field identifies the type + result = feast_value_type_to_python_type(protos[0]) + assert isinstance(result, uuid.UUID) + assert result == test_uuid + + def test_uuid_backward_compat_string_val(self): + """UUIDs stored as string_val (old format) still work with feature_type hint.""" + from feast.protos.feast.types.Value_pb2 import Value as ProtoValue + + test_uuid = uuid.uuid4() + # Simulate old-format proto with string_val + proto = ProtoValue(string_val=str(test_uuid)) + + # Without feature_type, returns plain string + result = feast_value_type_to_python_type(proto) + assert isinstance(result, str) + + # With feature_type hint, returns uuid.UUID + result = feast_value_type_to_python_type(proto, ValueType.UUID) + assert isinstance(result, uuid.UUID) + assert result == test_uuid + + def test_uuid_list_roundtrip(self): + """UUID list -> proto -> list of uuid.UUID objects roundtrip.""" + test_uuids = [uuid.uuid4(), uuid.uuid4()] + test_uuid_strs = [str(u) for u in test_uuids] + protos = python_values_to_proto_values([test_uuid_strs], ValueType.UUID_LIST) + result = feast_value_type_to_python_type(protos[0]) + assert all(isinstance(r, uuid.UUID) for r in result) + assert result == test_uuids + + def test_uuid_object_list_roundtrip(self): + """uuid.UUID objects in list -> proto -> list of uuid.UUID roundtrip.""" + test_uuids = [uuid.uuid4(), uuid.uuid4(), uuid.uuid4()] + protos = python_values_to_proto_values([test_uuids], ValueType.UUID_LIST) + result = feast_value_type_to_python_type(protos[0]) + assert all(isinstance(r, uuid.UUID) for r in result) + assert result == test_uuids + + def test_time_uuid_object_list_roundtrip(self): + """uuid.UUID objects in TIME_UUID list -> proto -> roundtrip.""" + test_uuids = [uuid.uuid1(), uuid.uuid1()] + protos = python_values_to_proto_values([test_uuids], ValueType.TIME_UUID_LIST) + result = feast_value_type_to_python_type(protos[0]) + assert all(isinstance(r, uuid.UUID) for r in result) + assert result == test_uuids + + def test_uuid_set_roundtrip(self): + """UUID set -> proto -> set of uuid.UUID objects roundtrip.""" + test_uuids = {uuid.uuid4(), uuid.uuid4(), uuid.uuid4()} + protos = python_values_to_proto_values([test_uuids], ValueType.UUID_SET) + + result = feast_value_type_to_python_type(protos[0]) + assert isinstance(result, set) + assert all(isinstance(r, uuid.UUID) for r in result) + assert result == test_uuids + + def test_time_uuid_set_roundtrip(self): + """TIME_UUID set -> proto -> set of uuid.UUID objects roundtrip.""" + test_uuids = {uuid.uuid1(), uuid.uuid1()} + protos = python_values_to_proto_values([test_uuids], ValueType.TIME_UUID_SET) + + result = feast_value_type_to_python_type(protos[0]) + assert isinstance(result, set) + assert all(isinstance(r, uuid.UUID) for r in result) + assert result == test_uuids + + def test_uuid_object_set_roundtrip(self): + """uuid.UUID objects in set -> proto -> set of uuid.UUID roundtrip.""" + test_uuids = {uuid.uuid4(), uuid.uuid4()} + protos = python_values_to_proto_values([test_uuids], ValueType.UUID_SET) + + result = feast_value_type_to_python_type(protos[0]) + assert isinstance(result, set) + assert result == test_uuids + + def test_uuid_set_backward_compat_string_set_val(self): + """UUIDs stored as string_set_val (old format) still work with feature_type hint.""" + from feast.protos.feast.types.Value_pb2 import StringSet + from feast.protos.feast.types.Value_pb2 import Value as ProtoValue + + test_uuids = {uuid.uuid4(), uuid.uuid4()} + # Simulate old-format proto with string_set_val + proto = ProtoValue(string_set_val=StringSet(val=[str(u) for u in test_uuids])) + + # Without feature_type, returns set of strings + result = feast_value_type_to_python_type(proto) + assert isinstance(result, set) + assert all(isinstance(r, str) for r in result) + + # With feature_type hint, returns set of uuid.UUID + result = feast_value_type_to_python_type(proto, ValueType.UUID_SET) + assert isinstance(result, set) + assert all(isinstance(r, uuid.UUID) for r in result) + assert result == test_uuids + + def test_pg_uuid_type_mapping(self): + """PostgreSQL uuid type maps to ValueType.UUID.""" + assert pg_type_to_feast_value_type("uuid") == ValueType.UUID + assert pg_type_to_feast_value_type("uuid[]") == ValueType.UUID_LIST + + +class TestDecimalTypes: + """Test cases for DECIMAL, DECIMAL_LIST, and DECIMAL_SET value types.""" + + def test_decimal_string_roundtrip(self): + """Decimal string -> proto -> decimal.Decimal object roundtrip.""" + import decimal + + val = decimal.Decimal("3.14159265358979323846") + protos = python_values_to_proto_values([str(val)], ValueType.DECIMAL) + assert protos[0].decimal_val == str(val) + + result = feast_value_type_to_python_type(protos[0]) + assert isinstance(result, decimal.Decimal) + assert result == val + + def test_decimal_object_serialization(self): + """decimal.Decimal object -> proto serialization (str conversion automatic).""" + import decimal + + val = decimal.Decimal("99.99") + protos = python_values_to_proto_values([val], ValueType.DECIMAL) + assert protos[0].decimal_val == "99.99" + + def test_decimal_preserves_precision(self): + """High-precision decimal values survive the proto round-trip without loss.""" + import decimal + + high_prec = decimal.Decimal("1.23456789012345678901234567890") + protos = python_values_to_proto_values([high_prec], ValueType.DECIMAL) + result = feast_value_type_to_python_type(protos[0]) + assert result == high_prec + + def test_decimal_negative_value(self): + """Negative decimal values round-trip correctly.""" + import decimal + + val = decimal.Decimal("-9876.543210") + protos = python_values_to_proto_values([val], ValueType.DECIMAL) + result = feast_value_type_to_python_type(protos[0]) + assert result == val + + def test_decimal_zero(self): + """Zero decimal value round-trips correctly.""" + import decimal + + val = decimal.Decimal("0") + protos = python_values_to_proto_values([val], ValueType.DECIMAL) + result = feast_value_type_to_python_type(protos[0]) + assert result == val + + def test_decimal_list_roundtrip(self): + """DECIMAL_LIST string list -> proto -> list of decimal.Decimal roundtrip.""" + import decimal + + vals = [decimal.Decimal("1.1"), decimal.Decimal("2.2"), decimal.Decimal("3.3")] + val_strs = [str(v) for v in vals] + protos = python_values_to_proto_values([val_strs], ValueType.DECIMAL_LIST) + result = feast_value_type_to_python_type(protos[0]) + assert all(isinstance(r, decimal.Decimal) for r in result) + assert result == vals + + def test_decimal_object_list_roundtrip(self): + """List of decimal.Decimal objects -> proto -> list of decimal.Decimal roundtrip.""" + import decimal + + vals = [ + decimal.Decimal("10.5"), + decimal.Decimal("20.75"), + decimal.Decimal("30.125"), + ] + protos = python_values_to_proto_values([vals], ValueType.DECIMAL_LIST) + result = feast_value_type_to_python_type(protos[0]) + assert all(isinstance(r, decimal.Decimal) for r in result) + assert result == vals + + def test_decimal_set_roundtrip(self): + """DECIMAL_SET -> proto -> set of decimal.Decimal roundtrip.""" + import decimal + + vals = {decimal.Decimal("1.1"), decimal.Decimal("2.2"), decimal.Decimal("3.3")} + protos = python_values_to_proto_values([vals], ValueType.DECIMAL_SET) + result = feast_value_type_to_python_type(protos[0]) + assert isinstance(result, set) + assert all(isinstance(r, decimal.Decimal) for r in result) + assert result == vals + + def test_decimal_set_deduplication(self): + """Duplicate decimal values in a set are deduplicated.""" + import decimal + + vals = {decimal.Decimal("5.0"), decimal.Decimal("5.0"), decimal.Decimal("6.0")} + protos = python_values_to_proto_values([vals], ValueType.DECIMAL_SET) + result = feast_value_type_to_python_type(protos[0]) + assert isinstance(result, set) + assert len(result) == 2 + + def test_decimal_type_inference(self): + """python_type_to_feast_value_type infers DECIMAL from decimal.Decimal values.""" + import decimal + + from feast.type_map import python_type_to_feast_value_type + + assert ( + python_type_to_feast_value_type("price", decimal.Decimal("1.5")) + == ValueType.DECIMAL + ) + + def test_decimal_value_type_string_conversion(self): + """_convert_value_type_str_to_value_type handles DECIMAL strings.""" + from feast.type_map import _convert_value_type_str_to_value_type + + assert _convert_value_type_str_to_value_type("DECIMAL") == ValueType.DECIMAL + assert ( + _convert_value_type_str_to_value_type("DECIMAL_LIST") + == ValueType.DECIMAL_LIST + ) + assert ( + _convert_value_type_str_to_value_type("DECIMAL_SET") + == ValueType.DECIMAL_SET + ) + + def test_decimal_proto_field_name_mapping(self): + """PROTO_VALUE_TO_VALUE_TYPE_MAP and VALUE_TYPE_TO_PROTO_VALUE_MAP include DECIMAL.""" + from feast.type_map import ( + PROTO_VALUE_TO_VALUE_TYPE_MAP, + VALUE_TYPE_TO_PROTO_VALUE_MAP, + ) + + assert PROTO_VALUE_TO_VALUE_TYPE_MAP["decimal_val"] == ValueType.DECIMAL + assert ( + PROTO_VALUE_TO_VALUE_TYPE_MAP["decimal_list_val"] == ValueType.DECIMAL_LIST + ) + assert PROTO_VALUE_TO_VALUE_TYPE_MAP["decimal_set_val"] == ValueType.DECIMAL_SET + assert VALUE_TYPE_TO_PROTO_VALUE_MAP[ValueType.DECIMAL] == "decimal_val" + assert ( + VALUE_TYPE_TO_PROTO_VALUE_MAP[ValueType.DECIMAL_LIST] == "decimal_list_val" + ) + assert VALUE_TYPE_TO_PROTO_VALUE_MAP[ValueType.DECIMAL_SET] == "decimal_set_val" + + def test_decimal_pandas_type(self): + """feast_value_type_to_pandas_type returns 'object' for DECIMAL.""" + from feast.type_map import feast_value_type_to_pandas_type + + assert feast_value_type_to_pandas_type(ValueType.DECIMAL) == "object" + + def test_decimal_pyarrow_type(self): + """feast_value_type_to_pa returns pyarrow.string() for DECIMAL scalar/list/set.""" + import pyarrow + + from feast.type_map import feast_value_type_to_pa + + assert feast_value_type_to_pa(ValueType.DECIMAL) == pyarrow.string() + assert feast_value_type_to_pa(ValueType.DECIMAL_LIST) == pyarrow.list_( + pyarrow.string() + ) + assert feast_value_type_to_pa(ValueType.DECIMAL_SET) == pyarrow.list_( + pyarrow.string() + ) + + def test_decimal_snowflake_udf(self): + """_convert_value_name_to_snowflake_udf maps DECIMAL types to varchar UDFs.""" + from feast.type_map import _convert_value_name_to_snowflake_udf + + project = "myproject" + assert _convert_value_name_to_snowflake_udf("DECIMAL", project) == ( + f"FEAST_{project.upper()}_SNOWFLAKE_VARCHAR_TO_STRING_PROTO" + ) + assert _convert_value_name_to_snowflake_udf("DECIMAL_LIST", project) == ( + f"FEAST_{project.upper()}_SNOWFLAKE_ARRAY_VARCHAR_TO_LIST_STRING_PROTO" + ) + assert _convert_value_name_to_snowflake_udf("DECIMAL_SET", project) == ( + f"FEAST_{project.upper()}_SNOWFLAKE_ARRAY_VARCHAR_TO_LIST_STRING_PROTO" + ) + + +class TestNestedCollectionTypes: + """Tests for nested collection type proto conversion (VALUE_LIST, VALUE_SET).""" + + def test_value_list_proto_roundtrip(self): + """Test python_values_to_proto_values and feast_value_type_to_python_type for VALUE_LIST.""" + values = [[[1, 2, 3], [4, 5]]] + protos = python_values_to_proto_values(values, ValueType.VALUE_LIST) + assert len(protos) == 1 + assert protos[0].WhichOneof("val") == "list_val" + result = feast_value_type_to_python_type(protos[0]) + assert isinstance(result, list) + assert len(result) == 2 + + def test_value_set_proto_roundtrip(self): + """Test VALUE_SET proto conversion.""" + values = [[["a", "b"], ["c"]]] + protos = python_values_to_proto_values(values, ValueType.VALUE_SET) + assert len(protos) == 1 + assert protos[0].WhichOneof("val") == "set_val" + result = feast_value_type_to_python_type(protos[0]) + assert isinstance(result, list) + assert len(result) == 2 + + def test_nested_collection_null_handling(self): + """Test that None values are handled correctly.""" + values = [None] + protos = python_values_to_proto_values(values, ValueType.VALUE_LIST) + assert len(protos) == 1 + assert protos[0].WhichOneof("val") is None + + def test_convert_value_type_str_nested(self): + """Test _convert_value_type_str_to_value_type for nested types.""" + assert ( + _convert_value_type_str_to_value_type("VALUE_LIST") == ValueType.VALUE_LIST + ) + assert _convert_value_type_str_to_value_type("VALUE_SET") == ValueType.VALUE_SET + + def test_nested_collection_empty_inner_list(self): + """Test that empty inner collections are handled gracefully.""" + values = [[[], [1, 2]]] + protos = python_values_to_proto_values(values, ValueType.VALUE_LIST) + result = feast_value_type_to_python_type(protos[0]) + assert isinstance(result, list) + assert len(result) == 2 + # Empty inner list should round-trip as None (empty ProtoValue) + assert result[0] is None + assert result[1] == [1, 2] + + def test_nested_collection_inner_none(self): + """Test that None inner elements are handled.""" + values = [[[1, 2], None, [3]]] + protos = python_values_to_proto_values(values, ValueType.VALUE_LIST) + result = feast_value_type_to_python_type(protos[0]) + assert len(result) == 3 + assert result[0] == [1, 2] + assert result[1] is None + assert result[2] == [3] + + def test_value_list_no_dedup(self): + """Test that VALUE_LIST does NOT deduplicate (Array semantics).""" + values = [[[1, 1, 2], [3, 3]]] + protos = python_values_to_proto_values(values, ValueType.VALUE_LIST) + result = feast_value_type_to_python_type(protos[0]) + assert result[0] == [1, 1, 2] + assert result[1] == [3, 3] + + def test_value_list_proto_roundtrip_values(self): + """Test that VALUE_LIST roundtrip preserves actual inner values.""" + values = [[[1, 2, 3], [4, 5]]] + protos = python_values_to_proto_values(values, ValueType.VALUE_LIST) + result = feast_value_type_to_python_type(protos[0]) + assert result[0] == [1, 2, 3] + assert result[1] == [4, 5] + + def test_value_set_proto_roundtrip_values(self): + """Test that VALUE_SET roundtrip preserves actual inner values.""" + values = [[["a", "b"], ["c"]]] + protos = python_values_to_proto_values(values, ValueType.VALUE_SET) + result = feast_value_type_to_python_type(protos[0]) + assert result[0] == ["a", "b"] + assert result[1] == ["c"] + + def test_multi_value_batch_nested(self): + """Test multiple nested collection values in a single batch.""" + values = [[[1, 2], [3]], [[4], [5, 6]]] + protos = python_values_to_proto_values(values, ValueType.VALUE_LIST) + assert len(protos) == 2 + r0 = feast_value_type_to_python_type(protos[0]) + r1 = feast_value_type_to_python_type(protos[1]) + assert r0 == [[1, 2], [3]] + assert r1 == [[4], [5, 6]] + + def test_feast_value_type_to_pa_nested(self): + """Test feast_value_type_to_pa for nested collection types.""" + for vt in ( + ValueType.VALUE_LIST, + ValueType.VALUE_SET, + ): + pa_type = feast_value_type_to_pa(vt) + assert pa_type == pyarrow.list_(pyarrow.list_(pyarrow.string())) + + def test_pa_to_feast_value_type_nested(self): + """Test pa_to_feast_value_type recognizes nested list PyArrow types.""" + assert ( + pa_to_feast_value_type("list>") + == ValueType.VALUE_LIST + ) + assert ( + pa_to_feast_value_type("list>") + == ValueType.VALUE_LIST + ) + assert ( + pa_to_feast_value_type("list>") + == ValueType.VALUE_LIST + ) diff --git a/sdk/python/tests/unit/test_types.py b/sdk/python/tests/unit/test_types.py index 438735d213a..aa89a1b4c6c 100644 --- a/sdk/python/tests/unit/test_types.py +++ b/sdk/python/tests/unit/test_types.py @@ -1,6 +1,23 @@ +import pyarrow import pytest -from feast.types import Array, Float32, Set, String, from_value_type +from feast.field import Field +from feast.types import ( + Array, + Bool, + Decimal, + Float32, + Float64, + Int32, + Int64, + Set, + String, + TimeUuid, + Uuid, + from_feast_to_pyarrow_type, + from_feast_type, + from_value_type, +) from feast.value_type import ValueType @@ -23,9 +40,6 @@ def test_array_feast_type(): with pytest.raises(ValueError): _ = Array(Array) - with pytest.raises(ValueError): - _ = Array(Array(String)) - def test_set_feast_type(): set_string = Set(String) @@ -39,8 +53,201 @@ def test_set_feast_type(): with pytest.raises(ValueError): _ = Set(Set) - with pytest.raises(ValueError): - _ = Set(Set(String)) + +def test_nested_array_array(): + """Array(Array(T)) should produce VALUE_LIST.""" + t = Array(Array(String)) + assert t.to_value_type() == ValueType.VALUE_LIST + assert from_feast_type(t) == ValueType.VALUE_LIST + + t2 = Array(Array(Int32)) + assert t2.to_value_type() == ValueType.VALUE_LIST + + +def test_nested_array_set(): + """Array(Set(T)) should produce VALUE_LIST.""" + t = Array(Set(String)) + assert t.to_value_type() == ValueType.VALUE_LIST + assert from_feast_type(t) == ValueType.VALUE_LIST + + +def test_nested_set_array(): + """Set(Array(T)) should produce VALUE_SET.""" + t = Set(Array(String)) + assert t.to_value_type() == ValueType.VALUE_SET + assert from_feast_type(t) == ValueType.VALUE_SET + + +def test_nested_set_set(): + """Set(Set(T)) should produce VALUE_SET.""" + t = Set(Set(String)) + assert t.to_value_type() == ValueType.VALUE_SET + assert from_feast_type(t) == ValueType.VALUE_SET + + +def test_nested_unbounded_depth(): + """Nesting depth should be unbounded.""" + # 3-level + t3 = Array(Array(Array(String))) + assert t3.to_value_type() == ValueType.VALUE_LIST + + t3_mixed = Array(Set(Array(String))) + assert t3_mixed.to_value_type() == ValueType.VALUE_LIST + + t3_set = Set(Array(Array(String))) + assert t3_set.to_value_type() == ValueType.VALUE_SET + + t3_set2 = Set(Set(Set(String))) + assert t3_set2.to_value_type() == ValueType.VALUE_SET + + # 4-level + t4 = Array(Array(Array(Array(Int32)))) + assert t4.to_value_type() == ValueType.VALUE_LIST + + +def test_nested_from_value_type_roundtrip(): + """from_value_type should return a placeholder for nested types.""" + for vt in ( + ValueType.VALUE_LIST, + ValueType.VALUE_SET, + ): + ft = from_value_type(vt) + assert ft.to_value_type() == vt + + +def test_nested_pyarrow_conversion(): + """Nested collection types should convert to pyarrow list(list(...)).""" + # Array(Array(String)) -> list(list(string)) + pa_type = from_feast_to_pyarrow_type(Array(Array(String))) + assert pa_type == pyarrow.list_(pyarrow.list_(pyarrow.string())) + + # Array(Set(Int64)) -> list(list(int64)) + pa_type = from_feast_to_pyarrow_type(Array(Set(Int64))) + assert pa_type == pyarrow.list_(pyarrow.list_(pyarrow.int64())) + + # Set(Array(Float64)) -> list(list(float64)) + pa_type = from_feast_to_pyarrow_type(Set(Array(Float64))) + assert pa_type == pyarrow.list_(pyarrow.list_(pyarrow.float64())) + + # Set(Set(Bool)) -> list(list(bool)) + pa_type = from_feast_to_pyarrow_type(Set(Set(Bool))) + assert pa_type == pyarrow.list_(pyarrow.list_(pyarrow.bool_())) + + # 3-level: Array(Array(Array(Int32))) -> list(list(list(int32))) + pa_type = from_feast_to_pyarrow_type(Array(Array(Array(Int32)))) + assert pa_type == pyarrow.list_(pyarrow.list_(pyarrow.list_(pyarrow.int32()))) + + +def test_nested_field_roundtrip(): + """Field with nested collection type should survive to_proto -> from_proto.""" + test_cases = [ + ("aa", Array(Array(String))), + ("as_field", Array(Set(Int32))), + ("sa", Set(Array(Float64))), + ("ss", Set(Set(Bool))), + # 3-level nesting + ("aaa", Array(Array(Array(Int32)))), + ("asa", Array(Set(Array(String)))), + # 4-level nesting + ("aaaa", Array(Array(Array(Array(Float64))))), + ] + for name, dtype in test_cases: + field = Field(name=name, dtype=dtype, tags={"user_tag": "value"}) + proto = field.to_proto() + restored = Field.from_proto(proto) + assert restored.name == name, f"Name mismatch for {dtype}" + assert restored.dtype.to_value_type() == dtype.to_value_type(), ( + f"dtype mismatch for {name}: {restored.dtype} vs {dtype}" + ) + # Verify inner type is preserved (not just ValueType equality) + assert str(restored.dtype) == str(dtype), ( + f"Inner type lost for {name}: got {restored.dtype}, expected {dtype}" + ) + assert restored.tags == {"user_tag": "value"}, ( + f"Tags should not contain internal tags for {name}" + ) + + +def test_uuid_feast_type(): + assert Uuid.to_value_type() == ValueType.UUID + assert from_value_type(ValueType.UUID) == Uuid + assert TimeUuid.to_value_type() == ValueType.TIME_UUID + assert from_value_type(ValueType.TIME_UUID) == TimeUuid + + +def test_uuid_array_feast_type(): + array_uuid = Array(Uuid) + assert array_uuid.to_value_type() == ValueType.UUID_LIST + assert from_value_type(array_uuid.to_value_type()) == array_uuid + + array_time_uuid = Array(TimeUuid) + assert array_time_uuid.to_value_type() == ValueType.TIME_UUID_LIST + assert from_value_type(array_time_uuid.to_value_type()) == array_time_uuid + + +def test_uuid_set_feast_type(): + set_uuid = Set(Uuid) + assert set_uuid.to_value_type() == ValueType.UUID_SET + assert from_value_type(set_uuid.to_value_type()) == set_uuid + + set_time_uuid = Set(TimeUuid) + assert set_time_uuid.to_value_type() == ValueType.TIME_UUID_SET + assert from_value_type(set_time_uuid.to_value_type()) == set_time_uuid + + +def test_decimal_feast_type(): + assert Decimal.to_value_type() == ValueType.DECIMAL + assert from_value_type(ValueType.DECIMAL) == Decimal + + +def test_decimal_array_feast_type(): + array_decimal = Array(Decimal) + assert array_decimal.to_value_type() == ValueType.DECIMAL_LIST + assert from_value_type(array_decimal.to_value_type()) == array_decimal + + +def test_decimal_set_feast_type(): + set_decimal = Set(Decimal) + assert set_decimal.to_value_type() == ValueType.DECIMAL_SET + assert from_value_type(set_decimal.to_value_type()) == set_decimal + + +def test_feast_type_str_roundtrip(): + """_feast_type_to_str and _str_to_feast_type should roundtrip for nested types.""" + from feast.field import _feast_type_to_str, _str_to_feast_type + + test_cases = [ + Array(Array(String)), + Array(Array(Int32)), + Array(Array(Float64)), + Array(Set(Int64)), + Array(Set(Bool)), + Set(Array(String)), + Set(Array(Float32)), + Set(Set(Int32)), + Set(Set(Float64)), + # 3+ level nesting + Array(Array(Array(String))), + Array(Set(Array(Int32))), + Set(Set(Set(Float64))), + ] + for dtype in test_cases: + s = _feast_type_to_str(dtype) + restored = _str_to_feast_type(s) + assert str(restored) == str(dtype), ( + f"Roundtrip failed: {dtype} -> '{s}' -> {restored}" + ) + + +def test_str_to_feast_type_invalid(): + """_str_to_feast_type should raise ValueError on unrecognized type names.""" + from feast.field import _str_to_feast_type + + with pytest.raises(ValueError, match="Unknown FeastType"): + _str_to_feast_type("INVALID_TYPE") + + with pytest.raises(ValueError, match="Unknown FeastType"): + _str_to_feast_type("Strig") def test_all_value_types(): diff --git a/sdk/python/tests/unit/test_utils.py b/sdk/python/tests/unit/test_utils.py new file mode 100644 index 00000000000..7eebf46461a --- /dev/null +++ b/sdk/python/tests/unit/test_utils.py @@ -0,0 +1,268 @@ +""" +Tests for feast.utils module. + +These unit tests cover the _populate_response_from_feature_data function +which converts raw online_read rows into protobuf FeatureVectors and +populates the GetOnlineFeaturesResponse. +""" + +from datetime import datetime, timezone +from unittest.mock import MagicMock + +from feast.protos.feast.serving.ServingService_pb2 import ( + FieldStatus, + GetOnlineFeaturesResponse, +) +from feast.protos.feast.types.Value_pb2 import Value as ValueProto +from feast.utils import _populate_response_from_feature_data + + +def _make_table(name="test_fv"): + """Create a minimal mock FeatureView for testing.""" + table = MagicMock() + table.projection.name_to_use.return_value = name + table.projection.name_alias = None + table.projection.name = name + return table + + +class TestPopulateResponseFromFeatureData: + """Tests for _populate_response_from_feature_data function.""" + + def test_basic_single_feature(self): + """Test basic conversion with single feature and single entity.""" + timestamp = datetime(2024, 1, 1, 12, 0, 0, tzinfo=timezone.utc) + value = ValueProto(float_val=1.5) + + read_rows = [(timestamp, {"feature_1": value})] + indexes = ([0],) + response = GetOnlineFeaturesResponse(results=[]) + + _populate_response_from_feature_data( + requested_features=["feature_1"], + read_rows=read_rows, + indexes=indexes, + online_features_response=response, + full_feature_names=False, + table=_make_table(), + output_len=1, + ) + + assert len(response.results) == 1 + assert response.results[0].values[0] == value + assert response.results[0].statuses[0] == FieldStatus.PRESENT + assert response.results[0].event_timestamps[0].seconds == int( + timestamp.timestamp() + ) + assert list(response.metadata.feature_names.val) == ["feature_1"] + + def test_multiple_features_same_entity(self): + """Test multiple features from the same row.""" + timestamp = datetime(2024, 1, 1, 12, 0, 0, tzinfo=timezone.utc) + v1 = ValueProto(float_val=1.0) + v2 = ValueProto(float_val=2.0) + + read_rows = [(timestamp, {"feature_1": v1, "feature_2": v2})] + indexes = ([0],) + response = GetOnlineFeaturesResponse(results=[]) + + _populate_response_from_feature_data( + requested_features=["feature_1", "feature_2"], + read_rows=read_rows, + indexes=indexes, + online_features_response=response, + full_feature_names=False, + table=_make_table(), + output_len=1, + ) + + assert len(response.results) == 2 + assert response.results[0].values[0] == v1 + assert response.results[1].values[0] == v2 + ts1 = response.results[0].event_timestamps[0].seconds + ts2 = response.results[1].event_timestamps[0].seconds + assert ts1 == ts2 == int(timestamp.timestamp()) + + def test_multiple_entities_deduplication(self): + """Test that duplicate entity rows are correctly mapped via indexes.""" + ts = datetime(2024, 1, 1, 12, 0, 0, tzinfo=timezone.utc) + val = ValueProto(float_val=42.0) + + read_rows = [(ts, {"feature_1": val})] + indexes = ([0, 1, 2],) # One unique row maps to 3 output positions + response = GetOnlineFeaturesResponse(results=[]) + + _populate_response_from_feature_data( + requested_features=["feature_1"], + read_rows=read_rows, + indexes=indexes, + online_features_response=response, + full_feature_names=False, + table=_make_table(), + output_len=3, + ) + + assert len(response.results[0].values) == 3 + for i in range(3): + assert response.results[0].values[i] == val + assert response.results[0].statuses[i] == FieldStatus.PRESENT + + def test_null_timestamp_handling(self): + """Test that null timestamps produce empty Timestamp proto.""" + read_rows = [ + (None, {"feature_1": ValueProto(float_val=1.0)}), + ( + datetime(2024, 1, 1, tzinfo=timezone.utc), + {"feature_1": ValueProto(float_val=2.0)}, + ), + ] + indexes = ([0],), ([1],) + indexes = ([0], [1]) + response = GetOnlineFeaturesResponse(results=[]) + + _populate_response_from_feature_data( + requested_features=["feature_1"], + read_rows=read_rows, + indexes=indexes, + online_features_response=response, + full_feature_names=False, + table=_make_table(), + output_len=2, + ) + + ts_list = response.results[0].event_timestamps + assert ts_list[0].seconds == 0 # Null timestamp -> empty proto + assert ts_list[1].seconds != 0 # Valid timestamp + + def test_missing_feature_data(self): + """Test handling of missing feature data (None row).""" + ts = datetime(2024, 1, 1, 12, 0, 0, tzinfo=timezone.utc) + + read_rows = [ + (ts, {"feature_1": ValueProto(float_val=1.0)}), + (ts, None), + ] + indexes = ([0], [1]) + response = GetOnlineFeaturesResponse(results=[]) + + _populate_response_from_feature_data( + requested_features=["feature_1"], + read_rows=read_rows, + indexes=indexes, + online_features_response=response, + full_feature_names=False, + table=_make_table(), + output_len=2, + ) + + assert response.results[0].statuses[0] == FieldStatus.PRESENT + assert response.results[0].statuses[1] == FieldStatus.NOT_FOUND + + def test_feature_not_in_row(self): + """Test handling when requested feature is not in the row's data.""" + ts = datetime(2024, 1, 1, 12, 0, 0, tzinfo=timezone.utc) + + read_rows = [(ts, {"feature_1": ValueProto(float_val=1.0)})] + indexes = ([0],) + response = GetOnlineFeaturesResponse(results=[]) + + _populate_response_from_feature_data( + requested_features=["feature_1", "feature_2"], + read_rows=read_rows, + indexes=indexes, + online_features_response=response, + full_feature_names=False, + table=_make_table(), + output_len=1, + ) + + assert len(response.results) == 2 + assert response.results[0].statuses[0] == FieldStatus.PRESENT + assert response.results[1].statuses[0] == FieldStatus.NOT_FOUND + + def test_empty_inputs(self): + """Test handling of empty inputs.""" + response = GetOnlineFeaturesResponse(results=[]) + _populate_response_from_feature_data( + requested_features=["feature_1"], + read_rows=[], + indexes=(), + online_features_response=response, + full_feature_names=False, + table=_make_table(), + output_len=0, + ) + assert len(response.results) == 1 + assert len(response.results[0].values) == 0 + + response2 = GetOnlineFeaturesResponse(results=[]) + ts = datetime(2024, 1, 1, 12, 0, 0, tzinfo=timezone.utc) + _populate_response_from_feature_data( + requested_features=[], + read_rows=[(ts, {"f": ValueProto()})], + indexes=([0],), + online_features_response=response2, + full_feature_names=False, + table=_make_table(), + output_len=1, + ) + assert len(response2.results) == 0 + + def test_full_feature_names(self): + """Test that full_feature_names prefixes feature names with table name.""" + ts = datetime(2024, 1, 1, 12, 0, 0, tzinfo=timezone.utc) + read_rows = [(ts, {"feature_1": ValueProto(float_val=1.0)})] + response = GetOnlineFeaturesResponse(results=[]) + + _populate_response_from_feature_data( + requested_features=["feature_1"], + read_rows=read_rows, + indexes=([0],), + online_features_response=response, + full_feature_names=True, + table=_make_table("my_fv"), + output_len=1, + ) + + assert list(response.metadata.feature_names.val) == ["my_fv__feature_1"] + + def test_large_scale_correctness(self): + """Test correctness with large number of features and entities. + + This test verifies that the fused implementation produces correct + results at scale (50 features x 500 entities = 25,000 data points). + """ + timestamp = datetime(2024, 1, 1, 12, 0, 0, tzinfo=timezone.utc) + num_entities = 500 + num_features = 50 + + feature_data = { + f"feature_{i}": ValueProto(float_val=float(i)) for i in range(num_features) + } + read_rows = [(timestamp, feature_data.copy()) for _ in range(num_entities)] + requested_features = [f"feature_{i}" for i in range(num_features)] + indexes = tuple([i] for i in range(num_entities)) + response = GetOnlineFeaturesResponse(results=[]) + + _populate_response_from_feature_data( + requested_features=requested_features, + read_rows=read_rows, + indexes=indexes, + online_features_response=response, + full_feature_names=False, + table=_make_table(), + output_len=num_entities, + ) + + assert len(response.results) == num_features + expected_ts = int(timestamp.timestamp()) + for feature_idx in range(num_features): + fv = response.results[feature_idx] + assert len(fv.values) == num_entities + assert len(fv.statuses) == num_entities + assert len(fv.event_timestamps) == num_entities + + for ts in fv.event_timestamps: + assert ts.seconds == expected_ts + for status in fv.statuses: + assert status == FieldStatus.PRESENT diff --git a/sdk/python/tests/unit/test_utils_entity_maps.py b/sdk/python/tests/unit/test_utils_entity_maps.py new file mode 100644 index 00000000000..cf331b4ad30 --- /dev/null +++ b/sdk/python/tests/unit/test_utils_entity_maps.py @@ -0,0 +1,280 @@ +# Copyright 2025 The Feast Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Unit tests for _get_entity_maps function in feast/utils.py + +These tests verify that the fix for issue #6012 correctly eliminates +redundant registry.get_entity() calls by using a local lookup dict. + +Related issue: https://github.com/feast-dev/feast/issues/6012 +""" + +from unittest.mock import MagicMock + +from feast.entity import Entity +from feast.utils import _get_entity_maps + + +class MockFeatureViewProjection: + """Mock FeatureViewProjection for testing.""" + + def __init__(self, join_key_map=None): + self.join_key_map = join_key_map or {} + + +class MockEntityColumn: + """Mock entity column for testing.""" + + def __init__(self, name: str, dtype): + self.name = name + self.dtype = dtype + + +class MockDtype: + """Mock dtype with to_value_type method.""" + + def __init__(self, value_type): + self._value_type = value_type + + def to_value_type(self): + return self._value_type + + +class MockFeatureView: + """Mock FeatureView for testing.""" + + def __init__(self, entities=None, entity_columns=None, join_key_map=None): + self.entities = entities or [] + self.entity_columns = entity_columns or [] + self.projection = MockFeatureViewProjection(join_key_map) + + +def create_mock_entity(name: str, join_key: str) -> Entity: + """Create a mock Entity with the specified name and join_key.""" + entity = MagicMock(spec=Entity) + entity.name = name + entity.join_key = join_key + return entity + + +class TestGetEntityMaps: + """Tests for _get_entity_maps function.""" + + def test_no_redundant_get_entity_calls(self): + """ + Verify that get_entity is NOT called after list_entities fetches all entities. + This is the core fix for issue #6012. + """ + # Create mock entities + entity1 = create_mock_entity("driver", "driver_id") + entity2 = create_mock_entity("customer", "customer_id") + + # Create mock registry + registry = MagicMock() + registry.list_entities.return_value = [entity1, entity2] + + # Create feature views that reference the entities + fv1 = MockFeatureView(entities=["driver"]) + fv2 = MockFeatureView(entities=["customer"]) + fv3 = MockFeatureView(entities=["driver", "customer"]) + + # Call the function under test + _get_entity_maps(registry, "test_project", [fv1, fv2, fv3]) + + # Verify list_entities was called once + registry.list_entities.assert_called_once_with("test_project", allow_cache=True) + + # Verify get_entity was NEVER called (this is the fix) + registry.get_entity.assert_not_called() + + def test_entity_name_to_join_key_mapping(self): + """Test that entity names are correctly mapped to join keys.""" + entity1 = create_mock_entity("driver", "driver_id") + entity2 = create_mock_entity("customer", "customer_id") + + registry = MagicMock() + registry.list_entities.return_value = [entity1, entity2] + + fv = MockFeatureView(entities=["driver", "customer"]) + + entity_name_to_join_key, _, _ = _get_entity_maps(registry, "test_project", [fv]) + + assert "driver" in entity_name_to_join_key + assert entity_name_to_join_key["driver"] == "driver_id" + assert "customer" in entity_name_to_join_key + assert entity_name_to_join_key["customer"] == "customer_id" + + def test_join_keys_set(self): + """Test that the join keys set is correctly returned.""" + entity1 = create_mock_entity("driver", "driver_id") + entity2 = create_mock_entity("customer", "customer_id") + + registry = MagicMock() + registry.list_entities.return_value = [entity1, entity2] + + fv = MockFeatureView(entities=["driver", "customer"]) + + _, _, join_keys = _get_entity_maps(registry, "test_project", [fv]) + + assert "driver_id" in join_keys + assert "customer_id" in join_keys + assert len(join_keys) == 2 + + def test_missing_entity_raises_exception(self): + """ + Test that missing entities (not in registry) raise EntityNotFoundException. + This maintains the original error behavior for misconfigured registries. + """ + import pytest + + from feast.errors import EntityNotFoundException + + entity1 = create_mock_entity("driver", "driver_id") + + registry = MagicMock() + registry.list_entities.return_value = [entity1] + + # Feature view references entity that doesn't exist in registry + fv = MockFeatureView(entities=["driver", "nonexistent_entity"]) + + # Should raise EntityNotFoundException for the missing entity + with pytest.raises(EntityNotFoundException) as exc_info: + _get_entity_maps(registry, "test_project", [fv]) + + assert "nonexistent_entity" in str(exc_info.value) + + def test_join_key_remapping(self): + """Test that join_key_map correctly remaps entity names and join keys.""" + entity = create_mock_entity("driver", "driver_id") + + registry = MagicMock() + registry.list_entities.return_value = [entity] + + # Feature view with join key mapping + fv = MockFeatureView( + entities=["driver"], + join_key_map={"driver_id": "remapped_driver_id"}, + ) + + entity_name_to_join_key, _, join_keys = _get_entity_maps( + registry, "test_project", [fv] + ) + + # The remapped join key should be in the mapping + assert "remapped_driver_id" in join_keys + + def test_empty_feature_views(self): + """Test with no feature views.""" + entity1 = create_mock_entity("driver", "driver_id") + + registry = MagicMock() + registry.list_entities.return_value = [entity1] + + entity_name_to_join_key, entity_type_map, join_keys = _get_entity_maps( + registry, "test_project", [] + ) + + # Should still have the base entity mapping from list_entities + assert "driver" in entity_name_to_join_key + assert entity_name_to_join_key["driver"] == "driver_id" + + def test_empty_registry_and_feature_views(self): + """Test with no entities and no feature views returns empty maps.""" + registry = MagicMock() + registry.list_entities.return_value = [] + + entity_name_to_join_key, entity_type_map, join_keys = _get_entity_maps( + registry, "test_project", [] + ) + + assert len(entity_name_to_join_key) == 0 + assert len(join_keys) == 0 + + def test_entity_type_map_from_entity_columns(self): + """Test that entity_type_map is populated from entity_columns.""" + from feast.value_type import ValueType + + entity = create_mock_entity("driver", "driver_id") + + registry = MagicMock() + registry.list_entities.return_value = [entity] + + # Create entity columns with dtype + driver_col = MockEntityColumn("driver_id", MockDtype(ValueType.INT64)) + rating_col = MockEntityColumn("rating", MockDtype(ValueType.FLOAT)) + + fv = MockFeatureView( + entities=["driver"], + entity_columns=[driver_col, rating_col], + ) + + _, entity_type_map, _ = _get_entity_maps(registry, "test_project", [fv]) + + assert "driver_id" in entity_type_map + assert entity_type_map["driver_id"] == ValueType.INT64 + assert "rating" in entity_type_map + assert entity_type_map["rating"] == ValueType.FLOAT + + +class TestGetEntityMapsPerformance: + """Performance-related tests for _get_entity_maps.""" + + def test_linear_scaling_with_feature_views(self): + """ + Verify that increasing feature views doesn't increase registry calls. + With N feature views referencing M entities, we should have: + - 1 list_entities call (not N*M get_entity calls) + """ + # Create many entities + entities = [create_mock_entity(f"entity_{i}", f"key_{i}") for i in range(10)] + + registry = MagicMock() + registry.list_entities.return_value = entities + + # Create many feature views, each referencing multiple entities + feature_views = [ + MockFeatureView(entities=[f"entity_{j}" for j in range(i % 10 + 1)]) + for i in range(50) + ] + + _get_entity_maps(registry, "test_project", feature_views) + + # Regardless of 50 feature views with varying entity counts: + # - list_entities should be called exactly once + # - get_entity should NEVER be called + registry.list_entities.assert_called_once() + registry.get_entity.assert_not_called() + + def test_duplicate_entity_references(self): + """ + Test that duplicate entity references across feature views + don't cause any issues or duplicate lookups. + """ + entity = create_mock_entity("driver", "driver_id") + + registry = MagicMock() + registry.list_entities.return_value = [entity] + + # Multiple feature views all referencing the same entity + feature_views = [MockFeatureView(entities=["driver"]) for _ in range(20)] + + entity_name_to_join_key, _, join_keys = _get_entity_maps( + registry, "test_project", feature_views + ) + + # Should work correctly with just one entity in the result + assert entity_name_to_join_key["driver"] == "driver_id" + assert "driver_id" in join_keys + registry.get_entity.assert_not_called() diff --git a/sdk/python/tests/unit/transformation/__init__.py b/sdk/python/tests/unit/transformation/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sdk/python/tests/unit/transformation/test_factory.py b/sdk/python/tests/unit/transformation/test_factory.py new file mode 100644 index 00000000000..4484af0ae23 --- /dev/null +++ b/sdk/python/tests/unit/transformation/test_factory.py @@ -0,0 +1,88 @@ +from unittest.mock import MagicMock, patch + +import pytest + +from feast.transformation.factory import ( + TRANSFORMATION_CLASS_FOR_TYPE, + get_transformation_class_from_type, +) + + +class TestTransformationClassForType: + def test_all_expected_types_registered(self): + expected_types = { + "python", + "pandas", + "substrait", + "sql", + "spark_sql", + "spark", + "ray", + } + assert set(TRANSFORMATION_CLASS_FOR_TYPE.keys()) == expected_types + + def test_spark_and_spark_sql_resolve_to_same_class(self): + assert ( + TRANSFORMATION_CLASS_FOR_TYPE["spark"] + == TRANSFORMATION_CLASS_FOR_TYPE["spark_sql"] + ) + + +class TestGetTransformationClassFromType: + @patch("feast.transformation.factory.import_class") + def test_known_type_resolves(self, mock_import): + mock_cls = MagicMock() + mock_import.return_value = mock_cls + + result = get_transformation_class_from_type("python") + + mock_import.assert_called_once_with( + "feast.transformation.python_transformation", + "PythonTransformation", + "PythonTransformation", + ) + assert result == mock_cls + + @patch("feast.transformation.factory.import_class") + def test_pandas_type_resolves(self, mock_import): + mock_cls = MagicMock() + mock_import.return_value = mock_cls + + get_transformation_class_from_type("pandas") + + mock_import.assert_called_once_with( + "feast.transformation.pandas_transformation", + "PandasTransformation", + "PandasTransformation", + ) + + @patch("feast.transformation.factory.import_class") + def test_sql_type_resolves(self, mock_import): + mock_cls = MagicMock() + mock_import.return_value = mock_cls + + get_transformation_class_from_type("sql") + + mock_import.assert_called_once_with( + "feast.transformation.sql_transformation", + "SQLTransformation", + "SQLTransformation", + ) + + def test_invalid_type_raises_value_error(self): + with pytest.raises(ValueError, match="Invalid transformation type"): + get_transformation_class_from_type("nonexistent") + + @patch("feast.transformation.factory.import_class") + def test_fully_qualified_class_name_accepted(self, mock_import): + """A string ending in 'Transformation' is treated as a fully qualified class path.""" + mock_cls = MagicMock() + mock_import.return_value = mock_cls + + get_transformation_class_from_type("my.custom.module.CustomTransformation") + + mock_import.assert_called_once_with( + "my.custom.module", + "CustomTransformation", + "CustomTransformation", + ) diff --git a/sdk/python/tests/unit/transformation/test_mode.py b/sdk/python/tests/unit/transformation/test_mode.py new file mode 100644 index 00000000000..d37fc97e28d --- /dev/null +++ b/sdk/python/tests/unit/transformation/test_mode.py @@ -0,0 +1,21 @@ +from feast.transformation.mode import TransformationMode + + +class TestTransformationMode: + def test_all_modes_defined(self): + expected = {"PYTHON", "PANDAS", "SPARK_SQL", "SPARK", "RAY", "SQL", "SUBSTRAIT"} + actual = {m.name for m in TransformationMode} + assert actual == expected + + def test_mode_values(self): + assert TransformationMode.PYTHON.value == "python" + assert TransformationMode.PANDAS.value == "pandas" + assert TransformationMode.SPARK_SQL.value == "spark_sql" + assert TransformationMode.SPARK.value == "spark" + assert TransformationMode.RAY.value == "ray" + assert TransformationMode.SQL.value == "sql" + assert TransformationMode.SUBSTRAIT.value == "substrait" + + def test_mode_from_value(self): + assert TransformationMode("python") == TransformationMode.PYTHON + assert TransformationMode("pandas") == TransformationMode.PANDAS diff --git a/sdk/python/tests/unit/transformation/test_spark_transformation.py b/sdk/python/tests/unit/transformation/test_spark_transformation.py deleted file mode 100644 index 63d9b520ce9..00000000000 --- a/sdk/python/tests/unit/transformation/test_spark_transformation.py +++ /dev/null @@ -1,127 +0,0 @@ -from unittest.mock import patch - -import pytest -from pyspark.sql import SparkSession -from pyspark.sql.functions import col, regexp_replace -from pyspark.testing.utils import assertDataFrameEqual - -from feast.transformation.base import Transformation -from feast.transformation.mode import TransformationMode -from feast.transformation.spark_transformation import SparkTransformation - - -def get_sample_df(spark): - sample_data = [ - {"name": "John D.", "age": 30}, - {"name": "Alice G.", "age": 25}, - {"name": "Bob T.", "age": 35}, - {"name": "Eve A.", "age": 28}, - ] - df = spark.createDataFrame(sample_data) - return df - - -def get_expected_df(spark): - expected_data = [ - {"name": "John D.", "age": 30}, - {"name": "Alice G.", "age": 25}, - {"name": "Bob T.", "age": 35}, - {"name": "Eve A.", "age": 28}, - ] - - expected_df = spark.createDataFrame(expected_data) - return expected_df - - -def remove_extra_spaces(df, column_name): - df_transformed = df.withColumn( - column_name, regexp_replace(col(column_name), "\\s+", " ") - ) - return df_transformed - - -def remove_extra_spaces_sql(df, column_name): - sql = f""" - SELECT - age, - regexp_replace({column_name}, '\\\\s+', ' ') as {column_name} - FROM {df} - """ - return sql - - -@pytest.fixture -def spark_fixture(): - spark = ( - SparkSession.builder.appName("Testing PySpark Example") - .config("spark.driver.host", "127.0.0.1") - .config("spark.driver.bindAddress", "127.0.0.1") - .getOrCreate() - ) - try: - yield spark - finally: - spark.stop() - - -@patch("feast.infra.compute_engines.spark.utils.get_or_create_new_spark_session") -def test_spark_transformation(spark_fixture): - spark = ( - SparkSession.builder.appName("Testing PySpark Example") - .config("spark.driver.host", "127.0.0.1") - .config("spark.driver.bindAddress", "127.0.0.1") - .getOrCreate() - ) - df = get_sample_df(spark) - - spark_transformation = Transformation( - mode=TransformationMode.SPARK, - udf=remove_extra_spaces, - udf_string="remove extra spaces", - ) - - transformed_df = spark_transformation.transform(df, "name") - expected_df = get_expected_df(spark) - assertDataFrameEqual(transformed_df, expected_df) - - -@patch("feast.infra.compute_engines.spark.utils.get_or_create_new_spark_session") -def test_spark_transformation_init_transformation(spark_fixture): - spark = ( - SparkSession.builder.appName("Testing PySpark Example") - .config("spark.driver.host", "127.0.0.1") - .config("spark.driver.bindAddress", "127.0.0.1") - .getOrCreate() - ) - df = get_sample_df(spark) - - spark_transformation = SparkTransformation( - mode=TransformationMode.SPARK, - udf=remove_extra_spaces, - udf_string="remove extra spaces", - ) - - transformed_df = spark_transformation.transform(df, "name") - expected_df = get_expected_df(spark) - assertDataFrameEqual(transformed_df, expected_df) - - -@patch("feast.infra.compute_engines.spark.utils.get_or_create_new_spark_session") -def test_spark_transformation_sql(spark_fixture): - spark = ( - SparkSession.builder.appName("Testing PySpark Example") - .config("spark.driver.host", "127.0.0.1") - .config("spark.driver.bindAddress", "127.0.0.1") - .getOrCreate() - ) - df = get_sample_df(spark) - - spark_transformation = SparkTransformation( - mode=TransformationMode.SPARK_SQL, - udf=remove_extra_spaces_sql, - udf_string="remove extra spaces sql", - ) - - transformed_df = spark_transformation.transform(df, "name") - expected_df = get_expected_df(spark) - assertDataFrameEqual(transformed_df, expected_df) diff --git a/sdk/python/tests/unit/transformation/test_sql_transformation.py b/sdk/python/tests/unit/transformation/test_sql_transformation.py new file mode 100644 index 00000000000..8d24eaac3ee --- /dev/null +++ b/sdk/python/tests/unit/transformation/test_sql_transformation.py @@ -0,0 +1,16 @@ +from feast.transformation.sql_transformation import SQLTransformation + + +def sql_udf(inputs): + return f"SELECT * FROM source WHERE id = {inputs['id']}" + + +def test_sql_transformation_transform(): + """SQLTransformation.transform delegates to the udf.""" + transformation = SQLTransformation( + mode="sql", + udf=sql_udf, + udf_string="sql_udf", + ) + result = transformation.transform({"id": 42}) + assert result == "SELECT * FROM source WHERE id = 42" diff --git a/sdk/python/tests/universal/__init__.py b/sdk/python/tests/universal/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sdk/python/tests/universal/feature_repos/duckdb_repo_configuration.py b/sdk/python/tests/universal/feature_repos/duckdb_repo_configuration.py new file mode 100644 index 00000000000..5e03065cc3b --- /dev/null +++ b/sdk/python/tests/universal/feature_repos/duckdb_repo_configuration.py @@ -0,0 +1,35 @@ +from feast.infra.offline_stores.duckdb import DuckDBOfflineStoreConfig +from tests.universal.feature_repos.universal.data_sources.file import ( + DeltaFileSourceCreator, + DeltaS3FileSourceCreator, + FileDataSourceCreator, +) + + +class DuckDBDataSourceCreator(FileDataSourceCreator): + def create_offline_store_config(self): + self.duckdb_offline_store_config = DuckDBOfflineStoreConfig() + return self.duckdb_offline_store_config + + +class DuckDBDeltaDataSourceCreator(DeltaFileSourceCreator): + def create_offline_store_config(self): + self.duckdb_offline_store_config = DuckDBOfflineStoreConfig() + return self.duckdb_offline_store_config + + +class DuckDBDeltaS3DataSourceCreator(DeltaS3FileSourceCreator): + def create_offline_store_config(self): + self.duckdb_offline_store_config = DuckDBOfflineStoreConfig( + staging_location="s3://test/staging", + staging_location_endpoint_override=self.endpoint_url, + ) + return self.duckdb_offline_store_config + + +AVAILABLE_OFFLINE_STORES = [ + ("local", DuckDBDataSourceCreator), + ("local", DuckDBDeltaDataSourceCreator), +] + +AVAILABLE_ONLINE_STORES = {"sqlite": ({"type": "sqlite"}, None)} diff --git a/sdk/python/tests/integration/feature_repos/integration_test_repo_config.py b/sdk/python/tests/universal/feature_repos/integration_test_repo_config.py similarity index 91% rename from sdk/python/tests/integration/feature_repos/integration_test_repo_config.py rename to sdk/python/tests/universal/feature_repos/integration_test_repo_config.py index 309f92005a3..f635d2e9c17 100644 --- a/sdk/python/tests/integration/feature_repos/integration_test_repo_config.py +++ b/sdk/python/tests/universal/feature_repos/integration_test_repo_config.py @@ -3,13 +3,13 @@ from enum import Enum from typing import Dict, Optional, Type, Union -from tests.integration.feature_repos.universal.data_source_creator import ( +from tests.universal.feature_repos.universal.data_source_creator import ( DataSourceCreator, ) -from tests.integration.feature_repos.universal.data_sources.file import ( +from tests.universal.feature_repos.universal.data_sources.file import ( FileDataSourceCreator, ) -from tests.integration.feature_repos.universal.online_store_creator import ( +from tests.universal.feature_repos.universal.online_store_creator import ( OnlineStoreCreator, ) diff --git a/sdk/python/tests/universal/feature_repos/ray_repo_configuration.py b/sdk/python/tests/universal/feature_repos/ray_repo_configuration.py new file mode 100644 index 00000000000..39e43ae7b12 --- /dev/null +++ b/sdk/python/tests/universal/feature_repos/ray_repo_configuration.py @@ -0,0 +1,6 @@ +from feast.infra.offline_stores.contrib.ray_repo_configuration import ( + RayDataSourceCreator, +) + +AVAILABLE_OFFLINE_STORES = [("local", RayDataSourceCreator)] +AVAILABLE_ONLINE_STORES = {"sqlite": ({"type": "sqlite"}, None)} diff --git a/sdk/python/tests/integration/feature_repos/repo_configuration.py b/sdk/python/tests/universal/feature_repos/repo_configuration.py similarity index 90% rename from sdk/python/tests/integration/feature_repos/repo_configuration.py rename to sdk/python/tests/universal/feature_repos/repo_configuration.py index 1f53df48f3e..ddd952f71dc 100644 --- a/sdk/python/tests/integration/feature_repos/repo_configuration.py +++ b/sdk/python/tests/universal/feature_repos/repo_configuration.py @@ -27,40 +27,26 @@ FeatureLoggingConfig, ) from feast.infra.feature_servers.local_process.config import LocalFeatureServerConfig -from feast.infra.offline_stores.contrib.ray_repo_configuration import ( - RayDataSourceCreator, -) from feast.permissions.action import AuthzedAction from feast.permissions.auth_model import OidcClientAuthConfig from feast.permissions.permission import Permission from feast.permissions.policy import RoleBasedPolicy from feast.repo_config import MaterializationConfig, RegistryConfig, RepoConfig from feast.utils import _utc_now -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, RegistryLocation, ) -from tests.integration.feature_repos.universal.data_source_creator import ( +from tests.universal.feature_repos.universal.data_source_creator import ( DataSourceCreator, ) -from tests.integration.feature_repos.universal.data_sources.bigquery import ( - BigQueryDataSourceCreator, -) -from tests.integration.feature_repos.universal.data_sources.file import ( - DuckDBDataSourceCreator, - DuckDBDeltaDataSourceCreator, +from tests.universal.feature_repos.universal.data_sources.file import ( FileDataSourceCreator, RemoteOfflineOidcAuthStoreDataSourceCreator, RemoteOfflineStoreDataSourceCreator, RemoteOfflineTlsStoreDataSourceCreator, ) -from tests.integration.feature_repos.universal.data_sources.redshift import ( - RedshiftDataSourceCreator, -) -from tests.integration.feature_repos.universal.data_sources.snowflake import ( - SnowflakeDataSourceCreator, -) -from tests.integration.feature_repos.universal.feature_views import ( +from tests.universal.feature_repos.universal.feature_views import ( conv_rate_plus_100_feature_view, create_conv_rate_request_source, create_customer_daily_profile_feature_view, @@ -72,22 +58,7 @@ create_order_feature_view, create_pushable_feature_view, ) -from tests.integration.feature_repos.universal.online_store.bigtable import ( - BigtableOnlineStoreCreator, -) -from tests.integration.feature_repos.universal.online_store.datastore import ( - DatastoreOnlineStoreCreator, -) -from tests.integration.feature_repos.universal.online_store.dynamodb import ( - DynamoDBOnlineStoreCreator, -) -from tests.integration.feature_repos.universal.online_store.milvus import ( - MilvusOnlineStoreCreator, -) -from tests.integration.feature_repos.universal.online_store.redis import ( - RedisOnlineStoreCreator, -) -from tests.integration.feature_repos.universal.online_store_creator import ( +from tests.universal.feature_repos.universal.online_store_creator import ( OnlineStoreCreator, ) @@ -118,29 +89,15 @@ "instance": os.getenv("BIGTABLE_INSTANCE_ID", "feast-integration-tests"), } -IKV_CONFIG = { - "type": "ikv", - "account_id": os.getenv("IKV_ACCOUNT_ID", ""), - "account_passkey": os.getenv("IKV_ACCOUNT_PASSKEY", ""), - "store_name": os.getenv("IKV_STORE_NAME", ""), - "mount_directory": os.getenv("IKV_MOUNT_DIR", ""), -} - OFFLINE_STORE_TO_PROVIDER_CONFIG: Dict[str, Tuple[str, Type[DataSourceCreator]]] = { "file": ("local", FileDataSourceCreator), - "bigquery": ("gcp", BigQueryDataSourceCreator), - "redshift": ("aws", RedshiftDataSourceCreator), - "snowflake": ("aws", SnowflakeDataSourceCreator), } AVAILABLE_OFFLINE_STORES: List[Tuple[str, Type[DataSourceCreator]]] = [ ("local", FileDataSourceCreator), - ("local", DuckDBDataSourceCreator), - ("local", DuckDBDeltaDataSourceCreator), ("local", RemoteOfflineStoreDataSourceCreator), ("local", RemoteOfflineOidcAuthStoreDataSourceCreator), ("local", RemoteOfflineTlsStoreDataSourceCreator), - ("local", RayDataSourceCreator), ] if os.getenv("FEAST_IS_LOCAL_TEST", "False") == "True": @@ -157,6 +114,16 @@ # Only configure Cloud DWH if running full integration tests if os.getenv("FEAST_IS_LOCAL_TEST", "False") != "True": + from tests.universal.feature_repos.universal.data_sources.bigquery import ( + BigQueryDataSourceCreator, + ) + from tests.universal.feature_repos.universal.data_sources.redshift import ( + RedshiftDataSourceCreator, + ) + from tests.universal.feature_repos.universal.data_sources.snowflake import ( + SnowflakeDataSourceCreator, + ) + AVAILABLE_OFFLINE_STORES.extend( [ ("gcp", BigQueryDataSourceCreator), @@ -165,6 +132,10 @@ ] ) + OFFLINE_STORE_TO_PROVIDER_CONFIG["bigquery"] = ("gcp", BigQueryDataSourceCreator) + OFFLINE_STORE_TO_PROVIDER_CONFIG["redshift"] = ("aws", RedshiftDataSourceCreator) + OFFLINE_STORE_TO_PROVIDER_CONFIG["snowflake"] = ("aws", SnowflakeDataSourceCreator) + AVAILABLE_ONLINE_STORES["redis"] = (REDIS_CONFIG, None) AVAILABLE_ONLINE_STORES["dynamodb"] = (DYNAMO_CONFIG, None) AVAILABLE_ONLINE_STORES["datastore"] = ("datastore", None) @@ -172,10 +143,6 @@ AVAILABLE_ONLINE_STORES["bigtable"] = (BIGTABLE_CONFIG, None) AVAILABLE_ONLINE_STORES["milvus"] = (MILVUS_CONFIG, None) - # Uncomment to test using private IKV account. Currently not enabled as - # there is no dedicated IKV instance for CI testing and there is no - # containerized version of IKV. - # AVAILABLE_ONLINE_STORES["ikv"] = (IKV_CONFIG, None) full_repo_configs_module = os.environ.get(FULL_REPO_CONFIGS_MODULE_ENV_NAME) if full_repo_configs_module is not None: @@ -214,6 +181,25 @@ # Replace online stores with emulated online stores if we're running local integration tests if os.getenv("FEAST_LOCAL_ONLINE_CONTAINER", "False").lower() == "true": + from tests.universal.feature_repos.universal.online_store.bigtable import ( + BigtableOnlineStoreCreator, + ) + from tests.universal.feature_repos.universal.online_store.datastore import ( + DatastoreOnlineStoreCreator, + ) + from tests.universal.feature_repos.universal.online_store.dynamodb import ( + DynamoDBOnlineStoreCreator, + ) + from tests.universal.feature_repos.universal.online_store.milvus import ( + MilvusOnlineStoreCreator, + ) + from tests.universal.feature_repos.universal.online_store.postgres import ( + PGVectorOnlineStoreCreator, + ) + from tests.universal.feature_repos.universal.online_store.redis import ( + RedisOnlineStoreCreator, + ) + replacements: Dict[ str, Tuple[Union[str, Dict[str, Any]], Optional[Type[OnlineStoreCreator]]] ] = { @@ -223,6 +209,10 @@ "datastore": ("datastore", DatastoreOnlineStoreCreator), "bigtable": ("bigtable", BigtableOnlineStoreCreator), } + AVAILABLE_ONLINE_STORES["pgvector"] = ( + {"type": "postgres", "vector_enabled": True, "sslmode": "disable"}, + PGVectorOnlineStoreCreator, + ) for key, replacement in replacements.items(): if key in AVAILABLE_ONLINE_STORES: diff --git a/sdk/python/tests/integration/feature_repos/universal/data_source_creator.py b/sdk/python/tests/universal/feature_repos/universal/data_source_creator.py similarity index 73% rename from sdk/python/tests/integration/feature_repos/universal/data_source_creator.py rename to sdk/python/tests/universal/feature_repos/universal/data_source_creator.py index 467db4dddce..6c0bc39b353 100644 --- a/sdk/python/tests/integration/feature_repos/universal/data_source_creator.py +++ b/sdk/python/tests/universal/feature_repos/universal/data_source_creator.py @@ -1,3 +1,4 @@ +import json from abc import ABC, abstractmethod from typing import Dict, Optional @@ -14,6 +15,29 @@ class DataSourceCreator(ABC): def __init__(self, project_name: str, *args, **kwargs): self.project_name = project_name + @staticmethod + def serialize_complex_columns(df: pd.DataFrame) -> pd.DataFrame: + """Serialize dict columns (Map/Struct types) to JSON strings. + + Backends like Snowflake, BigQuery, and Redshift cannot natively + ingest Python dicts via their bulk-load paths (VARIANT, STRUCT, + super types cause issues). Converting them to JSON strings lets + the data be stored as VARCHAR/STRING instead. + + List columns with primitive values (int, float, str, bool) are + left untouched since backends handle those as native ARRAY types. + """ + df = df.copy() + for col in df.columns: + if df[col].dropna().empty: + continue + sample = df[col].dropna().iloc[0] + if isinstance(sample, dict): + df[col] = df[col].apply( + lambda v: json.dumps(v) if v is not None else None + ) + return df + @abstractmethod def create_data_source( self, diff --git a/sdk/python/tests/universal/feature_repos/universal/data_sources/__init__.py b/sdk/python/tests/universal/feature_repos/universal/data_sources/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sdk/python/tests/integration/feature_repos/universal/data_sources/bigquery.py b/sdk/python/tests/universal/feature_repos/universal/data_sources/bigquery.py similarity index 96% rename from sdk/python/tests/integration/feature_repos/universal/data_sources/bigquery.py rename to sdk/python/tests/universal/feature_repos/universal/data_sources/bigquery.py index 4fcd9533e8e..39595acf536 100644 --- a/sdk/python/tests/integration/feature_repos/universal/data_sources/bigquery.py +++ b/sdk/python/tests/universal/feature_repos/universal/data_sources/bigquery.py @@ -15,7 +15,7 @@ SavedDatasetBigQueryStorage, ) from feast.utils import make_df_tzaware -from tests.integration.feature_repos.universal.data_source_creator import ( +from tests.universal.feature_repos.universal.data_source_creator import ( DataSourceCreator, ) @@ -80,6 +80,7 @@ def create_data_source( # `BigQueryOfflineStore.offline_write_batch`, but since we're bypassing that API here, we should follow the same # rule. The schema of this initial dataframe determines the schema in the newly created BigQuery table. df = make_df_tzaware(df) + df = self.serialize_complex_columns(df) job = self.client.load_table_from_dataframe(df, destination_name) job.result() diff --git a/sdk/python/tests/integration/feature_repos/universal/data_sources/file.py b/sdk/python/tests/universal/feature_repos/universal/data_sources/file.py similarity index 95% rename from sdk/python/tests/integration/feature_repos/universal/data_sources/file.py rename to sdk/python/tests/universal/feature_repos/universal/data_sources/file.py index a592dfc54a5..1084685e361 100644 --- a/sdk/python/tests/integration/feature_repos/universal/data_sources/file.py +++ b/sdk/python/tests/universal/feature_repos/universal/data_sources/file.py @@ -24,7 +24,6 @@ from feast.data_source import DataSource from feast.feature_logging import LoggingDestination from feast.infra.offline_stores.dask import DaskOfflineStoreConfig -from feast.infra.offline_stores.duckdb import DuckDBOfflineStoreConfig from feast.infra.offline_stores.file_source import ( FileLoggingDestination, SavedDatasetFileStorage, @@ -32,7 +31,7 @@ from feast.infra.offline_stores.remote import RemoteOfflineStoreConfig from feast.repo_config import FeastConfigBaseModel, RegistryConfig from feast.wait import wait_retry_backoff # noqa: E402 -from tests.integration.feature_repos.universal.data_source_creator import ( +from tests.universal.feature_repos.universal.data_source_creator import ( DataSourceCreator, ) from tests.utils.auth_permissions_util import include_auth_config @@ -346,28 +345,6 @@ def teardown(self): self.f.close() -# TODO split up DataSourceCreator and OfflineStoreCreator -class DuckDBDataSourceCreator(FileDataSourceCreator): - def create_offline_store_config(self): - self.duckdb_offline_store_config = DuckDBOfflineStoreConfig() - return self.duckdb_offline_store_config - - -class DuckDBDeltaDataSourceCreator(DeltaFileSourceCreator): - def create_offline_store_config(self): - self.duckdb_offline_store_config = DuckDBOfflineStoreConfig() - return self.duckdb_offline_store_config - - -class DuckDBDeltaS3DataSourceCreator(DeltaS3FileSourceCreator): - def create_offline_store_config(self): - self.duckdb_offline_store_config = DuckDBOfflineStoreConfig( - staging_location="s3://test/staging", - staging_location_endpoint_override=self.endpoint_url, - ) - return self.duckdb_offline_store_config - - class RemoteOfflineStoreDataSourceCreator(FileDataSourceCreator): def __init__(self, project_name: str, *args, **kwargs): super().__init__(project_name) diff --git a/sdk/python/tests/integration/feature_repos/universal/data_sources/redshift.py b/sdk/python/tests/universal/feature_repos/universal/data_sources/redshift.py similarity index 97% rename from sdk/python/tests/integration/feature_repos/universal/data_sources/redshift.py rename to sdk/python/tests/universal/feature_repos/universal/data_sources/redshift.py index 91d1a74f071..000bc226694 100644 --- a/sdk/python/tests/integration/feature_repos/universal/data_sources/redshift.py +++ b/sdk/python/tests/universal/feature_repos/universal/data_sources/redshift.py @@ -14,7 +14,7 @@ ) from feast.infra.utils import aws_utils from feast.repo_config import FeastConfigBaseModel -from tests.integration.feature_repos.universal.data_source_creator import ( +from tests.universal.feature_repos.universal.data_source_creator import ( DataSourceCreator, ) @@ -55,6 +55,7 @@ def create_data_source( ) -> DataSource: destination_name = self.get_prefixed_table_name(destination_name) + df = self.serialize_complex_columns(df) aws_utils.upload_df_to_redshift( self.client, self.offline_store_config.cluster_id, diff --git a/sdk/python/tests/integration/feature_repos/universal/data_sources/snowflake.py b/sdk/python/tests/universal/feature_repos/universal/data_sources/snowflake.py similarity index 96% rename from sdk/python/tests/integration/feature_repos/universal/data_sources/snowflake.py rename to sdk/python/tests/universal/feature_repos/universal/data_sources/snowflake.py index e9c4ad21a31..8e456168786 100644 --- a/sdk/python/tests/integration/feature_repos/universal/data_sources/snowflake.py +++ b/sdk/python/tests/universal/feature_repos/universal/data_sources/snowflake.py @@ -18,7 +18,7 @@ write_pandas, ) from feast.repo_config import FeastConfigBaseModel -from tests.integration.feature_repos.universal.data_source_creator import ( +from tests.universal.feature_repos.universal.data_source_creator import ( DataSourceCreator, ) @@ -53,6 +53,7 @@ def create_data_source( ) -> DataSource: destination_name = self.get_prefixed_table_name(destination_name) + df = self.serialize_complex_columns(df) with GetSnowflakeConnection(self.offline_store_config) as conn: write_pandas(conn, df, destination_name, auto_create_table=True) diff --git a/sdk/python/tests/integration/feature_repos/universal/entities.py b/sdk/python/tests/universal/feature_repos/universal/entities.py similarity index 100% rename from sdk/python/tests/integration/feature_repos/universal/entities.py rename to sdk/python/tests/universal/feature_repos/universal/entities.py diff --git a/sdk/python/tests/integration/feature_repos/universal/feature_views.py b/sdk/python/tests/universal/feature_repos/universal/feature_views.py similarity index 93% rename from sdk/python/tests/integration/feature_repos/universal/feature_views.py rename to sdk/python/tests/universal/feature_repos/universal/feature_views.py index 8b663252a02..2d1e62ea617 100644 --- a/sdk/python/tests/integration/feature_repos/universal/feature_views.py +++ b/sdk/python/tests/universal/feature_repos/universal/feature_views.py @@ -16,8 +16,19 @@ from feast.data_source import DataSource, RequestSource from feast.feature_view_projection import FeatureViewProjection from feast.on_demand_feature_view import PandasTransformation -from feast.types import Array, FeastType, Float32, Float64, Int32, Int64, String -from tests.integration.feature_repos.universal.entities import ( +from feast.types import ( + Array, + FeastType, + Float32, + Float64, + Int32, + Int64, + Json, + Map, + String, + Struct, +) +from tests.universal.feature_repos.universal.entities import ( customer, driver, item, @@ -193,6 +204,12 @@ def create_driver_hourly_stats_feature_view(source, infer_features: bool = False Field(name="acc_rate", dtype=Float32), Field(name="avg_daily_trips", dtype=Int32), Field(name=d.join_key, dtype=Int64), + Field(name="driver_metadata", dtype=Map), + Field(name="driver_config", dtype=Json), + Field( + name="driver_profile", + dtype=Struct({"name": String, "age": String}), + ), ], source=source, ttl=timedelta(hours=2), @@ -213,6 +230,12 @@ def create_driver_hourly_stats_batch_feature_view( Field(name="conv_rate", dtype=Float32), Field(name="acc_rate", dtype=Float32), Field(name="avg_daily_trips", dtype=Int32), + Field(name="driver_metadata", dtype=Map), + Field(name="driver_config", dtype=Json), + Field( + name="driver_profile", + dtype=Struct({"name": String, "age": String}), + ), ], source=source, ttl=timedelta(hours=2), diff --git a/sdk/python/tests/universal/feature_repos/universal/online_store/__init__.py b/sdk/python/tests/universal/feature_repos/universal/online_store/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store/bigtable.py b/sdk/python/tests/universal/feature_repos/universal/online_store/bigtable.py similarity index 95% rename from sdk/python/tests/integration/feature_repos/universal/online_store/bigtable.py rename to sdk/python/tests/universal/feature_repos/universal/online_store/bigtable.py index c06143e245b..a6f6ceb12da 100644 --- a/sdk/python/tests/integration/feature_repos/universal/online_store/bigtable.py +++ b/sdk/python/tests/universal/feature_repos/universal/online_store/bigtable.py @@ -5,7 +5,7 @@ from testcontainers.core.container import DockerContainer from testcontainers.core.waiting_utils import wait_for_logs -from tests.integration.feature_repos.universal.online_store_creator import ( +from tests.universal.feature_repos.universal.online_store_creator import ( OnlineStoreCreator, ) diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store/cassandra.py b/sdk/python/tests/universal/feature_repos/universal/online_store/cassandra.py similarity index 96% rename from sdk/python/tests/integration/feature_repos/universal/online_store/cassandra.py rename to sdk/python/tests/universal/feature_repos/universal/online_store/cassandra.py index 190d94a8305..c7ca91e18b2 100644 --- a/sdk/python/tests/integration/feature_repos/universal/online_store/cassandra.py +++ b/sdk/python/tests/universal/feature_repos/universal/online_store/cassandra.py @@ -20,7 +20,7 @@ from testcontainers.core.container import DockerContainer from testcontainers.core.waiting_utils import wait_for_logs -from tests.integration.feature_repos.universal.online_store_creator import ( +from tests.universal.feature_repos.universal.online_store_creator import ( OnlineStoreCreator, ) diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store/couchbase.py b/sdk/python/tests/universal/feature_repos/universal/online_store/couchbase.py similarity index 98% rename from sdk/python/tests/integration/feature_repos/universal/online_store/couchbase.py rename to sdk/python/tests/universal/feature_repos/universal/online_store/couchbase.py index 2723ff13a30..cb030b708c6 100644 --- a/sdk/python/tests/integration/feature_repos/universal/online_store/couchbase.py +++ b/sdk/python/tests/universal/feature_repos/universal/online_store/couchbase.py @@ -5,7 +5,7 @@ from testcontainers.core.container import DockerContainer from testcontainers.core.waiting_utils import wait_for_logs -from tests.integration.feature_repos.universal.online_store_creator import ( +from tests.universal.feature_repos.universal.online_store_creator import ( OnlineStoreCreator, ) diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store/datastore.py b/sdk/python/tests/universal/feature_repos/universal/online_store/datastore.py similarity index 94% rename from sdk/python/tests/integration/feature_repos/universal/online_store/datastore.py rename to sdk/python/tests/universal/feature_repos/universal/online_store/datastore.py index b5bbb94f7c1..8eaa5139e43 100644 --- a/sdk/python/tests/integration/feature_repos/universal/online_store/datastore.py +++ b/sdk/python/tests/universal/feature_repos/universal/online_store/datastore.py @@ -5,7 +5,7 @@ from testcontainers.core.container import DockerContainer from testcontainers.core.waiting_utils import wait_for_logs -from tests.integration.feature_repos.universal.online_store_creator import ( +from tests.universal.feature_repos.universal.online_store_creator import ( OnlineStoreCreator, ) diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store/dynamodb.py b/sdk/python/tests/universal/feature_repos/universal/online_store/dynamodb.py similarity index 93% rename from sdk/python/tests/integration/feature_repos/universal/online_store/dynamodb.py rename to sdk/python/tests/universal/feature_repos/universal/online_store/dynamodb.py index 1aefdffb24b..04a1ffac355 100644 --- a/sdk/python/tests/integration/feature_repos/universal/online_store/dynamodb.py +++ b/sdk/python/tests/universal/feature_repos/universal/online_store/dynamodb.py @@ -3,7 +3,7 @@ from testcontainers.core.container import DockerContainer from testcontainers.core.waiting_utils import wait_for_logs -from tests.integration.feature_repos.universal.online_store_creator import ( +from tests.universal.feature_repos.universal.online_store_creator import ( OnlineStoreCreator, ) diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store/elasticsearch.py b/sdk/python/tests/universal/feature_repos/universal/online_store/elasticsearch.py similarity index 90% rename from sdk/python/tests/integration/feature_repos/universal/online_store/elasticsearch.py rename to sdk/python/tests/universal/feature_repos/universal/online_store/elasticsearch.py index 1e8088a997e..8ef467ae796 100644 --- a/sdk/python/tests/integration/feature_repos/universal/online_store/elasticsearch.py +++ b/sdk/python/tests/universal/feature_repos/universal/online_store/elasticsearch.py @@ -2,7 +2,7 @@ from testcontainers.elasticsearch import ElasticSearchContainer -from tests.integration.feature_repos.universal.online_store_creator import ( +from tests.universal.feature_repos.universal.online_store_creator import ( OnlineStoreCreator, ) diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store/hazelcast.py b/sdk/python/tests/universal/feature_repos/universal/online_store/hazelcast.py similarity index 95% rename from sdk/python/tests/integration/feature_repos/universal/online_store/hazelcast.py rename to sdk/python/tests/universal/feature_repos/universal/online_store/hazelcast.py index d50f2b75a3d..22ea5dcc09d 100644 --- a/sdk/python/tests/integration/feature_repos/universal/online_store/hazelcast.py +++ b/sdk/python/tests/universal/feature_repos/universal/online_store/hazelcast.py @@ -6,7 +6,7 @@ from testcontainers.core.container import DockerContainer from testcontainers.core.waiting_utils import wait_for_logs -from tests.integration.feature_repos.universal.online_store_creator import ( +from tests.universal.feature_repos.universal.online_store_creator import ( OnlineStoreCreator, ) diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store/hbase.py b/sdk/python/tests/universal/feature_repos/universal/online_store/hbase.py similarity index 92% rename from sdk/python/tests/integration/feature_repos/universal/online_store/hbase.py rename to sdk/python/tests/universal/feature_repos/universal/online_store/hbase.py index dba611b30bc..d350828d08a 100644 --- a/sdk/python/tests/integration/feature_repos/universal/online_store/hbase.py +++ b/sdk/python/tests/universal/feature_repos/universal/online_store/hbase.py @@ -3,7 +3,7 @@ from testcontainers.core.container import DockerContainer from testcontainers.core.waiting_utils import wait_for_logs -from tests.integration.feature_repos.universal.online_store_creator import ( +from tests.universal.feature_repos.universal.online_store_creator import ( OnlineStoreCreator, ) diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store/hybrid_online_store.py b/sdk/python/tests/universal/feature_repos/universal/online_store/hybrid_online_store.py similarity index 90% rename from sdk/python/tests/integration/feature_repos/universal/online_store/hybrid_online_store.py rename to sdk/python/tests/universal/feature_repos/universal/online_store/hybrid_online_store.py index f0efbd11044..619702330e6 100644 --- a/sdk/python/tests/integration/feature_repos/universal/online_store/hybrid_online_store.py +++ b/sdk/python/tests/universal/feature_repos/universal/online_store/hybrid_online_store.py @@ -1,4 +1,4 @@ -from sdk.python.tests.integration.feature_repos.universal.online_store_creator import ( +from sdk.python.tests.universal.feature_repos.universal.online_store_creator import ( OnlineStoreCreator, ) diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store/init.sql b/sdk/python/tests/universal/feature_repos/universal/online_store/init.sql similarity index 100% rename from sdk/python/tests/integration/feature_repos/universal/online_store/init.sql rename to sdk/python/tests/universal/feature_repos/universal/online_store/init.sql diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store/milvus.py b/sdk/python/tests/universal/feature_repos/universal/online_store/milvus.py similarity index 91% rename from sdk/python/tests/integration/feature_repos/universal/online_store/milvus.py rename to sdk/python/tests/universal/feature_repos/universal/online_store/milvus.py index a8f2839bf8b..cfe6aec3677 100644 --- a/sdk/python/tests/integration/feature_repos/universal/online_store/milvus.py +++ b/sdk/python/tests/universal/feature_repos/universal/online_store/milvus.py @@ -1,6 +1,6 @@ from typing import Any -from tests.integration.feature_repos.universal.online_store_creator import ( +from tests.universal.feature_repos.universal.online_store_creator import ( OnlineStoreCreator, ) diff --git a/sdk/python/tests/universal/feature_repos/universal/online_store/mongodb.py b/sdk/python/tests/universal/feature_repos/universal/online_store/mongodb.py new file mode 100644 index 00000000000..0c0afd4908a --- /dev/null +++ b/sdk/python/tests/universal/feature_repos/universal/online_store/mongodb.py @@ -0,0 +1,31 @@ +from typing import Any, Dict + +from testcontainers.mongodb import MongoDbContainer + +from tests.universal.feature_repos.universal.online_store_creator import ( + OnlineStoreCreator, +) + + +class MongoDBOnlineStoreCreator(OnlineStoreCreator): + def __init__(self, project_name: str, **kwargs): + super().__init__(project_name) + # MongoDbContainer from testcontainers sets up authentication by default + # with username and password from the constructor + self.container = MongoDbContainer( + "mongo:latest", + username="test", + password="test", # pragma: allowlist secret + ).with_exposed_ports(27017) + + def create_online_store(self) -> Dict[str, Any]: + self.container.start() + exposed_port = self.container.get_exposed_port(27017) + # Include authentication in the connection string + return { + "type": "mongodb", + "connection_string": f"mongodb://test:test@localhost:{exposed_port}", # pragma: allowlist secret + } + + def teardown(self): + self.container.stop() diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store/mysql.py b/sdk/python/tests/universal/feature_repos/universal/online_store/mysql.py similarity index 95% rename from sdk/python/tests/integration/feature_repos/universal/online_store/mysql.py rename to sdk/python/tests/universal/feature_repos/universal/online_store/mysql.py index c0ba91d15a4..c1ebdf6c984 100644 --- a/sdk/python/tests/integration/feature_repos/universal/online_store/mysql.py +++ b/sdk/python/tests/universal/feature_repos/universal/online_store/mysql.py @@ -2,7 +2,7 @@ from testcontainers.mysql import MySqlContainer -from tests.integration.feature_repos.universal.online_store_creator import ( +from tests.universal.feature_repos.universal.online_store_creator import ( OnlineStoreCreator, ) diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store/postgres.py b/sdk/python/tests/universal/feature_repos/universal/online_store/postgres.py similarity index 95% rename from sdk/python/tests/integration/feature_repos/universal/online_store/postgres.py rename to sdk/python/tests/universal/feature_repos/universal/online_store/postgres.py index d11f563cb5c..b9fda20d26a 100644 --- a/sdk/python/tests/integration/feature_repos/universal/online_store/postgres.py +++ b/sdk/python/tests/universal/feature_repos/universal/online_store/postgres.py @@ -5,7 +5,7 @@ from testcontainers.core.waiting_utils import wait_for_logs from testcontainers.postgres import PostgresContainer -from tests.integration.feature_repos.universal.online_store_creator import ( +from tests.universal.feature_repos.universal.online_store_creator import ( OnlineStoreCreator, ) @@ -69,6 +69,7 @@ def create_online_store(self) -> Dict[str, Any]: "database": "test", "vector_enabled": True, "port": self.container.get_exposed_port(5432), + "sslmode": "disable", } def teardown(self): diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store/qdrant.py b/sdk/python/tests/universal/feature_repos/universal/online_store/qdrant.py similarity index 90% rename from sdk/python/tests/integration/feature_repos/universal/online_store/qdrant.py rename to sdk/python/tests/universal/feature_repos/universal/online_store/qdrant.py index 82a027b416d..a9036252711 100644 --- a/sdk/python/tests/integration/feature_repos/universal/online_store/qdrant.py +++ b/sdk/python/tests/universal/feature_repos/universal/online_store/qdrant.py @@ -2,7 +2,7 @@ from testcontainers.qdrant import QdrantContainer -from tests.integration.feature_repos.universal.online_store_creator import ( +from tests.universal.feature_repos.universal.online_store_creator import ( OnlineStoreCreator, ) diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store/redis.py b/sdk/python/tests/universal/feature_repos/universal/online_store/redis.py similarity index 92% rename from sdk/python/tests/integration/feature_repos/universal/online_store/redis.py rename to sdk/python/tests/universal/feature_repos/universal/online_store/redis.py index 8e18f7fb172..715755471df 100644 --- a/sdk/python/tests/integration/feature_repos/universal/online_store/redis.py +++ b/sdk/python/tests/universal/feature_repos/universal/online_store/redis.py @@ -3,7 +3,7 @@ from testcontainers.core.container import DockerContainer from testcontainers.core.waiting_utils import wait_for_logs -from tests.integration.feature_repos.universal.online_store_creator import ( +from tests.universal.feature_repos.universal.online_store_creator import ( OnlineStoreCreator, ) diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store/singlestore.py b/sdk/python/tests/universal/feature_repos/universal/online_store/singlestore.py similarity index 95% rename from sdk/python/tests/integration/feature_repos/universal/online_store/singlestore.py rename to sdk/python/tests/universal/feature_repos/universal/online_store/singlestore.py index d3a02421d0a..3c9a835dfe2 100644 --- a/sdk/python/tests/integration/feature_repos/universal/online_store/singlestore.py +++ b/sdk/python/tests/universal/feature_repos/universal/online_store/singlestore.py @@ -4,7 +4,7 @@ from testcontainers.core.container import DockerContainer -from tests.integration.feature_repos.universal.online_store_creator import ( +from tests.universal.feature_repos.universal.online_store_creator import ( OnlineStoreCreator, ) diff --git a/sdk/python/tests/integration/feature_repos/universal/online_store_creator.py b/sdk/python/tests/universal/feature_repos/universal/online_store_creator.py similarity index 100% rename from sdk/python/tests/integration/feature_repos/universal/online_store_creator.py rename to sdk/python/tests/universal/feature_repos/universal/online_store_creator.py diff --git a/sdk/python/tests/universal/offline_store/.gitkeep b/sdk/python/tests/universal/offline_store/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sdk/python/tests/universal/online_store/.gitkeep b/sdk/python/tests/universal/online_store/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sdk/python/tests/utils/cli_repo_creator.py b/sdk/python/tests/utils/cli_repo_creator.py index 554c5af99f2..3aa96768f61 100644 --- a/sdk/python/tests/utils/cli_repo_creator.py +++ b/sdk/python/tests/utils/cli_repo_creator.py @@ -148,6 +148,19 @@ def local_repo( entity_key_serialization_version: 3 """ ) + elif online_store: # Added for mongodb, but very general + yaml_config = dedent( + f""" + project: {project_id} + registry: {data_path / "registry.db"} + provider: local + online_store: + type: {online_store} + offline_store: + type: {offline_store} + entity_key_serialization_version: 3 + """ + ) else: pass diff --git a/sdk/python/tests/utils/e2e_test_validation.py b/sdk/python/tests/utils/e2e_test_validation.py index 6d887b8bb07..c89d61b9d5a 100644 --- a/sdk/python/tests/utils/e2e_test_validation.py +++ b/sdk/python/tests/utils/e2e_test_validation.py @@ -10,22 +10,16 @@ from feast import FeatureStore, FeatureView, RepoConfig from feast.utils import _utc_now -from tests.integration.feature_repos.integration_test_repo_config import ( +from tests.universal.feature_repos.integration_test_repo_config import ( IntegrationTestRepoConfig, ) -from tests.integration.feature_repos.universal.data_source_creator import ( +from tests.universal.feature_repos.universal.data_source_creator import ( DataSourceCreator, ) -from tests.integration.feature_repos.universal.data_sources.bigquery import ( - BigQueryDataSourceCreator, -) -from tests.integration.feature_repos.universal.data_sources.file import ( +from tests.universal.feature_repos.universal.data_sources.file import ( FileDataSourceCreator, FileParquetDatasetSourceCreator, ) -from tests.integration.feature_repos.universal.data_sources.redshift import ( - RedshiftDataSourceCreator, -) def validate_offline_online_store_consistency( @@ -225,6 +219,13 @@ def make_feature_store_yaml( # Only test if this is NOT a local test if os.getenv("FEAST_IS_LOCAL_TEST", "False") != "True": + from tests.universal.feature_repos.universal.data_sources.bigquery import ( + BigQueryDataSourceCreator, + ) + from tests.universal.feature_repos.universal.data_sources.redshift import ( + RedshiftDataSourceCreator, + ) + NULLABLE_ONLINE_STORE_CONFIGS.extend( [ IntegrationTestRepoConfig( diff --git a/sdk/python/tests/utils/type_test_utils.py b/sdk/python/tests/utils/type_test_utils.py new file mode 100644 index 00000000000..5abf069b928 --- /dev/null +++ b/sdk/python/tests/utils/type_test_utils.py @@ -0,0 +1,103 @@ +from dataclasses import dataclass +from typing import List, Optional + +from feast.types import ( + Array, + Bool, + FeastType, + Float32, + Int32, + Int64, + UnixTimestamp, +) +from tests.data.data_creator import create_basic_driver_dataset +from tests.universal.feature_repos.universal.feature_views import driver_feature_view + + +@dataclass(frozen=True, repr=True) +class TypeTestConfig: + feature_dtype: str + feature_is_list: bool + has_empty_list: bool + + +def get_feast_type(feature_dtype: str, feature_is_list: bool) -> FeastType: + dtype: Optional[FeastType] = None + if feature_is_list is True: + if feature_dtype == "int32": + dtype = Array(Int32) + elif feature_dtype == "int64": + dtype = Array(Int64) + elif feature_dtype == "float": + dtype = Array(Float32) + elif feature_dtype == "bool": + dtype = Array(Bool) + elif feature_dtype == "datetime": + dtype = Array(UnixTimestamp) + else: + if feature_dtype == "int32": + dtype = Int32 + elif feature_dtype == "int64": + dtype = Int64 + elif feature_dtype == "float": + dtype = Float32 + elif feature_dtype == "bool": + dtype = Bool + elif feature_dtype == "datetime": + dtype = UnixTimestamp + assert dtype + return dtype + + +def populate_test_configs(): + feature_dtypes = [ + "int32", + "int64", + "float", + "bool", + "datetime", + ] + configs: List[TypeTestConfig] = [] + for feature_dtype in feature_dtypes: + for feature_is_list in [True, False]: + for has_empty_list in [True, False]: + # For non list features `has_empty_list` does nothing + if feature_is_list is False and has_empty_list is True: + continue + + configs.append( + TypeTestConfig( + feature_dtype=feature_dtype, + feature_is_list=feature_is_list, + has_empty_list=has_empty_list, + ) + ) + return configs + + +def get_type_test_fixtures(request, environment): + config: TypeTestConfig = request.param + # Lower case needed because Redshift lower-cases all table names + destination_name = ( + f"feature_type_{config.feature_dtype}{config.feature_is_list}".replace( + ".", "" + ).lower() + ) + df = create_basic_driver_dataset( + Int64, + config.feature_dtype, + config.feature_is_list, + config.has_empty_list, + ) + data_source = environment.data_source_creator.create_data_source( + df, + destination_name=destination_name, + field_mapping={"ts_1": "ts"}, + ) + fv = driver_feature_view( + data_source=data_source, + name=destination_name, + dtype=get_feast_type(config.feature_dtype, config.feature_is_list), + ) + + return config, data_source, fv diff --git a/skills/SKILL.md b/skills/SKILL.md new file mode 100644 index 00000000000..8be173257ac --- /dev/null +++ b/skills/SKILL.md @@ -0,0 +1,253 @@ +--- +name: feast-user-guide +description: Guide for working with Feast (Feature Store) — defining features, configuring feature_store.yaml, retrieving features online/offline, using the CLI, and building RAG retrieval pipelines. Use when the user asks about creating entities, feature views, on-demand feature views, stream feature views, feature services, data sources, feature_store.yaml configuration, feast apply/materialize commands, online or historical feature retrieval, or vector-based document retrieval with Feast. +license: Apache-2.0 +compatibility: Works with Claude Code, OpenAI Codex, and any Agent Skills compatible tool. +metadata: + author: feast-dev + version: "1.0" +--- + +# Feast User Guide + +## Quick Start + +A Feast project requires: +1. A `feature_store.yaml` config file +2. Python files defining entities, data sources, feature views, and feature services +3. Running `feast apply` to register definitions + +```bash +feast init my_project +cd my_project +feast apply +``` + +## Core Concepts + +### Entity +An entity is a collection of semantically related features (e.g., a customer, a driver). Entities have join keys used to look up features. + +```python +from feast import Entity +from feast.value_type import ValueType + +driver = Entity( + name="driver_id", + description="Driver identifier", + value_type=ValueType.INT64, +) +``` + +### Data Sources +Data sources describe where raw feature data lives. + +```python +from feast import FileSource, BigQuerySource, KafkaSource, PushSource, RequestSource +from feast.data_format import ParquetFormat + +# Batch source (file) +driver_stats_source = FileSource( + name="driver_stats_source", + path="data/driver_stats.parquet", + timestamp_field="event_timestamp", + created_timestamp_column="created", +) + +# Request source (for on-demand features) +input_request = RequestSource( + name="vals_to_add", + schema=[Field(name="val_to_add", dtype=Float64)], +) +``` + +### FeatureView +Maps features from a data source to entities with a schema, TTL, and online/offline settings. + +```python +from feast import FeatureView, Field +from feast.types import Float32, Int64, String +from datetime import timedelta + +driver_hourly_stats = FeatureView( + name="driver_hourly_stats", + entities=[driver], + ttl=timedelta(days=365), + schema=[ + Field(name="conv_rate", dtype=Float32), + Field(name="acc_rate", dtype=Float32), + Field(name="avg_daily_trips", dtype=Int64), + ], + online=True, + source=driver_stats_source, +) +``` + +### OnDemandFeatureView +Computes features at request time from other feature views and/or request data. + +```python +from feast import on_demand_feature_view +import pandas as pd + +@on_demand_feature_view( + sources=[driver_hourly_stats, input_request], + schema=[Field(name="conv_rate_plus_val", dtype=Float64)], + mode="pandas", +) +def transformed_conv_rate(inputs: pd.DataFrame) -> pd.DataFrame: + df = pd.DataFrame() + df["conv_rate_plus_val"] = inputs["conv_rate"] + inputs["val_to_add"] + return df +``` + +### FeatureService +Groups features from multiple views for retrieval. + +```python +from feast import FeatureService + +driver_fs = FeatureService( + name="driver_ranking", + features=[driver_hourly_stats, transformed_conv_rate], +) +``` + +## Feature Retrieval + +### Online (low-latency) +```python +from feast import FeatureStore + +store = FeatureStore(repo_path=".") + +features = store.get_online_features( + features=[ + "driver_hourly_stats:conv_rate", + "driver_hourly_stats:acc_rate", + ], + entity_rows=[{"driver_id": 1001}, {"driver_id": 1002}], +).to_dict() +``` + +### Historical (training data with point-in-time joins) +```python +entity_df = pd.DataFrame({ + "driver_id": [1001, 1002], + "event_timestamp": [datetime(2023, 1, 1), datetime(2023, 1, 2)], +}) + +training_df = store.get_historical_features( + entity_df=entity_df, + features=["driver_hourly_stats:conv_rate", "driver_hourly_stats:acc_rate"], +).to_df() +``` + +Or use a FeatureService: +```python +training_df = store.get_historical_features( + entity_df=entity_df, + features=driver_fs, +).to_df() +``` + +## Materialization + +Load features from offline store into online store: + +```bash +# Full materialization over a time range +feast materialize 2023-01-01T00:00:00 2023-12-31T23:59:59 + +# Incremental (from last materialized timestamp) +feast materialize-incremental $(date -u +"%Y-%m-%dT%H:%M:%S") +``` + +Python API: +```python +from datetime import datetime +store.materialize(start_date=datetime(2023, 1, 1), end_date=datetime(2023, 12, 31)) +store.materialize_incremental(end_date=datetime.utcnow()) +``` + +## CLI Commands + +| Command | Purpose | +|---------|---------| +| `feast init [DIR]` | Create new feature repository | +| `feast apply` | Register/update feature definitions | +| `feast plan` | Preview changes without applying | +| `feast materialize START END` | Materialize features to online store | +| `feast materialize-incremental END` | Incremental materialization | +| `feast entities list` | List registered entities | +| `feast feature-views list` | List feature views | +| `feast feature-services list` | List feature services | +| `feast on-demand-feature-views list` | List on-demand feature views | +| `feast teardown` | Remove infrastructure resources | +| `feast version` | Show SDK version | + +Options: `--chdir` / `-c` (run in different directory), `--feature-store-yaml` / `-f` (override config path). + +## Vector Search / RAG + +Define a feature view with vector fields for similarity search: + +```python +from feast.types import Array, Float32 + +wiki_passages = FeatureView( + name="wiki_passages", + entities=[passage_entity], + schema=[ + Field(name="passage_text", dtype=String), + Field( + name="embedding", + dtype=Array(Float32), + vector_index=True, + vector_length=384, + vector_search_metric="COSINE", + ), + ], + source=passages_source, + online=True, +) +``` + +Retrieve similar documents: +```python +results = store.retrieve_online_documents( + feature="wiki_passages:embedding", + query=query_embedding, + top_k=5, +) +``` + +## feature_store.yaml Minimal Config + +```yaml +project: my_project +registry: data/registry.db +provider: local +online_store: + type: sqlite + path: data/online_store.db +``` + +## Common Imports + +```python +from feast import ( + Entity, FeatureView, OnDemandFeatureView, FeatureService, + Field, FileSource, RequestSource, FeatureStore, +) +from feast.on_demand_feature_view import on_demand_feature_view +from feast.types import Float32, Float64, Int64, String, Bool, Array +from feast.value_type import ValueType +from datetime import timedelta +``` + +## Detailed References + +- **Feature definitions** (all types, parameters, patterns): See [references/feature-definitions.md](references/feature-definitions.md) +- **Configuration** (feature_store.yaml, all store types, auth): See [references/configuration.md](references/configuration.md) +- **Retrieval & RAG** (online/offline retrieval, vector search, RAG retriever): See [references/retrieval-and-rag.md](references/retrieval-and-rag.md) diff --git a/skills/feast-dev/SKILL.md b/skills/feast-dev/SKILL.md new file mode 100644 index 00000000000..475854c0674 --- /dev/null +++ b/skills/feast-dev/SKILL.md @@ -0,0 +1,106 @@ +--- +name: feast-dev +description: Development guide for contributing to the Feast codebase. Covers environment setup, testing, linting, project structure, and PR workflow for feast-dev/feast. +license: Apache-2.0 +compatibility: Works with Claude Code, OpenAI Codex, and any Agent Skills compatible tool. Requires Python 3.10+, uv, and git. +metadata: + author: feast-dev + version: "1.0" +--- + +# Feast Development Guide + +## Environment Setup + +```bash +# Install development dependencies (uses uv pip sync with pinned requirements) +make install-python-dependencies-dev + +# Install minimal dependencies +make install-python-dependencies-minimal + +# Install pre-commit hooks (runs formatters and linters on commit) +make install-precommit +``` + +## Running Tests + +### Unit Tests +```bash +# Run all unit tests +make test-python-unit + +# Run a specific test file +python -m pytest sdk/python/tests/unit/test_unit_feature_store.py -v + +# Run a specific test by name +python -m pytest sdk/python/tests/unit/test_unit_feature_store.py -k "test_apply" -v + +# Run fast unit tests only (no external dependencies) +make test-python-unit-fast +``` + +### Integration Tests (local) +```bash +# Run integration tests in local dev mode +make test-python-integration-local +``` + +## Linting and Formatting + +```bash +# Format Python code +make format-python + +# Lint Python code +make lint-python + +# Run all precommit checks (format + lint) +make precommit-check + +# Type checking +cd sdk/python && python -m mypy feast +``` + +## Code Style + +- Use type hints on all function signatures +- Use `from __future__ import annotations` at the top of new files +- Follow existing patterns in the module you are modifying +- PR titles must follow semantic conventions: `feat:`, `fix:`, `ci:`, `chore:`, `docs:` +- Add a GitHub label to PRs (e.g. `kind/bug`, `kind/feature`, `kind/housekeeping`) +- Sign off commits with `git commit -s` (DCO requirement) + +## Documentation and Blog Posts + +- **Blog posts must be placed in `/infra/website/docs/blog/`** — do NOT place them under `docs/blog/` or elsewhere. +- Blog post files must include YAML frontmatter with `title`, `description`, `date`, and `authors` fields matching the format of existing posts in that directory. +- All other reference documentation (concepts, how-tos, reference pages) goes under `docs/`. + +## Project Structure + +``` +sdk/python/feast/ # Main Python SDK + cli/cli.py # CLI entry point (feast apply, feast materialize, etc.) + feature_store.py # FeatureStore class - core orchestration + repo_config.py # feature_store.yaml configuration parsing + repo_operations.py # feast apply / feast teardown logic + infra/ # Online/offline store implementations + online_stores/ # Redis, DynamoDB, SQLite, etc. + offline_stores/ # BigQuery, Snowflake, File, etc. + transformation/ # On-demand and streaming transformations +protos/feast/ # Protobuf definitions +sdk/python/tests/ # Test suite + unit/ # Fast, no external deps + integration/ # Requires infrastructure +``` + +## Key Abstractions + +- **FeatureStore** (`feature_store.py`): Entry point for all operations +- **FeatureView**: Defines a set of features from a data source +- **OnDemandFeatureView**: Computed features using request-time transformations +- **Entity**: Join key definition (e.g. driver_id, customer_id) +- **DataSource**: Where raw data lives (BigQuery, files, Snowflake, etc.) +- **OnlineStore**: Low-latency feature serving (Redis, DynamoDB, SQLite) +- **OfflineStore**: Historical feature retrieval (BigQuery, Snowflake, file) diff --git a/skills/references/configuration.md b/skills/references/configuration.md new file mode 100644 index 00000000000..9a1720984b1 --- /dev/null +++ b/skills/references/configuration.md @@ -0,0 +1,284 @@ +# Configuration Reference + +## Table of Contents +- [feature_store.yaml](#feature_storeyaml) +- [RepoConfig Fields](#repoconfig-fields) +- [Registry Configuration](#registry-configuration) +- [Online Store Types](#online-store-types) +- [Offline Store Types](#offline-store-types) +- [Batch Engine Types](#batch-engine-types) +- [Authentication](#authentication) +- [Feature Server](#feature-server) +- [Materialization Config](#materialization-config) +- [OpenLineage Config](#openlineage-config) +- [Feature Repository Layout](#feature-repository-layout) + +## feature_store.yaml + +Minimal local config: +```yaml +project: my_project +registry: data/registry.db +provider: local +online_store: + type: sqlite + path: data/online_store.db +``` + +GCP config: +```yaml +project: my_project +registry: gs://my-bucket/registry.pb +provider: gcp +online_store: + type: datastore +offline_store: + type: bigquery +``` + +AWS config: +```yaml +project: my_project +registry: s3://my-bucket/registry.pb +provider: aws +online_store: + type: dynamodb + region: us-east-1 +offline_store: + type: redshift + cluster_id: my-cluster + region: us-east-1 + database: feast + user: admin + s3_staging_location: s3://my-bucket/feast-staging +``` + +## RepoConfig Fields + +| Field | Alias | Type | Default | Description | +|-------|-------|------|---------|-------------| +| `project` | - | str | required | Project namespace (alphanumeric + underscores) | +| `project_description` | - | str | None | Project description | +| `provider` | - | str | `"local"` | `"local"`, `"gcp"`, or `"aws"` | +| `registry` | `registry_config` | str/dict | required | Registry path or config object | +| `online_store` | `online_config` | str/dict | `"sqlite"` | Online store type or config | +| `offline_store` | `offline_config` | str/dict | `"dask"` | Offline store type or config | +| `batch_engine` | `batch_engine_config` | str/dict | `"local"` | Batch materialization engine | +| `auth` | - | dict | no_auth | Authentication config | +| `feature_server` | - | dict | None | Feature server config | +| `entity_key_serialization_version` | - | int | 3 | Entity key serialization version | +| `coerce_tz_aware` | - | bool | True | Coerce timestamps to timezone-aware | +| `materialization` | `materialization_config` | dict | default | Materialization options | +| `openlineage` | `openlineage_config` | dict | None | OpenLineage config | + +## Registry Configuration + +| Field | Default | Description | +|-------|---------|-------------| +| `registry_type` | `"file"` | `"file"`, `"sql"`, `"snowflake.registry"`, `"remote"` | +| `path` | `""` | Local path, GCS/S3 URI (file), or DB connection URL (sql) | +| `cache_ttl_seconds` | 600 | Registry cache TTL (0 = no expiry) | +| `cache_mode` | `"sync"` | `"sync"` or `"thread"` | +| `s3_additional_kwargs` | None | Extra boto3 kwargs for S3 | + +### File registry +```yaml +registry: data/registry.db +``` +or +```yaml +registry: + registry_type: file + path: data/registry.db + cache_ttl_seconds: 60 +``` + +### SQL registry +```yaml +registry: + registry_type: sql + path: postgresql://user:pass@host:5432/feast # pragma: allowlist secret + cache_ttl_seconds: 60 +``` + +### Remote registry +```yaml +registry: + registry_type: remote + path: grpc://feast-registry-server:6570 +``` + +## Online Store Types + +| Type | Config Key | Use Case | +|------|-----------|----------| +| `sqlite` | `path` | Local development | +| `redis` | `connection_string` | Production, low-latency | +| `dynamodb` | `region` | AWS-native | +| `datastore` | `project_id` | GCP-native | +| `bigtable` | `project_id`, `instance` | GCP, high-throughput | +| `postgres` | `host`, `port`, `database`, `user`, `password` | Self-managed | +| `snowflake.online` | `account`, `database`, `schema` | Snowflake ecosystem | +| `milvus` | `host`, `port` | Vector search | +| `qdrant` | `host`, `port` | Vector search | +| `remote` | `path` | Remote feature server | + +### Examples + +```yaml +# SQLite (local dev) +online_store: + type: sqlite + path: data/online_store.db + +# Redis +online_store: + type: redis + connection_string: redis://localhost:6379 + +# PostgreSQL +online_store: + type: postgres + host: localhost + port: 5432 + database: feast + db_schema: public + user: postgres + password: secret + +# Milvus (vector search) +online_store: + type: milvus + host: localhost + port: 19530 +``` + +## Offline Store Types + +| Type | Use Case | +|------|----------| +| `dask` | Local development (default) | +| `duckdb` | Local, fast analytics | +| `bigquery` | GCP | +| `snowflake.offline` | Snowflake | +| `redshift` | AWS | +| `spark` | Large-scale processing | +| `postgres` | Self-managed | +| `trino` | Federated queries | +| `athena` | AWS serverless | +| `clickhouse` | Analytics | +| `remote` | Remote offline server | + +### Examples + +```yaml +# DuckDB +offline_store: + type: duckdb + +# BigQuery +offline_store: + type: bigquery + project_id: my-gcp-project + dataset: feast_dataset + +# Snowflake +offline_store: + type: snowflake.offline + account: my_account + user: user + password: pass + database: FEAST + schema: PUBLIC + warehouse: COMPUTE_WH + +# Spark +offline_store: + type: spark + spark_conf: + spark.master: "local[*]" +``` + +## Batch Engine Types + +| Type | Description | +|------|-------------| +| `local` | Local Python process (default) | +| `snowflake.engine` | Snowflake-based materialization | +| `spark.engine` | Spark-based materialization | +| `lambda` | AWS Lambda-based | +| `k8s` | Kubernetes job-based | +| `ray.engine` | Ray-based | + +```yaml +batch_engine: + type: local +``` + +## Authentication + +| Type | Description | +|------|-------------| +| `no_auth` | No authentication (default) | +| `kubernetes` | Kubernetes service account | +| `oidc` | OpenID Connect (server-side) | +| `oidc_client` | OpenID Connect (client-side) | + +```yaml +# OIDC example +auth: + type: oidc + client_id: feast-client + auth_server_url: https://auth.example.com + auth_discovery_url: https://auth.example.com/.well-known/openid-configuration +``` + +## Feature Server + +```yaml +feature_server: + type: local +``` + +MCP-based feature server: +```yaml +feature_server: + type: mcp +``` + +## Materialization Config + +```yaml +materialization: + pull_latest_features: false # Only pull latest feature values per entity +``` + +## OpenLineage Config + +```yaml +openlineage: + enabled: true + transport_type: http # http, console, file, kafka + transport_url: http://marquez:5000 + transport_endpoint: api/v1/lineage + namespace: feast + emit_on_apply: true + emit_on_materialize: true +``` + +## Feature Repository Layout + +``` +my_feature_repo/ +├── feature_store.yaml # Required config +├── .feastignore # Optional gitignore-style file +├── driver_features.py # Feature definitions +├── customer_features.py # More definitions +└── data/ + ├── driver_stats.parquet # Data files (for FileSource) + └── registry.db # Auto-generated registry +``` + +- Feast recursively scans all `.py` files for feature definitions +- Use `.feastignore` to exclude files/directories from scanning +- `feast apply` registers all discovered definitions into the registry diff --git a/skills/references/feature-definitions.md b/skills/references/feature-definitions.md new file mode 100644 index 00000000000..dc6764e94c7 --- /dev/null +++ b/skills/references/feature-definitions.md @@ -0,0 +1,350 @@ +# Feature Definitions Reference + +## Table of Contents +- [Entity](#entity) +- [Field](#field) +- [Data Sources](#data-sources) +- [FeatureView](#featureview) +- [OnDemandFeatureView](#ondemandfeatureview) +- [StreamFeatureView](#streamfeatureview) +- [FeatureService](#featureservice) +- [Aggregation](#aggregation) + +## Entity + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `name` | str | required | Unique entity name | +| `join_keys` | List[str] | `[name]` | Join keys for lookup (only one supported) | +| `value_type` | ValueType | - | Deprecated; use `join_keys` instead | +| `description` | str | `""` | Human-readable description | +| `tags` | Dict[str,str] | `{}` | Metadata tags | +| `owner` | str | `""` | Owner/maintainer | + +```python +from feast import Entity +from feast.value_type import ValueType + +driver = Entity(name="driver_id", description="Driver identifier") +customer = Entity(name="customer_id", join_keys=["customer_id"]) +``` + +## Field + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `name` | str | required | Field name | +| `dtype` | FeastType | required | Data type | +| `description` | str | `""` | Description | +| `vector_index` | bool | False | Enable vector similarity search | +| `vector_length` | int | - | Vector dimension (required if `vector_index=True`) | +| `vector_search_metric` | str | - | `"COSINE"`, `"L2"`, `"INNER_PRODUCT"` | + +### Type System + +**Scalar types** (from `feast.types`): `Float32`, `Float64`, `Int32`, `Int64`, `String`, `Bool`, `Bytes`, `UnixTimestamp` + +**Collection types**: `Array(T)` where T is a scalar type (e.g., `Array(Float32)` for embeddings) + +**ValueType enum** (legacy, from `feast.value_type`): `STRING`, `INT32`, `INT64`, `FLOAT`, `DOUBLE`, `BOOL`, `BYTES`, `UNIX_TIMESTAMP`; plus `_LIST` and `_SET` variants. + +**Python → Feast mapping**: `int` → INT64, `str` → STRING, `float` → DOUBLE, `bytes` → BYTES, `bool` → BOOL, `datetime` → UNIX_TIMESTAMP + +### Vector field example + +```python +Field( + name="embedding", + dtype=Array(Float32), + vector_index=True, + vector_length=384, + vector_search_metric="COSINE", +) +``` + +## Data Sources + +### Batch Sources + +**FileSource**: +```python +from feast import FileSource + +source = FileSource( + name="driver_stats", + path="data/driver_stats.parquet", + timestamp_field="event_timestamp", + created_timestamp_column="created", +) +``` + +**BigQuerySource**: +```python +from feast.infra.offline_stores.contrib.bigquery_offline_store.bigquery_source import BigQuerySource + +source = BigQuerySource( + name="driver_stats_bq", + table="project.dataset.driver_stats", + timestamp_field="event_timestamp", +) +``` + +Other batch sources: `SnowflakeSource`, `RedshiftSource`, `PostgreSQLSource`, `SparkSource`, `TrinoSource`, `AthenaSource`, `ClickhouseSource` + +### Stream Sources + +**KafkaSource**: +```python +from feast.data_source import KafkaSource + +source = KafkaSource( + name="driver_trips_stream", + kafka_bootstrap_servers="broker:9092", + topic="driver_trips", + timestamp_field="event_timestamp", + batch_source=file_source, # for backfill + message_format=AvroFormat(schema_json=schema), +) +``` + +**KinesisSource**: `region`, `stream_name`, `record_format`, `batch_source` + +**PushSource** (for manual push via SDK): +```python +from feast.data_source import PushSource + +push_source = PushSource(name="driver_push", batch_source=file_source) +``` + +### RequestSource (for OnDemandFeatureView) + +```python +from feast import RequestSource, Field +from feast.types import Float64 + +input_request = RequestSource( + name="vals_to_add", + schema=[Field(name="val_to_add", dtype=Float64)], +) +``` + +## FeatureView + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `name` | str | required | Unique name | +| `source` | DataSource | required | Batch or stream data source | +| `entities` | List[Entity] | `[]` | Associated entities | +| `schema` | List[Field] | `[]` | Feature schema (can be inferred from source) | +| `ttl` | timedelta | `timedelta(0)` | Time-to-live for features | +| `online` | bool | `True` | Available for online retrieval | +| `offline` | bool | `False` | Available for offline retrieval | +| `description` | str | `""` | Description | +| `tags` | Dict[str,str] | `{}` | Metadata | +| `owner` | str | `""` | Owner | +| `mode` | str | - | Transformation mode: `"python"`, `"pandas"`, `"sql"`, `"spark"`, `"ray"`, `"substrait"` | + +```python +from feast import FeatureView, Field +from feast.types import Float32, Int64 +from datetime import timedelta + +driver_hourly_stats = FeatureView( + name="driver_hourly_stats", + entities=[driver], + ttl=timedelta(days=365), + schema=[ + Field(name="conv_rate", dtype=Float32), + Field(name="acc_rate", dtype=Float32), + Field(name="avg_daily_trips", dtype=Int64), + ], + online=True, + source=driver_stats_source, +) +``` + +## OnDemandFeatureView + +Features computed at request time from other feature views and/or request data. + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `name` | str | required | Unique name | +| `sources` | List | required | Input FeatureViews and/or RequestSources | +| `schema` | List[Field] | required | Output schema | +| `mode` | str | `"pandas"` | `"pandas"` or `"python"` | +| `singleton` | bool | `False` | Single-row dict input (mode="python" only) | +| `write_to_online_store` | bool | `False` | Precompute on write instead of read | +| `aggregations` | List[Aggregation] | `[]` | Pre-transformation aggregations | + +### Pandas mode (default) + +```python +@on_demand_feature_view( + sources=[driver_hourly_stats, input_request], + schema=[Field(name="conv_rate_plus_val", dtype=Float64)], + mode="pandas", +) +def transformed_conv_rate(inputs: pd.DataFrame) -> pd.DataFrame: + df = pd.DataFrame() + df["conv_rate_plus_val"] = inputs["conv_rate"] + inputs["val_to_add"] + return df +``` + +### Python mode + +```python +@on_demand_feature_view( + sources=[driver_hourly_stats], + schema=[Field(name="conv_rate_category", dtype=String)], + mode="python", +) +def categorize_conv_rate(inputs: dict) -> dict: + output = {"conv_rate_category": []} + for rate in inputs["conv_rate"]: + output["conv_rate_category"].append("high" if rate > 0.5 else "low") + return output +``` + +### Python singleton mode + +```python +@on_demand_feature_view( + sources=[driver_hourly_stats], + schema=[Field(name="conv_rate_category", dtype=String)], + mode="python", + singleton=True, +) +def categorize_conv_rate(inputs: dict) -> dict: + rate = inputs["conv_rate"] + return {"conv_rate_category": "high" if rate > 0.5 else "low"} +``` + +### Write-to-online-store mode + +```python +@on_demand_feature_view( + sources=[push_source], + schema=[Field(name="trips_today_category", dtype=String)], + write_to_online_store=True, +) +def categorize_trips(inputs: pd.DataFrame) -> pd.DataFrame: + df = pd.DataFrame() + df["trips_today_category"] = inputs["trips_today"].apply( + lambda x: "high" if x > 10 else "low" + ) + return df +``` + +### Aggregation-based ODFV + +```python +from feast.aggregation import Aggregation + +@on_demand_feature_view( + sources=[driver_hourly_stats], + schema=[Field(name="sum_trips", dtype=Int64)], + aggregations=[Aggregation(column="avg_daily_trips", function="sum")], +) +def agg_view(inputs: pd.DataFrame) -> pd.DataFrame: + return inputs +``` + +### Validation note + +Use `feast apply --skip-feature-view-validation` if ODFV validation fails with complex logic (validation uses random inputs). + +## StreamFeatureView + +Extends FeatureView for stream sources (Kafka, Kinesis, PushSource). + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `name` | str | required | Unique name | +| `source` | DataSource | required | KafkaSource, KinesisSource, or PushSource | +| `entities` | List[Entity] | `[]` | Entities | +| `schema` | List[Field] | `[]` | Schema | +| `ttl` | timedelta | `timedelta(0)` | TTL | +| `aggregations` | List[Aggregation] | `[]` | Windowed aggregations | +| `timestamp_field` | str | - | Required if using aggregations | +| `udf` | function | - | Transformation function | +| `mode` | str | - | `"python"`, `"pandas"`, `"spark"`, `"spark_sql"` | + +```python +from feast import StreamFeatureView, Field +from feast.types import Int64 +from feast.aggregation import Aggregation +from datetime import timedelta + +driver_stream = StreamFeatureView( + name="driver_trips_stream", + entities=[driver], + source=kafka_source, + schema=[Field(name="trips", dtype=Int64)], + ttl=timedelta(hours=2), + aggregations=[ + Aggregation(column="trips", function="count", time_window=timedelta(hours=1)), + ], + timestamp_field="event_timestamp", +) +``` + +## FeatureService + +Groups features from one or more feature views for retrieval. + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `name` | str | required | Unique name | +| `features` | List | required | Feature views or projections | +| `description` | str | `""` | Description | +| `tags` | Dict[str,str] | `{}` | Metadata | +| `owner` | str | `""` | Owner | +| `logging_config` | LoggingConfig | - | Logging configuration | + +```python +from feast import FeatureService + +driver_activity_service = FeatureService( + name="driver_activity", + features=[ + driver_hourly_stats, + transformed_conv_rate, + ], + description="Features for driver activity model", +) +``` + +### Feature projections (select specific features) + +```python +driver_fs = FeatureService( + name="driver_ranking", + features=[ + driver_hourly_stats[["conv_rate", "acc_rate"]], + ], +) +``` + +## Aggregation + +For StreamFeatureView windowed aggregations. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `column` | str | Source column name | +| `function` | str | `"sum"`, `"max"`, `"min"`, `"count"`, `"mean"` | +| `time_window` | timedelta | Aggregation window | +| `slide_interval` | timedelta | Slide interval (for sliding windows) | + +```python +from feast.aggregation import Aggregation +from datetime import timedelta + +agg = Aggregation( + column="trips", + function="count", + time_window=timedelta(hours=1), + slide_interval=timedelta(minutes=5), +) +``` diff --git a/skills/references/retrieval-and-rag.md b/skills/references/retrieval-and-rag.md new file mode 100644 index 00000000000..8198134e5bc --- /dev/null +++ b/skills/references/retrieval-and-rag.md @@ -0,0 +1,287 @@ +# Retrieval & RAG Reference + +## Table of Contents +- [FeatureStore Construction](#featurestore-construction) +- [Online Feature Retrieval](#online-feature-retrieval) +- [Historical Feature Retrieval](#historical-feature-retrieval) +- [Push and Write Operations](#push-and-write-operations) +- [Vector Similarity Search](#vector-similarity-search) +- [RAG Retriever](#rag-retriever) +- [FeatureStore API Quick Reference](#featurestore-api-quick-reference) + +## FeatureStore Construction + +```python +from feast import FeatureStore + +# From repo path (looks for feature_store.yaml) +store = FeatureStore(repo_path="path/to/feature_repo") + +# From config object +from feast.repo_config import RepoConfig +store = FeatureStore(config=RepoConfig( + project="my_project", + registry="data/registry.db", + provider="local", + online_store={"type": "sqlite", "path": "data/online.db"}, +)) + +# From explicit YAML path +from pathlib import Path +store = FeatureStore(fs_yaml_file=Path("custom/feature_store.yaml")) +``` + +## Online Feature Retrieval + +Low-latency lookup from the online store. Features must be materialized first. + +### By feature references +```python +result = store.get_online_features( + features=[ + "driver_hourly_stats:conv_rate", + "driver_hourly_stats:acc_rate", + "driver_hourly_stats:avg_daily_trips", + ], + entity_rows=[ + {"driver_id": 1001}, + {"driver_id": 1002}, + ], +) + +feature_dict = result.to_dict() +feature_df = result.to_df() +``` + +### By FeatureService +```python +result = store.get_online_features( + features=driver_ranking_service, + entity_rows=[{"driver_id": 1001}], +) +``` + +### Feature reference format +`"feature_view_name:feature_name"` — e.g., `"driver_hourly_stats:conv_rate"` + +## Historical Feature Retrieval + +Point-in-time correct joins for training data. Prevents data leakage by joining features based on event timestamps. + +### Basic usage +```python +import pandas as pd +from datetime import datetime + +entity_df = pd.DataFrame({ + "driver_id": [1001, 1002, 1003], + "event_timestamp": [ + datetime(2023, 6, 1), + datetime(2023, 6, 15), + datetime(2023, 7, 1), + ], +}) + +training_df = store.get_historical_features( + entity_df=entity_df, + features=[ + "driver_hourly_stats:conv_rate", + "driver_hourly_stats:acc_rate", + ], +).to_df() +``` + +### With FeatureService +```python +training_df = store.get_historical_features( + entity_df=entity_df, + features=driver_ranking_service, +).to_df() +``` + +### Output +Returns a `RetrievalJob` with methods: +- `.to_df()` — pandas DataFrame +- `.to_arrow()` — PyArrow Table +- `.to_sql_string()` — SQL query (for SQL-based offline stores) + +## Push and Write Operations + +### Push (for PushSource/StreamFeatureView) +```python +store.push( + push_source_name="driver_push", + df=pd.DataFrame({ + "driver_id": [1001], + "trips_today": [15], + "event_timestamp": [datetime.utcnow()], + }), +) +``` + +### Write to online store +```python +store.write_to_online_store( + feature_view_name="driver_hourly_stats", + df=features_df, +) +``` + +### Write to offline store +```python +store.write_to_offline_store( + feature_view_name="driver_hourly_stats", + df=features_df, +) +``` + +## Vector Similarity Search + +Requires a FeatureView with a `vector_index=True` field and an online store that supports vector search (e.g., Milvus, Qdrant, PostgreSQL with pgvector). + +### Define vector feature view +```python +from feast import Entity, FeatureView, Field, FileSource +from feast.types import Array, Float32, String + +passage_entity = Entity(name="passage_id", join_keys=["passage_id"]) + +wiki_passages = FeatureView( + name="wiki_passages", + entities=[passage_entity], + schema=[ + Field(name="passage_text", dtype=String), + Field( + name="embedding", + dtype=Array(Float32), + vector_index=True, + vector_length=384, + vector_search_metric="COSINE", + ), + ], + source=passages_source, + online=True, +) +``` + +### Retrieve similar documents +```python +# v1 API +results = store.retrieve_online_documents( + feature="wiki_passages:embedding", + query=query_embedding_vector, + top_k=5, +) + +# v2 API (supports text, vector, and image queries) +results = store.retrieve_online_documents_v2( + feature_view_name="wiki_passages", + query_string="What is machine learning?", + top_k=5, +) +``` + +### Search metrics +- `"COSINE"` — Cosine similarity (default, best for normalized embeddings) +- `"L2"` — Euclidean distance +- `"INNER_PRODUCT"` — Dot product + +## RAG Retriever + +`FeastRAGRetriever` integrates Feast with HuggingFace for retrieval-augmented generation. + +### Prerequisites +- A FeatureView with a `vector_index=True` embedding field +- Features materialized to the online store +- HuggingFace `transformers` installed + +### Setup +```python +from feast.rag_retriever import FeastRAGRetriever +from transformers import AutoTokenizer, AutoModel, AutoModelForSeq2SeqLM + +question_tokenizer = AutoTokenizer.from_pretrained("facebook/dpr-question_encoder-single-nq-base") +question_encoder = AutoModel.from_pretrained("facebook/dpr-question_encoder-single-nq-base") +generator_tokenizer = AutoTokenizer.from_pretrained("facebook/bart-large") +generator_model = AutoModelForSeq2SeqLM.from_pretrained("facebook/bart-large") + +retriever = FeastRAGRetriever( + question_encoder_tokenizer=question_tokenizer, + question_encoder=question_encoder, + generator_tokenizer=generator_tokenizer, + generator_model=generator_model, + feast_repo_path="path/to/feature_repo", + feature_view="wiki_passages", + features=["passage_text", "embedding"], + search_type="vector", # "text", "vector", or "hybrid" + id_field="passage_id", + text_field="passage_text", +) +``` + +### Retrieve documents +```python +doc_embeddings, doc_ids, doc_dicts = retriever.retrieve( + question_input_ids=question_tokenizer("What is ML?", return_tensors="pt")["input_ids"], + n_docs=5, +) +``` + +### End-to-end answer generation +```python +answer = retriever.generate_answer( + query="What is machine learning?", + top_k=5, + max_new_tokens=200, +) +print(answer) +``` + +### FeastVectorStore (lower-level) + +```python +from feast.vector_store import FeastVectorStore + +vector_store = FeastVectorStore(feast_repo_path="path/to/feature_repo") + +results = vector_store.query( + query_vector=embedding_list, + top_k=10, +) +``` + +Supports `query_vector`, `query_string`, and `query_image_bytes` for different search modalities. + +## FeatureStore API Quick Reference + +| Method | Purpose | +|--------|---------| +| `apply(objects)` | Register entities, FVs, ODFVs, SFVs, services, sources | +| `plan(desired_registry)` | Preview apply changes | +| `get_online_features(features, entity_rows)` | Low-latency online lookup | +| `get_historical_features(entity_df, features)` | Point-in-time training data | +| `materialize(start_date, end_date)` | Load offline → online store | +| `materialize_incremental(end_date)` | Incremental materialization | +| `push(push_source_name, df)` | Push data to online/offline store | +| `write_to_online_store(fv_name, df)` | Direct write to online store | +| `write_to_offline_store(fv_name, df)` | Direct write to offline store | +| `retrieve_online_documents(feature, query, top_k)` | Vector similarity search | +| `retrieve_online_documents_v2(...)` | Vector search v2 (text/vector/image) | +| `list_entities()` | List all entities | +| `list_feature_views()` | List all feature views | +| `list_on_demand_feature_views()` | List on-demand feature views | +| `list_stream_feature_views()` | List stream feature views | +| `list_feature_services()` | List feature services | +| `list_data_sources()` | List data sources | +| `get_entity(name)` | Get entity by name | +| `get_feature_view(name)` | Get feature view by name | +| `get_feature_service(name)` | Get feature service by name | +| `delete_feature_view(name)` | Delete a feature view | +| `delete_feature_service(name)` | Delete a feature service | +| `create_saved_dataset(...)` | Save a dataset for reuse | +| `refresh_registry()` | Force refresh registry cache | +| `teardown()` | Remove all infrastructure resources | +| `serve(port)` | Start feature server | +| `serve_ui(port)` | Start Feast UI | +| `serve_registry(port)` | Start registry server | +| `serve_offline(port)` | Start offline server | diff --git a/ui/feature_repo/apply_permissions.py b/ui/feature_repo/apply_permissions.py index b7d39733634..4a62b8de9c3 100644 --- a/ui/feature_repo/apply_permissions.py +++ b/ui/feature_repo/apply_permissions.py @@ -11,15 +11,17 @@ store = FeatureStore(repo_path=".") -store.apply([ - zipcode_features_permission, - zipcode_source_permission, - model_v1_permission, - risky_features_permission, - document_embeddings_permission, - document_metadata_permission, - rag_model_permission, -]) +store.apply( + [ + zipcode_features_permission, + zipcode_source_permission, + model_v1_permission, + risky_features_permission, + document_embeddings_permission, + document_metadata_permission, + rag_model_permission, + ] +) print("Permissions applied successfully!") print("Current permissions:", store.list_permissions()) diff --git a/ui/feature_repo/apply_rag_data.py b/ui/feature_repo/apply_rag_data.py index 67d000f9d6c..be20dab38ab 100644 --- a/ui/feature_repo/apply_rag_data.py +++ b/ui/feature_repo/apply_rag_data.py @@ -5,28 +5,32 @@ now = datetime.now() embeddings = [] for i in range(10): - embeddings.append({ - 'document_id': f'doc_{i}', - 'embedding': np.random.rand(768).astype(np.float32), - 'event_timestamp': now - timedelta(days=i), - 'created_timestamp': now - timedelta(days=i, hours=1) - }) + embeddings.append( + { + "document_id": f"doc_{i}", + "embedding": np.random.rand(768).astype(np.float32), + "event_timestamp": now - timedelta(days=i), + "created_timestamp": now - timedelta(days=i, hours=1), + } + ) df_embeddings = pd.DataFrame(embeddings) -df_embeddings.to_parquet('data/document_embeddings.parquet', index=False) +df_embeddings.to_parquet("data/document_embeddings.parquet", index=False) metadata = [] for i in range(10): - metadata.append({ - 'document_id': f'doc_{i}', - 'title': f'Document {i}', - 'content': f'This is the content of document {i}', - 'source': 'web', - 'author': f'author_{i}', - 'publish_date': (now - timedelta(days=i*30)).strftime('%Y-%m-%d'), - 'event_timestamp': now - timedelta(days=i), - 'created_timestamp': now - timedelta(days=i, hours=1) - }) + metadata.append( + { + "document_id": f"doc_{i}", + "title": f"Document {i}", + "content": f"This is the content of document {i}", + "source": "web", + "author": f"author_{i}", + "publish_date": (now - timedelta(days=i * 30)).strftime("%Y-%m-%d"), + "event_timestamp": now - timedelta(days=i), + "created_timestamp": now - timedelta(days=i, hours=1), + } + ) df_metadata = pd.DataFrame(metadata) -df_metadata.to_parquet('data/document_metadata.parquet', index=False) +df_metadata.to_parquet("data/document_metadata.parquet", index=False) -print('Created RAG data files successfully!') +print("Created RAG data files successfully!") diff --git a/ui/feature_repo/features.py b/ui/feature_repo/features.py index 102dec74c7b..1c6854e257a 100644 --- a/ui/feature_repo/features.py +++ b/ui/feature_repo/features.py @@ -1,7 +1,6 @@ from datetime import timedelta import pandas as pd -import numpy as np from feast import Entity, FeatureService, FeatureView, Field, FileSource from feast.data_source import RequestSource @@ -139,6 +138,7 @@ ], ) + # Define an on demand feature view which can generate new features based on # existing feature views and RequestSource features @on_demand_feature_view( @@ -306,6 +306,7 @@ def transaction_gt_last_credit_card_due(inputs: pd.DataFrame) -> pd.DataFrame: ], ) + # Define an on-demand feature view for similarity calculation @on_demand_feature_view( sources=[document_embeddings_view, query_request], @@ -319,6 +320,7 @@ def document_similarity(inputs: pd.DataFrame) -> pd.DataFrame: df["similarity_score"] = 0.95 # Placeholder value return df + rag_model = FeatureService( name="rag_retriever", features=[ diff --git a/ui/package.json b/ui/package.json index 910ca25c2dd..4faafffe731 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,6 +1,6 @@ { "name": "@feast-dev/feast-ui", - "version": "0.60.0", + "version": "0.62.0", "private": false, "files": [ "dist" diff --git a/ui/public/projects-list.json b/ui/public/projects-list.json index 238df4b5b41..4868adf6d88 100644 --- a/ui/public/projects-list.json +++ b/ui/public/projects-list.json @@ -3,7 +3,7 @@ { "name": "Credit Score Project", "description": "Project for credit scoring team and associated models.", - "id": "credit_score_project", + "id": "credit_scoring_aws", "registryPath": "/registry.db" }, { diff --git a/ui/public/registry.db b/ui/public/registry.db index ae9a05a4a97..0c16e405ccb 100644 Binary files a/ui/public/registry.db and b/ui/public/registry.db differ diff --git a/ui/src/components/RegistryVisualization.test.tsx b/ui/src/components/RegistryVisualization.test.tsx new file mode 100644 index 00000000000..01da8f415a3 --- /dev/null +++ b/ui/src/components/RegistryVisualization.test.tsx @@ -0,0 +1,372 @@ +import React from "react"; +import { render, screen, within } from "../test-utils"; +import { waitFor } from "@testing-library/react"; +import RegistryVisualization from "./RegistryVisualization"; +import { feast } from "../protos"; +import { FEAST_FCO_TYPES } from "../parsers/types"; +import { EntityRelation } from "../parsers/parseEntityRelationships"; +import { ThemeProvider } from "../contexts/ThemeContext"; + +// ReactFlow requires ResizeObserver +class ResizeObserverMock { + observe() {} + unobserve() {} + disconnect() {} +} +(global as any).ResizeObserver = ResizeObserverMock; + +// Helper to build minimal registry data +const makeRegistry = ( + overrides: Partial = {}, +): feast.core.Registry => { + return feast.core.Registry.create({ + featureViews: [], + onDemandFeatureViews: [], + streamFeatureViews: [], + featureServices: [], + entities: [], + dataSources: [], + ...overrides, + }); +}; + +const makeRelationship = ( + sourceName: string, + sourceType: FEAST_FCO_TYPES, + targetName: string, + targetType: FEAST_FCO_TYPES, +): EntityRelation => ({ + source: { name: sourceName, type: sourceType }, + target: { name: targetName, type: targetType }, +}); + +const renderVisualization = ( + registryData: feast.core.Registry, + relationships: EntityRelation[] = [], + indirectRelationships: EntityRelation[] = [], +) => { + return render( + + + , + ); +}; + +describe("RegistryVisualization version indicators", () => { + test("renders version badge on feature view with currentVersionNumber > 1", async () => { + const registry = makeRegistry({ + featureViews: [ + feast.core.FeatureView.create({ + spec: { name: "my_feature_view" }, + meta: { currentVersionNumber: 3 }, + }), + ], + entities: [ + feast.core.Entity.create({ + spec: { name: "my_entity" }, + }), + ], + }); + + const relationships = [ + makeRelationship( + "my_feature_view", + FEAST_FCO_TYPES.featureView, + "my_entity", + FEAST_FCO_TYPES.entity, + ), + ]; + + renderVisualization(registry, relationships); + + await waitFor(() => { + expect(screen.getByText("v3")).toBeInTheDocument(); + }); + }); + + test("does not render version badge when currentVersionNumber is 0", async () => { + const registry = makeRegistry({ + featureViews: [ + feast.core.FeatureView.create({ + spec: { name: "unversioned_fv" }, + meta: { currentVersionNumber: 0 }, + }), + ], + entities: [ + feast.core.Entity.create({ + spec: { name: "my_entity" }, + }), + ], + }); + + const relationships = [ + makeRelationship( + "unversioned_fv", + FEAST_FCO_TYPES.featureView, + "my_entity", + FEAST_FCO_TYPES.entity, + ), + ]; + + renderVisualization(registry, relationships); + + await waitFor(() => { + expect(screen.getByText("unversioned_fv")).toBeInTheDocument(); + }); + + expect(screen.queryByText("v0")).not.toBeInTheDocument(); + }); + + test("does not render version badge when currentVersionNumber is 1 (initial version)", async () => { + const registry = makeRegistry({ + featureViews: [ + feast.core.FeatureView.create({ + spec: { name: "initial_fv" }, + meta: { currentVersionNumber: 1 }, + }), + ], + entities: [ + feast.core.Entity.create({ + spec: { name: "my_entity" }, + }), + ], + }); + + const relationships = [ + makeRelationship( + "initial_fv", + FEAST_FCO_TYPES.featureView, + "my_entity", + FEAST_FCO_TYPES.entity, + ), + ]; + + renderVisualization(registry, relationships); + + await waitFor(() => { + expect(screen.getByText("initial_fv")).toBeInTheDocument(); + }); + + expect(screen.queryByText("v1")).not.toBeInTheDocument(); + }); + + test("does not render version badge when meta has no version", async () => { + const registry = makeRegistry({ + featureViews: [ + feast.core.FeatureView.create({ + spec: { name: "no_version_fv" }, + meta: {}, + }), + ], + entities: [ + feast.core.Entity.create({ + spec: { name: "my_entity" }, + }), + ], + }); + + const relationships = [ + makeRelationship( + "no_version_fv", + FEAST_FCO_TYPES.featureView, + "my_entity", + FEAST_FCO_TYPES.entity, + ), + ]; + + renderVisualization(registry, relationships); + + await waitFor(() => { + expect(screen.getByText("no_version_fv")).toBeInTheDocument(); + }); + + // No version badges should exist at all + const badges = screen.queryAllByText(/^v\d+$/); + expect(badges).toHaveLength(0); + }); + + test("renders version badge on on-demand feature view", async () => { + const registry = makeRegistry({ + featureViews: [ + feast.core.FeatureView.create({ + spec: { name: "regular_fv" }, + }), + ], + onDemandFeatureViews: [ + feast.core.OnDemandFeatureView.create({ + spec: { name: "odfv_versioned" }, + meta: { currentVersionNumber: 2 }, + }), + ], + entities: [ + feast.core.Entity.create({ + spec: { name: "my_entity" }, + }), + ], + }); + + // Connect regular FV to entity so nodes render, and ODFV to regular FV + const relationships = [ + makeRelationship( + "regular_fv", + FEAST_FCO_TYPES.featureView, + "my_entity", + FEAST_FCO_TYPES.entity, + ), + ]; + + // Use the full component and toggle isolated nodes to show ODFV + render( + + + , + ); + + // Enable isolated nodes to show the ODFV + const isolatedCheckbox = screen.getByLabelText( + /Show Objects Without Relationships/i, + ); + isolatedCheckbox.click(); + + await waitFor(() => { + expect(screen.getByText("v2")).toBeInTheDocument(); + }); + }); + + test("renders version badge on stream feature view", async () => { + const registry = makeRegistry({ + featureViews: [ + feast.core.FeatureView.create({ + spec: { name: "regular_fv" }, + }), + ], + streamFeatureViews: [ + feast.core.StreamFeatureView.create({ + spec: { name: "sfv_versioned" }, + meta: { currentVersionNumber: 5 }, + }), + ], + entities: [ + feast.core.Entity.create({ + spec: { name: "my_entity" }, + }), + ], + }); + + const relationships = [ + makeRelationship( + "regular_fv", + FEAST_FCO_TYPES.featureView, + "my_entity", + FEAST_FCO_TYPES.entity, + ), + ]; + + render( + + + , + ); + + // Enable isolated nodes to show the SFV + const isolatedCheckbox = screen.getByLabelText( + /Show Objects Without Relationships/i, + ); + isolatedCheckbox.click(); + + await waitFor(() => { + expect(screen.getByText("v5")).toBeInTheDocument(); + }); + }); + + test("renders version history info from featureViewVersionHistory", async () => { + const registry = makeRegistry({ + featureViews: [ + feast.core.FeatureView.create({ + spec: { name: "versioned_fv" }, + meta: { currentVersionNumber: 2 }, + }), + ], + entities: [ + feast.core.Entity.create({ + spec: { name: "my_entity" }, + }), + ], + featureViewVersionHistory: feast.core.FeatureViewVersionHistory.create({ + records: [ + feast.core.FeatureViewVersionRecord.create({ + featureViewName: "versioned_fv", + versionNumber: 1, + description: "Initial version", + }), + feast.core.FeatureViewVersionRecord.create({ + featureViewName: "versioned_fv", + versionNumber: 2, + description: "Added new features", + }), + ], + }), + }); + + const relationships = [ + makeRelationship( + "versioned_fv", + FEAST_FCO_TYPES.featureView, + "my_entity", + FEAST_FCO_TYPES.entity, + ), + ]; + + renderVisualization(registry, relationships); + + await waitFor(() => { + expect(screen.getByText("v2")).toBeInTheDocument(); + }); + }); +}); + +describe("RegistryVisualization legend", () => { + test("renders Version Changed entry in legend", async () => { + const registry = makeRegistry({ + featureViews: [ + feast.core.FeatureView.create({ + spec: { name: "some_fv" }, + }), + ], + entities: [ + feast.core.Entity.create({ + spec: { name: "some_entity" }, + }), + ], + }); + + const relationships = [ + makeRelationship( + "some_fv", + FEAST_FCO_TYPES.featureView, + "some_entity", + FEAST_FCO_TYPES.entity, + ), + ]; + + renderVisualization(registry, relationships); + + await waitFor(() => { + expect(screen.getByText("Version Changed")).toBeInTheDocument(); + }); + + expect(screen.getByText("vN")).toBeInTheDocument(); + }); +}); diff --git a/ui/src/components/RegistryVisualization.tsx b/ui/src/components/RegistryVisualization.tsx index 64dc9f5f9b2..d3479078618 100644 --- a/ui/src/components/RegistryVisualization.tsx +++ b/ui/src/components/RegistryVisualization.tsx @@ -21,6 +21,7 @@ import { EuiSpacer, EuiLoadingSpinner, EuiToolTip, + EuiBadge, } from "@elastic/eui"; import { FEAST_FCO_TYPES } from "../parsers/types"; import { EntityRelation } from "../parsers/parseEntityRelationships"; @@ -64,6 +65,8 @@ interface NodeData { type: FEAST_FCO_TYPES; metadata: any; permissions?: any[]; // Add permissions field + versionNumber?: number; + versionInfo?: { totalVersions: number; latestDescription?: string }; } const getNodeColor = (type: FEAST_FCO_TYPES) => { @@ -119,6 +122,7 @@ const CustomNode = ({ data }: { data: NodeData }) => { const icon = getNodeIcon(data.type); const [isHovered, setIsHovered] = useState(false); const hasPermissions = data.permissions && data.permissions.length > 0; + const hasVersion = data.versionNumber != null && data.versionNumber > 1; const handleClick = () => { let path; @@ -207,6 +211,40 @@ const CustomNode = ({ data }: { data: NodeData }) => { )} + {/* Version indicator */} + {hasVersion && ( + +
Version: {data.versionNumber}
+ {data.versionInfo && ( + <> +
Total versions: {data.versionInfo.totalVersions}
+ {data.versionInfo.latestDescription && ( +
Latest: {data.versionInfo.latestDescription}
+ )} + + )} +
+ Click node for full history +
+ + } + > +
+ v{data.versionNumber} +
+
+ )} + {
{item.label}
))} +
+ + vN + +
Version Changed
+
); }; @@ -482,10 +534,42 @@ const registryToFlow = ( objects: feast.core.Registry, relationships: EntityRelation[], permissions?: any[], + versionHistory?: feast.core.IFeatureViewVersionRecord[], ) => { const nodes: Node[] = []; const edges: Edge[] = []; + // Build a lookup of version info by feature view name + const versionInfoMap = new Map< + string, + { totalVersions: number; latestDescription?: string } + >(); + if (versionHistory) { + const grouped: Record = {}; + for (let i = 0; i < versionHistory.length; i++) { + const record = versionHistory[i]; + const name = record.featureViewName; + if (!name) continue; + if (!grouped[name]) grouped[name] = []; + grouped[name].push(record); + } + const groupedNames = Object.keys(grouped); + for (let i = 0; i < groupedNames.length; i++) { + const name = groupedNames[i]; + const records = grouped[name]; + records.sort( + ( + a: feast.core.IFeatureViewVersionRecord, + b: feast.core.IFeatureViewVersionRecord, + ) => (b.versionNumber ?? 0) - (a.versionNumber ?? 0), + ); + versionInfoMap.set(name, { + totalVersions: records.length, + latestDescription: records[0]?.description ?? undefined, + }); + } + } + objects.featureServices?.forEach((fs) => { nodes.push({ id: `fs-${fs.spec?.name}`, @@ -507,60 +591,69 @@ const registryToFlow = ( }); objects.featureViews?.forEach((fv) => { + const fvName = fv.spec?.name; nodes.push({ - id: `fv-${fv.spec?.name}`, + id: `fv-${fvName}`, type: "custom", data: { - label: fv.spec?.name, + label: fvName, type: FEAST_FCO_TYPES.featureView, metadata: fv, permissions: permissions ? getEntityPermissions( permissions, FEAST_FCO_TYPES.featureView, - fv.spec?.name, + fvName, ) : [], + versionNumber: fv.meta?.currentVersionNumber ?? undefined, + versionInfo: fvName ? versionInfoMap.get(fvName) : undefined, }, position: { x: 0, y: 0 }, }); }); objects.onDemandFeatureViews?.forEach((odfv) => { + const odfvName = odfv.spec?.name; nodes.push({ - id: `odfv-${odfv.spec?.name}`, + id: `odfv-${odfvName}`, type: "custom", data: { - label: odfv.spec?.name, + label: odfvName, type: FEAST_FCO_TYPES.featureView, metadata: odfv, permissions: permissions ? getEntityPermissions( permissions, FEAST_FCO_TYPES.featureView, - odfv.spec?.name, + odfvName, ) : [], + versionNumber: odfv.meta?.currentVersionNumber ?? undefined, + versionInfo: odfvName ? versionInfoMap.get(odfvName) : undefined, }, position: { x: 0, y: 0 }, }); }); objects.streamFeatureViews?.forEach((sfv) => { + const sfvName = sfv.spec?.name; nodes.push({ - id: `sfv-${sfv.spec?.name}`, + id: `sfv-${sfvName}`, type: "custom", data: { - label: sfv.spec?.name, + label: sfvName, type: FEAST_FCO_TYPES.featureView, metadata: sfv, permissions: permissions ? getEntityPermissions( permissions, FEAST_FCO_TYPES.featureView, - sfv.spec?.name, + sfvName, ) : [], + versionNumber: sfv.meta?.currentVersionNumber ?? undefined, + versionInfo: sfvName ? versionInfoMap.get(sfvName) : undefined, }, position: { x: 0, y: 0 }, }); @@ -750,10 +843,14 @@ const RegistryVisualization: React.FC = ({ return rel.source && rel.target && rel.source.name && rel.target.name; }); + const versionRecords = + registryData.featureViewVersionHistory?.records ?? undefined; + const { nodes: initialNodes, edges: initialEdges } = registryToFlow( registryData, validRelationships, permissions, + versionRecords as feast.core.IFeatureViewVersionRecord[] | undefined, ); const { nodes: layoutedNodes, edges: layoutedEdges } = @@ -775,6 +872,7 @@ const RegistryVisualization: React.FC = ({ showIndirectRelationships, showIsolatedNodes, filterNode, + permissions, setNodes, setEdges, ]); diff --git a/ui/src/pages/feature-views/CurlGeneratorTab.tsx b/ui/src/pages/feature-views/CurlGeneratorTab.tsx index 147921458ee..5c83440a2a0 100644 --- a/ui/src/pages/feature-views/CurlGeneratorTab.tsx +++ b/ui/src/pages/feature-views/CurlGeneratorTab.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from "react"; +import React, { useState } from "react"; import { EuiPanel, EuiTitle, @@ -16,23 +16,22 @@ import { import { CodeBlock, github } from "react-code-blocks"; import { RegularFeatureViewCustomTabProps } from "../../custom-tabs/types"; +const defaultServerUrl = + process.env.REACT_APP_FEAST_FEATURE_SERVER_URL || "http://localhost:6566"; + const CurlGeneratorTab = ({ feastObjectQuery, }: RegularFeatureViewCustomTabProps) => { const data = feastObjectQuery.data as any; const [serverUrl, setServerUrl] = useState(() => { const savedUrl = localStorage.getItem("feast-feature-server-url"); - return savedUrl || "http://localhost:6566"; + return savedUrl || defaultServerUrl; }); const [entityValues, setEntityValues] = useState>({}); const [selectedFeatures, setSelectedFeatures] = useState< Record >({}); - useEffect(() => { - localStorage.setItem("feast-feature-server-url", serverUrl); - }, [serverUrl]); - if (feastObjectQuery.isLoading) { return Loading...; } @@ -106,8 +105,12 @@ const CurlGeneratorTab = ({ setServerUrl(e.target.value)} - placeholder="http://localhost:6566" + onChange={(e) => { + const nextValue = e.target.value; + setServerUrl(nextValue); + localStorage.setItem("feast-feature-server-url", nextValue); + }} + placeholder={defaultServerUrl} /> diff --git a/ui/src/pages/feature-views/FeatureViewListingTable.tsx b/ui/src/pages/feature-views/FeatureViewListingTable.tsx index e865abe6e74..7537f8122c9 100644 --- a/ui/src/pages/feature-views/FeatureViewListingTable.tsx +++ b/ui/src/pages/feature-views/FeatureViewListingTable.tsx @@ -49,6 +49,13 @@ const FeatureViewListingTable = ({ return features.length; }, }, + { + name: "Version", + render: (item: genericFVType) => { + const ver = (item.object as any)?.meta?.currentVersionNumber; + return ver != null && ver > 0 ? `v${ver}` : "—"; + }, + }, ]; // Add Project column when viewing all projects diff --git a/ui/src/pages/feature-views/FeatureViewVersionsTab.tsx b/ui/src/pages/feature-views/FeatureViewVersionsTab.tsx new file mode 100644 index 00000000000..1e5e44d6804 --- /dev/null +++ b/ui/src/pages/feature-views/FeatureViewVersionsTab.tsx @@ -0,0 +1,256 @@ +import React, { useContext, useState, useMemo } from "react"; +import { + EuiBasicTable, + EuiText, + EuiPanel, + EuiTitle, + EuiHorizontalRule, + EuiCodeBlock, + EuiSpacer, + EuiFlexGroup, + EuiFlexItem, + EuiBadge, +} from "@elastic/eui"; +import RegistryPathContext from "../../contexts/RegistryPathContext"; +import useLoadRegistry from "../../queries/useLoadRegistry"; +import { feast } from "../../protos"; +import { toDate } from "../../utils/timestamp"; +import { useParams } from "react-router-dom"; + +interface FeatureViewVersionsTabProps { + featureViewName: string; +} + +interface DecodedVersion { + record: feast.core.IFeatureViewVersionRecord; + features: feast.core.IFeatureSpecV2[]; + entities: string[]; + description: string; + udfBody: string | null; +} + +const decodeVersionProto = ( + record: feast.core.IFeatureViewVersionRecord, +): DecodedVersion => { + const result: DecodedVersion = { + record, + features: [], + entities: [], + description: "", + udfBody: null, + }; + + if (!record.featureViewProto || record.featureViewProto.length === 0) { + return result; + } + + try { + const bytes = + record.featureViewProto instanceof Uint8Array + ? record.featureViewProto + : new Uint8Array(record.featureViewProto); + + if (record.featureViewType === "on_demand_feature_view") { + const odfv = feast.core.OnDemandFeatureView.decode(bytes); + result.features = odfv.spec?.features || []; + result.description = odfv.spec?.description || ""; + result.udfBody = + odfv.spec?.featureTransformation?.userDefinedFunction?.bodyText || + odfv.spec?.userDefinedFunction?.bodyText || + null; + } else if (record.featureViewType === "stream_feature_view") { + const sfv = feast.core.StreamFeatureView.decode(bytes); + result.features = sfv.spec?.features || []; + result.entities = sfv.spec?.entities || []; + result.description = sfv.spec?.description || ""; + } else { + const fv = feast.core.FeatureView.decode(bytes); + result.features = fv.spec?.features || []; + result.entities = fv.spec?.entities || []; + result.description = fv.spec?.description || ""; + } + } catch (e) { + console.error("Failed to decode version proto:", e); + } + + return result; +}; + +const VersionDetail = ({ decoded }: { decoded: DecodedVersion }) => { + return ( + + {decoded.description && ( + + + {decoded.description} + + + )} + {decoded.udfBody && ( + + + +

Transformation

+
+ + + {decoded.udfBody} + +
+
+ )} + + + + +

Features ({decoded.features.length})

+
+ + {decoded.features.length > 0 ? ( + + feast.types.ValueType.Enum[vt], + }, + ]} + /> + ) : ( + No features in this version. + )} +
+
+ {decoded.entities.length > 0 && ( + + + +

Entities

+
+ + + {decoded.entities.map((entity) => ( + + {entity} + + ))} + +
+
+ )} +
+
+ ); +}; + +const FeatureViewVersionsTab = ({ + featureViewName, +}: FeatureViewVersionsTabProps) => { + const registryUrl = useContext(RegistryPathContext); + const { projectName } = useParams(); + 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 decodedVersions = useMemo( + () => records.map(decodeVersionProto), + [records], + ); + + if (records.length === 0) { + return No version history for this feature view.; + } + + const toggleRow = (versionNumber: number) => { + setExpandedRows((prev) => ({ + ...prev, + [versionNumber]: !prev[versionNumber], + })); + }; + + const columns = [ + { + field: "record.versionNumber", + name: "Version", + render: (_: unknown, item: DecodedVersion) => + `v${item.record.versionNumber}`, + sortable: true, + width: "80px", + }, + { + name: "Features", + render: (item: DecodedVersion) => `${item.features.length}`, + width: "80px", + }, + { + field: "record.featureViewType", + name: "Type", + render: (_: unknown, item: DecodedVersion) => + item.record.featureViewType || "—", + }, + { + field: "record.createdTimestamp", + name: "Created", + render: (_: unknown, item: DecodedVersion) => + item.record.createdTimestamp + ? toDate(item.record.createdTimestamp).toLocaleString() + : "—", + }, + { + field: "record.versionId", + name: "Version ID", + render: (_: unknown, item: DecodedVersion) => + item.record.versionId || "—", + }, + ]; + + const itemIdToExpandedRowMap: Record = {}; + decodedVersions.forEach((decoded) => { + const vn = decoded.record.versionNumber!; + if (expandedRows[vn]) { + itemIdToExpandedRowMap[String(vn)] = ; + } + }); + + return ( + String(item.record.versionNumber)} + itemIdToExpandedRowMap={itemIdToExpandedRowMap} + columns={[ + { + isExpander: true, + width: "40px", + render: (item: DecodedVersion) => { + const vn = item.record.versionNumber!; + return ( + + ); + }, + }, + ...columns, + ]} + /> + ); +}; + +export default FeatureViewVersionsTab; diff --git a/ui/src/pages/feature-views/OnDemandFeatureViewInstance.tsx b/ui/src/pages/feature-views/OnDemandFeatureViewInstance.tsx index 5a4b48f6d6d..70824219aaa 100644 --- a/ui/src/pages/feature-views/OnDemandFeatureViewInstance.tsx +++ b/ui/src/pages/feature-views/OnDemandFeatureViewInstance.tsx @@ -1,11 +1,12 @@ import React from "react"; import { Route, Routes, useNavigate } from "react-router-dom"; import { useParams } from "react-router-dom"; -import { EuiPageTemplate } from "@elastic/eui"; +import { EuiBadge, EuiPageTemplate } from "@elastic/eui"; import { FeatureViewIcon } from "../../graphics/FeatureViewIcon"; -import { useMatchExact } from "../../hooks/useMatchSubpath"; +import { useMatchExact, useMatchSubpath } from "../../hooks/useMatchSubpath"; import OnDemandFeatureViewOverviewTab from "./OnDemandFeatureViewOverviewTab"; +import FeatureViewVersionsTab from "./FeatureViewVersionsTab"; import { useOnDemandFeatureViewCustomTabs, @@ -29,7 +30,17 @@ const OnDemandFeatureInstance = ({ data }: OnDemandFeatureInstanceProps) => { + {featureViewName} + {data?.meta?.currentVersionNumber != null && + data.meta.currentVersionNumber > 0 && ( + + v{data.meta.currentVersionNumber} + + )} + + } tabs={[ { label: "Overview", @@ -38,6 +49,13 @@ const OnDemandFeatureInstance = ({ data }: OnDemandFeatureInstanceProps) => { navigate(""); }, }, + { + label: "Versions", + isSelected: useMatchSubpath("versions"), + onClick: () => { + navigate("versions"); + }, + }, ...customNavigationTabs, ]} /> @@ -47,6 +65,12 @@ const OnDemandFeatureInstance = ({ data }: OnDemandFeatureInstanceProps) => { path="/" element={} /> + + } + /> {CustomTabRoutes} diff --git a/ui/src/pages/feature-views/RegularFeatureViewInstance.tsx b/ui/src/pages/feature-views/RegularFeatureViewInstance.tsx index 48d61e45f8f..a3c831b315f 100644 --- a/ui/src/pages/feature-views/RegularFeatureViewInstance.tsx +++ b/ui/src/pages/feature-views/RegularFeatureViewInstance.tsx @@ -1,12 +1,13 @@ import React, { useContext } from "react"; import { Route, Routes, useNavigate } from "react-router-dom"; -import { EuiPageTemplate } from "@elastic/eui"; +import { EuiBadge, EuiPageTemplate } from "@elastic/eui"; import { FeatureViewIcon } from "../../graphics/FeatureViewIcon"; import { useMatchExact, useMatchSubpath } from "../../hooks/useMatchSubpath"; import RegularFeatureViewOverviewTab from "./RegularFeatureViewOverviewTab"; import FeatureViewLineageTab from "./FeatureViewLineageTab"; +import FeatureViewVersionsTab from "./FeatureViewVersionsTab"; import { useRegularFeatureViewCustomTabs, @@ -57,6 +58,14 @@ const RegularFeatureInstance = ({ }); } + tabs.push({ + label: "Versions", + isSelected: useMatchSubpath("versions"), + onClick: () => { + navigate("versions"); + }, + }); + tabs.push(...customNavigationTabs); const TabRoutes = useRegularFeatureViewCustomTabRoutes(); @@ -66,7 +75,17 @@ const RegularFeatureInstance = ({ + {data?.spec?.name} + {data?.meta?.currentVersionNumber != null && + data.meta.currentVersionNumber > 0 && ( + + v{data.meta.currentVersionNumber} + + )} + + } tabs={tabs} /> @@ -84,6 +103,12 @@ const RegularFeatureInstance = ({ path="/lineage" element={} /> + + } + /> {TabRoutes} diff --git a/ui/src/pages/feature-views/StreamFeatureViewInstance.tsx b/ui/src/pages/feature-views/StreamFeatureViewInstance.tsx index 0e22a6c2e5d..c0b9627bca5 100644 --- a/ui/src/pages/feature-views/StreamFeatureViewInstance.tsx +++ b/ui/src/pages/feature-views/StreamFeatureViewInstance.tsx @@ -1,11 +1,12 @@ import React from "react"; import { Route, Routes, useNavigate } from "react-router-dom"; import { useParams } from "react-router-dom"; -import { EuiPageTemplate } from "@elastic/eui"; +import { EuiBadge, EuiPageTemplate } from "@elastic/eui"; import { FeatureViewIcon } from "../../graphics/FeatureViewIcon"; -import { useMatchExact } from "../../hooks/useMatchSubpath"; +import { useMatchExact, useMatchSubpath } from "../../hooks/useMatchSubpath"; import StreamFeatureViewOverviewTab from "./StreamFeatureViewOverviewTab"; +import FeatureViewVersionsTab from "./FeatureViewVersionsTab"; import { useStreamFeatureViewCustomTabs, @@ -30,7 +31,17 @@ const StreamFeatureInstance = ({ data }: StreamFeatureInstanceProps) => { restrictWidth paddingSize="l" iconType={FeatureViewIcon} - pageTitle={`${featureViewName}`} + pageTitle={ + <> + {featureViewName} + {data?.meta?.currentVersionNumber != null && + data.meta.currentVersionNumber > 0 && ( + + v{data.meta.currentVersionNumber} + + )} + + } tabs={[ { label: "Overview", @@ -39,6 +50,13 @@ const StreamFeatureInstance = ({ data }: StreamFeatureInstanceProps) => { navigate(""); }, }, + { + label: "Versions", + isSelected: useMatchSubpath("versions"), + onClick: () => { + navigate("versions"); + }, + }, ...customNavigationTabs, ]} /> @@ -48,6 +66,12 @@ const StreamFeatureInstance = ({ data }: StreamFeatureInstanceProps) => { path="/" element={} /> + + } + /> {CustomTabRoutes}