Merge branch 'master' into fix-table-cache
This commit is contained in:
commit
a4d676f325
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,6 +1,7 @@
|
|||||||
*.pyc
|
*.pyc
|
||||||
*.egg-info
|
*.egg-info
|
||||||
dist/*
|
dist/*
|
||||||
|
build/*
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.watchr
|
.watchr
|
||||||
|
|
||||||
|
|||||||
11
.travis.yml
Normal file
11
.travis.yml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
language: python
|
||||||
|
python:
|
||||||
|
- '3.3'
|
||||||
|
- '2.7'
|
||||||
|
- '2.6'
|
||||||
|
install:
|
||||||
|
- pip install flake8
|
||||||
|
script:
|
||||||
|
- flake8 --ignore=E501,E123,E124,E126,E127,E128 dataset test
|
||||||
|
- python setup.py test
|
||||||
@ -8,7 +8,6 @@ from dataset.persistence.util import sqlite_datetime_fix
|
|||||||
from dataset.persistence.database import Database
|
from dataset.persistence.database import Database
|
||||||
from dataset.persistence.table import Table
|
from dataset.persistence.table import Table
|
||||||
from dataset.freeze.app import freeze
|
from dataset.freeze.app import freeze
|
||||||
from sqlalchemy import Integer, Text
|
|
||||||
|
|
||||||
__all__ = ['Database', 'Table', 'freeze', 'connect']
|
__all__ = ['Database', 'Table', 'freeze', 'connect']
|
||||||
|
|
||||||
|
|||||||
@ -86,4 +86,3 @@ class Export(object):
|
|||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
return self.get('name', self.get('query'))
|
return self.get('name', self.get('query'))
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import os
|
import os
|
||||||
import logging
|
|
||||||
import re
|
import re
|
||||||
import locale
|
import locale
|
||||||
|
|
||||||
@ -69,8 +68,7 @@ class Serializer(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def wrap(self):
|
def wrap(self):
|
||||||
return self.export.get_bool('wrap',
|
return self.export.get_bool('wrap', default=self.mode == 'list')
|
||||||
default=self.mode=='list')
|
|
||||||
|
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
self.init()
|
self.init()
|
||||||
|
|||||||
@ -21,4 +21,3 @@ class TabsonSerializer(JSONSerializer):
|
|||||||
if meta is not None:
|
if meta is not None:
|
||||||
result['meta'] = meta
|
result['meta'] = meta
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|||||||
@ -11,9 +11,9 @@ except ImportError:
|
|||||||
|
|
||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine
|
||||||
from sqlalchemy.pool import NullPool
|
from sqlalchemy.pool import NullPool
|
||||||
from sqlalchemy.schema import MetaData, Column, Index
|
from sqlalchemy.schema import MetaData, Column
|
||||||
from sqlalchemy.schema import Table as SQLATable
|
from sqlalchemy.schema import Table as SQLATable
|
||||||
from sqlalchemy import Integer, Text, String
|
from sqlalchemy import Integer, String
|
||||||
|
|
||||||
from alembic.migration import MigrationContext
|
from alembic.migration import MigrationContext
|
||||||
from alembic.operations import Operations
|
from alembic.operations import Operations
|
||||||
@ -107,10 +107,8 @@ class Database(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def tables(self):
|
def tables(self):
|
||||||
""" Get a listing of all tables that exist in the database.
|
"""
|
||||||
|
Get a listing of all tables that exist in the database.
|
||||||
>>> print db.tables
|
|
||||||
set([u'user', u'action'])
|
|
||||||
"""
|
"""
|
||||||
return list(
|
return list(
|
||||||
set(self.metadata.tables.keys()) | set(self._tables.keys())
|
set(self.metadata.tables.keys()) | set(self._tables.keys())
|
||||||
|
|||||||
@ -1,9 +1,5 @@
|
|||||||
import logging
|
import logging
|
||||||
from itertools import count
|
from itertools import count
|
||||||
try:
|
|
||||||
from collections import OrderedDict
|
|
||||||
except ImportError:
|
|
||||||
from ordereddict import OrderedDict # Python < 2.7 drop-in
|
|
||||||
|
|
||||||
from sqlalchemy.sql import and_, expression
|
from sqlalchemy.sql import and_, expression
|
||||||
from sqlalchemy.schema import Column, Index
|
from sqlalchemy.schema import Column, Index
|
||||||
@ -28,9 +24,6 @@ class Table(object):
|
|||||||
def columns(self):
|
def columns(self):
|
||||||
"""
|
"""
|
||||||
Get a listing of all columns that exist in the table.
|
Get a listing of all columns that exist in the table.
|
||||||
|
|
||||||
>>> print 'age' in table.columns
|
|
||||||
True
|
|
||||||
"""
|
"""
|
||||||
return set(self.table.columns.keys())
|
return set(self.table.columns.keys())
|
||||||
|
|
||||||
@ -105,7 +98,6 @@ class Table(object):
|
|||||||
if chunk:
|
if chunk:
|
||||||
_process_chunk(chunk)
|
_process_chunk(chunk)
|
||||||
|
|
||||||
|
|
||||||
def update(self, row, keys, ensure=True, types={}):
|
def update(self, row, keys, ensure=True, types={}):
|
||||||
"""
|
"""
|
||||||
Update a row in the table. The update is managed via
|
Update a row in the table. The update is managed via
|
||||||
@ -288,7 +280,7 @@ class Table(object):
|
|||||||
rp = self.database.executable.execute(query)
|
rp = self.database.executable.execute(query)
|
||||||
data = rp.fetchone()
|
data = rp.fetchone()
|
||||||
if data is not None:
|
if data is not None:
|
||||||
return OrderedDict(zip(rp.keys(), data))
|
return data
|
||||||
|
|
||||||
def _args_to_order_by(self, order_by):
|
def _args_to_order_by(self, order_by):
|
||||||
if order_by[0] == '-':
|
if order_by[0] == '-':
|
||||||
@ -337,6 +329,9 @@ class Table(object):
|
|||||||
rp = self.database.executable.execute(count_query)
|
rp = self.database.executable.execute(count_query)
|
||||||
total_row_count = rp.fetchone()[0]
|
total_row_count = rp.fetchone()[0]
|
||||||
|
|
||||||
|
if _limit is None:
|
||||||
|
_limit = total_row_count
|
||||||
|
|
||||||
if _step is None or _step is False or _step == 0:
|
if _step is None or _step is False or _step == 0:
|
||||||
_step = total_row_count
|
_step = total_row_count
|
||||||
|
|
||||||
@ -348,8 +343,6 @@ class Table(object):
|
|||||||
|
|
||||||
for i in count():
|
for i in count():
|
||||||
qoffset = _offset + (_step * i)
|
qoffset = _offset + (_step * i)
|
||||||
qlimit = _step
|
|
||||||
if _limit is not None:
|
|
||||||
qlimit = min(_limit - (_step * i), _step)
|
qlimit = min(_limit - (_step * i), _step)
|
||||||
if qlimit <= 0:
|
if qlimit <= 0:
|
||||||
break
|
break
|
||||||
|
|||||||
@ -1,9 +1,5 @@
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from inspect import isgenerator
|
from inspect import isgenerator
|
||||||
try:
|
|
||||||
from collections import OrderedDict
|
|
||||||
except ImportError:
|
|
||||||
from ordereddict import OrderedDict # Python < 2.7 drop-in
|
|
||||||
|
|
||||||
from sqlalchemy import Integer, UnicodeText, Float, DateTime, Boolean, types, Table, event
|
from sqlalchemy import Integer, UnicodeText, Float, DateTime, Boolean, types, Table, event
|
||||||
|
|
||||||
@ -50,7 +46,7 @@ class ResultIter(object):
|
|||||||
else:
|
else:
|
||||||
# stop here
|
# stop here
|
||||||
raise StopIteration
|
raise StopIteration
|
||||||
return OrderedDict(zip(self.keys, row))
|
return row
|
||||||
|
|
||||||
next = __next__
|
next = __next__
|
||||||
|
|
||||||
@ -64,6 +60,8 @@ def sqlite_datetime_fix():
|
|||||||
epoch = datetime(1970, 1, 1, 0, 0, 0)
|
epoch = datetime(1970, 1, 1, 0, 0, 0)
|
||||||
|
|
||||||
def process_bind_param(self, value, dialect):
|
def process_bind_param(self, value, dialect):
|
||||||
|
if isinstance(value, datetime):
|
||||||
|
return value
|
||||||
return (value / 1000 - self.epoch).total_seconds()
|
return (value / 1000 - self.epoch).total_seconds()
|
||||||
|
|
||||||
def process_result_value(self, value, dialect):
|
def process_result_value(self, value, dialect):
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
#coding: utf-8
|
#coding: utf-8
|
||||||
import re
|
import re
|
||||||
from unicodedata import normalize as ucnorm, category
|
|
||||||
|
|
||||||
SLUG_REMOVE = re.compile(r'[,\s\.\(\)/\\;:]*')
|
SLUG_REMOVE = re.compile(r'[,\s\.\(\)/\\;:]*')
|
||||||
|
|
||||||
|
|
||||||
class DatasetException(Exception):
|
class DatasetException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class FreezeException(DatasetException):
|
class FreezeException(DatasetException):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
7
setup.py
7
setup.py
@ -25,17 +25,18 @@ setup(
|
|||||||
author_email='info@okfn.org',
|
author_email='info@okfn.org',
|
||||||
url='http://github.com/pudo/dataset',
|
url='http://github.com/pudo/dataset',
|
||||||
license='MIT',
|
license='MIT',
|
||||||
packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
|
packages=find_packages(exclude=['ez_setup', 'examples', 'test']),
|
||||||
namespace_packages=[],
|
namespace_packages=[],
|
||||||
include_package_data=False,
|
include_package_data=False,
|
||||||
zip_safe=False,
|
zip_safe=False,
|
||||||
install_requires=[
|
install_requires=[
|
||||||
'sqlalchemy >= 0.8.1',
|
'sqlalchemy >= 0.9.1',
|
||||||
'alembic >= 0.6.1',
|
'alembic >= 0.6.2',
|
||||||
'python-slugify >= 0.0.6',
|
'python-slugify >= 0.0.6',
|
||||||
"PyYAML >= 3.10"
|
"PyYAML >= 3.10"
|
||||||
] + py26_dependency,
|
] + py26_dependency,
|
||||||
tests_require=[],
|
tests_require=[],
|
||||||
|
test_suite='test',
|
||||||
entry_points={
|
entry_points={
|
||||||
'console_scripts': [
|
'console_scripts': [
|
||||||
'datafreeze = dataset.freeze.app:main',
|
'datafreeze = dataset.freeze.app:main',
|
||||||
|
|||||||
@ -2,15 +2,18 @@ import os
|
|||||||
import unittest
|
import unittest
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
from sqlalchemy.exc import IntegrityError
|
||||||
|
|
||||||
from dataset import connect
|
from dataset import connect
|
||||||
from dataset.util import DatasetException
|
from dataset.util import DatasetException
|
||||||
|
|
||||||
from .sample_data import TEST_DATA, TEST_CITY_1
|
from .sample_data import TEST_DATA, TEST_CITY_1
|
||||||
from sqlalchemy.exc import IntegrityError
|
|
||||||
|
|
||||||
|
|
||||||
class DatabaseTestCase(unittest.TestCase):
|
class DatabaseTestCase(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
self.old_db_url = os.environ.get('DATABASE_URL')
|
||||||
os.environ['DATABASE_URL'] = 'sqlite:///:memory:'
|
os.environ['DATABASE_URL'] = 'sqlite:///:memory:'
|
||||||
self.db = connect('sqlite:///:memory:')
|
self.db = connect('sqlite:///:memory:')
|
||||||
self.tbl = self.db['weather']
|
self.tbl = self.db['weather']
|
||||||
@ -19,7 +22,10 @@ class DatabaseTestCase(unittest.TestCase):
|
|||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
# ensure env variable was unset
|
# ensure env variable was unset
|
||||||
|
if self.old_db_url is None:
|
||||||
del os.environ['DATABASE_URL']
|
del os.environ['DATABASE_URL']
|
||||||
|
else:
|
||||||
|
os.environ['DATABASE_URL'] = self.old_db_url
|
||||||
|
|
||||||
def test_valid_database_url(self):
|
def test_valid_database_url(self):
|
||||||
assert self.db.url, os.environ['DATABASE_URL']
|
assert self.db.url, os.environ['DATABASE_URL']
|
||||||
@ -187,6 +193,10 @@ class TableTestCase(unittest.TestCase):
|
|||||||
assert len(ds) == 3, ds
|
assert len(ds) == 3, ds
|
||||||
ds = list(self.tbl.find(place=TEST_CITY_1, _limit=2))
|
ds = list(self.tbl.find(place=TEST_CITY_1, _limit=2))
|
||||||
assert len(ds) == 2, ds
|
assert len(ds) == 2, ds
|
||||||
|
ds = list(self.tbl.find(place=TEST_CITY_1, _limit=2, _step=1))
|
||||||
|
assert len(ds) == 2, ds
|
||||||
|
ds = list(self.tbl.find(place=TEST_CITY_1, _limit=1, _step=2))
|
||||||
|
assert len(ds) == 1, ds
|
||||||
|
|
||||||
def test_distinct(self):
|
def test_distinct(self):
|
||||||
x = list(self.tbl.distinct('place'))
|
x = list(self.tbl.distinct('place'))
|
||||||
@ -195,8 +205,8 @@ class TableTestCase(unittest.TestCase):
|
|||||||
assert len(x) == 6, x
|
assert len(x) == 6, x
|
||||||
|
|
||||||
def test_insert_many(self):
|
def test_insert_many(self):
|
||||||
data = TEST_DATA * 5000
|
data = TEST_DATA * 100
|
||||||
self.tbl.insert_many(data)
|
self.tbl.insert_many(data, chunk_size=13)
|
||||||
assert len(self.tbl) == len(data) + 6
|
assert len(self.tbl) == len(data) + 6
|
||||||
|
|
||||||
def test_drop_warning(self):
|
def test_drop_warning(self):
|
||||||
@ -239,7 +249,7 @@ class TableTestCase(unittest.TestCase):
|
|||||||
tbl = self.tbl
|
tbl = self.tbl
|
||||||
tbl.create_column('foo', FLOAT)
|
tbl.create_column('foo', FLOAT)
|
||||||
assert 'foo' in tbl.table.c, tbl.table.c
|
assert 'foo' in tbl.table.c, tbl.table.c
|
||||||
assert FLOAT == type(tbl.table.c['foo'].type), tbl.table.c['foo'].type
|
assert isinstance(tbl.table.c['foo'].type, FLOAT), tbl.table.c['foo'].type
|
||||||
assert 'foo' in tbl.columns, tbl.columns
|
assert 'foo' in tbl.columns, tbl.columns
|
||||||
|
|
||||||
def test_key_order(self):
|
def test_key_order(self):
|
||||||
@ -247,6 +257,3 @@ class TableTestCase(unittest.TestCase):
|
|||||||
keys = list(res.next().keys())
|
keys = list(res.next().keys())
|
||||||
assert keys[0] == 'temperature'
|
assert keys[0] == 'temperature'
|
||||||
assert keys[1] == 'place'
|
assert keys[1] == 'place'
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user