Coverage for barrack.py: 100%
58 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-08 21:58 +0200
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-08 21:58 +0200
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3"""
4Traits / mixins are the heart of archery, but sometimes you need functions to help you
6"""
7try:
8 from collections import MutableMapping
9except ImportError:
10 from collections.abc import MutableMapping
13MARKER=object()
15class Path(tuple):
16 def endswith( self, *a_tuple ):
17 """check if path ends with the consecutive given has argumenbts value
19 >>> p = Path( [ 'a', 'b', 'c' ] )
20 >>> p.endswith( 'b', 'c' )
21 >>> True
22 >>> p.endswith( 'c', 'b' )
23 >>> False
24 """
25 return self[len(self) - len(a_tuple) : ] == a_tuple
27 def startswith( self, *a_tuple ):
28 """checks if a path starts with the value
30 >>> p = Path( [ 'a', 'b', 'c', 'd' ] )
31 >>> p.startswith( 'a', 'b' )
32 >>> True
33 """
34 return self[: len( a_tuple ) ] == a_tuple
36 def _contains( self, a_tuple, _from = 0, follow = 0):
37 if len( a_tuple) == follow:
38 return True
39 index = False
40 here = self[ _from:]
42 try:
43 index = here.index(a_tuple[follow] )
44 return self._contains(
45 a_tuple,
46 index + 1 ,
47 follow + 1
48 )
49 except ValueError:
50 return False
51 return False
53 def contains(self, *a_tuple ):
54 """checks if the serie of keys is contained in a path
56 >>> p = Path( [ 'a', 'b', 'c', 'd' ] )
57 >>> p.contains( 'b', 'c' )
58 >>> True
60 """
61 return self._contains(a_tuple)
63 def value(self):
64 """ function provided for code readability:
65 - returns the left most value of the Path aka the value
66 """
67 return self[-1]
69 def key(self):
70 """ function provided for code readability:
71 - returns all the keys in the Path
72 """
73 return Path(self[:-1])
75def make_from_path(type_of_mapping, path):
76 """Work in Progress
77 create a mutable mapping from a `Path`_ (tuple made of a series of keys in a dict leading to a
78 value followed by a value).
79 The source is used a mapping factory and is reset in the process
81 >>> make_from_path(dict, ("y", "z", 2))
82 >>> #Out[2]: {'y': {'z': 2}}
84 """
85 path = list(path)
86 value = path.pop()
87 last_key = path.pop()
88 tmap = type_of_mapping
89 mapping = tmap({last_key : value})
90 while path:
91 _next = path.pop()
92 mapping = tmap({_next : mapping })
93 return mapping
95def bowyer(_mapping_fact, _mapping_to_convert):
96 """the craftsman that makes bow
97 A function that given a function in the form
98 f(tree) will convert a one level tree in your mapping"""
99 _toc = _mapping_fact(_mapping_to_convert)
100 for k, v in _toc.items():
101 if isinstance(v, MutableMapping) and len(v):
102 _toc[k] = bowyer(_mapping_fact, v)
103 return _toc
105def mapping_row_iter(tree, path=MARKER):
106 """
107 iterator on a tree that yield an iterator on a mapping in the form of
108 a list of ordered key that leads to the element and the value
110 >>> from archery import mapping_row_iter
111 >>> [ x for x in mapping_row_iter({
112 ... "john" : {'math':10.0, 'sport':1.0},~
113 ... "lily" : { 'math':20, 'sport':15.0}
114 ... })]
115 >>> #[['john', 'sport', 1.0], ['john', 'math', 10.0],~
116 >>> #['lily', 'sport', 15.0], ['lily', 'math', 20]]
118 """
119 if path is MARKER:
120 path = ()
121 for k, v in tree.items():
122 if isinstance(v, MutableMapping) and len(v):
123 for child in mapping_row_iter(v, (path + (k,))):
124 yield child
125 else:
126 yield path + (k , v)
129def paired_row_iter(tree, path=MARKER):
130 """
131 iterator on a tree that yield a pair key (path to a value), value
132 """
133 if path is MARKER:
134 path = tuple()
136 for k, v in tree.items():
137 if isinstance(v, MutableMapping) and len(v):
138 for child in paired_row_iter(v, path + (k,)):
139 yield child
140 else:
141 yield ((path + (k,)) , v)