Repository: great-expectations/great_expectations
Pull request #6837 (2023-01-19 16:03:33)

[MAINTENANCE] Standardize project config CRUD
Changes proposed in this pull request:
- Add `update_project_config`
- Misc refactors


### Definition of Done
- [x] My code follows the Great Expectations [style guide](https://docs.greatexpectations.io/docs/contributing/style_guides/code_style)
- [x] I have performed a [self-review](https://docs.greatexpectations.io/docs/contributing/contributing_checklist) of my own code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have added [unit tests](https://docs.greatexpectations.io/docs/contributing/contributing_test#writing-unit-and-integration-tests) where applicable and made sure that new and existing tests are passing.
- [x] I have run any local integration tests and made sure that nothing is broken.


netlify[bot]: ### <span aria-hidden="true">👷</span> Deploy Preview for *niobium-lead-7998* processing.


|  Name | Link |
|---------------------------------|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | abe0164f6b508fd44d877c38a2508ff1fde522c8 |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/niobium-lead-7998/deploys/63c969dc39ef92000a829a3e |
codesee-maps[bot]: <details>
<summary><b>👇 <a href="https://app.codesee.io/r/reviews?pr=6837&src=https%3A%2F%2Fgithub.com%2Fgreat-expectations%2Fgreat_expectations">Click on the image</a> for a new way to code review</b>
</summary>

  - Make big changes easier — review code in small groups of related files
  - Know where to start — see the whole change at a glance
  - Take a code tour — explore the change with an interactive tour
  - Make comments and review — all fully sync’ed with github

    [Try it now!](https://app.codesee.io/r/reviews?pr=6837&src=https%3A%2F%2Fgithub.com%2Fgreat-expectations%2Fgreat_expectations)
</details>

[![Review these changes using an interactive CodeSee Map](https://s3.us-east-2.amazonaws.com/maps.codesee.io/images/github/great-expectations/great_expectations/6837/1a4260b9/abe0164f6b508fd44d877c38a2508ff1fde522c8.svg)](https://app.codesee.io/r/reviews?pr=6837&src=https%3A%2F%2Fgithub.com%2Fgreat-expectations%2Fgreat_expectations)

#### Legend
![CodeSee Map Legend](https://app.codesee.io/Legend_v2.png)

Patch:
diff --git a/great_expectations/data_context/data_context/abstract_data_context.py b/great_expectations/data_context/data_context/abstract_data_context.py
index a56634a21..cfbe22da3 100644
--- a/great_expectations/data_context/data_context/abstract_data_context.py
+++ b/great_expectations/data_context/data_context/abstract_data_context.py
@@ -298,7 +298,7 @@ class AbstractDataContext(ConfigPeer, ABC):
 
     @abstractmethod
     def _init_project_config(
-        self, project_config: Union[DataContextConfig, Mapping]
+        self, project_config: DataContextConfig | Mapping
     ) -> DataContextConfig:
         raise NotImplementedError
 
@@ -315,6 +315,16 @@ class AbstractDataContext(ConfigPeer, ABC):
         """
         self.variables.save_config()
 
+    def update_project_config(
+        self, project_config: DataContextConfig | Mapping
+    ) -> None:
+        """Update the context's config with the values from another config object.
+
+        Args:
+            project_config: The config to use to update the context's internal state.
+        """
+        self.config.update(project_config)
+
     @usage_statistics_enabled_method(
         event_name=UsageStatsEvents.DATA_CONTEXT_SAVE_EXPECTATION_SUITE,
         args_payload_fn=save_expectation_suite_usage_statistics,
@@ -2821,7 +2831,7 @@ Generated, evaluated, and stored {total_expectations} Expectations during profil
 
     @classmethod
     def get_or_create_data_context_config(
-        cls, project_config: Union[DataContextConfig, Mapping]
+        cls, project_config: DataContextConfig | Mapping
     ) -> DataContextConfig:
         """Utility method to take in an input config and ensure its conversion to a rich
         DataContextConfig. If the input is already of the appropriate type, the function
diff --git a/great_expectations/data_context/types/base.py b/great_expectations/data_context/types/base.py
index 47ff29ad1..732c5091d 100644
--- a/great_expectations/data_context/types/base.py
+++ b/great_expectations/data_context/types/base.py
@@ -14,6 +14,7 @@ from typing import (
     ClassVar,
     Dict,
     List,
+    Mapping,
     MutableMapping,
     Optional,
     Set,
@@ -2451,6 +2452,10 @@ class DataContextConfig(BaseYamlConfig):
         serializeable_dict = self.to_json_dict()
         return PasswordMasker.sanitize_config(serializeable_dict)
 
+    def update(self, config: DataContextConfig | Mapping) -> None:
+        for k, v in config.items():
+            self[k] = v
+
     def __repr__(self) -> str:
         """
         # TODO: <Alex>2/4/2022</Alex>


Test patch:
diff --git a/tests/data_context/test_data_context_state_management.py b/tests/data_context/test_data_context_state_management.py
index 79dbe0417..32d36afab 100644
--- a/tests/data_context/test_data_context_state_management.py
+++ b/tests/data_context/test_data_context_state_management.py
@@ -1,3 +1,7 @@
+from __future__ import annotations
+
+from typing import Mapping
+
 import pytest
 
 from great_expectations.data_context.data_context.ephemeral_data_context import (
@@ -6,6 +10,7 @@ from great_expectations.data_context.data_context.ephemeral_data_context import
 from great_expectations.data_context.types.base import (
     DataContextConfig,
     InMemoryStoreBackendDefaults,
+    ProgressBarsConfig,
 )
 from great_expectations.exceptions.exceptions import StoreConfigurationError
 
@@ -92,3 +97,28 @@ def test_delete_store_failure(in_memory_data_context: EphemeralDataContextSpy):
     assert num_stores_after == num_stores_before
     assert num_store_configs_after == num_store_configs_before
     assert context.save_count == 0
+
+
+@pytest.mark.unit
+@pytest.mark.parametrize(
+    "config",
+    [
+        pytest.param(
+            DataContextConfig(progress_bars=ProgressBarsConfig(globally=True)),
+            id="DataContextConfig",
+        ),
+        pytest.param(
+            {"progress_bars": ProgressBarsConfig(globally=True)}, id="Mapping"
+        ),
+    ],
+)
+def test_update_project_config(
+    in_memory_data_context: EphemeralDataContextSpy, config: DataContextConfig | Mapping
+):
+    context = in_memory_data_context
+
+    assert context.progress_bars is None
+
+    context.update_project_config(config)
+
+    assert context.progress_bars["globally"] is True