prefect-client 2.19.3__py3-none-any.whl → 3.0.0rc1__py3-none-any.whl
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/__init__.py +8 -56
- prefect/_internal/compatibility/deprecated.py +6 -115
- prefect/_internal/compatibility/experimental.py +4 -79
- prefect/_internal/concurrency/api.py +0 -34
- prefect/_internal/concurrency/calls.py +0 -6
- prefect/_internal/concurrency/cancellation.py +0 -3
- prefect/_internal/concurrency/event_loop.py +0 -20
- prefect/_internal/concurrency/inspection.py +3 -3
- prefect/_internal/concurrency/threads.py +35 -0
- prefect/_internal/concurrency/waiters.py +0 -28
- prefect/_internal/pydantic/__init__.py +0 -45
- prefect/_internal/pydantic/v1_schema.py +21 -22
- prefect/_internal/pydantic/v2_schema.py +0 -2
- prefect/_internal/pydantic/v2_validated_func.py +18 -23
- prefect/_internal/schemas/bases.py +44 -177
- prefect/_internal/schemas/fields.py +1 -43
- prefect/_internal/schemas/validators.py +60 -158
- prefect/artifacts.py +161 -14
- prefect/automations.py +39 -4
- prefect/blocks/abstract.py +1 -1
- prefect/blocks/core.py +268 -148
- prefect/blocks/fields.py +2 -57
- prefect/blocks/kubernetes.py +8 -12
- prefect/blocks/notifications.py +40 -20
- prefect/blocks/system.py +22 -11
- prefect/blocks/webhook.py +2 -9
- prefect/client/base.py +4 -4
- prefect/client/cloud.py +8 -13
- prefect/client/orchestration.py +347 -341
- prefect/client/schemas/actions.py +92 -86
- prefect/client/schemas/filters.py +20 -40
- prefect/client/schemas/objects.py +147 -145
- prefect/client/schemas/responses.py +16 -24
- prefect/client/schemas/schedules.py +47 -35
- prefect/client/subscriptions.py +2 -2
- prefect/client/utilities.py +5 -2
- prefect/concurrency/asyncio.py +3 -1
- prefect/concurrency/events.py +1 -1
- prefect/concurrency/services.py +6 -3
- prefect/context.py +195 -27
- prefect/deployments/__init__.py +5 -6
- prefect/deployments/base.py +7 -5
- prefect/deployments/flow_runs.py +185 -0
- prefect/deployments/runner.py +50 -45
- prefect/deployments/schedules.py +28 -23
- prefect/deployments/steps/__init__.py +0 -1
- prefect/deployments/steps/core.py +1 -0
- prefect/deployments/steps/pull.py +7 -21
- prefect/engine.py +12 -2422
- prefect/events/actions.py +17 -23
- prefect/events/cli/automations.py +19 -6
- prefect/events/clients.py +14 -37
- prefect/events/filters.py +14 -18
- prefect/events/related.py +2 -2
- prefect/events/schemas/__init__.py +0 -5
- prefect/events/schemas/automations.py +55 -46
- prefect/events/schemas/deployment_triggers.py +7 -197
- prefect/events/schemas/events.py +34 -65
- prefect/events/schemas/labelling.py +10 -14
- prefect/events/utilities.py +2 -3
- prefect/events/worker.py +2 -3
- prefect/filesystems.py +6 -517
- prefect/{new_flow_engine.py → flow_engine.py} +313 -72
- prefect/flow_runs.py +377 -5
- prefect/flows.py +248 -165
- prefect/futures.py +186 -345
- prefect/infrastructure/__init__.py +0 -27
- prefect/infrastructure/provisioners/__init__.py +5 -3
- prefect/infrastructure/provisioners/cloud_run.py +11 -6
- prefect/infrastructure/provisioners/container_instance.py +11 -7
- prefect/infrastructure/provisioners/ecs.py +6 -4
- prefect/infrastructure/provisioners/modal.py +8 -5
- prefect/input/actions.py +2 -4
- prefect/input/run_input.py +5 -7
- prefect/logging/formatters.py +0 -2
- prefect/logging/handlers.py +3 -11
- prefect/logging/loggers.py +2 -2
- prefect/manifests.py +2 -1
- prefect/records/__init__.py +1 -0
- prefect/records/result_store.py +42 -0
- prefect/records/store.py +9 -0
- prefect/results.py +43 -39
- prefect/runner/runner.py +9 -9
- prefect/runner/server.py +6 -10
- prefect/runner/storage.py +3 -8
- prefect/runner/submit.py +2 -2
- prefect/runner/utils.py +2 -2
- prefect/serializers.py +24 -35
- prefect/server/api/collections_data/views/aggregate-worker-metadata.json +5 -14
- prefect/settings.py +70 -133
- prefect/states.py +17 -47
- prefect/task_engine.py +697 -58
- prefect/task_runners.py +269 -301
- prefect/task_server.py +53 -34
- prefect/tasks.py +327 -337
- prefect/transactions.py +220 -0
- prefect/types/__init__.py +61 -82
- prefect/utilities/asyncutils.py +195 -136
- prefect/utilities/callables.py +121 -41
- prefect/utilities/collections.py +23 -38
- prefect/utilities/dispatch.py +11 -3
- prefect/utilities/dockerutils.py +4 -0
- prefect/utilities/engine.py +140 -20
- prefect/utilities/importtools.py +26 -27
- prefect/utilities/pydantic.py +128 -38
- prefect/utilities/schema_tools/hydration.py +5 -1
- prefect/utilities/templating.py +12 -2
- prefect/variables.py +78 -61
- prefect/workers/__init__.py +0 -1
- prefect/workers/base.py +15 -17
- prefect/workers/process.py +3 -8
- prefect/workers/server.py +2 -2
- {prefect_client-2.19.3.dist-info → prefect_client-3.0.0rc1.dist-info}/METADATA +22 -21
- prefect_client-3.0.0rc1.dist-info/RECORD +176 -0
- prefect/_internal/pydantic/_base_model.py +0 -51
- prefect/_internal/pydantic/_compat.py +0 -82
- prefect/_internal/pydantic/_flags.py +0 -20
- prefect/_internal/pydantic/_types.py +0 -8
- prefect/_internal/pydantic/utilities/__init__.py +0 -0
- prefect/_internal/pydantic/utilities/config_dict.py +0 -72
- prefect/_internal/pydantic/utilities/field_validator.py +0 -150
- prefect/_internal/pydantic/utilities/model_construct.py +0 -56
- prefect/_internal/pydantic/utilities/model_copy.py +0 -55
- prefect/_internal/pydantic/utilities/model_dump.py +0 -136
- prefect/_internal/pydantic/utilities/model_dump_json.py +0 -112
- prefect/_internal/pydantic/utilities/model_fields.py +0 -50
- prefect/_internal/pydantic/utilities/model_fields_set.py +0 -29
- prefect/_internal/pydantic/utilities/model_json_schema.py +0 -82
- prefect/_internal/pydantic/utilities/model_rebuild.py +0 -80
- prefect/_internal/pydantic/utilities/model_validate.py +0 -75
- prefect/_internal/pydantic/utilities/model_validate_json.py +0 -68
- prefect/_internal/pydantic/utilities/model_validator.py +0 -87
- prefect/_internal/pydantic/utilities/type_adapter.py +0 -71
- prefect/_vendor/__init__.py +0 -0
- prefect/_vendor/fastapi/__init__.py +0 -25
- prefect/_vendor/fastapi/applications.py +0 -946
- prefect/_vendor/fastapi/background.py +0 -3
- prefect/_vendor/fastapi/concurrency.py +0 -44
- prefect/_vendor/fastapi/datastructures.py +0 -58
- prefect/_vendor/fastapi/dependencies/__init__.py +0 -0
- prefect/_vendor/fastapi/dependencies/models.py +0 -64
- prefect/_vendor/fastapi/dependencies/utils.py +0 -877
- prefect/_vendor/fastapi/encoders.py +0 -177
- prefect/_vendor/fastapi/exception_handlers.py +0 -40
- prefect/_vendor/fastapi/exceptions.py +0 -46
- prefect/_vendor/fastapi/logger.py +0 -3
- prefect/_vendor/fastapi/middleware/__init__.py +0 -1
- prefect/_vendor/fastapi/middleware/asyncexitstack.py +0 -25
- prefect/_vendor/fastapi/middleware/cors.py +0 -3
- prefect/_vendor/fastapi/middleware/gzip.py +0 -3
- prefect/_vendor/fastapi/middleware/httpsredirect.py +0 -3
- prefect/_vendor/fastapi/middleware/trustedhost.py +0 -3
- prefect/_vendor/fastapi/middleware/wsgi.py +0 -3
- prefect/_vendor/fastapi/openapi/__init__.py +0 -0
- prefect/_vendor/fastapi/openapi/constants.py +0 -2
- prefect/_vendor/fastapi/openapi/docs.py +0 -203
- prefect/_vendor/fastapi/openapi/models.py +0 -480
- prefect/_vendor/fastapi/openapi/utils.py +0 -485
- prefect/_vendor/fastapi/param_functions.py +0 -340
- prefect/_vendor/fastapi/params.py +0 -453
- prefect/_vendor/fastapi/requests.py +0 -4
- prefect/_vendor/fastapi/responses.py +0 -40
- prefect/_vendor/fastapi/routing.py +0 -1331
- prefect/_vendor/fastapi/security/__init__.py +0 -15
- prefect/_vendor/fastapi/security/api_key.py +0 -98
- prefect/_vendor/fastapi/security/base.py +0 -6
- prefect/_vendor/fastapi/security/http.py +0 -172
- prefect/_vendor/fastapi/security/oauth2.py +0 -227
- prefect/_vendor/fastapi/security/open_id_connect_url.py +0 -34
- prefect/_vendor/fastapi/security/utils.py +0 -10
- prefect/_vendor/fastapi/staticfiles.py +0 -1
- prefect/_vendor/fastapi/templating.py +0 -3
- prefect/_vendor/fastapi/testclient.py +0 -1
- prefect/_vendor/fastapi/types.py +0 -3
- prefect/_vendor/fastapi/utils.py +0 -235
- prefect/_vendor/fastapi/websockets.py +0 -7
- prefect/_vendor/starlette/__init__.py +0 -1
- prefect/_vendor/starlette/_compat.py +0 -28
- prefect/_vendor/starlette/_exception_handler.py +0 -80
- prefect/_vendor/starlette/_utils.py +0 -88
- prefect/_vendor/starlette/applications.py +0 -261
- prefect/_vendor/starlette/authentication.py +0 -159
- prefect/_vendor/starlette/background.py +0 -43
- prefect/_vendor/starlette/concurrency.py +0 -59
- prefect/_vendor/starlette/config.py +0 -151
- prefect/_vendor/starlette/convertors.py +0 -87
- prefect/_vendor/starlette/datastructures.py +0 -707
- prefect/_vendor/starlette/endpoints.py +0 -130
- prefect/_vendor/starlette/exceptions.py +0 -60
- prefect/_vendor/starlette/formparsers.py +0 -276
- prefect/_vendor/starlette/middleware/__init__.py +0 -17
- prefect/_vendor/starlette/middleware/authentication.py +0 -52
- prefect/_vendor/starlette/middleware/base.py +0 -220
- prefect/_vendor/starlette/middleware/cors.py +0 -176
- prefect/_vendor/starlette/middleware/errors.py +0 -265
- prefect/_vendor/starlette/middleware/exceptions.py +0 -74
- prefect/_vendor/starlette/middleware/gzip.py +0 -113
- prefect/_vendor/starlette/middleware/httpsredirect.py +0 -19
- prefect/_vendor/starlette/middleware/sessions.py +0 -82
- prefect/_vendor/starlette/middleware/trustedhost.py +0 -64
- prefect/_vendor/starlette/middleware/wsgi.py +0 -147
- prefect/_vendor/starlette/requests.py +0 -328
- prefect/_vendor/starlette/responses.py +0 -347
- prefect/_vendor/starlette/routing.py +0 -933
- prefect/_vendor/starlette/schemas.py +0 -154
- prefect/_vendor/starlette/staticfiles.py +0 -248
- prefect/_vendor/starlette/status.py +0 -199
- prefect/_vendor/starlette/templating.py +0 -231
- prefect/_vendor/starlette/testclient.py +0 -804
- prefect/_vendor/starlette/types.py +0 -30
- prefect/_vendor/starlette/websockets.py +0 -193
- prefect/agent.py +0 -698
- prefect/deployments/deployments.py +0 -1042
- prefect/deprecated/__init__.py +0 -0
- prefect/deprecated/data_documents.py +0 -350
- prefect/deprecated/packaging/__init__.py +0 -12
- prefect/deprecated/packaging/base.py +0 -96
- prefect/deprecated/packaging/docker.py +0 -146
- prefect/deprecated/packaging/file.py +0 -92
- prefect/deprecated/packaging/orion.py +0 -80
- prefect/deprecated/packaging/serializers.py +0 -171
- prefect/events/instrument.py +0 -135
- prefect/infrastructure/base.py +0 -323
- prefect/infrastructure/container.py +0 -818
- prefect/infrastructure/kubernetes.py +0 -920
- prefect/infrastructure/process.py +0 -289
- prefect/new_task_engine.py +0 -423
- prefect/pydantic/__init__.py +0 -76
- prefect/pydantic/main.py +0 -39
- prefect/software/__init__.py +0 -2
- prefect/software/base.py +0 -50
- prefect/software/conda.py +0 -199
- prefect/software/pip.py +0 -122
- prefect/software/python.py +0 -52
- prefect/workers/block.py +0 -218
- prefect_client-2.19.3.dist-info/RECORD +0 -292
- {prefect_client-2.19.3.dist-info → prefect_client-3.0.0rc1.dist-info}/LICENSE +0 -0
- {prefect_client-2.19.3.dist-info → prefect_client-3.0.0rc1.dist-info}/WHEEL +0 -0
- {prefect_client-2.19.3.dist-info → prefect_client-3.0.0rc1.dist-info}/top_level.txt +0 -0
prefect/filesystems.py
CHANGED
@@ -1,33 +1,20 @@
|
|
1
1
|
import abc
|
2
|
-
import io
|
3
|
-
import json
|
4
2
|
import urllib.parse
|
5
3
|
from pathlib import Path
|
6
|
-
from
|
7
|
-
from tempfile import TemporaryDirectory
|
8
|
-
from typing import Any, Dict, Optional, Tuple, Union
|
4
|
+
from typing import Any, Dict, Optional
|
9
5
|
|
10
6
|
import anyio
|
11
7
|
import fsspec
|
12
|
-
|
13
|
-
from prefect._internal.compatibility.deprecated import deprecated_class
|
14
|
-
from prefect._internal.pydantic import HAS_PYDANTIC_V2
|
15
|
-
|
16
|
-
if HAS_PYDANTIC_V2:
|
17
|
-
from pydantic.v1 import Field, SecretStr, validator
|
18
|
-
else:
|
19
|
-
from pydantic import Field, SecretStr, validator
|
8
|
+
from pydantic import Field, SecretStr, field_validator
|
20
9
|
|
21
10
|
from prefect._internal.schemas.validators import (
|
22
11
|
stringify_path,
|
23
12
|
validate_basepath,
|
24
|
-
validate_github_access_token,
|
25
13
|
)
|
26
14
|
from prefect.blocks.core import Block
|
27
15
|
from prefect.utilities.asyncutils import run_sync_in_worker_thread, sync_compatible
|
28
16
|
from prefect.utilities.compat import copytree
|
29
17
|
from prefect.utilities.filesystem import filter_files
|
30
|
-
from prefect.utilities.processutils import run_process
|
31
18
|
|
32
19
|
|
33
20
|
class ReadableFileSystem(Block, abc.ABC):
|
@@ -99,7 +86,7 @@ class LocalFileSystem(WritableFileSystem, WritableDeploymentStorage):
|
|
99
86
|
default=None, description="Default local path for this block to write to."
|
100
87
|
)
|
101
88
|
|
102
|
-
@
|
89
|
+
@field_validator("basepath", mode="before")
|
103
90
|
def cast_pathlib(cls, value):
|
104
91
|
return stringify_path(value)
|
105
92
|
|
@@ -131,7 +118,7 @@ class LocalFileSystem(WritableFileSystem, WritableDeploymentStorage):
|
|
131
118
|
|
132
119
|
@sync_compatible
|
133
120
|
async def get_directory(
|
134
|
-
self, from_path: str = None, local_path: str = None
|
121
|
+
self, from_path: Optional[str] = None, local_path: Optional[str] = None
|
135
122
|
) -> None:
|
136
123
|
"""
|
137
124
|
Copies a directory from one place to another on the local filesystem.
|
@@ -280,7 +267,7 @@ class RemoteFileSystem(WritableFileSystem, WritableDeploymentStorage):
|
|
280
267
|
# Cache for the configured fsspec file system used for access
|
281
268
|
_filesystem: fsspec.AbstractFileSystem = None
|
282
269
|
|
283
|
-
@
|
270
|
+
@field_validator("basepath")
|
284
271
|
def check_basepath(cls, value):
|
285
272
|
return validate_basepath(value)
|
286
273
|
|
@@ -422,368 +409,6 @@ class RemoteFileSystem(WritableFileSystem, WritableDeploymentStorage):
|
|
422
409
|
return self._filesystem
|
423
410
|
|
424
411
|
|
425
|
-
@deprecated_class(
|
426
|
-
start_date="Mar 2024", help="Use the `S3Bucket` block from prefect-aws instead."
|
427
|
-
)
|
428
|
-
class S3(WritableFileSystem, WritableDeploymentStorage):
|
429
|
-
"""
|
430
|
-
DEPRECATION WARNING:
|
431
|
-
|
432
|
-
This class is deprecated as of March 2024 and will not be available after September 2024.
|
433
|
-
It has been replaced by `S3Bucket` from the `prefect-aws` package, which offers enhanced functionality
|
434
|
-
and better a better user experience.
|
435
|
-
|
436
|
-
Store data as a file on AWS S3.
|
437
|
-
|
438
|
-
Example:
|
439
|
-
Load stored S3 config:
|
440
|
-
```python
|
441
|
-
from prefect.filesystems import S3
|
442
|
-
|
443
|
-
s3_block = S3.load("BLOCK_NAME")
|
444
|
-
```
|
445
|
-
"""
|
446
|
-
|
447
|
-
_block_type_name = "S3"
|
448
|
-
_logo_url = "https://cdn.sanity.io/images/3ugk85nk/production/d74b16fe84ce626345adf235a47008fea2869a60-225x225.png"
|
449
|
-
_documentation_url = "https://docs.prefect.io/concepts/filesystems/#s3"
|
450
|
-
|
451
|
-
bucket_path: str = Field(
|
452
|
-
default=...,
|
453
|
-
description="An S3 bucket path.",
|
454
|
-
examples=["my-bucket/a-directory-within"],
|
455
|
-
)
|
456
|
-
aws_access_key_id: Optional[SecretStr] = Field(
|
457
|
-
default=None,
|
458
|
-
title="AWS Access Key ID",
|
459
|
-
description="Equivalent to the AWS_ACCESS_KEY_ID environment variable.",
|
460
|
-
examples=["AKIAIOSFODNN7EXAMPLE"],
|
461
|
-
)
|
462
|
-
aws_secret_access_key: Optional[SecretStr] = Field(
|
463
|
-
default=None,
|
464
|
-
title="AWS Secret Access Key",
|
465
|
-
description="Equivalent to the AWS_SECRET_ACCESS_KEY environment variable.",
|
466
|
-
examples=["wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"],
|
467
|
-
)
|
468
|
-
|
469
|
-
_remote_file_system: RemoteFileSystem = None
|
470
|
-
|
471
|
-
@property
|
472
|
-
def basepath(self) -> str:
|
473
|
-
return f"s3://{self.bucket_path}"
|
474
|
-
|
475
|
-
@property
|
476
|
-
def filesystem(self) -> RemoteFileSystem:
|
477
|
-
settings = {}
|
478
|
-
if self.aws_access_key_id:
|
479
|
-
settings["key"] = self.aws_access_key_id.get_secret_value()
|
480
|
-
if self.aws_secret_access_key:
|
481
|
-
settings["secret"] = self.aws_secret_access_key.get_secret_value()
|
482
|
-
self._remote_file_system = RemoteFileSystem(
|
483
|
-
basepath=f"s3://{self.bucket_path}", settings=settings
|
484
|
-
)
|
485
|
-
return self._remote_file_system
|
486
|
-
|
487
|
-
@sync_compatible
|
488
|
-
async def get_directory(
|
489
|
-
self, from_path: Optional[str] = None, local_path: Optional[str] = None
|
490
|
-
) -> bytes:
|
491
|
-
"""
|
492
|
-
Downloads a directory from a given remote path to a local directory.
|
493
|
-
|
494
|
-
Defaults to downloading the entire contents of the block's basepath to the current working directory.
|
495
|
-
"""
|
496
|
-
return await self.filesystem.get_directory(
|
497
|
-
from_path=from_path, local_path=local_path
|
498
|
-
)
|
499
|
-
|
500
|
-
@sync_compatible
|
501
|
-
async def put_directory(
|
502
|
-
self,
|
503
|
-
local_path: Optional[str] = None,
|
504
|
-
to_path: Optional[str] = None,
|
505
|
-
ignore_file: Optional[str] = None,
|
506
|
-
) -> int:
|
507
|
-
"""
|
508
|
-
Uploads a directory from a given local path to a remote directory.
|
509
|
-
|
510
|
-
Defaults to uploading the entire contents of the current working directory to the block's basepath.
|
511
|
-
"""
|
512
|
-
return await self.filesystem.put_directory(
|
513
|
-
local_path=local_path, to_path=to_path, ignore_file=ignore_file
|
514
|
-
)
|
515
|
-
|
516
|
-
@sync_compatible
|
517
|
-
async def read_path(self, path: str) -> bytes:
|
518
|
-
return await self.filesystem.read_path(path)
|
519
|
-
|
520
|
-
@sync_compatible
|
521
|
-
async def write_path(self, path: str, content: bytes) -> str:
|
522
|
-
return await self.filesystem.write_path(path=path, content=content)
|
523
|
-
|
524
|
-
|
525
|
-
@deprecated_class(
|
526
|
-
start_date="Mar 2024", help="Use the `GcsBucket` block from prefect-gcp instead."
|
527
|
-
)
|
528
|
-
class GCS(WritableFileSystem, WritableDeploymentStorage):
|
529
|
-
"""
|
530
|
-
DEPRECATION WARNING:
|
531
|
-
|
532
|
-
This class is deprecated as of March 2024 and will not be available after September 2024.
|
533
|
-
It has been replaced by `GcsBucket` from the `prefect-gcp` package, which offers enhanced functionality
|
534
|
-
and better a better user experience.
|
535
|
-
Store data as a file on Google Cloud Storage.
|
536
|
-
|
537
|
-
Example:
|
538
|
-
Load stored GCS config:
|
539
|
-
```python
|
540
|
-
from prefect.filesystems import GCS
|
541
|
-
|
542
|
-
gcs_block = GCS.load("BLOCK_NAME")
|
543
|
-
```
|
544
|
-
"""
|
545
|
-
|
546
|
-
_logo_url = "https://cdn.sanity.io/images/3ugk85nk/production/422d13bb838cf247eb2b2cf229ce6a2e717d601b-256x256.png"
|
547
|
-
_documentation_url = "https://docs.prefect.io/concepts/filesystems/#gcs"
|
548
|
-
|
549
|
-
bucket_path: str = Field(
|
550
|
-
default=...,
|
551
|
-
description="A GCS bucket path.",
|
552
|
-
examples=["my-bucket/a-directory-within"],
|
553
|
-
)
|
554
|
-
service_account_info: Optional[SecretStr] = Field(
|
555
|
-
default=None,
|
556
|
-
description="The contents of a service account keyfile as a JSON string.",
|
557
|
-
)
|
558
|
-
project: Optional[str] = Field(
|
559
|
-
default=None,
|
560
|
-
description=(
|
561
|
-
"The project the GCS bucket resides in. If not provided, the project will"
|
562
|
-
" be inferred from the credentials or environment."
|
563
|
-
),
|
564
|
-
)
|
565
|
-
|
566
|
-
@property
|
567
|
-
def basepath(self) -> str:
|
568
|
-
return f"gcs://{self.bucket_path}"
|
569
|
-
|
570
|
-
@property
|
571
|
-
def filesystem(self) -> RemoteFileSystem:
|
572
|
-
settings = {}
|
573
|
-
if self.service_account_info:
|
574
|
-
try:
|
575
|
-
settings["token"] = json.loads(
|
576
|
-
self.service_account_info.get_secret_value()
|
577
|
-
)
|
578
|
-
except json.JSONDecodeError:
|
579
|
-
raise ValueError(
|
580
|
-
"Unable to load provided service_account_info. Please make sure"
|
581
|
-
" that the provided value is a valid JSON string."
|
582
|
-
)
|
583
|
-
remote_file_system = RemoteFileSystem(
|
584
|
-
basepath=f"gcs://{self.bucket_path}", settings=settings
|
585
|
-
)
|
586
|
-
return remote_file_system
|
587
|
-
|
588
|
-
@sync_compatible
|
589
|
-
async def get_directory(
|
590
|
-
self, from_path: Optional[str] = None, local_path: Optional[str] = None
|
591
|
-
) -> bytes:
|
592
|
-
"""
|
593
|
-
Downloads a directory from a given remote path to a local directory.
|
594
|
-
|
595
|
-
Defaults to downloading the entire contents of the block's basepath to the current working directory.
|
596
|
-
"""
|
597
|
-
return await self.filesystem.get_directory(
|
598
|
-
from_path=from_path, local_path=local_path
|
599
|
-
)
|
600
|
-
|
601
|
-
@sync_compatible
|
602
|
-
async def put_directory(
|
603
|
-
self,
|
604
|
-
local_path: Optional[str] = None,
|
605
|
-
to_path: Optional[str] = None,
|
606
|
-
ignore_file: Optional[str] = None,
|
607
|
-
) -> int:
|
608
|
-
"""
|
609
|
-
Uploads a directory from a given local path to a remote directory.
|
610
|
-
|
611
|
-
Defaults to uploading the entire contents of the current working directory to the block's basepath.
|
612
|
-
"""
|
613
|
-
return await self.filesystem.put_directory(
|
614
|
-
local_path=local_path, to_path=to_path, ignore_file=ignore_file
|
615
|
-
)
|
616
|
-
|
617
|
-
@sync_compatible
|
618
|
-
async def read_path(self, path: str) -> bytes:
|
619
|
-
return await self.filesystem.read_path(path)
|
620
|
-
|
621
|
-
@sync_compatible
|
622
|
-
async def write_path(self, path: str, content: bytes) -> str:
|
623
|
-
return await self.filesystem.write_path(path=path, content=content)
|
624
|
-
|
625
|
-
|
626
|
-
@deprecated_class(
|
627
|
-
start_date="Mar 2024",
|
628
|
-
help="Use the `AzureBlobStorageContainer` block from prefect-azure instead.",
|
629
|
-
)
|
630
|
-
class Azure(WritableFileSystem, WritableDeploymentStorage):
|
631
|
-
"""
|
632
|
-
DEPRECATION WARNING:
|
633
|
-
|
634
|
-
This class is deprecated as of March 2024 and will not be available after September 2024.
|
635
|
-
It has been replaced by `AzureBlobStorageContainer` from the `prefect-azure` package, which
|
636
|
-
offers enhanced functionality and better a better user experience.
|
637
|
-
|
638
|
-
Store data as a file on Azure Datalake and Azure Blob Storage.
|
639
|
-
|
640
|
-
Example:
|
641
|
-
Load stored Azure config:
|
642
|
-
```python
|
643
|
-
from prefect.filesystems import Azure
|
644
|
-
|
645
|
-
az_block = Azure.load("BLOCK_NAME")
|
646
|
-
```
|
647
|
-
"""
|
648
|
-
|
649
|
-
_block_type_name = "Azure"
|
650
|
-
_logo_url = "https://cdn.sanity.io/images/3ugk85nk/production/54e3fa7e00197a4fbd1d82ed62494cb58d08c96a-250x250.png"
|
651
|
-
_documentation_url = "https://docs.prefect.io/concepts/filesystems/#azure"
|
652
|
-
|
653
|
-
bucket_path: str = Field(
|
654
|
-
default=...,
|
655
|
-
description="An Azure storage bucket path.",
|
656
|
-
examples=["my-bucket/a-directory-within"],
|
657
|
-
)
|
658
|
-
azure_storage_connection_string: Optional[SecretStr] = Field(
|
659
|
-
default=None,
|
660
|
-
title="Azure storage connection string",
|
661
|
-
description=(
|
662
|
-
"Equivalent to the AZURE_STORAGE_CONNECTION_STRING environment variable."
|
663
|
-
),
|
664
|
-
)
|
665
|
-
azure_storage_account_name: Optional[SecretStr] = Field(
|
666
|
-
default=None,
|
667
|
-
title="Azure storage account name",
|
668
|
-
description=(
|
669
|
-
"Equivalent to the AZURE_STORAGE_ACCOUNT_NAME environment variable."
|
670
|
-
),
|
671
|
-
)
|
672
|
-
azure_storage_account_key: Optional[SecretStr] = Field(
|
673
|
-
default=None,
|
674
|
-
title="Azure storage account key",
|
675
|
-
description="Equivalent to the AZURE_STORAGE_ACCOUNT_KEY environment variable.",
|
676
|
-
)
|
677
|
-
azure_storage_tenant_id: Optional[SecretStr] = Field(
|
678
|
-
None,
|
679
|
-
title="Azure storage tenant ID",
|
680
|
-
description="Equivalent to the AZURE_TENANT_ID environment variable.",
|
681
|
-
)
|
682
|
-
azure_storage_client_id: Optional[SecretStr] = Field(
|
683
|
-
None,
|
684
|
-
title="Azure storage client ID",
|
685
|
-
description="Equivalent to the AZURE_CLIENT_ID environment variable.",
|
686
|
-
)
|
687
|
-
azure_storage_client_secret: Optional[SecretStr] = Field(
|
688
|
-
None,
|
689
|
-
title="Azure storage client secret",
|
690
|
-
description="Equivalent to the AZURE_CLIENT_SECRET environment variable.",
|
691
|
-
)
|
692
|
-
azure_storage_anon: bool = Field(
|
693
|
-
default=True,
|
694
|
-
title="Azure storage anonymous connection",
|
695
|
-
description=(
|
696
|
-
"Set the 'anon' flag for ADLFS. This should be False for systems that"
|
697
|
-
" require ADLFS to use DefaultAzureCredentials."
|
698
|
-
),
|
699
|
-
)
|
700
|
-
azure_storage_container: Optional[SecretStr] = Field(
|
701
|
-
default=None,
|
702
|
-
title="Azure storage container",
|
703
|
-
description=(
|
704
|
-
"Blob Container in Azure Storage Account. If set the 'bucket_path' will"
|
705
|
-
" be interpreted using the following URL format:"
|
706
|
-
"'az://<container>@<storage_account>.dfs.core.windows.net/<bucket_path>'."
|
707
|
-
),
|
708
|
-
)
|
709
|
-
_remote_file_system: RemoteFileSystem = None
|
710
|
-
|
711
|
-
@property
|
712
|
-
def basepath(self) -> str:
|
713
|
-
if self.azure_storage_container:
|
714
|
-
return (
|
715
|
-
f"az://{self.azure_storage_container.get_secret_value()}"
|
716
|
-
f"@{self.azure_storage_account_name.get_secret_value()}"
|
717
|
-
f".dfs.core.windows.net/{self.bucket_path}"
|
718
|
-
)
|
719
|
-
else:
|
720
|
-
return f"az://{self.bucket_path}"
|
721
|
-
|
722
|
-
@property
|
723
|
-
def filesystem(self) -> RemoteFileSystem:
|
724
|
-
settings = {}
|
725
|
-
if self.azure_storage_connection_string:
|
726
|
-
settings[
|
727
|
-
"connection_string"
|
728
|
-
] = self.azure_storage_connection_string.get_secret_value()
|
729
|
-
if self.azure_storage_account_name:
|
730
|
-
settings[
|
731
|
-
"account_name"
|
732
|
-
] = self.azure_storage_account_name.get_secret_value()
|
733
|
-
if self.azure_storage_account_key:
|
734
|
-
settings["account_key"] = self.azure_storage_account_key.get_secret_value()
|
735
|
-
if self.azure_storage_tenant_id:
|
736
|
-
settings["tenant_id"] = self.azure_storage_tenant_id.get_secret_value()
|
737
|
-
if self.azure_storage_client_id:
|
738
|
-
settings["client_id"] = self.azure_storage_client_id.get_secret_value()
|
739
|
-
if self.azure_storage_client_secret:
|
740
|
-
settings[
|
741
|
-
"client_secret"
|
742
|
-
] = self.azure_storage_client_secret.get_secret_value()
|
743
|
-
settings["anon"] = self.azure_storage_anon
|
744
|
-
self._remote_file_system = RemoteFileSystem(
|
745
|
-
basepath=self.basepath, settings=settings
|
746
|
-
)
|
747
|
-
return self._remote_file_system
|
748
|
-
|
749
|
-
@sync_compatible
|
750
|
-
async def get_directory(
|
751
|
-
self, from_path: Optional[str] = None, local_path: Optional[str] = None
|
752
|
-
) -> bytes:
|
753
|
-
"""
|
754
|
-
Downloads a directory from a given remote path to a local directory.
|
755
|
-
|
756
|
-
Defaults to downloading the entire contents of the block's basepath to the current working directory.
|
757
|
-
"""
|
758
|
-
return await self.filesystem.get_directory(
|
759
|
-
from_path=from_path, local_path=local_path
|
760
|
-
)
|
761
|
-
|
762
|
-
@sync_compatible
|
763
|
-
async def put_directory(
|
764
|
-
self,
|
765
|
-
local_path: Optional[str] = None,
|
766
|
-
to_path: Optional[str] = None,
|
767
|
-
ignore_file: Optional[str] = None,
|
768
|
-
) -> int:
|
769
|
-
"""
|
770
|
-
Uploads a directory from a given local path to a remote directory.
|
771
|
-
|
772
|
-
Defaults to uploading the entire contents of the current working directory to the block's basepath.
|
773
|
-
"""
|
774
|
-
return await self.filesystem.put_directory(
|
775
|
-
local_path=local_path, to_path=to_path, ignore_file=ignore_file
|
776
|
-
)
|
777
|
-
|
778
|
-
@sync_compatible
|
779
|
-
async def read_path(self, path: str) -> bytes:
|
780
|
-
return await self.filesystem.read_path(path)
|
781
|
-
|
782
|
-
@sync_compatible
|
783
|
-
async def write_path(self, path: str, content: bytes) -> str:
|
784
|
-
return await self.filesystem.write_path(path=path, content=content)
|
785
|
-
|
786
|
-
|
787
412
|
class SMB(WritableFileSystem, WritableDeploymentStorage):
|
788
413
|
"""
|
789
414
|
Store data as a file on a SMB share.
|
@@ -815,7 +440,7 @@ class SMB(WritableFileSystem, WritableDeploymentStorage):
|
|
815
440
|
default=None, title="SMB Password", description="Password for SMB access."
|
816
441
|
)
|
817
442
|
smb_host: str = Field(
|
818
|
-
default=...,
|
443
|
+
default=..., title="SMB server/hostname", description="SMB server/hostname."
|
819
444
|
)
|
820
445
|
smb_port: Optional[int] = Field(
|
821
446
|
default=None, title="SMB port", description="SMB port (default: 445)."
|
@@ -881,139 +506,3 @@ class SMB(WritableFileSystem, WritableDeploymentStorage):
|
|
881
506
|
@sync_compatible
|
882
507
|
async def write_path(self, path: str, content: bytes) -> str:
|
883
508
|
return await self.filesystem.write_path(path=path, content=content)
|
884
|
-
|
885
|
-
|
886
|
-
@deprecated_class(
|
887
|
-
start_date="Mar 2024",
|
888
|
-
help="Use the `GitHubRepository` block from prefect-github instead.",
|
889
|
-
)
|
890
|
-
class GitHub(ReadableDeploymentStorage):
|
891
|
-
"""
|
892
|
-
DEPRECATION WARNING:
|
893
|
-
|
894
|
-
This class is deprecated as of March 2024 and will not be available after September 2024.
|
895
|
-
It has been replaced by `GitHubRepository` from the `prefect-github` package, which offers
|
896
|
-
enhanced functionality and better a better user experience.
|
897
|
-
q
|
898
|
-
Interact with files stored on GitHub repositories.
|
899
|
-
"""
|
900
|
-
|
901
|
-
_block_type_name = "GitHub"
|
902
|
-
_logo_url = "https://cdn.sanity.io/images/3ugk85nk/production/41971cfecfea5f79ff334164f06ecb34d1038dd4-250x250.png"
|
903
|
-
_documentation_url = "https://docs.prefect.io/concepts/filesystems/#github"
|
904
|
-
|
905
|
-
repository: str = Field(
|
906
|
-
default=...,
|
907
|
-
description=(
|
908
|
-
"The URL of a GitHub repository to read from, in either HTTPS or SSH"
|
909
|
-
" format."
|
910
|
-
),
|
911
|
-
)
|
912
|
-
reference: Optional[str] = Field(
|
913
|
-
default=None,
|
914
|
-
description="An optional reference to pin to; can be a branch name or tag.",
|
915
|
-
)
|
916
|
-
access_token: Optional[SecretStr] = Field(
|
917
|
-
name="Personal Access Token",
|
918
|
-
default=None,
|
919
|
-
description=(
|
920
|
-
"A GitHub Personal Access Token (PAT) with repo scope."
|
921
|
-
" To use a fine-grained PAT, provide '{username}:{PAT}' as the value."
|
922
|
-
),
|
923
|
-
)
|
924
|
-
include_git_objects: bool = Field(
|
925
|
-
default=True,
|
926
|
-
description=(
|
927
|
-
"Whether to include git objects when copying the repo contents to a"
|
928
|
-
" directory."
|
929
|
-
),
|
930
|
-
)
|
931
|
-
|
932
|
-
@validator("access_token")
|
933
|
-
def _ensure_credentials_go_with_https(cls, v: str, values: dict) -> str:
|
934
|
-
return validate_github_access_token(v, values)
|
935
|
-
|
936
|
-
def _create_repo_url(self) -> str:
|
937
|
-
"""Format the URL provided to the `git clone` command.
|
938
|
-
|
939
|
-
For private repos: https://<oauth-key>@github.com/<username>/<repo>.git
|
940
|
-
All other repos should be the same as `self.repository`.
|
941
|
-
"""
|
942
|
-
url_components = urllib.parse.urlparse(self.repository)
|
943
|
-
if url_components.scheme == "https" and self.access_token is not None:
|
944
|
-
updated_components = url_components._replace(
|
945
|
-
netloc=f"{self.access_token.get_secret_value()}@{url_components.netloc}"
|
946
|
-
)
|
947
|
-
full_url = urllib.parse.urlunparse(updated_components)
|
948
|
-
else:
|
949
|
-
full_url = self.repository
|
950
|
-
|
951
|
-
return full_url
|
952
|
-
|
953
|
-
@staticmethod
|
954
|
-
def _get_paths(
|
955
|
-
dst_dir: Union[str, None], src_dir: str, sub_directory: str
|
956
|
-
) -> Tuple[str, str]:
|
957
|
-
"""Returns the fully formed paths for GitHubRepository contents in the form
|
958
|
-
(content_source, content_destination).
|
959
|
-
"""
|
960
|
-
if dst_dir is None:
|
961
|
-
content_destination = Path(".").absolute()
|
962
|
-
else:
|
963
|
-
content_destination = Path(dst_dir)
|
964
|
-
|
965
|
-
content_source = Path(src_dir)
|
966
|
-
|
967
|
-
if sub_directory:
|
968
|
-
content_destination = content_destination.joinpath(sub_directory)
|
969
|
-
content_source = content_source.joinpath(sub_directory)
|
970
|
-
|
971
|
-
return str(content_source), str(content_destination)
|
972
|
-
|
973
|
-
@sync_compatible
|
974
|
-
async def get_directory(
|
975
|
-
self, from_path: Optional[str] = None, local_path: Optional[str] = None
|
976
|
-
) -> None:
|
977
|
-
"""
|
978
|
-
Clones a GitHub project specified in `from_path` to the provided `local_path`;
|
979
|
-
defaults to cloning the repository reference configured on the Block to the
|
980
|
-
present working directory.
|
981
|
-
|
982
|
-
Args:
|
983
|
-
from_path: If provided, interpreted as a subdirectory of the underlying
|
984
|
-
repository that will be copied to the provided local path.
|
985
|
-
local_path: A local path to clone to; defaults to present working directory.
|
986
|
-
"""
|
987
|
-
# CONSTRUCT COMMAND
|
988
|
-
cmd = ["git", "clone", self._create_repo_url()]
|
989
|
-
if self.reference:
|
990
|
-
cmd += ["-b", self.reference]
|
991
|
-
|
992
|
-
# Limit git history
|
993
|
-
cmd += ["--depth", "1"]
|
994
|
-
|
995
|
-
# Clone to a temporary directory and move the subdirectory over
|
996
|
-
with TemporaryDirectory(suffix="prefect") as tmp_dir:
|
997
|
-
cmd.append(tmp_dir)
|
998
|
-
|
999
|
-
err_stream = io.StringIO()
|
1000
|
-
out_stream = io.StringIO()
|
1001
|
-
process = await run_process(cmd, stream_output=(out_stream, err_stream))
|
1002
|
-
if process.returncode != 0:
|
1003
|
-
err_stream.seek(0)
|
1004
|
-
raise OSError(f"Failed to pull from remote:\n {err_stream.read()}")
|
1005
|
-
|
1006
|
-
content_source, content_destination = self._get_paths(
|
1007
|
-
dst_dir=local_path, src_dir=tmp_dir, sub_directory=from_path
|
1008
|
-
)
|
1009
|
-
|
1010
|
-
ignore_func = None
|
1011
|
-
if not self.include_git_objects:
|
1012
|
-
ignore_func = ignore_patterns(".git")
|
1013
|
-
|
1014
|
-
copytree(
|
1015
|
-
src=content_source,
|
1016
|
-
dst=content_destination,
|
1017
|
-
dirs_exist_ok=True,
|
1018
|
-
ignore=ignore_func,
|
1019
|
-
)
|