{ "info": { "author": "Yaniv Mordekhay", "author_email": "yaniv@linuxmail.org", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "*****\nRuler\n*****\n\n.. image:: https://travis-ci.org/yanivmo/ruler.svg?branch=master\n :target: https://travis-ci.org/yanivmo/ruler\n :alt: Build status\n\n.. image:: https://landscape.io/github/yanivmo/ruler/master/landscape.svg?style=flat\n :target: https://landscape.io/github/yanivmo/ruler/master\n :alt: Code Health\n\n.. image:: https://coveralls.io/repos/github/yanivmo/ruler/badge.svg?branch=master\n :target: https://coveralls.io/github/yanivmo/ruler?branch=master\n\n\nRuler is a lightweight regular expressions wrapper aiming to make regex definitions more\nmodular, intuitive, readable and the mismatch reporting more informative.\n\n\nQuick start\n===========\n\nLet's implement the following grammar, given in EBNF_::\n\n grammar = who, ' likes to drink ', what;\n who = 'John' | 'Peter' | 'Ann' | 'Paul' | 'Rachel';\n what = tea | juice;\n juice = 'juice';\n tea = 'tea', [milk];\n milk = ' with milk';\n\nUsing ruler it looks almost identical to EBNF_:\n\n>>> class Morning(Grammar):\n... who = OneOf('John', 'Peter', 'Ann', 'Paul', 'Rachel')\n... juice = Rule('juice')\n... milk = Optional(' with milk')\n... tea = Rule('tea', milk)\n... what = OneOf(juice, tea)\n... grammar = Rule(who, ' likes to drink ', what, '\\.')\n...\n... morning = Morning.create()\n\nA member named ``grammar`` must be always present - it acts as the start rule.\nLet's begin rather with a mismatch:\n\n>>> morning.match('John likes to drink coffee')\nFalse\n\n``match()`` returns ``True`` if the match was successful and ``False`` otherwise.\nOne of the major advantages of ``ruler``, as opposed to working directly with regular expressions,\nis the ability to know exactly what went wrong:\n\n>>> print(morning.error.long_description)\nMismatch at 20:\n John likes to drink coffee\n ^\n\"coffee\" does not match \"juice\"\n\"coffee\" does not match \"tea\"\n\nLet's fix our text:\n\n>>> morning.match('John likes to drink tea.')\nTrue\n\nAny rule that is declared as a member variable of your grammar class acts as a named capture group\narranged hierarchically. Use ``matched`` attribute to retrieve the text matched by a specific rule:\n\n>>> morning.matched\n'John likes to drink tea.'\n>>> morning.who.matched\n'John'\n>>> morning.what.matched\n'tea'\n\nBranches of OneOf rules that didn't match and optional rules that didn't match have ``None`` as\ntheir values making it easy to ask whether they matched:\n\n>>> morning.what.juice.matched is None\nTrue\n>>> morning.what.tea.matched is None\nFalse\n>>> morning.what.tea.milk.matched is None\nTrue\n\nRules can be reused multiple times. If the same rule appears multiple times under the same parent,\nthese rules are collected into a list:\n\n>>> class Morning(Grammar):\n... person = OneOf('John', 'Peter', 'Ann', 'Paul', 'Rachel')\n... who = Rule(person, Optional(', ', person), Optional(' and ', person))\n... juice = Rule('juice')\n... milk = Optional(' with milk')\n... tea = Rule('tea', milk)\n... what = OneOf(juice, tea)\n... grammar = Rule(who, ' like', Optional('s'), ' to drink ', what, '\\.')\n...\n... morning = Morning.create()\n... morning.match('Peter, Rachel and Ann like to drink juice.')\nTrue\n>>> morning.who.matched\n'Peter, Rachel and Ann'\n>>> morning.who.person[0].matched\n'Peter'\n>>> morning.who.person[1].matched\n'Rachel'\n>>> morning.who.person[2].matched\n'Ann'\n\nNotice that, in the grammar above, ``person`` rule is never a direct child of ``who`` but still\nis accessed as such. That is because when a rule hierarchy is built, a rule is placed under its\nclosest named ancestor.\n\nRules' string arguments may actually be any valid regular expression. So we could rewrite our\ngrammar like this:\n\n>>> class Morning(Grammar):\n... who = OneOf('\\w+')\n... juice = Rule('juice')\n... milk = Optional(' with milk')\n... tea = Rule('tea', milk)\n... what = OneOf(juice, tea)\n... grammar = Rule(who, ' likes to drink ', what, '\\.')\n...\n... morning = Morning()\n... morning.match('R2D2 likes to drink juice. And nothing else matters.')\nTrue\n>>> morning.matched\n'R2D2 likes to drink juice.'\n>>> morning.who.matched\n'R2D2'\n\n\nPerformance\n===========\nThe library is well optimized for fast matching. Nevertheless it is important to remember\nthat this is a Python wrapper of the regex library and as such can never outperform matching\ndirectly using the regex library. Currently ruler measures approximately ten times slower\nthan ``re``.\n\n\nDevelopment\n===========\n\n* To run the tests::\n\n pytest tests\n\n* To compare the performance to the re library::\n\n python performance/re_compare.py\n\n* To run performance profiling of a specific method, ``Rule.match`` for example::\n\n python performance/profile.py Rule.match\n\n More than one method can be specified in the same command.\n\nTox\n---\nTox takes care of everything without installing anything manually. There are two groups of tox\nenvironments: ``py*-test`` and ``py*-profile``. The test environments run the unit tests while the\nprofile environments run the performance profiling scripts. If tox is not enough then a development\nenvironment can be generated by creating a new virtualenv and then running\n``pip install -r requirements_develop.txt``.\n\n\nDependency management\n---------------------\nFor the development needs, there are three requirements files in the project's root directory:\n\n- ``requirements_test.txt`` contains all the dependencies needed to run the unit tests,\n- ``requirements_profile.txt`` contains all the dependencies needed to run the performance profiling,\n- ``requirements_develop.txt`` contains the testing dependencies, the profiling dependencies and some additional\n dependencies used in development.\n\nThe requirements files mentioned above are not intended for manual editing. Instead they are managed\nusing `pip-tools`_. The process of updating the requirements is as follows:\n\n#. Add, remove or update a dependency in one of the ``reqs_*.dep`` files:\n\n - Update ``reqs_install.dep`` if the dependency is needed for the regular installation by the end user,\n - Update ``reqs_test.dep`` if the dependency is needed to run the unit tests but is not necessary for the\n regular installation,\n - Update ``reqs_profile.dep`` if the dependency is needed to run the performance profiling but is not necessary\n for the regular installation,\n - Update ``reqs_develop.dep`` if the dependency is not in one of the previous categories.\n\n#. Generate the requirements file running ``pip-compile``. The exact command is documented in the beginning of each\n requirements file.\n#. Consider running ``pip-sync requirements_develop.txt``.\n\nNotice that there is no need to edit ``setup.py`` - it will pull the dependencies by itself from ``reqs_install.dep``.\n\n\n.. _EBNF: https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form\n.. _pip-tools: https://github.com/jazzband/pip-tools", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/yanivmo/ruler", "keywords": "regex parsing grammar", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "ruler", "package_url": "https://pypi.org/project/ruler/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/ruler/", "project_urls": { "Homepage": "https://github.com/yanivmo/ruler" }, "release_url": "https://pypi.org/project/ruler/2.0.0/", "requires_dist": [ "six" ], "requires_python": "", "summary": "Humane grammar library", "version": "2.0.0" }, "last_serial": 2946824, "releases": { "2.0.0": [ { "comment_text": "", "digests": { "md5": "49765b1c4af3c09bcf4761f00fabf745", "sha256": "f541871592c6c8c468ecfe4135a09fa32df60c834ea8a5306d13cc853ff22b08" }, "downloads": -1, "filename": "ruler-2.0.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "49765b1c4af3c09bcf4761f00fabf745", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 11143, "upload_time": "2017-06-13T12:34:06", "url": "https://files.pythonhosted.org/packages/37/3f/a29995476026ee662962a6a10c486f4c4f0d29ef91e8b791ad495933f413/ruler-2.0.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "2a40c1d5f460c1c635af5652146b1f3c", "sha256": "dcf4dc19054fa04a73c24b62e93dfecf17487406e409d2c66225de7738ee6e12" }, "downloads": -1, "filename": "ruler-2.0.0.tar.gz", "has_sig": false, "md5_digest": "2a40c1d5f460c1c635af5652146b1f3c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7975, "upload_time": "2017-06-13T12:34:08", "url": "https://files.pythonhosted.org/packages/ed/e5/026162295cec03bd2ff0c47404748f582eb43907ab4dac89435f273af965/ruler-2.0.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "49765b1c4af3c09bcf4761f00fabf745", "sha256": "f541871592c6c8c468ecfe4135a09fa32df60c834ea8a5306d13cc853ff22b08" }, "downloads": -1, "filename": "ruler-2.0.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "49765b1c4af3c09bcf4761f00fabf745", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 11143, "upload_time": "2017-06-13T12:34:06", "url": "https://files.pythonhosted.org/packages/37/3f/a29995476026ee662962a6a10c486f4c4f0d29ef91e8b791ad495933f413/ruler-2.0.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "2a40c1d5f460c1c635af5652146b1f3c", "sha256": "dcf4dc19054fa04a73c24b62e93dfecf17487406e409d2c66225de7738ee6e12" }, "downloads": -1, "filename": "ruler-2.0.0.tar.gz", "has_sig": false, "md5_digest": "2a40c1d5f460c1c635af5652146b1f3c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7975, "upload_time": "2017-06-13T12:34:08", "url": "https://files.pythonhosted.org/packages/ed/e5/026162295cec03bd2ff0c47404748f582eb43907ab4dac89435f273af965/ruler-2.0.0.tar.gz" } ] }