def get(self) -> Optional[Any]: """ Retrieve the secret value. If not found, returns `None`. If using local secrets, `Secret.get()` will attempt to call `json.loads` on the value pulled from context. For this reason it is recommended to store local secrets as JSON documents to avoid ambiguous behavior. Returns: - Any: the value of the secret; if not found, raises an error Raises: - ValueError: if `.get()` is called within a Flow building context, or if `use_local_secrets=True` and your Secret doesn't exist - ClientError: if `use_local_secrets=False` and the Client fails to retrieve your secret """ if isinstance(prefect.context.get("flow"), prefect.core.flow.Flow): raise ValueError( "Secrets should only be retrieved during a Flow run, not while building a Flow." ) if prefect.config.cloud.use_local_secrets is True: secrets = prefect.context.get("secrets", {}) try: value = secrets[self.name] except KeyError: raise ValueError('Local Secret "{}" was not found.'.format( self.name)) from None try: return json.loads(value) except (json.JSONDecodeError, TypeError): return value else: client = Client() result = client.graphql( """ query($name: String!) { secretValue(name: $name) } """, variables=dict(name=self.name), ) # type: Any return as_nested_dict(result.data.secretValue, dict)
def __call__(self, *args: MutableMapping, **kwargs: Any) -> Iterator["Context"]: """ A context manager for setting / resetting the Prefect context Example: import prefect.context with prefect.context(dict(a=1, b=2), c=3): print(prefect.context.a) # 1 """ previous_context = self.copy() try: new_context = dict(*args, **kwargs) if "config" in new_context: new_config = merge_dicts(self.get("config", {}), new_context["config"]) new_context["config"] = as_nested_dict(new_config, dct_class=Config) self.update(new_context) # type: ignore yield self finally: self.clear() self.update(previous_context)
def __repr__(self) -> str: self_as_dict = as_nested_dict(self, dct_class=dict) try: return json.dumps(self_as_dict, indent=4) except TypeError: return repr(self_as_dict)
def __repr__(self) -> str: try: return json.dumps(as_nested_dict(self, dict), indent=4) except TypeError: return repr(self.to_dict())
def _load(self, data, partial=None, unknown=None): # type: ignore if isinstance(data, DotDict): data = as_nested_dict(data, dict) return super()._load(data=data, partial=partial, unknown=unknown)
def test_graphql_repr_falls_back_to_dict_repr(): gql = {"flow_run": Pending("test")} res = as_nested_dict(gql, GraphQLResult) assert repr(res) == """{'flow_run': Pending("test")}"""
def test_graphql_result_has_nice_repr(): expected = '{\n "flow_run": {\n "flow": [\n {\n "id": 1\n },\n {\n "version": 2\n }\n ]\n }\n}' gql = {"flow_run": {"flow": [{"id": 1}, {"version": 2}]}} res = as_nested_dict(gql, GraphQLResult) assert repr(res) == expected
def test_protect_critical_keys_inactive_for_nested_query(): """ Fails if the `update` method is called after an update key is set """ gql = {"update": {"update": [{"x": 1}, {"x": 2}]}} as_nested_dict(gql, GraphQLResult)
def test_as_nested_dict_dct_class(): orig_d = dict(a=1, b=[2, dict(c=3)], d=dict(e=[dict(f=4)])) dot_dict_d = as_nested_dict(orig_d, DotDict) dict_d = as_nested_dict(dot_dict_d, dict) assert type(dict_d) is dict assert type(dict_d["d"]["e"][0]) is dict
def test_eq_complex_dict(self): x = dict(x=1, y=dict(z=[3, 4, dict(a=5)])) assert as_nested_dict(x) == x
def test_as_nested_dict_works_when_critical_keys_shadowed(): x = dict(update=1, items=2) y = as_nested_dict(x, DotDict) assert y.update == 1 assert y.items == 2