Repository: dbt-labs/dbt-core

Issue:
[PP] Bug when editing yaml file to add version
### Describe the bug

1. Create a `.yml` file with nothing in it:
```yml
# models/schema.yml
```
2. `dbt parse`
3. Add `version: 2` to the `.yml` file:
```yml
# models/schema.yml

version: 2
```
4. `dbt --partial-parse parse`

Error message:
```
Partial parsing enabled: 0 files deleted, 0 files added, 1 files changed.
Encountered an error:
'version'
```

### Stracktrace
```
2021-07-13 21:40:27.083754 (MainThread): Traceback (most recent call last):
  File "/usr/local/Cellar/dbt/0.20.0_1/libexec/lib/python3.8/site-packages/dbt/main.py", line 125, in main
    results, succeeded = handle_and_check(args)
  File "/usr/local/Cellar/dbt/0.20.0_1/libexec/lib/python3.8/site-packages/dbt/main.py", line 203, in handle_and_check
    task, res = run_from_args(parsed)
  File "/usr/local/Cellar/dbt/0.20.0_1/libexec/lib/python3.8/site-packages/dbt/main.py", line 256, in run_from_args
    results = task.run()
  File "/usr/local/Cellar/dbt/0.20.0_1/libexec/lib/python3.8/site-packages/dbt/task/parse.py", line 85, in run
    self.get_full_manifest()
  File "/usr/local/Cellar/dbt/0.20.0_1/libexec/lib/python3.8/site-packages/dbt/task/parse.py", line 64, in get_full_manifest
    manifest = loader.load()
  File "/usr/local/Cellar/dbt/0.20.0_1/libexec/lib/python3.8/site-packages/dbt/parser/manifest.py", line 212, in load
    project_parser_files = partial_parsing.get_parsing_files()
  File "/usr/local/Cellar/dbt/0.20.0_1/libexec/lib/python3.8/site-packages/dbt/parser/partial.py", line 125, in get_parsing_files
    self.change_schema_file(file_id)
  File "/usr/local/Cellar/dbt/0.20.0_1/libexec/lib/python3.8/site-packages/dbt/parser/partial.py", line 429, in change_schema_file
    saved_schema_file.pp_dict = {"version": saved_yaml_dict['version']}
KeyError: 'version'
```

**The output of `dbt --version`:**
```
$ dbt --version
installed version: 0.20.0
   latest version: 0.20.0

Up to date!
```


Discussion:
@gshank this might be a partial parsing bug. Could you please take a look?
The partial parsing code assumes that a SchemaSourceFile from the partial parse file has already been validated and so would have the 'version' key.  Should be easy to fix.

Resolving patch:
diff --git a/core/dbt/parser/partial.py b/core/dbt/parser/partial.py
--- a/core/dbt/parser/partial.py
+++ b/core/dbt/parser/partial.py
@@ -445,7 +445,13 @@ def change_schema_file(self, file_id):
         new_schema_file = self.new_files[file_id]
         saved_yaml_dict = saved_schema_file.dict_from_yaml
         new_yaml_dict = new_schema_file.dict_from_yaml
-        saved_schema_file.pp_dict = {"version": saved_yaml_dict['version']}
+        if 'version' in new_yaml_dict:
+            # despite the fact that this goes in the saved_schema_file, it
+            # should represent the new yaml dictionary, and should produce
+            # an error if the updated yaml file doesn't have a version
+            saved_schema_file.pp_dict = {"version": new_yaml_dict['version']}
+        else:
+            saved_schema_file.pp_dict = {}
         self.handle_schema_file_changes(saved_schema_file, saved_yaml_dict, new_yaml_dict)
 
         # copy from new schema_file to saved_schema_file to preserve references


Test patch:
diff --git a/test/integration/068_partial_parsing_tests/extra-files/empty_schema.yml b/test/integration/068_partial_parsing_tests/extra-files/empty_schema.yml
new file mode 100644
diff --git a/test/integration/068_partial_parsing_tests/extra-files/empty_schema_with_version.yml b/test/integration/068_partial_parsing_tests/extra-files/empty_schema_with_version.yml
new file mode 100644
--- /dev/null
+++ b/test/integration/068_partial_parsing_tests/extra-files/empty_schema_with_version.yml
@@ -0,0 +1 @@
+version: 2
diff --git a/test/integration/068_partial_parsing_tests/test_partial_parsing.py b/test/integration/068_partial_parsing_tests/test_partial_parsing.py
--- a/test/integration/068_partial_parsing_tests/test_partial_parsing.py
+++ b/test/integration/068_partial_parsing_tests/test_partial_parsing.py
@@ -168,6 +168,16 @@ def test_postgres_pp_models(self):
         results = self.run_dbt(["--partial-parse", "run"])
         self.assertEqual(len(results), 3)
 
+        # Add an empty schema file
+        shutil.copyfile('extra-files/empty_schema.yml', 'models-a/eschema.yml')
+        results = self.run_dbt(["--partial-parse", "run"])
+        self.assertEqual(len(results), 3)
+
+        # Add version to empty schema file
+        shutil.copyfile('extra-files/empty_schema_with_version.yml', 'models-a/eschema.yml')
+        results = self.run_dbt(["--partial-parse", "run"])
+        self.assertEqual(len(results), 3)
+
     def tearDown(self):
         if os.path.exists(normalize('models-a/model_two.sql')):
             os.remove(normalize('models-a/model_two.sql'))
@@ -181,6 +191,8 @@ def tearDown(self):
             os.remove(normalize('target/partial_parse.msgpack'))
         if os.path.exists(normalize('macros/my_macro.sql')):
             os.remove(normalize('macros/my_macro.sql'))
+        if os.path.exists(normalize('models-a/eschema.yml')):
+            os.remove(normalize('models-a/eschema.yml'))
 
 
 class TestSources(DBTIntegrationTest):