We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Source Description returns jinja as a string when trying to render Markdown
## Issue
When placing markdown into a source description, it renders as the jinja string rather than markdown.

### Issue description
The jinja string in the sources description is rendered as the string in the documentation.
Schema.yml file:
![image](https://user-images.githubusercontent.com/43586980/58519232-7d945b00-8167-11e9-87ee-06598d2ea4b4.png)

markdown file:
![image](https://user-images.githubusercontent.com/43586980/58519323-e54aa600-8167-11e9-8fa7-083a9cd086ad.png)

rendered description:
![image](https://user-images.githubusercontent.com/43586980/58519340-ff848400-8167-11e9-90d5-75247ab73cdc.png)


### Results
The jinja string is returned instead of rendered markdown like in models descriptions
Should render like this: 
![image](https://user-images.githubusercontent.com/43586980/58519524-ddd7cc80-8168-11e9-851a-c4eeac473093.png)

### System information
The output of `dbt --version`:
```
installed version: 0.13.1
   latest version: 0.13.1

Up to date!
```

The operating system you're running on:

Windows 10

The python version you're using (probably the output of `python --version`)

Python 3.6.8

### Steps to reproduce

create an .md doc 
dummy markdown provided below:
```
{% docs tradein %}

### tradein sample
# h1 Heading 8-)
## h2 Heading
### h3 Heading
#### h4 Heading
##### h5 Heading
###### h6 Heading

{% enddocs %}
```
in schema.yml add a source and reference the doc block created above in the description field

```
sources:
  - name: Amazon_Tradein
   description: '{{ doc("<name>") }}'
```

run
```
dbt docs generate
```
then run
```
dbt docs serve
```
and navigate to the sources description.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `core/dbt/parser/util.py`
Content:
```
1 
2 import dbt.exceptions
3 import dbt.utils
4 
5 
6 def docs(node, manifest, config, column_name=None):
7     """Return a function that will process `doc()` references in jinja, look
8     them up in the manifest, and return the appropriate block contents.
9     """
10     current_project = config.project_name
11 
12     def do_docs(*args):
13         if len(args) == 1:
14             doc_package_name = None
15             doc_name = args[0]
16         elif len(args) == 2:
17             doc_package_name, doc_name = args
18         else:
19             dbt.exceptions.doc_invalid_args(node, args)
20 
21         target_doc = ParserUtils.resolve_doc(
22             manifest, doc_name, doc_package_name, current_project,
23             node.package_name
24         )
25 
26         if target_doc is None:
27             dbt.exceptions.doc_target_not_found(node, doc_name,
28                                                 doc_package_name)
29 
30         return target_doc.block_contents
31 
32     return do_docs
33 
34 
35 class ParserUtils(object):
36     DISABLED = object()
37 
38     @classmethod
39     def resolve_source(cls, manifest, target_source_name,
40                        target_table_name, current_project, node_package):
41         candidate_targets = [current_project, node_package, None]
42         target_source = None
43         for candidate in candidate_targets:
44             target_source = manifest.find_source_by_name(
45                 target_source_name,
46                 target_table_name,
47                 candidate
48             )
49             if target_source is not None:
50                 return target_source
51 
52         return None
53 
54     @classmethod
55     def resolve_ref(cls, manifest, target_model_name, target_model_package,
56                     current_project, node_package):
57         if target_model_package is not None:
58             return manifest.find_refable_by_name(
59                 target_model_name,
60                 target_model_package)
61 
62         target_model = None
63         disabled_target = None
64 
65         # first pass: look for models in the current_project
66         # second pass: look for models in the node's package
67         # final pass: look for models in any package
68         # todo: exclude the packages we have already searched. overriding
69         # a package model in another package doesn't necessarily work atm
70         candidates = [current_project, node_package, None]
71         for candidate in candidates:
72             target_model = manifest.find_refable_by_name(
73                 target_model_name,
74                 candidate)
75 
76             if target_model is not None and dbt.utils.is_enabled(target_model):
77                 return target_model
78 
79             # it's possible that the node is disabled
80             if disabled_target is None:
81                 disabled_target = manifest.find_disabled_by_name(
82                     target_model_name, candidate
83                 )
84 
85         if disabled_target is not None:
86             return cls.DISABLED
87         return None
88 
89     @classmethod
90     def resolve_doc(cls, manifest, target_doc_name, target_doc_package,
91                     current_project, node_package):
92         """Resolve the given documentation. This follows the same algorithm as
93         resolve_ref except the is_enabled checks are unnecessary as docs are
94         always enabled.
95         """
96         if target_doc_package is not None:
97             return manifest.find_docs_by_name(target_doc_name,
98                                               target_doc_package)
99 
100         candidate_targets = [current_project, node_package, None]
101         target_doc = None
102         for candidate in candidate_targets:
103             target_doc = manifest.find_docs_by_name(target_doc_name, candidate)
104             if target_doc is not None:
105                 break
106         return target_doc
107 
108     @classmethod
109     def _get_node_column(cls, node, column_name):
110         """Given a ParsedNode, add some fields that might be missing. Return a
111         reference to the dict that refers to the given column, creating it if
112         it doesn't yet exist.
113         """
114         if not hasattr(node, 'columns'):
115             node.set('columns', {})
116 
117         if column_name in node.columns:
118             column = node.columns[column_name]
119         else:
120             column = {'name': column_name, 'description': ''}
121             node.columns[column_name] = column
122 
123         return column
124 
125     @classmethod
126     def process_docs_for_node(cls, manifest, current_project, node):
127         for docref in node.get('docrefs', []):
128             column_name = docref.get('column_name')
129             if column_name is None:
130                 description = node.get('description', '')
131             else:
132                 column = cls._get_node_column(node, column_name)
133                 description = column.get('description', '')
134             context = {
135                 'doc': docs(node, manifest, current_project, column_name),
136             }
137 
138             # At this point, target_doc is a ParsedDocumentation, and we
139             # know that our documentation string has a 'docs("...")'
140             # pointing at it. We want to render it.
141             description = dbt.clients.jinja.get_rendered(description,
142                                                          context)
143             # now put it back.
144             if column_name is None:
145                 node.set('description', description)
146             else:
147                 column['description'] = description
148 
149     @classmethod
150     def process_docs(cls, manifest, current_project):
151         for node in manifest.nodes.values():
152             cls.process_docs_for_node(manifest, current_project, node)
153         return manifest
154 
155     @classmethod
156     def process_refs_for_node(cls, manifest, current_project, node):
157         """Given a manifest and a node in that manifest, process its refs"""
158         target_model = None
159         target_model_name = None
160         target_model_package = None
161 
162         for ref in node.refs:
163             if len(ref) == 1:
164                 target_model_name = ref[0]
165             elif len(ref) == 2:
166                 target_model_package, target_model_name = ref
167 
168             target_model = cls.resolve_ref(
169                 manifest,
170                 target_model_name,
171                 target_model_package,
172                 current_project,
173                 node.get('package_name'))
174 
175             if target_model is None or target_model is cls.DISABLED:
176                 # This may raise. Even if it doesn't, we don't want to add
177                 # this node to the graph b/c there is no destination node
178                 node.config['enabled'] = False
179                 dbt.utils.invalid_ref_fail_unless_test(
180                     node, target_model_name, target_model_package,
181                     disabled=(target_model is cls.DISABLED)
182                 )
183 
184                 continue
185 
186             target_model_id = target_model.get('unique_id')
187 
188             node.depends_on['nodes'].append(target_model_id)
189             manifest.nodes[node['unique_id']] = node
190 
191     @classmethod
192     def process_refs(cls, manifest, current_project):
193         for node in manifest.nodes.values():
194             cls.process_refs_for_node(manifest, current_project, node)
195         return manifest
196 
197     @classmethod
198     def process_sources_for_node(cls, manifest, current_project, node):
199         target_source = None
200         for source_name, table_name in node.sources:
201             target_source = cls.resolve_source(
202                 manifest,
203                 source_name,
204                 table_name,
205                 current_project,
206                 node.get('package_name'))
207 
208             if target_source is None:
209                 # this folows the same pattern as refs
210                 node.config['enabled'] = False
211                 dbt.utils.invalid_source_fail_unless_test(
212                     node,
213                     source_name,
214                     table_name)
215                 continue
216             target_source_id = target_source.unique_id
217             node.depends_on['nodes'].append(target_source_id)
218             manifest.nodes[node['unique_id']] = node
219 
220     @classmethod
221     def process_sources(cls, manifest, current_project):
222         for node in manifest.nodes.values():
223             cls.process_sources_for_node(manifest, current_project, node)
224         return manifest
225 
226     @classmethod
227     def add_new_refs(cls, manifest, current_project, node, macros):
228         """Given a new node that is not in the manifest, copy the manifest and
229         insert the new node into it as if it were part of regular ref
230         processing
231         """
232         manifest = manifest.deepcopy(config=current_project)
233         # it's ok for macros to silently override a local project macro name
234         manifest.macros.update(macros)
235 
236         if node.unique_id in manifest.nodes:
237             # this should be _impossible_ due to the fact that rpc calls get
238             # a unique ID that starts with 'rpc'!
239             raise dbt.exceptions.raise_duplicate_resource_name(
240                 manifest.nodes[node.unique_id], node
241             )
242         manifest.nodes[node.unique_id] = node
243         cls.process_sources_for_node(manifest, current_project, node)
244         cls.process_refs_for_node(manifest, current_project, node)
245         cls.process_docs_for_node(manifest, current_project, node)
246         return manifest
247
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/core/dbt/parser/util.py b/core/dbt/parser/util.py
--- a/core/dbt/parser/util.py
+++ b/core/dbt/parser/util.py
@@ -1,6 +1,7 @@
 
 import dbt.exceptions
 import dbt.utils
+from dbt.node_types import NodeType
 
 
 def docs(node, manifest, config, column_name=None):
@@ -146,10 +147,27 @@
             else:
                 column['description'] = description
 
+    @classmethod
+    def process_docs_for_source(cls, manifest, current_project, source):
+        context = {
+            'doc': docs(source, manifest, current_project),
+        }
+        table_description = source.get('description', '')
+        source_description = source.get('source_description', '')
+        table_description = dbt.clients.jinja.get_rendered(table_description,
+                                                           context)
+        source_description = dbt.clients.jinja.get_rendered(source_description,
+                                                            context)
+        source.set('description', table_description)
+        source.set('source_description', source_description)
+
     @classmethod
     def process_docs(cls, manifest, current_project):
         for node in manifest.nodes.values():
-            cls.process_docs_for_node(manifest, current_project, node)
+            if node.resource_type == NodeType.Source:
+                cls.process_docs_for_source(manifest, current_project, node)
+            else:
+                cls.process_docs_for_node(manifest, current_project, node)
         return manifest
 
     @classmethod

{"golden_diff": "diff --git a/core/dbt/parser/util.py b/core/dbt/parser/util.py\n--- a/core/dbt/parser/util.py\n+++ b/core/dbt/parser/util.py\n@@ -1,6 +1,7 @@\n \n import dbt.exceptions\n import dbt.utils\n+from dbt.node_types import NodeType\n \n \n def docs(node, manifest, config, column_name=None):\n@@ -146,10 +147,27 @@\n             else:\n                 column['description'] = description\n \n+    @classmethod\n+    def process_docs_for_source(cls, manifest, current_project, source):\n+        context = {\n+            'doc': docs(source, manifest, current_project),\n+        }\n+        table_description = source.get('description', '')\n+        source_description = source.get('source_description', '')\n+        table_description = dbt.clients.jinja.get_rendered(table_description,\n+                                                           context)\n+        source_description = dbt.clients.jinja.get_rendered(source_description,\n+                                                            context)\n+        source.set('description', table_description)\n+        source.set('source_description', source_description)\n+\n     @classmethod\n     def process_docs(cls, manifest, current_project):\n         for node in manifest.nodes.values():\n-            cls.process_docs_for_node(manifest, current_project, node)\n+            if node.resource_type == NodeType.Source:\n+                cls.process_docs_for_source(manifest, current_project, node)\n+            else:\n+                cls.process_docs_for_node(manifest, current_project, node)\n         return manifest\n \n     @classmethod\n", "issue": "Source Description returns jinja as a string when trying to render Markdown\n## Issue\r\nWhen placing markdown into a source description, it renders as the jinja string rather than markdown.\r\n\r\n### Issue description\r\nThe jinja string in the sources description is rendered as the string in the documentation.\r\nSchema.yml file:\r\n![image](https://user-images.githubusercontent.com/43586980/58519232-7d945b00-8167-11e9-87ee-06598d2ea4b4.png)\r\n\r\nmarkdown file:\r\n![image](https://user-images.githubusercontent.com/43586980/58519323-e54aa600-8167-11e9-8fa7-083a9cd086ad.png)\r\n\r\nrendered description:\r\n![image](https://user-images.githubusercontent.com/43586980/58519340-ff848400-8167-11e9-90d5-75247ab73cdc.png)\r\n\r\n\r\n### Results\r\nThe jinja string is returned instead of rendered markdown like in models descriptions\r\nShould render like this: \r\n![image](https://user-images.githubusercontent.com/43586980/58519524-ddd7cc80-8168-11e9-851a-c4eeac473093.png)\r\n\r\n### System information\r\nThe output of `dbt --version`:\r\n```\r\ninstalled version: 0.13.1\r\n   latest version: 0.13.1\r\n\r\nUp to date!\r\n```\r\n\r\nThe operating system you're running on:\r\n\r\nWindows 10\r\n\r\nThe python version you're using (probably the output of `python --version`)\r\n\r\nPython 3.6.8\r\n\r\n### Steps to reproduce\r\n\r\ncreate an .md doc \r\ndummy markdown provided below:\r\n```\r\n{% docs tradein %}\r\n\r\n### tradein sample\r\n# h1 Heading 8-)\r\n## h2 Heading\r\n### h3 Heading\r\n#### h4 Heading\r\n##### h5 Heading\r\n###### h6 Heading\r\n\r\n{% enddocs %}\r\n```\r\nin schema.yml add a source and reference the doc block created above in the description field\r\n\r\n```\r\nsources:\r\n  - name: Amazon_Tradein\r\n   description: '{{ doc(\"<name>\") }}'\r\n```\r\n\r\nrun\r\n```\r\ndbt docs generate\r\n```\r\nthen run\r\n```\r\ndbt docs serve\r\n```\r\nand navigate to the sources description.\n", "before_files": [{"content": "\nimport dbt.exceptions\nimport dbt.utils\n\n\ndef docs(node, manifest, config, column_name=None):\n    \"\"\"Return a function that will process `doc()` references in jinja, look\n    them up in the manifest, and return the appropriate block contents.\n    \"\"\"\n    current_project = config.project_name\n\n    def do_docs(*args):\n        if len(args) == 1:\n            doc_package_name = None\n            doc_name = args[0]\n        elif len(args) == 2:\n            doc_package_name, doc_name = args\n        else:\n            dbt.exceptions.doc_invalid_args(node, args)\n\n        target_doc = ParserUtils.resolve_doc(\n            manifest, doc_name, doc_package_name, current_project,\n            node.package_name\n        )\n\n        if target_doc is None:\n            dbt.exceptions.doc_target_not_found(node, doc_name,\n                                                doc_package_name)\n\n        return target_doc.block_contents\n\n    return do_docs\n\n\nclass ParserUtils(object):\n    DISABLED = object()\n\n    @classmethod\n    def resolve_source(cls, manifest, target_source_name,\n                       target_table_name, current_project, node_package):\n        candidate_targets = [current_project, node_package, None]\n        target_source = None\n        for candidate in candidate_targets:\n            target_source = manifest.find_source_by_name(\n                target_source_name,\n                target_table_name,\n                candidate\n            )\n            if target_source is not None:\n                return target_source\n\n        return None\n\n    @classmethod\n    def resolve_ref(cls, manifest, target_model_name, target_model_package,\n                    current_project, node_package):\n        if target_model_package is not None:\n            return manifest.find_refable_by_name(\n                target_model_name,\n                target_model_package)\n\n        target_model = None\n        disabled_target = None\n\n        # first pass: look for models in the current_project\n        # second pass: look for models in the node's package\n        # final pass: look for models in any package\n        # todo: exclude the packages we have already searched. overriding\n        # a package model in another package doesn't necessarily work atm\n        candidates = [current_project, node_package, None]\n        for candidate in candidates:\n            target_model = manifest.find_refable_by_name(\n                target_model_name,\n                candidate)\n\n            if target_model is not None and dbt.utils.is_enabled(target_model):\n                return target_model\n\n            # it's possible that the node is disabled\n            if disabled_target is None:\n                disabled_target = manifest.find_disabled_by_name(\n                    target_model_name, candidate\n                )\n\n        if disabled_target is not None:\n            return cls.DISABLED\n        return None\n\n    @classmethod\n    def resolve_doc(cls, manifest, target_doc_name, target_doc_package,\n                    current_project, node_package):\n        \"\"\"Resolve the given documentation. This follows the same algorithm as\n        resolve_ref except the is_enabled checks are unnecessary as docs are\n        always enabled.\n        \"\"\"\n        if target_doc_package is not None:\n            return manifest.find_docs_by_name(target_doc_name,\n                                              target_doc_package)\n\n        candidate_targets = [current_project, node_package, None]\n        target_doc = None\n        for candidate in candidate_targets:\n            target_doc = manifest.find_docs_by_name(target_doc_name, candidate)\n            if target_doc is not None:\n                break\n        return target_doc\n\n    @classmethod\n    def _get_node_column(cls, node, column_name):\n        \"\"\"Given a ParsedNode, add some fields that might be missing. Return a\n        reference to the dict that refers to the given column, creating it if\n        it doesn't yet exist.\n        \"\"\"\n        if not hasattr(node, 'columns'):\n            node.set('columns', {})\n\n        if column_name in node.columns:\n            column = node.columns[column_name]\n        else:\n            column = {'name': column_name, 'description': ''}\n            node.columns[column_name] = column\n\n        return column\n\n    @classmethod\n    def process_docs_for_node(cls, manifest, current_project, node):\n        for docref in node.get('docrefs', []):\n            column_name = docref.get('column_name')\n            if column_name is None:\n                description = node.get('description', '')\n            else:\n                column = cls._get_node_column(node, column_name)\n                description = column.get('description', '')\n            context = {\n                'doc': docs(node, manifest, current_project, column_name),\n            }\n\n            # At this point, target_doc is a ParsedDocumentation, and we\n            # know that our documentation string has a 'docs(\"...\")'\n            # pointing at it. We want to render it.\n            description = dbt.clients.jinja.get_rendered(description,\n                                                         context)\n            # now put it back.\n            if column_name is None:\n                node.set('description', description)\n            else:\n                column['description'] = description\n\n    @classmethod\n    def process_docs(cls, manifest, current_project):\n        for node in manifest.nodes.values():\n            cls.process_docs_for_node(manifest, current_project, node)\n        return manifest\n\n    @classmethod\n    def process_refs_for_node(cls, manifest, current_project, node):\n        \"\"\"Given a manifest and a node in that manifest, process its refs\"\"\"\n        target_model = None\n        target_model_name = None\n        target_model_package = None\n\n        for ref in node.refs:\n            if len(ref) == 1:\n                target_model_name = ref[0]\n            elif len(ref) == 2:\n                target_model_package, target_model_name = ref\n\n            target_model = cls.resolve_ref(\n                manifest,\n                target_model_name,\n                target_model_package,\n                current_project,\n                node.get('package_name'))\n\n            if target_model is None or target_model is cls.DISABLED:\n                # This may raise. Even if it doesn't, we don't want to add\n                # this node to the graph b/c there is no destination node\n                node.config['enabled'] = False\n                dbt.utils.invalid_ref_fail_unless_test(\n                    node, target_model_name, target_model_package,\n                    disabled=(target_model is cls.DISABLED)\n                )\n\n                continue\n\n            target_model_id = target_model.get('unique_id')\n\n            node.depends_on['nodes'].append(target_model_id)\n            manifest.nodes[node['unique_id']] = node\n\n    @classmethod\n    def process_refs(cls, manifest, current_project):\n        for node in manifest.nodes.values():\n            cls.process_refs_for_node(manifest, current_project, node)\n        return manifest\n\n    @classmethod\n    def process_sources_for_node(cls, manifest, current_project, node):\n        target_source = None\n        for source_name, table_name in node.sources:\n            target_source = cls.resolve_source(\n                manifest,\n                source_name,\n                table_name,\n                current_project,\n                node.get('package_name'))\n\n            if target_source is None:\n                # this folows the same pattern as refs\n                node.config['enabled'] = False\n                dbt.utils.invalid_source_fail_unless_test(\n                    node,\n                    source_name,\n                    table_name)\n                continue\n            target_source_id = target_source.unique_id\n            node.depends_on['nodes'].append(target_source_id)\n            manifest.nodes[node['unique_id']] = node\n\n    @classmethod\n    def process_sources(cls, manifest, current_project):\n        for node in manifest.nodes.values():\n            cls.process_sources_for_node(manifest, current_project, node)\n        return manifest\n\n    @classmethod\n    def add_new_refs(cls, manifest, current_project, node, macros):\n        \"\"\"Given a new node that is not in the manifest, copy the manifest and\n        insert the new node into it as if it were part of regular ref\n        processing\n        \"\"\"\n        manifest = manifest.deepcopy(config=current_project)\n        # it's ok for macros to silently override a local project macro name\n        manifest.macros.update(macros)\n\n        if node.unique_id in manifest.nodes:\n            # this should be _impossible_ due to the fact that rpc calls get\n            # a unique ID that starts with 'rpc'!\n            raise dbt.exceptions.raise_duplicate_resource_name(\n                manifest.nodes[node.unique_id], node\n            )\n        manifest.nodes[node.unique_id] = node\n        cls.process_sources_for_node(manifest, current_project, node)\n        cls.process_refs_for_node(manifest, current_project, node)\n        cls.process_docs_for_node(manifest, current_project, node)\n        return manifest\n", "path": "core/dbt/parser/util.py"}], "after_files": [{"content": "\nimport dbt.exceptions\nimport dbt.utils\nfrom dbt.node_types import NodeType\n\n\ndef docs(node, manifest, config, column_name=None):\n    \"\"\"Return a function that will process `doc()` references in jinja, look\n    them up in the manifest, and return the appropriate block contents.\n    \"\"\"\n    current_project = config.project_name\n\n    def do_docs(*args):\n        if len(args) == 1:\n            doc_package_name = None\n            doc_name = args[0]\n        elif len(args) == 2:\n            doc_package_name, doc_name = args\n        else:\n            dbt.exceptions.doc_invalid_args(node, args)\n\n        target_doc = ParserUtils.resolve_doc(\n            manifest, doc_name, doc_package_name, current_project,\n            node.package_name\n        )\n\n        if target_doc is None:\n            dbt.exceptions.doc_target_not_found(node, doc_name,\n                                                doc_package_name)\n\n        return target_doc.block_contents\n\n    return do_docs\n\n\nclass ParserUtils(object):\n    DISABLED = object()\n\n    @classmethod\n    def resolve_source(cls, manifest, target_source_name,\n                       target_table_name, current_project, node_package):\n        candidate_targets = [current_project, node_package, None]\n        target_source = None\n        for candidate in candidate_targets:\n            target_source = manifest.find_source_by_name(\n                target_source_name,\n                target_table_name,\n                candidate\n            )\n            if target_source is not None:\n                return target_source\n\n        return None\n\n    @classmethod\n    def resolve_ref(cls, manifest, target_model_name, target_model_package,\n                    current_project, node_package):\n        if target_model_package is not None:\n            return manifest.find_refable_by_name(\n                target_model_name,\n                target_model_package)\n\n        target_model = None\n        disabled_target = None\n\n        # first pass: look for models in the current_project\n        # second pass: look for models in the node's package\n        # final pass: look for models in any package\n        # todo: exclude the packages we have already searched. overriding\n        # a package model in another package doesn't necessarily work atm\n        candidates = [current_project, node_package, None]\n        for candidate in candidates:\n            target_model = manifest.find_refable_by_name(\n                target_model_name,\n                candidate)\n\n            if target_model is not None and dbt.utils.is_enabled(target_model):\n                return target_model\n\n            # it's possible that the node is disabled\n            if disabled_target is None:\n                disabled_target = manifest.find_disabled_by_name(\n                    target_model_name, candidate\n                )\n\n        if disabled_target is not None:\n            return cls.DISABLED\n        return None\n\n    @classmethod\n    def resolve_doc(cls, manifest, target_doc_name, target_doc_package,\n                    current_project, node_package):\n        \"\"\"Resolve the given documentation. This follows the same algorithm as\n        resolve_ref except the is_enabled checks are unnecessary as docs are\n        always enabled.\n        \"\"\"\n        if target_doc_package is not None:\n            return manifest.find_docs_by_name(target_doc_name,\n                                              target_doc_package)\n\n        candidate_targets = [current_project, node_package, None]\n        target_doc = None\n        for candidate in candidate_targets:\n            target_doc = manifest.find_docs_by_name(target_doc_name, candidate)\n            if target_doc is not None:\n                break\n        return target_doc\n\n    @classmethod\n    def _get_node_column(cls, node, column_name):\n        \"\"\"Given a ParsedNode, add some fields that might be missing. Return a\n        reference to the dict that refers to the given column, creating it if\n        it doesn't yet exist.\n        \"\"\"\n        if not hasattr(node, 'columns'):\n            node.set('columns', {})\n\n        if column_name in node.columns:\n            column = node.columns[column_name]\n        else:\n            column = {'name': column_name, 'description': ''}\n            node.columns[column_name] = column\n\n        return column\n\n    @classmethod\n    def process_docs_for_node(cls, manifest, current_project, node):\n        for docref in node.get('docrefs', []):\n            column_name = docref.get('column_name')\n            if column_name is None:\n                description = node.get('description', '')\n            else:\n                column = cls._get_node_column(node, column_name)\n                description = column.get('description', '')\n            context = {\n                'doc': docs(node, manifest, current_project, column_name),\n            }\n\n            # At this point, target_doc is a ParsedDocumentation, and we\n            # know that our documentation string has a 'docs(\"...\")'\n            # pointing at it. We want to render it.\n            description = dbt.clients.jinja.get_rendered(description,\n                                                         context)\n            # now put it back.\n            if column_name is None:\n                node.set('description', description)\n            else:\n                column['description'] = description\n\n    @classmethod\n    def process_docs_for_source(cls, manifest, current_project, source):\n        context = {\n            'doc': docs(source, manifest, current_project),\n        }\n        table_description = source.get('description', '')\n        source_description = source.get('source_description', '')\n        table_description = dbt.clients.jinja.get_rendered(table_description,\n                                                           context)\n        source_description = dbt.clients.jinja.get_rendered(source_description,\n                                                            context)\n        source.set('description', table_description)\n        source.set('source_description', source_description)\n\n    @classmethod\n    def process_docs(cls, manifest, current_project):\n        for node in manifest.nodes.values():\n            if node.resource_type == NodeType.Source:\n                cls.process_docs_for_source(manifest, current_project, node)\n            else:\n                cls.process_docs_for_node(manifest, current_project, node)\n        return manifest\n\n    @classmethod\n    def process_refs_for_node(cls, manifest, current_project, node):\n        \"\"\"Given a manifest and a node in that manifest, process its refs\"\"\"\n        target_model = None\n        target_model_name = None\n        target_model_package = None\n\n        for ref in node.refs:\n            if len(ref) == 1:\n                target_model_name = ref[0]\n            elif len(ref) == 2:\n                target_model_package, target_model_name = ref\n\n            target_model = cls.resolve_ref(\n                manifest,\n                target_model_name,\n                target_model_package,\n                current_project,\n                node.get('package_name'))\n\n            if target_model is None or target_model is cls.DISABLED:\n                # This may raise. Even if it doesn't, we don't want to add\n                # this node to the graph b/c there is no destination node\n                node.config['enabled'] = False\n                dbt.utils.invalid_ref_fail_unless_test(\n                    node, target_model_name, target_model_package,\n                    disabled=(target_model is cls.DISABLED)\n                )\n\n                continue\n\n            target_model_id = target_model.get('unique_id')\n\n            node.depends_on['nodes'].append(target_model_id)\n            manifest.nodes[node['unique_id']] = node\n\n    @classmethod\n    def process_refs(cls, manifest, current_project):\n        for node in manifest.nodes.values():\n            cls.process_refs_for_node(manifest, current_project, node)\n        return manifest\n\n    @classmethod\n    def process_sources_for_node(cls, manifest, current_project, node):\n        target_source = None\n        for source_name, table_name in node.sources:\n            target_source = cls.resolve_source(\n                manifest,\n                source_name,\n                table_name,\n                current_project,\n                node.get('package_name'))\n\n            if target_source is None:\n                # this folows the same pattern as refs\n                node.config['enabled'] = False\n                dbt.utils.invalid_source_fail_unless_test(\n                    node,\n                    source_name,\n                    table_name)\n                continue\n            target_source_id = target_source.unique_id\n            node.depends_on['nodes'].append(target_source_id)\n            manifest.nodes[node['unique_id']] = node\n\n    @classmethod\n    def process_sources(cls, manifest, current_project):\n        for node in manifest.nodes.values():\n            cls.process_sources_for_node(manifest, current_project, node)\n        return manifest\n\n    @classmethod\n    def add_new_refs(cls, manifest, current_project, node, macros):\n        \"\"\"Given a new node that is not in the manifest, copy the manifest and\n        insert the new node into it as if it were part of regular ref\n        processing\n        \"\"\"\n        manifest = manifest.deepcopy(config=current_project)\n        # it's ok for macros to silently override a local project macro name\n        manifest.macros.update(macros)\n\n        if node.unique_id in manifest.nodes:\n            # this should be _impossible_ due to the fact that rpc calls get\n            # a unique ID that starts with 'rpc'!\n            raise dbt.exceptions.raise_duplicate_resource_name(\n                manifest.nodes[node.unique_id], node\n            )\n        manifest.nodes[node.unique_id] = node\n        cls.process_sources_for_node(manifest, current_project, node)\n        cls.process_refs_for_node(manifest, current_project, node)\n        cls.process_docs_for_node(manifest, current_project, node)\n        return manifest\n", "path": "core/dbt/parser/util.py"}]}