{ "info": { "author": "brentp", "author_email": "bpederse@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: C", "Programming Language :: Python", "Topic :: Database :: Database Engines/Servers" ], "description": "+++++++\nToTable\n+++++++\n\n.. contents ::\n\nAbout\n-----\n\nPythonic access to `tokyo cabinet`_ table database api. (NOTE: The \noriginal `cython`_ code was from `pykesto`_.)\nThe aims is to provide a simple syntax to load and query data in a table.\nMost of the work is handled by the `Col`_ query interface. e.g.\n::\n\n >>> from totable import ToTable, Col\n >>> tbl = ToTable('t.tct', 'w')\n >>> result = tbl.select(Col('age') > 18, Col('name').startswith('T'))\n\nto allow querying columns with numbers and letters transparently. Even\nthough tokyo cabinet stores all values as strings.\nAnd more syntatic sugar below.\n\nInstall\n-------\nfirst, install Tokyo-Cabinet `source`_, then,\nfrom a the directory containing this file:\n::\n\n # requires cython for now.\n $ cython src/ctotable.pyx\n $ python setup.py build_ext -i\n\n # test \n $ PYTHONPATH=. python totable/tests/test_totable.py\n\n # install\n $ sudo python setup.py install\n\n\nExample Use\n-----------\nMake some fake data. Note it works just like a DBM or dictionary, except\nthat the values themselves are dictionaries.\n::\n\n >>> from totable import ToTable, Col\n >>> tbl = ToTable('doctest.tct', 'w')\n >>> fnames = ['fred', 'jane', 'john', 'mark', 'bill', 'ted', 'ann']\n >>> lnames = ['smith', 'cox', 'kit', 'ttt', 'zzz', 'ark', 'ddk']\n >>> for i in range(len(fnames)):\n ... tbl[str(i)] = {'fname': fnames[i], 'lname': lnames[i],\n ... 'age': str((10 + i) * 2)}\n ... tbl[str(i + len(fnames))] = {'fname': fnames[i],\n ... 'lname': lnames[len(lnames) - i - 1],\n ... 'age': str((30 + i) * 2)}\n\n >>> len(tbl)\n 14\n\nCol\n===\n\n`Col`_, as sent to the select method makes it easy to do queries on a database\nthe format is Col(colname) == 'Fred' where colname is one of the keys in the\ndictionary items in the database. or can use kwargs to select()\n::\n\n >>> tbl.select(lname='cox')\n [('1', {'lname': 'cox', 'age': '22', 'fname': 'jane'}), ('12', {'lname': 'cox', 'age': '70', 'fname': 'ted'})]\n\nthough using Col gives more power\n\nstartswith\n**********\n::\n\n >>> results = tbl.select(Col('fname').startswith('j'))\n >>> [d['fname'] + ' ' + d['lname'] for k, d in results]\n ['jane cox', 'jane ark', 'john kit', 'john zzz']\n\nendswith\n********\n::\n\n #and combine queries by sending them in together.\n >>> results = tbl.select(Col('fname').startswith('j'), Col('lname').endswith('k'))\n >>> [d['fname'] + ' ' + d['lname'] for k, d in results]\n ['jane ark']\n\nlike\n****\nthis works like an sql query with '%' on either end. (dont attach those\nvalues to the query!). so to get everyone with and 'e' in their firstname...\n::\n\n >>> r = tbl.select(Col('fname').like('e'))\n >>> sorted(set([v['fname'] for k, v in r]))\n ['fred', 'jane', 'ted']\n\nin_list\n*******\nreturn row that exactly match *1* of the values in the list.\n::\n\n >>> r = tbl.select(Col('fname').in_list(['ted', 'fred']))\n >>> sorted(set([v['fname'] for k, v in r]))\n ['fred', 'ted']\n\n >>> r = tbl.select(Col('age').in_list([20, 70]))\n >>> sorted(set([v['age'] for k, v in r]))\n ['20', '70']\n\nbetween\n*******\nuse for number querying between a min and max. includes the endpoints.\n::\n\n >>> r = tbl.select(Col('age').between(68, 70))\n >>> [v['age'] for k, v in r]\n ['68', '70']\n\nnumeric queries (richcmp)\n*************************\nin TC, everything is stored as strings, but you can force number based \ncomparisons with ToTable by using (you guessed it) a number. Or using \na string for non-numeric comparisons.\n::\n\n >>> results = tbl.select(Col('age') > 68)\n >>> [d['age'] for k, d in results]\n ['70', '72']\n\ncombining queries\n*****************\njust add multiple Col() arguments to the select() call\nand they will be essentially *and*'ed together.\n::\n\n >>> results = tbl.select(Col('age') > 68, Col('age') < 72)\n >>> [d['age'] for k, d in results]\n ['70']\n\nNegate(~)\n*********\nfor example get everything that's not a given value...\n::\n\n >>> results = tbl.select(~Col('age') <= 68)\n >>> [d['age'] for k, d in results]\n ['70', '72']\n\n #all rows where fname is not 'jane' \n >>> results = tbl.select(~Col('fname') != 'jane')\n >>> 'jane' in [d['fname'] for k, d in results]\n False\n\nRegular Expression Matching\n***************************\nsupports normal regular expression characters \"[ $ ^ | \" , etc.\n\n::\n\n >>> results = tbl.select(Col('fname').matches(\"a\"))\n >>> sorted(set([d['fname'] for k, d in results]))\n ['ann', 'jane', 'mark']\n\n >>> results = tbl.select(Col('fname').matches(\"^a\"))\n >>> sorted(set([d['fname'] for k, d in results]))\n ['ann']\n\n\nOffset/Limit\n============\njust like SQL, yo.\n\n::\n\n >>> results = tbl.select(Col('age') < 68, limit=1)\n >>> len(results)\n 1\n\norder\n=====\ncurrently only works for string keys. use '-' for descending and \n'+' for ascending\n\n::\n\n >>> [v['fname'] for k, v in tbl.select(lname='cox', order='-fname')]\n ['ted', 'jane']\n\n # ascending\n >>> [v['fname'] for k, v in tbl.select(lname='cox', order='+fname')]\n ['jane', 'ted']\n\n\nvalues\n======\nTC is a key-value store, but it also acts as a table. it may be\nconvenient to get just the values as you'd expect from a database\ntable. Note in all examples above, the 'k'ey is not used, only \nthe value dictionary. This can be made simpler with 'values_only'.\nWhen 'values_only' is True, some python call overhead is removed\nas well.\n\n::\n >>> tbl.select(Col('fname').matches(\"^a\"), values_only=True)\n [{'lname': 'ddk', 'age': '32', 'fname': 'ann'}, {'lname': 'smith', 'age': '72', 'fname': 'ann'}]\n \n\nSchemaless\n==========\nsince it's schemaless, you can add anything\n\n::\n\n >>> tbl['weird'] = {\"val\": \"hello\"}\n >>> tbl['weird']\n {'val': 'hello'}\n\ndelete\n======\ndelete as expected for a dictionary interface.\n\n::\n\n >>> del tbl['weird']\n >>> print tbl.get('weird')\n None\n\n\nput\n===\nencapsulates put, putkeep and putcat with a mode kwarg that takes\n'p' or 'k' or 'c' respectively.\n::\n\n >>> tbl.put('a', {'a': '1'}, mode='p')\n >>> tbl.put('a', {'a': '2'}, mode='k')\n 'keep'\n >>> assert tbl['a'] == {'a': '1'}\n\n >>> tbl.put('b', {'a': '3'}, mode='k')\n 'put'\n\n >>> tbl.put('a', {'b': '99'}, 'c')\n >>> assert tbl['a'] == {'a': '1', 'b': '99'}\n\nPerformance Tuning\n==================\nTokyo Cabinet allows you to `tune` or `optimize` a table. the available parameters are:\n\n * `bnum` specifies the number of elements of the bucket array.\n Suggested size of 'bnum' is about from 0.5 to 4 times of the number\n of all records to be stored. default is about 132K.\n\n * `apow` specifies the size of record alignment by power of 2.\n The default value is 4 standing for 2^4=16.\n\n * `fpow` specifies the maximum number of elements of the free block\n pool by power of 2. The default value is 10 standing for 2^10=1024.\n\n * `opts` specifies options by bitwise-or (|):\n\n * 'TDBTLARGE' must be specified to use a database larger than 2GB. \n (you must also specify a config flag when compiling the TC library to\n enable this)\n * 'TDBTDEFLATE' use Deflate encoding.\n * 'TDBTBZIP' use BZIP2 encoding.\n * 'TDBTTCBS' use TCBS encoding.\n\nThe other parameters: `cache`_ and `mmap_size`_ are explained below.\n\ntune\n****\nThe arguments can be sent to the constructor.\n::\n\n >>> import totable\n >>> t = ToTable(\"some.tct\", 'w', bnum=1234, fpow=6, \\\n ... opts=totable.TDBTLARGE | totable.TDBTBZIP)\n\n >>> t.close()\n\noptimize\n********\noptimize is called on an database opened with mode='w'. if no arguments are\nspecified, it will automatically adjust 'bnum' (only) according to the number\nof elements in the table.\n::\n\n >>> t = ToTable(\"some.tct\", 'w')\n\n # ... add some records ...\n >>> t.optimize()\n True\n\nmmap_size\n*********\n`mmap_size` is the size of mapped memory. default is 67,108,864 (64MB)\nset in the constructor. this is `xmsiz` in TC parlance.\n::\n\n >>> t.close()\n >>> t = ToTable(\"some.tct\", 'w', mmap_size=128 * 1e6) # ~128MB.\n\ncache\n*****\nTC also allows setting various caching parameters.\n* `rcnum` is the max number of records to be cached. default is 0\n* `lcnum` is the max number of leaf-nodes to be cached. default is 4096\n* `ncnum` is the max number of non-leaf nodes cached. default is 512\nthese also must be set in the constructor.\n::\n\n >>> t.close()\n >>> t = ToTable(\"some.tct\", 'w', rcnum=1e7, lcnum=32768)\n\n\nindex\n*****\ncreate or delete a 's'tring or 'd'ecimal index on a column for faster queries.\n:: \n\n # create a decimal index on the number column 'age'.\n >>> tbl.create_index('age', 'd')\n True\n\n # create a 'string index on the string column 'fname'.\n >>> tbl.create_index('fname', 's')\n True\n\n # remove the index.\n >>> tbl.delete_index('fname')\n True\n\n # optimize the index\n >>> tbl.optimize_index('age')\n True\n\nclear\n=====\nremove all records from the db.\n::\n\n >>> len(tbl)\n 16\n >>> tbl.clear()\n >>> len(tbl)\n 0\n\ntransaction\n===========\ndo stuff in a transaction. a rollback() is performed on any exceptions.\n::\n\n >>> try:\n ... with transaction(tbl):\n ... tbl['zzz'] = {'a': '4'}\n ... 1/0\n ... except: pass\n\n >>> 'zzz' in tbl\n False\n\n\nSee Also\n--------\n\n * `tc`_ nice c-python bindings for all of the `tokyo cabinet`_ db types\n including the table\n\n * `pykesto`_ the project from which this library is taken. aims to provide\n transactions on top of `tokyo cabinet`_ .\n\n * to help out, see TODO list at top of `ctcable.pyx`_\n\n * tokyo cabinet database api http://1978th.net/tokyocabinet/spex-en.html#tctdbapi\n\n \n\n.. _`pykesto`: http://code.google.com/p/pykesto/\n.. _`tokyo cabinet`: http://1978th.net/tokyocabinet/\n.. _`tc`: http://github.com/rsms/tc\n.. _`cython`: http://cython.org/\n.. _`ctcable.pyx`: http://github.com/brentp/totable/blob/master/src/ctotable.pyx\n.. _`source`: http://sourceforge.net/projects/tokyocabinet/files/", "description_content_type": null, "docs_url": "https://pythonhosted.org/totable/", "download_url": "http://", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://", "keywords": null, "license": "UNKNOWN", "maintainer": null, "maintainer_email": null, "name": "totable", "package_url": "https://pypi.org/project/totable/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/totable/", "project_urls": { "Download": "http://", "Homepage": "http://" }, "release_url": "https://pypi.org/project/totable/0.1/", "requires_dist": null, "requires_python": null, "summary": "Cython wrapper for tokyo cabinet table", "version": "0.1" }, "last_serial": 800829, "releases": { "0.0.1": [], "0.1": [ { "comment_text": "", "digests": { "md5": "f7b3bc78b99b35210856d34198092622", "sha256": "f1ccacbef1104f7946872c980d3021b5aae55c622c76362c84980c95d2e800af" }, "downloads": -1, "filename": "totable-0.1.tar.gz", "has_sig": false, "md5_digest": "f7b3bc78b99b35210856d34198092622", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 59056, "upload_time": "2010-01-07T19:19:32", "url": "https://files.pythonhosted.org/packages/d0/15/49753ad20d8e798b54d61dcfaa0115c415f469c8b8e21bae50ab3cffcba8/totable-0.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "f7b3bc78b99b35210856d34198092622", "sha256": "f1ccacbef1104f7946872c980d3021b5aae55c622c76362c84980c95d2e800af" }, "downloads": -1, "filename": "totable-0.1.tar.gz", "has_sig": false, "md5_digest": "f7b3bc78b99b35210856d34198092622", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 59056, "upload_time": "2010-01-07T19:19:32", "url": "https://files.pythonhosted.org/packages/d0/15/49753ad20d8e798b54d61dcfaa0115c415f469c8b8e21bae50ab3cffcba8/totable-0.1.tar.gz" } ] }