Passed
Push — develop ( b1b5c2...3c9778 )
by Bastien
02:39
created

DeleteDBCommand.get_description()   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
cc 1
nop 1
1
# -*- coding: utf-8 -*-
2
import argparse
3
4
import plaster_pastedeploy
5
import transaction
6
from depot.manager import DepotManager
7
from pyramid.paster import get_appsettings
8
from sqlalchemy.exc import IntegrityError
9
10
from tracim_backend import CFG
11
from tracim_backend.command import AppContextCommand
12
from tracim_backend.exceptions import DatabaseInitializationFailed
13
from tracim_backend.exceptions import ForceArgumentNeeded
14
from tracim_backend.exceptions import InvalidSettingFile
15
from tracim_backend.fixtures import FixturesLoader
16
from tracim_backend.fixtures.content import Content as ContentFixture
17
from tracim_backend.fixtures.users_and_groups import Base as BaseFixture
18
from tracim_backend.models import get_engine
19
from tracim_backend.models import get_session_factory
20
from tracim_backend.models import get_tm_session
21
from tracim_backend.models.meta import DeclarativeBase
22
23
24
class InitializeDBCommand(AppContextCommand):
25
    auto_setup_context = False
26
27
    def get_description(self) -> str:
28
        return "Initialize database"
29
30
    def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
31
        parser = super().get_parser(prog_name)
32
        parser.add_argument(
33
            "--test-data",
34
            help='Add some default data to database to make test',
35
            dest='test_data',
36
            required=False,
37
            action='store_true',
38
            default=False,
39
        )
40
        return parser
41
42
    def take_action(self, parsed_args: argparse.Namespace) -> None:
43
        super(InitializeDBCommand, self).take_action(parsed_args)
44
        config_uri = parsed_args.config_file
45
        settings = get_appsettings(config_uri)
46
        # INFO - G.M - 2018-06-178 - We need to add info from [DEFAULT]
47
        # section of config file in order to have both global and
48
        # web app specific param.
49
        settings.update(settings.global_conf)
50
        if 'sqlalchemy.url' not in settings or not settings['sqlalchemy.url']:
51
            raise InvalidSettingFile('Wrong or empty sqlalchemy database url,'
52
                                     'check config file')
53
        self._create_schema(settings)
54
        self._populate_database(settings, add_test_data=parsed_args.test_data)
55
56
    @classmethod
57
    def _create_schema(
58
            cls,
59
            settings: plaster_pastedeploy.ConfigDict
60
    ) -> None:
61
        print("- Create Schemas of databases -")
62
        engine = get_engine(settings)
63
        DeclarativeBase.metadata.create_all(engine)
64
65
    @classmethod
66
    def _populate_database(
67
            cls,
68
            settings: plaster_pastedeploy.ConfigDict,
69
            add_test_data: bool
70
    ) -> None:
71
        engine = get_engine(settings)
72
        session_factory = get_session_factory(engine)
73
        app_config = CFG(settings)
74
        print("- Populate database with default data -")
75
        with transaction.manager:
76
            dbsession = get_tm_session(session_factory, transaction.manager)
77
            try:
78
                fixtures = [BaseFixture]
79
                fixtures_loader = FixturesLoader(dbsession, app_config)
80
                fixtures_loader.loads(fixtures)
81
                transaction.commit()
82
                if add_test_data:
83
                    app_config.configure_filedepot()
84
                    fixtures = [ContentFixture]
85
                    fixtures_loader.loads(fixtures)
86
                transaction.commit()
87
                print("Database initialized.")
88
            except IntegrityError as exc:
89
                transaction.abort()
90
                print('Database initialization failed')
91
                raise DatabaseInitializationFailed(
92
                    'Warning, there was a problem when adding default data'
93
                    ', it may have already been added.'
94
                ) from exc
95
96
97
class DeleteDBCommand(AppContextCommand):
98
    auto_setup_context = False
99
100
    def get_description(self) -> str:
101
        return "Delete database"
102
103
    def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
104
        parser = super().get_parser(prog_name)
105
        parser.add_argument(
106
            "--force",
107
            help='force delete of database',
108
            dest='force',
109
            required=False,
110
            action='store_true',
111
            default=False,
112
        )
113
        return parser
114
115
    def take_action(self, parsed_args: argparse.Namespace) -> None:
116
        super(DeleteDBCommand, self).take_action(parsed_args)
117
        config_uri = parsed_args.config_file
118
        # setup_logging(config_uri)
119
        settings = get_appsettings(config_uri)
120
        settings.update(settings.global_conf)
121
        if 'sqlalchemy.url' not in settings or not settings['sqlalchemy.url']:
122
            raise InvalidSettingFile('Wrong or empty sqlalchemy database url,'
123
                                     'check config file')
124
        engine = get_engine(settings)
125
        app_config = CFG(settings)
126
        app_config.configure_filedepot()
127
128
        if parsed_args.force:
129
            print('Database deletion begin.')
130
            DeclarativeBase.metadata.drop_all(engine)
131
            print('Database deletion done.')
132
            try:
133
                print('Cleaning depot begin.')
134
                depot = DepotManager.get()
135
                depot_files = depot.list()
136
                for file_ in depot_files:
137
                    depot.delete(file_)
138
                print('Cleaning depot done.')
139
            except FileNotFoundError:
140
                print(
141
                    'Warning ! Can delete depots file, is depot path correctly'
142
                    'configured ?'
143
                )
144
        else:
145
            raise ForceArgumentNeeded(
146
                'Warning, You should use --force if you really want to'
147
                ' delete database.'
148
            )
149