Пример #1
0
def test_assign():
    class Foo(object):
        pass

    assert glom({}, Assign(T['a'], 1)) == {'a': 1}
    assert glom({'a': {}}, Assign(T['a']['a'], 1)) == {'a': {'a': 1}}
    assert glom({'a': {}}, Assign('a.a', 1)) == {'a': {'a': 1}}
    assert glom(Foo(), Assign(T.a, 1)).a == 1
    assert glom({}, Assign('a', 1)) == {'a': 1}
    assert glom(Foo(), Assign('a', 1)).a == 1
    assert glom({'a': Foo()}, Assign('a.a', 1))['a'].a == 1

    def r():
        r = {}
        r['r'] = r
        return r

    assert glom(r(), Assign('r.r.r.r.r.r.r.r.r', 1)) == {'r': 1}
    assert glom(r(), Assign(T['r']['r']['r']['r'], 1)) == {'r': 1}
    assert glom(r(), Assign(Path('r', 'r', T['r']), 1)) == {'r': 1}
    assert assign(r(), Path('r', 'r', T['r']), 1) == {'r': 1}
    with pytest.raises(TypeError, match='path argument must be'):
        Assign(1, 'a')
    with pytest.raises(ValueError,
                       match='path must have at least one element'):
        Assign(T, 1)

    assert repr(Assign(T.a, 1)) == 'Assign(T.a, 1)'
    assign_spec = Assign(T.a, 1, missing=dict)
    assert repr(assign_spec) == "Assign(T.a, 1, missing=dict)"
    assert repr(assign_spec) == repr(eval(repr(assign_spec)))
Пример #2
0
def test_path_access_error_message():

    # test fuzzy access
    with raises(GlomError) as exc_info:
        glom({}, 'a.b')
    assert (
        "PathAccessError: could not access 'a', part 0 of Path('a', 'b'), got error: KeyError"
        in exc_info.exconly())
    ke = repr(KeyError('a'))  # py3.7+ changed the keyerror repr
    assert repr(
        exc_info.value) == "PathAccessError(" + ke + ", Path('a', 'b'), 0)"

    # test multi-part Path with T, catchable as a KeyError
    with raises(KeyError) as exc_info:
        # don't actually use glom to copy your data structures please
        glom({'a': {'b': 'c'}}, Path('a', T.copy(), 'd'))
    assert (
        "PathAccessError: could not access 'd', part 3 of Path('a', T.copy(), 'd'), got error: KeyError"
        in exc_info.exconly())
    ke = repr(KeyError('d'))  # py3.7+ changed the keyerror repr
    assert repr(exc_info.value
                ) == "PathAccessError(" + ke + ", Path('a', T.copy(), 'd'), 3)"

    # test AttributeError
    with raises(GlomError) as exc_info:
        glom({'a': {'b': 'c'}}, Path('a', T.b))
    assert (
        "PathAccessError: could not access 'b', part 1 of Path('a', T.b), got error: AttributeError"
        in exc_info.exconly())
    ae = repr(AttributeError("'dict' object has no attribute 'b'"))
    assert repr(
        exc_info.value) == "PathAccessError(" + ae + ", Path(\'a\', T.b), 1)"
Пример #3
0
def test_delete():
    class Foo(object):
        def __init__(self, d=None):
            for k, v in d.items():
                setattr(self, k, v)

    assert glom({'a': 1}, Delete(T['a'])) == {}
    assert glom({'a': {'a': 1}}, Delete(T['a']['a'])) == {'a': {}}
    assert glom({'a': {'a': 1}}, Delete('a.a')) == {'a': {}}
    assert not hasattr(glom(Foo({'a': 1}), Delete(T.a)), 'a')
    assert glom({'a': 1}, Delete('a')) == {}
    assert not hasattr(glom(Foo({'a': 1}), Delete('a')), 'a')
    assert not hasattr(glom({'a': Foo({'a': 1})}, Delete('a.a'))['a'], 'a')

    def r():
        r = {}
        r['r'] = r
        return r

    assert glom(r(), Delete('r.r.r.r.r.r.r.r.r')) == {}
    assert glom(r(), Delete(T['r']['r']['r']['r'])) == {}
    assert glom(r(), Delete(Path('r', 'r', T['r']))) == {}
    assert delete(r(), Path('r', 'r', T['r'])) == {}
    with pytest.raises(TypeError, match='path argument must be'):
        Delete(1, 'a')
    with pytest.raises(ValueError,
                       match='path must have at least one element'):
        Delete(T, 1)

    assert repr(Delete(T.a)) == 'Delete(T.a)'
Пример #4
0
def test_path_items():
    path = Path(T.a, 1, 2, T(test='yes'))

    assert path.items() == (('.', 'a'),
                            ('P', 1), ('P', 2),
                            ('(', ((), {'test': 'yes'})))

    assert Path().items() == ()
Пример #5
0
def test_path_items():
    path = Path(T.a, 1, 2, T(test='yes'))

    assert path.items() == (('.', 'a'), ('P', 1), ('P', 2), ('(', ((), {
        'test':
        'yes'
    })))

    assert Path().items() == ()
Пример #6
0
def test_delete():
    class Foo(object):
        def __init__(self, d=None):
            for k, v in d.items():
                setattr(self, k, v)

    assert glom({'a': 1}, Delete(T['a'])) == {}
    assert glom({'a': {'a': 1}}, Delete(T['a']['a'])) == {'a': {}}
    assert glom({'a': {'a': 1}}, Delete('a.a')) == {'a': {}}
    assert not hasattr(glom(Foo({'a': 1}), Delete(T.a)), 'a')
    assert glom({'a': 1}, Delete('a')) == {}
    assert not hasattr(glom(Foo({'a': 1}), Delete('a')), 'a')
    assert not hasattr(glom({'a': Foo({'a': 1})}, Delete('a.a'))['a'], 'a')

    def r():
        r = {}
        r['r'] = r
        return r

    assert glom(r(), Delete('r.r.r.r.r.r.r.r.r')) == {}
    assert glom(r(), Delete(T['r']['r']['r']['r'])) == {}
    assert glom(r(), Delete(Path('r', 'r', T['r']))) == {}
    assert delete(r(), Path('r', 'r', T['r'])) == {}
    with pytest.raises(TypeError, match='path argument must be'):
        Delete(1, 'a')
    with pytest.raises(ValueError,
                       match='path must have at least one element'):
        Delete(T, 1)

    assert repr(Delete(T.a)) == 'Delete(T.a)'

    # test delete from scope
    assert glom(1, (S(x=T), S['x'])) == 1
    with pytest.raises(PathAccessError):
        glom(1, (S(x=T), Delete(S['x']), S['x']))

    # test raising on missing parent
    with pytest.raises(PathAccessError):
        glom({}, Delete(T['a']['b']))

    # test raising on missing index
    with pytest.raises(PathDeleteError):
        glom([], Delete(T[0]))
    target = []
    assert glom(target, Delete(T[0], ignore_missing=True)) is target

    # test raising on missing attr
    with pytest.raises(PathDeleteError):
        glom(object(), Delete(T.does_not_exist))
    target = object()
    assert glom(target, Delete(T.does_not_exist,
                               ignore_missing=True)) is target
Пример #7
0
def test_s_scope_assign():
    data = {'a': 1, 'b': [{'c': 2}, {'c': 3}]}
    output = [{'a': 1, 'c': 2}, {'a': 1, 'c': 3}]
    assert glom(data, (S(a='a'), ('b', [{'a': S['a'], 'c': 'c'}]))) == output
    assert glom(data, ('b', [{'a': S[ROOT][Val(T)]['a'], 'c': 'c'}])) == output

    with pytest.raises(TypeError):
        S('posarg')
    with pytest.raises(TypeError):
        S()

    assert glom([[1]], (S(v=Vars()), [[A.v.a]], S.v.a)) == 1
    assert glom(1, (S(v=lambda t: {}), A.v['a'], S.v['a'])) == 1
    with pytest.raises(GlomError):
        glom(1, (S(v=lambda t: 1), A.v.a))

    class FailAssign(object):
        def __setattr__(self, name, val):
            raise Exception('nope')

    with pytest.raises(PathAssignError):
        glom(1, (S(v=lambda t: FailAssign()), Path(A.v, 'a')))

    assert repr(S(a=T.a.b)) == 'S(a=T.a.b)'

    spec = (S(a='x'), S.a)
    assert glom({'x': 'y'}, spec) == 'y'

    return
Пример #8
0
def test_path_t_roundtrip():
    # check that T repr roundrips
    assert repr(T['a'].b.c()) == "T['a'].b.c()"
    assert repr(T[1:]) == "T[1:]"
    assert repr(T[::3, 1:, 1:2, :2:3]) == "T[::3, 1:, 1:2, :2:3]"

    # check that Path repr roundtrips
    assert repr(Path('a', 1, 'b.b', -1.0)) == "Path('a', 1, 'b.b', -1.0)"

    # check that Path repr roundtrips when it contains Ts
    assert repr(Path(T['a'].b, 'c',
                     T['d'].e)) == "Path(T['a'].b, 'c', T['d'].e)"

    # check that T instances containing Path access revert to repring with Path
    assert repr(Path(T['a'].b, 'c',
                     T['d'].e).path_t) == "Path(T['a'].b, 'c', T['d'].e)"

    # check that Paths containing only T objects reduce to a T (joining the T objects)
    assert repr(Path(T['a'].b, T.c())) == "T['a'].b.c()"

    # check that multiple nested paths reduce
    assert repr(Path(Path(Path('a')))) == "Path('a')"

    # check builtin repr
    assert repr(T[len]) == 'T[len]'
    assert repr(T.func(len, sum)) == 'T.func(len, sum)'
Пример #9
0
def test_path_len():

    assert len(Path()) == 0
    assert len(Path('a', 'b', 'c')) == 3
    assert len(Path.from_text('1.2.3.4')) == 4

    assert len(Path(T)) == 0
    assert len(Path(T.a.b.c)) == 3
    assert len(Path(T.a()['b'].c.d)) == 5
Пример #10
0
def test_pae_api():
    target = {'value': {'data': [0, 1, 2]}}

    with pytest.raises(GlomError) as exc_info:
        glom(target, (T['value'], 'data.3'))

    assert exc_info.value.path == Path('data', '3')
    assert exc_info.value.path.__class__ is Path
    assert exc_info.value.exc.__class__ is IndexError
    assert exc_info.value.part_idx == 1
Пример #11
0
def mw_get_target(next_, posargs_, target_file, target_format, spec_file,
                  spec_format):
    spec_text, target_text = None, None
    if len(posargs_) == 2:
        spec_text, target_text = posargs_
    elif len(posargs_) == 1:
        spec_text, target_text = posargs_[0], None

    if spec_text and spec_file:
        _error('expected spec file or spec argument, not both')
    elif spec_file:
        try:
            with open(spec_file, 'r') as f:
                spec_text = f.read()
        except IOError as ose:
            _error('could not read spec file %r, got: %s' % (spec_file, ose))

    if not spec_text:
        spec = Path()
    elif spec_format == 'python':
        if spec_text[0] not in ('"', "'", "[", "{", "("):
            # intention: handle trivial path access, assume string
            spec_text = repr(spec_text)
        spec = ast.literal_eval(spec_text)
    elif spec_format == 'json':
        spec = json.loads(spec_text)
    else:
        _error('expected spec-format to be one of python or json')

    if target_text and target_file:
        _error('expected target file or target argument, not both')
    elif target_text == '-' or target_file == '-':
        with sys.stdin as f:
            target_text = f.read()
    elif target_file:
        try:
            target_text = open(target_file, 'r').read()
        except IOError as ose:
            _error('could not read target file %r, got: %s' %
                   (target_file, ose))
    elif not target_text and not os.isatty(sys.stdin.fileno()):
        with sys.stdin as f:
            target_text = f.read()

    if not target_text:
        target = {}
    elif target_format == 'json':
        try:
            target = json.loads(target_text)
        except Exception as e:
            _error('could not load target data, got: %s' % e)
    else:
        _error('expected spec-format to be one of python or json')

    return next_(spec=spec, target=target)
Пример #12
0
def set_data(obj: Dict, value: Union[Dict, List, str], *path: str) -> None:
    """
    Update data from the object with given value.
    e.g: dependencies.cuda."11.3.1"
    """
    try:
        _ = glom(obj, Assign(Path(*path), value))
    except PathAssignError:
        log.exception("Exception occurred in "
                      "update_data, unable to update "
                      f"{Path(*path)} with {value}")
        exit(1)
Пример #13
0
def test_startswith():
    ref = T.a.b[1]

    assert Path(ref).startswith(T)
    assert Path(ref).startswith(T.a.b)
    assert Path(ref).startswith(ref)
    assert Path(ref).startswith(ref.c) is False

    assert Path('a.b.c').startswith(Path())
    assert Path('a.b.c').startswith('a.b.c')

    with raises(TypeError):
        assert Path('a.b.c').startswith(None)

    return
Пример #14
0
def test_path_slices():
    path = Path(T.a.b, 1, 2, T(test='yes'))

    assert path[::] == path

    # positive indices
    assert path[3:] == Path(2, T(test='yes'))
    assert path[1:3] == Path(T.b, 1)
    assert path[:3] == Path(T.a.b, 1)

    # positive indices backwards
    assert path[2:1] == Path()

    # negative indices forward
    assert path[-1:] == Path(T(test='yes'))
    assert path[:-2] == Path(T.a.b, 1)
    assert path[-3:-1] == Path(1, 2)

    # negative indices backwards
    assert path[-1:-3] == Path()

    # slicing and stepping
    assert path[1::2] == Path(T.b, 2)
Пример #15
0
def get_data(obj: Union[Dict, MutableMapping], *path: str) -> Any:
    """
    Get data from the object by dotted path.
    e.g: dependencies.cuda."11.3.1"
    """
    try:
        data = glom(obj, Path(*path))
    except PathAccessError:
        log.exception("Exception occurred in "
                      "get_data, unable to retrieve "
                      f"{'.'.join([*path])} from {repr(obj)}")
        exit(1)
    else:
        return data
Пример #16
0
def test_empty_path_access():
    target = {}

    assert glom(target, Path()) is target
    assert glom(target, (Path(), Path(), Path())) is target

    dup_dict = glom(target, {'target': Path(), 'target2': Path()})
    dup_dict['target'] is target
    dup_dict['target2'] is target
Пример #17
0
def test_path_len():

    assert len(Path()) == 0
    assert len(Path('a', 'b', 'c')) == 3
    assert len(Path.from_text('1.2.3.4')) == 4

    assert len(Path(T)) == 0
    assert len(Path(T.a.b.c)) == 3
    assert len(Path(T.a()['b'].c.d)) == 5
Пример #18
0
def mw_get_target(next_, posargs_, target_file, target_format, spec_file,
                  spec_format):
    spec_text, target_text = None, None
    if len(posargs_) == 2:
        spec_text, target_text = posargs_
    elif len(posargs_) == 1:
        spec_text, target_text = posargs_[0], None

    if spec_text and spec_file:
        raise UsageError('expected spec file or spec argument, not both')
    elif spec_file:
        try:
            with open(spec_file, 'r') as f:
                spec_text = f.read()
        except IOError as ose:
            raise UsageError('could not read spec file %r, got: %s' %
                             (spec_file, ose))

    if not spec_text:
        spec = Path()
    elif spec_format == 'python':
        if spec_text[0] not in ('"', "'", "[", "{", "("):
            # intention: handle trivial path access, assume string
            spec_text = repr(spec_text)
        spec = ast.literal_eval(spec_text)
    elif spec_format == 'json':
        spec = json.loads(spec_text)
    elif spec_format == 'python-full':
        spec = _eval_python_full_spec(spec_text)
    else:
        raise UsageError(
            'expected spec-format to be one of json, python, or python-full')

    if target_text and target_file:
        raise UsageError('expected target file or target argument, not both')
    elif target_text == '-' or target_file == '-':
        target_text = sys.stdin.read()
    elif target_file:
        try:
            target_text = open(target_file, 'r').read()
        except IOError as ose:
            raise UsageError('could not read target file %r, got: %s' %
                             (target_file, ose))
    elif not target_text and not isatty(sys.stdin):
        target_text = sys.stdin.read()

    target = mw_handle_target(target_text, target_format)

    return next_(spec=spec, target=target)
Пример #19
0
def test_path_getitem():
    path = Path(T.a.b.c)

    assert path[0] == Path(T.a)
    assert path[1] == Path(T.b)
    assert path[2] == Path(T.c)
    assert path[-1] == Path(T.c)
    assert path[-2] == Path(T.b)

    with raises(IndexError, match='Path index out of range'):
        path[4]

    with raises(IndexError, match='Path index out of range'):
        path[-14]
    return
Пример #20
0
def test_path_t_roundtrip():
    # check that T repr roundrips
    assert repr(T['a'].b.c()) == "T['a'].b.c()"

    # check that Path repr roundtrips
    assert repr(Path('a', 1, 'b.b', -1.0)) == "Path('a', 1, 'b.b', -1.0)"

    # check that Path repr roundtrips when it contains Ts
    assert repr(Path(T['a'].b, 'c',
                     T['d'].e)) == "Path(T['a'].b, 'c', T['d'].e)"

    # check that T instances containing Path access revert to repring with Path
    assert repr(Path(T['a'].b, 'c',
                     T['d'].e).path_t) == "Path(T['a'].b, 'c', T['d'].e)"

    # check that Paths containing only T objects reduce to a T (joining the T objects)
    assert repr(Path(T['a'].b, T.c())) == "T['a'].b.c()"

    # check that multiple nested paths reduce
    assert repr(Path(Path(Path('a')))) == "Path('a')"
Пример #21
0
def test_vars():
    assert glom(1, A.a) == 1  # A should not change the target
    assert glom(1, (A.a, S.a)) == 1
    # check that tuple vars don't "leak" into parent tuple
    assert glom(1, (A.t, Val(2), A.t, S.t)) == 2
    assert glom(1, (A.t, (Val(2), A.t), S.t)) == 1
    let = S(v=Vars({'b': 2}, c=3))
    assert glom(1, (let, A.v.a, S.v.a)) == 1
    with pytest.raises(AttributeError):
        glom(
            1,
            (let, S.v.a))  # check that Vars() inside a spec doesn't hold state
    assert glom(1, (let, Path(A, 'v', 'a'), S.v.a)) == 1
    assert glom(1, (let, S.v.b)) == 2
    assert glom(1, (let, S.v.c)) == 3
    assert repr(let) == "S(v=Vars({'b': 2}, c=3))"
    assert repr(Vars(a=1, b=2)) in ("Vars(a=1, b=2)", "Vars(b=2, a=1)")
    assert repr(Vars(a=1, b=2).glomit(None,
                                      None)) in ("ScopeVars({'a': 1, 'b': 2})",
                                                 "Vars({'b': 2, 'a': 1})")

    assert repr(A.b["c"]) == "A.b['c']"
Пример #22
0
def test_let():  # backwards compat 2020-07
    data = {'a': 1, 'b': [{'c': 2}, {'c': 3}]}
    output = [{'a': 1, 'c': 2}, {'a': 1, 'c': 3}]
    assert glom(data, (Let(a='a'), ('b', [{'a': S['a'], 'c': 'c'}]))) == output
    assert glom(data, ('b', [{'a': S[ROOT][Val(T)]['a'], 'c': 'c'}])) == output

    with pytest.raises(TypeError):
        Let('posarg')
    with pytest.raises(TypeError):
        Let()

    assert glom([[1]], (Let(v=Vars()), [[A.v.a]], S.v.a)) == 1
    assert glom(1, (Let(v=lambda t: {}), A.v['a'], S.v['a'])) == 1
    with pytest.raises(GlomError):
        glom(1, (Let(v=lambda t: 1), A.v.a))

    class FailAssign(object):
        def __setattr__(self, name, val):
            raise Exception('nope')

    with pytest.raises(PathAssignError):
        glom(1, (Let(v=lambda t: FailAssign()), Path(A.v, 'a')))

    assert repr(Let(a=T.a.b)) == 'Let(a=T.a.b)'
Пример #23
0
def test_path_eq():
    assert Path('a', 'b') == Path('a', 'b')
    assert Path('a') != Path('b')

    assert Path() != object()
Пример #24
0
def test_list_path_access():
    assert glom(list(range(10)), Path(1)) == 1
Пример #25
0
def test_path():
    _obj = object()
    target = {'a': {'b.b': [None, {_obj: [None, None, 'd']}]}}

    assert glom(target, Path('a', 'b.b', 1, _obj, -1)) == 'd'
Пример #26
0
 def _format_vcap_path(self, path: str) -> Path:
     subpath = path.split(".")
     return Path(Path(self.vcap_service_prefix), *subpath)
Пример #27
0
def test_path_cache():
    assert Path.from_text('a.b.c') is Path.from_text('a.b.c')
    pre = Path._MAX_CACHE
    Path._MAX_CACHE = 0
    assert Path.from_text('d.e.f') is not Path.from_text('d.e.f')
Пример #28
0
 def test_format_vcap_path(self, cfenv):
     path = cfenv._format_vcap_path("0.credentials.uri")
     assert path == Path("p-config-server", "0", "credentials", "uri")
Пример #29
0
def test_from_t_identity():
    ref = Path(T.a.b)
    assert ref.from_t() == ref
    assert ref.from_t() is ref
Пример #30
0
def test_path_values():
    path = Path(T.a.b, 1, 2, T(test='yes'))

    assert path.values() == ('a', 'b', 1, 2, ((), {'test': 'yes'}))

    assert Path().values() == ()
Пример #31
0
def test_path_values():
    path = Path(T.a.b, 1, 2, T(test='yes'))

    assert path.values() == ('a', 'b', 1, 2, ((), {'test': 'yes'}))

    assert Path().values() == ()
Пример #32
0
def test_path_eq_t():
    assert Path(T.a.b) == T.a.b
    assert Path(T.a.b.c) != T.a.b
Пример #33
0
def test_from_t_identity():
    ref = Path(T.a.b)
    assert ref.from_t() == ref
    assert ref.from_t() is ref