Repository: kubeflow/pipelines

Issue:
[feature] Provide a `kfp.components.load_component_from_dict` function
### Feature Area

/area sdk

### What feature would you like to see?

Provide a `load_component_from_dict`  function that calls `ComponentSpec.from_dict` under the hood, which would allw the user to create operators in a fashion similar to the old `dsl.ContainerOp` without having to generate an intermediate yaml representation. The spec of this dictionary can be 1-to-1 with the yaml and this would be easy to maintain.

Today the main loader (`_load_component_spec_from_component_text`) looks like this:
```
    component_dict = load_yaml(text)
    component_spec = ComponentSpec.from_dict(component_dict)
```

Let me skip the yaml...

### What is the use case or pain point?

Forcing the use of yaml files on the SDK users is an arbitrary decision/choice of configuration vessel, and is fairly unnatural in an environment where users are already using a fully featured programming language like python

### Is there a workaround currently?

https://github.com/kubeflow/pipelines/issues/3748#issuecomment-627698554 however it seems to be using the internals of the SDK which means its not future proof or safe to use.

Love this idea? Give it a 👍. We prioritize fulfilling features with the most 👍.



Discussion:
Would a `load_component_spec_from_component_spec(ComponentSpec)` function be desirable as a replacement?
> Would a `load_component_spec_from_component_spec(ComponentSpec)` function be desirable as a replacement?

yes absolutely, as long as this way of building containers is guaranteed to be maintained in the future, it is a pain in the ass to have to re-write all components just to describe basic properties such as image name and inputs and outputs.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.


Resolving patch:
diff --git a/sdk/python/kfp/components/_components.py b/sdk/python/kfp/components/_components.py
--- a/sdk/python/kfp/components/_components.py
+++ b/sdk/python/kfp/components/_components.py
@@ -33,7 +33,7 @@
 _default_component_name = 'Component'
 
 
-def load_component(filename=None, url=None, text=None):
+def load_component(filename=None, url=None, text=None, component_spec=None):
     """Loads component from text, file or URL and creates a task factory
     function.
 
@@ -43,6 +43,7 @@ def load_component(filename=None, url=None, text=None):
         filename: Path of local file containing the component definition.
         url: The URL of the component file data.
         text: A string containing the component file data.
+        component_spec: A ComponentSpec containing the component definition.
 
     Returns:
         A factory function with a strongly-typed signature.
@@ -61,6 +62,8 @@ def load_component(filename=None, url=None, text=None):
         return load_component_from_url(url)
     elif text:
         return load_component_from_text(text)
+    elif component_spec:
+        return load_component_from_spec(component_spec)
     else:
         raise ValueError('Need to specify a source')
 
@@ -120,6 +123,22 @@ def load_component_from_text(text):
         component_spec=component_spec)
 
 
+def load_component_from_spec(component_spec):
+    """Loads component from a ComponentSpec and creates a task factory function.
+
+    Args:
+        component_spec: A ComponentSpec containing the component definition.
+
+    Returns:
+        A factory function with a strongly-typed signature.
+        Once called with the required arguments, the factory constructs a pipeline task instance (ContainerOp).
+    """
+    if component_spec is None:
+        raise TypeError
+    return _create_task_factory_from_component_spec(
+            component_spec=component_spec)
+
+
 def _fix_component_uri(uri: str) -> str:
     #Handling Google Cloud Storage URIs
     if uri.startswith('gs://'):


Test patch: