{ "info": { "author": "Thomas Huang", "author_email": "lyanghwy@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "License :: OSI Approved :: GNU Affero General Public License v3", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Database" ], "description": "dbpy\r\n#####\r\n\r\n\r\n\r\ndbpy is database abstration layer wrote by python. The design is inspired by `webpy db `_ and `drupal database `_ . If like the simple db abstration layer like ``tornado db`` or ``webpy db``, it is worth to try.\r\n\r\n\r\n`\u4e2d\u6587|chinese `_\r\n\r\nchanges\r\n==========\r\n\r\n#. Add pymysql adapter\r\n\r\n\r\n\r\nInstall the extension with the following command::\r\n\r\n $ easy_install pymysql\r\n\r\nor alternatively if you have pip installed::\r\n\r\n\r\n $ pip install pymysql\r\n\r\nFeatues\r\n================\r\n\r\n#. silmple and flexible\r\n#. graceful and useful sql query builder.\r\n#. thread-safe connection pool\r\n#. supports read/write master-slave mode\r\n#. supports transaction\r\n\r\nThe Projects use dbpy\r\n======================\r\n\r\n\r\n`Lilac (Distributed Scheduler Task System) `_\r\n\r\n.. contents::\r\n :depth: 4\r\n\r\n\r\n\r\n\r\nInstall\r\n==============\r\n\r\nInstall the extension with the following command::\r\n\r\n $ easy_install dbpy\r\n\r\nor alternatively if you have pip installed::\r\n\r\n\r\n $ pip install dbpy\r\n\r\n\r\nor clone it form github then run the command in shell:\r\n\r\n.. code-block:: bash\r\n\r\n cd db # the path to the project\r\n python setup.py install\r\n\r\nDevelopment\r\n===========\r\n\r\nFork or download it, then run:\r\n\r\n.. code-block:: bash \r\n\r\n cd db # the path to the project\r\n python setup.py develop\r\n\r\n\r\n\r\nCompatibility\r\n=============\r\n\r\nBuilt and tested under Python 2.7+\r\n\r\n\r\nDB API\r\n========\r\n\r\n\r\nHave a look:\r\n\r\n.. code-block:: python\r\n\r\n config = {\r\n 'passwd': 'test',\r\n 'user': 'test',\r\n 'host': 'localhost',\r\n 'db': 'test',\r\n 'max_idle' : 5*60\r\n }\r\n\r\n db.setup(config, minconn=5, maxconn=10, \r\n adapter='mysql', key='default', slave=False)\r\n\r\n db.execute('show tables')\r\n\r\n\r\n\r\nsetup\r\n---------\r\n\r\n:config: the connection basic config, the all of arguements of MySQLDB#connect is acceptable\u3002 the ``max_idle`` is the connect timeout setting that is used to reconnection when connection is timeout, default is 10 seconds.\r\n:minconn: the minimum connections for the connection pool, default is 5.\r\n:maxconn: the maximum connections for the connection pool, default is 10.\r\n:adapter: the database driver adapter name, currently supports mysql (MySQLdb, pymysql) only.\r\n:key: the database idenfify for database, default database is \"default\"\r\n:slave: if set to true, the database will be register as a slave database. make sure you setup a master firstly.\r\n\r\n\r\n.. code-block:: python\r\n\r\n config = {\r\n 'passwd': 'test',\r\n 'user': 'test',\r\n 'host': 'localhost',\r\n 'db': 'test',\r\n 'max_idle' : 5*60\r\n }\r\n\r\n db.setup(config, key='test')\r\n config['host'] = 'test.slave'\r\n # set a slave, and now the master can only to write\r\n db.setup(config, key='test', slave=True) \r\n\r\n config['host'] = 'test.slave2'\r\n # add more slave for 'test'\r\n db.setup(config, key='test', slave=True)\r\n\r\n\r\n config['host'] = 'host2'\r\n config['db'] = 'social'\r\n # set another database\r\n db.setup(config, key='social', slave=True)\r\n\r\nquery\r\n-------\r\n\r\n\r\n\r\nquery api is used for reading database operation, like select..., show tables, if you wanna update your database please use execute api.\r\n\r\nquery(sql, args=None, many=None, as_dict=False, key='default'):\r\n\r\n:sql: the raw sql\r\n:args: the args for sql arguement to prepare execute.\r\n:many: when set to a greater zero integer, it will use fetchmany then yield return a generator, otherwise a list.\r\n:as_dict: when set to true, query api will return the database result as dict row, otherwise tuple row.\r\n:key: the idenfify of database.\r\n\r\n.. code-block:: python\r\n\r\n print db.query('SELECT 1')\r\n # > ((1L,),)\r\n\r\n # use social db\r\n print db.query('SELECT 1', key='social')\r\n # > ((1L,),)\r\n\r\n print db.query('SELECT * FROM users WHERE uid=%s and name=%s', (1, 'user_1'))\r\n # > ((1L, u'user_1'),)\r\n\r\n # Wanna return dict row\r\n print db.query('SELECT * FROM users WHERE uid=%s and name=%s', \r\n (1, 'user_1'), as_dict=True)\r\n # > ({'uid': 1L, 'name': u'user_1'},)\r\n\r\n # Use fetchmany(many) then yeild, Return generator\r\n res = db.query('SELECT * FROM users WHERE uid=%s and name=%s', \r\n (1, 'user_1'), many=5, as_dict=True)\r\n print res\r\n print res.next()\r\n # > \r\n # > {'uid': 1L, 'name': u'user_1'}\r\n\r\n\r\nexecute\r\n--------\r\n\r\nthe api is used for writing database operation, like insert, update, delete.. if you wanna read query your database please use query api.\r\n\r\nexecute(sql, args=None, key='default'):\r\n\r\n\r\n:sql: the raw sql\r\n:args: the args for sql arguement to prepare execute.\r\n:key: the idenfify of database.\r\n\r\n\r\nReturn::\r\n\r\n it returns last_insert_id when sql is insert statement, otherwise rowcount\r\n\r\n.. code-block:: python\r\n \r\n db.execute('DROP TABLE IF EXISTS `users`')\r\n db.execute(\"\"\"CREATE TABLE `users` (\r\n `uid` int(10) unsigned NOT NULL AUTO_INCREMENT,\r\n `name` varchar(20) NOT NULL,\r\n PRIMARY KEY (`uid`))\"\"\")\r\n \r\n # when inset mutil-values\uff0cthe api will call executemany\r\n db.execute('INSERT INTO users VALUES(%s, %s)', [(10, 'execute_test'), (9, 'execute_test')])\r\n # > 9\r\n db.execute('DELETE FROM users WHERE name=%s', ('execute_test',))\r\n # > 2\r\n\r\n\r\n # use social db\r\n db.execute('delete from events where created_at<%s', (expired, ), key='social')\r\n # > 10\r\n\r\nselect\r\n-----------\r\n\r\nthe api is used for select sql database query.\r\n\r\nselect(table, key='default'):\r\n\r\n:table: the table name\r\n:key: the idenfify of database \r\n\r\nselect all\r\n~~~~~~~~~~~~~~~~\r\n\r\n.. code-block:: python\r\n\r\n db.select('users')\r\n # > SELECT * FROM `users`\r\n\r\nspecific columns\r\n~~~~~~~~~~~~~~~~~\r\n\r\n.. code-block:: python\r\n\r\n db.select('users').fields('uid', 'name')\r\n # > SELECT `uid`, `name` FROM `users`\r\n\r\n\r\nexecute\r\n~~~~~~~~~~~~~~~~\r\n\r\nwhen you already build your sql, try execute api to fetch your database result.\r\n\r\nexecute(many=None, as_dict=False):\r\n\r\n:many: when set to a greater zero integer, it will use fetchmany then yield return a generator, otherwise a list.\r\n:as_dict: when set to true, query api will return the database result as dict row, otherwise tuple row.\r\n\r\n.. code-block:: python\r\n\r\n q = db.select('users').fields('uid', 'name')\r\n res = q.execute()\r\n print res\r\n # > ((1L, u'user_1'), (2L, u'user_2'), (3L, u'user_3'), (4L, u'user_4'), (5L, None))\r\n\r\n res = q.execute(many=2, as_dict=True)\r\n print res\r\n print res.next()\r\n # > \r\n # > {'uid': 1L, 'name': u'user_1'}\r\n\r\n\r\nCondition\r\n~~~~~~~~~~~\r\n\r\nIt is time to try more complex select query.\r\n\r\ncondition(field, value=None, operator=None):\r\n\r\n:field: the field of table \r\n:value: the value of field, defaul is None (\"field is null\")\r\n:operator: the where operator like BETWEEN, IN, NOT IN, EXISTS, NOT EXISTS, IS NULL, IS NOT NULL, LIKE, NOT LIKE, =, <, >, >=, <=, <> and so on.\r\n\r\n\r\nsimple \r\n^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n db.select('users').condition('uid', 1) # condition('uid', 1, '=')\r\n # > SELECT * FROM `users`\r\n # > WHERE `uid` = %s \r\n\r\n\r\nin \r\n^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n\r\n db.select('users').condition('uid', (1, 3)) # condition('uid', [1, 3]) \u4e00\u6837\r\n # > SELECT * FROM `users`\r\n # > WHERE `uid` IN (%s, %s) \r\n\r\nbetween \r\n^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n db.select('users').condition('uid', (1, 3), 'between')\r\n # > SELECT * FROM `users`\r\n # > WHERE `uid` BETWEEN %s AND %s \r\n\r\n\r\nmulti condition\r\n^^^^^^^^^^^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n db.select('users').condition('uid', 1).condition('name', 'blabla')\r\n # > SELECT * FROM `users`\r\n # > WHERE `uid` = %s AND `name` = %s \r\n\r\nor condition\r\n^^^^^^^^^^^^^^\r\n\r\n.. code-block:: python\r\n\r\n or_cond = db.or_().condition('uid', 1).condition('name', 'blabla')\r\n db.select('users').condition(or_cond).condition('uid', 1, '<>')\r\n # > SELECT * FROM `users`\r\n # > WHERE ( `uid` = %s OR `name` = %s ) AND `uid` <> %s \r\n\r\n\r\n\r\norder by\r\n~~~~~~~~~\r\n\r\n.. code-block:: python\r\n\r\n db.select('users').order_by('name')\r\n # > SELECT * FROM `users`\r\n # > ORDER BY `name`\r\n\r\n db.select('users').order_by('name', 'DESC')\r\n # > SELECT * FROM `users`\r\n # > ORDER BY `name` DESC\r\n\r\n db.select('users').order_by('name', 'DESC').order_by('uid')\r\n # > SELECT * FROM `users`\r\n # > ORDER BY `name` DESC, `uid`\r\n\r\n\r\n\r\ndistinct\r\n~~~~~~~~~\r\n\r\n.. code-block:: python\r\n\r\n db.select('users').distinct().condition('uid', 1)\r\n # > SELECT DISTINCT * FROM `users`\r\n # > WHERE `uid` = %s \r\n\r\n db.select('users').fields('uid', 'name').distinct().condition('uid', 1)\r\n # > SELECT DISTINCT `uid`, `name` FROM `users`\r\n # > WHERE `uid` = %s \r\n\r\n\r\ngroup by\r\n~~~~~~~~~\r\n\r\n.. code-block:: python\r\n\r\n db.select('users').group_by('name', 'uid')\r\n # > SELECT * FROM `users`\r\n # > GROUP BY `name`, `uid`\r\n\r\n\r\nlimit and offset\r\n~~~~~~~~~~~~~~~~~\r\n\r\n.. code-block:: python\r\n\r\n db.select('users').limit(2).offset(5)\r\n # > SELECT * FROM `users`\r\n # > LIMIT 2 OFFSET 5\r\n\r\nnull condition\r\n~~~~~~~~~~~~~~~\r\n\r\n.. code-block:: python\r\n\r\n db.select('users').is_null('name').condition('uid', 5)\r\n # > SELECT * FROM `users`\r\n # > WHERE `name` IS NULL AND `uid` = %s \r\n\r\n db.select('users').is_not_null('name').condition('uid', 5)\r\n # > SELECT * FROM `users`\r\n # > WHERE `name` IS NOT NULL AND `uid` = %s \r\n\r\n db.select('users').condition('name', None)\r\n # > SELECT * FROM `users`\r\n # > WHERE `name` IS NULL \r\n\r\n\r\ncomplex conditions\r\n-------------------\r\n\r\nusing db.and_(), db.or_(), we can build complex where conditions:\r\n\r\n.. code-block:: python\r\n\r\n or_cond = db.or_().condition('field1', 1).condition('field2', 'blabla')\r\n and_cond = db.and_().condition('field3', 'what').condition('field4', 'then?')\r\n print db.select('table_name').condition(or_cond).condition(and_cond)\r\n\r\n # > SELECT * FROM `table_name`\r\n # > WHERE ( `field1` = %s OR `field2` = %s ) AND ( `field3` = %s AND `field4` = %s ) \r\n\r\nexpr\r\n------------\r\n\r\nif you wanna use the aggregate functions like sum, count, please use ``erpr`` :\r\n\r\n.. code-block:: python\r\n\r\n from db import expr\r\n\r\n db.select('users').fields(expr('count(*)'))\r\n # > SELECT count(*) FROM `users`\r\n\r\n db.select('users').fields(expr('count(uid)', 'total'))\r\n # > SELECT count(uid) AS `total` FROM `users`\r\n\r\n\r\n\r\ninsert\r\n-----------\r\n\r\nThe ``insert`` api is used for building insert into sql statement.\r\n\r\ninsert(table, key='default'):\r\n\r\n:table: the table name\r\n:key: the idenfify of database \r\n\r\n.. code-block:: python\r\n\r\n q = db.insert('users').values((10, 'test_insert'))\r\n # > INSERT INTO `users` VALUES(%s, %s)\r\n print q._values\r\n # > [(10, 'test_insert')]\r\n\r\n\r\n q = db.insert('users').fields('name').values({'name': 'insert_1'}).values(('insert_2',))\r\n # > INSERT INTO `users` (`name`) VALUES(%s)\r\n print q._values\r\n # > [('insert_1',), ('insert_2',)]\r\n\r\n\r\nWhen you use ``execute`` api to get result, it will reutrn the ``last insert id``\uff1a\r\n\r\n.. code-block:: python\r\n \r\n \r\n print q.execute()\r\n # > 2\r\n\r\n\r\n\r\nupdate\r\n-----------\r\n\r\nThe ``update`` api is used for building update sql statement.\r\n\r\nupdate(table, key='default'):\r\n\r\n:table: the table name\r\n:key: the idenfify of database \r\n\r\n\r\nmset and set\uff1a\r\n\r\n:mset: the value must be dict tpye, that sets mutil-fileds at once time.\r\n:set(column, value): set one field one time.\r\n\r\nthe where conditions please see `select`_ for more information.\r\n\r\n\r\n.. code-block:: python\r\n \r\n \r\n db.update('users').mset({'name':None, 'uid' : 12}).condition('name','user_1')\r\n # > UPDATE `users` SET `name` = %s, `uid` = %s WHERE `name` = %s \r\n\r\n q = (db.update('users').set('name', 'update_test').set('uid', 12)\r\n .condition('name', 'user_2').condition('uid', 2)) # .execute()\r\n print q.to_sql()\r\n # > UPDATE `users` SET `name` = %s, `uid` = %s WHERE `name` = %s AND `uid` = %s \r\n \r\n\r\n\r\nWhen you use ``execute`` api to get result, it will reutrn the ``rowcount``\uff1a\r\n\r\n\r\n.. code-block:: python\r\n \r\n \r\n print q.execute()\r\n # > 2\r\n\r\nlimit\r\n~~~~~~~~~\r\n\r\n\r\n\r\nYou can use limit api to lim the quantity of update.\r\n\r\n\r\n.. code-block:: python\r\n \r\n db.update('users').mset({'name':None, 'uid' : 12}).condition('name','user_1').limit(5)\r\n # > UPDATE `users` SET `name` = %s, `uid` = %s WHERE `name` = %s LIMIT 5\r\n\r\ndelete\r\n-----------\r\n\r\n\r\nThe ``delete`` api is used for building DELETE FROM sql statement.\r\n\r\ndelete(table, key='default'):\r\n\r\n:table: the table name\r\n:key: the idenfify of database \r\n\r\nthe where conditions please see `select`_ for more information.\r\n\r\n.. code-block:: python\r\n \r\n db.delete('users').condition('name','user_1')\r\n # > DELETE FROM `users` WHERE `name` = %s \r\n\t\r\nWhen you use ``execute`` api to get result, it will reutrn the ``rowcount``\uff1a\r\n\r\n.. code-block:: python\r\n \r\n \r\n print q.execute()\r\n # > 2\r\n\r\n\r\nto_sql and str\r\n---------------------\r\n\r\nyou can use to_sql or __str__ method to the objects of ``select``, ``insert``, ``update``, ``delete`` to print the sql you build.\r\n\r\n\r\n.. code-block:: python\r\n \r\n\r\n q = (db.update('users').set('name', 'update_test').set('uid', 12)\r\n .condition('name', 'user_2').condition('uid', 2))\r\n print q.to_sql()\r\n print q\r\n # > UPDATE `users` SET `name` = %s, `uid` = %s WHERE `name` = %s AND `uid` = %s \r\n\r\n\r\ntransaction\r\n------------\r\n\r\ntransaction(table, key='default'):\r\n\r\n:table: the table name\r\n:key: the idenfify of database \r\n\r\n\r\nThe simple transaction done all or do nothing, you cann't set savepoint. \r\n\r\n\r\n\r\n.. code-block:: python\r\n \r\n\r\n # with context\r\n with db.transaction() as t:\r\n t.delete('users').condition('uid', 1).execute()\r\n (t.update('users').mset({'name':None, 'uid' : 12})\r\n .condition('name','user_1').execute())\r\n\r\n\r\n # the normal way\r\n t = db.transaction()\r\n t.begin()\r\n t.delete('users').condition('uid', 1).execute()\r\n (t.update('users').mset({'name':None, 'uid' : 12})\r\n .condition('name','user_1').execute())\r\n\r\n #if failed will rollback\r\n t.commit()\r\n\r\n.. note:: when uses begin must be combine with commit\uff0cotherwise the connection will not return connection pool.suggets to use ``with context``\r\n\r\n\r\nsimple orm\r\n-----------\r\n\r\nthe orm demo `samples `_\r\n\r\n.. code-block:: python\r\n \r\n import model\r\n from orm import Backend\r\n import db\r\n\r\n db.setup({ 'host': 'localhost', 'user': 'test', 'passwd': 'test', 'db': 'blog'})\r\n\r\n\r\n user = Backend('user').find_by_username('username')\r\n if user and user.check('password'):\r\n print 'auth'\r\n\r\n user = model.User('username', 'email', 'real_name', 'password', \r\n 'bio', 'status', 'role')\r\n if Backend('user').create(user):\r\n print 'fine'\r\n\r\n user = Backend('user').find(12)\r\n user.real_name = 'blablabla....'\r\n if Backend('user').save(user):\r\n print 'user saved'\r\n\r\n if Backend('user').delete(user):\r\n print 'delete user failed'\r\n\r\n\r\n post = model.Post('title', 'slug', 'description', 'html', 'css', 'js', \r\n 'category', 'status', 'comments', 'author')\r\n if not Backend('post').create(post):\r\n print 'created failed'\r\n\r\nFuture\r\n--------\r\n\r\n\r\nPersonal idea:\r\n\r\n#. add ``join`` for select api \r\n#. add a schema class for creating or changing table.\r\n#. add some api for mysql individual sql like ``replace`` or ``duplicate update``\r\n#. improve connection pool.\r\n\r\n\r\nLICENSE\r\n=======\r\n\r\n Copyright (C) 2014-2015 Thomas Huang\r\n\r\n This program is free software: you can redistribute it and/or modify\r\n it under the terms of the GNU General Public License as published by\r\n the Free Software Foundation, version 2 of the License.\r\n\r\n This program is distributed in the hope that it will be useful,\r\n but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n GNU General Public License for more details.\r\n\r\n You should have received a copy of the GNU General Public License\r\n along with this program. If not, see .\r\n\r\n", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/whiteclover/dbpy", "keywords": "database abstraction layer for pythoneer(orm", "license": "GPL", "maintainer": "", "maintainer_email": "", "name": "dbpy", "package_url": "https://pypi.org/project/dbpy/", "platform": "", "project_url": "https://pypi.org/project/dbpy/", "project_urls": { "Homepage": "https://github.com/whiteclover/dbpy" }, "release_url": "https://pypi.org/project/dbpy/0.1.3/", "requires_dist": null, "requires_python": "", "summary": "database abstraction layer for pythoneer", "version": "0.1.3" }, "last_serial": 3203211, "releases": { "0.1.0": [], "0.1.1": [ { "comment_text": "", "digests": { "md5": "c452b4983e7c26b0ce776e23f5429028", "sha256": "adcce223e1b4056e91b3902ddcfb4b31fdd4f2f3c4232c471e4d691f943a7219" }, "downloads": -1, "filename": "dbpy-0.1.1.tar.gz", "has_sig": false, "md5_digest": "c452b4983e7c26b0ce776e23f5429028", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15116, "upload_time": "2015-03-09T03:27:13", "url": "https://files.pythonhosted.org/packages/8e/34/95a79dba8c788782ddee184b72f934b151b686b4b2b13ab0a2160196336a/dbpy-0.1.1.tar.gz" }, { "comment_text": "", "digests": { "md5": "b6939d9cdeb431b0285204bb9559bcbe", "sha256": "c03e64f3084941b703d9b70297999c1040a0f3bb25ef61a065aae064c48f0f4c" }, "downloads": -1, "filename": "dbpy-0.1.1.zip", "has_sig": false, "md5_digest": "b6939d9cdeb431b0285204bb9559bcbe", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 34546, "upload_time": "2015-03-09T03:27:10", "url": "https://files.pythonhosted.org/packages/c3/77/3cf8ee0259be928b12c0b9c89063891addc4f09a4371e932c22c203fcc21/dbpy-0.1.1.zip" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "bb499018603672b2b73a677f0d4b67ca", "sha256": "fc9c5daa21756a71077ebea67b57a6520742541b4afaba1f22a32add85a07e40" }, "downloads": -1, "filename": "dbpy-0.1.2.tar.gz", "has_sig": false, "md5_digest": "bb499018603672b2b73a677f0d4b67ca", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15502, "upload_time": "2015-07-26T05:37:54", "url": "https://files.pythonhosted.org/packages/f0/e1/c41e71eaf6b316f078e5fad3cfe61a5e0402c3fdb2a614cb096d9d825176/dbpy-0.1.2.tar.gz" }, { "comment_text": "", "digests": { "md5": "da586597f4a7a50e262af68c00c0d308", "sha256": "f03bed4ab2ff9e56b36b7c933638453d25e8fb45a5bbacfdeaa1180e9b9d151c" }, "downloads": -1, "filename": "dbpy-0.1.2.zip", "has_sig": false, "md5_digest": "da586597f4a7a50e262af68c00c0d308", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 37109, "upload_time": "2015-07-26T05:18:14", "url": "https://files.pythonhosted.org/packages/4f/d8/7f7a375c2e31983b78295bf1ba96d3b44ae13bf8f427849e2777b7b74ac8/dbpy-0.1.2.zip" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "d8d1372c057b42563aefd2e991154fc8", "sha256": "ba2d94b1f70d414eb0955085a56bf2b259ff7ce4c5accbc86ce971d87cb2a975" }, "downloads": -1, "filename": "dbpy-0.1.3.zip", "has_sig": false, "md5_digest": "d8d1372c057b42563aefd2e991154fc8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 38236, "upload_time": "2017-09-26T07:25:02", "url": "https://files.pythonhosted.org/packages/bb/83/95602f0fb5ad9f6ce51b739334fe8646f6764b931d7245cd7ad8eee0b7dc/dbpy-0.1.3.zip" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "d8d1372c057b42563aefd2e991154fc8", "sha256": "ba2d94b1f70d414eb0955085a56bf2b259ff7ce4c5accbc86ce971d87cb2a975" }, "downloads": -1, "filename": "dbpy-0.1.3.zip", "has_sig": false, "md5_digest": "d8d1372c057b42563aefd2e991154fc8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 38236, "upload_time": "2017-09-26T07:25:02", "url": "https://files.pythonhosted.org/packages/bb/83/95602f0fb5ad9f6ce51b739334fe8646f6764b931d7245cd7ad8eee0b7dc/dbpy-0.1.3.zip" } ] }