yhttp-dbmanager 7.0.2__tar.gz → 8.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. {yhttp_dbmanager-7.0.2/yhttp_dbmanager.egg-info → yhttp_dbmanager-8.0.2}/PKG-INFO +1 -1
  2. yhttp_dbmanager-7.0.2/tests/test_cli.py → yhttp_dbmanager-8.0.2/tests/test_cli_createdrop.py +2 -17
  3. yhttp_dbmanager-8.0.2/tests/test_cli_migration.py +78 -0
  4. yhttp_dbmanager-8.0.2/tests/test_cli_usercommand.py +30 -0
  5. yhttp_dbmanager-8.0.2/tests/test_migrator.py +68 -0
  6. {yhttp_dbmanager-7.0.2 → yhttp_dbmanager-8.0.2}/yhttp/ext/dbmanager/__init__.py +2 -1
  7. yhttp_dbmanager-8.0.2/yhttp/ext/dbmanager/cli.py +167 -0
  8. {yhttp_dbmanager-7.0.2 → yhttp_dbmanager-8.0.2}/yhttp/ext/dbmanager/install.py +8 -1
  9. yhttp_dbmanager-8.0.2/yhttp/ext/dbmanager/migration.py +192 -0
  10. {yhttp_dbmanager-7.0.2 → yhttp_dbmanager-8.0.2/yhttp_dbmanager.egg-info}/PKG-INFO +1 -1
  11. {yhttp_dbmanager-7.0.2 → yhttp_dbmanager-8.0.2}/yhttp_dbmanager.egg-info/SOURCES.txt +5 -1
  12. yhttp_dbmanager-7.0.2/yhttp/ext/dbmanager/cli.py +0 -86
  13. {yhttp_dbmanager-7.0.2 → yhttp_dbmanager-8.0.2}/LICENSE +0 -0
  14. {yhttp_dbmanager-7.0.2 → yhttp_dbmanager-8.0.2}/README.md +0 -0
  15. {yhttp_dbmanager-7.0.2 → yhttp_dbmanager-8.0.2}/setup.cfg +0 -0
  16. {yhttp_dbmanager-7.0.2 → yhttp_dbmanager-8.0.2}/setup.py +0 -0
  17. {yhttp_dbmanager-7.0.2 → yhttp_dbmanager-8.0.2}/tests/test_dbmanager.py +0 -0
  18. {yhttp_dbmanager-7.0.2 → yhttp_dbmanager-8.0.2}/tests/test_dburi.py +0 -0
  19. {yhttp_dbmanager-7.0.2 → yhttp_dbmanager-8.0.2}/tests/test_install.py +0 -0
  20. {yhttp_dbmanager-7.0.2 → yhttp_dbmanager-8.0.2}/yhttp/ext/dbmanager/dbmanager.py +0 -0
  21. {yhttp_dbmanager-7.0.2 → yhttp_dbmanager-8.0.2}/yhttp/ext/dbmanager/uri.py +0 -0
  22. {yhttp_dbmanager-7.0.2 → yhttp_dbmanager-8.0.2}/yhttp_dbmanager.egg-info/dependency_links.txt +0 -0
  23. {yhttp_dbmanager-7.0.2 → yhttp_dbmanager-8.0.2}/yhttp_dbmanager.egg-info/requires.txt +0 -0
  24. {yhttp_dbmanager-7.0.2 → yhttp_dbmanager-8.0.2}/yhttp_dbmanager.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: yhttp-dbmanager
3
- Version: 7.0.2
3
+ Version: 8.0.2
4
4
  Summary: Database manager command line interface and API for yhttp.
5
5
  Home-page: http://github.com/yhttp/yhttp-dbmanager
6
6
  Author: Vahid Mardani
@@ -2,30 +2,21 @@ import os
2
2
 
3
3
  from bddcli import Given, Application as CLIApplication, status, stderr, \
4
4
  when, stdout
5
- import easycli
6
5
  from yhttp.core import Application
7
6
 
8
7
  from yhttp.ext.dbmanager import install
9
8
 
10
9
 
11
- class Bar(easycli.SubCommand):
12
- __command__ = 'bar'
13
-
14
- def __call__(self, args):
15
- print('bar')
16
-
17
-
18
10
  app = Application('0.1.0', 'foo')
19
11
  app.settings.merge('''
20
12
  db:
21
13
  url: postgres://:@/foo
22
14
  ''')
23
- install(app, cliarguments=[Bar])
15
+ install(app)
24
16
 
25
17
 
26
18
  def test_applicationcli(cicd):
27
- app.ready()
28
- cliapp = CLIApplication('example', 'tests.test_cli:app.climain')
19
+ cliapp = CLIApplication('example', f'{__name__}:app.climain')
29
20
  env = os.environ.copy()
30
21
  if cicd:
31
22
  env.setdefault('YHTTP_DB_DEFAULT_HOST', 'localhost')
@@ -45,12 +36,6 @@ def test_applicationcli(cicd):
45
36
  assert status == 0
46
37
  assert stderr == ''
47
38
 
48
- # Custom Command line interface
49
- when('db bar')
50
- assert status == 0
51
- assert stderr == ''
52
- assert stdout == 'bar\n'
53
-
54
39
  when('db c')
55
40
  assert status == 0
56
41
  assert stderr == ''
@@ -0,0 +1,78 @@
1
+ import os
2
+ import tempfile
3
+
4
+ from bddcli import Given, Application as CLIApplication, status, stderr, \
5
+ when, stdout
6
+ from yhttp.core import Application
7
+
8
+ from yhttp.ext.dbmanager import install
9
+
10
+
11
+ vdir = tempfile.mkdtemp()
12
+ app = Application('0.1.0', 'foo')
13
+ app.settings.merge(f'''
14
+ db:
15
+ url: postgres://:@/foo
16
+ migration:
17
+ directory: {vdir}
18
+ ''')
19
+ if os.environ.get('CI') and os.environ.get('GITHUB_RUN_ID'):
20
+ app.settings.db.url = 'postgres://postgres:postgres@localhost/foo'
21
+
22
+ install(app)
23
+
24
+
25
+ foo_content = '''
26
+ def upgrade(db):
27
+ db.execute("""
28
+ CREATE TABLE foo (
29
+ id SERIAL PRIMARY KEY,
30
+ title VARCHAR(50) NOT NULL
31
+ );
32
+ """)
33
+
34
+
35
+ def downgrade(db):
36
+ db.execute("DROP TABLE foo")
37
+ '''
38
+ with open(f'{vdir}/0001-foo.py', 'w') as f:
39
+ f.write(foo_content)
40
+
41
+
42
+ def test_cli_migration(cicd):
43
+ cliapp = CLIApplication('foo', f'{__name__}:app.climain')
44
+ env = os.environ.copy()
45
+ if cicd:
46
+ env.setdefault('YHTTP_DB_DEFAULT_HOST', 'localhost')
47
+ env.setdefault('YHTTP_DB_DEFAULT_ADMINUSER', 'postgres')
48
+ env.setdefault('YHTTP_DB_DEFAULT_ADMINPASS', 'postgres')
49
+ env.setdefault('YHTTP_DB_DEFAULT_USER', 'postgres')
50
+ env.setdefault('YHTTP_DB_DEFAULT_PASS', 'postgres')
51
+
52
+ with Given(cliapp, 'db migration', environ=env):
53
+ when('db drop')
54
+ when('db create')
55
+ assert status == 0
56
+
57
+ when('db migration upgrade 1')
58
+ assert stderr == ''
59
+ assert status == 0
60
+ assert stdout == 'database successfully upgraded to version 0001.\n'
61
+
62
+ when('db migration downgrade 0')
63
+ assert stderr == ''
64
+ assert stdout == 'database successfully downgraded to version 0000.\n'
65
+ assert status == 0
66
+
67
+ when('db migration upgrade')
68
+ assert stderr == ''
69
+ assert status == 0
70
+ assert stdout == 'database successfully upgraded to version 0001.\n'
71
+
72
+ when('db migration new bar')
73
+ assert stderr == ''
74
+ assert status == 0
75
+ assert stdout.endswith('/0002-bar.py.\n')
76
+
77
+ when('db drop')
78
+ assert status == 0
@@ -0,0 +1,30 @@
1
+ from bddcli import Given, Application as CLIApplication, status, stderr, \
2
+ stdout
3
+ import easycli
4
+ from yhttp.core import Application
5
+
6
+ from yhttp.ext.dbmanager import install
7
+
8
+
9
+ class Bar(easycli.SubCommand):
10
+ __command__ = 'bar'
11
+
12
+ def __call__(self, args):
13
+ print('bar')
14
+
15
+
16
+ app = Application('0.1.0', 'foo')
17
+ app.settings.merge('''
18
+ db:
19
+ url: postgres://:@/foo
20
+ ''')
21
+ install(app, cliarguments=[Bar])
22
+
23
+
24
+ def test_applicationcli():
25
+ cliapp = CLIApplication('example', f'{__name__}:app.climain')
26
+
27
+ with Given(cliapp, 'db bar'):
28
+ assert status == 0
29
+ assert stderr == ''
30
+ assert stdout == 'bar\n'
@@ -0,0 +1,68 @@
1
+ import pytest
2
+
3
+
4
+ foo_content = '''
5
+ def upgrade(db):
6
+ db.execute("""
7
+ CREATE TABLE foo (
8
+ id SERIAL PRIMARY KEY,
9
+ title VARCHAR(50) NOT NULL
10
+ );
11
+ """)
12
+
13
+
14
+ def downgrade(db):
15
+ db.execute("DROP TABLE foo")
16
+ '''
17
+
18
+
19
+ bar_content = '''
20
+ def upgrade(db):
21
+ db.execute("""
22
+ CREATE TABLE bar (
23
+ id SERIAL PRIMARY KEY,
24
+ title VARCHAR(50) NOT NULL
25
+ );
26
+ """)
27
+
28
+
29
+ def downgrade(db):
30
+ db.execute("DROP TABLE bar")
31
+ '''
32
+
33
+
34
+ def test_migrator_upgrade_downgrade(migrator, mktmptree):
35
+ root = mktmptree({
36
+ '0001-foo.py': foo_content,
37
+ '0002-bar.py': bar_content,
38
+ })
39
+
40
+ with pytest.raises(ValueError):
41
+ migrator.versions_directory
42
+
43
+ migrator.settings.directory = root
44
+
45
+ assert migrator.dbversion() == 0
46
+ assert migrator.lastversion == 2
47
+
48
+ assert 2 == migrator.upgrade()
49
+ assert migrator.db.table_exists('foo')
50
+ assert migrator.db.table_exists('bar')
51
+
52
+ assert 0 == migrator.downgrade()
53
+ assert not migrator.db.table_exists('foo')
54
+ assert not migrator.db.table_exists('bar')
55
+
56
+ with pytest.raises(FileNotFoundError):
57
+ migrator.upgrade(3)
58
+
59
+ migrator.dbversion_set(3)
60
+ with pytest.raises(FileNotFoundError):
61
+ migrator.downgrade(2)
62
+
63
+
64
+ def test_migrator_newversion(migrator, tmpdir):
65
+ migrator.settings.directory = f'{tmpdir}/versions'
66
+
67
+ assert f'{tmpdir}/versions/0001-foo.py' == migrator.newversion('foo')
68
+ assert f'{tmpdir}/versions/0002-bar.py' == migrator.newversion('bar')
@@ -3,6 +3,7 @@ from .cli import DatabaseCommand
3
3
  from .install import install
4
4
  from .dbmanager import PostgresqlManager
5
5
  from .uri import DatabaseURI
6
+ from .migration import Migrator
6
7
 
7
8
 
8
- __version__ = '7.0.2'
9
+ __version__ = '8.0.2'
@@ -0,0 +1,167 @@
1
+ import os
2
+ import functools
3
+ import getpass
4
+
5
+ from easycli import SubCommand, Argument
6
+
7
+ from . import dbmanager, migration
8
+ from .uri import DatabaseURI
9
+
10
+
11
+ getdbpass = functools.partial(getpass.getpass, 'Enter db password: ')
12
+
13
+
14
+ DEFAULT_DBUSER = os.environ['USER']
15
+
16
+
17
+ class DatabaseAdministrativeCommand(SubCommand):
18
+ __arguments__ = [
19
+ Argument(
20
+ '-H',
21
+ '--host',
22
+ default=os.environ.get('YHTTP_DB_DEFAULT_HOST', ''),
23
+ help='DB hostname, default: empty.'
24
+ ),
25
+ Argument('-d', '--database', default='postgres', help='DB name'),
26
+ Argument(
27
+ '-u',
28
+ '--user',
29
+ default=os.environ.get(
30
+ 'YHTTP_DB_DEFAULT_ADMINUSER',
31
+ DEFAULT_DBUSER
32
+ ),
33
+ help=f'DB administrator username, default: ${DEFAULT_DBUSER}'
34
+ ),
35
+ Argument(
36
+ '-p', '--password',
37
+ nargs='?',
38
+ default=os.environ.get(
39
+ 'YHTTP_DB_DEFAULT_ADMINPASS',
40
+ 'postgres'
41
+ ),
42
+ help='DB administrator password'
43
+ ),
44
+ ]
45
+
46
+ def getdbmanager(self, args):
47
+ password = args.password or getdbpass()
48
+
49
+ return dbmanager.PostgresqlManager(
50
+ user=args.user,
51
+ password=password,
52
+ host=args.host,
53
+ database=args.database
54
+ )
55
+
56
+ def getappdbinfo(self, args):
57
+ dbsettings = args.application.settings.db
58
+ url = DatabaseURI.loads(dbsettings.url)
59
+ return url
60
+
61
+
62
+ class CreateDatabaseCommand(DatabaseAdministrativeCommand):
63
+ __command__ = 'create'
64
+ __aliases__ = ['c']
65
+
66
+ def __call__(self, args):
67
+ uri = self.getappdbinfo(args)
68
+ self.getdbmanager(args).create(uri.database, owner=uri.user)
69
+
70
+
71
+ class DropDatabaseCommand(DatabaseAdministrativeCommand):
72
+ __command__ = 'drop'
73
+ __aliases__ = ['d']
74
+
75
+ def __call__(self, args):
76
+ uri = self.getappdbinfo(args)
77
+ self.getdbmanager(args).drop(uri.database)
78
+
79
+
80
+ class MigrationSubCommand(SubCommand):
81
+ def migrator(self, args):
82
+ app = args.application
83
+ migrator = migration.Migrator(
84
+ app.settings.db.url,
85
+ app.settings.db.migration
86
+ )
87
+ return migrator
88
+
89
+
90
+ class UpgradeCommand(MigrationSubCommand):
91
+ __command__ = 'upgrade'
92
+ __aliases__ = ['u', 'up']
93
+ __arguments__ = [
94
+ Argument(
95
+ 'version',
96
+ nargs='?',
97
+ metavar='VERSION',
98
+ type=int,
99
+ help='Upgrade to this version, default: last version'
100
+ )
101
+ ]
102
+
103
+ def __call__(self, args):
104
+ with self.migrator(args) as m:
105
+ ver = m.upgrade(args.version)
106
+
107
+ print(f'database successfully upgraded to version {ver:04d}.')
108
+
109
+
110
+ class DowngradeCommand(MigrationSubCommand):
111
+ __command__ = 'downgrade'
112
+ __aliases__ = ['d', 'down']
113
+ __arguments__ = [
114
+ Argument(
115
+ 'version',
116
+ metavar='VERSION',
117
+ type=int,
118
+ help='Upgrade to this version.'
119
+ )
120
+ ]
121
+
122
+ def __call__(self, args):
123
+ with self.migrator(args) as m:
124
+ ver = m.downgrade(args.version)
125
+
126
+ print(f'database successfully downgraded to version {ver:04d}.')
127
+
128
+
129
+ class NewVersionCommand(MigrationSubCommand):
130
+ __command__ = 'new'
131
+ __aliases__ = ['n']
132
+ __arguments__ = [
133
+ Argument(
134
+ 'name',
135
+ metavar='TITLE',
136
+ help='Creates a new database version file'
137
+ )
138
+ ]
139
+
140
+ def __call__(self, args):
141
+ with self.migrator(args) as m:
142
+ ver = m.newversion(args.name)
143
+
144
+ print(f'File generated successfully: {ver}.')
145
+
146
+
147
+ class MigrationCommand(SubCommand):
148
+ __command__ = 'migration'
149
+ __aliases__ = ['mi']
150
+ __arguments__ = [
151
+ UpgradeCommand,
152
+ DowngradeCommand,
153
+ NewVersionCommand
154
+ ]
155
+
156
+ def __call__(self, args):
157
+ self._parser.print_help()
158
+
159
+
160
+ class DatabaseCommand(SubCommand):
161
+ __command__ = 'database'
162
+ __aliases__ = ['db']
163
+ __arguments__ = [
164
+ CreateDatabaseCommand,
165
+ DropDatabaseCommand,
166
+ MigrationCommand
167
+ ]
@@ -1,4 +1,5 @@
1
1
  from .cli import DatabaseCommand
2
+ from .migration import Migrator
2
3
 
3
4
 
4
5
  def install(app, cliarguments=None):
@@ -6,9 +7,15 @@ def install(app, cliarguments=None):
6
7
  if cliarguments:
7
8
  DatabaseCommand.__arguments__.extend(cliarguments)
8
9
 
10
+ app.settings.merge('''
11
+ db:
12
+ migration: {}
13
+ ''')
14
+ app.settings.db.migration.merge(Migrator.default_settings)
15
+
9
16
  @app.when
10
17
  def ready(app):
11
- if 'db' not in app.settings:
18
+ if 'url' not in app.settings.db:
12
19
  raise ValueError(
13
20
  'Please provide db.url configuration entry, for example: '
14
21
  'postgres://:@/dbname'
@@ -0,0 +1,192 @@
1
+ import os
2
+ import glob
3
+ import importlib
4
+ from functools import cached_property
5
+ from contextlib import contextmanager
6
+
7
+ import psycopg2
8
+
9
+
10
+ VERSIONFILE_TEMPLATE = '''\
11
+ def upgrade(db):
12
+ raise NotImplementedError()
13
+
14
+
15
+ def downgrade(db):
16
+ raise NotImplementedError()
17
+ '''
18
+
19
+
20
+ class Database:
21
+ def __init__(self, url):
22
+ self.url = url
23
+
24
+ @cached_property
25
+ def connection(self):
26
+ return psycopg2.connect(self.url)
27
+
28
+ def commit(self):
29
+ self.connection.commit()
30
+
31
+ def close(self):
32
+ self.connection.close()
33
+
34
+ def execute(self, query):
35
+ with self.connection.cursor() as c:
36
+ c.execute(query)
37
+
38
+ @contextmanager
39
+ def select(self, query):
40
+ with self.connection.cursor() as c:
41
+ c.execute(query)
42
+ yield c
43
+
44
+ def exists(self, query):
45
+ query = f'SELECT EXISTS ({query});'
46
+
47
+ with self.connection.cursor() as c:
48
+ c.execute(query)
49
+ r = c.fetchone()
50
+ return r[0]
51
+
52
+ def table_exists(self, name):
53
+ return self.exists(f'''
54
+ SELECT 1
55
+ FROM information_schema.tables
56
+ WHERE table_schema = 'public'
57
+ AND table_name = '{name}'
58
+ ''')
59
+
60
+
61
+ class Migrator:
62
+ default_settings = '''
63
+ versiontable: yhttp_version
64
+ '''
65
+
66
+ def __init__(self, url, settings):
67
+ self.url = url
68
+ self.settings = settings
69
+
70
+ def __enter__(self):
71
+ self.db
72
+ return self
73
+
74
+ def __exit__(self, exctype, excvalue, traceback):
75
+ self.close()
76
+
77
+ @cached_property
78
+ def db(self):
79
+ return Database(self.url)
80
+
81
+ def close(self):
82
+ self.db.close()
83
+
84
+ @cached_property
85
+ def vtable(self):
86
+ return self.settings.versiontable
87
+
88
+ def ensure_versiontable(self):
89
+ if self.db.table_exists(self.vtable):
90
+ return
91
+
92
+ self.db.execute(f'''
93
+ CREATE TABLE {self.vtable} (
94
+ version INTEGER NOT NULL
95
+ );
96
+ ''')
97
+
98
+ self.db.execute(f'''
99
+ INSERT INTO {self.vtable} (version) VALUES (0);
100
+ ''')
101
+ self.db.commit()
102
+
103
+ def dbversion(self):
104
+ self.ensure_versiontable()
105
+ with self.db.select(f'SELECT version from {self.vtable}') as c:
106
+ return c.fetchone()[0]
107
+
108
+ def dbversion_set(self, ver):
109
+ self.db.execute(f'UPDATE {self.vtable} SET version={ver}')
110
+ self.db.commit()
111
+
112
+ @cached_property
113
+ def versions_directory(self):
114
+ try:
115
+ vdir = self.settings.directory
116
+ except AttributeError:
117
+ raise ValueError(
118
+ 'Please provide db.migration.directory configuration entry.'
119
+ )
120
+
121
+ if not os.path.exists(vdir):
122
+ os.mkdir(vdir)
123
+
124
+ return vdir
125
+
126
+ @property
127
+ def lastversion(self):
128
+ files = glob.glob(f'{self.versions_directory}/*-*.py')
129
+ if not files:
130
+ return 0
131
+
132
+ lastfile = sorted(files)[-1]
133
+ ver = os.path.basename(lastfile).split('-', 1)[0]
134
+ return int(ver)
135
+
136
+ def newversion(self, name):
137
+ ver = self.lastversion + 1
138
+ filename = f'{ver:04d}-{name}.py'
139
+ filepath = os.path.join(self.versions_directory, filename)
140
+ with open(filepath, 'w') as f:
141
+ f.write(VERSIONFILE_TEMPLATE)
142
+
143
+ return filepath
144
+
145
+ def loadmodule(self, ver):
146
+ files = glob.glob(f'{self.versions_directory}/{ver:04d}-*.py')
147
+ if not files:
148
+ return None
149
+
150
+ modfile = files[0]
151
+ modname = os.path.splitext(os.path.basename(modfile))[0]
152
+ spec = importlib.util.spec_from_file_location(modname, modfile)
153
+ mod = importlib.util.module_from_spec(spec)
154
+ # sys.modules[module_name] = module
155
+ spec.loader.exec_module(mod)
156
+ return mod
157
+
158
+ def filenotfound(self, ver):
159
+ return FileNotFoundError(
160
+ f'script {ver:04d}_*.py not found within directory: '
161
+ f'{self.versions_directory}.'
162
+ )
163
+
164
+ def upgrade(self, targetver=None):
165
+ dbver = self.dbversion()
166
+ if targetver is None:
167
+ targetver = self.lastversion
168
+
169
+ while dbver < targetver:
170
+ cver = dbver + 1
171
+ mod = self.loadmodule(cver)
172
+ if mod is None:
173
+ raise self.filenotfound(cver)
174
+
175
+ mod.upgrade(self.db)
176
+ self.dbversion_set(cver)
177
+ dbver = cver
178
+
179
+ return targetver
180
+
181
+ def downgrade(self, targetver=0):
182
+ dbver = self.dbversion()
183
+ while dbver > targetver:
184
+ mod = self.loadmodule(dbver)
185
+ if mod is None:
186
+ raise self.filenotfound(dbver)
187
+
188
+ mod.downgrade(self.db)
189
+ dbver -= 1
190
+ self.dbversion_set(dbver)
191
+
192
+ return targetver
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: yhttp-dbmanager
3
- Version: 7.0.2
3
+ Version: 8.0.2
4
4
  Summary: Database manager command line interface and API for yhttp.
5
5
  Home-page: http://github.com/yhttp/yhttp-dbmanager
6
6
  Author: Vahid Mardani
@@ -1,14 +1,18 @@
1
1
  LICENSE
2
2
  README.md
3
3
  setup.py
4
- tests/test_cli.py
4
+ tests/test_cli_createdrop.py
5
+ tests/test_cli_migration.py
6
+ tests/test_cli_usercommand.py
5
7
  tests/test_dbmanager.py
6
8
  tests/test_dburi.py
7
9
  tests/test_install.py
10
+ tests/test_migrator.py
8
11
  yhttp/ext/dbmanager/__init__.py
9
12
  yhttp/ext/dbmanager/cli.py
10
13
  yhttp/ext/dbmanager/dbmanager.py
11
14
  yhttp/ext/dbmanager/install.py
15
+ yhttp/ext/dbmanager/migration.py
12
16
  yhttp/ext/dbmanager/uri.py
13
17
  yhttp_dbmanager.egg-info/PKG-INFO
14
18
  yhttp_dbmanager.egg-info/SOURCES.txt
@@ -1,86 +0,0 @@
1
- import os
2
- import functools
3
- import getpass
4
-
5
- from easycli import SubCommand, Argument
6
-
7
- from . import dbmanager
8
- from .uri import DatabaseURI
9
-
10
-
11
- getdbpass = functools.partial(getpass.getpass, 'Enter db password: ')
12
-
13
-
14
- DEFAULT_DBUSER = os.environ['USER']
15
-
16
-
17
- class DatabaseAdministrativeCommand(SubCommand):
18
- __arguments__ = [
19
- Argument(
20
- '-H',
21
- '--host',
22
- default=os.environ.get('YHTTP_DB_DEFAULT_HOST', ''),
23
- help='DB hostname, default: empty.'
24
- ),
25
- Argument('-d', '--database', default='postgres', help='DB name'),
26
- Argument(
27
- '-u',
28
- '--user',
29
- default=os.environ.get(
30
- 'YHTTP_DB_DEFAULT_ADMINUSER',
31
- DEFAULT_DBUSER
32
- ),
33
- help=f'DB administrator username, default: ${DEFAULT_DBUSER}'
34
- ),
35
- Argument(
36
- '-p', '--password',
37
- nargs='?',
38
- default=os.environ.get(
39
- 'YHTTP_DB_DEFAULT_ADMINPASS',
40
- 'postgres'
41
- ),
42
- help='DB administrator password'
43
- ),
44
- ]
45
-
46
- def getdbmanager(self, args):
47
- password = args.password or getdbpass()
48
-
49
- return dbmanager.PostgresqlManager(
50
- user=args.user,
51
- password=password,
52
- host=args.host,
53
- database=args.database
54
- )
55
-
56
- def getappdbinfo(self, args):
57
- dbsettings = args.application.settings.db
58
- url = DatabaseURI.loads(dbsettings.url)
59
- return url
60
-
61
-
62
- class CreateDatabase(DatabaseAdministrativeCommand):
63
- __command__ = 'create'
64
- __aliases__ = ['c']
65
-
66
- def __call__(self, args):
67
- uri = self.getappdbinfo(args)
68
- self.getdbmanager(args).create(uri.database, owner=uri.user)
69
-
70
-
71
- class DropDatabase(DatabaseAdministrativeCommand):
72
- __command__ = 'drop'
73
- __aliases__ = ['d']
74
-
75
- def __call__(self, args):
76
- uri = self.getappdbinfo(args)
77
- self.getdbmanager(args).drop(uri.database)
78
-
79
-
80
- class DatabaseCommand(SubCommand):
81
- __command__ = 'database'
82
- __aliases__ = ['db']
83
- __arguments__ = [
84
- CreateDatabase,
85
- DropDatabase
86
- ]
File without changes