flyte 0.0.1b3__py3-none-any.whl → 0.2.0b0__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.

Potentially problematic release.


This version of flyte might be problematic. Click here for more details.

Files changed (209) hide show
  1. flyte/_cli/_common.py +12 -0
  2. {union → flyte}/_cli/_params.py +106 -147
  3. flyte/_cli/_run.py +24 -2
  4. flyte/_cli/main.py +28 -2
  5. flyte/_image.py +1 -2
  6. flyte/_initialize.py +24 -15
  7. flyte/_internal/runtime/convert.py +6 -0
  8. flyte/_run.py +0 -1
  9. flyte/_version.py +2 -2
  10. flyte/config/__init__.py +168 -0
  11. flyte/config/_config.py +196 -0
  12. flyte/config/_internal.py +64 -0
  13. flyte/remote/_console.py +1 -1
  14. flyte/types/_type_engine.py +4 -3
  15. {flyte-0.0.1b3.dist-info → flyte-0.2.0b0.dist-info}/METADATA +1 -1
  16. flyte-0.2.0b0.dist-info/RECORD +204 -0
  17. flyte-0.0.1b3.dist-info/RECORD +0 -390
  18. union/__init__.py +0 -54
  19. union/_api_commons.py +0 -3
  20. union/_bin/__init__.py +0 -0
  21. union/_bin/runtime.py +0 -113
  22. union/_build.py +0 -25
  23. union/_cache/__init__.py +0 -12
  24. union/_cache/cache.py +0 -141
  25. union/_cache/defaults.py +0 -9
  26. union/_cache/policy_function_body.py +0 -42
  27. union/_cli/__init__.py +0 -0
  28. union/_cli/_common.py +0 -263
  29. union/_cli/_create.py +0 -40
  30. union/_cli/_delete.py +0 -23
  31. union/_cli/_deploy.py +0 -120
  32. union/_cli/_get.py +0 -162
  33. union/_cli/_run.py +0 -150
  34. union/_cli/main.py +0 -72
  35. union/_code_bundle/__init__.py +0 -8
  36. union/_code_bundle/_ignore.py +0 -113
  37. union/_code_bundle/_packaging.py +0 -187
  38. union/_code_bundle/_utils.py +0 -342
  39. union/_code_bundle/bundle.py +0 -176
  40. union/_context.py +0 -146
  41. union/_datastructures.py +0 -295
  42. union/_deploy.py +0 -185
  43. union/_doc.py +0 -29
  44. union/_docstring.py +0 -26
  45. union/_environment.py +0 -43
  46. union/_group.py +0 -31
  47. union/_hash.py +0 -23
  48. union/_image.py +0 -760
  49. union/_initialize.py +0 -585
  50. union/_interface.py +0 -84
  51. union/_internal/__init__.py +0 -3
  52. union/_internal/controllers/__init__.py +0 -77
  53. union/_internal/controllers/_local_controller.py +0 -77
  54. union/_internal/controllers/pbhash.py +0 -39
  55. union/_internal/controllers/remote/__init__.py +0 -40
  56. union/_internal/controllers/remote/_action.py +0 -131
  57. union/_internal/controllers/remote/_client.py +0 -43
  58. union/_internal/controllers/remote/_controller.py +0 -169
  59. union/_internal/controllers/remote/_core.py +0 -341
  60. union/_internal/controllers/remote/_informer.py +0 -260
  61. union/_internal/controllers/remote/_service_protocol.py +0 -44
  62. union/_internal/imagebuild/__init__.py +0 -11
  63. union/_internal/imagebuild/docker_builder.py +0 -416
  64. union/_internal/imagebuild/image_builder.py +0 -243
  65. union/_internal/imagebuild/remote_builder.py +0 -0
  66. union/_internal/resolvers/__init__.py +0 -0
  67. union/_internal/resolvers/_task_module.py +0 -31
  68. union/_internal/resolvers/common.py +0 -24
  69. union/_internal/resolvers/default.py +0 -27
  70. union/_internal/runtime/__init__.py +0 -0
  71. union/_internal/runtime/convert.py +0 -163
  72. union/_internal/runtime/entrypoints.py +0 -121
  73. union/_internal/runtime/io.py +0 -136
  74. union/_internal/runtime/resources_serde.py +0 -134
  75. union/_internal/runtime/task_serde.py +0 -202
  76. union/_internal/runtime/taskrunner.py +0 -179
  77. union/_internal/runtime/types_serde.py +0 -53
  78. union/_logging.py +0 -124
  79. union/_protos/__init__.py +0 -0
  80. union/_protos/common/authorization_pb2.py +0 -66
  81. union/_protos/common/authorization_pb2.pyi +0 -106
  82. union/_protos/common/authorization_pb2_grpc.py +0 -4
  83. union/_protos/common/identifier_pb2.py +0 -71
  84. union/_protos/common/identifier_pb2.pyi +0 -82
  85. union/_protos/common/identifier_pb2_grpc.py +0 -4
  86. union/_protos/common/identity_pb2.py +0 -48
  87. union/_protos/common/identity_pb2.pyi +0 -72
  88. union/_protos/common/identity_pb2_grpc.py +0 -4
  89. union/_protos/common/list_pb2.py +0 -36
  90. union/_protos/common/list_pb2.pyi +0 -69
  91. union/_protos/common/list_pb2_grpc.py +0 -4
  92. union/_protos/common/policy_pb2.py +0 -37
  93. union/_protos/common/policy_pb2.pyi +0 -27
  94. union/_protos/common/policy_pb2_grpc.py +0 -4
  95. union/_protos/common/role_pb2.py +0 -37
  96. union/_protos/common/role_pb2.pyi +0 -51
  97. union/_protos/common/role_pb2_grpc.py +0 -4
  98. union/_protos/common/runtime_version_pb2.py +0 -28
  99. union/_protos/common/runtime_version_pb2.pyi +0 -24
  100. union/_protos/common/runtime_version_pb2_grpc.py +0 -4
  101. union/_protos/logs/dataplane/payload_pb2.py +0 -96
  102. union/_protos/logs/dataplane/payload_pb2.pyi +0 -168
  103. union/_protos/logs/dataplane/payload_pb2_grpc.py +0 -4
  104. union/_protos/secret/definition_pb2.py +0 -49
  105. union/_protos/secret/definition_pb2.pyi +0 -93
  106. union/_protos/secret/definition_pb2_grpc.py +0 -4
  107. union/_protos/secret/payload_pb2.py +0 -62
  108. union/_protos/secret/payload_pb2.pyi +0 -94
  109. union/_protos/secret/payload_pb2_grpc.py +0 -4
  110. union/_protos/secret/secret_pb2.py +0 -38
  111. union/_protos/secret/secret_pb2.pyi +0 -6
  112. union/_protos/secret/secret_pb2_grpc.py +0 -198
  113. union/_protos/validate/validate/validate_pb2.py +0 -76
  114. union/_protos/workflow/node_execution_service_pb2.py +0 -26
  115. union/_protos/workflow/node_execution_service_pb2.pyi +0 -4
  116. union/_protos/workflow/node_execution_service_pb2_grpc.py +0 -32
  117. union/_protos/workflow/queue_service_pb2.py +0 -75
  118. union/_protos/workflow/queue_service_pb2.pyi +0 -103
  119. union/_protos/workflow/queue_service_pb2_grpc.py +0 -172
  120. union/_protos/workflow/run_definition_pb2.py +0 -100
  121. union/_protos/workflow/run_definition_pb2.pyi +0 -256
  122. union/_protos/workflow/run_definition_pb2_grpc.py +0 -4
  123. union/_protos/workflow/run_logs_service_pb2.py +0 -41
  124. union/_protos/workflow/run_logs_service_pb2.pyi +0 -28
  125. union/_protos/workflow/run_logs_service_pb2_grpc.py +0 -69
  126. union/_protos/workflow/run_service_pb2.py +0 -133
  127. union/_protos/workflow/run_service_pb2.pyi +0 -173
  128. union/_protos/workflow/run_service_pb2_grpc.py +0 -412
  129. union/_protos/workflow/state_service_pb2.py +0 -58
  130. union/_protos/workflow/state_service_pb2.pyi +0 -69
  131. union/_protos/workflow/state_service_pb2_grpc.py +0 -138
  132. union/_protos/workflow/task_definition_pb2.py +0 -72
  133. union/_protos/workflow/task_definition_pb2.pyi +0 -65
  134. union/_protos/workflow/task_definition_pb2_grpc.py +0 -4
  135. union/_protos/workflow/task_service_pb2.py +0 -44
  136. union/_protos/workflow/task_service_pb2.pyi +0 -31
  137. union/_protos/workflow/task_service_pb2_grpc.py +0 -104
  138. union/_resources.py +0 -226
  139. union/_retry.py +0 -32
  140. union/_reusable_environment.py +0 -25
  141. union/_run.py +0 -374
  142. union/_secret.py +0 -61
  143. union/_task.py +0 -354
  144. union/_task_environment.py +0 -186
  145. union/_timeout.py +0 -47
  146. union/_tools.py +0 -27
  147. union/_utils/__init__.py +0 -11
  148. union/_utils/asyn.py +0 -119
  149. union/_utils/file_handling.py +0 -71
  150. union/_utils/helpers.py +0 -46
  151. union/_utils/lazy_module.py +0 -54
  152. union/_utils/uv_script_parser.py +0 -49
  153. union/_version.py +0 -21
  154. union/connectors/__init__.py +0 -0
  155. union/errors.py +0 -128
  156. union/extras/__init__.py +0 -5
  157. union/extras/_container.py +0 -263
  158. union/io/__init__.py +0 -11
  159. union/io/_dataframe.py +0 -0
  160. union/io/_dir.py +0 -425
  161. union/io/_file.py +0 -418
  162. union/io/pickle/__init__.py +0 -0
  163. union/io/pickle/transformer.py +0 -117
  164. union/io/structured_dataset/__init__.py +0 -122
  165. union/io/structured_dataset/basic_dfs.py +0 -219
  166. union/io/structured_dataset/structured_dataset.py +0 -1057
  167. union/py.typed +0 -0
  168. union/remote/__init__.py +0 -23
  169. union/remote/_client/__init__.py +0 -0
  170. union/remote/_client/_protocols.py +0 -129
  171. union/remote/_client/auth/__init__.py +0 -12
  172. union/remote/_client/auth/_authenticators/__init__.py +0 -0
  173. union/remote/_client/auth/_authenticators/base.py +0 -391
  174. union/remote/_client/auth/_authenticators/client_credentials.py +0 -73
  175. union/remote/_client/auth/_authenticators/device_code.py +0 -120
  176. union/remote/_client/auth/_authenticators/external_command.py +0 -77
  177. union/remote/_client/auth/_authenticators/factory.py +0 -200
  178. union/remote/_client/auth/_authenticators/pkce.py +0 -515
  179. union/remote/_client/auth/_channel.py +0 -184
  180. union/remote/_client/auth/_client_config.py +0 -83
  181. union/remote/_client/auth/_default_html.py +0 -32
  182. union/remote/_client/auth/_grpc_utils/__init__.py +0 -0
  183. union/remote/_client/auth/_grpc_utils/auth_interceptor.py +0 -204
  184. union/remote/_client/auth/_grpc_utils/default_metadata_interceptor.py +0 -144
  185. union/remote/_client/auth/_keyring.py +0 -154
  186. union/remote/_client/auth/_token_client.py +0 -258
  187. union/remote/_client/auth/errors.py +0 -16
  188. union/remote/_client/controlplane.py +0 -86
  189. union/remote/_data.py +0 -149
  190. union/remote/_logs.py +0 -74
  191. union/remote/_project.py +0 -86
  192. union/remote/_run.py +0 -820
  193. union/remote/_secret.py +0 -132
  194. union/remote/_task.py +0 -193
  195. union/report/__init__.py +0 -3
  196. union/report/_report.py +0 -178
  197. union/report/_template.html +0 -124
  198. union/storage/__init__.py +0 -24
  199. union/storage/_remote_fs.py +0 -34
  200. union/storage/_storage.py +0 -247
  201. union/storage/_utils.py +0 -5
  202. union/types/__init__.py +0 -11
  203. union/types/_renderer.py +0 -162
  204. union/types/_string_literals.py +0 -120
  205. union/types/_type_engine.py +0 -2131
  206. union/types/_utils.py +0 -80
  207. {flyte-0.0.1b3.dist-info → flyte-0.2.0b0.dist-info}/WHEEL +0 -0
  208. {flyte-0.0.1b3.dist-info → flyte-0.2.0b0.dist-info}/entry_points.txt +0 -0
  209. {flyte-0.0.1b3.dist-info → flyte-0.2.0b0.dist-info}/top_level.txt +0 -0
union/_deploy.py DELETED
@@ -1,185 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import asyncio
4
- from dataclasses import dataclass
5
- from typing import TYPE_CHECKING, Dict, List, Optional, Tuple
6
-
7
- import rich.repr
8
-
9
- from ._api_commons import syncer
10
- from ._datastructures import SerializationContext
11
- from ._environment import Environment
12
- from ._image import Image
13
- from ._initialize import get_client, get_common_config, requires_client, requires_initialization
14
- from ._logging import logger
15
- from ._task import TaskTemplate
16
- from ._task_environment import TaskEnvironment
17
-
18
- if TYPE_CHECKING:
19
- from union._protos.workflow import task_definition_pb2
20
-
21
- from ._code_bundle import CopyFiles
22
- from ._internal.imagebuild.image_builder import ImageCache
23
-
24
-
25
- @rich.repr.auto
26
- @dataclass
27
- class DeploymentPlan:
28
- envs: Dict[str, Environment]
29
- version: Optional[str] = None
30
-
31
-
32
- @rich.repr.auto
33
- @dataclass
34
- class Deployment:
35
- envs: Dict[str, Environment]
36
- deployed_tasks: List[task_definition_pb2.TaskSpec] | None = None
37
-
38
-
39
- @requires_client
40
- async def _deploy_task(
41
- task: TaskTemplate, serialization_context: SerializationContext, dryrun: bool = False
42
- ) -> task_definition_pb2.TaskSpec:
43
- """
44
- Deploy the given task.
45
- """
46
- from ._internal.runtime.task_serde import translate_task_to_wire
47
- from ._protos.workflow import task_definition_pb2, task_service_pb2
48
-
49
- image_uri = task.image.uri if isinstance(task.image, Image) else task.image
50
-
51
- spec = translate_task_to_wire(task, serialization_context)
52
- if dryrun:
53
- return spec
54
- logger.info(f"Deploying task {task.name}, with image {image_uri} and {serialization_context.version=} spec: {spec}")
55
- cfg = get_common_config()
56
- task_id = task_definition_pb2.TaskIdentifier(
57
- org=cfg.org,
58
- project=cfg.project,
59
- domain=cfg.domain,
60
- version=serialization_context.version,
61
- name=spec.task_template.id.name,
62
- )
63
-
64
- resp = await get_client().task_service.DeployTask(task_service_pb2.DeployTaskRequest(task_id=task_id, spec=spec))
65
- logger.info(f"Deployed task {task.name}, {resp}")
66
- return spec
67
-
68
-
69
- async def _build_image_bg(env_name: str, image: Image) -> Tuple[str, str]:
70
- """
71
- Build the image in the background and return the environment name and the built image.
72
- """
73
- from ._build import build
74
-
75
- logger.info(f"Building image {image.name} for environment {env_name}")
76
- return env_name, await build.aio(image)
77
-
78
-
79
- async def build_images(deployment: DeploymentPlan) -> ImageCache:
80
- """
81
- Build the images for the given deployment plan and update the environment with the built image.
82
- """
83
- from ._internal.imagebuild.image_builder import ImageCache
84
-
85
- images = []
86
- image_identifier_map = {}
87
- for env_name, env in deployment.envs.items():
88
- if not isinstance(env.image, str):
89
- logger.info(f"Building Image for environment {env_name}, image: {env.image}")
90
- images.append(_build_image_bg(env_name, env.image))
91
-
92
- elif env.image == "auto" and "auto" not in image_identifier_map:
93
- auto_image = Image.auto()
94
- image_identifier_map["auto"] = auto_image.uri
95
- final_images = await asyncio.gather(*images)
96
-
97
- for env_name, image_uri in final_images:
98
- logger.info(f"Built Image for environment {env_name}, image: {image_uri}")
99
- env = deployment.envs[env_name]
100
- image_identifier_map[env.image.identifier] = env.image.uri
101
-
102
- return ImageCache(image_lookup=image_identifier_map)
103
-
104
-
105
- @requires_initialization
106
- async def apply(deployment: DeploymentPlan, copy_style: CopyFiles, dryrun: bool = False) -> Deployment:
107
- from ._code_bundle import build_code_bundle
108
-
109
- cfg = get_common_config()
110
- image_cache = await build_images(deployment)
111
- if copy_style == "none":
112
- code_bundle = None
113
- assert deployment.version is not None, "Version must be set when copy_style is none"
114
- else:
115
- code_bundle = await build_code_bundle(from_dir=cfg.root_dir, dryrun=dryrun, copy_style=copy_style)
116
- deployment.version = code_bundle.computed_version
117
-
118
- sc = SerializationContext(
119
- code_bundle=code_bundle,
120
- version=deployment.version or code_bundle.computed_version,
121
- image_cache=image_cache,
122
- )
123
-
124
- tasks = []
125
- for env_name, env in deployment.envs.items():
126
- logger.info(f"Deploying environment {env_name}")
127
- if isinstance(env, TaskEnvironment):
128
- for task in env.tasks.values():
129
- tasks.append(_deploy_task(task, dryrun=dryrun, serialization_context=sc))
130
- return Deployment(envs=deployment.envs, deployed_tasks=await asyncio.gather(*tasks))
131
-
132
-
133
- def _recursive_discover(
134
- planned_envs: Dict[str, Environment], envs: Environment | List[Environment]
135
- ) -> Dict[str, Environment]:
136
- """
137
- Recursively deploy the environment and its dependencies, if not already deployed (present in env_tasks) and
138
- return the updated env_tasks.
139
- """
140
- if isinstance(envs, Environment):
141
- envs = [envs]
142
- for env in envs:
143
- # Skip if the environment is already planned
144
- if env.name in planned_envs:
145
- continue
146
- # Recursively discover dependent environments
147
- for dependent_env in env.env_dep_hints:
148
- _recursive_discover(planned_envs, dependent_env)
149
- # Add the environment to the existing envs
150
- planned_envs[env.name] = env
151
- return planned_envs
152
-
153
-
154
- def plan_deploy(*envs: Environment, version: Optional[str] = None) -> DeploymentPlan:
155
- if envs is None:
156
- return DeploymentPlan({})
157
- planned_envs = _recursive_discover({}, *envs)
158
- return DeploymentPlan(planned_envs, version=version)
159
-
160
-
161
- @syncer.wrap
162
- async def deploy(
163
- *envs: Environment,
164
- dryrun: bool = False,
165
- version: str | None = None,
166
- interactive_mode: bool | None = None,
167
- copy_style: CopyFiles = "loaded_modules",
168
- ) -> Deployment:
169
- """
170
- Deploy the given environment or list of environments.
171
- :param envs: Environment or list of environments to deploy.
172
- :param dryrun: dryrun mode, if True, the deployment will not be applied to the control plane.
173
- :param version: version of the deployment, if None, the version will be computed from the code bundle.
174
- TODO: Support for interactive_mode
175
- :param interactive_mode: Optional, can be forced to True or False.
176
- If not provided, it will be set based on the current environment. For example Jupyter notebooks are considered
177
- interactive mode, while scripts are not. This is used to determine how the code bundle is created.
178
- :param copy_style: Copy style to use when running the task
179
-
180
- :return: Deployment object containing the deployed environments and tasks.
181
- """
182
- if interactive_mode:
183
- raise NotImplementedError("Interactive mode not yet implemented for deployment")
184
- deployment = plan_deploy(*envs, version=version)
185
- return await apply(deployment, copy_style=copy_style, dryrun=dryrun)
union/_doc.py DELETED
@@ -1,29 +0,0 @@
1
- import inspect
2
- from dataclasses import dataclass
3
- from typing import Callable
4
-
5
-
6
- @dataclass
7
- class Documentation:
8
- """
9
- This class is used to store the documentation of a task.
10
-
11
- It can be set explicitly or extracted from the docstring of the task.
12
- """
13
-
14
- description: str
15
-
16
- def __help__str__(self):
17
- return self.description
18
-
19
-
20
- def extract_docstring(func: Callable) -> Documentation:
21
- """
22
- Extracts the description from a docstring.
23
- """
24
- if not func:
25
- return Documentation(description="")
26
- docstring = inspect.getdoc(func)
27
- if not docstring:
28
- return Documentation(description="")
29
- return Documentation(description=docstring)
union/_docstring.py DELETED
@@ -1,26 +0,0 @@
1
- from typing import Callable, Dict, Optional
2
-
3
-
4
- class Docstring(object):
5
- def __init__(self, docstring: Optional[str] = None, callable_: Optional[Callable] = None):
6
- if docstring is not None:
7
- # from docstring_parser import parse
8
- self._parsed_docstring = "" # parse(docstring)
9
- else:
10
- self._parsed_docstring = "" # parse(callable_.__doc__)
11
-
12
- @property
13
- def input_descriptions(self) -> Dict[str, str]:
14
- return {p.arg_name: p.description for p in self._parsed_docstring.params}
15
-
16
- @property
17
- def output_descriptions(self) -> Dict[str, str]:
18
- return {p.return_name: p.description for p in self._parsed_docstring.many_returns}
19
-
20
- @property
21
- def short_description(self) -> Optional[str]:
22
- return self._parsed_docstring.short_description
23
-
24
- @property
25
- def long_description(self) -> Optional[str]:
26
- return self._parsed_docstring.long_description
union/_environment.py DELETED
@@ -1,43 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass, field
4
- from typing import TYPE_CHECKING, Dict, List, Literal, Optional, Union
5
-
6
- import rich.repr
7
-
8
- from union._secret import SecretRequest
9
-
10
- from ._image import Image
11
- from ._resources import Resources
12
-
13
- if TYPE_CHECKING:
14
- from kubernetes.client import V1PodTemplate
15
-
16
-
17
- @rich.repr.auto
18
- @dataclass(init=True, repr=True)
19
- class Environment:
20
- """
21
- :param name: Name of the environment
22
- :param image: Docker image to use for the environment. If set to "auto", will use the default image.
23
- :param resources: Resources to allocate for the environment.
24
- :param env: Environment variables to set for the environment.
25
- :param secrets: Secrets to inject into the environment.
26
- :param env_dep_hints: Environment dependencies to hint, so when you deploy the environment, the dependencies are
27
- also deployed. This is useful when you have a set of environments that depend on each other.
28
- """
29
-
30
- name: str
31
- env_dep_hints: List[Environment] = field(default_factory=list)
32
- pod_template: Optional[Union[str, "V1PodTemplate"]] = None
33
- description: Optional[str] = None
34
- secrets: Optional[SecretRequest] = None
35
- env: Optional[Dict[str, str]] = None
36
- resources: Optional[Resources] = None
37
- image: Union[str, Image, Literal["auto"]] = "auto"
38
-
39
- def add_dependency(self, *env: Environment):
40
- """
41
- Add a dependency to the environment.
42
- """
43
- self.env_dep_hints.extend(env)
union/_group.py DELETED
@@ -1,31 +0,0 @@
1
- from contextlib import contextmanager
2
-
3
- from ._context import internal_ctx
4
- from ._datastructures import GroupData
5
-
6
-
7
- @contextmanager
8
- def group(name: str):
9
- """
10
- Create a new group with the given name. The method is intended to be used as a context manager.
11
-
12
- Example:
13
- ```python
14
- @task
15
- async def my_task():
16
- ...
17
- with group("my_group"):
18
- t1(x,y) # tasks in this block will be grouped under "my_group"
19
- ...
20
- ```
21
-
22
- :param name: The name of the group
23
- """
24
- ctx = internal_ctx()
25
- if ctx.data.task_context is None:
26
- yield
27
- return
28
- tctx = ctx.data.task_context
29
- new_tctx = tctx.replace(group_data=GroupData(name))
30
- with ctx.replace_task_context(new_tctx):
31
- yield
union/_hash.py DELETED
@@ -1,23 +0,0 @@
1
- from typing import Callable, Generic, TypeVar
2
-
3
- T = TypeVar("T")
4
-
5
-
6
- class HashOnReferenceMixin(object):
7
- def __hash__(self):
8
- return hash(id(self))
9
-
10
-
11
- class HashMethod(Generic[T]):
12
- """
13
- Flyte-specific object used to wrap the hash function for a specific type
14
- """
15
-
16
- def __init__(self, function: Callable[[T], str]):
17
- self._function = function
18
-
19
- def calculate(self, obj: T) -> str:
20
- """
21
- Calculate hash for `obj`.
22
- """
23
- return self._function(obj)