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