prefect-client 3.1.2__tar.gz → 3.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {prefect-client-3.1.2/src/prefect_client.egg-info → prefect-client-3.1.3}/PKG-INFO +1 -1
- {prefect-client-3.1.2 → prefect-client-3.1.3}/requirements-client.txt +2 -1
- {prefect-client-3.1.2 → prefect-client-3.1.3}/requirements.txt +0 -1
- prefect-client-3.1.3/src/prefect/_internal/compatibility/async_dispatch.py +63 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_version.py +3 -3
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/blocks/notifications.py +1 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/cache_policies.py +13 -2
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/client/schemas/objects.py +8 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/events/filters.py +13 -9
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/exceptions.py +4 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/flow_engine.py +56 -1
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/logging/handlers.py +5 -4
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/experiments.py +0 -5
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/telemetry/processors.py +2 -2
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/filesystem.py +35 -8
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/hashing.py +28 -7
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/urls.py +2 -2
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/workers/base.py +30 -20
- {prefect-client-3.1.2 → prefect-client-3.1.3/src/prefect_client.egg-info}/PKG-INFO +1 -1
- prefect-client-3.1.3/src/prefect_client.egg-info/dependency_links.txt +1 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect_client.egg-info/requires.txt +2 -1
- prefect-client-3.1.2/src/prefect/_internal/compatibility/async_dispatch.py +0 -73
- prefect-client-3.1.2/src/prefect/utilities/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/LICENSE +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/MANIFEST.in +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/README.md +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/requirements-dev.txt +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/setup.cfg +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/setup.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/.prefectignore +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/_logging.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/compatibility/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/compatibility/deprecated.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/compatibility/migration.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/concurrency/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/concurrency/api.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/concurrency/calls.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/concurrency/cancellation.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/concurrency/event_loop.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/concurrency/inspection.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/concurrency/primitives.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/concurrency/services.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/concurrency/threads.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/concurrency/waiters.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/integrations.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/pydantic/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/pydantic/annotations/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/pydantic/annotations/pendulum.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/pydantic/schemas.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/pydantic/v1_schema.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/pydantic/v2_schema.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/pydantic/v2_validated_func.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/pytz.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/retries.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/schemas/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/schemas/bases.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/schemas/fields.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/schemas/serializers.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/_internal/schemas/validators.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/agent.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/artifacts.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/automations.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/blocks/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/blocks/abstract.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/blocks/core.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/blocks/fields.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/blocks/redis.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/blocks/system.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/blocks/webhook.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/client/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/client/base.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/client/cloud.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/client/collections.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/client/constants.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/client/orchestration.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/client/schemas/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/client/schemas/actions.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/client/schemas/filters.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/client/schemas/responses.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/client/schemas/schedules.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/client/schemas/sorting.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/client/subscriptions.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/client/types/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/client/types/flexible_schedule_list.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/client/utilities.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/concurrency/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/concurrency/asyncio.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/concurrency/context.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/concurrency/events.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/concurrency/services.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/concurrency/sync.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/concurrency/v1/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/concurrency/v1/asyncio.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/concurrency/v1/context.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/concurrency/v1/events.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/concurrency/v1/services.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/concurrency/v1/sync.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/context.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/deployments/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/deployments/base.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/deployments/deployments.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/deployments/flow_runs.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/deployments/runner.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/deployments/schedules.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/deployments/steps/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/deployments/steps/core.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/deployments/steps/pull.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/deployments/steps/utility.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/docker/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/docker/docker_image.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/engine.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/events/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/events/actions.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/events/cli/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/events/cli/automations.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/events/clients.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/events/related.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/events/schemas/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/events/schemas/automations.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/events/schemas/deployment_triggers.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/events/schemas/events.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/events/schemas/labelling.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/events/utilities.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/events/worker.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/filesystems.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/flow_runs.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/flows.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/futures.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/infrastructure/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/infrastructure/base.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/infrastructure/provisioners/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/infrastructure/provisioners/cloud_run.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/infrastructure/provisioners/container_instance.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/infrastructure/provisioners/ecs.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/infrastructure/provisioners/modal.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/input/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/input/actions.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/input/run_input.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/locking/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/locking/filesystem.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/locking/memory.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/locking/protocol.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/logging/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/logging/configuration.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/logging/filters.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/logging/formatters.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/logging/highlighters.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/logging/loggers.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/logging/logging.yml +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/main.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/plugins.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/py.typed +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/records/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/records/base.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/records/filesystem.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/records/memory.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/records/result_store.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/results.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/runner/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/runner/runner.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/runner/server.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/runner/storage.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/runner/submit.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/runner/utils.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/runtime/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/runtime/deployment.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/runtime/flow_run.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/runtime/task_run.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/serializers.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/server/api/collections_data/views/aggregate-worker-metadata.json +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/server/api/static/prefect-logo-mark-gradient.png +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/base.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/constants.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/context.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/legacy.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/api.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/cli.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/client.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/cloud.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/deployments.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/flows.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/internal.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/logging.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/results.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/root.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/runner.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/server/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/server/api.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/server/database.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/server/deployments.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/server/ephemeral.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/server/events.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/server/flow_run_graph.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/server/root.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/server/services.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/server/tasks.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/server/ui.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/tasks.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/testing.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/models/worker.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/profiles.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/profiles.toml +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/settings/sources.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/states.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/task_engine.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/task_runners.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/task_runs.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/task_worker.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/tasks.py +0 -0
- /prefect-client-3.1.2/src/prefect_client.egg-info/dependency_links.txt → /prefect-client-3.1.3/src/prefect/telemetry/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/telemetry/bootstrap.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/telemetry/instrumentation.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/telemetry/logging.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/transactions.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/types/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/types/entrypoint.py +0 -0
- {prefect-client-3.1.2/src/prefect/telemetry → prefect-client-3.1.3/src/prefect/utilities}/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/annotations.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/asyncutils.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/callables.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/collections.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/compat.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/context.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/dispatch.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/dockerutils.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/engine.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/importtools.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/math.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/names.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/processutils.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/pydantic.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/render_swagger.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/schema_tools/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/schema_tools/hydration.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/schema_tools/validation.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/services.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/slugify.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/templating.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/text.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/timeout.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/utilities/visualization.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/variables.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/workers/__init__.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/workers/block.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/workers/cloud.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/workers/process.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/workers/server.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect/workers/utilities.py +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect_client.egg-info/SOURCES.txt +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/src/prefect_client.egg-info/top_level.txt +0 -0
- {prefect-client-3.1.2 → prefect-client-3.1.3}/versioneer.py +0 -0
@@ -3,7 +3,7 @@ asgi-lifespan >= 1.0, < 3.0
|
|
3
3
|
cachetools >= 5.3, < 6.0
|
4
4
|
cloudpickle >= 2.0, < 4.0
|
5
5
|
coolname >= 1.0.4, < 3.0.0
|
6
|
-
croniter >= 1.0.12, <
|
6
|
+
croniter >= 1.0.12, < 6.0.0
|
7
7
|
exceptiongroup >= 1.0.0
|
8
8
|
fastapi >= 0.111.0, < 1.0.0
|
9
9
|
fsspec >= 2022.5.0
|
@@ -14,6 +14,7 @@ httpx[http2] >= 0.23, != 0.23.2
|
|
14
14
|
importlib_metadata >= 4.4; python_version < '3.10'
|
15
15
|
jsonpatch >= 1.32, < 2.0
|
16
16
|
jsonschema >= 4.0.0, < 5.0.0
|
17
|
+
opentelemetry-api >= 1.27.0, < 2.0.0
|
17
18
|
orjson >= 3.7, < 4.0
|
18
19
|
packaging >= 21.3, < 24.3
|
19
20
|
pathspec >= 0.8.0
|
@@ -0,0 +1,63 @@
|
|
1
|
+
import asyncio
|
2
|
+
import inspect
|
3
|
+
from functools import wraps
|
4
|
+
from typing import Any, Callable, Coroutine, Optional, TypeVar, Union
|
5
|
+
|
6
|
+
from typing_extensions import ParamSpec
|
7
|
+
|
8
|
+
from prefect.tasks import Task
|
9
|
+
|
10
|
+
R = TypeVar("R")
|
11
|
+
P = ParamSpec("P")
|
12
|
+
|
13
|
+
|
14
|
+
def is_in_async_context() -> bool:
|
15
|
+
"""
|
16
|
+
Returns True if called from within an async context (coroutine or running event loop)
|
17
|
+
"""
|
18
|
+
try:
|
19
|
+
asyncio.get_running_loop()
|
20
|
+
return True
|
21
|
+
except RuntimeError:
|
22
|
+
return False
|
23
|
+
|
24
|
+
|
25
|
+
def _is_acceptable_callable(obj: Union[Callable, Task]) -> bool:
|
26
|
+
if inspect.iscoroutinefunction(obj):
|
27
|
+
return True
|
28
|
+
if isinstance(obj, Task) and inspect.iscoroutinefunction(obj.fn):
|
29
|
+
return True
|
30
|
+
return False
|
31
|
+
|
32
|
+
|
33
|
+
def async_dispatch(
|
34
|
+
async_impl: Callable[P, Coroutine[Any, Any, R]],
|
35
|
+
) -> Callable[[Callable[P, R]], Callable[P, Union[R, Coroutine[Any, Any, R]]]]:
|
36
|
+
"""
|
37
|
+
Decorator that dispatches to either sync or async implementation based on context.
|
38
|
+
|
39
|
+
Args:
|
40
|
+
async_impl: The async implementation to dispatch to when in async context
|
41
|
+
"""
|
42
|
+
|
43
|
+
def decorator(
|
44
|
+
sync_fn: Callable[P, R],
|
45
|
+
) -> Callable[P, Union[R, Coroutine[Any, Any, R]]]:
|
46
|
+
if not _is_acceptable_callable(async_impl):
|
47
|
+
raise TypeError("async_impl must be an async function")
|
48
|
+
|
49
|
+
@wraps(sync_fn)
|
50
|
+
def wrapper(
|
51
|
+
*args: P.args,
|
52
|
+
_sync: Optional[bool] = None, # type: ignore
|
53
|
+
**kwargs: P.kwargs,
|
54
|
+
) -> Union[R, Coroutine[Any, Any, R]]:
|
55
|
+
should_run_sync = _sync if _sync is not None else not is_in_async_context()
|
56
|
+
|
57
|
+
if should_run_sync:
|
58
|
+
return sync_fn(*args, **kwargs)
|
59
|
+
return async_impl(*args, **kwargs)
|
60
|
+
|
61
|
+
return wrapper # type: ignore
|
62
|
+
|
63
|
+
return decorator
|
@@ -8,11 +8,11 @@ import json
|
|
8
8
|
|
9
9
|
version_json = '''
|
10
10
|
{
|
11
|
-
"date": "2024-11-
|
11
|
+
"date": "2024-11-19T15:25:34-0600",
|
12
12
|
"dirty": true,
|
13
13
|
"error": null,
|
14
|
-
"full-revisionid": "
|
15
|
-
"version": "3.1.
|
14
|
+
"full-revisionid": "39b6028cea9f2b0437546ba13cc08bb3bf6d94a4",
|
15
|
+
"version": "3.1.3"
|
16
16
|
}
|
17
17
|
''' # END VERSION_JSON
|
18
18
|
|
@@ -7,6 +7,7 @@ from typing import TYPE_CHECKING, Any, Callable, Dict, List, Literal, Optional,
|
|
7
7
|
from typing_extensions import Self
|
8
8
|
|
9
9
|
from prefect.context import TaskRunContext
|
10
|
+
from prefect.exceptions import HashError
|
10
11
|
from prefect.utilities.hashing import hash_objects
|
11
12
|
|
12
13
|
if TYPE_CHECKING:
|
@@ -223,7 +224,6 @@ class TaskSource(CachePolicy):
|
|
223
224
|
lines = task_ctx.task.fn.__code__.co_code
|
224
225
|
else:
|
225
226
|
raise
|
226
|
-
|
227
227
|
return hash_objects(lines, raise_on_failure=True)
|
228
228
|
|
229
229
|
|
@@ -293,7 +293,18 @@ class Inputs(CachePolicy):
|
|
293
293
|
if key not in exclude:
|
294
294
|
hashed_inputs[key] = val
|
295
295
|
|
296
|
-
|
296
|
+
try:
|
297
|
+
return hash_objects(hashed_inputs, raise_on_failure=True)
|
298
|
+
except HashError as exc:
|
299
|
+
msg = (
|
300
|
+
f"{exc}\n\n"
|
301
|
+
"This often occurs when task inputs contain objects that cannot be cached "
|
302
|
+
"like locks, file handles, or other system resources.\n\n"
|
303
|
+
"To resolve this, you can:\n"
|
304
|
+
" 1. Exclude these arguments by defining a custom `cache_key_fn`\n"
|
305
|
+
" 2. Disable caching by passing `cache_policy=NONE`\n"
|
306
|
+
)
|
307
|
+
raise ValueError(msg) from exc
|
297
308
|
|
298
309
|
def __sub__(self, other: str) -> "CachePolicy":
|
299
310
|
if not isinstance(other, str):
|
@@ -497,6 +497,9 @@ class FlowRunPolicy(PrefectBaseModel):
|
|
497
497
|
resuming: Optional[bool] = Field(
|
498
498
|
default=False, description="Indicates if this run is resuming from a pause."
|
499
499
|
)
|
500
|
+
retry_type: Optional[Literal["in_process", "reschedule"]] = Field(
|
501
|
+
default=None, description="The type of retry this run is undergoing."
|
502
|
+
)
|
500
503
|
|
501
504
|
@model_validator(mode="before")
|
502
505
|
@classmethod
|
@@ -560,6 +563,11 @@ class FlowRun(ObjectBaseModel):
|
|
560
563
|
description="A list of tags on the flow run",
|
561
564
|
examples=[["tag-1", "tag-2"]],
|
562
565
|
)
|
566
|
+
labels: KeyValueLabels = Field(
|
567
|
+
default_factory=dict,
|
568
|
+
description="Prefect Cloud: A dictionary of key-value labels. Values can be strings, numbers, or booleans.",
|
569
|
+
examples=[{"key": "value1", "key2": 42}],
|
570
|
+
)
|
563
571
|
parent_task_run_id: Optional[UUID] = Field(
|
564
572
|
default=None,
|
565
573
|
description=(
|
@@ -83,17 +83,18 @@ class EventOccurredFilter(EventDataFilter):
|
|
83
83
|
|
84
84
|
class EventNameFilter(EventDataFilter):
|
85
85
|
prefix: Optional[List[str]] = Field(
|
86
|
-
None, description="Only include events matching one of these prefixes"
|
86
|
+
default=None, description="Only include events matching one of these prefixes"
|
87
87
|
)
|
88
88
|
exclude_prefix: Optional[List[str]] = Field(
|
89
|
-
None, description="Exclude events matching one of these prefixes"
|
89
|
+
default=None, description="Exclude events matching one of these prefixes"
|
90
90
|
)
|
91
91
|
|
92
92
|
name: Optional[List[str]] = Field(
|
93
|
-
None,
|
93
|
+
default=None,
|
94
|
+
description="Only include events matching one of these names exactly",
|
94
95
|
)
|
95
96
|
exclude_name: Optional[List[str]] = Field(
|
96
|
-
None, description="Exclude events matching one of these names exactly"
|
97
|
+
default=None, description="Exclude events matching one of these names exactly"
|
97
98
|
)
|
98
99
|
|
99
100
|
def includes(self, event: Event) -> bool:
|
@@ -230,17 +231,20 @@ class EventFilter(EventDataFilter):
|
|
230
231
|
description="Filter criteria for when the events occurred",
|
231
232
|
)
|
232
233
|
event: Optional[EventNameFilter] = Field(
|
233
|
-
None,
|
234
|
+
default=None,
|
234
235
|
description="Filter criteria for the event name",
|
235
236
|
)
|
236
237
|
any_resource: Optional[EventAnyResourceFilter] = Field(
|
237
|
-
None,
|
238
|
+
default=None,
|
239
|
+
description="Filter criteria for any resource involved in the event",
|
238
240
|
)
|
239
241
|
resource: Optional[EventResourceFilter] = Field(
|
240
|
-
None,
|
242
|
+
default=None,
|
243
|
+
description="Filter criteria for the resource of the event",
|
241
244
|
)
|
242
245
|
related: Optional[EventRelatedFilter] = Field(
|
243
|
-
None,
|
246
|
+
default=None,
|
247
|
+
description="Filter criteria for the related resources of the event",
|
244
248
|
)
|
245
249
|
id: EventIDFilter = Field(
|
246
250
|
default_factory=lambda: EventIDFilter(id=[]),
|
@@ -248,6 +252,6 @@ class EventFilter(EventDataFilter):
|
|
248
252
|
)
|
249
253
|
|
250
254
|
order: EventOrder = Field(
|
251
|
-
EventOrder.DESC,
|
255
|
+
default=EventOrder.DESC,
|
252
256
|
description="The order to return filtered events",
|
253
257
|
)
|
@@ -22,8 +22,11 @@ from typing import (
|
|
22
22
|
)
|
23
23
|
from uuid import UUID
|
24
24
|
|
25
|
+
from opentelemetry import trace
|
26
|
+
from opentelemetry.trace import Tracer, get_tracer
|
25
27
|
from typing_extensions import ParamSpec
|
26
28
|
|
29
|
+
import prefect
|
27
30
|
from prefect import Task
|
28
31
|
from prefect.client.orchestration import SyncPrefectClient, get_client
|
29
32
|
from prefect.client.schemas import FlowRun, TaskRun
|
@@ -124,6 +127,10 @@ class FlowRunEngine(Generic[P, R]):
|
|
124
127
|
_client: Optional[SyncPrefectClient] = None
|
125
128
|
short_circuit: bool = False
|
126
129
|
_flow_run_name_set: bool = False
|
130
|
+
_tracer: Tracer = field(
|
131
|
+
default_factory=lambda: get_tracer("prefect", prefect.__version__)
|
132
|
+
)
|
133
|
+
_span: Optional[trace.Span] = None
|
127
134
|
|
128
135
|
def __post_init__(self):
|
129
136
|
if self.flow is None and self.flow_run_id is None:
|
@@ -233,6 +240,17 @@ class FlowRunEngine(Generic[P, R]):
|
|
233
240
|
self.flow_run.state = state # type: ignore
|
234
241
|
self.flow_run.state_name = state.name # type: ignore
|
235
242
|
self.flow_run.state_type = state.type # type: ignore
|
243
|
+
|
244
|
+
if self._span:
|
245
|
+
self._span.add_event(
|
246
|
+
state.name,
|
247
|
+
{
|
248
|
+
"prefect.state.message": state.message or "",
|
249
|
+
"prefect.state.type": state.type,
|
250
|
+
"prefect.state.name": state.name or state.type,
|
251
|
+
"prefect.state.id": str(state.id),
|
252
|
+
},
|
253
|
+
)
|
236
254
|
return state
|
237
255
|
|
238
256
|
def result(self, raise_on_failure: bool = True) -> "Union[R, State, None]":
|
@@ -281,6 +299,9 @@ class FlowRunEngine(Generic[P, R]):
|
|
281
299
|
)
|
282
300
|
self.set_state(terminal_state)
|
283
301
|
self._return_value = resolved_result
|
302
|
+
|
303
|
+
self._end_span_on_success()
|
304
|
+
|
284
305
|
return result
|
285
306
|
|
286
307
|
def handle_exception(
|
@@ -311,6 +332,9 @@ class FlowRunEngine(Generic[P, R]):
|
|
311
332
|
)
|
312
333
|
state = self.set_state(Running())
|
313
334
|
self._raised = exc
|
335
|
+
|
336
|
+
self._end_span_on_error(exc, state.message)
|
337
|
+
|
314
338
|
return state
|
315
339
|
|
316
340
|
def handle_timeout(self, exc: TimeoutError) -> None:
|
@@ -329,6 +353,8 @@ class FlowRunEngine(Generic[P, R]):
|
|
329
353
|
self.set_state(state)
|
330
354
|
self._raised = exc
|
331
355
|
|
356
|
+
self._end_span_on_error(exc, message)
|
357
|
+
|
332
358
|
def handle_crash(self, exc: BaseException) -> None:
|
333
359
|
state = run_coro_as_sync(exception_to_crashed_state(exc))
|
334
360
|
self.logger.error(f"Crash detected! {state.message}")
|
@@ -336,6 +362,23 @@ class FlowRunEngine(Generic[P, R]):
|
|
336
362
|
self.set_state(state, force=True)
|
337
363
|
self._raised = exc
|
338
364
|
|
365
|
+
self._end_span_on_error(exc, state.message)
|
366
|
+
|
367
|
+
def _end_span_on_success(self):
|
368
|
+
if not self._span:
|
369
|
+
return
|
370
|
+
self._span.set_status(trace.Status(trace.StatusCode.OK))
|
371
|
+
self._span.end(time.time_ns())
|
372
|
+
self._span = None
|
373
|
+
|
374
|
+
def _end_span_on_error(self, exc: BaseException, description: Optional[str]):
|
375
|
+
if not self._span:
|
376
|
+
return
|
377
|
+
self._span.record_exception(exc)
|
378
|
+
self._span.set_status(trace.Status(trace.StatusCode.ERROR, description))
|
379
|
+
self._span.end(time.time_ns())
|
380
|
+
self._span = None
|
381
|
+
|
339
382
|
def load_subflow_run(
|
340
383
|
self,
|
341
384
|
parent_task_run: TaskRun,
|
@@ -578,6 +621,18 @@ class FlowRunEngine(Generic[P, R]):
|
|
578
621
|
flow_version=self.flow.version,
|
579
622
|
empirical_policy=self.flow_run.empirical_policy,
|
580
623
|
)
|
624
|
+
|
625
|
+
self._span = self._tracer.start_span(
|
626
|
+
name=self.flow_run.name,
|
627
|
+
attributes={
|
628
|
+
**self.flow_run.labels,
|
629
|
+
"prefect.run.type": "flow",
|
630
|
+
"prefect.run.id": str(self.flow_run.id),
|
631
|
+
"prefect.tags": self.flow_run.tags,
|
632
|
+
"prefect.flow.name": self.flow.name,
|
633
|
+
},
|
634
|
+
)
|
635
|
+
|
581
636
|
try:
|
582
637
|
yield self
|
583
638
|
|
@@ -632,7 +687,7 @@ class FlowRunEngine(Generic[P, R]):
|
|
632
687
|
|
633
688
|
@contextmanager
|
634
689
|
def start(self) -> Generator[None, None, None]:
|
635
|
-
with self.initialize_run():
|
690
|
+
with self.initialize_run(), trace.use_span(self._span):
|
636
691
|
self.begin_run()
|
637
692
|
|
638
693
|
if self.state.is_running():
|
@@ -32,7 +32,6 @@ from prefect.settings import (
|
|
32
32
|
PREFECT_LOGGING_TO_API_BATCH_SIZE,
|
33
33
|
PREFECT_LOGGING_TO_API_MAX_LOG_SIZE,
|
34
34
|
PREFECT_LOGGING_TO_API_WHEN_MISSING_FLOW,
|
35
|
-
get_current_settings,
|
36
35
|
)
|
37
36
|
|
38
37
|
|
@@ -241,10 +240,12 @@ class APILogHandler(logging.Handler):
|
|
241
240
|
|
242
241
|
class WorkerAPILogHandler(APILogHandler):
|
243
242
|
def emit(self, record: logging.LogRecord):
|
244
|
-
|
245
|
-
|
246
|
-
|
243
|
+
# Open-source API servers do not currently support worker logs, and
|
244
|
+
# worker logs only have an associated worker ID when connected to Cloud,
|
245
|
+
# so we won't send worker logs to the API unless they have a worker ID.
|
246
|
+
if not getattr(record, "worker_id", None):
|
247
247
|
return
|
248
|
+
super().emit(record)
|
248
249
|
|
249
250
|
def prepare(self, record: logging.LogRecord) -> Dict[str, Any]:
|
250
251
|
"""
|
@@ -18,11 +18,6 @@ class ExperimentsSettings(PrefectBaseSettings):
|
|
18
18
|
),
|
19
19
|
)
|
20
20
|
|
21
|
-
worker_logging_to_api_enabled: bool = Field(
|
22
|
-
default=False,
|
23
|
-
description="Enables the logging of worker logs to Prefect Cloud.",
|
24
|
-
)
|
25
|
-
|
26
21
|
telemetry_enabled: bool = Field(
|
27
22
|
default=False,
|
28
23
|
description="Enables sending telemetry to Prefect Cloud.",
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import time
|
2
2
|
from threading import Event, Lock, Thread
|
3
|
-
from typing import Optional
|
3
|
+
from typing import Dict, Optional
|
4
4
|
|
5
5
|
from opentelemetry.context import Context
|
6
6
|
from opentelemetry.sdk.trace import ReadableSpan, Span, SpanProcessor
|
@@ -10,7 +10,7 @@ from opentelemetry.sdk.trace.export import SpanExporter
|
|
10
10
|
class InFlightSpanProcessor(SpanProcessor):
|
11
11
|
def __init__(self, span_exporter: SpanExporter):
|
12
12
|
self.span_exporter = span_exporter
|
13
|
-
self._in_flight = {}
|
13
|
+
self._in_flight: Dict[int, Span] = {}
|
14
14
|
self._lock = Lock()
|
15
15
|
self._stop_event = Event()
|
16
16
|
self._export_thread = Thread(target=self._export_periodically, daemon=True)
|
@@ -7,7 +7,7 @@ import pathlib
|
|
7
7
|
import threading
|
8
8
|
from contextlib import contextmanager
|
9
9
|
from pathlib import Path, PureWindowsPath
|
10
|
-
from typing import Optional, Union
|
10
|
+
from typing import Optional, Union, cast
|
11
11
|
|
12
12
|
import fsspec
|
13
13
|
import pathspec
|
@@ -22,8 +22,8 @@ def create_default_ignore_file(path: str) -> bool:
|
|
22
22
|
Creates default ignore file in the provided path if one does not already exist; returns boolean specifying
|
23
23
|
whether a file was created.
|
24
24
|
"""
|
25
|
-
|
26
|
-
ignore_file =
|
25
|
+
_path = pathlib.Path(path)
|
26
|
+
ignore_file = _path / ".prefectignore"
|
27
27
|
if ignore_file.exists():
|
28
28
|
return False
|
29
29
|
default_file = pathlib.Path(prefect.__module_path__) / ".prefectignore"
|
@@ -54,12 +54,34 @@ def filter_files(
|
|
54
54
|
chdir_lock = threading.Lock()
|
55
55
|
|
56
56
|
|
57
|
+
def _normalize_path(path: Union[str, Path]) -> str:
|
58
|
+
"""
|
59
|
+
Normalize a path, handling UNC paths on Windows specially.
|
60
|
+
"""
|
61
|
+
path = Path(path)
|
62
|
+
|
63
|
+
# Handle UNC paths on Windows differently
|
64
|
+
if os.name == "nt" and str(path).startswith("\\\\"):
|
65
|
+
# For UNC paths, use absolute() instead of resolve()
|
66
|
+
# to avoid the Windows path resolution issues
|
67
|
+
return str(path.absolute())
|
68
|
+
else:
|
69
|
+
try:
|
70
|
+
# For non-UNC paths, try resolve() first
|
71
|
+
return str(path.resolve())
|
72
|
+
except OSError:
|
73
|
+
# Fallback to absolute() if resolve() fails
|
74
|
+
return str(path.absolute())
|
75
|
+
|
76
|
+
|
57
77
|
@contextmanager
|
58
78
|
def tmpchdir(path: str):
|
59
79
|
"""
|
60
|
-
Change current-working directories for the duration of the context
|
80
|
+
Change current-working directories for the duration of the context,
|
81
|
+
with special handling for UNC paths on Windows.
|
61
82
|
"""
|
62
|
-
path =
|
83
|
+
path = _normalize_path(path)
|
84
|
+
|
63
85
|
if os.path.isfile(path) or (not os.path.exists(path) and not path.endswith("/")):
|
64
86
|
path = os.path.dirname(path)
|
65
87
|
|
@@ -67,7 +89,12 @@ def tmpchdir(path: str):
|
|
67
89
|
|
68
90
|
with chdir_lock:
|
69
91
|
try:
|
70
|
-
|
92
|
+
# On Windows with UNC paths, we need to handle the directory change carefully
|
93
|
+
if os.name == "nt" and path.startswith("\\\\"):
|
94
|
+
# Use os.path.abspath to handle UNC paths
|
95
|
+
os.chdir(os.path.abspath(path))
|
96
|
+
else:
|
97
|
+
os.chdir(path)
|
71
98
|
yield path
|
72
99
|
finally:
|
73
100
|
os.chdir(owd)
|
@@ -76,7 +103,7 @@ def tmpchdir(path: str):
|
|
76
103
|
def filename(path: str) -> str:
|
77
104
|
"""Extract the file name from a path with remote file system support"""
|
78
105
|
try:
|
79
|
-
of: OpenFile = fsspec.open(path)
|
106
|
+
of: OpenFile = cast(OpenFile, fsspec.open(path))
|
80
107
|
sep = of.fs.sep
|
81
108
|
except (ImportError, AttributeError):
|
82
109
|
sep = "\\" if "\\" in path else "/"
|
@@ -98,7 +125,7 @@ def is_local_path(path: Union[str, pathlib.Path, OpenFile]):
|
|
98
125
|
else:
|
99
126
|
raise TypeError(f"Invalid path of type {type(path).__name__!r}")
|
100
127
|
|
101
|
-
return
|
128
|
+
return isinstance(of.fs, LocalFileSystem)
|
102
129
|
|
103
130
|
|
104
131
|
def to_display_path(
|
@@ -6,6 +6,7 @@ from typing import Optional, Union
|
|
6
6
|
|
7
7
|
import cloudpickle
|
8
8
|
|
9
|
+
from prefect.exceptions import HashError
|
9
10
|
from prefect.serializers import JSONSerializer
|
10
11
|
|
11
12
|
if sys.version_info[:2] >= (3, 9):
|
@@ -53,19 +54,39 @@ def hash_objects(
|
|
53
54
|
) -> Optional[str]:
|
54
55
|
"""
|
55
56
|
Attempt to hash objects by dumping to JSON or serializing with cloudpickle.
|
56
|
-
|
57
|
-
|
57
|
+
|
58
|
+
Args:
|
59
|
+
*args: Positional arguments to hash
|
60
|
+
hash_algo: Hash algorithm to use
|
61
|
+
raise_on_failure: If True, raise exceptions instead of returning None
|
62
|
+
**kwargs: Keyword arguments to hash
|
63
|
+
|
64
|
+
Returns:
|
65
|
+
A hash string or None if hashing failed
|
66
|
+
|
67
|
+
Raises:
|
68
|
+
HashError: If objects cannot be hashed and raise_on_failure is True
|
58
69
|
"""
|
70
|
+
json_error = None
|
71
|
+
pickle_error = None
|
72
|
+
|
59
73
|
try:
|
60
74
|
serializer = JSONSerializer(dumps_kwargs={"sort_keys": True})
|
61
75
|
return stable_hash(serializer.dumps((args, kwargs)), hash_algo=hash_algo)
|
62
|
-
except Exception:
|
63
|
-
|
76
|
+
except Exception as e:
|
77
|
+
json_error = str(e)
|
64
78
|
|
65
79
|
try:
|
66
80
|
return stable_hash(cloudpickle.dumps((args, kwargs)), hash_algo=hash_algo)
|
67
|
-
except Exception:
|
68
|
-
|
69
|
-
|
81
|
+
except Exception as e:
|
82
|
+
pickle_error = str(e)
|
83
|
+
|
84
|
+
if raise_on_failure:
|
85
|
+
msg = (
|
86
|
+
"Unable to create hash - objects could not be serialized.\n"
|
87
|
+
f" JSON error: {json_error}\n"
|
88
|
+
f" Pickle error: {pickle_error}"
|
89
|
+
)
|
90
|
+
raise HashError(msg)
|
70
91
|
|
71
92
|
return None
|
@@ -3,7 +3,7 @@ import ipaddress
|
|
3
3
|
import socket
|
4
4
|
import urllib.parse
|
5
5
|
from string import Formatter
|
6
|
-
from typing import TYPE_CHECKING, Any,
|
6
|
+
from typing import TYPE_CHECKING, Any, Literal, Optional, Union
|
7
7
|
from urllib.parse import urlparse
|
8
8
|
from uuid import UUID
|
9
9
|
|
@@ -135,7 +135,7 @@ def url_for(
|
|
135
135
|
obj_id: Optional[Union[str, UUID]] = None,
|
136
136
|
url_type: URLType = "ui",
|
137
137
|
default_base_url: Optional[str] = None,
|
138
|
-
**additional_format_kwargs:
|
138
|
+
**additional_format_kwargs: Any,
|
139
139
|
) -> Optional[str]:
|
140
140
|
"""
|
141
141
|
Returns the URL for a Prefect object.
|