prefect-client 2.19.4__py3-none-any.whl → 3.0.0rc2__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.
Files changed (242) hide show
  1. prefect/__init__.py +8 -56
  2. prefect/_internal/compatibility/deprecated.py +6 -115
  3. prefect/_internal/compatibility/experimental.py +4 -79
  4. prefect/_internal/concurrency/api.py +0 -34
  5. prefect/_internal/concurrency/calls.py +0 -6
  6. prefect/_internal/concurrency/cancellation.py +0 -3
  7. prefect/_internal/concurrency/event_loop.py +0 -20
  8. prefect/_internal/concurrency/inspection.py +3 -3
  9. prefect/_internal/concurrency/threads.py +35 -0
  10. prefect/_internal/concurrency/waiters.py +0 -28
  11. prefect/_internal/pydantic/__init__.py +0 -45
  12. prefect/_internal/pydantic/v1_schema.py +21 -22
  13. prefect/_internal/pydantic/v2_schema.py +0 -2
  14. prefect/_internal/pydantic/v2_validated_func.py +18 -23
  15. prefect/_internal/schemas/bases.py +44 -177
  16. prefect/_internal/schemas/fields.py +1 -43
  17. prefect/_internal/schemas/validators.py +60 -158
  18. prefect/artifacts.py +161 -14
  19. prefect/automations.py +39 -4
  20. prefect/blocks/abstract.py +1 -1
  21. prefect/blocks/core.py +268 -148
  22. prefect/blocks/fields.py +2 -57
  23. prefect/blocks/kubernetes.py +8 -12
  24. prefect/blocks/notifications.py +40 -20
  25. prefect/blocks/redis.py +168 -0
  26. prefect/blocks/system.py +22 -11
  27. prefect/blocks/webhook.py +2 -9
  28. prefect/client/base.py +4 -4
  29. prefect/client/cloud.py +8 -13
  30. prefect/client/orchestration.py +362 -340
  31. prefect/client/schemas/actions.py +92 -86
  32. prefect/client/schemas/filters.py +20 -40
  33. prefect/client/schemas/objects.py +158 -152
  34. prefect/client/schemas/responses.py +16 -24
  35. prefect/client/schemas/schedules.py +47 -35
  36. prefect/client/subscriptions.py +2 -2
  37. prefect/client/utilities.py +5 -2
  38. prefect/concurrency/asyncio.py +4 -2
  39. prefect/concurrency/events.py +1 -1
  40. prefect/concurrency/services.py +7 -4
  41. prefect/context.py +195 -27
  42. prefect/deployments/__init__.py +5 -6
  43. prefect/deployments/base.py +7 -5
  44. prefect/deployments/flow_runs.py +185 -0
  45. prefect/deployments/runner.py +50 -45
  46. prefect/deployments/schedules.py +28 -23
  47. prefect/deployments/steps/__init__.py +0 -1
  48. prefect/deployments/steps/core.py +1 -0
  49. prefect/deployments/steps/pull.py +7 -21
  50. prefect/engine.py +12 -2422
  51. prefect/events/actions.py +17 -23
  52. prefect/events/cli/automations.py +19 -6
  53. prefect/events/clients.py +14 -37
  54. prefect/events/filters.py +14 -18
  55. prefect/events/related.py +2 -2
  56. prefect/events/schemas/__init__.py +0 -5
  57. prefect/events/schemas/automations.py +55 -46
  58. prefect/events/schemas/deployment_triggers.py +7 -197
  59. prefect/events/schemas/events.py +36 -65
  60. prefect/events/schemas/labelling.py +10 -14
  61. prefect/events/utilities.py +2 -3
  62. prefect/events/worker.py +2 -3
  63. prefect/filesystems.py +6 -517
  64. prefect/{new_flow_engine.py → flow_engine.py} +315 -74
  65. prefect/flow_runs.py +379 -7
  66. prefect/flows.py +248 -165
  67. prefect/futures.py +187 -345
  68. prefect/infrastructure/__init__.py +0 -27
  69. prefect/infrastructure/provisioners/__init__.py +5 -3
  70. prefect/infrastructure/provisioners/cloud_run.py +11 -6
  71. prefect/infrastructure/provisioners/container_instance.py +11 -7
  72. prefect/infrastructure/provisioners/ecs.py +6 -4
  73. prefect/infrastructure/provisioners/modal.py +8 -5
  74. prefect/input/actions.py +2 -4
  75. prefect/input/run_input.py +9 -9
  76. prefect/logging/formatters.py +0 -2
  77. prefect/logging/handlers.py +3 -11
  78. prefect/logging/loggers.py +2 -2
  79. prefect/manifests.py +2 -1
  80. prefect/records/__init__.py +1 -0
  81. prefect/records/cache_policies.py +179 -0
  82. prefect/records/result_store.py +42 -0
  83. prefect/records/store.py +9 -0
  84. prefect/results.py +43 -39
  85. prefect/runner/runner.py +9 -9
  86. prefect/runner/server.py +6 -10
  87. prefect/runner/storage.py +3 -8
  88. prefect/runner/submit.py +2 -2
  89. prefect/runner/utils.py +2 -2
  90. prefect/serializers.py +24 -35
  91. prefect/server/api/collections_data/views/aggregate-worker-metadata.json +5 -14
  92. prefect/settings.py +76 -136
  93. prefect/states.py +22 -50
  94. prefect/task_engine.py +666 -56
  95. prefect/task_runners.py +272 -300
  96. prefect/task_runs.py +203 -0
  97. prefect/{task_server.py → task_worker.py} +89 -60
  98. prefect/tasks.py +358 -341
  99. prefect/transactions.py +224 -0
  100. prefect/types/__init__.py +61 -82
  101. prefect/utilities/asyncutils.py +195 -136
  102. prefect/utilities/callables.py +121 -41
  103. prefect/utilities/collections.py +23 -38
  104. prefect/utilities/dispatch.py +11 -3
  105. prefect/utilities/dockerutils.py +4 -0
  106. prefect/utilities/engine.py +140 -20
  107. prefect/utilities/importtools.py +26 -27
  108. prefect/utilities/pydantic.py +128 -38
  109. prefect/utilities/schema_tools/hydration.py +5 -1
  110. prefect/utilities/templating.py +12 -2
  111. prefect/variables.py +84 -62
  112. prefect/workers/__init__.py +0 -1
  113. prefect/workers/base.py +26 -18
  114. prefect/workers/process.py +3 -8
  115. prefect/workers/server.py +2 -2
  116. {prefect_client-2.19.4.dist-info → prefect_client-3.0.0rc2.dist-info}/METADATA +23 -21
  117. prefect_client-3.0.0rc2.dist-info/RECORD +179 -0
  118. prefect/_internal/pydantic/_base_model.py +0 -51
  119. prefect/_internal/pydantic/_compat.py +0 -82
  120. prefect/_internal/pydantic/_flags.py +0 -20
  121. prefect/_internal/pydantic/_types.py +0 -8
  122. prefect/_internal/pydantic/utilities/__init__.py +0 -0
  123. prefect/_internal/pydantic/utilities/config_dict.py +0 -72
  124. prefect/_internal/pydantic/utilities/field_validator.py +0 -150
  125. prefect/_internal/pydantic/utilities/model_construct.py +0 -56
  126. prefect/_internal/pydantic/utilities/model_copy.py +0 -55
  127. prefect/_internal/pydantic/utilities/model_dump.py +0 -136
  128. prefect/_internal/pydantic/utilities/model_dump_json.py +0 -112
  129. prefect/_internal/pydantic/utilities/model_fields.py +0 -50
  130. prefect/_internal/pydantic/utilities/model_fields_set.py +0 -29
  131. prefect/_internal/pydantic/utilities/model_json_schema.py +0 -82
  132. prefect/_internal/pydantic/utilities/model_rebuild.py +0 -80
  133. prefect/_internal/pydantic/utilities/model_validate.py +0 -75
  134. prefect/_internal/pydantic/utilities/model_validate_json.py +0 -68
  135. prefect/_internal/pydantic/utilities/model_validator.py +0 -87
  136. prefect/_internal/pydantic/utilities/type_adapter.py +0 -71
  137. prefect/_vendor/__init__.py +0 -0
  138. prefect/_vendor/fastapi/__init__.py +0 -25
  139. prefect/_vendor/fastapi/applications.py +0 -946
  140. prefect/_vendor/fastapi/background.py +0 -3
  141. prefect/_vendor/fastapi/concurrency.py +0 -44
  142. prefect/_vendor/fastapi/datastructures.py +0 -58
  143. prefect/_vendor/fastapi/dependencies/__init__.py +0 -0
  144. prefect/_vendor/fastapi/dependencies/models.py +0 -64
  145. prefect/_vendor/fastapi/dependencies/utils.py +0 -877
  146. prefect/_vendor/fastapi/encoders.py +0 -177
  147. prefect/_vendor/fastapi/exception_handlers.py +0 -40
  148. prefect/_vendor/fastapi/exceptions.py +0 -46
  149. prefect/_vendor/fastapi/logger.py +0 -3
  150. prefect/_vendor/fastapi/middleware/__init__.py +0 -1
  151. prefect/_vendor/fastapi/middleware/asyncexitstack.py +0 -25
  152. prefect/_vendor/fastapi/middleware/cors.py +0 -3
  153. prefect/_vendor/fastapi/middleware/gzip.py +0 -3
  154. prefect/_vendor/fastapi/middleware/httpsredirect.py +0 -3
  155. prefect/_vendor/fastapi/middleware/trustedhost.py +0 -3
  156. prefect/_vendor/fastapi/middleware/wsgi.py +0 -3
  157. prefect/_vendor/fastapi/openapi/__init__.py +0 -0
  158. prefect/_vendor/fastapi/openapi/constants.py +0 -2
  159. prefect/_vendor/fastapi/openapi/docs.py +0 -203
  160. prefect/_vendor/fastapi/openapi/models.py +0 -480
  161. prefect/_vendor/fastapi/openapi/utils.py +0 -485
  162. prefect/_vendor/fastapi/param_functions.py +0 -340
  163. prefect/_vendor/fastapi/params.py +0 -453
  164. prefect/_vendor/fastapi/requests.py +0 -4
  165. prefect/_vendor/fastapi/responses.py +0 -40
  166. prefect/_vendor/fastapi/routing.py +0 -1331
  167. prefect/_vendor/fastapi/security/__init__.py +0 -15
  168. prefect/_vendor/fastapi/security/api_key.py +0 -98
  169. prefect/_vendor/fastapi/security/base.py +0 -6
  170. prefect/_vendor/fastapi/security/http.py +0 -172
  171. prefect/_vendor/fastapi/security/oauth2.py +0 -227
  172. prefect/_vendor/fastapi/security/open_id_connect_url.py +0 -34
  173. prefect/_vendor/fastapi/security/utils.py +0 -10
  174. prefect/_vendor/fastapi/staticfiles.py +0 -1
  175. prefect/_vendor/fastapi/templating.py +0 -3
  176. prefect/_vendor/fastapi/testclient.py +0 -1
  177. prefect/_vendor/fastapi/types.py +0 -3
  178. prefect/_vendor/fastapi/utils.py +0 -235
  179. prefect/_vendor/fastapi/websockets.py +0 -7
  180. prefect/_vendor/starlette/__init__.py +0 -1
  181. prefect/_vendor/starlette/_compat.py +0 -28
  182. prefect/_vendor/starlette/_exception_handler.py +0 -80
  183. prefect/_vendor/starlette/_utils.py +0 -88
  184. prefect/_vendor/starlette/applications.py +0 -261
  185. prefect/_vendor/starlette/authentication.py +0 -159
  186. prefect/_vendor/starlette/background.py +0 -43
  187. prefect/_vendor/starlette/concurrency.py +0 -59
  188. prefect/_vendor/starlette/config.py +0 -151
  189. prefect/_vendor/starlette/convertors.py +0 -87
  190. prefect/_vendor/starlette/datastructures.py +0 -707
  191. prefect/_vendor/starlette/endpoints.py +0 -130
  192. prefect/_vendor/starlette/exceptions.py +0 -60
  193. prefect/_vendor/starlette/formparsers.py +0 -276
  194. prefect/_vendor/starlette/middleware/__init__.py +0 -17
  195. prefect/_vendor/starlette/middleware/authentication.py +0 -52
  196. prefect/_vendor/starlette/middleware/base.py +0 -220
  197. prefect/_vendor/starlette/middleware/cors.py +0 -176
  198. prefect/_vendor/starlette/middleware/errors.py +0 -265
  199. prefect/_vendor/starlette/middleware/exceptions.py +0 -74
  200. prefect/_vendor/starlette/middleware/gzip.py +0 -113
  201. prefect/_vendor/starlette/middleware/httpsredirect.py +0 -19
  202. prefect/_vendor/starlette/middleware/sessions.py +0 -82
  203. prefect/_vendor/starlette/middleware/trustedhost.py +0 -64
  204. prefect/_vendor/starlette/middleware/wsgi.py +0 -147
  205. prefect/_vendor/starlette/requests.py +0 -328
  206. prefect/_vendor/starlette/responses.py +0 -347
  207. prefect/_vendor/starlette/routing.py +0 -933
  208. prefect/_vendor/starlette/schemas.py +0 -154
  209. prefect/_vendor/starlette/staticfiles.py +0 -248
  210. prefect/_vendor/starlette/status.py +0 -199
  211. prefect/_vendor/starlette/templating.py +0 -231
  212. prefect/_vendor/starlette/testclient.py +0 -804
  213. prefect/_vendor/starlette/types.py +0 -30
  214. prefect/_vendor/starlette/websockets.py +0 -193
  215. prefect/agent.py +0 -698
  216. prefect/deployments/deployments.py +0 -1042
  217. prefect/deprecated/__init__.py +0 -0
  218. prefect/deprecated/data_documents.py +0 -350
  219. prefect/deprecated/packaging/__init__.py +0 -12
  220. prefect/deprecated/packaging/base.py +0 -96
  221. prefect/deprecated/packaging/docker.py +0 -146
  222. prefect/deprecated/packaging/file.py +0 -92
  223. prefect/deprecated/packaging/orion.py +0 -80
  224. prefect/deprecated/packaging/serializers.py +0 -171
  225. prefect/events/instrument.py +0 -135
  226. prefect/infrastructure/base.py +0 -323
  227. prefect/infrastructure/container.py +0 -818
  228. prefect/infrastructure/kubernetes.py +0 -920
  229. prefect/infrastructure/process.py +0 -289
  230. prefect/new_task_engine.py +0 -423
  231. prefect/pydantic/__init__.py +0 -76
  232. prefect/pydantic/main.py +0 -39
  233. prefect/software/__init__.py +0 -2
  234. prefect/software/base.py +0 -50
  235. prefect/software/conda.py +0 -199
  236. prefect/software/pip.py +0 -122
  237. prefect/software/python.py +0 -52
  238. prefect/workers/block.py +0 -218
  239. prefect_client-2.19.4.dist-info/RECORD +0 -292
  240. {prefect_client-2.19.4.dist-info → prefect_client-3.0.0rc2.dist-info}/LICENSE +0 -0
  241. {prefect_client-2.19.4.dist-info → prefect_client-3.0.0rc2.dist-info}/WHEEL +0 -0
  242. {prefect_client-2.19.4.dist-info → prefect_client-3.0.0rc2.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 shutil import ignore_patterns
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
- @validator("basepath", pre=True)
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
- @validator("basepath")
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=..., tile="SMB server/hostname", description="SMB server/hostname."
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
- )