Skip to content

Commit

Permalink
Common response class extracted to its own module. Rows data is now s…
Browse files Browse the repository at this point in the history
…tored including field name, following the CARTO style. Closes #35
  • Loading branch information
Dani Ramirez committed Jan 30, 2019
1 parent 2dd8546 commit 60d4680
Show file tree
Hide file tree
Showing 8 changed files with 34 additions and 25 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ A **new** bunch of middleware functions to build applications on top of CARTO.
- [ ] Protected parametrized queries (i.e. avoiding injection)
- [ ] Bind/dynamic parameters in queries (server-side render)
- [ ] Postgres data source
- [ ] psycopg2
- [x] psycopg2
- [ ] SQLAlchemy
- [ ] Asyncpg
- [x] Cache
Expand All @@ -25,6 +25,7 @@ A **new** bunch of middleware functions to build applications on top of CARTO.
- [x] Redis Cache
- [x] Tests
- [ ] Documentation
- [x] Sample scripts
- [x] Unit tests
- [x] Sample scripts

Expand Down
15 changes: 15 additions & 0 deletions src/core/common/query_response.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

class LongitudeQueryResponse:
def __init__(self, rows=None, fields=None, profiling=None):
self.rows = rows or []
self.fields = fields or {}
self.profiling = profiling or {}
self._from_cache = False


@property
def comes_from_cache(self):
return self._from_cache

def mark_as_cached(self):
self._from_cache = True
14 changes: 0 additions & 14 deletions src/core/data_sources/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,17 +146,3 @@ def flush_cache(self):
if self._cache and self._cache.is_ready:
self._cache.flush()


class LongitudeQueryResponse:
def __init__(self, rows=None, fields=None, profiling=None):
self.rows = rows or []
self.fields = fields or {}
self.profiling = profiling or {}
self._from_cache = False

@property
def comes_from_cache(self):
return self._from_cache

def mark_as_cached(self):
self._from_cache = True
8 changes: 5 additions & 3 deletions src/core/data_sources/carto.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from carto.exceptions import CartoException

from .base import DataSource, LongitudeQueryCannotBeExecutedException, LongitudeQueryResponse
from .base import DataSource, LongitudeQueryCannotBeExecutedException
from ..common.query_response import LongitudeQueryResponse
from carto.auth import APIKeyAuthClient
from carto.sql import BatchSQLClient, SQLClient

Expand Down Expand Up @@ -65,9 +66,10 @@ def execute_query(self, formatted_query, needs_commit, query_config, **opts):

def parse_response(self, response):
return LongitudeQueryResponse(
rows=[[v for k, v in dictionary.items()] for dictionary in response['rows']],
rows=response['rows'],
fields=response['fields'],
profiling={
'response_time': response['time']
'response_time': response['time'],
'total_rows': response['total_rows']
}
)
8 changes: 5 additions & 3 deletions src/core/data_sources/postgres/default.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import psycopg2
import psycopg2.extensions
from ..base import DataSource
from ..base import LongitudeQueryResponse
from ...common.query_response import LongitudeQueryResponse
from time import time


Expand Down Expand Up @@ -68,6 +68,8 @@ def _type_as_string(type_id):

def parse_response(self, response):
if response:
fields_names = {n.name: self._type_as_string(n.type_code).name for n in response['fields']}
return LongitudeQueryResponse(rows=response['rows'], fields=fields_names, profiling=response['profiling'])
raw_fields = response['fields']
fields_names = {n.name: {'type': self._type_as_string(n.type_code).name} for n in raw_fields}
rows = [{raw_fields[i].name: f for i, f in enumerate(row_data)} for row_data in response['rows']]
return LongitudeQueryResponse(rows=rows, fields=fields_names, profiling=response['profiling'])
return None
3 changes: 2 additions & 1 deletion src/core/tests/test_data_source_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
from unittest import TestCase, mock

from ..caches.base import LongitudeCache
from ..data_sources.base import DataSource, DataSourceQueryConfig, LongitudeQueryResponse
from ..data_sources.base import DataSource, DataSourceQueryConfig
from ..common.query_response import LongitudeQueryResponse


def load_raw_text(filename):
Expand Down
2 changes: 1 addition & 1 deletion src/core/tests/test_data_source_carto.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def test_setup_can_accept_on_premise_domain(self):
def test_succesful_query(self):
ds = CartoDataSource()
ds._sql_client = mock.MagicMock()
ds._sql_client.send.return_value = {'rows': [], 'time': 42.0, 'fields': {}}
ds._sql_client.send.return_value = {'rows': [], 'time': 42.0, 'fields': {}, 'total_rows': 0}
result = ds.query('some query')
ds._sql_client.send.assert_called_with('some query', do_post=False, format='json', parse_json=True)
self.assertEqual([], result.rows)
Expand Down
6 changes: 4 additions & 2 deletions src/samples/postgres_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@
needs_commit=True)
print(r1.profiling)

r2 = ds.query("insert into users(name, password) values('longitude', 'password')", needs_commit=True)
print(r2.profiling)
for i in range(10):
r2 = ds.query("insert into users(name, password) values('longitude%d', 'password%d')" % (i, i),
needs_commit=True)
print(r2.profiling)

r3 = ds.query('select * from users')
print(r3.rows)
Expand Down

0 comments on commit 60d4680

Please sign in to comment.