def test_call_and_target(): class F(object): def __init__(s, a, b, c): s.a, s.b, s.c = a, b, c call_f = Call(F, kwargs=dict(a=T, b=T, c=T)) assert repr(call_f) val = glom(1, call_f) assert (val.a, val.b, val.c) == (1, 1, 1) class F(object): def __init__(s, a): s.a = a val = glom({'one': F('two')}, Call(F, args=(T['one'].a, ))) assert val.a == 'two' assert glom({'a': 1}, Call(F, kwargs=T)).a == 1 assert glom([1], Call(F, args=T)).a == 1 assert glom(F, T(T)).a == F assert glom([F, 1], T[0](T[1]).a) == 1 assert glom([[1]], S[UP][Val(T)][0][0]) == 1 assert glom([[1]], S[UP][UP][UP][Val(T)]) == [[1]] # tops out assert list(glom({'a': 'b'}, Call(T.values))) == ['b'] with pytest.raises(TypeError, match='expected func to be a callable or T'): Call(func=object()) assert glom(lambda: 'hi', Call()) == 'hi' return
def test_precedence(): """test corner cases of dict key precedence""" glom({(0, 1): 3}, Match({ (0, 1): Val(1), # this should match (0, int): Val(2), # optional (0, M == 1): Val(3), # optional }) ) with pytest.raises(ValueError): Optional(int) # int is already optional so not valid to wrap
def test_val(): assert Literal is Val expected = {'value': 'c', 'type': 'a.b'} target = {'a': {'b': 'c'}} val = glom(target, {'value': 'a.b', 'type': Val('a.b')}) assert val == expected assert glom(None, Val('success')) == 'success' assert repr(Val(3.14)) == 'Val(3.14)' assert repr(Val(3.14)) == 'Val(3.14)'
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
def test_max_skip(): target = list(range(10)) + list(range(5)) max_spec = (S(max=Vars(max=0)), [((M > M(S.max.max)) & A.max.max) | Val(SKIP)], S.max) result = glom(target, max_spec) assert result.max == 9
def test_pattern_matching(): pattern_matcher = Or(And(Match(1), Val('one')), And(Match(2), Val('two')), And(Match(float), Val('float'))) assert glom(1, pattern_matcher) == 'one' assert glom(1.1, pattern_matcher) == 'float' # obligatory fibonacci fib = (M > 2) & (lambda n: glom(n - 1, fib) + glom(n - 2, fib)) | T assert glom(5, fib) == 8 factorial = (lambda t: t + 1, Ref('fact', (lambda t: t - 1, (M == 0) & Fill(1) | (S(r=Ref('fact')), S, lambda s: s['r'] * s[T])))) assert glom(4, factorial) == 4 * 3 * 2
def test_json_ref(): assert glom( {'a': {'b': [0, 1]}}, Ref('json', Match(Or( And(dict, {Ref('json'): Ref('json')}), And(list, [Ref('json')]), And(0, Val(None)), object)))) == {'a': {'b': [None, 1]}}
def test_check_ported_tests(): """ Tests ported from Check() to make sure all the functionality has an analogue. """ target = [{'id': 0}, {'id': 1}, {'id': 2}] # check that skipping non-passing values works assert glom(target, [Coalesce(M(T['id']) == 0, default=SKIP)]) == [{'id': 0}] # TODO: should M(subspec, default='') work? I lean no. # NB: this is not a very idiomatic use of Match, just brought over for Check reasons assert glom(target, [Match({'id': And(int, M == 1)}, default=SKIP)]) == [{'id': 1}] assert glom(target, [Match({'id': And(int, M <= 1)}, default=STOP)]) == [{'id': 0}, {'id': 1}] # check that stopping chain execution on non-passing values works spec = (Or(Match(len), Val(STOP)), T[0]) assert glom('hello', spec, glom_debug=True) == 'h' assert glom('', spec) == '' # would fail with IndexError if STOP didn't work target = [1, u'a'] assert glom(target, [Match(unicode, default=SKIP)]) == ['a'] assert glom(target, Match([Or(unicode, int)])) == [1, 'a'] target = ['1'] assert glom(target, [(M(T), int)]) == [1] assert glom(target, M(T)) == ['1'] failing_checks = [({'a': {'b': 1}}, {'a': ('a', 'b', Match(str))}, '''expected type str, not int'''), # TODO: bbrepr at least, maybe include path like Check did ({'a': {'b': 1}}, {'a': ('a', Match({'b': str}))}, '''expected type str, not int'''), # TODO: include subspec path ('b') (1, Match(Or(unicode, bool))), (1, Match(unicode)), (1, Match(0)), (1, Match(Or(0, 2))), ('-3.14', Match(lambda x: int(x) > 0)), # ('-3.14', M(lambda x: int(x) > 0)), # TODO: M doesn't behave quite like Match because it's mode-free ] for fc in failing_checks: if len(fc) == 2: target, check = fc msg = None else: target, check, msg = fc with pytest.raises(MatchError) as exc_info: glom(target, check) if msg is not None: actual_msg = str(exc_info.value) assert actual_msg.find(msg) != -1 assert repr(exc_info.value) return
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']"
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)'
def generer_fichier_deputes( deputes_path, groupes_path, partis_path, deputes_groupes_path, deputes_partis_path, dest, ): deputes = pd.read_csv(deputes_path) groupes = pd.read_csv(groupes_path) deputes_groupes = pd.read_csv(deputes_groupes_path).join( groupes.set_index("code")[["nom", "sigle"]], on="code") deputes_groupes = ( deputes_groupes[deputes_groupes.date_fin.isnull()].sort_values( ["code_depute", "relation"]).drop_duplicates( "code_depute", keep="last") # garder "P" (président) plutôt que "M" (membre) .set_index("code_depute")) deputes_groupes[ "groupe"] = deputes_groupes.nom + " (" + deputes_groupes.sigle + ")" partis = pd.read_csv(partis_path) deputes_partis = pd.read_csv(deputes_partis_path).join( partis.set_index("code")[["nom", "sigle"]], on="code") deputes_partis = deputes_partis[ deputes_partis.date_fin.isnull()].set_index("code_depute") deputes_partis = deputes_partis.nom + " (" + deputes_partis.sigle + ")" deputes_partis.name = "parti" deputes = deputes.join(deputes_groupes[["groupe", "relation"]], on=["code"]).join(deputes_partis, on=["code"]) with lzma.open(dest, "wt") as f, id_from_file( "circonscriptions_legislatives.csv") as id_circos, id_from_file( "deputes.csv") as id_deputes: spec = { "id": Invoke(id_deputes).specs(code=T.code), "circonscription_id": Invoke(id_circos).specs(code=T.circonscription), **{ c: getattr(T, c) for c in [ "code", "nom", "prenom", "sexe", "date_naissance", "legislature", "date_debut_mandat", ] }, "groupe": Coalesce(T.groupe, skip=pd.isna, default=""), "parti": Coalesce(T.parti, skip=pd.isna, default=""), "date_fin_mandat": Coalesce(T.date_fin_mandat, skip=pd.isna, default=NULL), "relation": Coalesce(T.relation, skip=pd.isna, default=""), "profession": Val(NULL), } w = csv.DictWriter(f, fieldnames=spec) w.writeheader() w.writerows(glom(deputes.itertuples(), Iter(spec)))
def test_clamp(): assert glom(range(10), [(M < 7) | Val(7)]) == [0, 1, 2, 3, 4, 5, 6, 7, 7, 7] assert glom(range(10), [(M < 7) | Val(SKIP)]) == [0, 1, 2, 3, 4, 5, 6]
def test_examples(): assert glom(8, (M > 7) & Val(7)) == 7 assert glom(range(10), [(M > 7) & Val(7) | T]) == [0, 1, 2, 3, 4, 5, 6, 7, 7, 7] assert glom(range(10), [(M > 7) & Val(SKIP) | T]) == [0, 1, 2, 3, 4, 5, 6, 7]