コード例 #1
0
ファイル: registries.py プロジェクト: philipp-sontag-by/kopf
def _matches_field_values(
    handler: handlers.ResourceHandler,
    cause: causes.ResourceCause,
    kwargs: MutableMapping[str, Any],
) -> bool:
    if not handler.field:
        return True

    if not kwargs:
        kwargs.update(cause.kwargs)

    absent = _UNSET.token  # or any other identifyable object
    if isinstance(cause, causes.ChangingCause):
        # For on.update/on.field, so as for on.create/resume/delete for uniformity and simplicity:
        old = dicts.resolve(cause.old, handler.field, absent)
        new = dicts.resolve(cause.new, handler.field, absent)
        values = [
            new, old
        ]  # keep "new" first, to avoid "old" callbacks if "new" works.
    else:
        # For event-watching, timers/daemons (could also work for on.create/resume/delete):
        val = dicts.resolve(cause.body, handler.field, absent)
        values = [val]
    return ((handler.value is None and any(value is not absent
                                           for value in values))
            or (handler.value is filters.PRESENT and any(value is not absent
                                                         for value in values))
            or (handler.value is filters.ABSENT and any(value is absent
                                                        for value in values))
            or (callable(handler.value)
                and any(handler.value(value, **kwargs) for value in values))
            or (any(handler.value == value for value in values)))
コード例 #2
0
ファイル: registries.py プロジェクト: philipp-sontag-by/kopf
def _matches_field_changes(
    handler: handlers.ResourceHandler,
    cause: causes.ResourceCause,
    kwargs: MutableMapping[str, Any],
) -> bool:
    if not isinstance(handler, handlers.ChangingHandler):
        return True
    if not isinstance(cause, causes.ChangingCause):
        return True
    if not handler.field:
        return True

    if not kwargs:
        kwargs.update(cause.kwargs)

    absent = _UNSET.token  # or any other identifyable object
    old = dicts.resolve(cause.old, handler.field, absent)
    new = dicts.resolve(cause.new, handler.field, absent)
    return ((
        not handler.field_needs_change
        or old != new  # ... or there IS a change.
    ) and ((handler.old is None) or
           (handler.old is filters.ABSENT and old is absent) or
           (handler.old is filters.PRESENT and old is not absent) or
           (callable(handler.old) and handler.old(old, **kwargs)) or
           (handler.old == old))
            and ((handler.new is None) or
                 (handler.new is filters.ABSENT and new is absent) or
                 (handler.new is filters.PRESENT and new is not absent) or
                 (callable(handler.new) and handler.new(new, **kwargs)) or
                 (handler.new == new)))
コード例 #3
0
 def adjust_cause(self, cause: execution.CauseT) -> execution.CauseT:
     if self.field is not None and isinstance(cause, causes.ChangingCause):
         old = dicts.resolve(cause.old, self.field, None)
         new = dicts.resolve(cause.new, self.field, None)
         diff = diffs.reduce(cause.diff, self.field)
         new_cause = dataclasses.replace(cause, old=old, new=new, diff=diff)
         return cast(execution.CauseT, new_cause)  # TODO: mypy bug?
     else:
         return cause
コード例 #4
0
 def purge(
     self,
     *,
     key: ids.HandlerId,
     body: bodies.Body,
     patch: patches.Patch,
 ) -> None:
     absent = object()
     key_field = self.field + (key, )
     body_value = dicts.resolve(body, key_field, absent)
     patch_value = dicts.resolve(patch, key_field, absent)
     if body_value is not absent:
         dicts.ensure(patch, key_field, None)
     elif patch_value is not absent:
         dicts.remove(patch, key_field)
コード例 #5
0
 def purge(
     self,
     *,
     key: ids.HandlerId,
     body: bodies.Body,
     patch: patches.Patch,
 ) -> None:
     absent = object()
     for full_key in self.make_keys(key, body=body):
         key_field = ['metadata', 'annotations', full_key]
         body_value = dicts.resolve(body, key_field, absent)
         patch_value = dicts.resolve(patch, key_field, absent)
         if body_value is not absent:
             dicts.ensure(patch, key_field, None)
         elif patch_value is not absent:
             dicts.remove(patch, key_field)
コード例 #6
0
ファイル: diffbase.py プロジェクト: philipp-sontag-by/kopf
 def fetch(
     self,
     *,
     body: bodies.Body,
 ) -> Optional[bodies.BodyEssence]:
     encoded: Optional[str] = dicts.resolve(body, self.field, None)
     essence: Optional[bodies.BodyEssence] = json.loads(
         encoded) if encoded is not None else None
     return essence
コード例 #7
0
 def fetch(
     self,
     *,
     key: ids.HandlerId,
     body: bodies.Body,
 ) -> Optional[ProgressRecord]:
     container: Mapping[ids.HandlerId, ProgressRecord]
     container = dicts.resolve(body, self.field, {})
     return container.get(key, None)
コード例 #8
0
 def touch(
     self,
     *,
     body: bodies.Body,
     patch: patches.Patch,
     value: Optional[str],
 ) -> None:
     key_field = self.touch_field
     body_value = dicts.resolve(body, key_field, None)
     if body_value != value:  # also covers absent-vs-None cases.
         dicts.ensure(patch, key_field, value)
コード例 #9
0
def reduce_iter(
    d: Diff,
    path: dicts.FieldPath,
) -> Iterator[DiffItem]:
    for op, field, old, new in d:

        # As-is diff (i.e. a root field).
        if not path:
            yield DiffItem(op, tuple(field), old, new)

        # The diff-field is longer than the path: get "spec.struct" when "spec.struct.field" is set.
        # Retranslate the diff with the field prefix shrinked.
        elif tuple(field[:len(path)]) == tuple(path):
            yield DiffItem(op, tuple(field[len(path):]), old, new)

        # The diff-field is shorter than the path: get "spec.struct" when "spec={...}" is added.
        # Generate a new diff, with new ops, for the resolved sub-field.
        elif tuple(field) == tuple(path[:len(field)]):
            tail = path[len(field):]
            old_tail = dicts.resolve(old, tail, default=None)
            new_tail = dicts.resolve(new, tail, default=None)
            yield from diff_iter(old_tail, new_tail)
コード例 #10
0
 def fetch(
     self,
     *,
     key: ids.HandlerId,
     body: bodies.Body,
 ) -> Optional[ProgressRecord]:
     for full_key in self.make_keys(key, body=body):
         key_field = ['metadata', 'annotations', full_key]
         encoded = dicts.resolve(body, key_field, None)
         decoded = json.loads(encoded) if encoded is not None else None
         if decoded is not None:
             return cast(ProgressRecord, decoded)
     return None
コード例 #11
0
 def touch(
     self,
     *,
     body: bodies.Body,
     patch: patches.Patch,
     value: Optional[str],
 ) -> None:
     for full_key in self.make_keys(self.touch_key, body=body):
         key_field = ['metadata', 'annotations', full_key]
         body_value = dicts.resolve(body, key_field, None)
         if body_value != value:  # also covers absent-vs-None cases.
             dicts.ensure(patch, key_field, value)
             self._store_marker(prefix=self.prefix, patch=patch, body=body)
コード例 #12
0
def test_dict_with_empty_path(resolve):
    d = {'key': 'val'}
    r = resolve(d, [])
    assert r == d
    assert r is d
コード例 #13
0
def test_dict_with_none_is_treated_as_a_regular_default_value(resolve):
    d = {'abc': {'def': {'hij': 'val'}}}
    r = resolve(d, ['abc', 'def', 'xyz'], None)
    assert r is None
コード例 #14
0
def test_dict_with_nonmapping_with_default(resolve):
    d = {'key': 'val'}
    r = resolve(d, ['key', 'sub'], default)
    assert r is default
コード例 #15
0
def test_dict_with_nonmapping_with_no_default(resolve):
    d = {'key': 'val'}
    with pytest.raises(TypeError):
        resolve(d, ['key', 'sub'])
コード例 #16
0
def test_dict_with_inexistent_key_with_default(resolve, key):
    d = {'abc': {'def': {'hij': 'val'}}}
    r = resolve(d, key, default)
    assert r is default
コード例 #17
0
def test_dict_with_inexistent_key_with_no_default(resolve, key):
    d = {'abc': {'def': {'hij': 'val'}}}
    with pytest.raises(KeyError):
        resolve(d, key)
コード例 #18
0
def test_dict_with_existent_key_with_default(resolve):
    d = {'abc': {'def': {'hij': 'val'}}}
    r = resolve(d, ['abc', 'def', 'hij'], default)
    assert r == 'val'