From b1fff4628f94a3f3eab70f5fcc1e5005679ef1d0 Mon Sep 17 00:00:00 2001 From: Javier Sancho Date: Wed, 30 May 2018 12:06:40 +0200 Subject: [PATCH] Some refactoring for treating tables and arrays in the same way --- datasette_pytables/__init__.py | 119 ++++++++++++++++----------------- tests/test_api.py | 6 +- 2 files changed, 62 insertions(+), 63 deletions(-) diff --git a/datasette_pytables/__init__.py b/datasette_pytables/__init__.py index 80349a6..7bbc7c1 100644 --- a/datasette_pytables/__init__.py +++ b/datasette_pytables/__init__.py @@ -11,7 +11,7 @@ def inspect(path): h5file = tables.open_file(path) for table in filter(lambda node: not(isinstance(node, tables.group.Group)), h5file): - colnames = [] + colnames = ['value'] if isinstance(table, tables.table.Table): colnames = table.colnames @@ -87,6 +87,9 @@ class Connection: table = self.h5file.get_node(parsed_sql['from']) table_rows = [] fields = parsed_sql['select'] + colnames = ['value'] + if type(table) is tables.table.Table: + colnames = table.colnames query = '' start = 0 @@ -95,10 +98,9 @@ class Connection: # Use 'where' statement or get all the rows def _cast_param(field, pname): # Cast value to the column type + coltype = table.dtype.name if type(table) is tables.table.Table: coltype = table.coltypes[field] - else: - coltype = table.dtype.name fcast = None if coltype == 'string': fcast = str @@ -161,71 +163,68 @@ class Connection: table_rows = table.iterrows(start, end) # Prepare rows - if len(fields) == 1 and type(fields[0]['value']) is dict and \ - fields[0]['value'].get('count') == '*': - rows.append(Row({'count(*)': int(table.nrows)})) - else: + def normalize_field_value(value): + if type(value) is bytes: + return value.decode('utf-8') + elif not type(value) in (int, float, complex): + return str(value) + else: + return value + + def make_get_rowid(): if type(table) is tables.table.Table: - count = 0 - for table_row in table_rows: - count += 1 - if limit and count > limit: - break - if truncate and max_returned_rows and count > max_returned_rows: - truncated = True - break - row = Row() - for field in fields: - field_name = field['value'] - if type(field_name) is dict and 'distinct' in field_name: - field_name = field_name['distinct'] - if field_name == 'rowid': - row['rowid'] = int(table_row.nrow) - elif field_name == '*': - for col in table.colnames: - value = table_row[col] - if type(value) is bytes: - value = value.decode('utf-8') - row[col] = value - else: - row[field_name] = table_row[field_name] - rows.append(row) + def get_rowid(row): + return int(row.nrow) else: - # Any kind of array rowid = start - 1 - count = 0 - for table_row in table_rows: - count += 1 - if limit and count > limit: - break - if truncate and max_returned_rows and count > max_returned_rows: - truncated = True - break - row = Row() + def get_rowid(row): + nonlocal rowid rowid += 1 - for field in fields: - field_name = field['value'] - if type(field_name) is dict and 'distinct' in field_name: - field_name = field_name['distinct'] - if field_name == 'rowid': - row['rowid'] = rowid - else: - value = table_row - if type(value) is bytes: - value = value.decode('utf-8') - elif not type(value) in (int, float, complex): - value = str(value) - row['value'] = value - rows.append(row) + return rowid + return get_rowid + + def make_get_row_value(): + if type(table) is tables.table.Table: + def get_row_value(row, field): + return row[field] + else: + def get_row_value(row, field): + return row + return get_row_value + + if len(fields) == 1 and type(fields[0]['value']) is dict and \ + fields[0]['value'].get('count') == '*': + rows.append(Row({'count(*)': int(table.nrows)})) + else: + get_rowid = make_get_rowid() + get_row_value = make_get_row_value() + count = 0 + for table_row in table_rows: + count += 1 + if limit and count > limit: + break + if truncate and max_returned_rows and count > max_returned_rows: + truncated = True + break + row = Row() + for field in fields: + field_name = field['value'] + if type(field_name) is dict and 'distinct' in field_name: + field_name = field_name['distinct'] + if field_name == 'rowid': + row['rowid'] = get_rowid(table_row) + elif field_name == '*': + for col in colnames: + row[col] = normalize_field_value(get_row_value(table_row, col)) + else: + row[field_name] = normalize_field_value(get_row_value(table_row, field_name)) + rows.append(row) # Prepare query description for field in [f['value'] for f in fields]: if field == '*': - if type(table) is tables.table.Table: - for col in table.colnames: - description.append((col,)) - else: - description.append(('value',)) + for col in colnames: + description.append((col,)) else: description.append((field,)) diff --git a/tests/test_api.py b/tests/test_api.py index 14bfbfd..5d0bfdc 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -18,7 +18,7 @@ def test_database_page(app_client): assert 'test_tables' == data['database'] assert [{ 'name': '/array1', - 'columns': [], + 'columns': ['value'], 'primary_keys': [], 'count': 2, 'label_column': None, @@ -27,7 +27,7 @@ def test_database_page(app_client): 'foreign_keys': {'incoming': [], 'outgoing': []} }, { 'name': '/group1/array2', - 'columns': [], + 'columns': ['value'], 'primary_keys': [], 'count': 10000, 'label_column': None, @@ -45,7 +45,7 @@ def test_database_page(app_client): 'foreign_keys': {'incoming': [], 'outgoing': []} }, { 'name': '/group2/multi', - 'columns': [], + 'columns': ['value'], 'primary_keys': [], 'count': 10, 'label_column': None, -- 2.39.2