{ "info": { "author": "Eric V. Smith", "author_email": "eric@trueblade.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python :: 2", "Programming Language :: Python :: 3", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "====================\nheader_detail_footer\n====================\n\nOverview\n========\n\nThe header_detail_footer module provides a way to parse input\niterables (usually text files) that contain header rows, an unknown\nnumber of data rows (called the details), and footer rows. The number\nof header and footer rows must be specified when parsing begins. There\ncan be zero or more header rows, and independently zero or more footer\nrows. The detail rows are all of the rows between the header and\nfooter. If a file consists of just headers and footers, there will be\nzero detail rows.\n\nThe module API consists of a single function, parse(), and several\nexceptions.\n\nNote that the contents of each input \"row\" are never inspected: they\nare just iterated over and returned by the parser. They are often\nstrings, but they could be any object.\n\nTypical usage\n=============\n\nThis code shows a simple usage of the `parse()` function::\n\n >>> from header_detail_footer import parse\n >>> header, details, footer = parse(['header', 'row 1', 'row 2', 'footer'])\n >>> header\n 'header'\n >>> list(details)\n ['row 1', 'row 2']\n >>> footer()\n 'footer'\n\nThe parse() function\n====================\n\nThe parse() function takes 1 required parameter, the input\niterable. There are two optional parameters, header_rows and\nfooter_rows. Both default to 1. They represent the number of header\nand footer rows present in the input, respectively.\n\nparse() returns a 3-tuple: (header, details, footer). header is the\nheader row(s), if any; details is an iterator returning each detail\nrow; and footer is a callable returning the footer row(s), if any.\n\nFor header and footer(), they return a single row from the input if\nheader_rows or footer_rows is 1, respectively. Otherwise, including\nthe case of 0 rows, they contain a list::\n\n >>> header, details, footer = parse(['row 1', 'row 2', 'footer 1', 'footer 2'],\n ... header_rows=0, footer_rows=2)\n >>> header\n []\n >>> list(details)\n ['row 1', 'row 2']\n >>> footer()\n ['footer 1', 'footer 2']\n\nThe returned footer callable need never be called. If footer is ever\ncalled, details must have been exhausted, otherwise a RuntimeError is\nraised::\n\n >>> header, detail, footer = parse('abc')\n >>> footer()\n Traceback (most recent call last):\n ...\n RuntimeError: called footer() before details were exhausted\n\nExceptions\n==========\n\nTwo exceptions are defined at the module level: `HeaderError` and\n`FooterError`. Note that these exceptions are raised in the `parser()`\nmethod. They are never raised when iterating over the header, details,\nor footer.\n\nHeaderError\n-----------\n\nRaised by `parser()` if the input does not contain enough rows for the header::\n\n >>> header, details, footer = parse(['row 1'], header_rows=3) #doctest: +IGNORE_EXCEPTION_DETAIL\n Traceback (most recent call last):\n ...\n HeaderError: too few rows for header\n\nFooterError\n-----------\n\nRaised by `parser()` if the input does contain enough rows for the\nheader, but not enough rows for the footer::\n\n >>> header, details, footer = parse(['row 1', 'row 2', 'row 3'],\n ... header_rows=2, footer_rows=2) #doctest: +IGNORE_EXCEPTION_DETAIL\n Traceback (most recent call last):\n ...\n FooterError: too few rows for footer\n\nUsage with CSV files\n====================\n\nIf you have a CSV file with a header row containing column names, and\nalso with a footer row, it's easiest if you tell header_detail_footer\nthat there is no header row. That way, the details iterator can be\npassed to csv.DictReader, which will pick up the header row as usual::\n\n >>> import csv\n\n # here, the footer row contains a row count\n >>> _, details, footer = parse(['FRUIT,COLOR',\n ... 'apple,red',\n ... 'orange,orange',\n ... 'rowcount:2'],\n ... header_rows=0) # specify 0 header rows\n\n # pass the details to csv.DictReader. this includes what is now\n # the csv header row\n >>> reader = csv.DictReader(details)\n\n # print out each row\n >>> for count, row in enumerate(reader, 1):\n ... (count, [(key, value) for key, value in sorted(row.items())])\n ...\n (1, [('COLOR', 'red'), ('FRUIT', 'apple')])\n (2, [('COLOR', 'orange'), ('FRUIT', 'orange')])\n\n # verify the footer count\n >>> _, _, footer_count = footer().partition(':')\n >>> int(footer_count) == count\n True\n\nChange log\n==========\n\n2.4 2016-10-27 Eric V. Smith\n----------------------------\n\n* Renamed distribution name to replace hyphens with underscores. The\n name is now header_detail_footer (issue #7).\n\n* Remove hack for renaming RPMs (issue #5).\n\n* Always require setuptools (issue #4).\n\n* No code changes.\n\n2.3 2014-03-13 Eric V. Smith\n----------------------------\n\n* Added MANIFEST.in to MANIFEST.in (issue #2).\n\n* Have bdist_rpm use the package name 'python-header-detail-footer'\n (issue #3).\n\n2.2 2013-12-03 Eric V. Smith\n----------------------------\n\n* Add documentation about CSV files.\n\n* Change protocol error from ValueError to RuntimeError. Closes\n Bitbucket issue #1.\n\n2.1 2013-11-16 Eric V. Smith\n----------------------------\n\n* Add a MANIFEST.in so non-code files end up in sdist.\n\n2.0 2013-11-15 Eric V. Smith\n----------------------------\n\n* Changed API to return a callable only for footer, since that's the\n only thing that needs to be delayed after details are exhausted.\n\n* Changed nomenclature: now refers to \"rows\" instead of \"lines\".\n\n\n1.0 2013-11-15 Eric V. Smith\n----------------------------\n\n* First stable version.\n\n0.1 2013-11-14 Eric V. Smith\n----------------------------\n\n* Initial release.\n\n\n", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://bitbucket.org/ericvsmith/header-detail-footer", "keywords": "", "license": "Apache License Version 2.0", "maintainer": "", "maintainer_email": "", "name": "header-detail-footer", "package_url": "https://pypi.org/project/header-detail-footer/", "platform": "", "project_url": "https://pypi.org/project/header-detail-footer/", "project_urls": { "Homepage": "https://bitbucket.org/ericvsmith/header-detail-footer" }, "release_url": "https://pypi.org/project/header-detail-footer/2.4/", "requires_dist": null, "requires_python": "", "summary": "Parse input streams with headers and footers.", "version": "2.4" }, "last_serial": 2426215, "releases": { "0.1": [], "1.0": [ { "comment_text": "", "digests": { "md5": "f5fd076c602cdfbf79d33775c45b07b4", "sha256": "866b8d48f8d363f113802423af0cee16f6544fdd46eac5bb388a1ffd0d7a4374" }, "downloads": -1, "filename": "header-detail-footer-1.0.tar.gz", "has_sig": false, "md5_digest": "f5fd076c602cdfbf79d33775c45b07b4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4134, "upload_time": "2013-11-15T09:41:29", "url": "https://files.pythonhosted.org/packages/50/9c/f5ccac9cc789980460df8a44b720ccbb259f9cdefb6bf65b8b60a8455e12/header-detail-footer-1.0.tar.gz" } ], "2.0": [ { "comment_text": "", "digests": { "md5": "f26dbf2431bfa80bb026798e39d590e5", "sha256": "05d78ee8a3219822160a72e2a4c9f4265ec130729ff078c8b94f056bdd7373b7" }, "downloads": -1, "filename": "header-detail-footer-2.0.tar.gz", "has_sig": false, "md5_digest": "f26dbf2431bfa80bb026798e39d590e5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4355, "upload_time": "2013-11-15T15:01:29", "url": "https://files.pythonhosted.org/packages/a9/51/8c115e81b78bd2267ccb90bfa9a358d9f62b7ac2950ff09713ad8433c57c/header-detail-footer-2.0.tar.gz" } ], "2.1": [ { "comment_text": "", "digests": { "md5": "3101e38e1252454a016f730dfac3af46", "sha256": "288a2cc5e4654e357ca245f741d19b4694084f969a50d56702b58c6d08bea2c6" }, "downloads": -1, "filename": "header-detail-footer-2.1.tar.gz", "has_sig": false, "md5_digest": "3101e38e1252454a016f730dfac3af46", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8202, "upload_time": "2013-11-17T12:55:53", "url": "https://files.pythonhosted.org/packages/79/d3/7f62f71018458a9d6e38488e6d1913f68f51af722bc7fc26b32d555f5b38/header-detail-footer-2.1.tar.gz" } ], "2.2": [ { "comment_text": "", "digests": { "md5": "2e0f4c28afdd3cb92292590cc3523059", "sha256": "3e176ab5d0daa9b8e5ea8c954a4b114a06b71037130b2b635b627e8bfc23ce9c" }, "downloads": -1, "filename": "header-detail-footer-2.2.tar.gz", "has_sig": false, "md5_digest": "2e0f4c28afdd3cb92292590cc3523059", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8768, "upload_time": "2013-12-03T14:31:00", "url": "https://files.pythonhosted.org/packages/ea/7c/9781168cecdb5297c49ac9e18bfa877f60956b3f3905a587cd1a823f8b96/header-detail-footer-2.2.tar.gz" } ], "2.3": [ { "comment_text": "", "digests": { "md5": "5f565614eaed642897d47821b2a8eb50", "sha256": "85105da7f93d64a9d03ca081a7bc8ba8a52095e4dc6b7e4dff64bdbc1140ee7b" }, "downloads": -1, "filename": "header-detail-footer-2.3.tar.gz", "has_sig": false, "md5_digest": "5f565614eaed642897d47821b2a8eb50", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9376, "upload_time": "2014-03-14T12:29:33", "url": "https://files.pythonhosted.org/packages/83/ed/174b6350b5f7a4cb92f42d114b15a95032fc20b367464dd43360b75b2133/header-detail-footer-2.3.tar.gz" } ], "2.4": [ { "comment_text": "", "digests": { "md5": "584cd89be20426b22a33fe7b5c373431", "sha256": "6d47c9b05614b4e03837d9d7f1bb701e13633a56a511653897dc2c714742d2a8" }, "downloads": -1, "filename": "header_detail_footer-2.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "584cd89be20426b22a33fe7b5c373431", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 8534, "upload_time": "2016-10-27T13:30:29", "url": "https://files.pythonhosted.org/packages/c4/14/08fcc71e406f56844e8b1063b13de70098cf8346f01e67f9886e027e4d4c/header_detail_footer-2.4-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ffe94a13be7d5d6b4a3832d43744f7d9", "sha256": "9bc109b38140daf85df43e7cf8f17344f5f8b28f9ccc46f803b5c6db05fe7afe" }, "downloads": -1, "filename": "header_detail_footer-2.4.tar.gz", "has_sig": false, "md5_digest": "ffe94a13be7d5d6b4a3832d43744f7d9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11619, "upload_time": "2016-10-27T13:30:31", "url": "https://files.pythonhosted.org/packages/0c/52/0978bf990a9d1c90513cb261a2ecf18020350b503f71fc95a80a07224042/header_detail_footer-2.4.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "584cd89be20426b22a33fe7b5c373431", "sha256": "6d47c9b05614b4e03837d9d7f1bb701e13633a56a511653897dc2c714742d2a8" }, "downloads": -1, "filename": "header_detail_footer-2.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "584cd89be20426b22a33fe7b5c373431", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 8534, "upload_time": "2016-10-27T13:30:29", "url": "https://files.pythonhosted.org/packages/c4/14/08fcc71e406f56844e8b1063b13de70098cf8346f01e67f9886e027e4d4c/header_detail_footer-2.4-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ffe94a13be7d5d6b4a3832d43744f7d9", "sha256": "9bc109b38140daf85df43e7cf8f17344f5f8b28f9ccc46f803b5c6db05fe7afe" }, "downloads": -1, "filename": "header_detail_footer-2.4.tar.gz", "has_sig": false, "md5_digest": "ffe94a13be7d5d6b4a3832d43744f7d9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11619, "upload_time": "2016-10-27T13:30:31", "url": "https://files.pythonhosted.org/packages/0c/52/0978bf990a9d1c90513cb261a2ecf18020350b503f71fc95a80a07224042/header_detail_footer-2.4.tar.gz" } ] }