def test_fdict_viewitems(): '''Test fdict viewitems()''' # No fastview a = fdict({'a': {'b': 1, 'c': 2}, 'd': 3}) assert dict(a.items()) == fdict.flatkeys({'a': {'b': 1, 'c': 2}, 'd': 3}) assert dict(a['a'].items()) == {'c': 2, 'b': 1} # Fastview mode a = fdict({'a': {'b': 1, 'c': 2, 'e': {'f': 4}}, 'd': 3}, fastview=True) assert dict(a.items()) == fdict.flatkeys({ 'a': { 'b': 1, 'c': 2, 'e': { 'f': 4 } }, 'd': 3 }) assert dict(a['a'].items()) == {'c': 2, 'b': 1, 'e/f': 4} # test with fastview mode and nodes=True v1 = dict(a.items(nodes=True)) assert v1 == { 'a/c': 2, 'a/b': 1, 'a/e/f': 4, 'a/e/': set(['a/e/f']), 'a/': set(['a/e/', 'a/c', 'a/b']), 'd': 3 } v2 = dict(a['a'].items(nodes=True)) assert v2 == {'e/': set(['e/f']), 'b': 1, 'c': 2, 'e/f': 4} # test with fullpath v3 = dict(a['a'].items(nodes=True, fullpath=True)) assert v3 == {'a/e/': set(['a/e/f']), 'a/c': 2, 'a/b': 1, 'a/e/f': 4}
def test_fdict_setitem_update_fdict(): '''Test fdict setitem+update with another fdict or dict''' a = fdict({'a': {'b': 1, 'c': set([1, 2])}}) a1 = a.copy() a2 = a.copy() a3 = a.copy() a4 = a.copy() a5 = a.copy() a6 = a.copy() b1 = fdict({'b': 2, 'd': 3}) b2 = {'b': 2, 'd': 3} b3 = fdict({'e': {'f': 4}}) a1['a'] = b1 a2['a'] = b2 a3['a'] = b3['e'] # Node replacement fails with non-fastview fdict for now (else it would imply calling viewitems and being super slow! Then it would be no better than fastview mode) #assert a1 == a2 == {'a/d': 3, 'a/b': 2} #assert ('a/c', set([1, 2])) not in a1.items() #assert ('a/c', set([1, 2])) not in a2.items() #assert a3 == {'a/f': 4} a4['a'].update(b1) a5['a'].update(b2) a6['a'].update(b3['e']) assert a4 == a5 == {'a/d': 3, 'a/c': set([1, 2]), 'a/b': 2} assert ('a/c', set([1, 2])) in a4.items() assert ('a/c', set([1, 2])) in a5.items() assert a6 == {'a/f': 4, 'a/c': set([1, 2]), 'a/b': 1}
def test_fdict_str_repr(): '''Test fdict str and repr''' def convert_sets_to_lists(d): for k, v in d.items(): if isinstance(v, set): d[k] = list(v) return d # No fastview a = fdict({'a': {'b': 1, 'c': [1, 2]}}) assert ast.literal_eval(str(a)) == ast.literal_eval(repr(a)) == a.to_dict() assert ast.literal_eval(str(a['a'])) == ast.literal_eval(repr( a['a'])) == a['a'].to_dict() a = fdict({'a': { 'b': 1, 'c': [1, 2], 'd': { 'e': 1 } }}, fastview=True) # fastview mode asub = a['a'] # Need to convert all sets to lists, else literal_eval will fail a.d = convert_sets_to_lists(a.d) # cannot use ast for asub with fastview because of nodes, they will always be shown as sets (unless we extract but then there is no rootpath and we cannot test this branch) assert ast.literal_eval(str(a)) == ast.literal_eval(repr(a)) == a.d assert "'d/'" not in str(asub) and "'c': [1, 2]" in str( asub) and "'b': 1" in str(asub) and "'d/e': 1" in str(asub) assert "'d/'" in repr(asub) and "'c': [1, 2]" in repr( asub) and "'b': 1" in repr(asub) and "'d/e': 1" in repr( asub) # nodes are present in repr but not in str
def test_fdict_basic(): '''fdict: Basic tests + copy test''' a = fdict() a['a'] = {} a['c']['b'] = set([1, 2]) assert list(a.keys()) == ['c/b'] assert dict(a.items()) == dict([('c/b', set([1, 2]))]) # Test sharing of the internal dict across nested fdicts assert id(a.d) == id(a['c'].d) # Test equality assert a == { 'c/b': set([1, 2]) } and a == { 'c': { 'b': set([1, 2]) } } # equality dict assert a['c/b'] == set([1, 2]) # leaf direct access assert a['c']['b'] == set([1, 2]) # leaf indirect access assert a['c'] == {'b': set([1, 2])} # node assert a['c/d'] == {} # inexistent node assert (a['c/d'] == 1) == False # inexistent node and wrong type # Test getitem assert a['c']['b'] == a['c/b'] == set([1, 2]) # leaf assert dict(a['c'].items()) == {'b': set([1, 2])} # node # Copy test acopy = a.copy() assert dict(acopy.items()) == dict(a.items()) assert acopy is not a # Referencing into another variable of a nested item + check update of nested items b = acopy['c'] assert dict(b.items()) == dict([('b', set([1, 2]))]) acopy['c'].update({'d': 3}) assert acopy == {'c/b': set([1, 2]), 'c/d': 3} assert b == {'b': set([1, 2]), 'd': 3} # Test subitem assignment with a nested dict d = fdict() d['b'] = {'a': 1} d['c/b'] = set([2, 3, 5]) assert d.to_dict() == {'c/b': set([2, 3, 5]), 'b/a': 1} # Test simple update a.update(d) assert a.to_dict() == {'c/b': set([2, 3, 5]), 'b/a': 1} assert a['c'].to_dict() == {'b': set([2, 3, 5])} # Test initialization with a dict a = fdict(d={'a': {'b': set([1, 2])}}) assert not isinstance(a['a']['b'], fdict) and isinstance( a['a']['b'], set) # should return the leaf's object, not a nested fdict! assert a['a']['b'] == set([1, 2])
def validate_data(doc, sender=None, project=None): d = fdict(doc, delimiter=delimiter) for key in list(d.keys()): key = key.strip() nodes = key.split(delimiter) is_quantity_key = int(nodes[-1] in quantity_keys) if len(nodes) > max_depth + is_quantity_key: raise ValidationError( {"error": f"max nesting ({max_depth}) exceeded for {key}"}) if is_quantity_key: continue for node in nodes: for char in node: if char in invalidChars: raise ValidationError({ "error": f"invalid character '{char}' in {node} ({key})" }) value = str(d[key]) words = value.split() try_quantity = bool(len(words) == 2 and is_float(words[0])) if try_quantity or isinstance(d[key], (int, float)): try: q = Q_(value).to_compact() if not q.check(0): q.ito_reduced_units() if sender: _key = key.replace(".", "__") query = {"project": project, f"data__{_key}__exists": True} sample = (sender.objects.only(f"data.{key}.unit").filter( **query).first()) if sample: sample_fdct = fdict(sample["data"], delimiter=delimiter) q.ito(sample_fdct[f"{key}.unit"]) v = Decimal(str(q.magnitude)) vt = v.as_tuple() if vt.exponent < 0: dgts = len(vt.digits) dgts = max_dgts if dgts > max_dgts else dgts v = f"{v:.{dgts}g}" if try_quantity: q = Q_(f"{v} {q.units}") except Exception as ex: raise ValidationError({"error": str(ex)}) d[key] = { "display": str(q), "value": q.magnitude, "unit": str(q.units) } return d.to_dict_nested()
def test_fdict_init_tuples(): '''Test fdict init with a non-dict object (eg, list of tuples)''' a = fdict([('a', {'b': 1, 'c': set([1, 2])})]) assert a == {'a/c': set([1, 2]), 'a/b': 1} a = fdict([('a', { 'b': 1, 'c': set([1, 2]) })], fastview=True) # fastview mode assert a == {'a/c': set([1, 2]), 'a/b': 1} assert a.d == {'a/c': set([1, 2]), 'a/b': 1, 'a/': set(['a/c', 'a/b'])}
def test_fdict_extract_contains_delitem(): '''Test fdict extract, contains and delitem''' a10 = fdict() a10['c/b/d'] = set([1, 2]) assert a10['c'].extract(fullpath=True).d == {'c/b/d': set([1, 2])} assert a10['c'].extract(fullpath=True) == {'b/d': set([1, 2])} assert a10['c'].extract(fullpath=False).d == {'b/d': set([1, 2])} # Contains test p = fdict() p['a/b/c'] = set([1, 2]) p['a/c'] = 3 p['a/d'] = {'e': {'f': 4}, 'g': 5} p['h'] = 6 assert 'h' in p # check existence of a leaf (O(1)) assert 'a/b/c' in p # check existence of a nested leaf (O(1)) assert 'a/b' in p # check existence of a nested dict (O(n)) assert 'c' in p['a/b'] assert 'c' in p['a']['b'] assert 'b' in p['a'] assert not 'b' in p assert not 'x' in p assert not 'x' in p['a'] # Del test p = fdict() p['a/b/c'] = set([1, 2]) p['a/c'] = 3 p['a/d'] = {'e': {'f': 4}, 'g': 5} p['h'] = 6 p2 = p.copy() assert 'h' in p # check existence of a leaf (O(1)) assert 'a/b/c' in p # check existence of a nested leaf (O(1)) assert 'a/b' in p # check existence of a nested dict (O(n)) del p['a/b/c'] del p2['a']['b'][ 'c'] # test both types of access (fullpath or by subselection) assert p == p2 == {'h': 6, 'a/d/e/f': 4, 'a/c': 3, 'a/d/g': 5} del p['h'] del p2['h'] assert p == p2 == {'a/d/e/f': 4, 'a/c': 3, 'a/d/g': 5} del p['a/d'] del p2['a']['d'] assert p == p2 == {'a/c': 3} try: # Delete inexistent key del p['a']['b']['x'] assert False except KeyError as exc: assert True else: assert False
def test_fdict_fastview_delitem(): '''Test fdict fastview delitem''' # Test leaf deletion a = fdict({ 'a': { 'b': 1, 'c': set([1, 2]), 'd': { 'e': 3 } }, 'f': 4 }, fastview=True) assert a.d == { 'a/c': set([1, 2]), 'a/b': 1, 'f': 4, 'a/d/': set(['a/d/e']), 'a/d/e': 3, 'a/': set(['a/d/', 'a/c', 'a/b']) } del a['a']['d']['e'] assert a.d == { 'a/c': set([1, 2]), 'a/b': 1, 'f': 4, 'a/': set(['a/c', 'a/b']) } del a['a/c'] assert a.d == {'a/b': 1, 'f': 4, 'a/': set(['a/b'])} del a['a/b'] assert a.d == {'f': 4} del a['f'] assert a.d == a == {} # Test node deletion a = fdict({'a': {'b': {'c': set([1, 2])}}, 'd': 3}, fastview=True) a2 = a.copy() assert a.d == a2.d == { 'a/b/c': set([1, 2]), 'd': 3, 'a/': set(['a/b/']), 'a/b/': set(['a/b/c']) } del a['a']['b'] del a2['a/b'] assert a.d == a2.d == {'d': 3}
def test_fdict_flattening_extract_update(): '''Test fdict flattening, extract and update''' # Flattening test m = {} m['a'] = 1 m['b'] = {'c': 3, 'd': {'e': 5}} m['f'] = set([1, 2, 5]) m2 = fdict(m) assert dict(m2.items()) == fdict.flatkeys(m) # Update and extract test n = {} n['b'] = {'d': {'f': 6}} n['g'] = 7 m2.update(n) assert m2 == { 'a': 1, 'g': 7, 'b/c': 3, 'b/d/e': 5, 'b/d/f': 6, 'f': set([1, 2, 5]) } assert m2['b'].d == m2.d assert m2['b'].extract().d == {'b/c': 3, 'b/d/e': 5, 'b/d/f': 6} # len() test assert len(m2) == 6 assert len(m2['b']) == 3 assert len(m2['b']['d']) == len(m2['b/d']) == 2 assert not hasattr(m2['g'], '__len__') and isinstance(m2['g'], int)
def test_fdict_str_nodict(): '''Test fdict string representation and repr if provided an internal dict-like object that has no str method''' class nostrdict(object): def __init__(self, d=None): if d is None: d = {} self.d = d self.viewkeys, self.viewvalues, self.viewitems = fdict._getitermethods( self.d) self.keys, self.values, self.items = fdict._getitermethods(self.d) return def __getitem__(self, key): return self.d.__getitem__(key) def __setitem__(self, key, d): return self.d.__setitem__(key, d) __str__ = None __repr__ = None anodict = nostrdict({'a': 1}) assert dict(anodict.viewitems()) == {'a': 1} a = fdict(anodict, rootpath='lala') a.rootpath = '' # cheat to bypass object conversion to dict at init, and then remove rootpath assert dict(a.items()) == {'a': 1} assert str(a) == repr(a) == "{'a': 1}"
def test_fdict_fastview_setitem_noconflict_delitem(): '''Test fdict fastview setitem replacement of singleton by nested dict and inversely + delitem''' a = fdict({'a/b': 1, 'a/c': set([1, 2, 3]), 'd': [1, 2, 3]}, fastview=True) # singleton to nested dict a['d/e'] = 4 a['d/f'] = 5 assert ('d', [1, 2, 3]) not in a.viewitems(nodes=True) # nested dict to singleton a['a'] = 2 # add nested dict (and check metadata creation for each parent of nested leaves in the nested dict) a['g'] = {'h': {'i': {'j': 6}, 'k': 7}, 'l': 8} assert a['a'] == 2 # delitem singleton del a['g/h/i/j'] assert a.d == { 'a': 2, 'd/': set(['d/f', 'd/e']), 'g/l': 8, 'd/f': 5, 'd/e': 4, 'g/h/': set(['g/h/k']), 'g/': set(['g/l', 'g/h/']), 'g/h/k': 7 } # delitem nested dict del a['d'] assert a.d == { 'a': 2, 'g/l': 8, 'g/h/': set(['g/h/k']), 'g/': set(['g/l', 'g/h/']), 'g/h/k': 7 }
def test_fdict_fastview_pop_popitem(): '''Test fdict with fastview pop and popitem''' # fastview mode a = fdict({'a': {'b': 1, 'c': 2}, 'd': 3}, fastview=True) a2 = a.copy() leaf = a.pop('a/b') assert leaf == 1 assert a.d == {'a/': set(['a/c']), 'a/c': 2, 'd': 3} node = a.pop('a') assert node.d == {'a/c': 2, 'a/': set(['a/c'])} assert a == {'d': 3} inexistent = a.pop('e', 'inexistent!') assert inexistent == 'inexistent!' a2.popitem() a2.popitem() a2.popitem() try: a2.popitem() assert False except KeyError: assert True else: assert False
def get(self, **kwargs): cid = kwargs["pk"] # only Fetch enabled try: card = super().get(**kwargs) # trigger DoesNotExist if necessary if not card["html"]: contrib = Contributions.objects.only("project", "data").get(pk=cid) info = Projects.objects.get(pk=contrib.project.id) ctx = {"cid": cid} ctx["title"] = info.title ctx["descriptions"] = info.description.strip().split(".", 1) authors = [a.strip() for a in info.authors.split(",") if a] ctx["authors"] = {"main": authors[0], "etal": authors[1:]} ctx["landing_page"] = f"/{contrib.project.id}/" ctx["more"] = f"/{cid}" ctx["urls"] = info.urls.values() card_script = get_resource_as_string("templates/linkify.min.js") card_script += get_resource_as_string( "templates/linkify-element.min.js" ) card_script += get_resource_as_string("templates/card.min.js") fd = fdict(contrib.data, delimiter=".") ends = [f".{qk}" for qk in quantity_keys] for key in list(fd.keys()): if any(key.endswith(e) for e in ends): value = fd.pop(key) if key.endswith(ends[0]): new_key = key.rsplit(".", 1)[0] # drop .display fd[new_key] = value data = fd.to_dict_nested() browser = get_browser() browser.execute_script(card_script, data) bs = BeautifulSoup(browser.page_source, "html.parser") ctx["data"] = bs.body.table # browser.close() rendered = html_minify(render_template("card.html", **ctx)) tree = html.fromstring(rendered) inline(tree) card = Cards.objects.get(pk=cid) card.html = html.tostring(tree.body[0]).decode("utf-8") card.save() return super().get(**kwargs) except DoesNotExist: card = None try: card = Cards.objects.only("pk").get(pk=cid) except DoesNotExist: # Card has never been requested before # create and save unexecuted card, also start entry to avoid rebuild on subsequent requests contrib = Contributions.objects.only("project", "is_public").get(pk=cid) card = Cards(pk=cid, is_public=contrib.is_public) card.save() return self.get(**kwargs) if card is not None: raise DoesNotExist( f"Card {card.pk} exists but user not in project group" )
def test_fdict_empty_list(): '''Test fdict assigning an empty list''' a = fdict({}) a['a'] = {} assert a == {} a['b'] = [] a['b'].append(1) assert a == {'b': [1]}
def test_fdict_viewkeys(): '''Test fdict viewkeys()''' # No fastview a = fdict({'a': {'b': 1, 'c': 2}, 'd': 3}) assert set(a.keys()) == set(['a/c', 'd', 'a/b']) assert set(a['a'].keys()) == set(['c', 'b']) # Fastview mode a = fdict({'a': {'b': 1, 'c': 2, 'e': {'f': 4}}, 'd': 3}, fastview=True) assert set(a.keys()) == set(['a/c', 'd', 'a/e/f', 'a/b']) assert set(a['a'].keys()) == set(['c', 'b', 'e/f']) # test with fastview mode and nodes=True v1 = set(a.keys(nodes=True)) assert v1 == set(['a/c', 'd', 'a/e/f', 'a/e/', 'a/', 'a/b']) v2 = set(a['a'].keys(nodes=True)) assert v2 == set(['e/', 'c', 'b', 'e/f']) # test with fullpath v3 = set(a['a'].keys(nodes=True, fullpath=True)) assert v3 == set(['a/e/', 'a/c', 'a/b', 'a/e/f'])
def test_fdict_viewvalues(): '''Test fdict viewvalues()''' # No fastview a = fdict({'a': {'b': 1, 'c': 2}, 'd': 3}) assert set(a.values()) == set([1, 2, 3]) assert set(a['a'].values()) == set([1, 2]) # Fastview mode a = fdict({'a': {'b': 1, 'c': 2, 'e': {'f': 4}}, 'd': 3}, fastview=True) assert set(a.values()) == set([1, 2, 3, 4]) assert set(a['a'].values()) == set([1, 2, 4]) # test with fastview mode and nodes=True v1 = list(a.values(nodes=True)) assert set(['a/e/f']) in v1 and set(['a/b', 'a/c', 'a/e/']) in v1 v2 = list(a['a'].values(nodes=True)) assert set(['e/f']) in v2 # test with fullpath v3 = list(a['a'].values(nodes=True, fullpath=True)) assert set(['a/e/f']) in v3
def test_fdict_update_exception(): '''Test fdict update exception if supplied non-dict object''' a = fdict() try: a.update([1, 2]) assert False except ValueError: assert True else: assert False
def test_fdict_firstmethods(): '''Test fdict first*() methods (firstkey, firstitem, firstvalue)''' # Test firstkey, firstitem and firstvalue a = fdict({'a': {'b': {'c': 1, 'd': 2}, 'e': 3}, 'f': 4}) fkey = a['a'].firstkey() fitem = a['a'].firstitem() fval = a['a'].firstvalue() assert fkey == 'b' or fkey == 'e' assert fitem == ('b', {'c': 1, 'd': 2}) or fitem == ('e', 3) assert fval == {'c': 1, 'd': 2} or fval == 3
def test_fdict_extract_fastview(): '''Test fdict extract with fastview''' a = fdict({'a': { 'b': 1, 'c': [1, 2], 'd': { 'e': 1 } }}, fastview=True) # fastview mode asub = a['a'].extract(fullpath=True) assert asub == fdict({'c': [1, 2], 'b': 1, 'd/e': 1}) assert asub.d == { 'a/d/': set(['a/d/e']), 'a/c': [1, 2], 'a/b': 1, 'a/': set(['a/d/', 'a/c', 'a/b']), 'a/d/e': 1 } asub2 = a['a'].extract(fullpath=False) assert asub2 == {'c': [1, 2], 'b': 1, 'd/e': 1} assert asub2.d == {'d/': set(['d/e']), 'c': [1, 2], 'b': 1, 'd/e': 1}
def test_fdict_setitem_nesteddict(): '''Test fdict setitem (assignment) of a nested dict''' # Test dict to sub fdict assignment a = fdict() a2 = a.copy() a3 = a.copy() a4 = a.copy() a['a']['c'] = {'subelements': {'e': 1, 'f': {'g': 1}}} a2['a/c'] = {'subelements': {'e': 1, 'f': {'g': 1}}} a3['a']['c'] = fdict({'subelements': {'e': 1, 'f': {'g': 1}}}) a4['a/c'] = fdict({'subelements': {'e': 1, 'f': {'g': 1}}}) assert a.d == a2.d == a3.d == a4.d == { 'a/c/subelements/f/g': 1, 'a/c/subelements/e': 1 } # Test singleton assignments and all is alright a['b'] = {} a['b']['d'] = 2 a['a']['b'] = 3 assert a == { 'a/c/subelements/f/g': 1, 'a/c/subelements/e': 1, 'b/d': 2, 'a/b': 3 } # Test nested fdict to sub fdict assignment a = fdict() a['a']['c'] = {'subelements': {'e': 1, 'f': {'g': 1}}} a2 = a.copy() a3 = a.copy() b = fdict({'x': {'y': {'subelements': {'e': -2, 'f': {'g': -2}}}}}) a['a']['c'] = b['x']['y'] assert a.d == {'a/c/subelements/f/g': -2, 'a/c/subelements/e': -2} # Test nested fdict to root fdict assigment a2 = b['x']['y'] assert a2 == {'subelements/f/g': -2, 'subelements/e': -2} # Test root fdict to sub fdict assignment a3['a']['c'] = b assert a3.d == { 'a/c/subelements/f/g': 1, 'a/c/subelements/e': 1, 'a/c/x/y/subelements/f/g': -2, 'a/c/x/y/subelements/e': -2 } # Test nested normal dict to sub fdict assignment a = fdict() a['a']['c'] = {'subelements': {'e': 1, 'f': {'g': 1}}} a3 = a.copy() b = {'x': {'y': {'subelements': {'e': -2, 'f': {'g': -2}}}}} a['a']['c'] = b['x']['y'] assert a.d == {'a/c/subelements/f/g': -2, 'a/c/subelements/e': -2} # Test root fdict to sub fdict assignment a3['a']['c'] = b assert a3.d == { 'a/c/subelements/f/g': 1, 'a/c/subelements/e': 1, 'a/c/x/y/subelements/f/g': -2, 'a/c/x/y/subelements/e': -2 }
def test_fdict_fastview_del(): '''Test fastview del''' a = fdict( { 'a/e/g/': set(['a/e/g/i', 'a/e/g/h']), 'a/e/f': 3, 'a/e/': set(['a/e/g/', 'a/e/f']), 'a/': set(['a/e/', 'a/b/']), 'a/b/c': 1, 'a/b/d': 2, 'a/b/': set(['a/b/c', 'a/b/d']), 'a/e/g/i': 5, 'a/e/g/h': 4 }, fastview=True) a2 = a.copy() # leaf deletion assert set(a['a'].keys(fullpath=True, nodes=True)) == set([ 'a/e/', 'a/e/g/', 'a/b/', 'a/b/c', 'a/b/d', 'a/e/f', 'a/e/g/i', 'a/e/g/h' ]) del a['a/e/g/h'] del a2['a']['e']['g']['h'] assert a.d == a2.d == { 'a/e/g/': set(['a/e/g/i']), 'a/e/f': 3, 'a/e/': set(['a/e/g/', 'a/e/f']), 'a/': set(['a/e/', 'a/b/']), 'a/b/c': 1, 'a/b/d': 2, 'a/b/': set(['a/b/c', 'a/b/d']), 'a/e/g/i': 5 } assert 'a/e/g/h' not in list(a['a'].keys(fullpath=True, nodes=True)) # node deletion assert set(a['a/e'].keys()) == set(a2['a']['e'].keys()) == set( ['g/i', 'f']) assert set(a['a/e'].keys(nodes=True)) == set( a['a']['e'].keys(nodes=True)) == set(['g/', 'g/i', 'f']) del a['a/e'] del a2['a']['e'] assert a.d == a2.d == { 'a/': set(['a/b/']), 'a/b/c': 1, 'a/b/d': 2, 'a/b/': set(['a/b/c', 'a/b/d']) } assert a == a2 == {'a/b/c': 1, 'a/b/d': 2} assert not set(a['a/e'].keys()) and not dict(a2['a']['e']) assert set(a['a'].keys(fullpath=True, nodes=True)) == set(['a/b/', 'a/b/d', 'a/b/c'])
def test_fdict_setitem_update_fdict_fastview(): '''Test fdict fastview setitem+update with another fdict or dict''' a = fdict({'a': {'b': 1, 'c': set([1, 2])}}, fastview=True) a1 = a.copy() a2 = a.copy() a3 = a.copy() a4 = a.copy() a5 = a.copy() a6 = a.copy() b1 = fdict({'b': 2, 'd': 3}) b2 = {'b': 2, 'd': 3} b3 = fdict({'e': {'f': 4}}, fastview=True) a1['a'] = b1 a2['a'] = b2 a3['a'] = b3['e'] assert a1.d == a2.d == {'a/d': 3, 'a/b': 2, 'a/': set(['a/d', 'a/b'])} assert ('a/c', set([1, 2])) not in a1.items() assert ('a/c', set([1, 2])) not in a2.items() assert a3.d == {'a/f': 4, 'a/': set(['a/f'])} a4['a'].update(b1) a5['a'].update(b2) a6['a'].update(b3['e']) assert a4.d == a5.d == { 'a/d': 3, 'a/c': set([1, 2]), 'a/b': 2, 'a/': set(['a/c', 'a/b', 'a/d']) } assert ('a/c', set([1, 2])) in a4.items() and 'a/d' in a4.d['a/'] assert ('a/c', set([1, 2])) in a5.items() and 'a/d' in a5.d['a/'] assert a6.d == { 'a/f': 4, 'a/c': set([1, 2]), 'a/b': 1, 'a/': set(['a/f', 'a/c', 'a/b']) }
def test_fdict_update_nesteddict(): '''Test fdict update of a nested dict''' # Test dict to sub fdict assignment a = fdict() a['a'] = {} a['a']['b'] = 2 a2 = a.copy() a3 = a.copy() a4 = a.copy() a['a']['c'].update({'subelements': {'e': 1, 'f': {'g': 1}}}) a2['a/c'].update({'subelements': {'e': 1, 'f': {'g': 1}}}) a3['a']['c'].update(fdict({'subelements': {'e': 1, 'f': {'g': 1}}})) a4['a/c'].update(fdict({'subelements': {'e': 1, 'f': {'g': 1}}})) assert a.d == a2.d == a3.d == a4.d == { 'a/c/subelements/f/g': 1, 'a/c/subelements/e': 1, 'a/b': 2 } # Test nested fdict to sub fdict assignment a = fdict() a['a']['c'] = {'subelements': {'e': 1, 'f': {'g': 1}}} a2 = a.copy() a3 = a.copy() b = fdict({'x': {'y': {'subelements': {'e': -2, 'f': {'g': -2}}}}}) a['a']['c'].update(b['x']['y']) assert a.d == {'a/c/subelements/f/g': -2, 'a/c/subelements/e': -2} # Test nested fdict to root fdict assigment a2.update(b['x']['y']) assert a2.d == { 'a/c/subelements/f/g': 1, 'a/c/subelements/e': 1, 'subelements/f/g': -2, 'subelements/e': -2 } # Test root fdict to sub fdict assignment a3['a']['c'].update(b) assert a3.d == { 'a/c/subelements/f/g': 1, 'a/c/subelements/e': 1, 'a/c/x/y/subelements/f/g': -2, 'a/c/x/y/subelements/e': -2 } # Test nested normal dict to sub fdict assignment a = fdict() a['a']['c'] = {'subelements': {'e': 1, 'f': {'g': 1}}} a3 = a.copy() b = {'x': {'y': {'subelements': {'e': -2, 'f': {'g': -2}}}}} a['a']['c'].update(b['x']['y']) assert a.d == {'a/c/subelements/f/g': -2, 'a/c/subelements/e': -2} # Test root fdict to sub fdict assignment a3['a']['c'].update(b) assert a3.d == { 'a/c/subelements/f/g': 1, 'a/c/subelements/e': 1, 'a/c/x/y/subelements/f/g': -2, 'a/c/x/y/subelements/e': -2 }
def test_fdict_setitem_replacement(): '''Test emptying by setitem to empty dict and singleton replacement by a nested dict''' a = fdict({ 'a/b': 1, 'a/c': set([1, 2, 3]), 'd': [1, 2, 3], 'e': [1, 2, 3] }) # emptying by setitem with empty dict a['d'] = {} assert a == {'a/c': set([1, 2, 3]), 'a/b': 1, 'e': [1, 2, 3]} # replace singleton with a dict a['e'] = {'f': 2, 'g': 3} assert a == {'a/c': set([1, 2, 3]), 'a/b': 1, 'e/g': 3, 'e/f': 2} # replace dict with a singleton (does not work, both will coexist) a['a'] = 2 assert a == {'a': 2, 'a/c': set([1, 2, 3]), 'a/b': 1, 'e/g': 3, 'e/f': 2}
def test_fdict_fastview_metadata_nested_dict(): '''Test fastview nodes metadata creation with nested dicts and at creation''' a = fdict({'a/b': 1, 'a/c': set([1, 2, 3]), 'd': [1, 2, 3]}, fastview=True) # add nested dict a['g'] = {'h': {'i': {'j': 6}, 'k': 7}, 'l': 8} assert a.d == { 'g/l': 8, 'g/h/i/j': 6, 'g/h/i/': set(['g/h/i/j']), 'a/': set(['a/b', 'a/c']), 'a/c': set([1, 2, 3]), 'a/b': 1, 'g/h/': set(['g/h/k', 'g/h/i/']), 'g/': set(['g/l', 'g/h/']), 'g/h/k': 7, 'd': [1, 2, 3] }
def test_fdict_viewrestrict(): '''Test fdict view*_restrict methods''' a = fdict({'a': {'b': {'c': 1, 'd': 2}, 'e': 3}, 'f': 4}) assert set(a.viewkeys_restrict()) == set(['a', 'f']) assert set(a['a'].viewkeys_restrict()) == set(['b', 'e']) assert set(a['a'].viewkeys_restrict(fullpath=True)) == set(['a/b', 'a/e']) res = list(a.viewitems_restrict()) assert ('a', {'b/d': 2, 'b/c': 1, 'e': 3}) in res and ('f', 4) in res res = list(a['a'].viewitems_restrict()) assert ('b', {'c': 1, 'd': 2}) in res and ('e', 3) in res res = list(a['a'].viewitems_restrict(fullpath=True)) assert ('a/b', {'c': 1, 'd': 2}) in res and ('a/e', 3) in res res = list(a.viewvalues_restrict()) assert {'b/d': 2, 'b/c': 1, 'e': 3} in res and 4 in res res = list(a['a'].viewvalues_restrict()) assert {'c': 1, 'd': 2} in res and 3 in res res = list(a['a'].viewvalues_restrict(fullpath=True)) assert {'c': 1, 'd': 2} in res and 3 in res
def test_fdict_eq_extended(): '''Test fdict equality/inequality''' a = fdict({'a': {'b': 1, 'c': 2}, 'd': 3}) # Unequal by size assert a != {'a': 1} assert a != fdict({'a': 1}) assert a['a'] != fdict({'b': 1, 'c': 2, 'e': 4}) # Unequal by value assert a != {'a': {'b': 1, 'c': 2}, 'd': -1} assert a != {'a': {'b': 1, 'c': -1}, 'd': 3} # Equal assert a == {'a': {'b': 1, 'c': 2}, 'd': 3} assert a == fdict({'a': {'b': 1, 'c': 2}, 'd': 3}) assert a['a'] == {'b': 1, 'c': 2} assert a['a'] == fdict({'b': 1, 'c': 2}) # Equality with subclasses or variants assert a == fdict({'a': {'b': 1, 'c': 2}, 'd': 3}, fastview=True) assert a['a'] == fdict({'b': 1, 'c': 2}, fastview=True) assert a == sfdict({'a': {'b': 1, 'c': 2}, 'd': 3}) assert a['a'] == sfdict({'b': 1, 'c': 2})
def test_fdict_pop_popitem(): '''Test fdict pop and popitem''' a = fdict({'a': {'b': 1, 'c': 2}, 'd': 3}) a2 = a.copy() leaf = a.pop('a/b') assert leaf == 1 assert a == {'a/c': 2, 'd': 3} node = a.pop('a') assert node.d == {'a/c': 2} assert a == {'d': 3} inexistent = a.pop('e', 'inexistent!') assert inexistent == 'inexistent!' a2.popitem() a2.popitem() a2.popitem() try: a2.popitem() assert False except KeyError: assert True else: assert False
def set_data(self, data={}): self.global_data = fdict(data) self.update_data()
def test_fdict_creation(): '''fdict: Test creation of just a nested dict, without anything else''' a = fdict() a['c']['b'] = set([1, 2]) assert a == {'c/b': set([1, 2])}