Repository: PrefectHQ/prefect

Issue:
Doc markdown formatting tweaks
- [x] uniform spacing between **Args:**, **Returns:** and **Raises:** sections
- [x] bad code indentation preservation in the main [`Task` docstring](https://prefect-docs.appspot.com/api/core/task.html) (the codeblock `with Flow()...`)
- [ ] fix how class call signatures are formatted
- [x] add docstrings for the various `.copy()` methods (Task, Flow)


Discussion:

Resolving patch:
diff --git a/docs/generate_docs.py b/docs/generate_docs.py
--- a/docs/generate_docs.py
+++ b/docs/generate_docs.py
@@ -175,9 +175,14 @@
     {
         "page": "tasks/function.md",
         "classes": [prefect.tasks.core.function.FunctionTask],
+        "title": "FunctionTask",
     },
-    {"page": "tasks/shell.md", "classes": [prefect.tasks.shell.ShellTask]},
-    {"page": "utilities/bokeh.md", "classes": [BokehRunner]},
+    {
+        "page": "tasks/shell.md",
+        "classes": [prefect.tasks.shell.ShellTask],
+        "title": "ShellTask",
+    },
+    {"page": "utilities/bokeh.md", "classes": [BokehRunner], "title": "BokehRunner"},
     {
         "page": "utilities/collections.md",
         "classes": [prefect.utilities.collections.DotDict],
@@ -308,7 +313,7 @@ def get_call_signature(obj):
         kwargs = list(zip(args[-len(defaults) :], defaults))  # true kwargs
 
     varargs = [f"*{varargs}"] if varargs else []
-    varkwargs = [f"*{varkwargs}"] if varkwargs else []
+    varkwargs = [f"**{varkwargs}"] if varkwargs else []
 
     return standalone, varargs, kwargs, varkwargs
 
@@ -318,8 +323,12 @@ def format_signature(obj):
     standalone, varargs, kwargs, varkwargs = get_call_signature(obj)
     # NOTE: I assume the call signature is f(x, y, ..., *args, z=1, ...,
     # **kwargs) and NOT f(*args, x, y, ...)
+    add_quotes = lambda s: f'"{s}"' if isinstance(s, str) else s
     psig = ", ".join(
-        standalone + varargs + [f"{name}={val}" for name, val in kwargs] + varkwargs
+        standalone
+        + varargs
+        + [f"{name}={add_quotes(val)}" for name, val in kwargs]
+        + varkwargs
     )
     return psig
 
@@ -341,29 +350,27 @@ def get_source(obj):
     begins_at = dir_struct.index("src") + 2
     line_no = inspect.getsourcelines(obj)[1]
     url_ending = "/".join(dir_struct[begins_at:]) + f"#L{line_no}"
-    source_tag = f'<span style="float:right; font-size:0.8em; width: 50%; max-width: 6em;">[[source]]({base_url}{url_ending})</span>'
+    link = f'<a href="{base_url}{url_ending}">[source]</a>'
+    source_tag = f'<span style="text-align:right; float:right; font-size:0.8em; width: 50%; max-width: 6em; display: inline-block;">{link}</span>'
     return source_tag
 
 
 @preprocess
 def format_subheader(obj, level=1, in_table=False):
     class_sig = format_signature(obj)
-    header_attrs = ""
-    if level == 1 and inspect.isclass(obj):
-        header = f"## {obj.__name__}\n\n###"
-
-        # add display: flex to the header to nicely format long signatures
-        header_attrs = r'{style="display: flex; align-items: baseline;"}'
+    if inspect.isclass(obj):
+        header = ""
     elif not in_table:
         header = "##" + "#" * level
     else:
         header = "|"
-    is_class = (
-        '<span style="font-size:0.85em;">Class: </span>' if inspect.isclass(obj) else ""
-    )
-    class_name = f"{create_absolute_path(obj)}.{obj.__qualname__}"
+    is_class = "<em><b>class </b></em>" if inspect.isclass(obj) else ""
+    class_name = f"<b>{create_absolute_path(obj)}.{obj.__qualname__}</b>"
+    div_tag = f"<div class='sig' style='padding-left:3.5em;text-indent:-3.5em;'>"
 
-    call_sig = f" {header} {is_class} ```{class_name}({class_sig})```{get_source(obj)} {header_attrs}\n"
+    call_sig = (
+        f" {header} {div_tag}{is_class}{class_name}({class_sig}){get_source(obj)}</div>"
+    )
     return call_sig
 
 
@@ -460,7 +467,7 @@ def generate_coverage():
 
             top_doc = page.get("top-level-doc")
             if top_doc is not None:
-                f.write(inspect.getdoc(top_doc) + "\n<hr>\n")
+                f.write(inspect.getdoc(top_doc) + "\n\n")
             for obj in classes:
                 f.write(format_subheader(obj))
 
diff --git a/src/prefect/core/flow.py b/src/prefect/core/flow.py
--- a/src/prefect/core/flow.py
+++ b/src/prefect/core/flow.py
@@ -136,13 +136,13 @@ def __init__(
         for t in tasks or []:
             self.add_task(t)
 
+        self.set_reference_tasks(reference_tasks or [])
         for e in edges or []:
             self.add_edge(
                 upstream_task=e.upstream_task,
                 downstream_task=e.downstream_task,
                 key=e.key,
             )
-        self.set_reference_tasks(reference_tasks or [])
 
         self._prefect_version = prefect.__version__
 
diff --git a/src/prefect/core/task.py b/src/prefect/core/task.py
--- a/src/prefect/core/task.py
+++ b/src/prefect/core/task.py
@@ -175,22 +175,21 @@ def run(self) -> None:  # type: ignore
         """
         The `run()` method is called (with arguments, if appropriate) to run a task.
 
-        In addition to running arbitrary functions, tasks can interact with
-        Prefect in a few ways:
-            1. Return an optional result. When this function runs successfully,
-                the task is considered successful and the result (if any) can be
-                made available to downstream tasks.
-            2. Raise an error. Errors are interpreted as failure.
-            3. Raise a signal. Signals can include `FAIL`, `SUCCESS`, `RETRY`, `SKIP`, etc.
-                and indicate that the task should be put in the indicated
-                state.
-                - `FAIL` will lead to retries if appropriate
-                - `SUCCESS` will cause the task to be marked successful
-                - `RETRY` will cause the task to be marked for retry, even if `max_retries`
-                    has been exceeded
-                - `SKIP` will skip the task and possibly propogate the skip state through the
-                    flow, depending on whether downstream tasks have
-                    `skip_on_upstream_skip=True`.
+        In addition to running arbitrary functions, tasks can interact with Prefect in a few ways:
+        <ul><li> Return an optional result. When this function runs successfully,
+            the task is considered successful and the result (if any) can be
+            made available to downstream tasks. </li>
+        <li> Raise an error. Errors are interpreted as failure. </li>
+        <li> Raise a [signal](../engine/signals.html). Signals can include `FAIL`, `SUCCESS`, `RETRY`, `SKIP`, etc.
+            and indicate that the task should be put in the indicated state.
+                <ul>
+                <li> `FAIL` will lead to retries if appropriate </li>
+                <li> `SUCCESS` will cause the task to be marked successful </li>
+                <li> `RETRY` will cause the task to be marked for retry, even if `max_retries`
+                    has been exceeded </li>
+                <li> `SKIP` will skip the task and possibly propogate the skip state through the
+                    flow, depending on whether downstream tasks have `skip_on_upstream_skip=True`. </li></ul>
+        </li></ul>
         """
         pass
 


Test patch:
diff --git a/tests/core/test_flow.py b/tests/core/test_flow.py
--- a/tests/core/test_flow.py
+++ b/tests/core/test_flow.py
@@ -42,6 +42,13 @@ def test_create_flow_with_name(self):
         f2 = Flow(name="test")
         assert f2.name == "test"
 
+    def test_create_flow_with_edges(self):
+        f1 = Flow(
+            edges=[Edge(upstream_task=Task(), downstream_task=AddTask(), key="x")]
+        )
+        assert len(f1.edges) == 1
+        assert len(f1.tasks) == 2
+
     def test_create_flow_with_version(self):
         f1 = Flow()
         assert f1.version == prefect.config.flows.default_version