Skip to content

Commit

Permalink
Remove not needed attrs from SQLite backend. Closes #52 (#54)
Browse files Browse the repository at this point in the history
* Remove not needed attrs from SQLite backend

* Changelog & fixes

* Fix
  • Loading branch information
Stranger6667 committed Aug 11, 2018
1 parent 0b5cc41 commit ffb2c83
Show file tree
Hide file tree
Showing 11 changed files with 63 additions and 51 deletions.
2 changes: 2 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Changed
~~~~~~~

- Do not recreate the DB if it the schema is absent in the dump. `#39`_
- ``xdump.sqlite.SQLiteBackend`` now accepts only ``dbname`` and ``verbosity``. `#52`_

`0.5.0`_ - 2018-08-02
---------------------
Expand Down Expand Up @@ -105,6 +106,7 @@ Fixed
.. _0.1.2: https://github.com/Stranger6667/xdump/compare/0.1.1...0.1.2
.. _0.1.1: https://github.com/Stranger6667/xdump/compare/0.1.0...0.1.1

.. _#52: https://github.com/Stranger6667/xdump/issues/52
.. _#48: https://github.com/Stranger6667/xdump/issues/48
.. _#45: https://github.com/Stranger6667/xdump/issues/45
.. _#44: https://github.com/Stranger6667/xdump/issues/44
Expand Down
8 changes: 1 addition & 7 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,13 +238,7 @@ def backend(request):
from xdump.sqlite import SQLiteBackend

dbname = request.getfixturevalue('dbname')
return SQLiteBackend(
dbname=dbname,
user=None,
password=None,
host=None,
port=None,
)
return SQLiteBackend(dbname=dbname)


@pytest.fixture
Expand Down
16 changes: 8 additions & 8 deletions tests/django/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@
def setup(settings, backend):
if IS_POSTGRES:
settings.DATABASES['default']['ENGINE'] = 'django.db.backends.postgresql'
for source, target in (
('user', 'USER'),
('password', 'PASSWORD'),
('host', 'HOST'),
('port', 'PORT')
):
settings.DATABASES['default'][target] = getattr(backend, source)
elif IS_SQLITE:
settings.DATABASES['default']['ENGINE'] = 'django.db.backends.sqlite'
for source, target in (
('dbname', 'NAME'),
('user', 'USER'),
('password', 'PASSWORD'),
('host', 'HOST'),
('port', 'PORT')
):
settings.DATABASES['default'][target] = getattr(backend, source)
settings.DATABASES['default']['NAME'] = backend.dbname
settings.XDUMP = {
'FULL_TABLES': ('groups', ),
'PARTIAL_TABLES': {'employees': EMPLOYEES_SQL}
Expand Down
16 changes: 12 additions & 4 deletions tests/test_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import pytest

from .conftest import DATABASE, EMPLOYEES_SQL, IS_POSTGRES
from .conftest import DATABASE, EMPLOYEES_SQL, IS_POSTGRES, IS_SQLITE


def test_logging(backend, capsys):
Expand Down Expand Up @@ -65,12 +65,20 @@ def test_drop_database(self, backend, db_helper):

def test_create_database(self, backend, db_helper):
dbname = db_helper.get_new_database_name()
backend.create_database(dbname, backend.user)
if IS_POSTGRES:
backend.create_database(dbname, backend.user)
elif IS_SQLITE:
backend.create_database(dbname)
assert db_helper.is_database_exists(dbname)

@pytest.mark.parametrize('owner', (False, True))
@pytest.mark.usefixtures('schema', 'data')
def test_recreate_database(self, backend, db_helper):
backend.recreate_database()
def test_recreate_database(self, backend, db_helper, owner):
if IS_POSTGRES and owner:
owner = backend.user
else:
owner = None
backend.recreate_database(owner)
assert db_helper.is_database_exists(backend.dbname)

def test_non_existent_db(self, backend, db_helper):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_sqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@
@pytest.mark.skipif(sqlite3.sqlite_version_info >= (3, 8, 3), reason='Not relevant for newer SQLite version')
def test_old_version_info():
with pytest.raises(RuntimeError):
SQLiteBackend()
SQLiteBackend(dbname='tests')
15 changes: 4 additions & 11 deletions xdump/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,12 @@
from contextlib import contextmanager
from time import time

import attr

from ._compat import lru_cache
from .logging import get_logger


@attr.s(cmp=False)
class BaseBackend(object):
dbname = attr.ib()
user = attr.ib()
password = attr.ib()
host = attr.ib()
port = attr.ib(convert=str)
verbosity = attr.ib(convert=int, default=0)
dbname = None
connections = {'default': {}}
schema_filename = 'dump/schema.sql'
initial_setup_files = (schema_filename, )
Expand Down Expand Up @@ -193,6 +185,9 @@ def write_schema(self, file):
schema = self.dump_schema()
file.writestr(self.schema_filename, schema)

def dump_schema(self):
raise NotImplementedError

def write_full_tables(self, file, tables):
"""
Writes a complete tables dump to the archive.
Expand All @@ -217,8 +212,6 @@ def recreate_database(self, owner=None):
"""
Drops all connections to the database, drops the database and creates it again.
"""
if owner is None:
owner = self.user
self.drop_database(self.dbname)
self.create_database(self.dbname, owner)
self.cache_clear()
Expand Down
15 changes: 6 additions & 9 deletions xdump/cli/dump.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,14 @@ def parse_value(value):
] + COMMON_DECORATORS


def base_dump(backend_path, user, password, host, port, dbname, verbosity, output, full, partial, compression, schema,
data):
def base_dump(backend_path, output, full, partial, compression, schema, data, **kwargs):
"""Common implementation of dump command. Writes a few logs, imports a backend and makes a dump."""
compression = COMPRESSION_MAPPING[compression]

click.echo('Dumping ...')
click.echo('Output file: {0}'.format(output))

backend = init_backend(
backend_path, dbname=dbname, host=host, port=port, user=user, password=password, verbosity=verbosity
)
backend = init_backend(backend_path, **kwargs)
backend.dump(
output, full_tables=full, partial_tables=partial, compression=compression, dump_schema=schema,
dump_data=data
Expand All @@ -79,11 +76,11 @@ def base_dump(backend_path, user, password, host, port, dbname, verbosity, outpu

@apply_decorators(DEFAULT_PARAMETERS + PG_DECORATORS)
def postgres(user, password, host, port, dbname, verbosity, output, full, partial, compression, schema, data):
base_dump('xdump.postgresql.PostgreSQLBackend', user, password, host, port, dbname, verbosity, output, full,
partial, compression, schema, data)
base_dump('xdump.postgresql.PostgreSQLBackend', output, full, partial, compression, schema, data, user=user,
password=password, host=host, port=port, dbname=dbname, verbosity=verbosity)


@apply_decorators(DEFAULT_PARAMETERS)
def sqlite(dbname, verbosity, output, full, partial, compression, schema, data):
base_dump('xdump.sqlite.SQLiteBackend', None, None, None, None, dbname, verbosity, output, full, partial,
compression, schema, data)
base_dump('xdump.sqlite.SQLiteBackend', output, full, partial, compression, schema, data, dbname=dbname,
verbosity=verbosity)
12 changes: 5 additions & 7 deletions xdump/cli/load.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,11 @@ def load():
] + COMMON_DECORATORS


def base_load(backend_path, user, password, host, port, dbname, verbosity, input, cleanup_method):
def base_load(backend_path, input, cleanup_method, **kwargs):
click.echo('Loading ...')
click.echo('Input file: {0}'.format(input))

backend = init_backend(
backend_path, dbname=dbname, host=host, port=port, user=user, password=password, verbosity=verbosity
)
backend = init_backend(backend_path, **kwargs)

if cleanup_method == 'truncate':
backend.truncate()
Expand All @@ -40,10 +38,10 @@ def base_load(backend_path, user, password, host, port, dbname, verbosity, input

@apply_decorators(DEFAULT_PARAMETERS + PG_DECORATORS)
def postgres(user, password, host, port, dbname, verbosity, input, cleanup_method):
base_load('xdump.postgresql.PostgreSQLBackend', user, password, host, port, dbname, verbosity, input,
cleanup_method)
base_load('xdump.postgresql.PostgreSQLBackend', input, cleanup_method, user=user, password=password, host=host,
port=port, dbname=dbname, verbosity=verbosity)


@apply_decorators(DEFAULT_PARAMETERS)
def sqlite(dbname, verbosity, input, cleanup_method):
base_load('xdump.sqlite.SQLiteBackend', None, None, None, None, dbname, verbosity, input, cleanup_method)
base_load('xdump.sqlite.SQLiteBackend', input, cleanup_method, dbname=dbname, verbosity=verbosity)
10 changes: 8 additions & 2 deletions xdump/extra/django/xdump/management/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ def get_xdump_backend(self, alias='default', backend=None, verbosity=0):
'django.db.backends.postgresql_psycopg2': 'xdump.postgresql.PostgreSQLBackend',
'django.db.backends.sqlite': 'xdump.sqlite.SQLiteBackend',
}[configuration['ENGINE']]
backend_class = import_string(backend)
return backend_class(
return _init_backend(
backend,
dbname=configuration['NAME'],
user=configuration.get('USER'),
password=configuration.get('PASSWORD'),
Expand All @@ -65,3 +65,9 @@ def get_dump_kwargs(self):
'full_tables': settings.XDUMP['FULL_TABLES'],
'partial_tables': settings.XDUMP['PARTIAL_TABLES'],
}


def _init_backend(path, **kwargs):
backend_class = import_string(path)
init_kwargs = {attr.name: kwargs[attr.name] for attr in backend_class.__attrs_attrs__}
return backend_class(**init_kwargs)
10 changes: 10 additions & 0 deletions xdump/postgresql.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import subprocess
from io import BytesIO

import attr
import psycopg2
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT, ISOLATION_LEVEL_REPEATABLE_READ
from psycopg2.extras import RealDictConnection
Expand Down Expand Up @@ -62,7 +63,14 @@
'''


@attr.s(cmp=False)
class PostgreSQLBackend(BaseBackend):
dbname = attr.ib()
user = attr.ib()
password = attr.ib()
host = attr.ib()
port = attr.ib(convert=str)
verbosity = attr.ib(convert=int, default=0)
sequences_filename = 'dump/sequences.sql'
initial_setup_files = BaseBackend.initial_setup_files + (sequences_filename, )
connections = {
Expand Down Expand Up @@ -187,6 +195,8 @@ def initial_setup(self, archive):
self.restore_search_path(search_path)

def recreate_database(self, owner=None):
if owner is None:
owner = self.user
self.drop_connections(self.dbname)
super(PostgreSQLBackend, self).recreate_database(owner)

Expand Down
8 changes: 6 additions & 2 deletions xdump/sqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import sys
from csv import DictReader, DictWriter

import attr

from ._compat import FileNotFoundError, StringIO, lru_cache
from .base import BaseBackend

Expand All @@ -22,12 +24,14 @@ def force_string(value):
TABLES_SQL = "SELECT name AS table_name FROM sqlite_master WHERE type='table'"


@attr.s(cmp=False)
class SQLiteBackend(BaseBackend):
dbname = attr.ib()
verbosity = attr.ib(convert=int, default=0)

def __init__(self, *args, **kwargs):
def __attrs_post_init__(self):
if sqlite3.sqlite_version_info < (3, 8, 3):
raise RuntimeError('Minimum supported SQLite version is 3.8.3. You have {0}'.format(sqlite3.sqlite_version))
super(SQLiteBackend, self).__init__(*args, **kwargs)

def connect(self, *args, **kwargs):
connection = sqlite3.connect(self.dbname)
Expand Down

0 comments on commit ffb2c83

Please sign in to comment.