yhttp-dbmanager 2.6.2__py3-none-any.whl

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.
@@ -0,0 +1,8 @@
1
+ # flake8: noqa
2
+ from .cli import DatabaseCLI
3
+ from .install import install
4
+ from .dbmanager import PostgresqlManager
5
+ from .uri import DatabaseURI
6
+
7
+
8
+ __version__ = '2.6.2'
@@ -0,0 +1,86 @@
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
+ dbname=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.dbname, 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.dbname)
78
+
79
+
80
+ class DatabaseCLI(SubCommand):
81
+ __command__ = 'database'
82
+ __aliases__ = ['db']
83
+ __arguments__ = [
84
+ CreateDatabase,
85
+ DropDatabase
86
+ ]
@@ -0,0 +1,75 @@
1
+ import abc
2
+
3
+ import psycopg2
4
+ from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT
5
+
6
+
7
+ class DatabaseManager(metaclass=abc.ABCMeta):
8
+
9
+ @abc.abstractmethod
10
+ def execute(self, query): # pragma: no cover
11
+ pass
12
+
13
+ @abc.abstractmethod
14
+ def create(self, name, owner=None, dropifexists=False): # pragma: no cover
15
+ pass
16
+
17
+ @abc.abstractmethod
18
+ def drop(self, name): # pragma: no cover
19
+ pass
20
+
21
+ @abc.abstractmethod
22
+ def exists(self, name): # pragma: no cover
23
+ pass
24
+
25
+ @abc.abstractmethod
26
+ def dropifexists(self, name): # pragma: no cover
27
+ pass
28
+
29
+
30
+ class PostgresqlManager(DatabaseManager):
31
+
32
+ def __init__(self, host=None, dbname='postgres', user=None, password=None):
33
+ self.connection = psycopg2.connect(
34
+ host=host,
35
+ dbname=dbname,
36
+ user=user,
37
+ password=password
38
+ )
39
+ self.connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
40
+
41
+ def execute(self, query):
42
+ cursor = self.connection.cursor()
43
+ try:
44
+ cursor.execute(query)
45
+ finally:
46
+ cursor.close()
47
+
48
+ def exists(self, name):
49
+ query = f'SELECT 1 FROM pg_database WHERE datname=\'{name}\''
50
+
51
+ cursor = self.connection.cursor()
52
+ try:
53
+ cursor.execute(query)
54
+ r = cursor.fetchone()
55
+ if r:
56
+ return r[0] == 1
57
+ else:
58
+ return False
59
+ finally:
60
+ cursor.close()
61
+
62
+ def create(self, name, owner=None, dropifexists=False):
63
+ if dropifexists:
64
+ self.dropifexists(name)
65
+
66
+ query = f'CREATE DATABASE "{name}"' + \
67
+ (f' WITH OWNER {owner}' if owner else '')
68
+
69
+ self.execute(query)
70
+
71
+ def drop(self, name):
72
+ self.execute(f'DROP DATABASE "{name}"')
73
+
74
+ def dropifexists(self, name):
75
+ self.execute(f'DROP DATABASE IF EXISTS "{name}"')
@@ -0,0 +1,17 @@
1
+ from .cli import DatabaseCLI
2
+
3
+
4
+ def install(app, cliarguments=None):
5
+ app.cliarguments.append(DatabaseCLI)
6
+ if cliarguments:
7
+ DatabaseCLI.__arguments__.extend(cliarguments)
8
+
9
+ @app.when
10
+ def ready(app):
11
+ if 'db' not in app.settings:
12
+ raise ValueError(
13
+ 'Please provide db.url configuration entry, for example: '
14
+ 'postgres://:@/dbname'
15
+ )
16
+
17
+ return app
@@ -0,0 +1,41 @@
1
+ import re
2
+
3
+
4
+ URIPATTERN = re.compile(
5
+ r'(?P<provider>.*)://(?P<user>.*):(?P<password>.*)@(?P<host>.*)/'
6
+ r'(?P<dbname>.*)'
7
+ )
8
+
9
+
10
+ class DatabaseURI:
11
+ def __init__(self, provider, dbname, host='', user='', password=''):
12
+ assert provider
13
+ assert dbname
14
+
15
+ self.provider = provider
16
+ self.host = host
17
+ self.dbname = dbname
18
+ self.user = user
19
+ self.password = password
20
+
21
+ def dumps(self):
22
+ return f'{self.provider}://{self.user}:{self.password}@{self.host}' \
23
+ f'/{self.dbname}'
24
+
25
+ @classmethod
26
+ def loads(cls, uri):
27
+ match = URIPATTERN.match(uri)
28
+ if not match:
29
+ raise ValueError(f'Invalid URI: {uri}')
30
+
31
+ u = match.groupdict()
32
+
33
+ assert u.get('provider')
34
+ assert u.get('dbname')
35
+ return cls(
36
+ u.get('provider'),
37
+ u.get('dbname'),
38
+ u.get('host'),
39
+ u.get('user'),
40
+ u.get('password'),
41
+ )
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 yhttp
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,69 @@
1
+ Metadata-Version: 2.1
2
+ Name: yhttp-dbmanager
3
+ Version: 2.6.2
4
+ Summary: Database manager command line interface and API for yhttp.
5
+ Home-page: http://github.com/yhttp/yhttp-dbmanager
6
+ Author: Vahid Mardani
7
+ Author-email: vahid.mardani@gmail.com
8
+ License: MIT
9
+ Classifier: Environment :: Console
10
+ Classifier: Environment :: Web Environment
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Natural Language :: English
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: License :: Other/Proprietary License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3.6
17
+ Classifier: Topic :: Software Development
18
+ Classifier: Topic :: Internet :: WWW/HTTP
19
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
20
+ Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
21
+ Classifier: Topic :: Software Development :: Libraries
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: yhttp <5,>=3.5.2
26
+ Requires-Dist: dbmanager
27
+ Requires-Dist: psycopg2
28
+
29
+ # Dependencies
30
+ install `postgreslq` brefore use of this project.
31
+
32
+
33
+ ## Contribution
34
+
35
+ ### Prepare
36
+
37
+ Create and grant `postgres` role with `createdb` permission:
38
+ ```bash
39
+ echo "CREATE USER ${USER} WITH CREATEDB" | sudo -u postgres psql
40
+ # Or
41
+ echo "ALTER USER ${USER} CREATEDB" | sudo -u postgres psql
42
+ ```
43
+
44
+ Create virtual environment:
45
+ ```bash
46
+ make venv
47
+ ```
48
+
49
+ Install this project as editable mode and all other development dependencies:
50
+ ```bash
51
+ make env
52
+ ```
53
+
54
+ ### Tests
55
+ Execute all tests:
56
+ ```bash
57
+ make test
58
+ ```
59
+
60
+ Execute all tests and report coverage result:
61
+ ```bash
62
+ make cover
63
+ make cover-html
64
+ ```
65
+
66
+ ### Virtualenv
67
+ ```bash
68
+ source ./activate.sh
69
+ ```
@@ -0,0 +1,10 @@
1
+ yhttp/ext/dbmanager/__init__.py,sha256=cOlAL6XZpC4MEmc63_fWk4iLdLH-IY8O9fanJvZUhIE,167
2
+ yhttp/ext/dbmanager/cli.py,sha256=MfmToDtHBuQH0HpQnIcGVplw1B8K628mh83VW7MLH54,2139
3
+ yhttp/ext/dbmanager/dbmanager.py,sha256=ZXy5LhmFMqK1CkSMMlPVQp3-ecbt6MPHbQmiAJ4RAu8,1908
4
+ yhttp/ext/dbmanager/install.py,sha256=fSNUqFknpP3ZficNjzlRlejEpxtf70OrOFh-yL-TMXY,431
5
+ yhttp/ext/dbmanager/uri.py,sha256=CQdw_1yJwUwV67L3hQICA4ziKCDYb4E2Gqd4Y2Cc8-w,973
6
+ yhttp_dbmanager-2.6.2.dist-info/LICENSE,sha256=1lZ7neh4Es6earhYMwYaqsuS1Alohsrf9GZRVdl7l5o,1062
7
+ yhttp_dbmanager-2.6.2.dist-info/METADATA,sha256=cyCVZKIDoC0j4DBZSbOnY4o3Ve76M4Ut27CEdqRh8mo,1734
8
+ yhttp_dbmanager-2.6.2.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
9
+ yhttp_dbmanager-2.6.2.dist-info/top_level.txt,sha256=efaJ4DfUOs7MO3pjIEyRhnQASGVyD6vH-SL3ogQxkeU,6
10
+ yhttp_dbmanager-2.6.2.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (72.1.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ yhttp