def test_link(self): """ Link to any node """ with self.app.app_context(): init_db() a_id = insert_node(name='a', value=None) b_id = insert_node(name='b', value=None) c_id = insert_node(name='c', value="c") d_id = insert_node(name='d', value="d") # a -> c, b -> c # a -> d insert_node_node(node_id=a_id, target_node_id=c_id) insert_node_node(node_id=a_id, target_node_id=d_id) insert_node_node(node_id=b_id, target_node_id=c_id) result = db.execute(text(fetch_query_string('select_link_node_from_node.sql')), node_id=a_id) result = [x['node_id'] for x in result] assert c_id in result assert d_id in result assert a_id not in result result = db.execute(text(fetch_query_string('select_link_node_from_node.sql')), node_id=b_id) result = [x['node_id'] for x in result] assert c_id in result assert d_id not in result assert a_id not in result
def test_delete_one_node(self): """ Delete a node """ with self.app.app_context(): init_db() result = db.execute(text(fetch_query_string('insert_node.sql')), name='a', value='apple') a = result.lastrowid result = db.execute(text( fetch_query_string('select_node_from_id.sql')), node_id=a).fetchall() assert len(result) == 1 r = result[0] assert a == r['node_id'] assert 'a' == r['name'] assert 'apple' == r['value'] # now delete delete_node(node_id=a) result = db.execute(text( fetch_query_string('select_node_from_id.sql')), node_id=a).fetchall() assert len(result) == 0
def test_db(self): """Check usage of db""" with self.app.app_context(): with self.app.test_client() as c: init_db() db.execute(text("""insert into Node (name, value) values (:name, :value)"""), **{"name": "bill", "value": "?"})
def test_a(self): """ """ f = open(os.path.join(self.tmp_template_dir, 'insert_llama.sql'), 'w') f.write(""" insert into Llama (llama_name, location, description) values (:llama_name, :location, :description); """) f.close() f = open(os.path.join(self.tmp_template_dir, 'select_llama.sql'), 'w') f.write(""" select * from Llama where llama_name = :llama_name; """) f.close() with self.app.app_context(): with self.app.test_client() as c: init_db() db.execute(text(""" create table Llama ( llama_name varchar(255), location varchar(255), description text ); """)) llamas_id = insert_node(name='llamas', value=None) insert_route(path='/api/llamas/', node_id=llamas_id, weight=1, method="POST") insert_query(name='insert_llama.sql', node_id=llamas_id) llama_1 = { 'llama_name': 'Rocky', 'location': 'unknown', 'description': 'first llama' } rv = c.post('/api/llamas/', data=llama_1) assert 201 == rv.status_code llama_2 = { 'llama_name': 'Nocky', 'location': 'unknown', 'description': 'second llama' } rv = c.post('/api/llamas/', data=llama_2) assert 201 == rv.status_code select_llama = insert_node(name='llamas', value=None) insert_route(path='/api/llamas/name/<llama_name>/', node_id=select_llama, weight=1) insert_query(name='select_llama.sql', node_id=select_llama) rv = c.get('/api/llamas/name/Rocky/', follow_redirects=True) rv_json = json.loads(rv.data) assert set(llama_1.keys()) == set(rv_json.keys()) assert set(llama_1.values()) == set(rv_json.values()) rv = c.get('/api/llamas/name/Nocky/', follow_redirects=True) rv_json = json.loads(rv.data) assert set(llama_2.keys()) == set(rv_json.keys()) assert set(llama_2.values()) == set(rv_json.values())
def insert_node_node(**kw): """ Link a node to another node. node_id -> target_node_id. Where `node_id` is the parent and `target_node_id` is the child. """ with current_app.app_context(): insert_query(name='select_link_node_from_node.sql', node_id=kw.get('node_id')) db.execute(text(fetch_query_string('insert_node_node.sql')), **kw)
def existing_node_input(): """ Get an existing node id by name or id. Return -1 if invalid """ input_from_user = raw_input("Existing node name or id: ") node_id = INVALID_NODE if not input_from_user: return node_id # int or str? try: parsed_input = int(input_from_user) except ValueError: parsed_input = input_from_user if isinstance(parsed_input, int): result = db.execute(text(fetch_query_string('select_node_from_id.sql')), node_id=parsed_input).fetchall() if result: node_id = int(result[0]['node_id']) else: result = db.execute(text(fetch_query_string('select_node_from_name.sql')), node_name=parsed_input).fetchall() if result: if len(result) == 1: print 'Node id: {node_id}\nNode name: {name}'.format(**result[0]) print '-------------' node_id = result[0]['node_id'] else: print 'Multiple nodes found with the name: {0}'.format(parsed_input) for item in result: print '{node_id}: {name} = {value}'.format(**item) node_selection = raw_input('Enter a node id from this list or enter "?" to render all or "?<node>" for a specific one.') if node_selection: node_selection_match = re.match(r"\?(\d)*", node_selection) if node_selection_match: if node_selection_match.groups()[0]: value = render_node(int(node_selection_match.groups()[0]), noderequest={'_no_template':True}, **result[0]) print safe_dump(value, default_flow_style=False) else: for item in result: value = render_node(item['node_id'], noderequest={'_no_template':True}, **item) print 'Node id: {0}'.format(item['node_id']) print safe_dump(value, default_flow_style=False) print '---' node_id = node_input() else: try: node_id = int(node_selection) except ValueError: node_id = INVALID_NODE print 'invalid node id: %s' % node return node_id
def add_template_for_node(name, node_id): "Set the template to use to display the node" with current_app.app_context(): db.execute(text(fetch_query_string('insert_template.sql')), name=name, node_id=node_id) result = db.execute(text(fetch_query_string('select_template.sql')), name=name, node_id=node_id).fetchall() if result: template_id = result[0]['id'] db.execute(text(fetch_query_string('update_template_node.sql')), template=template_id, node_id=node_id)
def init_db(): """Initialize a new database with the default tables for chill. Creates the following tables: Chill Node Node_Node Route Query Template """ with current_app.app_context(): for filename in CHILL_CREATE_TABLE_FILES: db.execute(text(fetch_query_string(filename)))
def test_db(self): """Check usage of db""" with self.app.app_context(): with self.app.test_client() as c: init_db() db.execute( text( """insert into Node (name, value) values (:name, :value)""" ), **{ "name": "bill", "value": "?" })
def test_insert_one_node_with_unicode(self): """ Add a node with a unicode value """ with self.app.app_context(): init_db() result = db.execute(text(fetch_query_string('insert_node.sql')), name='a', value=u'Àрpĺè') a = result.lastrowid result = db.execute(text('select * from Node where id = :id;'), id=a).fetchall() assert len(result) == 1 r = result[0] assert a == r['id'] assert 'a' == r['name'] assert u'Àрpĺè' == r['value']
def insert_route(**kw): """ `path` - '/', '/some/other/path/', '/test/<int:index>/' `node_id` `weight` - How this path is selected before other similar paths `method` - 'GET' is default. """ binding = { 'path': None, 'node_id': None, 'weight': None, 'method': "GET" } binding.update(kw) with current_app.app_context(): db.execute(text(fetch_query_string('insert_route.sql')), **binding)
def select_node(**kw): """ Select node by id. """ with current_app.app_context(): result = db.execute(text(fetch_query_string('select_node_from_id.sql')), **kw).fetchall() return result
def check_map(uri, url_root): """ return a tuple of the rule and kw. """ # TODO: Building the Map each time this is called seems like it could be more effiecent. result = [] try: result = db.execute(text(fetch_query_string('select_route_where_dynamic.sql'))).fetchall() except OperationalError as err: current_app.logger.error("OperationalError: %s", err) return (None, None) if result: #routes = result.as_dict() #(routes, col_names) = rowify(result, c.description) #current_app.logger.debug( [x['rule'] for x in routes] ) rules = map( lambda r: Rule(r['rule'], endpoint='dynamic'), result ) d_map = Map( rules ) map_adapter = d_map.bind(url_root) #current_app.logger.debug(uri) try: (rule, rule_kw) = map_adapter.match(path_info=uri, return_rule=True) #current_app.logger.debug(rule) return (str(rule), rule_kw) except HTTPException: pass return (None, {})
def uri_index(): def cleanup_url(url): url = url.strip() if url.startswith('/'): if url.endswith('/index.html'): return url elif url.endswith('/'): url = url.strip('/') if len(url) == 0: return ('public.index', {}) return ('public.uri_index', {'uri': url}) try: result = db.execute(text(fetch_query_string('select_paths_to_freeze.sql'))).fetchall() except (DatabaseError, StatementError) as err: app.logger.error("DatabaseError: %s", err) return [] urls = filter(None, map(lambda x:cleanup_url(x[0]), result)) urls_file = app.config.get('URLS_FILE', None) if urls_file: urls_file = urls_file if urls_file[0] == os.sep else os.path.join(os.getcwd(), urls_file) f = open(urls_file, 'r') urls.extend(filter(None, map(cleanup_url, f.readlines()))) f.close() return urls
def check_map(uri, url_root): """ return a tuple of the rule and kw. """ # TODO: Building the Map each time this is called seems like it could be more effiecent. result = [] try: result = db.execute( text(fetch_query_string( 'select_route_where_dynamic.sql'))).fetchall() except OperationalError as err: current_app.logger.error("OperationalError: %s", err) return (None, None) if result: #routes = result.as_dict() #(routes, col_names) = rowify(result, c.description) #current_app.logger.debug( [x['rule'] for x in routes] ) rules = map(lambda r: Rule(r['rule'], endpoint='dynamic'), result) d_map = Map(rules) map_adapter = d_map.bind(url_root) #current_app.logger.debug(uri) try: (rule, rule_kw) = map_adapter.match(path_info=uri, return_rule=True) #current_app.logger.debug(rule) return (str(rule), rule_kw) except HTTPException: pass return (None, {})
def node_from_uri(uri, method="GET"): # check if page exists in data_path # a//b == a/b/ == a/./b == a/foo/../b # '' == '.' # Prepend the uri with '/' and normalize uri = os.path.normpath(os.path.join('/', uri)) uri, ext = os.path.splitext(uri) if not uri.endswith('/'): uri = ''.join((uri, '/')) #current_app.logger.debug('uri: "%s"' % uri) rule_kw = {} select_node_from_route = fetch_query_string('select_node_from_route.sql') result = [] try: result = db.execute(text(select_node_from_route), uri=uri, method=method).fetchall() except DatabaseError as err: current_app.logger.error("DatabaseError: %s", err) #current_app.logger.debug('result: "{}", {}'.format(result, len(result))) if not result or len(result) == 0: # See if the uri matches any dynamic rules (rule, rule_kw) = check_map(uri, request.url_root) #current_app.logger.debug(rule) #current_app.logger.debug('rule: "%s"' % rule or '') if rule: try: result = db.execute(text(select_node_from_route), uri=rule, method=method).fetchall() except DatabaseError as err: current_app.logger.error("DatabaseError: %s", err) if result: #result = result.as_dict() #(result, col_names) = rowify(result, c.description) # Only one result for a getting a node from a unique path. return (result[0], rule_kw) return (None, rule_kw)
def insert_query(**kw): """ Insert a query name for a node_id. `name` `node_id` Adds the name to the Query table if not already there. Sets the query field in Node table. """ with current_app.app_context(): result = db.execute(text(fetch_query_string('select_query_where_name.sql')), **kw).fetchall() if result: kw['query_id'] = result[0]['id'] else: result = db.execute(text(fetch_query_string('insert_query.sql')), **kw) kw['query_id'] = result.lastrowid db.execute(text(fetch_query_string('insert_query_node.sql')), **kw)
def test_a(self): """ """ f = open(os.path.join(self.tmp_template_dir, 'delete_llama.sql'), 'w') f.write(""" Delete from Llama where llama_name = :llama_name; """) f.close() f = open(os.path.join(self.tmp_template_dir, 'select_llama.sql'), 'w') f.write(""" select * from Llama where llama_name = :llama_name; """) f.close() with self.app.app_context(): with self.app.test_client() as c: init_db() db.execute(text(""" create table Llama ( llama_name varchar(255), location varchar(255), description text ); """)) db.execute(text(""" insert into Llama (llama_name, location, description) values ('Docky', 'somewhere', 'damaged'); """)) select_llama = insert_node(name='llamas', value=None) insert_route(path='/api/llamas/name/<llama_name>/', node_id=select_llama, weight=1) insert_query(name='select_llama.sql', node_id=select_llama) llamas_id = insert_node(name='llamas', value=None) insert_route(path='/api/llamas/name/<llama_name>/', node_id=llamas_id, weight=1, method="DELETE") insert_query(name='delete_llama.sql', node_id=llamas_id) rv = c.get('/api/llamas/name/Docky/', follow_redirects=True) assert 200 == rv.status_code rv = c.delete('/api/llamas/name/Docky/') assert 204 == rv.status_code rv = c.get('/api/llamas/name/Docky/', follow_redirects=True) assert 404 == rv.status_code
def _query(_node_id, value=None, **kw): "Look up value by using Query table" query_result = [] try: query_result = db.execute(text(fetch_query_string('select_query_from_node.sql')), **kw).fetchall() except DatabaseError as err: current_app.logger.error("DatabaseError: %s, %s", err, kw) return value #current_app.logger.debug("queries kw: %s", kw) #current_app.logger.debug("queries value: %s", value) current_app.logger.debug("queries: %s", query_result) if query_result: values = [] for query_name in [x['name'] for x in query_result]: if query_name: result = [] try: current_app.logger.debug("query_name: %s", query_name) #current_app.logger.debug("kw: %s", kw) # Query string can be insert or select here #statement = text(fetch_query_string(query_name)) #params = [x.key for x in statement.params().get_children()] #skw = {key: kw[key] for key in params} #result = db.execute(statement, **skw) result = db.execute(text(fetch_query_string(query_name)), **kw) current_app.logger.debug("result query: %s", result.keys()) except (DatabaseError, StatementError) as err: current_app.logger.error("DatabaseError (%s) %s: %s", query_name, kw, err) if result and result.returns_rows: result = result.fetchall() #values.append(([[dict(zip(result.keys(), x)) for x in result]], result.keys())) #values.append((result.fetchall(), result.keys())) #current_app.logger.debug("fetchall: %s", values) if len(result) == 0: values.append(([], [])) else: current_app.logger.debug("result: %s", result) # There may be more results, but only interested in the # first one. Use the older rowify method for now. # TODO: use case for rowify? values.append(rowify(result, [(x, None) for x in result[0].keys()])) #current_app.logger.debug("fetchone: %s", values) value = values #current_app.logger.debug("value: %s", value) return value
def test_template(self): with self.app.app_context(): init_db() a = insert_node(name='a', value=None) add_template_for_node('template_a.html', a) aa = insert_node(name='aa', value=None) add_template_for_node('template_a.html', aa) b = insert_node(name='b', value=None) add_template_for_node('template_b.html', b) c = insert_node(name='c', value=None) add_template_for_node('template_c.html', c) result = db.execute(text( fetch_query_string('select_template_from_node.sql')), node_id=a) result = [x['name'] for x in result] assert len(result) == 1 assert result[0] == 'template_a.html' # another node that uses the same template result = db.execute(text( fetch_query_string('select_template_from_node.sql')), node_id=aa) result = [x['name'] for x in result] assert len(result) == 1 assert result[0] == 'template_a.html' # can overwrite what node is tied to what template add_template_for_node('template_over_a.html', a) result = db.execute(text( fetch_query_string('select_template_from_node.sql')), node_id=a) result = [x['name'] for x in result] assert len(result) == 1 assert result[0] == 'template_over_a.html' # this one still uses the other template result = db.execute(text( fetch_query_string('select_template_from_node.sql')), node_id=aa) result = [x['name'] for x in result] assert len(result) == 1 assert result[0] == 'template_a.html'
def insert_node(**kw): "Insert a node with a name and optional value. Return the node id." with current_app.app_context(): result = db.execute(text(fetch_query_string('insert_node.sql')), **kw) # TODO: support for postgres may require using a RETURNING id; sql # statement and using the inserted_primary_key? #node_id = result.inserted_primary_key node_id = result.lastrowid return node_id
def test_delete_one_node(self): """ Delete a node """ with self.app.app_context(): init_db() result = db.execute(text(fetch_query_string('insert_node.sql')), name='a', value='apple') a = result.lastrowid result = db.execute(text(fetch_query_string('select_node_from_id.sql')), node_id=a).fetchall() assert len(result) == 1 r = result[0] assert a == r['node_id'] assert 'a' == r['name'] assert 'apple' == r['value'] # now delete delete_node(node_id=a) result = db.execute(text(fetch_query_string('select_node_from_id.sql')), node_id=a).fetchall() assert len(result) == 0
def test_template(self): with self.app.app_context(): init_db() a = insert_node(name='a', value=None) add_template_for_node('template_a.html', a) aa = insert_node(name='aa', value=None) add_template_for_node('template_a.html', aa) b = insert_node(name='b', value=None) add_template_for_node('template_b.html', b) c = insert_node(name='c', value=None) add_template_for_node('template_c.html', c) result = db.execute(text(fetch_query_string('select_template_from_node.sql')), node_id=a) result = [x['name'] for x in result] assert len(result) == 1 assert result[0] == 'template_a.html' # another node that uses the same template result = db.execute(text(fetch_query_string('select_template_from_node.sql')), node_id=aa) result = [x['name'] for x in result] assert len(result) == 1 assert result[0] == 'template_a.html' # can overwrite what node is tied to what template add_template_for_node('template_over_a.html', a) result = db.execute(text(fetch_query_string('select_template_from_node.sql')), node_id=a) result = [x['name'] for x in result] assert len(result) == 1 assert result[0] == 'template_over_a.html' # this one still uses the other template result = db.execute(text(fetch_query_string('select_template_from_node.sql')), node_id=aa) result = [x['name'] for x in result] assert len(result) == 1 assert result[0] == 'template_a.html'
def test_delete_node_with_link(self): """ Delete a node also will delete from link """ with self.app.app_context(): init_db() a_id = insert_node(name='a', value=None) b_id = insert_node(name='b', value=None) c_id = insert_node(name='c', value="c") d_id = insert_node(name='d', value="d") # a -> c, b -> c # a -> d insert_node_node(node_id=a_id, target_node_id=c_id) insert_node_node(node_id=a_id, target_node_id=d_id) insert_node_node(node_id=b_id, target_node_id=c_id) result = db.execute(text( fetch_query_string('select_link_node_from_node.sql')), node_id=a_id) result = [x['node_id'] for x in result] assert c_id in result assert d_id in result assert a_id not in result result = db.execute(text( fetch_query_string('select_link_node_from_node.sql')), node_id=b_id) result = [x['node_id'] for x in result] assert c_id in result assert d_id not in result assert a_id not in result # now delete (should use the 'on delete cascade' sql bit) db.execute(text(fetch_query_string('delete_node_for_id.sql')), node_id=a_id) result = db.execute(text( fetch_query_string('select_node_from_id.sql')), node_id=a_id).fetchall() assert len(result) == 0 result = db.execute(text( fetch_query_string('select_link_node_from_node.sql')), node_id=a_id).fetchall() assert len(result) == 0 result = db.execute(text( fetch_query_string('select_node_node_from_node_id.sql')), node_id=a_id).fetchall() assert len(result) == 0
def render_value_for_node(node_id): """ Wrap render_node for usage in operate scripts. Returns without template rendered. """ value = None result = [] try: result = db.execute(text(fetch_query_string('select_node_from_id.sql')), node_id=node_id).fetchall() except DatabaseError as err: current_app.logger.error("DatabaseError: %s", err) if result: kw = dict(zip(result[0].keys(), result[0].values())) value = render_node(node_id, noderequest={'_no_template':True}, **kw) return value
def _template(node_id, value=None): "Check if a template is assigned to it and render that with the value" result = [] select_template_from_node = fetch_query_string('select_template_from_node.sql') try: result = db.execute(text(select_template_from_node), node_id=node_id) template_result = result.fetchone() result.close() if template_result and template_result['name']: template = template_result['name'] if isinstance(value, dict): return render_template(template, **value) else: return render_template(template, value=value) except DatabaseError as err: current_app.logger.error("DatabaseError: %s", err) # No template assigned to this node so just return the value return value
def test_delete_node_with_link(self): """ Delete a node also will delete from link """ with self.app.app_context(): init_db() a_id = insert_node(name='a', value=None) b_id = insert_node(name='b', value=None) c_id = insert_node(name='c', value="c") d_id = insert_node(name='d', value="d") # a -> c, b -> c # a -> d insert_node_node(node_id=a_id, target_node_id=c_id) insert_node_node(node_id=a_id, target_node_id=d_id) insert_node_node(node_id=b_id, target_node_id=c_id) result = db.execute(text(fetch_query_string('select_link_node_from_node.sql')), node_id=a_id) result = [x['node_id'] for x in result] assert c_id in result assert d_id in result assert a_id not in result result = db.execute(text(fetch_query_string('select_link_node_from_node.sql')), node_id=b_id) result = [x['node_id'] for x in result] assert c_id in result assert d_id not in result assert a_id not in result # now delete (should use the 'on delete cascade' sql bit) db.execute(text(fetch_query_string('delete_node_for_id.sql')), node_id=a_id) result = db.execute(text(fetch_query_string('select_node_from_id.sql')), node_id=a_id).fetchall() assert len(result) == 0 result = db.execute(text(fetch_query_string('select_link_node_from_node.sql')), node_id=a_id).fetchall() assert len(result) == 0 result = db.execute(text(fetch_query_string('select_node_node_from_node_id.sql')), node_id=a_id).fetchall() assert len(result) == 0
def operate_menu(): "Select between these operations on the database" selection = True while selection: print globals()['operate_menu'].__doc__ selection = select([ 'chill.database functions', 'execute sql file', 'render_node', 'New collection', 'Manage collection', 'Add document for node', 'help', ]) if selection == 'chill.database functions': mode_database_functions() elif selection == 'execute sql file': print "View the sql file and show a fill in the blanks interface with raw_input" sqlfile = choose_query_file() if not sqlfile: # return to the menu choices if not file picked selection = True else: sql_named_placeholders_re = re.compile(r":(\w+)") sql = fetch_query_string(sqlfile) placeholders = set(sql_named_placeholders_re.findall(sql)) print sql data = {} for placeholder in placeholders: value = raw_input(placeholder + ': ') data[placeholder] = value result = [] try: result = db.execute(text(sql), data) except DatabaseError as err: current_app.logger.error("DatabaseError: %s", err) if result and result.returns_rows: result = result.fetchall() print result if not result: print 'No results.' else: kw = result[0] if 'node_id' in kw: print 'render node %s' % kw['node_id'] value = render_node(kw['node_id'], **kw) print safe_dump(value, default_flow_style=False) else: #print safe_dump(rowify(result, [(x, None) for x in result[0].keys()]), default_flow_style=False) print safe_dump([dict(zip(x.keys(), x.values())) for x in result], default_flow_style=False) elif selection == 'render_node': print globals()['render_node'].__doc__ node_id = existing_node_input() value = render_value_for_node(node_id) print safe_dump(value, default_flow_style=False) elif selection == 'New collection': mode_new_collection() elif selection == 'Manage collection': mode_collection() elif selection == 'Add document for node': folder = current_app.config.get('DOCUMENT_FOLDER') if not folder: print "No DOCUMENT_FOLDER configured for the application." else: choices = map(os.path.basename, glob(os.path.join(folder, '*')) ) choices.sort() if len(choices) == 0: print "No files found in DOCUMENT_FOLDER." else: filename = select(choices) if filename: defaultname = os.path.splitext(filename)[0] nodename = raw_input("Enter name for node [{0}]: ".format(defaultname)) or defaultname node = insert_node(name=nodename, value=filename) print "Added document '%s' to node '%s' with id: %s" % (filename, nodename, node) elif selection == 'help': print "------" print __doc__ print "------" else: print 'Done'
def delete_node(**kw): """ Delete a node by id. """ with current_app.app_context(): db.execute(text(fetch_query_string('delete_node_for_id.sql')), **kw)
def test_rules(self): f = open(os.path.join(self.tmp_template_dir, 'insert_promoattr.sql'), 'w') f.write(""" insert into PromoAttr (node_id, title, description) values (:node_id, :title, :description); """) f.close() f = open(os.path.join(self.tmp_template_dir, 'select_promoattr.sql'), 'w') f.write(""" select * from PromoAttr where node_id = :node_id; """) f.close() f = open(os.path.join(self.tmp_template_dir, 'select_promos.sql'), 'w') f.write(""" select id as node_id, * from Node where name = 'promo' order by id limit 2 offset 13; """) f.close() f = open(os.path.join(self.tmp_template_dir, 'select_mainmenu.sql'), 'w') f.write(""" select name as link from Node where name like 'page_' order by link; """) f.close() f = open(os.path.join(self.tmp_template_dir, 'select_pageattr.sql'), 'w') f.write(""" select 'example title' as title, 'a description of the page' as description; """) f.close() expected = { "mainmenu": [ { "link": "page1" }, { "link": "page2" }, { "link": "page3" } ], "pageattr": { "description": "a description of the page", "title": "example title" }, "promos": [ { "promo": { "description": "aaaaaaaaaaaaa", "node_id": 20, "title": "promo 13" } }, { "promo": { "description": "aaaaaaaaaaaaaa", "node_id": 21, "title": "promo 14" } } ] } with self.app.app_context(): with self.app.test_client() as c: init_db() db.execute(text(""" create table PromoAttr ( node_id integer, abc integer, title varchar(255), description text ); """)) page_id = insert_node(name='page1', value=None) insert_route(path='/page1/', node_id=page_id) pageattr_id = insert_node(name='pageattr', value=None) insert_node_node(node_id=page_id, target_node_id=pageattr_id) insert_query(name='select_pageattr.sql', node_id=pageattr_id) mainmenu_id = insert_node(name='mainmenu', value=None) insert_node_node(node_id=page_id, target_node_id=mainmenu_id) insert_query(name='select_mainmenu.sql', node_id=mainmenu_id) # Add some other pages that will be shown in menu as just links insert_node(name='page2', value=None) insert_node(name='page3', value=None) promos_id = insert_node(name='promos', value=None) insert_node_node(node_id=page_id, target_node_id=promos_id) insert_query(name='select_promos.sql', node_id=promos_id) for a in range(0,100): a_id = insert_node(name='promo', value=None) db.execute(text(fetch_query_string('insert_promoattr.sql')), **{'node_id':a_id, 'title':'promo %i' % a, 'description': 'a'*a}) # wire the promo to it's attr insert_query(name='select_promoattr.sql', node_id=a_id) rv = c.get('/page1', follow_redirects=True) assert 200 == rv.status_code rv_json = json.loads(rv.data) assert set(expected.keys()) == set(rv_json.keys()) assert set(expected['pageattr'].keys()) == set(rv_json['pageattr'].keys())