Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: found a few issues with Iter() and the new features #195

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions glom/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -775,9 +775,8 @@ def __init__(self, spec, scope=None):
def glom(self, target, **kw):
scope = dict(self.scope)
scope.update(kw.get('scope', {}))
kw['scope'] = ChainMap(scope)
glom_ = scope.get(glom, glom)
return glom_(target, self.spec, **kw)
kw['scope'] = scope
return glom(target, self.spec, **kw)

def glomit(self, target, scope):
scope.update(self.scope)
Expand Down Expand Up @@ -1983,7 +1982,7 @@ def _get_iterable_handler(type_obj):
self.register_op('get', lambda _: getattr)


_DEFAULT_SCOPE = ChainMap({})
_DEFAULT_SCOPE = ChainMap({CHILD_ERRORS: []})


def glom(target, spec, **kwargs):
Expand Down
23 changes: 19 additions & 4 deletions glom/streaming.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from boltons.iterutils import split_iter, chunked_iter, windowed_iter, unique_iter, first
from boltons.funcutils import FunctionBuilder

from .core import glom, T, STOP, SKIP, _MISSING, Path, TargetRegistry, Call, Spec, S, bbrepr, format_invocation
from .core import glom, T, STOP, SKIP, _MISSING, Path, TargetRegistry, Call, Spec, S, bbrepr, format_invocation, GlomError, Pipe
from .matching import Check

class Iter(object):
Expand Down Expand Up @@ -332,7 +332,7 @@ def all(self):
Note that this spec will always consume the whole iterable, and as
such, the spec returned is *not* an :class:`Iter()` instance.
"""
return (self, list)
return Pipe(self, list)

def first(self, key=T, default=None):
"""A convenience method for lazily yielding a single truthy item from
Expand All @@ -349,7 +349,7 @@ def first(self, key=T, default=None):
As this spec yields at most one item, and not an iterable, the
spec returned from this method is not an :class:`Iter()` instance.
"""
return (self, First(key=key, default=default))
return Pipe(self, First(key=key, default=default))


class First(object):
Expand All @@ -372,7 +372,10 @@ def __init__(self, key=T, default=None):
self._spec = key
self._default = default

spec_glom = Spec(Call(partial, args=(Spec(self._spec).glom,), kwargs={'scope': S}))
spec_glom = Spec(Call(partial,
args=(Spec(self._spec).glom,),
kwargs={'scope': S, 'skip_exc': GlomError
}))
self._first = Call(first, args=(T,), kwargs={'default': default, 'key': spec_glom})

def glomit(self, target, scope):
Expand All @@ -383,3 +386,15 @@ def __repr__(self):
if self._default is None:
return '%s(%s)' % (cn, bbrepr(self._spec))
return '%s(%s, default=%s)' % (cn, bbrepr(self._spec), bbrepr(self._default))


"""
Issues:

* Spec.glom() impl was way obsolete for all the other advancements
* glom not "reentrant" (calling glom from inside glom, passing scope along) breaks bc DEFAULT_SCOPE didn't have CHILD_ERRORS and the way error handling is written requires all maps to have it (.maps[1])
* Should glom() respect if people have passed in their own MODE in scope? right now it always sets it to AUTO
* The whole "terminus spec" approach to Iter().first() and Iter().all() assumes that tuple=Pipe
* In matching.py, _glom_match should be MATCH to mirror AUTO/FILL
* Also in matching.py, _glom_match seems to handle type (non-instance) specs, we should try to move away from those.
"""
15 changes: 11 additions & 4 deletions glom/test/test_streaming.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from itertools import count, dropwhile, chain

from glom import Iter
from glom import glom, SKIP, STOP, T, Call, Spec, Glommer, Check, SKIP
from glom import glom, SKIP, STOP, T, Call, Spec, Glommer, Check, SKIP, Pipe


RANGE_5 = list(range(5))
Expand Down Expand Up @@ -192,13 +192,20 @@ def test_first():
out = glom(target, spec)
assert out == 3j
assert next(target) == 4
assert repr(spec) == '(Iter(), First(T.imag))'
assert repr(spec) == 'Pipe(Iter(), First(T.imag))'

spec = Iter().first(T.imag, default=0)
target = iter([1, 2, 4])
out = glom(target, spec)
assert out == 0
assert repr(spec) == '(Iter(), First(T.imag, default=0))'
assert repr(spec) == 'Pipe(Iter(), First(T.imag, default=0))'

target = [{}, {}, {'user': {'client': 123}}, {}]

output = glom(target, Iter().first('user.client'))

assert output['user']['client'] == 123



def test_all():
Expand All @@ -207,4 +214,4 @@ def test_all():
out = glom(int_iter, Iter().all())
assert out == list(range(10))
assert next(int_iter, None) is None
assert repr(Iter().all()) == repr((Iter(), list))
assert repr(Iter().all()) == repr(Pipe(Iter(), list))