{ "info": { "author": "Bertrand Vidal", "author_email": "vidal.bertrand@gmail.com", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Developers", "Intended Audience :: Information Technology", "Operating System :: OS Independent", "Programming Language :: Python :: 2", "Programming Language :: Python :: 3" ], "description": "parse\\_this\n===========\n\n|PyPI latest version badge| |Code health|\n\nMakes it easy to parse command line arguments for any function, method\nor classmethod.\n\nYou just finished writing an awesome piece of code and now comes the\nboring part: adding the command line parsing to actually use it ...\n\nSo now you need to use the awesome, but very verbose, ``argparse``\nmodule. For each argument of your entry point method you need to add a\nname, a help message and/or a default value. But wait... Your parameters\nare correctly named right!? And you have an awesome docstring for that\nmethod. There is probably a way of creating the ``ArgumentParser``\neasily right?\n\nYes and it's called ``parse_this``!\n\nUsage\n-----\n\n``parse_this`` contains a simple way to create a command line interface\nfrom an entire class. For that you will need to use the ``parse_class``\nclass decorator.\n\n.. code:: python\n\n # script.py\n from __future__ import print_function\n from parse_this import Self, create_parser, parse_class\n\n\n @parse_class()\n class ParseMePlease(object):\n \"\"\"This will be the description of the parser.\"\"\"\n\n @create_parser(Self, int)\n def __init__(self, foo, ham=1):\n \"\"\"Get ready to be parsed!\n\n Args:\n foo: because naming stuff is hard\n ham: ham is good and it defaults to 1\n \"\"\"\n self._foo = foo\n self._ham = ham\n\n @create_parser(Self, int, int)\n def do_stuff(self, bar, spam=1):\n \"\"\"Can do incredible stuff with bar and spam.\n\n Args:\n bar: as in foobar, will be multiplied with everything else\n spam: goes well with eggs, spam, bacon, spam, sausage and spam\n\n Returns:\n Everything multiplied with each others\n \"\"\"\n return self._foo * self._ham * bar * spam\n\n\n if __name__ == \"__main__\":\n print(ParseMePlease.parser.call())\n\n.. code:: bash\n\n python script.py --help # Print a comprehensive help and usage message\n python script.py 2 do-stuff 2\n >>> 4\n python script.py 2 --ham 2 do-stuff 2 --spam 2\n >>> 16\n\nHow does it work **TL;DR version**?\n\n- You need to decorate the methods you want to be usable from the\n command line using ``create_parser``.\n- The ``__init__`` method arguments and keyword arguments will be the\n arguments and options of the script command line *i.e.* the first\n arguments and options\n- The other methods will be transformed into sub-command, again mapping\n the command line arguments and options to the method's own arguments\n- All you have to do for this to work is:\n- Decorate your class with ``parse_class``\n- Decorate methods with ``create_parser`` making it aware of the type\n of the arguments. Using ``Self`` to designate the ``self`` parameter\n- Document your class and method with properly formed docstring to get\n help and usage message\n- Call ``.parser.call()`` and you are done!\n\nIf you feel like you may need more customization and details, please\nread on!\n\n- If the ``__init__`` method is decorated it will be considered the\n first, or top-level, parser this means that all arguments in your\n ``__init__`` will be arguments pass right after invoking you script\n i.e. ``python script.py init_arg_1 init_arg_2 etc...``\n- The description of the top-level parser is taken from the class's\n docstring or overwritten by the keyword argument ``description`` of\n ``parse_class``.\n- Each method decorated by ``create_parser`` will become a subparser of\n its own. The command name of the subparser is the same as the method\n name with ``_`` replaced by ``-``. 'Private' methods, whose name\n start with an ``_``, do not have a subparser by default, as this\n would expose them to the outside. However if you want to expose them\n you can set the keyword argument ``parse_private=True`` in\n ``parse_class``. If exposed their command name will not contain the\n leading ``-`` as this would be confusing for command parsing. Special\n methods, such as ``__str__``, can be decorated as well. Their command\n name will be stripped of all ``_``\\ s resulting in command names such\n as ``str``.\n- When used in a ``parse_class`` decorated class ``create_parser`` can\n take an extra parameters ``name`` that will be used as the\n sub-command name. The same modifications are made to the ``name``\n replacing ``_`` with ``-``\n- When calling ``python script.py --help`` the help message for\n **every** parser will be displayed making easier to find what you are\n looking for\n\nArguments and types\n~~~~~~~~~~~~~~~~~~~\n\nBoth ``parse_this`` and ``create_parser`` need a list of types to which\narguments will be converted to. Any Python standard type can be used,\ntwo special values are used for the ``self`` and ``cls`` respectively\n``Self`` and ``Class``. There is no need to provide a type for keyword\nagurments since it is infered from the default value of the argument. If\nyour method signature contains ``arg_with_default=12`` ``parse_this``\nexpect an ``int`` where ``arg_with_default`` is.\n\nIf this is the containt of ``test.py``:\n\n.. code:: python\n\n from __future__ import print_function\n from parse_this import create_parser, Self\n\n\n class INeedParsing(object):\n \"\"\"A class that clearly needs argument parsing!\"\"\"\n\n def __init__(self, an_argument):\n self._an_arg = an_argument\n\n @create_parser(Self, int, str, params_delim=\"--\")\n def parse_me_if_you_can(self, an_int, a_string, an_other_int=12):\n \"\"\"I dare you to parse me !!!\n\n Args:\n an_int -- int are pretty cool\n a_string -- string aren't that nice\n an_other_int -- guess what? I got a default value\n \"\"\"\n return a_string * an_int, an_other_int * self._an_arg\n\n\n if __name__ == \"__main__\":\n need_parsing = INeedParsing(2)\n print(INeedParsing.parse_me_if_you_can.parser.call(need_parsing))\n\nThe following would be the output of the command line\n``python test.py --help``:\n\n.. code:: bash\n\n usage: test.py [-h] [--an_other_int AN_OTHER_INT] an_int a_string\n\n I dare you to parse me !!!\n\n positional arguments:\n an_int int are pretty cool\n a_string string aren't that nice\n\n optional arguments:\n -h, --help show this help message and exit\n --an_other_int AN_OTHER_INT guess what? I got a default value\n\nThe method ``parse_me_if_you_can`` expect an ``int`` of the name\n``an_int``, a ``str`` of the name ``a_string`` and other ``int`` with\nthe name ``an_other_int`` and a default value of 12. So does the parser\n!!! As displayed by the ``--help`` command.\n\nNote: ``create_parser`` cannot decorate the ``__init__`` method of a\nclass unless the class is itself decorated with ``parse_class``. A\n``ParseThisError`` will be raised if you attempt to use the ``call``\nmethod of such a parser.\n\nThe following would be the output of the command line\n``python test.py 2 yes --default 4``:\n\n.. code:: bash\n\n ('yesyes', 8)\n\nHelp message\n~~~~~~~~~~~~\n\nIn order to get a help message generated automatically from the method\ndocstring it needs to be in the specific format described below:\n\n.. code:: python\n\n ...\n @create_parser(Self, int, int, params_delim=)\n def method(self, spam, ham):\n \"\"\"\n \n \n \n \"\"\"\n pass\n ...\n\n- description: is a multiline description of the method used for the\n command line\n- each line of argument help have the following component:\n- arg\\_name: the **same** name as the argument of the method.\n- delimiter\\_chars: one or more chars that separate the argument and\n its help message. Using whitespaces is not recommended as it could\n have an expected behavior with multiline help message.\n- arg\\_help: is everything behind the delimiter\\_chars until the next\n argument, **a blank line** or the end of the docstring.\n\nThe ``delimiter_chars`` can be passed to both ``parse_this`` and\n``create_parser`` as the keywords argument ``params_delim``. It defaults\nto ``:`` since this is the convention I most often use.\n\nIf no docstring is specified a generic - not so useful - help message\nwill be generated for the command line and arguments.\n\nUsing None as a default value and bool as flags\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nUsing ``None`` as a default value is common practice in Python but for\n``parse_this`` and ``create_parser`` to work properly the type of the\nargument which defaults to ``None`` needs to be specified. Otherwise a\n``ParseThisError`` will be raised.\n\n.. code:: python\n\n ...\n\n @create_parser(str):\n def function(ham, spam=None):\n if spam is not None:\n return ham * spam\n return ham\n\n # Will raise ParseThisError: To use default value of 'None' you need to specify the type of the argument 'spam' for the method 'function'\n\n ...\n\nBut specifying the type of ``spam`` will allow ``create_parser`` to work\nproperly\n\n.. code:: python\n\n ...\n\n @create_parser(str, int)\n def function(ham, spam=None):\n if spam is not None:\n return ham * spam\n return ham\n\n # Calling function.parser.call(args=\"yes\".split()) -> 'yes'\n # Calling function.parser.call(args=\"yes --spam 3\".split()) -> 'yesyesyes'\n ...\n\nAn other common practice is to use ``bool``\\ s as flags or switches. All\narguments of type ``bool``, either typed direclty or inferred from the\ndefault value, will become optional arguments of the command line. A\n``bool`` argument without default value will default to ``True`` as in\nthe following example:\n\n.. code:: python\n\n ...\n @create_parser(str, bool)\n def function(ham, spam):\n if spam:\n return ham, spam\n return ham\n\n # Calling function.parser.call(args=\"yes\".split()) -> 'yes', True\n # Calling function.parser.call(args=\"yes --spam\".split()) -> 'yes'\n ...\n\nAdding ``--spam`` to the arguments will act as a flag/switch setting\n``spam`` to ``False``. Note that ``spam`` as become optional and will be\ngiven the value ``True`` if ``--spam`` is not among the arguments to\nparse.\n\nArguments with a boolean default value will act in the same way i.e.\nacting as flag to change the default value:\n\n.. code:: python\n\n ...\n @create_parser(str)\n def function(ham, spam=False):\n if spam:\n return ham, spam\n return ham\n # Calling function.parser.call(args=\"yes\".split()) -> 'yes'\n # Calling function.parser.call(args=\"yes --spam\".split()) -> 'yes', True\n ...\n\nHere everything works as intended and the default value for ``spam`` is\n``False`` and passing ``--spam`` as an argument to be parsed will assign\nit ``True``.\n\nDecorator\n---------\n\nAs a decorator ``create_parser`` will create an argument parser for the\ndecorated function. A ``parser`` attribute will be added to the method\nand can be used to parse the command line argument.\n\n.. code:: python\n\n from __future__ import print_function\n from parse_this import create_parser\n\n\n @create_parser(str, int)\n def concatenate_str(one, two=2):\n \"\"\"Concatenates a string with itself a given number of times.\n\n Args:\n one: string to be concatenated with itself\n two: number of times the string is concatenated, defaults to 2\n \"\"\"\n return one * two\n\n\n if __name__ == \"__main__\":\n print(concatenate_str.parser.call())\n\nCalling this script from the command line as follow:\n\n.. code:: bash\n\n python script.py yes --two 3\n\nwill return ``'yesyesyes'`` as expected and all the parsing have been\ndone for you.\n\nNote that the function can still be called as any other function from\nany python file. Also it is **not** possible to stack ``create_parser``\nwith any decorator that would modify the signature of the decorated\nfunction e.g. using ``functools.wraps``.\n\nFunction\n--------\n\nAs a function ``parse_this`` will handle the command line arguments\ndirectly.\n\n.. code:: python\n\n from __future__ import print_function\n from parse_this import parse_this\n\n\n def concatenate_str(one, two=2):\n \"\"\"Concatenates a string with itself a given number of times.\n\n Args:\n one: string to be concatenated with itself\n two: number of times the string is concatenated, defaults to 2\n \"\"\"\n return one * two\n\n\n if __name__ == \"__main__\":\n print(parse_this(concatenate_str, [str, int]))\n\nCalling this script with the same command line arguments ``yes --two 3``\nwill also return ``'yesyesyes'`` as expected.\n\nClassmethods\n------------\n\nIn a similar fashion you can parse line arguments for classmethods:\n\n.. code:: python\n\n\n class MyClass(object):\n ...\n @classmethod\n @create_parser(Class, int, str, params_delim=\"--\")\n def parse_me_if_you_can(cls, an_int, a_string, default=12):\n \"\"\"I dare you to parse me !!!\n\n Args:\n an_int -- int are pretty cool\n a_string -- string aren't that nice\n default -- guess what I got a default value\n \"\"\"\n return a_string * an_int, default * default\n ...\n\n MyClass.parse_me_if_you_can.parser.call(MyClass)\n\nThe output will be the same as using ``create_parser`` on a regular\nmethod. The only difference is the use of the special value ``Class`` to\nspecify where the ``cls`` argument is used.\n\n**Notes**: \\* The ``classmethod`` decorator is placed **on top** of the\n``create_parser`` decorator in order for the method to still be a\nconsidered a class method. \\* A ``classmethod`` decorated with\n``create_parser`` in a class decorated with ``parse_class`` will not be\naccessible through the class command line.\n\nINSTALLING PARSE\\_THIS\n----------------------\n\n``parse_this`` can be installed using the following command:\n\n.. code:: bash\n\n pip install parse_this\n\nor\n\n.. code:: bash\n\n easy_install parse_this\n\nRUNNING TESTS\n-------------\n\nTo check that everything is running fine you can run the following\ncommand:\n\n.. code:: bash\n\n python setup.py nosetests\n\nCAVEATS\n-------\n\n- ``parse_this`` and ``create_parser`` are not able to be used on\n methods with ``*args`` and ``**kwargs``\n- A subsequent effect of the previous caveat is that ``create_parser``\n cannot be stacked with other decorator that would alter the\n callable's signature\n- Classmethods cannot be access from the command line in a class\n decorated with ``parse_class``\n- When using ``create_parser`` on a method that has an argument with\n ``None`` as a default value its type *must be* past in the list of\n types. A ``ParseThisError`` will be raised otherwise.\n\nLICENSE\n-------\n\n``parse_this`` is released under the MIT Licence. See the bundled\nLICENSE file for details.\n\n.. |PyPI latest version badge| image:: https://badge.fury.io/py/parse_this.svg\n :target: https://pypi.python.org/pypi/parse_this\n.. |Code health| image:: https://landscape.io/github/bertrandvidal/parse_this/master/landscape.png\n :target: https://landscape.io/github/bertrandvidal/parse_this/master", "description_content_type": null, "docs_url": null, "download_url": "https://pypi.python.org/pypi/parse_this", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/bertrandvidal/parse_this", "keywords": null, "license": "License :: MIT", "maintainer": null, "maintainer_email": null, "name": "parse_this", "package_url": "https://pypi.org/project/parse_this/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/parse_this/", "project_urls": { "Download": "https://pypi.python.org/pypi/parse_this", "Homepage": "https://github.com/bertrandvidal/parse_this" }, "release_url": "https://pypi.org/project/parse_this/1.0.3/", "requires_dist": null, "requires_python": null, "summary": "Makes it easy to create a command line interface for any function, method or classmethod..", "version": "1.0.3" }, "last_serial": 1446015, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "bca3ed374f85876e26823fe443bb3d8c", "sha256": "6843c5a7daa9a891294ca435f138662b374c88a2dbe3adb7df0034259aa02391" }, "downloads": -1, "filename": "parse_this-0.1.tar.gz", "has_sig": false, "md5_digest": "bca3ed374f85876e26823fe443bb3d8c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2743, "upload_time": "2014-11-12T00:17:38", "url": "https://files.pythonhosted.org/packages/96/0d/1508b6cf06728351d099196adbcd77ab9ec75300c347e055ac269ed42459/parse_this-0.1.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "c5b4abd002370236e5de331b5335825e", "sha256": "50b8463689b597a3c964dec05edbb4555cdba39341451e65cc2a073fcc86e7d1" }, "downloads": -1, "filename": "parse_this-0.2.tar.gz", "has_sig": false, "md5_digest": "c5b4abd002370236e5de331b5335825e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3409, "upload_time": "2014-11-12T01:08:59", "url": "https://files.pythonhosted.org/packages/94/8d/c119fd6a99a2c9a14e467c8a965f483c7aa69936383905f229778b38b5e6/parse_this-0.2.tar.gz" } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "3866ff5650c368ce6add7763c381b41f", "sha256": "1f92c49b95be881b6b0b1b2630fb9ae49314dc1586210a7667473f854ac73109" }, "downloads": -1, "filename": "parse_this-0.2.1.tar.gz", "has_sig": false, "md5_digest": "3866ff5650c368ce6add7763c381b41f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3396, "upload_time": "2014-11-12T01:23:56", "url": "https://files.pythonhosted.org/packages/90/a6/b3686142455ae04905f48665779096fd1a419e59ca93fe4f990902d35366/parse_this-0.2.1.tar.gz" } ], "0.2.2": [ { "comment_text": "", "digests": { "md5": "b4114ad2cadc3cb1ebf3e60f6639f34b", "sha256": "c37fa6ec55dfb2f3f429a1c7e3b864cf4b6fde8892602fbbb00d11ba17a37c4f" }, "downloads": -1, "filename": "parse_this-0.2.2.tar.gz", "has_sig": false, "md5_digest": "b4114ad2cadc3cb1ebf3e60f6639f34b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6483, "upload_time": "2014-12-24T14:22:53", "url": "https://files.pythonhosted.org/packages/6c/ce/2b0aab133e914ddd102ccb915d79358e2c05ad99cb76527e811443c5085e/parse_this-0.2.2.tar.gz" } ], "0.2.3": [ { "comment_text": "", "digests": { "md5": "a983b0ac8b0d0a08542517ae8d7350e1", "sha256": "2b1da671a9ac3ff5601c05857ac6adf93cae7a4b6fe9964626a9d008a32ddd99" }, "downloads": -1, "filename": "parse_this-0.2.3.tar.gz", "has_sig": false, "md5_digest": "a983b0ac8b0d0a08542517ae8d7350e1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6671, "upload_time": "2015-02-07T21:21:23", "url": "https://files.pythonhosted.org/packages/84/8c/858b78388e9f776e24c30ee31e12b45fb1b901de9a64c6c547be7c8be5b9/parse_this-0.2.3.tar.gz" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "a78a9b714bd46feaa5f180b28ad11c2d", "sha256": "b8537925a056cadd86286498ca1ac74f19fa204a6538119758729a0ef53b6778" }, "downloads": -1, "filename": "parse_this-0.3.0.tar.gz", "has_sig": false, "md5_digest": "a78a9b714bd46feaa5f180b28ad11c2d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6711, "upload_time": "2015-02-07T22:24:52", "url": "https://files.pythonhosted.org/packages/18/71/f8e60fa2a679a4e14f4659e283473aff599857d1daca372dacc1c04b1cc7/parse_this-0.3.0.tar.gz" } ], "0.3.1": [ { "comment_text": "", "digests": { "md5": "6fa879094e6506f814f0303bf465bbe8", "sha256": "e8f349ecb1a5276e1ee85264a9227c23ccdc805f75913e14a741000075d7d46a" }, "downloads": -1, "filename": "parse_this-0.3.1.tar.gz", "has_sig": false, "md5_digest": "6fa879094e6506f814f0303bf465bbe8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7275, "upload_time": "2015-02-07T23:31:02", "url": "https://files.pythonhosted.org/packages/0f/24/a46a40651687fcd87238aa7f74931a5fe6c1b863637eb2b72f91da4ab856/parse_this-0.3.1.tar.gz" } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "12e24f2f999a153f568f56c9ea6fa19c", "sha256": "1f921ca21bf5f0c9ec6d08513269f2cf5ef4c950c6326c7f35fc92057f68f642" }, "downloads": -1, "filename": "parse_this-0.4.0.tar.gz", "has_sig": false, "md5_digest": "12e24f2f999a153f568f56c9ea6fa19c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10870, "upload_time": "2015-02-09T16:06:33", "url": "https://files.pythonhosted.org/packages/26/37/66037487429f8a70def8f13fc6ff2461d79d005bd4cf6a60743990f58093/parse_this-0.4.0.tar.gz" } ], "1.0.0": [ { "comment_text": "", "digests": { "md5": "facbd7b6c4e32ec2a116aab3c7cb0e32", "sha256": "546f66289a3b9041b13cd8515900f80ebca8061878e21aa6fc6ebcffdf10074c" }, "downloads": -1, "filename": "parse_this-1.0.0.tar.gz", "has_sig": false, "md5_digest": "facbd7b6c4e32ec2a116aab3c7cb0e32", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14705, "upload_time": "2015-02-11T18:33:07", "url": "https://files.pythonhosted.org/packages/91/ed/64f77882f957410767e625bbd491c9516bafce82a9e55f8a370ae03265be/parse_this-1.0.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "925454516241a30e4ac63e1253ed3923", "sha256": "8d981617686192146e2663abd3baf07bc9040841d157ad89062ff7818664fb8e" }, "downloads": -1, "filename": "parse_this-1.0.1.tar.gz", "has_sig": false, "md5_digest": "925454516241a30e4ac63e1253ed3923", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16328, "upload_time": "2015-02-13T14:30:06", "url": "https://files.pythonhosted.org/packages/98/65/f3ed08a9fd92ed4414e7216a9c8fdeac42f4906cd6637b3d2133be5bda86/parse_this-1.0.1.tar.gz" } ], "1.0.2": [ { "comment_text": "", "digests": { "md5": "085a829b53ab17944bb95e085104f481", "sha256": "8b98fc00b182562fa71bde3f1d913cc5f55bf7c695f038723aaa1b9b2821020c" }, "downloads": -1, "filename": "parse_this-1.0.2.tar.gz", "has_sig": false, "md5_digest": "085a829b53ab17944bb95e085104f481", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18476, "upload_time": "2015-02-25T16:36:30", "url": "https://files.pythonhosted.org/packages/1b/40/acc0efbb4421cf6d284f27907be3de180d979e1619be6e440a0b7f5897f1/parse_this-1.0.2.tar.gz" } ], "1.0.3": [ { "comment_text": "", "digests": { "md5": "506743cbc6dac7a339392d4d118564bd", "sha256": "efb9e02d6e7e43bd65440c06c3cb2e52914d44ac82991bada6626d6556853edc" }, "downloads": -1, "filename": "parse_this-1.0.3.tar.gz", "has_sig": false, "md5_digest": "506743cbc6dac7a339392d4d118564bd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20361, "upload_time": "2015-03-03T13:06:16", "url": "https://files.pythonhosted.org/packages/95/3b/8b459f6cdded8c325f42d31dd7a9bb67accea3d8a1962331e0ff907a82f4/parse_this-1.0.3.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "506743cbc6dac7a339392d4d118564bd", "sha256": "efb9e02d6e7e43bd65440c06c3cb2e52914d44ac82991bada6626d6556853edc" }, "downloads": -1, "filename": "parse_this-1.0.3.tar.gz", "has_sig": false, "md5_digest": "506743cbc6dac7a339392d4d118564bd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20361, "upload_time": "2015-03-03T13:06:16", "url": "https://files.pythonhosted.org/packages/95/3b/8b459f6cdded8c325f42d31dd7a9bb67accea3d8a1962331e0ff907a82f4/parse_this-1.0.3.tar.gz" } ] }