Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User Documentation Proposal #1200

Merged
merged 46 commits into from
Jan 5, 2023
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
7e7018a
Doc hub
pingsutw Jun 24, 2022
36a225b
Doc hub
pingsutw Jun 24, 2022
27f5e02
Add dochub service
pingsutw Sep 9, 2022
7694442
update flyte remote
pingsutw Sep 14, 2022
771d1c1
Merged master
pingsutw Sep 14, 2022
71760dd
Merged master
pingsutw Sep 15, 2022
3948fb6
update
pingsutw Sep 16, 2022
559754f
Fix tests
pingsutw Sep 27, 2022
6499c42
Fix tests
pingsutw Sep 27, 2022
fb69f0b
Fixed tests
pingsutw Sep 27, 2022
1c65d59
Use doc string description
pingsutw Sep 27, 2022
0f86023
remove create_description_entity endpoint
pingsutw Oct 5, 2022
58598aa
more tests
pingsutw Oct 6, 2022
28d66e4
more tets
pingsutw Oct 6, 2022
40ca982
update workflow spec
pingsutw Oct 7, 2022
0bb5122
fix test
pingsutw Oct 7, 2022
1535204
Upload long description file through data proxy
pingsutw Oct 11, 2022
8930177
rename
pingsutw Oct 13, 2022
1ac181f
update
pingsutw Oct 19, 2022
5625465
update source code
pingsutw Oct 20, 2022
e876e96
merged master
pingsutw Oct 20, 2022
473f6e6
update
pingsutw Oct 21, 2022
95afed6
Merged master
pingsutw Nov 18, 2022
3acfaf2
merged master
pingsutw Nov 18, 2022
08eda7a
nit
pingsutw Nov 18, 2022
5736963
lint
pingsutw Nov 19, 2022
0677c2d
Merged master
pingsutw Dec 19, 2022
c17f832
nit
pingsutw Dec 19, 2022
645af3c
nit
pingsutw Dec 19, 2022
f6f082d
Add git package
pingsutw Dec 19, 2022
a71b1be
Add git package
pingsutw Dec 19, 2022
d45c2d9
update package
pingsutw Dec 19, 2022
61820e0
fix tests
pingsutw Dec 21, 2022
3268c11
Merged master
pingsutw Dec 21, 2022
ccfa2e4
nit
pingsutw Dec 22, 2022
f73e13e
nit
pingsutw Dec 22, 2022
f48f83c
nit
pingsutw Dec 22, 2022
a3a5f7d
set default value to None
pingsutw Dec 29, 2022
44899da
fix tests
pingsutw Dec 29, 2022
e72520c
Merge branch 'master' into doc-hub
pingsutw Dec 29, 2022
75e5961
make get_git_repo_url public
pingsutw Jan 3, 2023
a791f2c
Update doc in get_serializable_flyte_workflow
pingsutw Jan 4, 2023
92f08f0
Merge branch 'master' into doc-hub
wild-endeavor Jan 4, 2023
a4a895d
remove update_description_entity
pingsutw Jan 4, 2023
677919c
lint
pingsutw Jan 4, 2023
c5b7143
Merge branch 'master' into doc-hub
wild-endeavor Jan 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions flytekit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@
from flytekit.models.common import Annotations, AuthRole, Labels
from flytekit.models.core.execution import WorkflowExecutionPhase
from flytekit.models.core.types import BlobType
from flytekit.models.documentation import Description, Documentation, SourceCode
from flytekit.models.literals import Blob, BlobMetadata, Literal, Scalar
from flytekit.models.types import LiteralType
from flytekit.types import directory, file, numpy, schema
Expand Down
6 changes: 5 additions & 1 deletion flytekit/configuration/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ class GCSConfig(object):
gsutil_parallelism: bool = False

@classmethod
def auto(self, config_file: typing.Union[str, ConfigFile] = None) -> GCSConfig:
def auto(cls, config_file: typing.Union[str, ConfigFile] = None) -> GCSConfig:
config_file = get_config_file(config_file)
kwargs = {}
kwargs = set_if_exists(kwargs, "gsutil_parallelism", _internal.GCP.GSUTIL_PARALLELISM.read(config_file))
Expand Down Expand Up @@ -647,6 +647,7 @@ class SerializationSettings(object):
domain: typing.Optional[str] = None
version: typing.Optional[str] = None
env: Optional[Dict[str, str]] = None
git_repo: Optional[str] = None
python_interpreter: str = DEFAULT_RUNTIME_PYTHON_INTERPRETER
flytekit_virtualenv_root: Optional[str] = None
fast_serialization_settings: Optional[FastSerializationSettings] = None
Expand Down Expand Up @@ -719,6 +720,7 @@ def new_builder(self) -> Builder:
version=self.version,
image_config=self.image_config,
env=self.env.copy() if self.env else None,
git_repo=self.git_repo,
flytekit_virtualenv_root=self.flytekit_virtualenv_root,
python_interpreter=self.python_interpreter,
fast_serialization_settings=self.fast_serialization_settings,
Expand Down Expand Up @@ -768,6 +770,7 @@ class Builder(object):
version: str
image_config: ImageConfig
env: Optional[Dict[str, str]] = None
git_repo: Optional[str] = None
flytekit_virtualenv_root: Optional[str] = None
python_interpreter: Optional[str] = None
fast_serialization_settings: Optional[FastSerializationSettings] = None
Expand All @@ -783,6 +786,7 @@ def build(self) -> SerializationSettings:
version=self.version,
image_config=self.image_config,
env=self.env,
git_repo=self.git_repo,
flytekit_virtualenv_root=self.flytekit_virtualenv_root,
python_interpreter=self.python_interpreter,
fast_serialization_settings=self.fast_serialization_settings,
Expand Down
2 changes: 1 addition & 1 deletion flytekit/configuration/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ def legacy_config(self) -> _configparser.ConfigParser:
return self._legacy_config

@property
def yaml_config(self) -> typing.Dict[str, Any]:
def yaml_config(self) -> typing.Dict[str, typing.Any]:
return self._yaml_config


Expand Down
18 changes: 18 additions & 0 deletions flytekit/core/base_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
from flytekit.models import literals as _literal_models
from flytekit.models import task as _task_model
from flytekit.models.core import workflow as _workflow_model
from flytekit.models.documentation import Description, Documentation
from flytekit.models.interface import Variable
from flytekit.models.security import SecurityContext

Expand Down Expand Up @@ -156,6 +157,7 @@ def __init__(
metadata: Optional[TaskMetadata] = None,
task_type_version=0,
security_ctx: Optional[SecurityContext] = None,
docs: Optional[Documentation] = None,
**kwargs,
):
self._task_type = task_type
Expand All @@ -164,6 +166,7 @@ def __init__(
self._metadata = metadata if metadata else TaskMetadata()
self._task_type_version = task_type_version
self._security_ctx = security_ctx
self._docs = docs

FlyteEntities.entities.append(self)

Expand Down Expand Up @@ -195,6 +198,10 @@ def task_type_version(self) -> int:
def security_context(self) -> SecurityContext:
return self._security_ctx

@property
def docs(self) -> Documentation:
return self._docs

def get_type_for_input_var(self, k: str, v: Any) -> type:
"""
Returns the python native type for the given input variable
Expand Down Expand Up @@ -390,6 +397,17 @@ def __init__(
self._environment = environment if environment else {}
self._task_config = task_config
self._disable_deck = disable_deck
if self._python_interface.docstring:
if self.docs is None:
self._docs = Documentation(
short_description=self._python_interface.docstring.short_description,
long_description=Description(value=self._python_interface.docstring.long_description),
)
else:
if self._python_interface.docstring.short_description:
self._docs.short_description = self._python_interface.docstring.short_description
if self._python_interface.docstring.long_description:
self._docs.long_description = Description(value=self._python_interface.docstring.long_description)

# TODO lets call this interface and the other as flyte_interface?
@property
Expand Down
1 change: 0 additions & 1 deletion flytekit/core/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,6 @@ def transform_interface_to_typed_interface(
"""
if interface is None:
return None

if interface.docstring is None:
input_descriptions = output_descriptions = {}
else:
Expand Down
4 changes: 4 additions & 0 deletions flytekit/core/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from flytekit.core.python_function_task import PythonFunctionTask
from flytekit.core.reference_entity import ReferenceEntity, TaskReference
from flytekit.core.resources import Resources
from flytekit.models.documentation import Documentation
from flytekit.models.security import Secret


Expand Down Expand Up @@ -89,6 +90,7 @@ def task(
secret_requests: Optional[List[Secret]] = None,
execution_mode: Optional[PythonFunctionTask.ExecutionBehavior] = PythonFunctionTask.ExecutionBehavior.DEFAULT,
task_resolver: Optional[TaskResolverMixin] = None,
docs: Optional[Documentation] = None,
disable_deck: bool = True,
) -> Union[Callable, PythonFunctionTask]:
"""
Expand Down Expand Up @@ -179,6 +181,7 @@ def foo2():
:param execution_mode: This is mainly for internal use. Please ignore. It is filled in automatically.
:param task_resolver: Provide a custom task resolver.
:param disable_deck: If true, this task will not output deck html file
:param docs: Documentation about this task
"""

def wrapper(fn) -> PythonFunctionTask:
Expand All @@ -204,6 +207,7 @@ def wrapper(fn) -> PythonFunctionTask:
execution_mode=execution_mode,
task_resolver=task_resolver,
disable_deck=disable_deck,
docs=docs,
)
update_wrapper(task_instance, fn)
return task_instance
Expand Down
27 changes: 26 additions & 1 deletion flytekit/core/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
from flytekit.models import interface as _interface_models
from flytekit.models import literals as _literal_models
from flytekit.models.core import workflow as _workflow_model
from flytekit.models.documentation import Description, Documentation

GLOBAL_START_NODE = Node(
id=_common_constants.GLOBAL_INPUT_NODE_ID,
Expand Down Expand Up @@ -168,6 +169,7 @@ def __init__(
workflow_metadata: WorkflowMetadata,
workflow_metadata_defaults: WorkflowMetadataDefaults,
python_interface: Interface,
docs: Optional[Documentation] = None,
**kwargs,
):
self._name = name
Expand All @@ -179,13 +181,31 @@ def __init__(
self._unbound_inputs = set()
self._nodes = []
self._output_bindings: List[_literal_models.Binding] = []
self._docs = docs

if self._python_interface.docstring:
if self.docs is None:
self._docs = Documentation(
short_description=self._python_interface.docstring.short_description,
long_description=Description(value=self._python_interface.docstring.long_description),
)
else:
if self._python_interface.docstring.short_description:
self._docs.short_description = self._python_interface.docstring.short_description
if self._python_interface.docstring.long_description:
self._docs = Description(value=self._python_interface.docstring.long_description)

FlyteEntities.entities.append(self)
super().__init__(**kwargs)

@property
def name(self) -> str:
return self._name

@property
def docs(self):
return self._docs

@property
def short_name(self) -> str:
return extract_obj_name(self._name)
Expand Down Expand Up @@ -571,7 +591,8 @@ def __init__(
workflow_function: Callable,
metadata: Optional[WorkflowMetadata],
default_metadata: Optional[WorkflowMetadataDefaults],
docstring: Docstring = None,
docstring: Optional[Docstring] = None,
docs: Optional[Documentation] = None,
):
name, _, _, _ = extract_task_module(workflow_function)
self._workflow_function = workflow_function
Expand All @@ -586,6 +607,7 @@ def __init__(
workflow_metadata=metadata,
workflow_metadata_defaults=default_metadata,
python_interface=native_interface,
docs=docs,
)

@property
Expand Down Expand Up @@ -690,6 +712,7 @@ def workflow(
_workflow_function=None,
failure_policy: Optional[WorkflowFailurePolicy] = None,
interruptible: bool = False,
docs: Optional[Documentation] = None,
):
"""
This decorator declares a function to be a Flyte workflow. Workflows are declarative entities that construct a DAG
Expand Down Expand Up @@ -718,6 +741,7 @@ def workflow(
:param _workflow_function: This argument is implicitly passed and represents the decorated function.
:param failure_policy: Use the options in flytekit.WorkflowFailurePolicy
:param interruptible: Whether or not tasks launched from this workflow are by default interruptible
:param docs: Description entity for the workflow
"""

def wrapper(fn):
Expand All @@ -730,6 +754,7 @@ def wrapper(fn):
metadata=workflow_metadata,
default_metadata=workflow_metadata_defaults,
docstring=Docstring(callable_=fn),
docs=docs,
)
workflow_instance.compile()
update_wrapper(workflow_instance, fn)
Expand Down
20 changes: 19 additions & 1 deletion flytekit/models/admin/workflow.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
import typing

from flyteidl.admin import workflow_pb2 as _admin_workflow

from flytekit.models import common as _common
from flytekit.models.core import compiler as _compiler_models
from flytekit.models.core import identifier as _identifier
from flytekit.models.core import workflow as _core_workflow
from flytekit.models.documentation import Documentation


class WorkflowSpec(_common.FlyteIdlEntity):
def __init__(self, template, sub_workflows):
def __init__(
self,
template: _core_workflow.WorkflowTemplate,
sub_workflows: typing.List[_core_workflow.WorkflowTemplate],
docs: typing.Optional[Documentation] = None,
):
"""
This object fully encapsulates the specification of a workflow
:param flytekit.models.core.workflow.WorkflowTemplate template:
:param list[flytekit.models.core.workflow.WorkflowTemplate] sub_workflows:
"""
self._template = template
self._sub_workflows = sub_workflows
self._docs = docs

@property
def template(self):
Expand All @@ -30,13 +39,21 @@ def sub_workflows(self):
"""
return self._sub_workflows

@property
def docs(self):
"""
:rtype: Description entity for the workflow
"""
return self._docs

def to_flyte_idl(self):
"""
:rtype: flyteidl.admin.workflow_pb2.WorkflowSpec
"""
return _admin_workflow.WorkflowSpec(
template=self._template.to_flyte_idl(),
sub_workflows=[s.to_flyte_idl() for s in self._sub_workflows],
description=self._docs.to_flyte_idl() if self._docs else None,
)

@classmethod
Expand All @@ -48,6 +65,7 @@ def from_flyte_idl(cls, pb2_object):
return cls(
_core_workflow.WorkflowTemplate.from_flyte_idl(pb2_object.template),
[_core_workflow.WorkflowTemplate.from_flyte_idl(s) for s in pb2_object.sub_workflows],
Documentation.from_flyte_idl(pb2_object.description) if pb2_object.description else None,
)


Expand Down
93 changes: 93 additions & 0 deletions flytekit/models/documentation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
from dataclasses import dataclass
from enum import Enum
from typing import Optional

from flyteidl.admin import description_entity_pb2

from flytekit.models import common as _common_models


@dataclass
class Description(_common_models.FlyteIdlEntity):
"""
Full user description with formatting preserved. This can be rendered
by clients, such as the console or command line tools with in-tact
formatting.
"""

class DescriptionFormat(Enum):
UNKNOWN = 0
MARKDOWN = 1
HTML = 2
RST = 3

value: Optional[str] = None
uri: Optional[str] = None
icon_link: Optional[str] = None
format: DescriptionFormat = DescriptionFormat.RST

def to_flyte_idl(self):
return description_entity_pb2.Description(
value=self.value if self.value else None,
uri=self.uri if self.uri else None,
format=self.format.value,
icon_link=self.icon_link,
)

@classmethod
def from_flyte_idl(cls, pb2_object: description_entity_pb2.Description) -> "Description":
return cls(
value=pb2_object.value if pb2_object.value else None,
uri=pb2_object.uri if pb2_object.uri else None,
format=Description.DescriptionFormat(pb2_object.format),
icon_link=pb2_object.icon_link if pb2_object.icon_link else None,
)


@dataclass
class SourceCode(_common_models.FlyteIdlEntity):
"""
Link to source code used to define this task or workflow.
"""

link: Optional[str] = None

def to_flyte_idl(self):
return description_entity_pb2.SourceCode(link=self.link)

@classmethod
def from_flyte_idl(cls, pb2_object: description_entity_pb2.SourceCode) -> "SourceCode":
return cls(link=pb2_object.link) if pb2_object.link else None


@dataclass
class Documentation(_common_models.FlyteIdlEntity):
"""
DescriptionEntity contains detailed description for the task/workflow/launch plan.
Documentation could provide insight into the algorithms, business use case, etc.
Args:
short_description (str): One-liner overview of the entity.
long_description (Optional[Description]): Full user description with formatting preserved.
source_code (Optional[SourceCode]): link to source code used to define this entity
"""

short_description: Optional[str] = None
long_description: Optional[Description] = None
source_code: Optional[SourceCode] = None

def to_flyte_idl(self):
return description_entity_pb2.DescriptionEntity(
short_description=self.short_description,
long_description=self.long_description.to_flyte_idl() if self.long_description else None,
source_code=self.source_code.to_flyte_idl() if self.source_code else None,
)

@classmethod
def from_flyte_idl(cls, pb2_object: description_entity_pb2.DescriptionEntity) -> "Documentation":
return cls(
short_description=pb2_object.short_description,
long_description=Description.from_flyte_idl(pb2_object.long_description)
if pb2_object.long_description
else None,
source_code=SourceCode.from_flyte_idl(pb2_object.source_code) if pb2_object.source_code else None,
)
Loading