prefect-client 2.19.1__py3-none-any.whl → 2.19.3__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.
@@ -97,6 +97,10 @@ class WorkPoolStatus(AutoEnum):
97
97
  NOT_READY = AutoEnum.auto()
98
98
  PAUSED = AutoEnum.auto()
99
99
 
100
+ @property
101
+ def display_name(self):
102
+ return self.name.replace("_", " ").capitalize()
103
+
100
104
 
101
105
  class WorkerStatus(AutoEnum):
102
106
  """Enumeration of worker statuses."""
prefect/flows.py CHANGED
@@ -5,7 +5,9 @@ Module containing the base workflow class and decorator - for most use cases, us
5
5
  # This file requires type-checking with pyright because mypy does not yet support PEP612
6
6
  # See https://github.com/python/mypy/issues/8645
7
7
 
8
+ import ast
8
9
  import datetime
10
+ import importlib.util
9
11
  import inspect
10
12
  import os
11
13
  import tempfile
@@ -1640,7 +1642,9 @@ def load_flow_from_script(path: str, flow_name: str = None) -> Flow:
1640
1642
  )
1641
1643
 
1642
1644
 
1643
- def load_flow_from_entrypoint(entrypoint: str) -> Flow:
1645
+ def load_flow_from_entrypoint(
1646
+ entrypoint: str,
1647
+ ) -> Flow:
1644
1648
  """
1645
1649
  Extract a flow object from a script at an entrypoint by running all of the code in the file.
1646
1650
 
@@ -1793,3 +1797,57 @@ async def serve(
1793
1797
  )
1794
1798
 
1795
1799
  await runner.start()
1800
+
1801
+
1802
+ def load_flow_argument_from_entrypoint(
1803
+ entrypoint: str, arg: str = "name"
1804
+ ) -> Optional[str]:
1805
+ """
1806
+ Extract a flow argument from an entrypoint string.
1807
+
1808
+ Loads the source code of the entrypoint and extracts the flow argument from the
1809
+ `flow` decorator.
1810
+
1811
+ Args:
1812
+ entrypoint: a string in the format `<path_to_script>:<flow_func_name>` or a module path
1813
+ to a flow function
1814
+
1815
+ Returns:
1816
+ The flow argument value
1817
+ """
1818
+ if ":" in entrypoint:
1819
+ # split by the last colon once to handle Windows paths with drive letters i.e C:\path\to\file.py:do_stuff
1820
+ path, func_name = entrypoint.rsplit(":", maxsplit=1)
1821
+ source_code = Path(path).read_text()
1822
+ else:
1823
+ path, func_name = entrypoint.rsplit(".", maxsplit=1)
1824
+ spec = importlib.util.find_spec(path)
1825
+ if not spec or not spec.origin:
1826
+ raise ValueError(f"Could not find module {path!r}")
1827
+ source_code = Path(spec.origin).read_text()
1828
+ parsed_code = ast.parse(source_code)
1829
+ func_def = next(
1830
+ (
1831
+ node
1832
+ for node in ast.walk(parsed_code)
1833
+ if isinstance(node, ast.FunctionDef) and node.name == func_name
1834
+ ),
1835
+ None,
1836
+ )
1837
+ if not func_def:
1838
+ raise ValueError(f"Could not find flow {func_name!r} in {path!r}")
1839
+ for decorator in func_def.decorator_list:
1840
+ if (
1841
+ isinstance(decorator, ast.Call)
1842
+ and getattr(decorator.func, "id", "") == "flow"
1843
+ ):
1844
+ for keyword in decorator.keywords:
1845
+ if keyword.arg == arg:
1846
+ return (
1847
+ keyword.value.value
1848
+ ) # Return the string value of the argument
1849
+
1850
+ if arg == "name":
1851
+ return func_name.replace(
1852
+ "_", "-"
1853
+ ) # If no matching decorator or keyword argument is found
prefect/runner/runner.py CHANGED
@@ -78,9 +78,7 @@ from prefect.deployments.runner import (
78
78
  )
79
79
  from prefect.deployments.schedules import FlexibleScheduleList
80
80
  from prefect.events import DeploymentTriggerTypes, TriggerTypes
81
- from prefect.exceptions import (
82
- Abort,
83
- )
81
+ from prefect.exceptions import Abort, ObjectNotFound
84
82
  from prefect.flows import Flow
85
83
  from prefect.logging.loggers import PrefectLogAdapter, flow_run_logger, get_logger
86
84
  from prefect.runner.server import start_webserver
@@ -1130,12 +1128,18 @@ class Runner:
1130
1128
  Run the hooks for a flow.
1131
1129
  """
1132
1130
  if state.is_cancelling():
1133
- flow = await load_flow_from_flow_run(
1134
- flow_run, client=self._client, storage_base_path=str(self._tmp_dir)
1135
- )
1136
- hooks = flow.on_cancellation or []
1131
+ try:
1132
+ flow = await load_flow_from_flow_run(
1133
+ flow_run, client=self._client, storage_base_path=str(self._tmp_dir)
1134
+ )
1135
+ hooks = flow.on_cancellation or []
1137
1136
 
1138
- await _run_hooks(hooks, flow_run, flow, state)
1137
+ await _run_hooks(hooks, flow_run, flow, state)
1138
+ except ObjectNotFound:
1139
+ run_logger = self._get_flow_run_logger(flow_run)
1140
+ run_logger.warning(
1141
+ f"Runner cannot retrieve flow to execute cancellation hooks for flow run {flow_run.id!r}."
1142
+ )
1139
1143
 
1140
1144
  async def _run_on_crashed_hooks(
1141
1145
  self,
@@ -2,8 +2,11 @@
2
2
  Utilities for working with Python callables.
3
3
  """
4
4
 
5
+ import ast
6
+ import importlib.util
5
7
  import inspect
6
8
  from functools import partial
9
+ from pathlib import Path
7
10
  from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple
8
11
 
9
12
  import cloudpickle
@@ -31,7 +34,10 @@ from prefect.exceptions import (
31
34
  ReservedArgumentError,
32
35
  SignatureMismatchError,
33
36
  )
34
- from prefect.logging.loggers import disable_logger
37
+ from prefect.logging.loggers import disable_logger, get_logger
38
+ from prefect.utilities.importtools import safe_load_namespace
39
+
40
+ logger = get_logger(__name__)
35
41
 
36
42
 
37
43
  def get_call_parameters(
@@ -318,9 +324,62 @@ def parameter_schema(fn: Callable) -> ParameterSchema:
318
324
  # `eval_str` is not available in Python < 3.10
319
325
  signature = inspect.signature(fn)
320
326
 
327
+ docstrings = parameter_docstrings(inspect.getdoc(fn))
328
+
329
+ return generate_parameter_schema(signature, docstrings)
330
+
331
+
332
+ def parameter_schema_from_entrypoint(entrypoint: str) -> ParameterSchema:
333
+ """
334
+ Generate a parameter schema from an entrypoint string.
335
+
336
+ Will load the source code of the function and extract the signature and docstring
337
+ to generate the schema.
338
+
339
+ Useful for generating a schema for a function when instantiating the function may
340
+ not be possible due to missing imports or other issues.
341
+
342
+ Args:
343
+ entrypoint: A string representing the entrypoint to a function. The string
344
+ should be in the format of `module.path.to.function:do_stuff`.
345
+
346
+ Returns:
347
+ ParameterSchema: The parameter schema for the function.
348
+ """
349
+ if ":" in entrypoint:
350
+ # split by the last colon once to handle Windows paths with drive letters i.e C:\path\to\file.py:do_stuff
351
+ path, func_name = entrypoint.rsplit(":", maxsplit=1)
352
+ source_code = Path(path).read_text()
353
+ else:
354
+ path, func_name = entrypoint.rsplit(".", maxsplit=1)
355
+ spec = importlib.util.find_spec(path)
356
+ if not spec or not spec.origin:
357
+ raise ValueError(f"Could not find module {path!r}")
358
+ source_code = Path(spec.origin).read_text()
359
+ signature = _generate_signature_from_source(source_code, func_name)
360
+ docstring = _get_docstring_from_source(source_code, func_name)
361
+ return generate_parameter_schema(signature, parameter_docstrings(docstring))
362
+
363
+
364
+ def generate_parameter_schema(
365
+ signature: inspect.Signature, docstrings: Dict[str, str]
366
+ ) -> ParameterSchema:
367
+ """
368
+ Generate a parameter schema from a function signature and docstrings.
369
+
370
+ To get a signature from a function, use `inspect.signature(fn)` or
371
+ `_generate_signature_from_source(source_code, func_name)`.
372
+
373
+ Args:
374
+ signature: The function signature.
375
+ docstrings: A dictionary mapping parameter names to docstrings.
376
+
377
+ Returns:
378
+ ParameterSchema: The parameter schema.
379
+ """
380
+
321
381
  model_fields = {}
322
382
  aliases = {}
323
- docstrings = parameter_docstrings(inspect.getdoc(fn))
324
383
 
325
384
  class ModelConfig:
326
385
  arbitrary_types_allowed = True
@@ -362,3 +421,132 @@ def raise_for_reserved_arguments(fn: Callable, reserved_arguments: Iterable[str]
362
421
  raise ReservedArgumentError(
363
422
  f"{argument!r} is a reserved argument name and cannot be used."
364
423
  )
424
+
425
+
426
+ def _generate_signature_from_source(
427
+ source_code: str, func_name: str
428
+ ) -> inspect.Signature:
429
+ """
430
+ Extract the signature of a function from its source code.
431
+
432
+ Will ignore missing imports and exceptions while loading local class definitions.
433
+
434
+ Args:
435
+ source_code: The source code where the function named `func_name` is declared.
436
+ func_name: The name of the function.
437
+
438
+ Returns:
439
+ The signature of the function.
440
+ """
441
+ # Load the namespace from the source code. Missing imports and exceptions while
442
+ # loading local class definitions are ignored.
443
+ namespace = safe_load_namespace(source_code)
444
+ # Parse the source code into an AST
445
+ parsed_code = ast.parse(source_code)
446
+
447
+ func_def = next(
448
+ (
449
+ node
450
+ for node in ast.walk(parsed_code)
451
+ if isinstance(node, ast.FunctionDef) and node.name == func_name
452
+ ),
453
+ None,
454
+ )
455
+ if func_def is None:
456
+ raise ValueError(f"Function {func_name} not found in source code")
457
+ parameters = []
458
+
459
+ for arg in func_def.args.args:
460
+ name = arg.arg
461
+ annotation = arg.annotation
462
+ if annotation is not None:
463
+ try:
464
+ # Compile and evaluate the annotation
465
+ ann_code = compile(ast.Expression(annotation), "<string>", "eval")
466
+ annotation = eval(ann_code, namespace)
467
+ except Exception as e:
468
+ # Don't raise an error if the annotation evaluation fails. Set the
469
+ # annotation to `inspect.Parameter.empty` instead which is equivalent to
470
+ # not having an annotation.
471
+ logger.debug("Failed to evaluate annotation for %s: %s", name, e)
472
+ annotation = inspect.Parameter.empty
473
+ else:
474
+ annotation = inspect.Parameter.empty
475
+
476
+ param = inspect.Parameter(
477
+ name, inspect.Parameter.POSITIONAL_OR_KEYWORD, annotation=annotation
478
+ )
479
+ parameters.append(param)
480
+
481
+ defaults = [None] * (
482
+ len(func_def.args.args) - len(func_def.args.defaults)
483
+ ) + func_def.args.defaults
484
+ for param, default in zip(parameters, defaults):
485
+ if default is not None:
486
+ try:
487
+ def_code = compile(ast.Expression(default), "<string>", "eval")
488
+ default = eval(def_code, namespace)
489
+ except Exception as e:
490
+ logger.debug(
491
+ "Failed to evaluate default value for %s: %s", param.name, e
492
+ )
493
+ default = None # Set to None if evaluation fails
494
+ parameters[parameters.index(param)] = param.replace(default=default)
495
+
496
+ if func_def.args.vararg:
497
+ parameters.append(
498
+ inspect.Parameter(
499
+ func_def.args.vararg.arg, inspect.Parameter.VAR_POSITIONAL
500
+ )
501
+ )
502
+ if func_def.args.kwarg:
503
+ parameters.append(
504
+ inspect.Parameter(func_def.args.kwarg.arg, inspect.Parameter.VAR_KEYWORD)
505
+ )
506
+
507
+ # Handle return annotation
508
+ return_annotation = func_def.returns
509
+ if return_annotation is not None:
510
+ try:
511
+ ret_ann_code = compile(
512
+ ast.Expression(return_annotation), "<string>", "eval"
513
+ )
514
+ return_annotation = eval(ret_ann_code, namespace)
515
+ except Exception as e:
516
+ logger.debug("Failed to evaluate return annotation: %s", e)
517
+ return_annotation = inspect.Signature.empty
518
+
519
+ return inspect.Signature(parameters, return_annotation=return_annotation)
520
+
521
+
522
+ def _get_docstring_from_source(source_code: str, func_name: str) -> Optional[str]:
523
+ """
524
+ Extract the docstring of a function from its source code.
525
+
526
+ Args:
527
+ source_code (str): The source code of the function.
528
+ func_name (str): The name of the function.
529
+
530
+ Returns:
531
+ The docstring of the function. If the function has no docstring, returns None.
532
+ """
533
+ parsed_code = ast.parse(source_code)
534
+
535
+ func_def = next(
536
+ (
537
+ node
538
+ for node in ast.walk(parsed_code)
539
+ if isinstance(node, ast.FunctionDef) and node.name == func_name
540
+ ),
541
+ None,
542
+ )
543
+ if func_def is None:
544
+ raise ValueError(f"Function {func_name} not found in source code")
545
+
546
+ if (
547
+ func_def.body
548
+ and isinstance(func_def.body[0], ast.Expr)
549
+ and isinstance(func_def.body[0].value, ast.Constant)
550
+ ):
551
+ return func_def.body[0].value.value
552
+ return None
@@ -1,3 +1,4 @@
1
+ import ast
1
2
  import importlib
2
3
  import importlib.util
3
4
  import inspect
@@ -14,8 +15,11 @@ from typing import Any, Callable, Dict, Iterable, NamedTuple, Optional, Union
14
15
  import fsspec
15
16
 
16
17
  from prefect.exceptions import ScriptError
18
+ from prefect.logging.loggers import get_logger
17
19
  from prefect.utilities.filesystem import filename, is_local_path, tmpchdir
18
20
 
21
+ logger = get_logger(__name__)
22
+
19
23
 
20
24
  def to_qualified_name(obj: Any) -> str:
21
25
  """
@@ -356,3 +360,70 @@ class AliasedModuleLoader(Loader):
356
360
  if self.callback is not None:
357
361
  self.callback(self.alias)
358
362
  sys.modules[self.alias] = root_module
363
+
364
+
365
+ def safe_load_namespace(source_code: str):
366
+ """
367
+ Safely load a namespace from source code.
368
+
369
+ This function will attempt to import all modules and classes defined in the source
370
+ code. If an import fails, the error is caught and the import is skipped. This function
371
+ will also attempt to compile and evaluate class and function definitions locally.
372
+
373
+ Args:
374
+ source_code: The source code to load
375
+
376
+ Returns:
377
+ The namespace loaded from the source code. Can be used when evaluating source
378
+ code.
379
+ """
380
+ parsed_code = ast.parse(source_code)
381
+
382
+ namespace = {}
383
+
384
+ # Walk through the AST and find all import statements
385
+ for node in ast.walk(parsed_code):
386
+ if isinstance(node, ast.Import):
387
+ for alias in node.names:
388
+ module_name = alias.name
389
+ as_name = alias.asname if alias.asname else module_name
390
+ try:
391
+ # Attempt to import the module
392
+ namespace[as_name] = importlib.import_module(module_name)
393
+ logger.debug("Successfully imported %s", module_name)
394
+ except ImportError as e:
395
+ logger.debug(f"Failed to import {module_name}: {e}")
396
+ elif isinstance(node, ast.ImportFrom):
397
+ module_name = node.module
398
+ if module_name is None:
399
+ continue
400
+ try:
401
+ module = importlib.import_module(module_name)
402
+ for alias in node.names:
403
+ name = alias.name
404
+ asname = alias.asname if alias.asname else name
405
+ try:
406
+ # Get the specific attribute from the module
407
+ attribute = getattr(module, name)
408
+ namespace[asname] = attribute
409
+ except AttributeError as e:
410
+ logger.debug(
411
+ "Failed to retrieve %s from %s: %s", name, module_name, e
412
+ )
413
+ except ImportError as e:
414
+ logger.debug("Failed to import from %s: %s", node.module, e)
415
+
416
+ # Handle local class definitions
417
+ for node in ast.walk(parsed_code):
418
+ if isinstance(node, (ast.ClassDef, ast.FunctionDef)):
419
+ try:
420
+ # Compile and execute each class and function definition locally
421
+ code = compile(
422
+ ast.Module(body=[node], type_ignores=[]),
423
+ filename="<ast>",
424
+ mode="exec",
425
+ )
426
+ exec(code, namespace)
427
+ except Exception as e:
428
+ logger.debug("Failed to compile class definition: %s", e)
429
+ return namespace
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: prefect-client
3
- Version: 2.19.1
3
+ Version: 2.19.3
4
4
  Summary: Workflow orchestration and management.
5
5
  Home-page: https://www.prefect.io
6
6
  Author: Prefect Technologies, Inc.
@@ -9,7 +9,7 @@ prefect/engine.py,sha256=hGaxEyJB0OSb_fc2sRsoL550DGOeuwttWOY3dQR6wZw,90418
9
9
  prefect/exceptions.py,sha256=Fyl-GXvF9OuKHtsyn5EhWg81pkU1UG3DFHsI1JzhOQE,10851
10
10
  prefect/filesystems.py,sha256=XniPSdBAqywj43X7GyfuWJQIbz07QJ5Y3cVNLhIF3lQ,35260
11
11
  prefect/flow_runs.py,sha256=mFHLavZk1yZ62H3UazuNDBZWAF7AqKttA4rMcHgsVSw,3119
12
- prefect/flows.py,sha256=8eE3n_uOb7gs65STLaSFd8832_o9RdOLtRpqkY6FU7c,73247
12
+ prefect/flows.py,sha256=7Lir_rlrMwgTpuMOrJ56K5xwfVhDv5dYQz_HMrkdZv0,75150
13
13
  prefect/futures.py,sha256=RaWfYIXtH7RsWxQ5QWTTlAzwtVV8XWpXaZT_hLq35vQ,12590
14
14
  prefect/manifests.py,sha256=sTM7j8Us5d49zaydYKWsKb7zJ96v1ChkLkLeR0GFYD8,683
15
15
  prefect/new_flow_engine.py,sha256=A1adTWTBAwPCn6ay003Jsoc2SdYgHV4AcJo1bmpa_7Y,16039
@@ -170,7 +170,7 @@ prefect/client/utilities.py,sha256=7V4IkfC8x_OZuPXGvtIMmwZCOW63hSY8iVQkuRYTR6g,3
170
170
  prefect/client/schemas/__init__.py,sha256=KlyqFV-hMulMkNstBn_0ijoHoIwJZaBj6B1r07UmgvE,607
171
171
  prefect/client/schemas/actions.py,sha256=npka1_fiJ_Y_GU6R_uv8wS2kGiJAu5XXqK5b6S0zy-8,27957
172
172
  prefect/client/schemas/filters.py,sha256=gv57m0bHJqL7Ifsc_vAdRODFomaMVcrGXKAahOSBU4w,35598
173
- prefect/client/schemas/objects.py,sha256=VwCwegu238EobrWuo4WkXlzG0-_M6PXqvMT17F6VUfA,53031
173
+ prefect/client/schemas/objects.py,sha256=Ie82ck5vXXgs0Q_luVe_NJkg_SAYN68d0nTxxFKt31M,53130
174
174
  prefect/client/schemas/responses.py,sha256=XAc95g3PRL9UIkH9_VMuv0ECHKdc19guBLmdt5KefkI,15325
175
175
  prefect/client/schemas/schedules.py,sha256=ZF7fFbkcc8rVdx2MxE8DR0av3FUE9qDPjLreEuV8HfM,12193
176
176
  prefect/client/schemas/sorting.py,sha256=EIQ6FUjUWMwk6fn6ckVLQLXOP-GI5kce7ftjUkDFWV0,2490
@@ -235,7 +235,7 @@ prefect/logging/logging.yml,sha256=UkEewf0c3_dURI2uCU4RrxkhI5Devoa1s93fl7hilcg,3
235
235
  prefect/pydantic/__init__.py,sha256=BsW32X7fvl44J1JQer1tkEpfleMtL2kL5Uy1KmwWvso,2714
236
236
  prefect/pydantic/main.py,sha256=ups_UULBhCPhB-E7X7-Qgbpor1oJdqChRzpD0ZYQH8A,839
237
237
  prefect/runner/__init__.py,sha256=7U-vAOXFkzMfRz1q8Uv6Otsvc0OrPYLLP44srwkJ_8s,89
238
- prefect/runner/runner.py,sha256=Lj_N91SXzCdqhhXWZLNnwuyblpxTTtN52MKYLtM7fNY,44838
238
+ prefect/runner/runner.py,sha256=45sZR2kDvhTODyGmeiRe-bgVWq5JHsmZvFPBsiiyKxA,45147
239
239
  prefect/runner/server.py,sha256=mgjH5SPlj3xu0_pZHg15zw59OSJ5lIzTIZ101s281Oo,10655
240
240
  prefect/runner/storage.py,sha256=iZey8Am51c1fZFpS9iVXWYpKiM_lSocvaJEOZVExhvA,22428
241
241
  prefect/runner/submit.py,sha256=w53VdsqfwjW-M3e8hUAAoVlNrXsvGuuyGpEN0wi3vX0,8537
@@ -255,7 +255,7 @@ prefect/types/__init__.py,sha256=aZvlQ2uXl949sJ_khmxSVkRH3o6edo-eJ_GBGMBN5Yg,313
255
255
  prefect/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
256
256
  prefect/utilities/annotations.py,sha256=bXB43j5Zsq5gaBcJe9qnszBlnNwCTwqSTgcu2OkkRLo,2776
257
257
  prefect/utilities/asyncutils.py,sha256=1xpjGFs72vQTPXfG0ww1mfNBwp0-UbRICLGVeRuiqOg,17010
258
- prefect/utilities/callables.py,sha256=vbgRqfd79iXbh4QhNX1Ig9MTIcj-aAgH5yLSqobd2sM,11657
258
+ prefect/utilities/callables.py,sha256=YKStXG3vA60akk084ve4AH35DS57v_jIQo55eBUMG9c,18292
259
259
  prefect/utilities/collections.py,sha256=0v-NNXxYYzkUTCCNDMNB44AnDv9yj35UYouNraCqlo8,15449
260
260
  prefect/utilities/compat.py,sha256=mNQZDnzyKaOqy-OV-DnmH_dc7CNF5nQgW_EsA4xMr7g,906
261
261
  prefect/utilities/context.py,sha256=BThuUW94-IYgFYTeMIM9KMo8ShT3oiI7w5ajZHzU1j0,1377
@@ -264,7 +264,7 @@ prefect/utilities/dockerutils.py,sha256=O5lIgCej5KGRYU2TC1NzNuIK595uOIWJilhZXYEV
264
264
  prefect/utilities/engine.py,sha256=TKiYqpfgt4zopuI8yvh2e-V9GgLcRrh3TpKRhvLuHdw,25669
265
265
  prefect/utilities/filesystem.py,sha256=M_TeZ1MftjBf7hDLWk-Iphir369TpJ1binMsBKiO9YE,4449
266
266
  prefect/utilities/hashing.py,sha256=EOwZLmoIZImuSTxAvVqInabxJ-4RpEfYeg9e2EDQF8o,1752
267
- prefect/utilities/importtools.py,sha256=isblzKv7EPo7HtnlKYpL4t-GJdtTjUSMmvXgXSMEVZM,11764
267
+ prefect/utilities/importtools.py,sha256=cG0559s8y8N9JJEfUDS9cpRScK2_KthKBpq6-BxbrnU,14561
268
268
  prefect/utilities/math.py,sha256=wLwcKVidpNeWQi1TUIWWLHGjlz9UgboX9FUGhx_CQzo,2821
269
269
  prefect/utilities/names.py,sha256=x-stHcF7_tebJPvB1dz-5FvdXJXNBTg2kFZXSnIBBmk,1657
270
270
  prefect/utilities/processutils.py,sha256=yo_GO48pZzgn4A0IK5irTAoqyUCYvWKDSqHXCrtP8c4,14547
@@ -285,8 +285,8 @@ prefect/workers/block.py,sha256=5bdCuqT-4I-et_8ZLG2y1AODzYiCQwFiivhdt5NMEog,7635
285
285
  prefect/workers/process.py,sha256=pPtCdA7fKQ4OsvoitT-cayZeh5HgLX4xBUYlb2Zad-Q,9475
286
286
  prefect/workers/server.py,sha256=WVZJxR8nTMzK0ov0BD0xw5OyQpT26AxlXbsGQ1OrxeQ,1551
287
287
  prefect/workers/utilities.py,sha256=VfPfAlGtTuDj0-Kb8WlMgAuOfgXCdrGAnKMapPSBrwc,2483
288
- prefect_client-2.19.1.dist-info/LICENSE,sha256=MCxsn8osAkzfxKC4CC_dLcUkU8DZLkyihZ8mGs3Ah3Q,11357
289
- prefect_client-2.19.1.dist-info/METADATA,sha256=X5UJXDm0rxH08gKCwM0U4S6y3szNCNKyLqLAbTz_dNU,7401
290
- prefect_client-2.19.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
291
- prefect_client-2.19.1.dist-info/top_level.txt,sha256=MJZYJgFdbRc2woQCeB4vM6T33tr01TmkEhRcns6H_H4,8
292
- prefect_client-2.19.1.dist-info/RECORD,,
288
+ prefect_client-2.19.3.dist-info/LICENSE,sha256=MCxsn8osAkzfxKC4CC_dLcUkU8DZLkyihZ8mGs3Ah3Q,11357
289
+ prefect_client-2.19.3.dist-info/METADATA,sha256=mZrLCglFtET3Q_ovgbuRaA-E9Mpci-7GKd9OojmlAjI,7401
290
+ prefect_client-2.19.3.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
291
+ prefect_client-2.19.3.dist-info/top_level.txt,sha256=MJZYJgFdbRc2woQCeB4vM6T33tr01TmkEhRcns6H_H4,8
292
+ prefect_client-2.19.3.dist-info/RECORD,,